Skip to content

Commit 2efc949

Browse files
committed
fix: restore voice wake after failed iOS PTT start
1 parent d6ed2c3 commit 2efc949

3 files changed

Lines changed: 28 additions & 0 deletions

File tree

apps/ios/Sources/Model/NodeAppModel.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1696,7 +1696,15 @@ final class NodeAppModel {
16961696
switch req.command {
16971697
case OpenClawTalkCommand.pttStart.rawValue:
16981698
self.pttVoiceWakeSuspended = self.voiceWake.suspendForExternalAudioCapture()
1699+
var didStart = false
1700+
defer {
1701+
if !didStart {
1702+
self.voiceWake.resumeAfterExternalAudioCapture(wasSuspended: self.pttVoiceWakeSuspended)
1703+
self.pttVoiceWakeSuspended = false
1704+
}
1705+
}
16991706
let payload = try await self.talkMode.beginPushToTalk()
1707+
didStart = true
17001708
let json = try Self.encodePayload(payload)
17011709
return BridgeInvokeResponse(id: req.id, ok: true, payloadJSON: json)
17021710
case OpenClawTalkCommand.pttStop.rawValue:

apps/ios/Sources/Voice/VoiceWakeManager.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,10 @@ extension VoiceWakeManager {
545545
self.isStarting = isStarting
546546
}
547547

548+
func _test_isSuspendedForExternalAudio() -> Bool {
549+
self.isSuspendedForExternalAudio
550+
}
551+
548552
func _test_waitForScheduledStart() async {
549553
let task = self.scheduledStartTask
550554
await task?.value

apps/ios/Tests/NodeAppModelInvokeTests.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,22 @@ private final class MockBootstrapNotificationCenter: NotificationCentering, @unc
687687
#expect(watchService.lastSentAppSnapshot?.talkEnabled == false)
688688
}
689689

690+
@Test @MainActor func handleInvokePTTStartRestoresVoiceWakeWhenStartFails() async {
691+
let talkMode = TalkModeManager(allowSimulatorCapture: true)
692+
let appModel = NodeAppModel(talkMode: talkMode)
693+
appModel.voiceWake.isEnabled = true
694+
appModel.voiceWake.isListening = true
695+
appModel.voiceWake.statusText = "Listening"
696+
697+
let req = BridgeInvokeRequest(id: "ptt-start", command: OpenClawTalkCommand.pttStart.rawValue)
698+
let res = await appModel._test_handleInvoke(req)
699+
700+
#expect(res.ok == false)
701+
#expect(res.error?.message.contains("Gateway not connected") == true)
702+
#expect(appModel.voiceWake._test_isSuspendedForExternalAudio() == false)
703+
appModel.voiceWake.stop()
704+
}
705+
690706
@Test @MainActor func watchAppCommandOpensChatSessionOnPhoneModel() async {
691707
let watchService = MockWatchMessagingService()
692708
let appModel = NodeAppModel(watchMessagingService: watchService)

0 commit comments

Comments
 (0)