Bring back hidden items bottom sheet
This commit is contained in:
parent
dc492cf2c8
commit
9bdac79b20
@ -36,6 +36,7 @@ import de.mm20.launcher2.ui.base.ProvideSettings
|
|||||||
import de.mm20.launcher2.ui.component.NavBarEffects
|
import de.mm20.launcher2.ui.component.NavBarEffects
|
||||||
import de.mm20.launcher2.ui.ktx.animateTo
|
import de.mm20.launcher2.ui.ktx.animateTo
|
||||||
import de.mm20.launcher2.ui.launcher.modals.EditFavoritesView
|
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.HomeTransitionManager
|
||||||
import de.mm20.launcher2.ui.launcher.transitions.LocalHomeTransitionManager
|
import de.mm20.launcher2.ui.launcher.transitions.LocalHomeTransitionManager
|
||||||
import de.mm20.launcher2.ui.locals.LocalSnackbarHostState
|
import de.mm20.launcher2.ui.locals.LocalSnackbarHostState
|
||||||
@ -142,6 +143,13 @@ class LauncherActivity : BaseActivity() {
|
|||||||
.navigationBarsPadding()
|
.navigationBarsPadding()
|
||||||
.imePadding()
|
.imePadding()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val showHiddenItems by viewModel.isHiddenItemsShown.observeAsState(false)
|
||||||
|
if (showHiddenItems) {
|
||||||
|
HiddenItemsSheet(onDismiss = {
|
||||||
|
viewModel.hideHiddenItems()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import org.koin.core.component.inject
|
|||||||
class LauncherActivityVM : ViewModel(), KoinComponent {
|
class LauncherActivityVM : ViewModel(), KoinComponent {
|
||||||
private val dataStore: LauncherDataStore by inject()
|
private val dataStore: LauncherDataStore by inject()
|
||||||
|
|
||||||
|
val isHiddenItemsShown = MutableLiveData(false)
|
||||||
val isEditFavoritesShown = MutableLiveData(false)
|
val isEditFavoritesShown = MutableLiveData(false)
|
||||||
|
|
||||||
private var isDarkInMode = MutableStateFlow(false)
|
private var isDarkInMode = MutableStateFlow(false)
|
||||||
@ -54,5 +55,13 @@ class LauncherActivityVM : ViewModel(), KoinComponent {
|
|||||||
isEditFavoritesShown.value = false
|
isEditFavoritesShown.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun showHiddenItems() {
|
||||||
|
isHiddenItemsShown.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hideHiddenItems() {
|
||||||
|
isHiddenItemsShown.value = false
|
||||||
|
}
|
||||||
|
|
||||||
val layout = dataStore.data.map { it.appearance.layout }.asLiveData()
|
val layout = dataStore.data.map { it.appearance.layout }.asLiveData()
|
||||||
}
|
}
|
||||||
@ -0,0 +1,116 @@
|
|||||||
|
package de.mm20.launcher2.ui.launcher.modals
|
||||||
|
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.animation.core.MutableTransitionState
|
||||||
|
import androidx.compose.animation.slideIn
|
||||||
|
import androidx.compose.foundation.gestures.Orientation
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
|
import androidx.compose.material.FractionalThreshold
|
||||||
|
import androidx.compose.material.rememberSwipeableState
|
||||||
|
import androidx.compose.material.swipeable
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.IntOffset
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.window.Dialog
|
||||||
|
import androidx.compose.ui.window.DialogProperties
|
||||||
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import de.mm20.launcher2.ui.R
|
||||||
|
import de.mm20.launcher2.ui.ktx.toPixels
|
||||||
|
import de.mm20.launcher2.ui.launcher.search.common.grid.SearchResultGrid
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
@OptIn(ExperimentalComposeUiApi::class, ExperimentalMaterialApi::class)
|
||||||
|
@Composable
|
||||||
|
fun HiddenItemsSheet(
|
||||||
|
onDismiss: () -> Unit
|
||||||
|
) {
|
||||||
|
val viewModel: HiddenItemsSheetVM = viewModel()
|
||||||
|
|
||||||
|
Dialog(
|
||||||
|
properties = DialogProperties(usePlatformDefaultWidth = false),
|
||||||
|
onDismissRequest = { onDismiss() }) {
|
||||||
|
val animationState = remember {
|
||||||
|
MutableTransitionState(false).apply {
|
||||||
|
targetState = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimatedVisibility(
|
||||||
|
animationState,
|
||||||
|
enter = slideIn { IntOffset(0, it.height) }
|
||||||
|
) {
|
||||||
|
val swipeState =
|
||||||
|
rememberSwipeableState(initialValue = SwipeState.Default) {
|
||||||
|
if (it == SwipeState.Dismiss) onDismiss()
|
||||||
|
return@rememberSwipeableState true
|
||||||
|
}
|
||||||
|
Surface(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.swipeable(
|
||||||
|
swipeState,
|
||||||
|
mapOf(
|
||||||
|
0f to SwipeState.Default,
|
||||||
|
600.dp.toPixels() to SwipeState.Dismiss
|
||||||
|
),
|
||||||
|
orientation = Orientation.Vertical,
|
||||||
|
thresholds = { _, _ -> FractionalThreshold(0.5f) },
|
||||||
|
)
|
||||||
|
.offset { IntOffset(0, swipeState.offset.value.roundToInt()) }
|
||||||
|
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
stringResource(R.string.preference_hidden_items),
|
||||||
|
style = MaterialTheme.typography.titleLarge,
|
||||||
|
modifier = Modifier.padding(24.dp)
|
||||||
|
|
||||||
|
)
|
||||||
|
val items by viewModel.hiddenItems.collectAsState(emptyList())
|
||||||
|
SearchResultGrid(
|
||||||
|
items,
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(8.dp)
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
)
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(12.dp),
|
||||||
|
contentAlignment = Alignment.CenterEnd
|
||||||
|
) {
|
||||||
|
TextButton(onClick = { onDismiss() }) {
|
||||||
|
Text(
|
||||||
|
stringResource(id = R.string.close),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum class SwipeState {
|
||||||
|
Default, Dismiss
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
package de.mm20.launcher2.ui.launcher.modals
|
||||||
|
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import de.mm20.launcher2.favorites.FavoritesRepository
|
||||||
|
import de.mm20.launcher2.search.data.Searchable
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
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()
|
||||||
|
}
|
||||||
@ -1,10 +1,8 @@
|
|||||||
package de.mm20.launcher2.ui.launcher.search
|
package de.mm20.launcher2.ui.launcher.search
|
||||||
|
|
||||||
import androidx.compose.foundation.BorderStroke
|
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.rounded.Settings
|
|
||||||
import androidx.compose.material.icons.rounded.VisibilityOff
|
import androidx.compose.material.icons.rounded.VisibilityOff
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
@ -16,6 +14,7 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import de.mm20.launcher2.ui.launcher.LauncherActivityVM
|
||||||
import de.mm20.launcher2.ui.launcher.search.apps.AppResults
|
import de.mm20.launcher2.ui.launcher.search.apps.AppResults
|
||||||
import de.mm20.launcher2.ui.launcher.search.appshortcuts.AppShortcutResults
|
import de.mm20.launcher2.ui.launcher.search.appshortcuts.AppShortcutResults
|
||||||
import de.mm20.launcher2.ui.launcher.search.calculator.CalculatorResults
|
import de.mm20.launcher2.ui.launcher.search.calculator.CalculatorResults
|
||||||
@ -55,14 +54,14 @@ fun SearchColumn(
|
|||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.End
|
horizontalArrangement = Arrangement.End
|
||||||
) {
|
) {
|
||||||
val viewModel: SearchVM = viewModel()
|
val viewModel: LauncherActivityVM = viewModel()
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
Surface(
|
Surface(
|
||||||
shadowElevation = 2.dp,
|
shadowElevation = 2.dp,
|
||||||
color = MaterialTheme.colorScheme.secondaryContainer,
|
color = MaterialTheme.colorScheme.secondaryContainer,
|
||||||
contentColor = MaterialTheme.colorScheme.onSecondaryContainer,
|
contentColor = MaterialTheme.colorScheme.onSecondaryContainer,
|
||||||
shape = CircleShape,
|
shape = CircleShape,
|
||||||
onClick = { viewModel.showHiddenItems(context) }
|
onClick = { viewModel.showHiddenItems() }
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.padding(12.dp),
|
modifier = Modifier.padding(12.dp),
|
||||||
@ -74,24 +73,6 @@ fun SearchColumn(
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.width(16.dp))
|
|
||||||
Surface(
|
|
||||||
shadowElevation = 2.dp,
|
|
||||||
color = MaterialTheme.colorScheme.secondaryContainer,
|
|
||||||
contentColor = MaterialTheme.colorScheme.onSecondaryContainer,
|
|
||||||
shape = CircleShape,
|
|
||||||
onClick = { viewModel.openSearchSettings(context) }
|
|
||||||
) {
|
|
||||||
Box(
|
|
||||||
modifier = Modifier.padding(12.dp),
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Rounded.Settings,
|
|
||||||
contentDescription = null,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user