import SwiftUI @main struct gitbayApp: App { @UIApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate @State private var session: SessionStore @State private var router = PushRouter() @State private var registrar: PushRegistrar init() { GitbayFonts.register() // The registrar takes the session at construction, so both are // built here rather than as property initialisers — one // registrar for the life of the app, which the delegate and // SessionStore's removal hook then both point at. let session = SessionStore() _session = State(wrappedValue: session) _registrar = State(wrappedValue: PushRegistrar(session: session)) } var body: some Scene { WindowGroup { ContentView() .environment(session) .environment(router) .environment(registrar) .font(.gbSans(.body)) .tint(.gbAccent) // The screenshot checkpoint forces appearance per run; // simulator clones ignore the base device's setting. .preferredColorScheme(Self.forcedColorScheme) .task { let registrar = self.registrar appDelegate.registrar = registrar appDelegate.router = router appDelegate.session = session // Weak: the registrar holds the session, and this // closure is stored on the session. session.willRemoveAccount = { [weak registrar] account in await registrar?.deregister(account) } session.didAddAccount = { [weak registrar] account in await registrar?.register(account) } // A tap that launched the app reaches the delegate // before this runs; it parked the payload. appDelegate.deliverPendingNotification() await registrar.registerIfAlreadyAuthorized() } } } /// A clone follows whatever appearance it was created with, so the /// checkpoint has to name the one it wants. Neither flag means the /// app follows the system, as it does for real users. private static var forcedColorScheme: ColorScheme? { let args = ProcessInfo.processInfo.arguments if args.contains("-gb-dark") { return .dark } if args.contains("-gb-light") { return .light } return nil } }