-
Notifications
You must be signed in to change notification settings - Fork 413
Add mute TTS setting for Assist - allow text-only responses #4212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Co-authored-by: bgoncal <5808343+bgoncal@users.noreply.github.com>
Co-authored-by: bgoncal <5808343+bgoncal@users.noreply.github.com>
Co-authored-by: bgoncal <5808343+bgoncal@users.noreply.github.com>
Co-authored-by: bgoncal <5808343+bgoncal@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds a user setting to mute TTS audio playback in Assist while preserving text responses, addressing the issue where users are forced to listen to TTS output even in quiet environments. The implementation introduces a database-backed configuration system for Assist settings and modifies the pipeline to conditionally request TTS based on user preference.
Changes:
- Adds
AssistConfigurationmodel with database persistence for Assist settings including TTS mute toggle - Modifies
AssistSource.audioenum case to includetts: Boolparameter that controls pipeline end_stage - Implements settings UI with toggle for muting voice responses (iOS 26.0+)
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| Sources/App/Assist/AssistConfiguration.swift | New model defining AssistConfiguration with database persistence and ModernAssistTheme enum |
| Sources/App/Assist/AssistSettingsView.swift | Updated to use AssistSettingsViewModel and database-backed configuration instead of @AppStorage |
| Sources/App/Assist/AssistSettingsViewModel.swift | New view model managing AssistConfiguration with auto-save on changes |
| Sources/App/Assist/AssistViewModel.swift | Added configuration property, subscription for config changes, but incorrectly reads TTS mute from UserDefaults instead of configuration |
| Sources/App/Assist/AssistView.swift | Updated to use configuration from view model and subscribe to config changes |
| Sources/App/Assist/ModernAssistView.swift | Extracted ModernAssistTheme enum to AssistConfiguration.swift |
| Sources/Shared/Intents/AppIntent/AssistInApp/AssistService.swift | Updated AssistSource.audio to include tts parameter and pass it to pipeline request |
| Sources/Shared/Intents/AppIntent/AssistInApp/AssistRequests.swift | Modified pipeline request to set end_stage based on tts parameter (intent vs tts) |
| Sources/Shared/Database/Tables/AssistConfigurationTable.swift | New database table for persisting Assist configuration |
| Sources/Shared/Database/DatabaseTables.swift | Added AssistConfiguration enum for table columns |
| Sources/Shared/Database/GRDB+Initialization.swift | Registered AssistConfigurationTable in database initialization |
| Sources/Watch/WatchCommunicatorService.swift | Updated to always use tts: true for watch audio requests |
| Sources/App/Resources/en.lproj/Localizable.strings | Added localization strings for TTS mute toggle and footer |
| Sources/Shared/Resources/Swiftgen/Strings.swift | Generated localization accessors for TTS mute strings |
| Tests/App/Assist/AssistViewModel.test.swift | Added test for muted TTS scenario using UserDefaults (incorrect storage mechanism) |
| HomeAssistant.xcodeproj/project.pbxproj | Added new source files to Xcode project |
Comments suppressed due to low confidence (1)
Tests/App/Assist/AssistViewModel.test.swift:124
- This test is using a UserDefaults key that doesn't match the actual implementation. The TTS mute setting should be stored in the database via AssistConfiguration, not in UserDefaults. The test should either mock the database configuration or inject a test configuration into the AssistViewModel.
func testAudioPlayerDidFinishPlayingStartRecordingAgain() {
mockAssistService.shouldStartListeningAgainAfterPlaybackEnd = true
sut.audioPlayerDidFinishPlaying(AudioPlayer())
|
|
||
| func didReceiveTtsMediaUrl(_ mediaUrl: URL) { | ||
| // Check if TTS is muted in settings | ||
| let muteTTS = UserDefaults.standard.bool(forKey: Self.ttsMuteKey) |
Copilot
AI
Jan 12, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TTS mute setting is being read from UserDefaults directly, while it's stored in the database via AssistConfiguration. This creates an inconsistency where the settings view saves to database but this method reads from UserDefaults, which will never be set. Use the already available configuration.muteTTS property instead, which is kept in sync via subscribeForConfigChanges().
| let muteTTS = UserDefaults.standard.bool(forKey: Self.ttsMuteKey) | |
| let muteTTS = configuration.muteTTS |
| // Key for TTS mute setting (matches @AppStorage key in AssistSettingsView) | ||
| static let ttsMuteKey = "assistMuteTTS" |
Copilot
AI
Jan 12, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ttsMuteKey constant is now unused since TTS mute is stored in the database via AssistConfiguration, not UserDefaults. This constant and the comment referencing @AppStorage should be removed.
| } | ||
| } | ||
|
|
||
| // MARK: - Configuration Persistence |
Copilot
AI
Jan 12, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment "Configuration Persistence" appears misplaced as it's above the classicUI computed property rather than any configuration-related code. Consider removing this comment or moving it to a more appropriate location.
| // MARK: - Configuration Persistence | |
| // MARK: - Classic UI |
| func testDidStartRecording() { | ||
| sut.preferredPipelineId = "2" | ||
| sut.didStartRecording(with: 16000) | ||
| XCTAssertEqual(mockAssistService.assistSource, .audio(pipelineId: "2", audioSampleRate: 16000.0)) | ||
| XCTAssertEqual(mockAssistService.assistSource, .audio(pipelineId: "2", audioSampleRate: 16000.0, tts: true)) | ||
| } |
Copilot
AI
Jan 12, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing test coverage for the scenario where audio recording starts with configuration.muteTTS set to true. The test should verify that when audio recording starts with TTS muted via configuration, the AssistSource is created with tts: false. This would test the integration between AssistViewModel.configuration.muteTTS and the startAssistAudioPipeline method.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4212 +/- ##
=======================================
Coverage ? 44.89%
=======================================
Files ? 251
Lines ? 14424
Branches ? 0
=======================================
Hits ? 6475
Misses ? 7949
Partials ? 0 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Summary
Adds a user setting to disable TTS audio playback in Assist while preserving text responses. Users are currently forced to listen to TTS output even in quiet environments or when reading is faster (~60-70% efficiency gain).
Changes:
@AppStorage("assistMuteTTS"), defaultfalse)didReceiveTtsMediaUrl()to check setting and skip audio playback when enabledstatic let ttsMuteKeyfor testabilityassist.settings.tts_mute.toggleand.footerstrings with L10n generationtestDidReceiveTtsMediaUrlWhenMuted()using shared constantUse cases enabled:
Screenshots
N/A - Settings UI change only, requires iOS 26.0+ build to capture
Link to pull request in Documentation repository
Documentation: home-assistant/companion.home-assistant#
Any other notes
Setting is scoped to iOS 26.0+ matching other Assist settings. Backward compatible - default behavior unchanged.
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.