1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2// KAApp.swift — point d'entrée : onboarding animé au premier lancement, puis3// la super-app (5 onglets + bulle KA Agent flottante partout).4import SwiftUI56@main7struct KAApp: App {8 @AppStorage("ka.onboarded") private var onboarded = false9 @AppStorage("ka.appearance") private var appearance = "clair"10 @StateObject private var favorites = FavoritesStore.shared1112 init() {13 // cache réseau généreux : images et JSON fluides, consultation hors ligne14 URLCache.shared = URLCache(memoryCapacity: 64 * 1024 * 1024,15 diskCapacity: 512 * 1024 * 1024)16 }1718 var body: some Scene {19 WindowGroup {20 Group {21 if onboarded {22 RootView()23 } else {24 OnboardingView()25 }26 }27 .environmentObject(favorites)28 .environmentObject(RecentsStore.shared)29 .preferredColorScheme(appearance == "clair" ? .light : appearance == "sombre" ? .dark : nil)30 }31 }32}3334// MARK: - Racine : 5 onglets + bulle Agent3536struct RootView: View {37 @State private var showAgent = false38 @State private var tab = 039 @StateObject private var recents = RecentsStore.shared4041 var body: some View {42 ZStack(alignment: .bottomTrailing) {43 TabView(selection: $tab) {44 HomeView()45 .tabItem { Label("Accueil", systemImage: "house.fill") }.tag(0)46 SearchView()47 .tabItem { Label("Recherche", systemImage: "magnifyingglass") }.tag(1)48 UniversesView()49 .tabItem { Label("Explorer", systemImage: "circle.grid.3x3.fill") }.tag(2)50 MapTab()51 .tabItem { Label("Carte", systemImage: "map.fill") }.tag(3)52 MoreTab()53 .tabItem { Label("Profil", systemImage: "person.crop.circle") }.tag(4)54 .badge(recents.alertCount)55 }56 .tint(KATheme.green)57 .task { await recents.refreshAlerts() }5859 // Bulle KA Agent — flottante au-dessus de la tab bar, partout60 Button {61 Haptics.rigid()62 showAgent = true63 } label: {64 Text("Ka")65 .font(.system(size: 19, weight: .bold, design: .rounded))66 .frame(width: 54, height: 54)67 .background(KATheme.lime, in: Circle())68 .foregroundStyle(KATheme.inkLight)69 .overlay(Circle().strokeBorder(KATheme.inkLight, lineWidth: 2))70 .shadow(color: .black.opacity(0.25), radius: 1, x: 3, y: 3)71 }72 .padding(.trailing, 16)73 .padding(.bottom, 64)74 .accessibilityLabel("Ouvrir KA Agent, l'assistant de l'écosystème")75 }76 .sheet(isPresented: $showAgent) {77 AgentChatView()78 .presentationDetents([.large])79 }80 }81}8283/// Onglet Carte : la carte unifiée directement (pas de fermeture — c'est un onglet)84struct MapTab: View {85 var body: some View {86 UnifiedMapView(embedded: true)87 }88}8990/// Onglet Profil — inclut Favoris, Historique et Recherches sauvegardées.91struct MoreTab: View {92 var body: some View {93 ProfileView()94 }95}96