SwiftUI watch-only app in watch/, generated by XcodeGen. Codable models mirror gateway/src/contract.ts, with lenient string enums so new phases or decisions still decode. A DemoGateway serves fixtures from the docs/api.md examples for previews and demo mode. Swift Testing covers decoding the documented JSON, request encoding, notification action parsing and the small view helpers. Co-Authored-By: Claude Opus 5.5 <[email protected]>
60 lines
1.7 KiB
Swift
60 lines
1.7 KiB
Swift
// App entry. Notification setup and APNs registration go through the WatchKit app delegate.
|
|
|
|
import SwiftUI
|
|
import WatchKit
|
|
|
|
@main
|
|
struct WristCodeApp: App {
|
|
@WKApplicationDelegateAdaptor(AppDelegate.self) private var delegate
|
|
@State private var model = AppModel.shared
|
|
|
|
var body: some Scene {
|
|
WindowGroup {
|
|
RootView()
|
|
.environment(model)
|
|
}
|
|
}
|
|
}
|
|
|
|
struct RootView: View {
|
|
@Environment(AppModel.self) private var model
|
|
|
|
var body: some View {
|
|
@Bindable var model = model
|
|
Group {
|
|
if model.mode == .unpaired {
|
|
PairView()
|
|
} else {
|
|
NavigationStack(path: $model.path) {
|
|
FeedView()
|
|
.navigationDestination(for: Route.self) { route in
|
|
switch route {
|
|
case let .thread(hostId, threadId):
|
|
ThreadView(hostId: hostId, threadId: threadId)
|
|
case .newThread:
|
|
NewThreadView()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.fontDesign(.rounded)
|
|
.tint(Theme.work)
|
|
}
|
|
}
|
|
|
|
final class AppDelegate: NSObject, WKApplicationDelegate {
|
|
func applicationDidFinishLaunching() {
|
|
NotificationHandler.shared.install()
|
|
Task { await AppModel.shared.enableNotifications() }
|
|
}
|
|
|
|
func didRegisterForRemoteNotifications(withDeviceToken deviceToken: Data) {
|
|
AppModel.shared.didRegister(apnsToken: deviceToken)
|
|
}
|
|
|
|
func didFailToRegisterForRemoteNotificationsWithError(_ error: any Error) {
|
|
print("APNs registration failed: \(error.localizedDescription)")
|
|
}
|
|
}
|