TalerWallet1App.swift (4276B)
1 /* 2 * This file is part of GNU Taler, ©2022-25 Taler Systems S.A. 3 * See LICENSE.md 4 */ 5 /** 6 * Main app entry point 7 * 8 * @author Jonathan Buchanan 9 * @author Marc Stibane 10 */ 11 import BackgroundTasks 12 import SwiftUI 13 import os.log 14 import SymLog 15 16 @main 17 struct TalerWallet1App: App { 18 private let symLog = SymLogV() 19 @Environment(\.scenePhase) private var phase 20 @StateObject private var viewState = ViewState.shared // popToRootView() 21 @StateObject private var viewState2 = ViewState2.shared // popToRootView() 22 @State private var soundPlayed = false 23 24 private let walletCore = WalletCore.shared 25 private let controller = Controller.shared 26 private let model = WalletModel.shared 27 private let debugViewC = DebugViewC.shared 28 let logger = Logger(subsystem: "net.taler.gnu", category: "Main App") 29 private let biometricService = BiometricService.shared 30 31 func scheduleAppRefresh() { 32 let request = BGAppRefreshTaskRequest(identifier: "net.taler.gnu.refresh") 33 request.earliestBeginDate = .now.addingTimeInterval(24 * 3600) 34 try? BGTaskScheduler.shared.submit(request) 35 } 36 37 var body: some Scene { 38 WindowGroup { 39 MainView(logger: logger, stack: CallStack("App"), soundPlayed: $soundPlayed) 40 .environmentObject(debugViewC) // change viewID / sheetID 41 .environmentObject(viewState) // popToRoot 42 .environmentObject(viewState2) // popToRoot 43 .environmentObject(controller) 44 .environmentObject(model) 45 .environmentObject(biometricService) 46 .addKeyboardVisibilityToEnvironment() 47 /// external events are taler:// or payto:// URLs passed to this app 48 /// we handle them in .onOpenURL in MainView.swift 49 .handlesExternalEvents(preferring: ["*"], allowing: ["*"]) 50 .task { 51 #if DEBUG 52 let testing = true 53 #else 54 let testing = false 55 #endif 56 try! await controller.initWalletCore(model, setTesting: testing) // will (and should) crash on failure 57 } 58 } 59 .onChange(of: phase) { newPhase in 60 switch newPhase { 61 case .active: 62 logger.log("❗️.onChange() ==> Active") 63 case .background: 64 logger.log("❗️.onChange() ==> Background)") 65 // scheduleAppRefresh() 66 default: break 67 } 68 } 69 // if #available(iOS 16.4, *) { 70 // .backgroundTask(.appRefresh("net.taler.refresh")) { 71 // symLog.log("backgroundTask running") 72 //#if 0 73 // let request = URLRequest(url: URL(string: "your_backend")!) 74 // guard let data = try? await URLSession.shared.data(for: request).0 else { 75 // return 76 // } 77 // 78 // let decoder = JSONDecoder() 79 // guard let products = try? decoder.decode([Product].self, from: data) else { 80 // return 81 // } 82 // 83 // if !products.isEmpty && !Task.isCancelled { 84 // await notifyUser(for: products) 85 // } 86 //#endif 87 // } 88 // } else { 89 // // Fallback on earlier versions 90 // } 91 92 } 93 } 94 95 final class ViewState : ObservableObject { 96 static let shared = ViewState() 97 @Published var rootViewId = UUID() 98 let logger = Logger(subsystem: "net.taler.gnu", category: "ViewState") 99 100 public func popToRootView(_ stack: CallStack?) -> Void { 101 logger.info("popToRootView") 102 rootViewId = UUID() // setting a new ID will cause 1st NavStack popToRootView behaviour 103 } 104 105 private init() { } 106 } 107 108 final class ViewState2 : ObservableObject { 109 static let shared = ViewState2() 110 @Published var rootViewId = UUID() 111 let logger = Logger(subsystem: "net.taler.gnu", category: "ViewState2") 112 113 public func popToRootView(_ stack: CallStack?) -> Void { 114 logger.info("popToRootView") 115 rootViewId = UUID() // setting a new ID will cause 2nd NavStack popToRootView behaviour 116 } 117 118 private init() { } 119 }