diff --git a/apps/android/app/src/main/java/com/steipete/clawdis/node/MainViewModel.kt b/apps/android/app/src/main/java/com/steipete/clawdis/node/MainViewModel.kt index f1fef1640..69b394a63 100644 --- a/apps/android/app/src/main/java/com/steipete/clawdis/node/MainViewModel.kt +++ b/apps/android/app/src/main/java/com/steipete/clawdis/node/MainViewModel.kt @@ -36,7 +36,6 @@ class MainViewModel(app: Application) : AndroidViewModel(app) { val wakeWords: StateFlow> = runtime.wakeWords val voiceWakeMode: StateFlow = runtime.voiceWakeMode val voiceWakeStatusText: StateFlow = runtime.voiceWakeStatusText - val voiceWakeStatusText: StateFlow = runtime.voiceWakeStatusText val voiceWakeIsListening: StateFlow = runtime.voiceWakeIsListening val talkEnabled: StateFlow = runtime.talkEnabled val talkStatusText: StateFlow = runtime.talkStatusText diff --git a/apps/android/app/src/main/java/com/steipete/clawdis/node/ui/RootScreen.kt b/apps/android/app/src/main/java/com/steipete/clawdis/node/ui/RootScreen.kt index 86d5a334e..cb11cf303 100644 --- a/apps/android/app/src/main/java/com/steipete/clawdis/node/ui/RootScreen.kt +++ b/apps/android/app/src/main/java/com/steipete/clawdis/node/ui/RootScreen.kt @@ -115,30 +115,30 @@ fun RootScreen(viewModel: MainViewModel) { ) } - if (cameraHud != null) { - return@remember when (cameraHud.kind) { + cameraHud?.let { hud -> + return@remember when (hud.kind) { CameraHudKind.Photo -> StatusActivity( - title = cameraHud.message, + title = hud.message, icon = Icons.Default.PhotoCamera, contentDescription = "Taking photo", ) CameraHudKind.Recording -> StatusActivity( - title = cameraHud.message, + title = hud.message, icon = Icons.Default.FiberManualRecord, contentDescription = "Recording", tint = androidx.compose.ui.graphics.Color.Red, ) CameraHudKind.Success -> StatusActivity( - title = cameraHud.message, + title = hud.message, icon = Icons.Default.CheckCircle, contentDescription = "Capture finished", ) CameraHudKind.Error -> StatusActivity( - title = cameraHud.message, + title = hud.message, icon = Icons.Default.Error, contentDescription = "Capture failed", tint = androidx.compose.ui.graphics.Color.Red, diff --git a/apps/ios/Sources/Status/StatusPill.swift b/apps/ios/Sources/Status/StatusPill.swift index f5df8e7df..1e30ad16d 100644 --- a/apps/ios/Sources/Status/StatusPill.swift +++ b/apps/ios/Sources/Status/StatusPill.swift @@ -31,12 +31,12 @@ struct StatusPill: View { struct Activity: Equatable { var title: String var systemImage: String - var tint: Color? = nil + var tint: Color? } var bridge: BridgeState var voiceWakeEnabled: Bool - var activity: Activity? = nil + var activity: Activity? var brighten: Bool = false var onTap: () -> Void diff --git a/apps/ios/Sources/Voice/TalkModeManager.swift b/apps/ios/Sources/Voice/TalkModeManager.swift index 649eaa03a..82cd451c3 100644 --- a/apps/ios/Sources/Voice/TalkModeManager.swift +++ b/apps/ios/Sources/Voice/TalkModeManager.swift @@ -233,7 +233,7 @@ final class TalkModeManager: NSObject { "sessionKey": "main", "message": message, "thinking": "low", - "timeoutMs": 30_000, + "timeoutMs": 30000, "idempotencyKey": UUID().uuidString, ] let data = try JSONSerialization.data(withJSONObject: payload) @@ -260,7 +260,10 @@ final class TalkModeManager: NSObject { } private func fetchLatestAssistantText(bridge: BridgeSession) async throws -> String? { - let res = try await bridge.request(method: "chat.history", paramsJSON: "{\"sessionKey\":\"main\"}", timeoutSeconds: 15) + let res = try await bridge.request( + method: "chat.history", + paramsJSON: "{\"sessionKey\":\"main\"}", + timeoutSeconds: 15) guard let json = try JSONSerialization.jsonObject(with: res) as? [String: Any] else { return nil } guard let messages = json["messages"] as? [[String: Any]] else { return nil } for msg in messages.reversed() { @@ -499,7 +502,7 @@ private enum TalkModeRuntime { static func validatedSeed(_ value: Int?) -> UInt32? { guard let value else { return nil } - if value < 0 || value > 4294967295 { return nil } + if value < 0 || value > 4_294_967_295 { return nil } return UInt32(value) } diff --git a/apps/ios/SwiftSources.input.xcfilelist b/apps/ios/SwiftSources.input.xcfilelist index 3e2a9a7b0..81d42dce1 100644 --- a/apps/ios/SwiftSources.input.xcfilelist +++ b/apps/ios/SwiftSources.input.xcfilelist @@ -54,4 +54,6 @@ Sources/Voice/VoiceWakePreferences.swift ../shared/ClawdisKit/Sources/ClawdisKit/ScreenCommands.swift ../shared/ClawdisKit/Sources/ClawdisKit/StoragePaths.swift ../shared/ClawdisKit/Sources/ClawdisKit/SystemCommands.swift +../shared/ClawdisKit/Sources/ClawdisKit/TalkDirective.swift ../../Swabble/Sources/SwabbleKit/WakeWordGate.swift +Sources/Voice/TalkModeManager.swift diff --git a/apps/shared/ClawdisKit/Sources/ClawdisKit/TalkDirective.swift b/apps/shared/ClawdisKit/Sources/ClawdisKit/TalkDirective.swift index 6bc4c0195..af0e2365f 100644 --- a/apps/shared/ClawdisKit/Sources/ClawdisKit/TalkDirective.swift +++ b/apps/shared/ClawdisKit/Sources/ClawdisKit/TalkDirective.swift @@ -67,7 +67,8 @@ public enum TalkDirectiveParser { var lines = normalized.split(separator: "\n", omittingEmptySubsequences: false) guard !lines.isEmpty else { return TalkDirectiveParseResult(directive: nil, stripped: text, unknownKeys: []) } - guard let firstNonEmpty = lines.firstIndex(where: { !$0.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty }) + guard let firstNonEmpty = + lines.firstIndex(where: { !$0.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty }) else { return TalkDirectiveParseResult(directive: nil, stripped: text, unknownKeys: []) } @@ -83,8 +84,8 @@ public enum TalkDirectiveParser { return TalkDirectiveParseResult(directive: nil, stripped: text, unknownKeys: []) } - let speakerBoost = boolValue(json, keys: ["speaker_boost", "speakerBoost"]) - ?? boolValue(json, keys: ["no_speaker_boost", "noSpeakerBoost"]).map { !$0 } + let speakerBoost = self.boolValue(json, keys: ["speaker_boost", "speakerBoost"]) + ?? self.boolValue(json, keys: ["no_speaker_boost", "noSpeakerBoost"]).map { !$0 } let directive = TalkDirective( voiceId: stringValue(json, keys: ["voice", "voice_id", "voiceId"]),