Tier 5 - Code Refactoring: - iOS: Split NodeAppModel.swift (988→493 LOC) into focused modules - NodeCommandHandlers.swift: command routing (372 LOC) - NodeGatewaySync.swift: gateway sync, branding (153 LOC) - Android: Split NodeRuntime.kt (1268→756 LOC, 40% reduction) - NodeCommandHandlers.kt: command routing (326 LOC) - NodeGatewaySync.kt: gateway sync, A2UI helpers (294 LOC) Tier 6 - App Store Preparation: - iOS: Add PrivacyInfo.xcprivacy (iOS 17+ privacy manifest) - Android: Add ProGuard rules and enable minification for release builds Infrastructure (from earlier tiers): - iOS: Add OfflineMessageQueue for disconnected message queueing - iOS: Add PushManager for VoIP push foundation - iOS: Add TTSVoiceSettingsView for voice selection - Android: Add ClawdbotMessagingService for FCM push - Android: Add SyncWorker for background chat sync - Both: Deep linking support (clawdbot:// URL scheme) - Both: Empty states and loading indicators in settings Testing: - iOS: Add OfflineMessageQueueTests (8 tests) - Android: Add NodeGatewaySyncTest (11 tests) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
62 lines
1.9 KiB
Swift
62 lines
1.9 KiB
Swift
import SwiftUI
|
|
import UIKit
|
|
|
|
@main
|
|
struct MoltbotApp: App {
|
|
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
|
|
@State private var appModel: NodeAppModel
|
|
@State private var gatewayController: GatewayConnectionController
|
|
@Environment(\.scenePhase) private var scenePhase
|
|
|
|
init() {
|
|
GatewaySettingsStore.bootstrapPersistence()
|
|
let appModel = NodeAppModel()
|
|
_appModel = State(initialValue: appModel)
|
|
_gatewayController = State(initialValue: GatewayConnectionController(appModel: appModel))
|
|
|
|
// Register for push notifications
|
|
PushManager.shared.registerForVoIPPush()
|
|
Task {
|
|
await PushManager.shared.registerForRemoteNotifications()
|
|
}
|
|
}
|
|
|
|
var body: some Scene {
|
|
WindowGroup {
|
|
RootCanvas()
|
|
.environment(self.appModel)
|
|
.environment(self.appModel.voiceWake)
|
|
.environment(self.gatewayController)
|
|
.onOpenURL { url in
|
|
Task { await self.appModel.handleDeepLink(url: url) }
|
|
}
|
|
.onChange(of: self.scenePhase) { _, newValue in
|
|
self.appModel.setScenePhase(newValue)
|
|
self.gatewayController.setScenePhase(newValue)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - AppDelegate for Push Notification Token Handling
|
|
|
|
class AppDelegate: NSObject, UIApplicationDelegate {
|
|
func application(
|
|
_ application: UIApplication,
|
|
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
|
|
) {
|
|
Task { @MainActor in
|
|
PushManager.shared.didRegisterForRemoteNotifications(deviceToken: deviceToken)
|
|
}
|
|
}
|
|
|
|
func application(
|
|
_ application: UIApplication,
|
|
didFailToRegisterForRemoteNotificationsWithError error: Error
|
|
) {
|
|
Task { @MainActor in
|
|
PushManager.shared.didFailToRegisterForRemoteNotifications(error: error)
|
|
}
|
|
}
|
|
}
|