feat(ui): Implement reorder mode for shopping lists
Extends the reorder mode functionality to the main shopping lists screen. - A long press on a shopping list card now activates reorder mode. - In this mode, drag handles are shown on both the left and right sides of each card to support left- and right-handed use. - Other actions (edit, delete, navigation) are disabled while in reorder mode. - Navigating away from the screen via the drawer correctly disables the reorder mode.
This commit is contained in:
@@ -156,6 +156,7 @@ fun AppShell(
|
||||
label = { Text(stringResource(id = screen.titleRes)) },
|
||||
selected = screen == currentScreen,
|
||||
onClick = {
|
||||
shoppingListsViewModel.disableReorderMode()
|
||||
currentScreen = screen
|
||||
selectedListId = null
|
||||
scope.launch { drawerState.close() }
|
||||
|
||||
@@ -5,6 +5,7 @@ import androidx.compose.animation.core.animateDpAsState
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.gestures.detectTapGestures
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
@@ -66,6 +67,7 @@ fun ShoppingListsScreen(
|
||||
onEditList: (ShoppingListWithItems) -> Unit
|
||||
) {
|
||||
val uiState by viewModel.uiState.collectAsState()
|
||||
val isReorderMode by viewModel.isReorderMode.collectAsState()
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
Column(
|
||||
@@ -91,10 +93,17 @@ fun ShoppingListsScreen(
|
||||
viewModel.deleteList(it.shoppingList)
|
||||
}
|
||||
},
|
||||
modifier = Modifier
|
||||
.clickable { onListClick(listWithItems.shoppingList.id) },
|
||||
modifier = Modifier.pointerInput(isReorderMode) {
|
||||
if (!isReorderMode) {
|
||||
detectTapGestures(
|
||||
onLongPress = { viewModel.enableReorderMode() },
|
||||
onTap = { onListClick(listWithItems.shoppingList.id) }
|
||||
)
|
||||
}
|
||||
},
|
||||
scope = this,
|
||||
isDragging = isDragging
|
||||
isDragging = isDragging,
|
||||
isReorderMode = isReorderMode
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -112,16 +121,14 @@ fun ShoppingListCard(
|
||||
onDeleteList: (ShoppingListWithItems) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
scope: ReorderableCollectionItemScope,
|
||||
isDragging: Boolean
|
||||
isDragging: Boolean,
|
||||
isReorderMode: Boolean
|
||||
) {
|
||||
val elevation = animateDpAsState(if (isDragging) 0.dp else 0.dp, label = "elevation")
|
||||
val elevation = animateDpAsState(if (isDragging) 4.dp else 1.dp, label = "elevation")
|
||||
val scale = animateFloatAsState(if (isDragging) 1.05f else 1.0f, label = "scale")
|
||||
val backgroundColor = animateColorAsState(
|
||||
if (isDragging) MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.7f)
|
||||
else Color.Transparent, label = "backgroundColor"
|
||||
)
|
||||
|
||||
Card(
|
||||
modifier = with(scope) { modifier.draggableHandle() }
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 4.dp, horizontal = 16.dp)
|
||||
.graphicsLayer {
|
||||
@@ -129,7 +136,6 @@ fun ShoppingListCard(
|
||||
scaleY = scale.value
|
||||
}
|
||||
.shadow(elevation.value)
|
||||
.background(backgroundColor.value)
|
||||
) {
|
||||
Column(modifier = Modifier.padding(16.dp)) {
|
||||
Row(
|
||||
@@ -137,17 +143,27 @@ fun ShoppingListCard(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
if (isReorderMode) {
|
||||
IconButton(modifier = with(scope) { Modifier.draggableHandle() }, onClick = {}) {
|
||||
Icon(Icons.Rounded.DragHandle, contentDescription = "Reorder")
|
||||
}
|
||||
}
|
||||
Text(
|
||||
text = listWithItems.shoppingList.name,
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
IconButton(onClick = { onEditList(listWithItems) }) {
|
||||
IconButton(onClick = { onEditList(listWithItems) }, enabled = !isReorderMode) {
|
||||
Icon(Icons.Default.Edit, contentDescription = stringResource(R.string.edit_list))
|
||||
}
|
||||
IconButton(onClick = { onDeleteList(listWithItems) }) {
|
||||
IconButton(onClick = { onDeleteList(listWithItems) }, enabled = !isReorderMode) {
|
||||
Icon(Icons.Default.Delete, contentDescription = stringResource(R.string.delete_list))
|
||||
}
|
||||
if (isReorderMode) {
|
||||
IconButton(modifier = with(scope) { Modifier.draggableHandle() }, onClick = {}) {
|
||||
Icon(Icons.Rounded.DragHandle, contentDescription = "Reorder")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user