Watch app MVP: XcodeGen project, gateway client, pair, feed, thread, new thread, notifications
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]>
This commit is contained in:
1 parent
ba1624eb9e
commit
bdfb79b891
19 files changed
+2413
No files matched your search
@@ -0,0 +1,59 @@
|
||||
// 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)")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user