Reset search filters when query is cleared

This commit is contained in:
MM20 2024-04-21 20:30:55 +02:00
parent eda57aea2b
commit ee83b87f39
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
12 changed files with 91 additions and 55 deletions

View File

@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
@ -13,7 +12,6 @@ import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.*
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
@ -184,12 +182,9 @@ fun AssistantScaffold(
LauncherSearchBar(
modifier = Modifier
.fillMaxSize(),
searchBarOffset = {
(if (searchBarFocused || fixedSearchBar) 0
else searchBarOffset.toInt() * if (bottomSearchBar) -1 else 1)
- (if (bottomSearchBar) with(density) { keyboardFilterBarPadding.toPx() }.toInt() else 0)
},
style = searchBarStyle,
level = { searchBarLevel },
value = { value },
focused = searchBarFocused,
onFocusChange = {
if (it) viewModel.openSearch()
@ -198,11 +193,13 @@ fun AssistantScaffold(
actions = actions,
highlightedAction = searchVM.bestMatch.value as? SearchAction,
isSearchOpen = true,
value = { value },
onValueChange = { searchVM.search(it) },
darkColors = LocalPreferDarkContentOverWallpaper.current && searchBarColor == SearchBarColors.Auto || searchBarColor == SearchBarColors.Dark,
style = searchBarStyle,
bottomSearchBar = bottomSearchBar,
searchBarOffset = {
(if (searchBarFocused || fixedSearchBar) 0
else searchBarOffset.toInt() * if (bottomSearchBar) -1 else 1)
- (if (bottomSearchBar) with(density) { keyboardFilterBarPadding.toPx() }.toInt() else 0)
},
onKeyboardActionGo = if (launchOnEnter) {
{ searchVM.launchBestMatchOrAction(context) }
} else null

View File

@ -30,7 +30,6 @@ import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.PagerDefaults
@ -55,7 +54,6 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.geometry.Offset
@ -602,16 +600,9 @@ fun PagerScaffold(
LauncherSearchBar(
modifier = Modifier
.fillMaxSize(),
style = searchBarStyle,
level = { searchBarLevel },
searchBarOffset = {
(if (focusSearchBar || fixedSearchBar) 0 else searchBarOffset.value.toInt() * if (bottomSearchBar) 1 else -1) +
with(density) {
(widgetEditModeOffset - if (bottomSearchBar) keyboardFilterBarPadding else 0.dp)
.toPx()
.roundToInt()
}
},
bottomSearchBar = bottomSearchBar,
value = { value },
focused = focusSearchBar,
onFocusChange = {
if (it) viewModel.openSearch()
@ -620,10 +611,16 @@ fun PagerScaffold(
actions = actions,
highlightedAction = searchVM.bestMatch.value as? SearchAction,
isSearchOpen = isSearchOpen,
value = { value },
onValueChange = { searchVM.search(it) },
darkColors = LocalPreferDarkContentOverWallpaper.current && searchBarColor == SearchBarColors.Auto || searchBarColor == SearchBarColors.Dark,
style = searchBarStyle,
bottomSearchBar = bottomSearchBar,
searchBarOffset = {
(if (focusSearchBar || fixedSearchBar) 0 else searchBarOffset.value.toInt() * if (bottomSearchBar) 1 else -1) +
with(density) {
(widgetEditModeOffset - if (bottomSearchBar) keyboardFilterBarPadding else 0.dp)
.toPx()
.roundToInt()
}
},
onKeyboardActionGo = if (launchOnEnter) {
{ searchVM.launchBestMatchOrAction(context) }
} else null

View File

@ -58,9 +58,7 @@ import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.IntOffset
@ -580,12 +578,19 @@ fun PullDownScaffold(
LauncherSearchBar(
modifier = Modifier
.fillMaxSize(),
style = searchBarStyle,
level = { searchBarLevel },
value = { value },
focused = searchBarFocused,
onFocusChange = {
if (it) viewModel.openSearch()
viewModel.setSearchbarFocus(it)
},
actions = actions,
highlightedAction = searchVM.bestMatch.value as? SearchAction,
isSearchOpen = isSearchOpen,
darkColors = LocalPreferDarkContentOverWallpaper.current && searchBarColor == SearchBarColors.Auto || searchBarColor == SearchBarColors.Dark,
bottomSearchBar = bottomSearchBar,
searchBarOffset = {
(if (searchBarFocused || fixedSearchBar) 0 else searchBarOffset.value.toInt() * (if (bottomSearchBar) 1 else -1)) +
with(density) {
@ -594,14 +599,6 @@ fun PullDownScaffold(
.roundToInt()
}
},
actions = actions,
highlightedAction = searchVM.bestMatch.value as? SearchAction,
isSearchOpen = isSearchOpen,
value = { value },
onValueChange = { searchVM.search(it) },
darkColors = LocalPreferDarkContentOverWallpaper.current && searchBarColor == SearchBarColors.Auto || searchBarColor == SearchBarColors.Dark,
style = searchBarStyle,
bottomSearchBar = bottomSearchBar,
onKeyboardActionGo = if (launchOnEnter) {
{ searchVM.launchBestMatchOrAction(context) }
} else null

View File

@ -11,9 +11,9 @@ import de.mm20.launcher2.permissions.PermissionsManager
import de.mm20.launcher2.preferences.SearchResultOrder
import de.mm20.launcher2.preferences.search.CalendarSearchSettings
import de.mm20.launcher2.preferences.search.ContactSearchSettings
import de.mm20.launcher2.preferences.search.FavoritesSettings
import de.mm20.launcher2.preferences.search.FileSearchSettings
import de.mm20.launcher2.preferences.search.LocationSearchSettings
import de.mm20.launcher2.preferences.search.SearchFilterSettings
import de.mm20.launcher2.preferences.search.ShortcutSearchSettings
import de.mm20.launcher2.preferences.ui.SearchUiSettings
import de.mm20.launcher2.search.AppProfile
@ -42,7 +42,6 @@ import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
@ -63,6 +62,7 @@ class SearchVM : ViewModel(), KoinComponent {
private val searchUiSettings: SearchUiSettings by inject()
private val locationSearchSettings: LocationSearchSettings by inject()
private val devicePoseProvider: DevicePoseProvider by inject()
private val searchFilterSettings: SearchFilterSettings by inject()
val launchOnEnter = searchUiSettings.launchOnEnter
.stateIn(viewModelScope, SharingStarted.Eagerly, false)
@ -93,7 +93,8 @@ class SearchVM : ViewModel(), KoinComponent {
val showFilters = mutableStateOf(false)
val filters = mutableStateOf(SearchFilters())
val defaultFilters = searchFilterSettings.defaultFilter.stateIn(viewModelScope, SharingStarted.Eagerly, SearchFilters())
val filters = mutableStateOf(defaultFilters.value)
val separateWorkProfile = searchUiSettings.separateWorkProfile
@ -133,6 +134,7 @@ class SearchVM : ViewModel(), KoinComponent {
fun reset() {
closeFilters()
filters.value = defaultFilters.value
search("")
}
@ -142,6 +144,9 @@ class SearchVM : ViewModel(), KoinComponent {
if (searchQuery.value != query) {
showFilters.value = false
}
if (query.isEmpty() && searchQuery.value.isNotEmpty()) {
filters.value = defaultFilters.value
}
searchQuery.value = query
isSearchEmpty.value = query.isEmpty()
hiddenResults.value = emptyList()

View File

@ -2,11 +2,8 @@ package de.mm20.launcher2.ui.launcher.search.filters
import androidx.compose.foundation.background
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.imePadding

View File

@ -2,19 +2,13 @@ package de.mm20.launcher2.ui.launcher.searchbar
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.tween
import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.imeAnimationTarget
import androidx.compose.foundation.layout.isImeVisible
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
@ -29,8 +23,6 @@ import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -46,7 +38,6 @@ import de.mm20.launcher2.ui.component.SearchBar
import de.mm20.launcher2.ui.component.SearchBarLevel
import de.mm20.launcher2.ui.launcher.search.SearchVM
import de.mm20.launcher2.ui.launcher.search.filters.KeyboardFilterBar
import de.mm20.launcher2.ui.launcher.sheets.LocalBottomSheetManager
@Composable
fun LauncherSearchBar(
@ -54,7 +45,6 @@ fun LauncherSearchBar(
style: SearchBarStyle,
level: () -> SearchBarLevel,
value: () -> String,
onValueChange: (String) -> Unit,
focused: Boolean,
onFocusChange: (Boolean) -> Unit,
actions: List<SearchAction>,
@ -85,7 +75,9 @@ fun LauncherSearchBar(
.windowInsetsPadding(WindowInsets.safeDrawing)
.padding(8.dp)
.offset { IntOffset(0, searchBarOffset()) },
style = style, level = level(), value = _value, onValueChange = onValueChange,
style = style, level = level(), value = _value, onValueChange = {
searchVM.search(it)
},
reverse = bottomSearchBar,
darkColors = darkColors,
menu = {
@ -118,7 +110,9 @@ fun LauncherSearchBar(
}
}
}
SearchBarMenu(searchBarValue = _value, onSearchBarValueChange = onValueChange)
SearchBarMenu(searchBarValue = _value, onInputClear = {
searchVM.reset()
})
},
actions = {
SearchBarActions(

View File

@ -38,7 +38,7 @@ import de.mm20.launcher2.ui.settings.SettingsActivity
@Composable
fun RowScope.SearchBarMenu(
searchBarValue: String,
onSearchBarValueChange: (newValue: String) -> Unit,
onInputClear: () -> Unit,
) {
val context = LocalContext.current
var showOverflowMenu by remember { mutableStateOf(false) }
@ -47,7 +47,7 @@ fun RowScope.SearchBarMenu(
val widgetsVM: WidgetsVM = viewModel()
IconButton(onClick = {
if (searchBarValue.isNotBlank()) onSearchBarValueChange("")
if (searchBarValue.isNotBlank()) onInputClear()
else showOverflowMenu = true
}) {
Icon(

View File

@ -1,6 +1,7 @@
plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.plugin.serialization)
}
android {

View File

@ -1,7 +1,9 @@
package de.mm20.launcher2.search
import de.mm20.launcher2.ktx.toInt
import kotlinx.serialization.Serializable
@Serializable
data class SearchFilters(
val allowNetwork: Boolean = false,
val hiddenItems: Boolean = false,

View File

@ -2,6 +2,7 @@ package de.mm20.launcher2.preferences
import android.content.Context
import de.mm20.launcher2.preferences.search.LocationSearchSettings
import de.mm20.launcher2.search.SearchFilters
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@ -144,6 +145,23 @@ data class LauncherSettingsData internal constructor(
val locationSearchShowPositionOnMap: Boolean = false,
val locationSearchThemeMap: Boolean = true,
val searchFilter: SearchFilters = SearchFilters(),
val searchFilterBar: Boolean = true,
val searchFilterBarItems: List<KeyboardFilterBarItem> = listOf(
KeyboardFilterBarItem.OnlineResults,
KeyboardFilterBarItem.Apps,
KeyboardFilterBarItem.Shortcuts,
KeyboardFilterBarItem.Events,
KeyboardFilterBarItem.Contacts,
KeyboardFilterBarItem.Files,
KeyboardFilterBarItem.Places,
KeyboardFilterBarItem.Articles,
KeyboardFilterBarItem.Websites,
KeyboardFilterBarItem.Places,
KeyboardFilterBarItem.Tools,
KeyboardFilterBarItem.HiddenResults,
),
) {
constructor(
@ -377,3 +395,18 @@ data class ProviderSettings(
val locationId: String? = null,
val locationName: String? = null,
)
@Serializable
enum class KeyboardFilterBarItem {
@SerialName("online") OnlineResults,
@SerialName("apps") Apps,
@SerialName("websites") Websites,
@SerialName("articles") Articles,
@SerialName("places") Places,
@SerialName("files") Files,
@SerialName("shortcuts") Shortcuts,
@SerialName("contacts") Contacts,
@SerialName("events") Events,
@SerialName("tools") Tools,
@SerialName("hidden") HiddenResults,
}

View File

@ -9,6 +9,7 @@ import de.mm20.launcher2.preferences.search.FavoritesSettings
import de.mm20.launcher2.preferences.search.FileSearchSettings
import de.mm20.launcher2.preferences.search.LocationSearchSettings
import de.mm20.launcher2.preferences.search.RankingSettings
import de.mm20.launcher2.preferences.search.SearchFilterSettings
import de.mm20.launcher2.preferences.search.ShortcutSearchSettings
import de.mm20.launcher2.preferences.search.UnitConverterSettings
import de.mm20.launcher2.preferences.search.WebsiteSearchSettings
@ -49,4 +50,5 @@ val preferencesModule = module {
factory { CalculatorSearchSettings(get()) }
factory { ClockWidgetSettings(get()) }
factory { LocationSearchSettings(get()) }
factory { SearchFilterSettings(get()) }
}

View File

@ -0,0 +1,11 @@
package de.mm20.launcher2.preferences.search
import de.mm20.launcher2.preferences.LauncherDataStore
import kotlinx.coroutines.flow.map
class SearchFilterSettings internal constructor(
private val launcherDataStore: LauncherDataStore,
) {
val defaultFilter
get() = launcherDataStore.data.map { it.searchFilter }
}