Add search-only visibility level to items
This commit is contained in:
@@ -8,6 +8,7 @@ import de.mm20.launcher2.preferences.search.FavoritesSettings
|
||||
import de.mm20.launcher2.preferences.search.FavoritesSettingsData
|
||||
import de.mm20.launcher2.search.SavableSearchable
|
||||
import de.mm20.launcher2.search.data.Tag
|
||||
import de.mm20.launcher2.searchable.PinnedLevel
|
||||
import de.mm20.launcher2.services.favorites.FavoritesService
|
||||
import de.mm20.launcher2.widgets.CalendarWidget
|
||||
import de.mm20.launcher2.widgets.WidgetRepository
|
||||
@@ -29,8 +30,7 @@ abstract class FavoritesVM : ViewModel(), KoinComponent {
|
||||
|
||||
val pinnedTags = favoritesService.getFavorites(
|
||||
includeTypes = listOf("tag"),
|
||||
manuallySorted = true,
|
||||
automaticallySorted = true,
|
||||
minPinnedLevel = PinnedLevel.AutomaticallySorted,
|
||||
).map {
|
||||
it.filterIsInstance<Tag>()
|
||||
}
|
||||
@@ -52,15 +52,15 @@ abstract class FavoritesVM : ViewModel(), KoinComponent {
|
||||
|
||||
val pinned = favoritesService.getFavorites(
|
||||
excludeTypes = if (excludeCalendar) listOf("calendar", "tag") else listOf("tag"),
|
||||
manuallySorted = true,
|
||||
automaticallySorted = true,
|
||||
minPinnedLevel = PinnedLevel.AutomaticallySorted,
|
||||
limit = 10 * columns,
|
||||
)
|
||||
if (includeFrequentlyUsed) {
|
||||
emitAll(pinned.flatMapLatest { pinned ->
|
||||
favoritesService.getFavorites(
|
||||
excludeTypes = if (excludeCalendar) listOf("calendar", "tag") else listOf("tag"),
|
||||
frequentlyUsed = true,
|
||||
maxPinnedLevel = PinnedLevel.FrequentlyUsed,
|
||||
minPinnedLevel = PinnedLevel.FrequentlyUsed,
|
||||
limit = frequentlyUsedRows * columns - pinned.size % columns,
|
||||
).map {
|
||||
pinned + it
|
||||
|
||||
@@ -4,11 +4,14 @@ import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.requiredHeight
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
@@ -28,7 +31,6 @@ import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextFieldDefaults
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextFieldDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -58,9 +60,11 @@ fun OutlinedTagsInputField(
|
||||
modifier: Modifier = Modifier,
|
||||
tags: List<String>,
|
||||
onTagsChange: (tags: List<String>) -> Unit,
|
||||
label: @Composable (() -> Unit)? = null,
|
||||
placeholder: @Composable (() -> Unit)? = null,
|
||||
leadingIcon: @Composable (() -> Unit)? = null,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
textStyle: TextStyle = MaterialTheme.typography.bodyLarge,
|
||||
textStyle: TextStyle = LocalTextStyle.current,
|
||||
textColor: Color = LocalContentColor.current,
|
||||
onAutocomplete: (suspend (query: String) -> List<String>)? = null
|
||||
) {
|
||||
@@ -127,14 +131,23 @@ fun OutlinedTagsInputField(
|
||||
}),
|
||||
decorationBox = { innerTextField ->
|
||||
OutlinedTextFieldDefaults.DecorationBox(
|
||||
contentPadding = PaddingValues(0.dp),
|
||||
value = value,
|
||||
contentPadding = PaddingValues(
|
||||
start = 16.dp,
|
||||
end = 0.dp,
|
||||
top = 12.dp,
|
||||
bottom = 12.dp
|
||||
),
|
||||
value = tags.joinToString() + value,
|
||||
label = label,
|
||||
leadingIcon = leadingIcon,
|
||||
innerTextField = {
|
||||
Box {
|
||||
Box(
|
||||
contentAlignment = Alignment.CenterStart,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.horizontalScroll(rememberScrollState())
|
||||
.padding(horizontal = 16.dp),
|
||||
.requiredHeight(32.dp)
|
||||
.horizontalScroll(rememberScrollState()),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
for ((i, tag) in tags.withIndex()) {
|
||||
|
||||
@@ -32,6 +32,7 @@ import de.mm20.launcher2.search.Website
|
||||
import de.mm20.launcher2.search.data.Calculator
|
||||
import de.mm20.launcher2.search.data.UnitConverter
|
||||
import de.mm20.launcher2.searchable.SavableSearchableRepository
|
||||
import de.mm20.launcher2.searchable.VisibilityLevel
|
||||
import de.mm20.launcher2.searchactions.actions.SearchAction
|
||||
import de.mm20.launcher2.services.favorites.FavoritesService
|
||||
import kotlinx.coroutines.CancellationException
|
||||
@@ -102,13 +103,6 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
|
||||
val separateWorkProfile = searchUiSettings.separateWorkProfile
|
||||
|
||||
private val hiddenItemKeys = searchableRepository
|
||||
.getKeys(
|
||||
hidden = true,
|
||||
limit = 9999,
|
||||
)
|
||||
.shareIn(viewModelScope, SharingStarted.Eagerly, replay = 1)
|
||||
|
||||
val bestMatch = mutableStateOf<Searchable?>(null)
|
||||
|
||||
init {
|
||||
@@ -251,6 +245,10 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
}
|
||||
}
|
||||
|
||||
val hiddenItemKeys = searchableRepository.getKeys(
|
||||
maxVisibility = if (query.isEmpty()) VisibilityLevel.SearchOnly else VisibilityLevel.Hidden,
|
||||
)
|
||||
|
||||
hiddenItemKeys.collectLatest { hiddenKeys ->
|
||||
val hidden = mutableListOf<SavableSearchable>()
|
||||
val apps = mutableListOf<Application>()
|
||||
|
||||
@@ -379,38 +379,6 @@ fun AppItem(
|
||||
)
|
||||
}
|
||||
|
||||
val isHidden by viewModel.isHidden.collectAsState(false)
|
||||
val hideAction = if (isHidden) {
|
||||
DefaultToolbarAction(
|
||||
label = stringResource(R.string.menu_unhide),
|
||||
icon = Icons.Rounded.Visibility,
|
||||
action = {
|
||||
viewModel.unhide()
|
||||
onBack()
|
||||
}
|
||||
)
|
||||
} else {
|
||||
DefaultToolbarAction(
|
||||
label = stringResource(R.string.menu_hide),
|
||||
icon = Icons.Rounded.VisibilityOff,
|
||||
action = {
|
||||
viewModel.hide()
|
||||
onBack()
|
||||
lifecycleOwner.lifecycleScope.launch {
|
||||
val result = snackbarHostState.showSnackbar(
|
||||
message = context.getString(R.string.msg_item_hidden, app.label),
|
||||
actionLabel = context.getString(R.string.action_undo),
|
||||
duration = SnackbarDuration.Short,
|
||||
)
|
||||
if (result == SnackbarResult.ActionPerformed) {
|
||||
viewModel.unhide()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
toolbarActions.add(hideAction)
|
||||
|
||||
Toolbar(
|
||||
leftActions = listOf(
|
||||
DefaultToolbarAction(
|
||||
|
||||
@@ -221,39 +221,6 @@ fun CalendarItem(
|
||||
toolbarActions.add(favAction)
|
||||
}
|
||||
|
||||
val isHidden by viewModel.isHidden.collectAsState(false)
|
||||
val hideAction = if (isHidden) {
|
||||
DefaultToolbarAction(
|
||||
label = stringResource(R.string.menu_unhide),
|
||||
icon = Icons.Rounded.Visibility,
|
||||
action = {
|
||||
viewModel.unhide()
|
||||
onBack()
|
||||
}
|
||||
)
|
||||
} else {
|
||||
DefaultToolbarAction(
|
||||
label = stringResource(R.string.menu_hide),
|
||||
icon = Icons.Rounded.VisibilityOff,
|
||||
action = {
|
||||
viewModel.hide()
|
||||
onBack()
|
||||
lifecycleOwner.lifecycleScope.launch {
|
||||
val result = snackbarHostState.showSnackbar(
|
||||
message = context.getString(
|
||||
R.string.msg_item_hidden,
|
||||
calendar.label
|
||||
),
|
||||
actionLabel = context.getString(R.string.action_undo),
|
||||
duration = SnackbarDuration.Short,
|
||||
)
|
||||
if (result == SnackbarResult.ActionPerformed) {
|
||||
viewModel.unhide()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
toolbarActions.add(
|
||||
DefaultToolbarAction(
|
||||
label = stringResource(R.string.menu_calendar_open_externally),
|
||||
@@ -272,8 +239,6 @@ fun CalendarItem(
|
||||
action = { sheetManager.showCustomizeSearchableModal(calendar) }
|
||||
))
|
||||
|
||||
toolbarActions.add(hideAction)
|
||||
|
||||
Toolbar(
|
||||
leftActions = listOf(
|
||||
DefaultToolbarAction(
|
||||
|
||||
@@ -78,18 +78,6 @@ class SearchableItemVM : ListItemViewModel(), KoinComponent {
|
||||
searchable.value?.let { favoritesService.unpinItem(it) }
|
||||
}
|
||||
|
||||
val isHidden = searchable.flatMapLatest {
|
||||
if (it == null) emptyFlow() else favoritesService.isHidden(it)
|
||||
}
|
||||
|
||||
fun hide() {
|
||||
searchable.value?.let { favoritesService.hideItem(it) }
|
||||
}
|
||||
|
||||
fun unhide() {
|
||||
searchable.value?.let { favoritesService.unhideItem(it) }
|
||||
}
|
||||
|
||||
val badge = searchable.flatMapLatest {
|
||||
if (it == null) emptyFlow() else badgeService.getBadge(it)
|
||||
}.stateIn(viewModelScope, SharingStarted.Lazily, null)
|
||||
|
||||
@@ -205,39 +205,6 @@ fun ContactItem(
|
||||
toolbarActions.add(favAction)
|
||||
}
|
||||
|
||||
val isHidden by viewModel.isHidden.collectAsState(false)
|
||||
val hideAction = if (isHidden) {
|
||||
DefaultToolbarAction(
|
||||
label = stringResource(R.string.menu_unhide),
|
||||
icon = Icons.Rounded.Visibility,
|
||||
action = {
|
||||
viewModel.unhide()
|
||||
onBack()
|
||||
}
|
||||
)
|
||||
} else {
|
||||
DefaultToolbarAction(
|
||||
label = stringResource(R.string.menu_hide),
|
||||
icon = Icons.Rounded.VisibilityOff,
|
||||
action = {
|
||||
viewModel.hide()
|
||||
onBack()
|
||||
lifecycleOwner.lifecycleScope.launch {
|
||||
val result = snackbarHostState.showSnackbar(
|
||||
message = context.getString(
|
||||
R.string.msg_item_hidden,
|
||||
contact.label
|
||||
),
|
||||
actionLabel = context.getString(R.string.action_undo),
|
||||
duration = SnackbarDuration.Short,
|
||||
)
|
||||
if (result == SnackbarResult.ActionPerformed) {
|
||||
viewModel.unhide()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
toolbarActions.add(
|
||||
DefaultToolbarAction(
|
||||
label = stringResource(R.string.menu_contacts_open_externally),
|
||||
@@ -255,7 +222,6 @@ fun ContactItem(
|
||||
action = { sheetManager.showCustomizeSearchableModal(contact) }
|
||||
))
|
||||
|
||||
toolbarActions.add(hideAction)
|
||||
|
||||
Toolbar(
|
||||
leftActions = listOf(
|
||||
|
||||
@@ -257,41 +257,6 @@ fun FileItem(
|
||||
action = { sheetManager.showCustomizeSearchableModal(file) }
|
||||
))
|
||||
|
||||
val isHidden by viewModel.isHidden.collectAsState(false)
|
||||
val hideAction = if (isHidden) {
|
||||
DefaultToolbarAction(
|
||||
label = stringResource(R.string.menu_unhide),
|
||||
icon = Icons.Rounded.Visibility,
|
||||
action = {
|
||||
viewModel.unhide()
|
||||
onBack()
|
||||
}
|
||||
)
|
||||
} else {
|
||||
DefaultToolbarAction(
|
||||
label = stringResource(R.string.menu_hide),
|
||||
icon = Icons.Rounded.VisibilityOff,
|
||||
action = {
|
||||
viewModel.hide()
|
||||
onBack()
|
||||
lifecycleOwner.lifecycleScope.launch {
|
||||
val result = snackbarHostState.showSnackbar(
|
||||
message = context.getString(
|
||||
R.string.msg_item_hidden,
|
||||
file.label
|
||||
),
|
||||
actionLabel = context.getString(R.string.action_undo),
|
||||
duration = SnackbarDuration.Short,
|
||||
)
|
||||
if (result == SnackbarResult.ActionPerformed) {
|
||||
viewModel.unhide()
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
toolbarActions.add(hideAction)
|
||||
|
||||
Toolbar(
|
||||
leftActions = listOf(
|
||||
DefaultToolbarAction(
|
||||
|
||||
@@ -775,41 +775,6 @@ fun LocationItem(
|
||||
}
|
||||
}
|
||||
|
||||
val isHidden by viewModel.isHidden.collectAsState(false)
|
||||
val hideAction = if (isHidden) {
|
||||
DefaultToolbarAction(
|
||||
label = stringResource(R.string.menu_unhide),
|
||||
icon = Icons.Rounded.Visibility,
|
||||
action = {
|
||||
viewModel.unhide()
|
||||
onBack()
|
||||
}
|
||||
)
|
||||
} else {
|
||||
DefaultToolbarAction(
|
||||
label = stringResource(R.string.menu_hide),
|
||||
icon = Icons.Rounded.VisibilityOff,
|
||||
action = {
|
||||
viewModel.hide()
|
||||
onBack()
|
||||
lifecycleOwner.lifecycleScope.launch {
|
||||
val result = snackbarHostState.showSnackbar(
|
||||
message = context.getString(
|
||||
R.string.msg_item_hidden,
|
||||
location.labelOverride ?: location.label
|
||||
),
|
||||
actionLabel = context.getString(R.string.action_undo),
|
||||
duration = SnackbarDuration.Short,
|
||||
)
|
||||
if (result == SnackbarResult.ActionPerformed) {
|
||||
viewModel.unhide()
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
toolbarActions.add(hideAction)
|
||||
|
||||
Toolbar(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
leftActions = listOf(DefaultToolbarAction(
|
||||
|
||||
@@ -218,41 +218,6 @@ fun AppShortcutItem(
|
||||
))
|
||||
}
|
||||
|
||||
val isHidden by viewModel.isHidden.collectAsState(false)
|
||||
val hideAction = if (isHidden) {
|
||||
DefaultToolbarAction(
|
||||
label = stringResource(R.string.menu_unhide),
|
||||
icon = Icons.Rounded.Visibility,
|
||||
action = {
|
||||
viewModel.unhide()
|
||||
onBack()
|
||||
}
|
||||
)
|
||||
} else {
|
||||
DefaultToolbarAction(
|
||||
label = stringResource(R.string.menu_hide),
|
||||
icon = Icons.Rounded.VisibilityOff,
|
||||
action = {
|
||||
viewModel.hide()
|
||||
onBack()
|
||||
|
||||
lifecycleOwner.lifecycleScope.launch {
|
||||
val result = snackbarHostState.showSnackbar(
|
||||
message = context.getString(
|
||||
R.string.msg_item_hidden,
|
||||
shortcut.label
|
||||
),
|
||||
actionLabel = context.getString(R.string.action_undo),
|
||||
duration = SnackbarDuration.Short,
|
||||
)
|
||||
if (result == SnackbarResult.ActionPerformed) {
|
||||
viewModel.unhide()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
toolbarActions.add(hideAction)
|
||||
|
||||
Toolbar(
|
||||
leftActions = listOf(
|
||||
DefaultToolbarAction(
|
||||
|
||||
+158
-14
@@ -1,9 +1,7 @@
|
||||
package de.mm20.launcher2.ui.launcher.sheets
|
||||
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.drawable.InsetDrawable
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
@@ -19,17 +17,25 @@ import androidx.compose.foundation.lazy.grid.GridItemSpan
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
import androidx.compose.foundation.lazy.grid.items
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.rounded.Label
|
||||
import androidx.compose.material.icons.outlined.Visibility
|
||||
import androidx.compose.material.icons.rounded.ArrowDropDown
|
||||
import androidx.compose.material.icons.rounded.Edit
|
||||
import androidx.compose.material.icons.rounded.FilterAlt
|
||||
import androidx.compose.material.icons.rounded.Search
|
||||
import androidx.compose.material.icons.rounded.Tag
|
||||
import androidx.compose.material.icons.rounded.Visibility
|
||||
import androidx.compose.material.icons.rounded.VisibilityOff
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.ExposedDropdownMenuBox
|
||||
import androidx.compose.material3.ExposedDropdownMenuDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.MenuAnchorType
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Text
|
||||
@@ -44,7 +50,6 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
@@ -55,7 +60,10 @@ import de.mm20.launcher2.badges.Badge
|
||||
import de.mm20.launcher2.badges.BadgeIcon
|
||||
import de.mm20.launcher2.icons.CustomIconWithPreview
|
||||
import de.mm20.launcher2.icons.IconPack
|
||||
import de.mm20.launcher2.search.Application
|
||||
import de.mm20.launcher2.search.CalendarEvent
|
||||
import de.mm20.launcher2.search.SavableSearchable
|
||||
import de.mm20.launcher2.searchable.VisibilityLevel
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.component.BottomSheetDialog
|
||||
import de.mm20.launcher2.ui.component.OutlinedTagsInputField
|
||||
@@ -84,9 +92,11 @@ fun CustomizeSearchableSheet(
|
||||
|
||||
BottomSheetDialog(
|
||||
onDismissRequest = onDismiss,
|
||||
title = {
|
||||
Text(stringResource(if (pickIcon) R.string.icon_picker_title else R.string.menu_customize))
|
||||
},
|
||||
title = if (pickIcon) {
|
||||
{
|
||||
Text(stringResource(R.string.icon_picker_title))
|
||||
}
|
||||
} else null,
|
||||
dismissible = { !pickIcon },
|
||||
confirmButton = if (pickIcon) {
|
||||
{
|
||||
@@ -126,44 +136,178 @@ fun CustomizeSearchableSheet(
|
||||
mutableStateOf(searchable.labelOverride ?: "")
|
||||
}
|
||||
OutlinedTextField(
|
||||
modifier =
|
||||
Modifier
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 24.dp),
|
||||
.padding(top = 24.dp, bottom = 16.dp),
|
||||
value = customLabelValue,
|
||||
onValueChange = {
|
||||
customLabelValue = it
|
||||
},
|
||||
singleLine = true,
|
||||
label = {
|
||||
Text(stringResource(R.string.customize_item_label))
|
||||
},
|
||||
placeholder = {
|
||||
Text(searchable.label)
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(Icons.AutoMirrored.Rounded.Label, null)
|
||||
}
|
||||
)
|
||||
|
||||
var tags by remember { mutableStateOf(emptyList<String>()) }
|
||||
var visibility by remember { mutableStateOf(VisibilityLevel.Default) }
|
||||
|
||||
LaunchedEffect(searchable.key) {
|
||||
visibility = viewModel.getVisibility().first()
|
||||
tags = viewModel.getTags().first()
|
||||
}
|
||||
|
||||
OutlinedTagsInputField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 16.dp),
|
||||
.padding(top = 8.dp)
|
||||
.fillMaxWidth(),
|
||||
tags = tags, onTagsChange = { tags = it.distinct() },
|
||||
placeholder = {
|
||||
Text(stringResource(R.string.customize_tags_placeholder))
|
||||
label = {
|
||||
Text(stringResource(R.string.customize_item_tags))
|
||||
},
|
||||
textStyle = MaterialTheme.typography.bodyMedium,
|
||||
onAutocomplete = {
|
||||
viewModel.autocompleteTags(it).minus(tags.toSet())
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(Icons.Rounded.Tag, null)
|
||||
}
|
||||
)
|
||||
|
||||
var showDropdown by remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
|
||||
ExposedDropdownMenuBox(
|
||||
expanded = showDropdown,
|
||||
onExpandedChange = { showDropdown = it },
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 16.dp),
|
||||
) {
|
||||
OutlinedTextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.menuAnchor(MenuAnchorType.PrimaryNotEditable),
|
||||
value = when (visibility) {
|
||||
VisibilityLevel.Default -> {
|
||||
when (searchable) {
|
||||
is Application -> stringResource(R.string.item_visibility_app_default)
|
||||
is CalendarEvent -> stringResource(R.string.item_visibility_calendar_default)
|
||||
else -> stringResource(R.string.item_visibility_search_only)
|
||||
}
|
||||
}
|
||||
|
||||
VisibilityLevel.SearchOnly -> stringResource(R.string.item_visibility_search_only)
|
||||
VisibilityLevel.Hidden -> stringResource(R.string.item_visibility_hidden)
|
||||
},
|
||||
label = {
|
||||
Text(stringResource(R.string.customize_item_visibility))
|
||||
},
|
||||
onValueChange = {},
|
||||
readOnly = true,
|
||||
singleLine = true,
|
||||
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = showDropdown) },
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
when (visibility) {
|
||||
VisibilityLevel.Default -> Icons.Rounded.Visibility
|
||||
VisibilityLevel.SearchOnly -> Icons.Outlined.Visibility
|
||||
VisibilityLevel.Hidden -> Icons.Rounded.VisibilityOff
|
||||
},
|
||||
null
|
||||
)
|
||||
},
|
||||
colors = ExposedDropdownMenuDefaults.outlinedTextFieldColors(),
|
||||
)
|
||||
ExposedDropdownMenu(
|
||||
expanded = showDropdown,
|
||||
onDismissRequest = {
|
||||
showDropdown = false
|
||||
}
|
||||
) {
|
||||
if (searchable is Application) {
|
||||
DropdownMenuItem(
|
||||
onClick = {
|
||||
visibility = VisibilityLevel.Default
|
||||
showDropdown = false
|
||||
},
|
||||
text = {
|
||||
Text(stringResource(R.string.item_visibility_app_default))
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(Icons.Rounded.Visibility, null)
|
||||
}
|
||||
)
|
||||
} else if (searchable is CalendarEvent) {
|
||||
DropdownMenuItem(
|
||||
onClick = {
|
||||
visibility = VisibilityLevel.Default
|
||||
showDropdown = false
|
||||
},
|
||||
text = {
|
||||
Text(stringResource(R.string.item_visibility_app_default))
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(Icons.Rounded.Visibility, null)
|
||||
}
|
||||
)
|
||||
} else {
|
||||
DropdownMenuItem(
|
||||
onClick = {
|
||||
visibility = VisibilityLevel.Default
|
||||
showDropdown = false
|
||||
},
|
||||
text = {
|
||||
Text(stringResource(R.string.item_visibility_search_only))
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(Icons.Rounded.Visibility, null)
|
||||
}
|
||||
)
|
||||
}
|
||||
if (searchable is Application || searchable is CalendarEvent) {
|
||||
DropdownMenuItem(
|
||||
onClick = {
|
||||
visibility = VisibilityLevel.SearchOnly
|
||||
showDropdown = false
|
||||
},
|
||||
text = {
|
||||
Text(stringResource(R.string.item_visibility_search_only))
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
Icons.Outlined.Visibility,
|
||||
null
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
DropdownMenuItem(
|
||||
onClick = {
|
||||
visibility = VisibilityLevel.Hidden
|
||||
showDropdown = false
|
||||
},
|
||||
text = {
|
||||
Text(stringResource(R.string.item_visibility_hidden))
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(Icons.Rounded.VisibilityOff, null)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
DisposableEffect(searchable.key) {
|
||||
onDispose {
|
||||
viewModel.setCustomLabel(customLabelValue)
|
||||
viewModel.setTags(tags)
|
||||
viewModel.setVisibility(visibility)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
@@ -8,6 +8,8 @@ import de.mm20.launcher2.icons.IconPack
|
||||
import de.mm20.launcher2.icons.IconService
|
||||
import de.mm20.launcher2.icons.LauncherIcon
|
||||
import de.mm20.launcher2.search.SavableSearchable
|
||||
import de.mm20.launcher2.searchable.VisibilityLevel
|
||||
import de.mm20.launcher2.services.favorites.FavoritesService
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.cancelAndJoin
|
||||
import kotlinx.coroutines.delay
|
||||
@@ -25,6 +27,7 @@ class CustomizeSearchableSheetVM(
|
||||
) : KoinComponent {
|
||||
private val iconService: IconService by inject()
|
||||
private val customAttributesRepository: CustomAttributesRepository by inject()
|
||||
private val favoritesService: FavoritesService by inject()
|
||||
|
||||
val isIconPickerOpen = mutableStateOf(false)
|
||||
|
||||
@@ -89,10 +92,18 @@ class CustomizeSearchableSheetVM(
|
||||
customAttributesRepository.setTags(searchable, tags)
|
||||
}
|
||||
|
||||
fun setVisibility(visibility: VisibilityLevel) {
|
||||
favoritesService.setVisibility(searchable, visibility)
|
||||
}
|
||||
|
||||
fun getTags(): Flow<List<String>> {
|
||||
return customAttributesRepository.getTags(searchable)
|
||||
}
|
||||
|
||||
fun getVisibility(): Flow<VisibilityLevel> {
|
||||
return favoritesService.getVisibility(searchable)
|
||||
}
|
||||
|
||||
suspend fun autocompleteTags(query: String): List<String> {
|
||||
return customAttributesRepository.getAllTags(startsWith = query).first()
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import de.mm20.launcher2.appshortcuts.AppShortcut
|
||||
import de.mm20.launcher2.preferences.search.FavoritesSettings
|
||||
import de.mm20.launcher2.search.Searchable
|
||||
import de.mm20.launcher2.search.data.Tag
|
||||
import de.mm20.launcher2.searchable.PinnedLevel
|
||||
import de.mm20.launcher2.services.favorites.FavoritesService
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
@@ -60,21 +61,22 @@ class EditFavoritesSheetVM : ViewModel(), KoinComponent {
|
||||
loading.value = showLoadingIndicator
|
||||
manuallySorted = mutableListOf()
|
||||
manuallySorted = favoritesService.getFavorites(
|
||||
manuallySorted = true,
|
||||
minPinnedLevel = PinnedLevel.AutomaticallySorted,
|
||||
excludeTypes = listOf("tag"),
|
||||
).first().toMutableList()
|
||||
automaticallySorted = favoritesService.getFavorites(
|
||||
automaticallySorted = true,
|
||||
minPinnedLevel = PinnedLevel.AutomaticallySorted,
|
||||
maxPinnedLevel = PinnedLevel.AutomaticallySorted,
|
||||
excludeTypes = listOf("tag"),
|
||||
).first().toMutableList()
|
||||
frequentlyUsed = favoritesService.getFavorites(
|
||||
frequentlyUsed = true,
|
||||
minPinnedLevel = PinnedLevel.FrequentlyUsed,
|
||||
maxPinnedLevel = PinnedLevel.FrequentlyUsed,
|
||||
excludeTypes = listOf("tag"),
|
||||
).first().toMutableList()
|
||||
val pinnedTags = favoritesService.getFavorites(
|
||||
includeTypes = listOf("tag"),
|
||||
manuallySorted = true,
|
||||
automaticallySorted = true,
|
||||
minPinnedLevel = PinnedLevel.AutomaticallySorted,
|
||||
).first().filterIsInstance<Tag>().toMutableList()
|
||||
availableTags.value =
|
||||
customAttributesRepository
|
||||
@@ -296,7 +298,8 @@ class EditFavoritesSheetVM : ViewModel(), KoinComponent {
|
||||
favoritesService.unpinItem(item.item)
|
||||
viewModelScope.launch {
|
||||
frequentlyUsed = favoritesService.getFavorites(
|
||||
frequentlyUsed = true,
|
||||
minPinnedLevel = PinnedLevel.FrequentlyUsed,
|
||||
maxPinnedLevel = PinnedLevel.FrequentlyUsed,
|
||||
excludeTypes = listOf("tag"),
|
||||
).first().toMutableList()
|
||||
buildItemList()
|
||||
|
||||
+4
-3
@@ -14,6 +14,8 @@ import de.mm20.launcher2.ktx.tryStartActivity
|
||||
import de.mm20.launcher2.permissions.PermissionGroup
|
||||
import de.mm20.launcher2.permissions.PermissionsManager
|
||||
import de.mm20.launcher2.search.CalendarEvent
|
||||
import de.mm20.launcher2.searchable.PinnedLevel
|
||||
import de.mm20.launcher2.searchable.VisibilityLevel
|
||||
import de.mm20.launcher2.services.favorites.FavoritesService
|
||||
import de.mm20.launcher2.widgets.CalendarWidget
|
||||
import de.mm20.launcher2.widgets.CalendarWidgetConfig
|
||||
@@ -42,8 +44,7 @@ class CalendarWidgetVM : ViewModel(), KoinComponent {
|
||||
val pinnedCalendarEvents =
|
||||
favoritesService.getFavorites(
|
||||
includeTypes = listOf("calendar"),
|
||||
automaticallySorted = true,
|
||||
manuallySorted = true,
|
||||
minPinnedLevel = PinnedLevel.AutomaticallySorted,
|
||||
).stateIn(viewModelScope, SharingStarted.WhileSubscribed(), emptyList())
|
||||
val nextEvents = mutableStateOf<List<CalendarEvent>>(emptyList())
|
||||
var availableDates = listOf(LocalDate.now())
|
||||
@@ -172,7 +173,7 @@ class CalendarWidgetVM : ViewModel(), KoinComponent {
|
||||
).collectLatest { events ->
|
||||
searchableRepository.getKeys(
|
||||
includeTypes = listOf("calendar"),
|
||||
hidden = true,
|
||||
maxVisibility = VisibilityLevel.SearchOnly,
|
||||
limit = 9999,
|
||||
).collectLatest { hidden ->
|
||||
upcomingEvents = events.filter { !hidden.contains(it.key) }
|
||||
|
||||
+2
-3
@@ -10,6 +10,7 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import de.mm20.launcher2.preferences.ui.UiSettings
|
||||
import de.mm20.launcher2.searchable.PinnedLevel
|
||||
import de.mm20.launcher2.services.favorites.FavoritesService
|
||||
import de.mm20.launcher2.ui.launcher.search.common.grid.SearchResultGrid
|
||||
import de.mm20.launcher2.widgets.CalendarWidget
|
||||
@@ -44,9 +45,7 @@ class FavoritesPartProvider : PartProvider, KoinComponent {
|
||||
val favorites by remember(columns, excludeCalendar) {
|
||||
favoritesService.getFavorites(
|
||||
excludeTypes = if (excludeCalendar) listOf("calendar", "tag") else listOf("tag"),
|
||||
manuallySorted = true,
|
||||
automaticallySorted = true,
|
||||
frequentlyUsed = true,
|
||||
minPinnedLevel = PinnedLevel.FrequentlyUsed,
|
||||
limit = columns
|
||||
)
|
||||
}.collectAsState(emptyList())
|
||||
|
||||
+161
-99
@@ -1,7 +1,7 @@
|
||||
package de.mm20.launcher2.ui.settings.hiddenitems
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
@@ -9,6 +9,8 @@ import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Visibility
|
||||
import androidx.compose.material.icons.rounded.Check
|
||||
import androidx.compose.material.icons.rounded.Visibility
|
||||
import androidx.compose.material.icons.rounded.VisibilityOff
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
@@ -25,13 +27,15 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.DpOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import de.mm20.launcher2.icons.LauncherIcon
|
||||
import de.mm20.launcher2.search.Application
|
||||
import de.mm20.launcher2.search.CalendarEvent
|
||||
import de.mm20.launcher2.search.SavableSearchable
|
||||
import de.mm20.launcher2.searchable.VisibilityLevel
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.component.ShapedLauncherIcon
|
||||
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
|
||||
@@ -42,7 +46,6 @@ import de.mm20.launcher2.ui.component.preferences.SwitchPreference
|
||||
fun HiddenItemsSettingsScreen() {
|
||||
val viewModel: HiddenItemsSettingsScreenVM = viewModel()
|
||||
|
||||
val context = LocalContext.current
|
||||
val density = LocalDensity.current
|
||||
|
||||
val apps by viewModel.allApps.collectAsState()
|
||||
@@ -66,63 +69,41 @@ fun HiddenItemsSettingsScreen() {
|
||||
viewModel.getIcon(searchable, with(density) { 32.dp.roundToPx() })
|
||||
}.collectAsState(null)
|
||||
|
||||
val isHidden by remember(searchable.key) {
|
||||
viewModel.isHidden(searchable)
|
||||
}.collectAsState(false)
|
||||
val visibility by remember(searchable.key) {
|
||||
viewModel.getVisibility(searchable)
|
||||
}.collectAsState(null)
|
||||
|
||||
var showPopup by remember(searchable.key) {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
var showDropdown by remember { mutableStateOf(false) }
|
||||
|
||||
Box {
|
||||
HiddenItem(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.combinedClickable(
|
||||
onClick = {
|
||||
viewModel.setHidden(searchable, !isHidden)
|
||||
},
|
||||
onLongClick = {
|
||||
showPopup = true
|
||||
.clickable {
|
||||
if (searchable is Application || searchable is CalendarEvent) {
|
||||
showDropdown = true
|
||||
} else {
|
||||
if (visibility == null) return@clickable
|
||||
viewModel.setVisibility(
|
||||
searchable,
|
||||
if (visibility == VisibilityLevel.Default) VisibilityLevel.Hidden else VisibilityLevel.Default
|
||||
)
|
||||
}
|
||||
),
|
||||
},
|
||||
icon = icon,
|
||||
label = searchable.label,
|
||||
isHidden = isHidden,
|
||||
visibility = visibility,
|
||||
)
|
||||
VisibilityDropdown(
|
||||
expanded = showDropdown,
|
||||
onDismissRequest = { showDropdown = false },
|
||||
item = searchable,
|
||||
value = visibility,
|
||||
onValueChanged = {
|
||||
viewModel.setVisibility(searchable, it)
|
||||
showDropdown = false
|
||||
}
|
||||
)
|
||||
|
||||
DropdownMenu(
|
||||
expanded = showPopup,
|
||||
onDismissRequest = { showPopup = false },
|
||||
offset = DpOffset(16.dp, 0.dp)
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.menu_launch)) },
|
||||
onClick = {
|
||||
viewModel.launch(context, searchable)
|
||||
showPopup = false
|
||||
})
|
||||
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.menu_app_info)) },
|
||||
onClick = {
|
||||
viewModel.openAppInfo(context, searchable)
|
||||
showPopup = false
|
||||
})
|
||||
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(
|
||||
stringResource(
|
||||
if (isHidden) R.string.menu_unhide else R.string.menu_hide
|
||||
)
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
viewModel.setHidden(searchable, !isHidden)
|
||||
showPopup = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,67 +123,141 @@ fun HiddenItemsSettingsScreen() {
|
||||
viewModel.getIcon(searchable, with(density) { 32.dp.roundToPx() })
|
||||
}.collectAsState(null)
|
||||
|
||||
val isHidden by remember(searchable.key) {
|
||||
viewModel.isHidden(searchable)
|
||||
}.collectAsState(false)
|
||||
val visibility by remember(searchable.key) {
|
||||
viewModel.getVisibility(searchable)
|
||||
}.collectAsState(null)
|
||||
|
||||
var showPopup by remember(searchable.key) {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
var showDropdown by remember { mutableStateOf(false) }
|
||||
|
||||
Box {
|
||||
HiddenItem(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.combinedClickable(
|
||||
onClick = {
|
||||
viewModel.setHidden(searchable, !isHidden)
|
||||
},
|
||||
onLongClick = {
|
||||
showPopup = true
|
||||
.clickable {
|
||||
if (searchable is Application || searchable is CalendarEvent) {
|
||||
showDropdown = true
|
||||
} else {
|
||||
if (visibility == null) return@clickable
|
||||
viewModel.setVisibility(
|
||||
searchable,
|
||||
if (visibility == VisibilityLevel.Default) VisibilityLevel.Hidden else VisibilityLevel.Default
|
||||
)
|
||||
}
|
||||
),
|
||||
},
|
||||
icon = icon,
|
||||
label = searchable.label,
|
||||
isHidden = isHidden,
|
||||
visibility = visibility,
|
||||
)
|
||||
VisibilityDropdown(
|
||||
expanded = showDropdown,
|
||||
onDismissRequest = { showDropdown = false },
|
||||
item = searchable,
|
||||
value = visibility,
|
||||
onValueChanged = {
|
||||
viewModel.setVisibility(searchable, it)
|
||||
showDropdown = false
|
||||
}
|
||||
)
|
||||
|
||||
DropdownMenu(
|
||||
expanded = showPopup,
|
||||
onDismissRequest = { showPopup = false },
|
||||
offset = DpOffset(16.dp, 0.dp)
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.menu_open_file)) },
|
||||
onClick = {
|
||||
viewModel.launch(context, searchable)
|
||||
showPopup = false
|
||||
})
|
||||
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(
|
||||
stringResource(
|
||||
if (isHidden) R.string.menu_unhide else R.string.menu_hide
|
||||
)
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
viewModel.setHidden(searchable, !isHidden)
|
||||
showPopup = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun HiddenItem(
|
||||
private fun VisibilityDropdown(
|
||||
expanded: Boolean,
|
||||
onDismissRequest: () -> Unit,
|
||||
item: SavableSearchable,
|
||||
value: VisibilityLevel?,
|
||||
onValueChanged: (VisibilityLevel) -> Unit,
|
||||
) {
|
||||
DropdownMenu(expanded = expanded, onDismissRequest = onDismissRequest) {
|
||||
DropdownMenuItem(
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Visibility,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
text = {
|
||||
Text(
|
||||
when (item) {
|
||||
is Application -> stringResource(R.string.item_visibility_app_default)
|
||||
is CalendarEvent -> stringResource(R.string.item_visibility_calendar_default)
|
||||
else -> stringResource(R.string.item_visibility_search_only)
|
||||
}
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
onValueChanged(VisibilityLevel.Default)
|
||||
},
|
||||
trailingIcon = {
|
||||
if (value == VisibilityLevel.Default) {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Check,
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
if (item is Application || item is CalendarEvent) {
|
||||
DropdownMenuItem(
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Visibility,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
text = {
|
||||
Text(stringResource(R.string.item_visibility_search_only))
|
||||
},
|
||||
onClick = {
|
||||
onValueChanged(VisibilityLevel.SearchOnly)
|
||||
},
|
||||
trailingIcon = {
|
||||
if (value == VisibilityLevel.SearchOnly) {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Check,
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
DropdownMenuItem(
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.VisibilityOff,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
text = {
|
||||
Text(stringResource(R.string.item_visibility_hidden))
|
||||
},
|
||||
onClick = {
|
||||
onValueChanged(VisibilityLevel.Hidden)
|
||||
},
|
||||
trailingIcon = {
|
||||
if (value == VisibilityLevel.Hidden) {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Check,
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun HiddenItem(
|
||||
modifier: Modifier,
|
||||
icon: LauncherIcon?,
|
||||
label: String,
|
||||
isHidden: Boolean,
|
||||
visibility: VisibilityLevel?,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
@@ -219,11 +274,18 @@ fun HiddenItem(
|
||||
modifier = Modifier.weight(1f, fill = true),
|
||||
style = MaterialTheme.typography.titleMedium
|
||||
)
|
||||
Icon(
|
||||
modifier = Modifier.alpha(if (isHidden) 0.3f else 1f),
|
||||
imageVector = if (isHidden) Icons.Rounded.VisibilityOff else Icons.Rounded.Visibility,
|
||||
tint = if (isHidden) MaterialTheme.colorScheme.onSurface else MaterialTheme.colorScheme.primary,
|
||||
contentDescription = null
|
||||
)
|
||||
if (visibility != null) {
|
||||
Icon(
|
||||
modifier = Modifier.alpha(if (visibility == VisibilityLevel.Hidden) 0.3f else 1f),
|
||||
imageVector = when (visibility) {
|
||||
VisibilityLevel.Hidden -> Icons.Rounded.VisibilityOff
|
||||
VisibilityLevel.Default -> Icons.Rounded.Visibility
|
||||
VisibilityLevel.SearchOnly -> Icons.Outlined.Visibility
|
||||
},
|
||||
tint = if (visibility == VisibilityLevel.Default) MaterialTheme.colorScheme.primary
|
||||
else MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-10
@@ -12,6 +12,7 @@ import de.mm20.launcher2.ktx.isAtLeastApiLevel
|
||||
import de.mm20.launcher2.preferences.ui.SearchUiSettings
|
||||
import de.mm20.launcher2.search.SavableSearchable
|
||||
import de.mm20.launcher2.search.Application
|
||||
import de.mm20.launcher2.searchable.VisibilityLevel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
@@ -20,7 +21,6 @@ import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
@@ -36,20 +36,18 @@ class HiddenItemsSettingsScreenVM : ViewModel(), KoinComponent {
|
||||
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), emptyList())
|
||||
val hiddenItems: StateFlow<List<SavableSearchable>> = flow {
|
||||
val hidden =
|
||||
searchableRepository.get(hidden = true).first().filter { it !is Application }.sorted()
|
||||
searchableRepository.get(
|
||||
maxVisibility = VisibilityLevel.SearchOnly,
|
||||
).first().filter { it !is Application }.sorted()
|
||||
emit(hidden)
|
||||
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), emptyList())
|
||||
|
||||
fun isHidden(searchable: SavableSearchable): Flow<Boolean> {
|
||||
return searchableRepository.isHidden(searchable)
|
||||
fun getVisibility(searchable: SavableSearchable): Flow<VisibilityLevel> {
|
||||
return searchableRepository.getVisibility(searchable)
|
||||
}
|
||||
|
||||
fun setHidden(searchable: SavableSearchable, hidden: Boolean) {
|
||||
if (hidden) {
|
||||
searchableRepository.upsert(searchable, hidden = true, pinned = false)
|
||||
} else {
|
||||
searchableRepository.update(searchable, hidden = false)
|
||||
}
|
||||
fun setVisibility(searchable: SavableSearchable, visibilityLevel: VisibilityLevel) {
|
||||
searchableRepository.upsert(searchable, visibilityLevel)
|
||||
}
|
||||
|
||||
fun getIcon(searchable: SavableSearchable, size: Int): Flow<LauncherIcon?> {
|
||||
|
||||
@@ -121,9 +121,6 @@ class IconsSettingsScreenVM(
|
||||
favoritesService.getFavorites(
|
||||
includeTypes = listOf("app"),
|
||||
limit = grid.columnCount,
|
||||
manuallySorted = true,
|
||||
automaticallySorted = true,
|
||||
frequentlyUsed = true,
|
||||
)
|
||||
}.shareIn(viewModelScope, started = SharingStarted.WhileSubscribed(), 1)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user