Add setting to auto-show search keyboard

This commit is contained in:
Torsten Grote
2026-04-24 12:06:25 -03:00
parent f9bc9aca89
commit 656c1aaf5a
10 changed files with 70 additions and 7 deletions

View File

@@ -58,6 +58,9 @@ object SettingsConstants {
const val PREF_KEY_WARN_WHEN_METERED = "warnWhenMetered"
const val PREF_DEFAULT_WARN_WHEN_METERED = true
const val PREF_KEY_SHOW_SEARCH_KEYBOARD = "showSearchKeyboard"
const val PREF_DEFAULT_SHOW_SEARCH_KEYBOARD = false
const val PREF_KEY_SHOW_INCOMPATIBLE = "incompatibleVersions"
const val PREF_DEFAULT_SHOW_INCOMPATIBLE = true

View File

@@ -33,6 +33,7 @@ import org.fdroid.settings.SettingsConstants.PREF_DEFAULT_PREVENT_SCREENSHOTS
import org.fdroid.settings.SettingsConstants.PREF_DEFAULT_PROXY
import org.fdroid.settings.SettingsConstants.PREF_DEFAULT_REPO_UPDATES
import org.fdroid.settings.SettingsConstants.PREF_DEFAULT_SHOW_INCOMPATIBLE
import org.fdroid.settings.SettingsConstants.PREF_DEFAULT_SHOW_SEARCH_KEYBOARD
import org.fdroid.settings.SettingsConstants.PREF_DEFAULT_THEME
import org.fdroid.settings.SettingsConstants.PREF_DEFAULT_WARN_WHEN_METERED
import org.fdroid.settings.SettingsConstants.PREF_DNS_CACHE
@@ -50,6 +51,7 @@ import org.fdroid.settings.SettingsConstants.PREF_KEY_PREVENT_SCREENSHOTS
import org.fdroid.settings.SettingsConstants.PREF_KEY_PROXY
import org.fdroid.settings.SettingsConstants.PREF_KEY_REPO_UPDATES
import org.fdroid.settings.SettingsConstants.PREF_KEY_SHOW_INCOMPATIBLE
import org.fdroid.settings.SettingsConstants.PREF_KEY_SHOW_SEARCH_KEYBOARD
import org.fdroid.settings.SettingsConstants.PREF_KEY_THEME
import org.fdroid.settings.SettingsConstants.PREF_KEY_WARN_WHEN_METERED
import org.fdroid.settings.SettingsConstants.PREF_USE_DNS_CACHE
@@ -194,6 +196,10 @@ class SettingsManager @Inject constructor(@param:ApplicationContext private val
MutableStateFlow(prefs.getBoolean(PREF_KEY_WARN_WHEN_METERED, PREF_DEFAULT_WARN_WHEN_METERED))
val warnWhenMeteredFlow = _warnWhenMeteredFlow.asStateFlow()
private val _showSearchKeyboardFlow =
MutableStateFlow(prefs.getBoolean(PREF_KEY_SHOW_SEARCH_KEYBOARD, PREF_DEFAULT_SHOW_SEARCH_KEYBOARD))
val showSearchKeyboardFlow = _showSearchKeyboardFlow.asStateFlow()
val filterIncompatible: Boolean
get() = !prefs.getBoolean(PREF_KEY_SHOW_INCOMPATIBLE, PREF_DEFAULT_SHOW_INCOMPATIBLE)
@@ -217,6 +223,11 @@ class SettingsManager @Inject constructor(@param:ApplicationContext private val
_warnWhenMeteredFlow.update { false }
}
fun setShowSearchKeyboard(show: Boolean) {
prefs.edit { putBoolean(PREF_KEY_SHOW_SEARCH_KEYBOARD, show) }
_showSearchKeyboardFlow.update { show }
}
fun saveAppListFilter(sortOrder: AppListSortOrder, filterIncompatible: Boolean) {
prefs.edit {
putBoolean(PREF_KEY_SHOW_INCOMPATIBLE, !filterIncompatible)

View File

@@ -86,6 +86,8 @@ fun Main(onListeningForIntent: () -> Unit = {}) {
viewModel.savedSearchesFlow.collectAsStateWithLifecycle().value
override val categories: List<CategoryItem>? =
viewModel.categories.collectAsStateWithLifecycle(null).value
override val autoShowKeyboard: Boolean =
viewModel.autoShowKeyboard.collectAsStateWithLifecycle().value
override val showKeyboard: Boolean = showSearchKeyboard
override val actions: SearchActions = viewModel

View File

@@ -7,18 +7,27 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.input.TextFieldState
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Keyboard
import androidx.compose.material3.Checkbox
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SearchBarDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import org.fdroid.R
import org.fdroid.search.SavedSearch
import org.fdroid.ui.FDroidContent
import org.fdroid.ui.navigation.NavigationKey
import org.fdroid.ui.utils.TopAppBarOverflowButton
import org.fdroid.ui.utils.appListItems
import org.fdroid.ui.utils.categoryItems
import org.fdroid.ui.utils.getSearchInfo
@@ -36,14 +45,36 @@ fun GlobalSearch(
if (info.showKeyboard) info.onKeyboardShown()
}
val searchResults = info.searchResults
val showKeyboard =
info.showKeyboard || // either show keyboard because user double tapped the search icon
(info.autoShowKeyboard && // or auto-show is activated
(searchResults == null || // but only if no search results are shown
searchResults.apps.isEmpty() && searchResults.categories.isEmpty()))
Scaffold(
topBar = {
TopSearchBar(
searchFieldState = textFieldState,
shouldRequestFocus = info.showKeyboard,
shouldRequestFocus = showKeyboard,
onSearch = info.actions::onSearch,
onSearchCleared = info.actions::onSearchCleared,
onHideSearch = onBack,
actions = {
if (textFieldState.text.isEmpty()) {
TopAppBarOverflowButton { onDismiss ->
DropdownMenuItem(
leadingIcon = { Icon(Icons.Default.Keyboard, null) },
text = { Text(stringResource(R.string.search_auto_keyboard)) },
trailingIcon = {
Checkbox(checked = info.autoShowKeyboard, onCheckedChange = null)
},
onClick = {
info.actions.setAutoShowKeyboard(!info.autoShowKeyboard)
onDismiss()
},
)
}
}
},
)
}
) { paddingValues ->

View File

@@ -7,6 +7,7 @@ interface SearchInfo {
val searchResults: SearchResults?
val savedSearches: List<SavedSearch>?
val categories: List<CategoryItem>?
val autoShowKeyboard: Boolean
val showKeyboard: Boolean
val actions: SearchActions
fun onKeyboardShown()
@@ -18,4 +19,6 @@ interface SearchActions {
fun onSearchCleared()
fun onClearSearchHistory()
fun setAutoShowKeyboard(autoShow: Boolean)
}

View File

@@ -8,16 +8,21 @@ import jakarta.inject.Inject
import kotlinx.coroutines.launch
import org.fdroid.search.SearchHelper.isSearchable
import org.fdroid.search.SearchManager
import org.fdroid.settings.SettingsManager
@HiltViewModel
class SearchViewModel
@Inject
constructor(app: Application, private val searchManager: SearchManager) :
AndroidViewModel(app), SearchActions {
constructor(
app: Application,
private val searchManager: SearchManager,
private val settingsManager: SettingsManager,
) : AndroidViewModel(app), SearchActions {
val searchResults = searchManager.searchResults
val savedSearchesFlow = searchManager.savedSearches
val categories = searchManager.categories
val autoShowKeyboard = settingsManager.showSearchKeyboardFlow
override suspend fun onSearch(term: String) {
if (term.isSearchable()) searchManager.search(term)
@@ -28,4 +33,8 @@ constructor(app: Application, private val searchManager: SearchManager) :
override fun onClearSearchHistory() {
viewModelScope.launch { searchManager.onClearSearchHistory() }
}
override fun setAutoShowKeyboard(autoShow: Boolean) {
settingsManager.setShowSearchKeyboard(autoShow)
}
}

View File

@@ -650,6 +650,7 @@ fun getSearchInfo(
override val savedSearches: List<SavedSearch>? = savedSearches
override val categories: List<CategoryItem>? = categories
override val autoShowKeyboard: Boolean = false
override val showKeyboard: Boolean = false
override val actions: SearchActions =
@@ -659,6 +660,8 @@ fun getSearchInfo(
override fun onSearchCleared() {}
override fun onClearSearchHistory() {}
override fun setAutoShowKeyboard(autoShow: Boolean) {}
}
override fun onKeyboardShown() {}

View File

@@ -38,6 +38,7 @@
<string name="search_no_results">No apps found\n\nTry using fewer search terms or add more repositories</string>
<string name="search_filter_no_results">No matching apps\n\nTry using fewer search terms or remove filters</string>
<string name="search_my_apps_no_results">No matching apps\n\nTry using fewer search terms</string>
<string name="search_auto_keyboard">Automatically open keyboard</string>
<string name="sort_title">Sorting and compatibility</string>
<string name="sort_by_name">Sort by name</string>
<string name="sort_by_latest">Sort by last update</string>

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e926d11d01b2d8786e9af5077f60d47b51d23605e016559c94b998c85edd44f0
size 119038
oid sha256:9d61085047b8397d4f99513c930fac8bf4b5e6fcdd6f38a5c6aa177eb8a294be
size 119701

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b84731273d6b914154b20cd44c6a0ef56b6d5fd0815d0585e6d39da75b75760b
size 31966
oid sha256:119b1d10a0e9926c96197938152d5ef6e2e15c71017064e48af612a794e82082
size 32593