import ManaCore import SwiftUI /// Top-Level-Switch: Login vs Haupt-App. Haupt-App ist eine TabBar mit /// drei Tabs (Decks / Entdecken / Account). struct RootView: View { @Environment(AuthClient.self) private var auth @State private var selectedTab: AppTab = .decks @State private var pendingDeepLinkSlug: String? @State private var showCreateDeck = false var body: some View { Group { switch auth.status { case .signedIn: mainTabs .onOpenURL { url in handle(url: url) } .onContinueUserActivity(NSUserActivityTypeBrowsingWeb) { activity in if let url = activity.webpageURL { handle(url: url) } } case .unknown, .signedOut, .signingIn, .error: LoginView() } } .task { await auth.ensureSignedIn() } } @ViewBuilder private var mainTabs: some View { TabView(selection: $selectedTab) { DeckListView(showCreate: $showCreateDeck) .tabItem { Label("Decks", systemImage: "rectangle.stack") } .tag(AppTab.decks) ExploreView(deepLinkSlug: $pendingDeepLinkSlug) .tabItem { Label("Entdecken", systemImage: "sparkles") } .tag(AppTab.explore) NavigationStack { AccountView() } .tabItem { Label("Account", systemImage: "person.crop.circle") } .tag(AppTab.account) } .decksCreateAccessory(visible: selectedTab == .decks) { showCreateDeck = true } } /// Universal-Link- und URL-Scheme-Handler: /// - `https://cardecky.mana.how/d/` → Explore-Tab + PublicDeckView /// - `cards://study/` → später (β-6 Notifications) private func handle(url: URL) { Log.app.info("Open URL: \(url.absoluteString, privacy: .public)") if url.host == "cardecky.mana.how" || url.scheme == "cards" { let parts = url.pathComponents.filter { $0 != "/" } if parts.count >= 2, parts[0] == "d" { pendingDeepLinkSlug = parts[1] selectedTab = .explore } } } } enum AppTab: Hashable { case decks case explore case account } private extension View { /// iOS 26: floating „Neues Deck"-Pille via `.tabViewBottomAccessory`, /// nur sichtbar wenn der Decks-Tab aktiv ist. iOS 18 fällt auf den /// bestehenden `.bottomBar`-„+"-Toolbar-Button in `DeckListView` zurück. @ViewBuilder func decksCreateAccessory(visible: Bool, onTap: @escaping () -> Void) -> some View { if #available(iOS 26.0, *) { self.tabViewBottomAccessory { if visible { DeckCreateAccessoryPill(action: onTap) } } } else { self } } } @available(iOS 26.0, *) private struct DeckCreateAccessoryPill: View { let action: () -> Void var body: some View { Button(action: action) { Label("Neues Deck", systemImage: "plus") .font(.subheadline.weight(.semibold)) .padding(.horizontal, 14) .padding(.vertical, 8) } .buttonStyle(.borderedProminent) .tint(CardsTheme.primary) .accessibilityLabel("Neues Deck erstellen") } }