Enable voice responses by default for voice questions#6398
Conversation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pass fromVoice flag through openAIInputWithQuery and sendFollowUpQuery so voice playback only triggers for PTT queries, not typed ones. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Greptile SummaryThis PR gates floating-bar voice responses to PTT (push-to-talk) queries only by tracking a Confidence Score: 5/5Safe to merge — voice-gating logic is correct and all code paths stop prior playback before starting new queries currentQueryFromVoice is properly set, propagated, and cleared in all code paths (openAIInputWithQuery, sendFollowUpQuery, clearVisibleConversation). sendAIQuery always calls FloatingBarVoicePlaybackService.shared.stop() first so typed queries naturally halt any in-progress voice. The default-true migration is correct: new users get true, existing users who never touched the setting also get true (key absent in UserDefaults), and users who explicitly disabled it retain false. Only remaining finding is a P2 style issue in OnboardingVoiceDemoView. desktop/Desktop/Sources/OnboardingVoiceDemoView.swift — @State voiceResponsesEnabled could be refactored to bind directly to ShortcutSettings Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[User holds PTT shortcut] --> B[PushToTalkManager.startListening]
B --> C[FloatingBarVoicePlaybackService.stop]
B --> D[Audio capture + live transcription]
D --> E[sendTranscript fromVoice:true]
E --> F[openAIInputWithQuery / sendFollowUpQuery]
F --> G[currentQueryFromVoice = true]
G --> H[sendAIQuery]
H --> I[FloatingBarVoicePlaybackService.stop]
I --> J{shouldPlayVoice = currentQueryFromVoice AND voiceAnswersEnabled}
J -->|true| K[playFillerIfEnabled]
K --> L[AI streams response]
L --> M[updateStreamingResponseIfEnabled]
M --> N[Voice spoken aloud]
J -->|false| O[Text-only response]
P[User types query] -->|fromVoice:false| F2[openAIInputWithQuery]
F2 --> G2[currentQueryFromVoice = false]
G2 --> H
Reviews (1): Last reviewed commit: "Add voice responses checkbox and show PT..." | Re-trigger Greptile |
| @@ -42,7 +43,7 @@ struct OnboardingVoiceDemoView: View { | |||
|
|
|||
| VStack(spacing: 24) { | |||
| VStack(spacing: 12) { | |||
| Text("Hold and Ask") | |||
| Text("Hold \(shortcutSettings.pttShortcut.displayLabel) and Ask") | |||
| .font(.system(size: 24, weight: .bold)) | |||
| .foregroundColor(OmiColors.textPrimary) | |||
|
|
|||
| @@ -52,6 +53,24 @@ struct OnboardingVoiceDemoView: View { | |||
| .multilineTextAlignment(.center) | |||
| } | |||
|
|
|||
| // Voice responses checkbox | |||
| HStack(spacing: 8) { | |||
| Toggle("", isOn: $voiceResponsesEnabled) | |||
| .toggleStyle(.checkbox) | |||
| .onChange(of: voiceResponsesEnabled) { _, newValue in | |||
| ShortcutSettings.shared.floatingBarVoiceAnswersEnabled = newValue | |||
There was a problem hiding this comment.
Local
@State can drift from ShortcutSettings
voiceResponsesEnabled is initialised once from ShortcutSettings.shared.floatingBarVoiceAnswersEnabled and is never re-synced if the setting is mutated externally (e.g. a SettingsSyncManager push after login completes during onboarding). The floatingBarVoiceAnswersBinding pattern already used in SettingsPage binds directly to the observed object and avoids the redundant state:
// In OnboardingVoiceDemoView — replace the @State and onChange with a binding helper:
private var floatingBarVoiceAnswersBinding: Binding<Bool> {
Binding(
get: { shortcutSettings.floatingBarVoiceAnswersEnabled },
set: { newValue in
shortcutSettings.floatingBarVoiceAnswersEnabled = newValue
SettingsSyncManager.shared.pushPartialUpdate(
AssistantSettingsResponse(
floatingBar: FloatingBarSettingsResponse(voiceAnswersEnabled: newValue)
)
)
}
)
}Then bind the Toggle to floatingBarVoiceAnswersBinding and drop @State private var voiceResponsesEnabled.
…6398) ## Summary - Voice responses enabled **by default** for all users (was opt-in experimental) - Only plays voice for **voice (PTT) queries** — typed questions get text-only responses - Updated settings label from "Voice Answers (Experimental)" to "Voice Responses" - Added "Enable voice responses" checkbox to onboarding voice demo step - Onboarding title now shows the actual PTT key ("Hold Option and Ask" instead of "Hold and Ask") ## Test plan - [ ] PTT voice question → AI response spoken aloud - [ ] Typed question → no audio response - [ ] Toggle off in Settings → voice stops for all queries - [ ] Onboarding checkbox controls the setting - [ ] Onboarding title shows correct PTT key 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Summary
Test plan
🤖 Generated with Claude Code