diff --git a/apps/ios/WatchApp/Sources/OpenClawWatchApp.swift b/apps/ios/WatchApp/Sources/OpenClawWatchApp.swift index 5708ec554b37..5bbd6de8179b 100644 --- a/apps/ios/WatchApp/Sources/OpenClawWatchApp.swift +++ b/apps/ios/WatchApp/Sources/OpenClawWatchApp.swift @@ -147,7 +147,9 @@ struct OpenClawWatchApp: App { let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines) guard !trimmed.isEmpty else { return nil } guard self.inboxStore.hasGatewayTaggedAppSnapshot else { - self.inboxStore.markAppCommandBlocked(.sendChat, reason: "refreshing iPhone state") + self.inboxStore.markAppCommandBlocked( + .sendChat, + reason: String(localized: "Refreshing iPhone state")) self.refreshAppSnapshot() return nil } diff --git a/apps/ios/WatchApp/Sources/WatchInboxMessages.swift b/apps/ios/WatchApp/Sources/WatchInboxMessages.swift index 38e1eee3afef..cdb33f61420e 100644 --- a/apps/ios/WatchApp/Sources/WatchInboxMessages.swift +++ b/apps/ios/WatchApp/Sources/WatchInboxMessages.swift @@ -235,7 +235,7 @@ struct WatchAppCommandStatus: Codable, Equatable { case .failed: String(format: localize(.failedFormat), label, self.detail ?? localize(.unavailable)) case .blocked: - localize(.refreshingFromIPhone) + self.detail ?? localize(.refreshingFromIPhone) } } @@ -584,23 +584,27 @@ struct WatchAppSnapshotMessage: Codable, Equatable { self.chatItems = try container.decodeIfPresent([WatchChatItem].self, forKey: .chatItems) self.sentAtMs = try container.decodeIfPresent(Int64.self, forKey: .sentAtMs) self.snapshotId = try container.decodeIfPresent(String.self, forKey: .snapshotId) + let gatewayStatusText = try container.decodeIfPresent(String.self, forKey: .gatewayStatusText) + let talkStatusText = try container.decodeIfPresent(String.self, forKey: .talkStatusText) + let chatStatusCode = try container.decodeIfPresent(String.self, forKey: .chatStatusCode) + let chatStatusText = try container.decodeIfPresent(String.self, forKey: .chatStatusText) self.gatewayStatus = (try? container.decode( OpenClawWatchAppStatus.self, forKey: .gatewayStatus)) ?? Self.decodeLegacyGatewayStatus( - text: container.decodeIfPresent(String.self, forKey: .gatewayStatusText), + text: gatewayStatusText, connected: self.gatewayConnected) self.talkStatus = (try? container.decode( OpenClawWatchAppStatus.self, forKey: .talkStatus)) ?? Self.decodeLegacyTalkStatus( - text: container.decodeIfPresent(String.self, forKey: .talkStatusText), + text: talkStatusText, enabled: self.talkEnabled, listening: self.talkListening, speaking: self.talkSpeaking) self.chatStatus = (try? container.decode( OpenClawWatchAppStatus.self, forKey: .chatStatus)) ?? Self.decodeLegacyChatStatus( - code: container.decodeIfPresent(String.self, forKey: .chatStatusCode), - text: container.decodeIfPresent(String.self, forKey: .chatStatusText)) + code: chatStatusCode, + text: chatStatusText) } func encode(to encoder: Encoder) throws { diff --git a/apps/ios/WatchApp/Sources/WatchInboxStore.swift b/apps/ios/WatchApp/Sources/WatchInboxStore.swift index 8b925008628c..04e4ce4da1da 100644 --- a/apps/ios/WatchApp/Sources/WatchInboxStore.swift +++ b/apps/ios/WatchApp/Sources/WatchInboxStore.swift @@ -709,8 +709,11 @@ import WatchKit self.persistState() } - func markAppCommandBlocked(_ command: WatchAppCommand, reason _: String) { - self.appCommandStatus = WatchAppCommandStatus(command: command, code: .blocked) + func markAppCommandBlocked(_ command: WatchAppCommand, reason: String) { + self.appCommandStatus = WatchAppCommandStatus( + command: command, + code: .blocked, + detail: reason) self.persistState() } @@ -736,8 +739,11 @@ import WatchKit extension WatchInboxStore { func consume(execApprovalResolved message: WatchExecApprovalResolvedMessage) { guard self.routeGatewayPayload(.execApprovalResolved(message: message)) else { return } - let outcome = if let outcomeText = message.outcomeText, !outcomeText.isEmpty { - WatchExecApprovalOutcome(code: .verbatim, verbatim: outcomeText) + let normalizedOutcomeText = message.outcomeText? + .trimmingCharacters(in: .whitespacesAndNewlines) + .prefix(160) + let outcome = if let normalizedOutcomeText, !normalizedOutcomeText.isEmpty { + WatchExecApprovalOutcome(code: .verbatim, verbatim: String(normalizedOutcomeText)) } else if message.source == "another-reviewer" { WatchExecApprovalOutcome(code: .resolvedElsewhere) } else {