Bring back hidden items bottom sheet

This commit is contained in:
MM20 2022-05-29 20:05:39 +02:00
parent dc492cf2c8
commit 9bdac79b20
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
5 changed files with 153 additions and 22 deletions

View File

@ -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()
})
}
} }
} }
} }

View File

@ -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()
} }

View File

@ -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
}

View File

@ -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()
}

View File

@ -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,
)
}
}
} }
} }
} }