Hidden items sheet: only show items that match the current search query
This commit is contained in:
parent
5ae0ec42b7
commit
e318664b6e
@ -7,18 +7,19 @@ import android.os.Bundle
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.viewModels
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||
import androidx.compose.material3.SnackbarHost
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.blur
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsControllerCompat
|
||||
import androidx.lifecycle.Lifecycle
|
||||
@ -38,7 +39,6 @@ import de.mm20.launcher2.ui.base.ProvideSettings
|
||||
import de.mm20.launcher2.ui.component.NavBarEffects
|
||||
import de.mm20.launcher2.ui.ktx.animateTo
|
||||
import de.mm20.launcher2.ui.launcher.modals.EditFavoritesView
|
||||
import de.mm20.launcher2.ui.launcher.modals.HiddenItemsSheet
|
||||
import de.mm20.launcher2.ui.launcher.transitions.HomeTransitionManager
|
||||
import de.mm20.launcher2.ui.launcher.transitions.LocalHomeTransitionManager
|
||||
import de.mm20.launcher2.ui.locals.LocalSnackbarHostState
|
||||
@ -143,13 +143,6 @@ class LauncherActivity : BaseActivity() {
|
||||
.navigationBarsPadding()
|
||||
.imePadding()
|
||||
)
|
||||
|
||||
val showHiddenItems by viewModel.isHiddenItemsShown.observeAsState(false)
|
||||
if (showHiddenItems) {
|
||||
HiddenItemsSheet(onDismiss = {
|
||||
viewModel.hideHiddenItems()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,7 +13,6 @@ import org.koin.core.component.inject
|
||||
class LauncherActivityVM : ViewModel(), KoinComponent {
|
||||
private val dataStore: LauncherDataStore by inject()
|
||||
|
||||
val isHiddenItemsShown = MutableLiveData(false)
|
||||
val isEditFavoritesShown = MutableLiveData(false)
|
||||
|
||||
private var isDarkInMode = MutableStateFlow(false)
|
||||
@ -55,13 +54,5 @@ class LauncherActivityVM : ViewModel(), KoinComponent {
|
||||
isEditFavoritesShown.value = false
|
||||
}
|
||||
|
||||
fun showHiddenItems() {
|
||||
isHiddenItemsShown.value = true
|
||||
}
|
||||
|
||||
fun hideHiddenItems() {
|
||||
isHiddenItemsShown.value = false
|
||||
}
|
||||
|
||||
val layout = dataStore.data.map { it.appearance.layout }.asLiveData()
|
||||
}
|
||||
@ -22,12 +22,14 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.component.BottomSheetDialog
|
||||
import de.mm20.launcher2.ui.launcher.search.common.grid.SearchResultGrid
|
||||
|
||||
@Composable
|
||||
fun HiddenItemsSheet(
|
||||
items: List<Searchable>,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
val viewModel: HiddenItemsSheetVM = viewModel()
|
||||
@ -56,8 +58,6 @@ fun HiddenItemsSheet(
|
||||
}
|
||||
) {
|
||||
|
||||
|
||||
val items by remember { viewModel.hiddenItems }.collectAsState(emptyList())
|
||||
SearchResultGrid(
|
||||
items,
|
||||
modifier = Modifier
|
||||
@ -65,7 +65,3 @@ fun HiddenItemsSheet(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private enum class SwipeState {
|
||||
Default, Dismiss
|
||||
}
|
||||
@ -9,12 +9,7 @@ import kotlinx.coroutines.flow.map
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
class HiddenItemsSheetVM: ViewModel(), KoinComponent {
|
||||
private val repository: FavoritesRepository by inject()
|
||||
|
||||
val hiddenItems = repository.getHiddenItems().map {
|
||||
it.sorted()
|
||||
}
|
||||
class HiddenItemsSheetVM: ViewModel() {
|
||||
|
||||
fun showHiddenItems(context: Context) {
|
||||
context.startActivity(
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package de.mm20.launcher2.ui.launcher.search
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.VisibilityOff
|
||||
@ -8,6 +9,8 @@ import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
@ -20,6 +23,7 @@ import de.mm20.launcher2.ui.launcher.search.calendar.CalendarResults
|
||||
import de.mm20.launcher2.ui.launcher.search.contacts.ContactResults
|
||||
import de.mm20.launcher2.ui.launcher.search.favorites.FavoritesResults
|
||||
import de.mm20.launcher2.ui.launcher.search.files.FileResults
|
||||
import de.mm20.launcher2.ui.launcher.search.hidden.HiddenResults
|
||||
import de.mm20.launcher2.ui.launcher.search.unitconverter.UnitConverterResults
|
||||
import de.mm20.launcher2.ui.launcher.search.website.WebsiteResults
|
||||
import de.mm20.launcher2.ui.launcher.search.wikipedia.WikipediaResults
|
||||
@ -45,33 +49,6 @@ fun SearchColumn(
|
||||
WikipediaResults(reverse)
|
||||
WebsiteResults(reverse)
|
||||
FileResults(reverse)
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.End
|
||||
) {
|
||||
val viewModel: LauncherActivityVM = viewModel()
|
||||
Surface(
|
||||
shadowElevation = 2.dp,
|
||||
tonalElevation = 2.dp,
|
||||
color = MaterialTheme.colorScheme.surfaceVariant,
|
||||
contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
onClick = { viewModel.showHiddenItems() }
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.padding(vertical = 8.dp, horizontal = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.padding(start = 12.dp, end = 12.dp),
|
||||
imageVector = Icons.Rounded.VisibilityOff,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
HiddenResults()
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,5 @@
|
||||
package de.mm20.launcher2.ui.launcher.search
|
||||
|
||||
import android.util.Log
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
@ -61,6 +60,8 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
val unitConverterResult = MutableLiveData<UnitConverter?>(null)
|
||||
val websearchResults = MutableLiveData<List<Websearch>>(emptyList())
|
||||
|
||||
val hiddenResults = MutableLiveData<List<Searchable>>(emptyList())
|
||||
|
||||
val hideFavorites = MutableLiveData(false)
|
||||
|
||||
private val hiddenItemKeys = favoritesRepository
|
||||
@ -93,6 +94,10 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
fun search(query: String) {
|
||||
searchQuery.value = query
|
||||
isSearchEmpty.value = query.isEmpty()
|
||||
hiddenResults.value = emptyList()
|
||||
|
||||
val hiddenItems = MutableStateFlow(HiddenItemResults())
|
||||
|
||||
try {
|
||||
searchJob?.cancel()
|
||||
} catch (e: CancellationException) {
|
||||
@ -103,22 +108,34 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
val jobs = mutableListOf<Deferred<Any>>()
|
||||
jobs += async {
|
||||
appRepository.search(query).collectLatest { apps ->
|
||||
hiddenItemKeys.collectLatest { hidden ->
|
||||
appResults.postValue(apps.filter { !hidden.contains(it.key) })
|
||||
hiddenItemKeys.collectLatest { hiddenKeys ->
|
||||
val results = apps.partition { !hiddenKeys.contains(it.key) }
|
||||
appResults.postValue(results.first)
|
||||
hiddenItems.update {
|
||||
it.copy(apps = results.second)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
jobs += async {
|
||||
contactRepository.search(query).collectLatest { contacts ->
|
||||
hiddenItemKeys.collectLatest { hidden ->
|
||||
contactResults.postValue(contacts.filter { !hidden.contains(it.key) })
|
||||
hiddenItemKeys.collectLatest { hiddenKeys ->
|
||||
val results = contacts.partition { !hiddenKeys.contains(it.key) }
|
||||
contactResults.postValue(results.first)
|
||||
hiddenItems.update {
|
||||
it.copy(contacts = results.second)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
jobs += async {
|
||||
calendarRepository.search(query).collectLatest { events ->
|
||||
hiddenItemKeys.collectLatest { hidden ->
|
||||
calendarResults.postValue(events.filter { !hidden.contains(it.key) })
|
||||
hiddenItemKeys.collectLatest { hiddenKeys ->
|
||||
val results = events.partition { !hiddenKeys.contains(it.key) }
|
||||
calendarResults.postValue(results.first)
|
||||
hiddenItems.update {
|
||||
it.copy(calendarEvents = results.second)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -144,8 +161,12 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
}
|
||||
jobs += async {
|
||||
fileRepository.search(query).collectLatest { files ->
|
||||
hiddenItemKeys.collectLatest { hidden ->
|
||||
fileResults.postValue(files.filter { !hidden.contains(it.key) })
|
||||
hiddenItemKeys.collectLatest { hiddenKeys ->
|
||||
val results = files.partition { !hiddenKeys.contains(it.key) }
|
||||
fileResults.postValue(results.first)
|
||||
hiddenItems.update {
|
||||
it.copy(files = results.second)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -161,6 +182,11 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
}
|
||||
}
|
||||
}
|
||||
launch {
|
||||
hiddenItems.collectLatest {
|
||||
hiddenResults.postValue(it.joinToList())
|
||||
}
|
||||
}
|
||||
jobs.map { it.await() }
|
||||
isSearching.postValue(false)
|
||||
}
|
||||
@ -243,4 +269,16 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private data class HiddenItemResults(
|
||||
val apps: List<Application> = emptyList(),
|
||||
val contacts: List<Contact> = emptyList(),
|
||||
val calendarEvents: List<CalendarEvent> = emptyList(),
|
||||
val files: List<File> = emptyList(),
|
||||
val appShortcuts: List<AppShortcut> = emptyList(),
|
||||
) {
|
||||
fun joinToList(): List<Searchable> {
|
||||
return apps + contacts + calendarEvents + files + appShortcuts
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
package de.mm20.launcher2.ui.launcher.search.hidden
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.VisibilityOff
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import de.mm20.launcher2.ui.launcher.LauncherActivityVM
|
||||
import de.mm20.launcher2.ui.launcher.modals.HiddenItemsSheet
|
||||
import de.mm20.launcher2.ui.launcher.search.SearchVM
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ColumnScope.HiddenResults() {
|
||||
val viewModel: SearchVM = viewModel()
|
||||
val hiddenResults by viewModel.hiddenResults.observeAsState(
|
||||
emptyList()
|
||||
)
|
||||
|
||||
var showHiddenItems by remember { mutableStateOf(false) }
|
||||
|
||||
AnimatedVisibility(visible = hiddenResults.isNotEmpty()) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.End
|
||||
) {
|
||||
Surface(
|
||||
shadowElevation = 2.dp,
|
||||
tonalElevation = 2.dp,
|
||||
color = MaterialTheme.colorScheme.surfaceVariant,
|
||||
contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
onClick = { showHiddenItems = true }
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.padding(vertical = 8.dp, horizontal = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.padding(start = 12.dp, end = 12.dp),
|
||||
imageVector = Icons.Rounded.VisibilityOff,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (showHiddenItems) {
|
||||
HiddenItemsSheet(hiddenResults, onDismiss = {showHiddenItems = false})
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user