From bfbceb1999d4d8dbd27e485d17f6379c59fa2e3e Mon Sep 17 00:00:00 2001 From: Justin Visser Date: Thu, 21 May 2026 13:01:12 +0200 Subject: [PATCH] Add option to hide the voice search button Adds a toggle to SearchPreferences (`show_voice_search_button`, default true) and a new entry in the search page's view options dialog. When disabled, the voice search button is hidden from the search row. For existing users, an entry in AppUpgradeHandler sets the value to true so the button stays visible after upgrade. --- .../preferences/AppPreferencesSerializer.kt | 1 + .../wholphin/services/AppUpgradeHandler.kt | 7 +++ .../wholphin/ui/main/SearchPage.kt | 61 ++++++++++++++++--- app/src/main/proto/WholphinDataStore.proto | 1 + app/src/main/res/values/strings.xml | 3 + 5 files changed, 66 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreferencesSerializer.kt b/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreferencesSerializer.kt index 47dae5ec..99145371 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreferencesSerializer.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreferencesSerializer.kt @@ -105,6 +105,7 @@ class AppPreferencesSerializer .newBuilder() .apply { combinedSearchResults = false + showVoiceSearchButton = true }.build() subtitlesPreferences = diff --git a/app/src/main/java/com/github/damontecres/wholphin/services/AppUpgradeHandler.kt b/app/src/main/java/com/github/damontecres/wholphin/services/AppUpgradeHandler.kt index 778f300c..7ba190de 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/services/AppUpgradeHandler.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/services/AppUpgradeHandler.kt @@ -21,6 +21,7 @@ import com.github.damontecres.wholphin.preferences.updatePhotoPreferences import com.github.damontecres.wholphin.preferences.updatePlaybackOverrides import com.github.damontecres.wholphin.preferences.updatePlaybackPreferences import com.github.damontecres.wholphin.preferences.updateScreensaverPreferences +import com.github.damontecres.wholphin.preferences.updateSearchPreferences import com.github.damontecres.wholphin.preferences.updateSubtitlePreferences import com.github.damontecres.wholphin.ui.preferences.PreferencesViewModel import com.github.damontecres.wholphin.ui.preferences.subtitle.SubtitleSettings @@ -334,5 +335,11 @@ class AppUpgradeHandler it.updatePlaybackPreferences { cinemaMode = AppPreference.CinemaMode.defaultValue } } } + + if (previous.isEqualOrBefore(Version.fromString("0.6.4-8-g0"))) { + appPreferences.updateData { + it.updateSearchPreferences { showVoiceSearchButton = true } + } + } } } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/main/SearchPage.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/main/SearchPage.kt index 28d469e9..3e4b1b63 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/main/SearchPage.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/main/SearchPage.kt @@ -138,6 +138,11 @@ class SearchViewModel .map { it.interfacePreferences.searchPreferences.combinedSearchResults } .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), false) + val voiceSearchButtonVisibleFlow: StateFlow = + appPreferences.data + .map { it.interfacePreferences.searchPreferences.showVoiceSearchButton } + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), true) + val movies = MutableLiveData(SearchResult.NoQuery) val series = MutableLiveData(SearchResult.NoQuery) val episodes = MutableLiveData(SearchResult.NoQuery) @@ -275,6 +280,16 @@ class SearchViewModel } } + fun setVoiceSearchButtonVisible(visible: Boolean) { + viewModelScope.launchIO { + appPreferences.updateData { + it.updateSearchPreferences { + showVoiceSearchButton = visible + } + } + } + } + private fun searchSeerr(query: String) { viewModelScope.launchIO { if (seerrService.active.first()) { @@ -351,6 +366,7 @@ fun SearchPage( val seerrResults by viewModel.seerrResults.observeAsState(SearchResult.NoQuery) val combinedResults by viewModel.combinedResults.observeAsState(SearchResult.NoQuery) val combinedMode by viewModel.combinedModeFlow.collectAsState() + val voiceSearchButtonVisible by viewModel.voiceSearchButtonVisibleFlow.collectAsState() // val query = rememberTextFieldState() var query by rememberSaveable { mutableStateOf("") } @@ -508,13 +524,15 @@ fun SearchPage( .focusRestorer(textFieldFocusRequester) .focusRequester(focusRequesters[SEARCH_ROW]), ) { - VoiceSearchButton( - onSpeechResult = { spokenText -> - query = spokenText - triggerImmediateSearch(spokenText) - }, - voiceInputManager = viewModel.voiceInputManager, - ) + if (voiceSearchButtonVisible) { + VoiceSearchButton( + onSpeechResult = { spokenText -> + query = spokenText + triggerImmediateSearch(spokenText) + }, + voiceInputManager = viewModel.voiceInputManager, + ) + } SearchEditTextBox( value = query, @@ -757,6 +775,8 @@ fun SearchPage( SearchViewOptionsDialog( combinedResults = combinedMode, onCombinedResultsChange = viewModel::setCombinedResults, + voiceSearchButtonVisible = voiceSearchButtonVisible, + onVoiceSearchButtonVisibleChange = viewModel::setVoiceSearchButtonVisible, onDismissRequest = { showViewOptions = false }, ) } @@ -766,6 +786,8 @@ fun SearchPage( fun SearchViewOptionsDialog( combinedResults: Boolean, onCombinedResultsChange: (Boolean) -> Unit, + voiceSearchButtonVisible: Boolean, + onVoiceSearchButtonVisibleChange: (Boolean) -> Unit, onDismissRequest: () -> Unit, ) { Dialog( @@ -815,6 +837,31 @@ fun SearchViewOptionsDialog( onClick = { onCombinedResultsChange(!combinedResults) }, modifier = Modifier.fillMaxWidth(), ) + + ListItem( + selected = false, + headlineContent = { + Text(stringResource(R.string.show_voice_search_button)) + }, + supportingContent = { + Text( + if (voiceSearchButtonVisible) { + stringResource(R.string.show_voice_search_button_on) + } else { + stringResource(R.string.show_voice_search_button_off) + }, + ) + }, + trailingContent = { + Switch( + checked = voiceSearchButtonVisible, + onCheckedChange = onVoiceSearchButtonVisibleChange, + colors = SwitchColors(), + ) + }, + onClick = { onVoiceSearchButtonVisibleChange(!voiceSearchButtonVisible) }, + modifier = Modifier.fillMaxWidth(), + ) } } } diff --git a/app/src/main/proto/WholphinDataStore.proto b/app/src/main/proto/WholphinDataStore.proto index fb72875b..f4ca3f98 100644 --- a/app/src/main/proto/WholphinDataStore.proto +++ b/app/src/main/proto/WholphinDataStore.proto @@ -168,6 +168,7 @@ message ScreensaverPreferences{ message SearchPreferences { bool combined_search_results = 1; + bool show_voice_search_button = 2; } enum DisplayToggle{ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3ea099a7..b9fd7756 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -449,6 +449,9 @@ Combined search results Show all results in a single list Show results by category + Show voice search button + Visible + Hidden Results Resolution switching Local