Use BottomSheetDialog component for hidden items sheet
This commit is contained in:
parent
c7c97a3866
commit
9090d16af2
@ -4,9 +4,7 @@ import androidx.compose.animation.animateContentSize
|
|||||||
import androidx.compose.animation.core.animateDpAsState
|
import androidx.compose.animation.core.animateDpAsState
|
||||||
import androidx.compose.foundation.gestures.Orientation
|
import androidx.compose.foundation.gestures.Orientation
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.rememberScrollState
|
|
||||||
import androidx.compose.foundation.shape.CornerSize
|
import androidx.compose.foundation.shape.CornerSize
|
||||||
import androidx.compose.foundation.verticalScroll
|
|
||||||
import androidx.compose.material.*
|
import androidx.compose.material.*
|
||||||
import androidx.compose.material3.CenterAlignedTopAppBar
|
import androidx.compose.material3.CenterAlignedTopAppBar
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
@ -28,7 +26,6 @@ import androidx.compose.ui.window.Dialog
|
|||||||
import androidx.compose.ui.window.DialogProperties
|
import androidx.compose.ui.window.DialogProperties
|
||||||
import de.mm20.launcher2.ui.ktx.toDp
|
import de.mm20.launcher2.ui.ktx.toDp
|
||||||
import de.mm20.launcher2.ui.ktx.toPixels
|
import de.mm20.launcher2.ui.ktx.toPixels
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@OptIn(ExperimentalComposeUiApi::class, ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalComposeUiApi::class, ExperimentalMaterialApi::class)
|
||||||
@ -36,6 +33,7 @@ import kotlin.math.roundToInt
|
|||||||
fun BottomSheetDialog(
|
fun BottomSheetDialog(
|
||||||
onDismissRequest: () -> Unit,
|
onDismissRequest: () -> Unit,
|
||||||
title: @Composable () -> Unit,
|
title: @Composable () -> Unit,
|
||||||
|
actions: @Composable RowScope.() -> Unit = {},
|
||||||
confirmButton: @Composable (() -> Unit)? = null,
|
confirmButton: @Composable (() -> Unit)? = null,
|
||||||
dismissButton: @Composable (() -> Unit)? = null,
|
dismissButton: @Composable (() -> Unit)? = null,
|
||||||
content: @Composable () -> Unit,
|
content: @Composable () -> Unit,
|
||||||
@ -165,7 +163,8 @@ fun BottomSheetDialog(
|
|||||||
) {
|
) {
|
||||||
Column {
|
Column {
|
||||||
CenterAlignedTopAppBar(
|
CenterAlignedTopAppBar(
|
||||||
title = title
|
title = title,
|
||||||
|
actions = actions,
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|||||||
@ -1,48 +1,31 @@
|
|||||||
package de.mm20.launcher2.ui.launcher.modals
|
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.Column
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.offset
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.CornerSize
|
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.ExperimentalMaterialApi
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
import androidx.compose.material.FractionalThreshold
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.rounded.Edit
|
||||||
import androidx.compose.material.icons.rounded.Settings
|
import androidx.compose.material.icons.rounded.Settings
|
||||||
import androidx.compose.material.rememberSwipeableState
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material.swipeable
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.OutlinedButton
|
||||||
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.geometry.Offset
|
|
||||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
|
||||||
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
|
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.IntOffset
|
|
||||||
import androidx.compose.ui.unit.Velocity
|
|
||||||
import androidx.compose.ui.unit.dp
|
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 androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import de.mm20.launcher2.ui.R
|
import de.mm20.launcher2.ui.R
|
||||||
import de.mm20.launcher2.ui.ktx.toPixels
|
import de.mm20.launcher2.ui.component.BottomSheetDialog
|
||||||
import de.mm20.launcher2.ui.launcher.search.common.grid.SearchResultGrid
|
import de.mm20.launcher2.ui.launcher.search.common.grid.SearchResultGrid
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
@OptIn(ExperimentalComposeUiApi::class, ExperimentalMaterialApi::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HiddenItemsSheet(
|
fun HiddenItemsSheet(
|
||||||
onDismiss: () -> Unit
|
onDismiss: () -> Unit
|
||||||
@ -51,131 +34,36 @@ fun HiddenItemsSheet(
|
|||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
Dialog(
|
BottomSheetDialog(
|
||||||
properties = DialogProperties(usePlatformDefaultWidth = false),
|
onDismissRequest = onDismiss,
|
||||||
onDismissRequest = { onDismiss() }) {
|
title = {
|
||||||
val animationState = remember {
|
Text(
|
||||||
MutableTransitionState(false).apply {
|
stringResource(R.string.preference_hidden_items),
|
||||||
targetState = true
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
modifier = Modifier.padding(end = 16.dp),
|
||||||
|
maxLines = 1
|
||||||
|
)
|
||||||
|
},
|
||||||
|
actions = {
|
||||||
|
IconButton(onClick = { viewModel.showHiddenItems(context) }) {
|
||||||
|
Icon(imageVector = Icons.Rounded.Edit, contentDescription = null)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
OutlinedButton(onClick = onDismiss) {
|
||||||
|
Text(stringResource(id = R.string.close))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
) {
|
||||||
|
|
||||||
|
|
||||||
val swipeState =
|
val items by remember { viewModel.hiddenItems }.collectAsState(emptyList())
|
||||||
rememberSwipeableState(initialValue = SwipeState.Default) {
|
SearchResultGrid(
|
||||||
if (it == SwipeState.Dismiss) onDismiss()
|
items,
|
||||||
return@rememberSwipeableState true
|
modifier = Modifier
|
||||||
}
|
.verticalScroll(rememberScrollState())
|
||||||
|
)
|
||||||
val nestedScrollConnection = remember {
|
|
||||||
object : NestedScrollConnection {
|
|
||||||
|
|
||||||
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
|
|
||||||
if (available.y > 0) {
|
|
||||||
return super.onPreScroll(available, source)
|
|
||||||
}
|
|
||||||
val c = swipeState.performDrag(available.y)
|
|
||||||
return Offset(available.x, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPostScroll(
|
|
||||||
consumed: Offset,
|
|
||||||
available: Offset,
|
|
||||||
source: NestedScrollSource
|
|
||||||
): Offset {
|
|
||||||
if (available.y < 0) {
|
|
||||||
return super.onPreScroll(available, source)
|
|
||||||
}
|
|
||||||
val c = swipeState.performDrag(available.y)
|
|
||||||
return Offset(available.x, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun onPreFling(available: Velocity): Velocity {
|
|
||||||
if(available.y > 0) {
|
|
||||||
return super.onPreFling(available)
|
|
||||||
}
|
|
||||||
swipeState.performFling(available.y)
|
|
||||||
return available
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun onPostFling(
|
|
||||||
consumed: Velocity,
|
|
||||||
available: Velocity
|
|
||||||
): Velocity {
|
|
||||||
if (available.y < 0) {
|
|
||||||
return super.onPreFling(available)
|
|
||||||
}
|
|
||||||
swipeState.performFling(available.y)
|
|
||||||
return available
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimatedVisibility(
|
|
||||||
animationState,
|
|
||||||
enter = slideIn { IntOffset(0, it.height) }
|
|
||||||
) {
|
|
||||||
Surface(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.nestedScroll(nestedScrollConnection)
|
|
||||||
.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()) },
|
|
||||||
shape = MaterialTheme.shapes.large.copy(
|
|
||||||
bottomEnd = CornerSize(0f),
|
|
||||||
bottomStart = CornerSize(0f),
|
|
||||||
),
|
|
||||||
tonalElevation = 16.dp,
|
|
||||||
shadowElevation = 16.dp,
|
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
) {
|
|
||||||
|
|
||||||
SmallTopAppBar(
|
|
||||||
title = {
|
|
||||||
Text(
|
|
||||||
stringResource(R.string.preference_hidden_items),
|
|
||||||
overflow = TextOverflow.Ellipsis,
|
|
||||||
modifier = Modifier.padding(horizontal = 16.dp),
|
|
||||||
maxLines = 1
|
|
||||||
)
|
|
||||||
},
|
|
||||||
actions = {
|
|
||||||
IconButton(onClick = { viewModel.showHiddenItems(context) }) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Rounded.Settings,
|
|
||||||
contentDescription = stringResource(
|
|
||||||
R.string.settings
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
val items by remember { viewModel.hiddenItems }.collectAsState(emptyList())
|
|
||||||
SearchResultGrid(
|
|
||||||
items,
|
|
||||||
modifier = Modifier
|
|
||||||
.weight(1f)
|
|
||||||
.padding(8.dp)
|
|
||||||
.verticalScroll(rememberScrollState())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum class SwipeState {
|
private enum class SwipeState {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user