Add filter bar customizations
This commit is contained in:
parent
5d824108c7
commit
94893a2c43
@ -301,7 +301,7 @@ fun Modifier.dragAndDrop(
|
||||
dragHorizontal: Boolean = true,
|
||||
hapticFeedback: HapticFeedback
|
||||
) =
|
||||
this then pointerInput(null) {
|
||||
this then Modifier.pointerInput(null) {
|
||||
val scope = CoroutineScope(coroutineContext)
|
||||
detectDragGesturesAfterLongPress(
|
||||
onDragStart = { offset ->
|
||||
|
||||
@ -96,6 +96,7 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
private val defaultFilters = searchFilterSettings.defaultFilter.stateIn(viewModelScope, SharingStarted.Eagerly, SearchFilters())
|
||||
val filters = mutableStateOf(defaultFilters.value)
|
||||
val filterBar = searchFilterSettings.filterBar
|
||||
val filterBarItems = searchFilterSettings.filterBarItems
|
||||
|
||||
val separateWorkProfile = searchUiSettings.separateWorkProfile
|
||||
|
||||
|
||||
@ -31,14 +31,21 @@ import androidx.compose.material3.VerticalDivider
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import de.mm20.launcher2.preferences.KeyboardFilterBarItem
|
||||
import de.mm20.launcher2.search.SearchFilters
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.icons.Wikipedia
|
||||
|
||||
@Composable
|
||||
fun KeyboardFilterBar(filters: SearchFilters, onFiltersChange: (SearchFilters) -> Unit) {
|
||||
fun KeyboardFilterBar(
|
||||
filters: SearchFilters,
|
||||
onFiltersChange: (SearchFilters) -> Unit,
|
||||
items: List<KeyboardFilterBarItem>,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val allCategoriesEnabled = filters.allCategoriesEnabled
|
||||
Column(
|
||||
modifier = Modifier
|
||||
@ -54,179 +61,33 @@ fun KeyboardFilterBar(filters: SearchFilters, onFiltersChange: (SearchFilters) -
|
||||
.padding(horizontal = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
FilterChip(
|
||||
selected = filters.allowNetwork,
|
||||
onClick = {
|
||||
onFiltersChange(filters.copy(allowNetwork = !filters.allowNetwork))
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Language,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(FilterChipDefaults.IconSize)
|
||||
)
|
||||
},
|
||||
label = { Text(stringResource(R.string.search_filter_online)) }
|
||||
)
|
||||
for (i in items.indices) {
|
||||
val item = items[i]
|
||||
val prevItem = items.getOrNull(i - 1)
|
||||
if (prevItem != null && prevItem.isCategory != item.isCategory) {
|
||||
VerticalDivider(
|
||||
modifier = Modifier
|
||||
.height(36.dp)
|
||||
.padding(horizontal = 8.dp)
|
||||
.padding(end = 8.dp)
|
||||
)
|
||||
}
|
||||
FilterChip(
|
||||
modifier = Modifier.padding(end = 8.dp),
|
||||
selected = filters.apps && !allCategoriesEnabled,
|
||||
modifier = Modifier.padding(end = if (i == items.lastIndex) 0.dp else 8.dp),
|
||||
selected = filters.isSelected(item),
|
||||
onClick = {
|
||||
onFiltersChange(filters.toggleApps())
|
||||
onFiltersChange(filters.toggle(item))
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Apps,
|
||||
imageVector = item.icon,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(FilterChipDefaults.IconSize)
|
||||
)
|
||||
},
|
||||
label = { Text(stringResource(R.string.search_filter_apps)) }
|
||||
)
|
||||
FilterChip(
|
||||
modifier = Modifier.padding(end = 8.dp),
|
||||
selected = filters.files && !allCategoriesEnabled,
|
||||
onClick = {
|
||||
onFiltersChange(filters.toggleFiles())
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Description,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(FilterChipDefaults.IconSize)
|
||||
)
|
||||
},
|
||||
label = { Text(stringResource(R.string.preference_search_files)) }
|
||||
)
|
||||
FilterChip(
|
||||
modifier = Modifier.padding(end = 8.dp),
|
||||
selected = filters.contacts && !allCategoriesEnabled,
|
||||
onClick = {
|
||||
onFiltersChange(filters.toggleContacts())
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Person,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(FilterChipDefaults.IconSize)
|
||||
)
|
||||
},
|
||||
label = { Text(stringResource(R.string.preference_search_contacts)) }
|
||||
)
|
||||
FilterChip(
|
||||
modifier = Modifier.padding(end = 8.dp),
|
||||
selected = filters.events && !allCategoriesEnabled,
|
||||
onClick = {
|
||||
onFiltersChange(filters.toggleEvents())
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Today,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(FilterChipDefaults.IconSize)
|
||||
)
|
||||
},
|
||||
label = { Text(stringResource(R.string.preference_search_calendar)) }
|
||||
)
|
||||
FilterChip(
|
||||
modifier = Modifier.padding(end = 8.dp),
|
||||
selected = filters.shortcuts && !allCategoriesEnabled,
|
||||
onClick = {
|
||||
onFiltersChange(filters.toggleShortcuts())
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.AppShortcut,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(FilterChipDefaults.IconSize)
|
||||
)
|
||||
},
|
||||
label = { Text(stringResource(R.string.preference_search_appshortcuts)) }
|
||||
)
|
||||
FilterChip(
|
||||
modifier = Modifier.padding(end = 8.dp),
|
||||
selected = filters.articles && !allCategoriesEnabled,
|
||||
onClick = {
|
||||
onFiltersChange(filters.toggleArticles())
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Wikipedia,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(FilterChipDefaults.IconSize)
|
||||
)
|
||||
},
|
||||
label = { Text(stringResource(R.string.preference_search_wikipedia)) }
|
||||
)
|
||||
FilterChip(
|
||||
modifier = Modifier.padding(end = 8.dp),
|
||||
selected = filters.websites && !allCategoriesEnabled,
|
||||
onClick = {
|
||||
onFiltersChange(filters.toggleWebsites())
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Public,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(FilterChipDefaults.IconSize)
|
||||
)
|
||||
},
|
||||
label = { Text(stringResource(R.string.preference_search_websites)) }
|
||||
)
|
||||
FilterChip(
|
||||
modifier = Modifier.padding(end = 8.dp),
|
||||
selected = filters.places && !allCategoriesEnabled,
|
||||
onClick = {
|
||||
onFiltersChange(filters.togglePlaces())
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Place,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(FilterChipDefaults.IconSize)
|
||||
)
|
||||
},
|
||||
label = { Text(stringResource(R.string.preference_search_locations)) }
|
||||
)
|
||||
FilterChip(
|
||||
selected = filters.tools && !allCategoriesEnabled,
|
||||
onClick = {
|
||||
onFiltersChange(filters.toggleTools())
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Handyman,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(FilterChipDefaults.IconSize)
|
||||
)
|
||||
},
|
||||
label = { Text(stringResource(R.string.search_filter_tools)) }
|
||||
)
|
||||
VerticalDivider(
|
||||
modifier = Modifier
|
||||
.height(36.dp)
|
||||
.padding(horizontal = 8.dp)
|
||||
)
|
||||
FilterChip(
|
||||
selected = filters.hiddenItems,
|
||||
onClick = {
|
||||
onFiltersChange(filters.copy(hiddenItems = !filters.hiddenItems))
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.VisibilityOff,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(FilterChipDefaults.IconSize)
|
||||
)
|
||||
},
|
||||
label = { Text(stringResource(R.string.preference_hidden_items)) }
|
||||
label = { Text(item.getLabel(context)) }
|
||||
)
|
||||
}
|
||||
}
|
||||
HorizontalDivider()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
package de.mm20.launcher2.ui.launcher.search.filters
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.AppShortcut
|
||||
import androidx.compose.material.icons.rounded.Apps
|
||||
import androidx.compose.material.icons.rounded.Description
|
||||
import androidx.compose.material.icons.rounded.Handyman
|
||||
import androidx.compose.material.icons.rounded.Language
|
||||
import androidx.compose.material.icons.rounded.Person
|
||||
import androidx.compose.material.icons.rounded.Place
|
||||
import androidx.compose.material.icons.rounded.Public
|
||||
import androidx.compose.material.icons.rounded.Today
|
||||
import androidx.compose.material.icons.rounded.VisibilityOff
|
||||
import de.mm20.launcher2.preferences.KeyboardFilterBarItem
|
||||
import de.mm20.launcher2.search.SearchFilters
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.icons.Wikipedia
|
||||
|
||||
val KeyboardFilterBarItem.icon
|
||||
get() = when (this) {
|
||||
KeyboardFilterBarItem.Apps -> Icons.Rounded.Apps
|
||||
KeyboardFilterBarItem.Events -> Icons.Rounded.Today
|
||||
KeyboardFilterBarItem.Contacts -> Icons.Rounded.Person
|
||||
KeyboardFilterBarItem.Places -> Icons.Rounded.Place
|
||||
KeyboardFilterBarItem.Files -> Icons.Rounded.Description
|
||||
KeyboardFilterBarItem.Tools -> Icons.Rounded.Handyman
|
||||
KeyboardFilterBarItem.Articles -> Icons.Rounded.Wikipedia
|
||||
KeyboardFilterBarItem.Websites -> Icons.Rounded.Public
|
||||
KeyboardFilterBarItem.Shortcuts -> Icons.Rounded.AppShortcut
|
||||
KeyboardFilterBarItem.HiddenResults -> Icons.Rounded.VisibilityOff
|
||||
KeyboardFilterBarItem.OnlineResults -> Icons.Rounded.Language
|
||||
}
|
||||
|
||||
fun KeyboardFilterBarItem.getLabel(context: Context): String {
|
||||
return when (this) {
|
||||
KeyboardFilterBarItem.Apps -> context.getString(R.string.search_filter_apps)
|
||||
KeyboardFilterBarItem.Events -> context.getString(R.string.preference_search_calendar)
|
||||
KeyboardFilterBarItem.Contacts -> context.getString(R.string.preference_search_contacts)
|
||||
KeyboardFilterBarItem.Places -> context.getString(R.string.preference_search_locations)
|
||||
KeyboardFilterBarItem.Files -> context.getString(R.string.preference_search_files)
|
||||
KeyboardFilterBarItem.Tools -> context.getString(R.string.search_filter_tools)
|
||||
KeyboardFilterBarItem.Articles -> context.getString(R.string.preference_search_wikipedia)
|
||||
KeyboardFilterBarItem.Websites -> context.getString(R.string.preference_search_websites)
|
||||
KeyboardFilterBarItem.Shortcuts -> context.getString(R.string.preference_search_appshortcuts)
|
||||
KeyboardFilterBarItem.HiddenResults -> context.getString(R.string.preference_hidden_items)
|
||||
KeyboardFilterBarItem.OnlineResults -> context.getString(R.string.search_filter_online)
|
||||
}
|
||||
}
|
||||
|
||||
val KeyboardFilterBarItem.isCategory
|
||||
get() = when (this) {
|
||||
KeyboardFilterBarItem.OnlineResults, KeyboardFilterBarItem.HiddenResults -> false
|
||||
else -> true
|
||||
}
|
||||
|
||||
fun SearchFilters.isSelected(item: KeyboardFilterBarItem): Boolean {
|
||||
if (item.isCategory && allCategoriesEnabled) return false
|
||||
return when (item) {
|
||||
KeyboardFilterBarItem.Apps -> apps
|
||||
KeyboardFilterBarItem.Events -> events
|
||||
KeyboardFilterBarItem.Contacts -> contacts
|
||||
KeyboardFilterBarItem.Places -> places
|
||||
KeyboardFilterBarItem.Files -> files
|
||||
KeyboardFilterBarItem.Tools -> tools
|
||||
KeyboardFilterBarItem.Articles -> articles
|
||||
KeyboardFilterBarItem.Websites -> websites
|
||||
KeyboardFilterBarItem.Shortcuts -> shortcuts
|
||||
KeyboardFilterBarItem.HiddenResults -> hiddenItems
|
||||
KeyboardFilterBarItem.OnlineResults -> allowNetwork
|
||||
}
|
||||
}
|
||||
|
||||
fun SearchFilters.toggle(item: KeyboardFilterBarItem): SearchFilters {
|
||||
return when (item) {
|
||||
KeyboardFilterBarItem.Apps -> return toggleApps()
|
||||
KeyboardFilterBarItem.Events -> return toggleEvents()
|
||||
KeyboardFilterBarItem.Contacts -> return toggleContacts()
|
||||
KeyboardFilterBarItem.Places -> return togglePlaces()
|
||||
KeyboardFilterBarItem.Files -> return toggleFiles()
|
||||
KeyboardFilterBarItem.Tools -> return toggleTools()
|
||||
KeyboardFilterBarItem.Articles -> return toggleArticles()
|
||||
KeyboardFilterBarItem.Websites -> return toggleWebsites()
|
||||
KeyboardFilterBarItem.Shortcuts -> return toggleShortcuts()
|
||||
KeyboardFilterBarItem.HiddenResults -> return copy(hiddenItems = !hiddenItems)
|
||||
KeyboardFilterBarItem.OnlineResults -> return copy(allowNetwork = !allowNetwork)
|
||||
}
|
||||
}
|
||||
@ -137,11 +137,13 @@ fun LauncherSearchBar(
|
||||
exit = fadeOut(),
|
||||
modifier = Modifier.align(Alignment.BottomCenter)
|
||||
) {
|
||||
val items by searchVM.filterBarItems.collectAsState(emptyList())
|
||||
KeyboardFilterBar(
|
||||
filters = searchVM.filters.value,
|
||||
onFiltersChange = {
|
||||
searchVM.setFilters(it)
|
||||
}
|
||||
},
|
||||
items = items
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,6 +42,7 @@ import de.mm20.launcher2.ui.settings.debug.DebugSettingsScreen
|
||||
import de.mm20.launcher2.ui.settings.easteregg.EasterEggSettingsScreen
|
||||
import de.mm20.launcher2.ui.settings.favorites.FavoritesSettingsScreen
|
||||
import de.mm20.launcher2.ui.settings.filesearch.FileSearchSettingsScreen
|
||||
import de.mm20.launcher2.ui.settings.filterbar.FilterBarSettingsScreen
|
||||
import de.mm20.launcher2.ui.settings.gestures.GestureSettingsScreen
|
||||
import de.mm20.launcher2.ui.settings.hiddenitems.HiddenItemsSettingsScreen
|
||||
import de.mm20.launcher2.ui.settings.homescreen.HomescreenSettingsScreen
|
||||
@ -170,6 +171,9 @@ class SettingsActivity : BaseActivity() {
|
||||
composable("settings/search/tags") {
|
||||
TagsSettingsScreen()
|
||||
}
|
||||
composable("settings/search/filterbar") {
|
||||
FilterBarSettingsScreen()
|
||||
}
|
||||
composable(ROUTE_WEATHER_INTEGRATION) {
|
||||
WeatherIntegrationSettingsScreen()
|
||||
}
|
||||
|
||||
@ -0,0 +1,139 @@
|
||||
package de.mm20.launcher2.ui.settings.filterbar
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.animation.core.animateDpAsState
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.ArrowBack
|
||||
import androidx.compose.material3.CenterAlignedTopAppBar
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.zIndex
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import de.mm20.launcher2.preferences.KeyboardFilterBarItem
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.component.dragndrop.DraggableItem
|
||||
import de.mm20.launcher2.ui.component.dragndrop.LazyDragAndDropColumn
|
||||
import de.mm20.launcher2.ui.component.dragndrop.rememberLazyDragAndDropListState
|
||||
import de.mm20.launcher2.ui.component.preferences.SwitchPreference
|
||||
import de.mm20.launcher2.ui.launcher.search.filters.getLabel
|
||||
import de.mm20.launcher2.ui.launcher.search.filters.icon
|
||||
import de.mm20.launcher2.ui.launcher.search.filters.isCategory
|
||||
import de.mm20.launcher2.ui.locals.LocalNavController
|
||||
|
||||
@Composable
|
||||
fun FilterBarSettingsScreen() {
|
||||
val viewModel: FilterBarSettingsScreenVM = viewModel()
|
||||
val navController = LocalNavController.current
|
||||
val systemUiController = rememberSystemUiController()
|
||||
systemUiController.setStatusBarColor(MaterialTheme.colorScheme.surface)
|
||||
systemUiController.setNavigationBarColor(Color.Black)
|
||||
|
||||
val context = LocalContext.current
|
||||
val activity = LocalContext.current as? AppCompatActivity
|
||||
|
||||
val listState = rememberLazyDragAndDropListState(
|
||||
onDragStart = {
|
||||
it.key is KeyboardFilterBarItem
|
||||
},
|
||||
onItemMove = { from, to ->
|
||||
val item = (from.key as? KeyboardFilterBarItem) ?: return@rememberLazyDragAndDropListState
|
||||
val toItem = (to.key as? KeyboardFilterBarItem) ?: return@rememberLazyDragAndDropListState
|
||||
viewModel.moveItem(item, toItem)
|
||||
}
|
||||
)
|
||||
|
||||
val enabledItems by viewModel.filterBarItems.collectAsState()
|
||||
|
||||
val disabledItems by remember {
|
||||
derivedStateOf {
|
||||
KeyboardFilterBarItem.entries.filter { enabledItems?.contains(it) == false }
|
||||
}
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
CenterAlignedTopAppBar(
|
||||
title = {
|
||||
Text(
|
||||
stringResource(id = R.string.preference_customize_filter_bar),
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
maxLines = 1
|
||||
)
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = {
|
||||
if (navController?.navigateUp() != true) {
|
||||
activity?.onBackPressed()
|
||||
}
|
||||
}) {
|
||||
Icon(imageVector = Icons.Rounded.ArrowBack, contentDescription = "Back")
|
||||
}
|
||||
},
|
||||
)
|
||||
}) {
|
||||
|
||||
if (enabledItems == null) {
|
||||
return@Scaffold
|
||||
}
|
||||
|
||||
LazyDragAndDropColumn(
|
||||
state = listState,
|
||||
bidirectionalDrag = false,
|
||||
contentPadding = it,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
) {
|
||||
for (i in 0 until KeyboardFilterBarItem.entries.size) {
|
||||
val item = enabledItems!!.getOrNull(i) ?: disabledItems[i - enabledItems!!.size]
|
||||
val prevItem = enabledItems!!.getOrNull(i - 1) ?: disabledItems.getOrNull(i - enabledItems!!.size - 1)
|
||||
if (prevItem != null && prevItem.isCategory != item.isCategory) {
|
||||
item(key = "divider-$i") {
|
||||
HorizontalDivider()
|
||||
}
|
||||
}
|
||||
item(key = item) {
|
||||
DraggableItem(state = listState, key = item) {
|
||||
val elevation by animateDpAsState(if (it) 4.dp else 0.dp)
|
||||
Surface(
|
||||
shadowElevation = elevation,
|
||||
tonalElevation = elevation,
|
||||
modifier = Modifier.zIndex(if (it) 1f else 0f)
|
||||
) {
|
||||
SwitchPreference(
|
||||
title = item.getLabel(context),
|
||||
icon = item.icon,
|
||||
value = enabledItems!!.contains(item), onValueChanged = {
|
||||
if (it) {
|
||||
viewModel.addAction(item)
|
||||
} else {
|
||||
viewModel.removeAction(item)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package de.mm20.launcher2.ui.settings.filterbar
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import de.mm20.launcher2.preferences.KeyboardFilterBarItem
|
||||
import de.mm20.launcher2.preferences.search.SearchFilterSettings
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
class FilterBarSettingsScreenVM(
|
||||
) : ViewModel(), KoinComponent {
|
||||
private val searchFilterSettings: SearchFilterSettings by inject()
|
||||
|
||||
val filterBarItems = searchFilterSettings.filterBarItems
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
||||
|
||||
fun moveItem(item: KeyboardFilterBarItem, toItem: KeyboardFilterBarItem) {
|
||||
val items = filterBarItems.value?.toMutableList() ?: return
|
||||
val fromIndex = items.indexOf(item)
|
||||
val toIndex = items.indexOf(toItem)
|
||||
if (fromIndex > items.lastIndex) return
|
||||
if (toIndex > items.lastIndex) return
|
||||
if (fromIndex != -1) items.removeAt(fromIndex)
|
||||
if (toIndex != -1) items.add(toIndex, item)
|
||||
searchFilterSettings.setFilterBarItems(items)
|
||||
}
|
||||
|
||||
fun addAction(item: KeyboardFilterBarItem) {
|
||||
val items = filterBarItems.value?.toMutableList() ?: return
|
||||
items.add(item)
|
||||
searchFilterSettings.setFilterBarItems(items)
|
||||
}
|
||||
|
||||
fun removeAction(item: KeyboardFilterBarItem) {
|
||||
val items = filterBarItems.value?.toMutableList() ?: return
|
||||
items.remove(item)
|
||||
searchFilterSettings.setFilterBarItems(items)
|
||||
}
|
||||
}
|
||||
@ -290,6 +290,15 @@ fun SearchSettingsScreen() {
|
||||
viewModel.setFilterBar(it)
|
||||
}
|
||||
)
|
||||
AnimatedVisibility(filterBar == true) {
|
||||
Preference(
|
||||
title = stringResource(R.string.preference_customize_filter_bar),
|
||||
summary = stringResource(R.string.preference_customize_filter_bar_summary),
|
||||
onClick = {
|
||||
navController?.navigate("settings/search/filterbar")
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasWorkProfile) {
|
||||
|
||||
@ -922,5 +922,7 @@
|
||||
<string name="preference_default_filter_summary">Customize the default filter for searches</string>
|
||||
<string name="preference_filter_bar">Show filter bar</string>
|
||||
<string name="preference_filter_bar_summary">Show quick filters above the keyboard</string>
|
||||
<string name="preference_customize_filter_bar">Customize filter bar</string>
|
||||
<string name="preference_customize_filter_bar_summary">Customize which items are included in the filter bar</string>
|
||||
<string name="filter_settings_network_warning">The current filter enables online results by default. Your search queries might unintentionally be sent to external web services. For privacy reasons, this is not recommended.</string>
|
||||
</resources>
|
||||
@ -154,7 +154,6 @@ data class LauncherSettingsData internal constructor(
|
||||
KeyboardFilterBarItem.Events,
|
||||
KeyboardFilterBarItem.Contacts,
|
||||
KeyboardFilterBarItem.Files,
|
||||
KeyboardFilterBarItem.Places,
|
||||
KeyboardFilterBarItem.Articles,
|
||||
KeyboardFilterBarItem.Websites,
|
||||
KeyboardFilterBarItem.Places,
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package de.mm20.launcher2.preferences.search
|
||||
|
||||
import de.mm20.launcher2.preferences.KeyboardFilterBarItem
|
||||
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||
import de.mm20.launcher2.search.SearchFilters
|
||||
import kotlinx.coroutines.flow.map
|
||||
@ -25,4 +26,12 @@ class SearchFilterSettings internal constructor(
|
||||
}
|
||||
}
|
||||
|
||||
val filterBarItems
|
||||
get() = launcherDataStore.data.map { it.searchFilterBarItems.distinct() }
|
||||
|
||||
fun setFilterBarItems(items: List<KeyboardFilterBarItem>) {
|
||||
launcherDataStore.update {
|
||||
it.copy(searchFilterBarItems = items)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user