gitbay/gitbayApp.swift

v1.9.0
gitbay-ios/gitbay/gitbayApp.swift history · blame · raw

72 lines · 3026 bytes

 1import SwiftUI
 2
 3@main
 4struct gitbayApp: App {
 5
 6    @UIApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate
 7    @State private var session: SessionStore
 8    @State private var router = PushRouter()
 9    @State private var registrar: PushRegistrar
10
11    init() {
12        GitbayFonts.register()
13        // The registrar takes the session at construction, so both are
14        // built here rather than as property initialisers — one
15        // registrar for the life of the app, which the delegate and
16        // SessionStore's removal hook then both point at.
17        let session = SessionStore()
18        _session = State(wrappedValue: session)
19        _registrar = State(wrappedValue: PushRegistrar(session: session))
20    }
21
22    var body: some Scene {
23        WindowGroup {
24            ContentView()
25                .environment(session)
26                .environment(router)
27                .environment(registrar)
28                .font(.gbSans(.body))
29                .tint(.gbAccent)
30                // The screenshot checkpoint forces appearance per run;
31                // simulator clones ignore the base device's setting.
32                .preferredColorScheme(Self.forcedColorScheme)
33                .onOpenURL { url in
34                    // A page the app has no screen for goes back to
35                    // Safari; the rest waits for ContentView's drain.
36                    if WebURLRoute(url: url) == nil {
37                        UIApplication.shared.open(url)
38                    } else {
39                        router.pendingLink = url
40                    }
41                }
42                .task {
43                    let registrar = self.registrar
44                    appDelegate.registrar = registrar
45                    appDelegate.router = router
46                    appDelegate.session = session
47                    // Weak: the registrar holds the session, and this
48                    // closure is stored on the session.
49                    session.willRemoveAccount = { [weak registrar] account in
50                        await registrar?.deregister(account)
51                    }
52                    session.didAddAccount = { [weak registrar] account in
53                        await registrar?.register(account)
54                    }
55                    // A tap that launched the app reaches the delegate
56                    // before this runs; it parked the payload.
57                    appDelegate.deliverPendingNotification()
58                    await registrar.registerIfAlreadyAuthorized()
59                }
60        }
61    }
62
63    /// A clone follows whatever appearance it was created with, so the
64    /// checkpoint has to name the one it wants. Neither flag means the
65    /// app follows the system, as it does for real users.
66    private static var forcedColorScheme: ColorScheme? {
67        let args = ProcessInfo.processInfo.arguments
68        if args.contains("-gb-dark") { return .dark }
69        if args.contains("-gb-light") { return .light }
70        return nil
71    }
72}