feat: improve drag-and-drop functionality by interleaving dividers in ListsScreen and ManageColumnsDialog for better user experience

This commit is contained in:
2025-10-26 14:20:29 +01:00
parent fb484cd2ba
commit 168f660446
2 changed files with 88 additions and 72 deletions
@@ -24,7 +24,6 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.ClickableText import androidx.compose.foundation.text.ClickableText
@@ -2540,13 +2539,21 @@ fun ManageColumnsDialog(
.fillMaxWidth() .fillMaxWidth()
.reorderable(reorderState), .reorderable(reorderState),
state = reorderState.listState, state = reorderState.listState,
contentPadding = PaddingValues(16.dp), contentPadding = PaddingValues(horizontal = 8.dp, vertical = 16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(0.dp),
) { ) {
itemsIndexed( // Interleave dividers as separate Lazy items so dividers don't move with dragged rows
items = reorderedFields, items(
key = { _, field -> field.id }, count = reorderedFields.size * 2 - 1,
) { index, field -> key = { pos ->
if (pos % 2 == 0) reorderedFields[pos / 2].id else "divider-$pos"
},
) { pos ->
if (pos % 2 == 1) {
Divider()
} else {
val index = pos / 2
val field = reorderedFields[index]
ReorderableItem( ReorderableItem(
reorderState, reorderState,
key = field.id, key = field.id,
@@ -2554,7 +2561,6 @@ fun ManageColumnsDialog(
Box( Box(
modifier = Modifier.animateItemPlacement(), modifier = Modifier.animateItemPlacement(),
) { ) {
if (index > 0) Divider()
ColumnItem( ColumnItem(
field = field, field = field,
onEdit = { fieldToEdit = field }, onEdit = { fieldToEdit = field },
@@ -2586,6 +2592,7 @@ fun ManageColumnsDialog(
} }
} }
} }
}
Divider() Divider()
@@ -2681,18 +2688,16 @@ fun ColumnItem(
modifier = modifier =
Modifier Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp), .padding(horizontal = 8.dp, vertical = 10.dp),
horizontalArrangement = Arrangement.SpaceBetween, horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
// Drag handle // Drag handle
Column(horizontalAlignment = Alignment.CenterHorizontally) {
if (dragHandle != null) { if (dragHandle != null) {
dragHandle() dragHandle()
} }
}
Spacer(modifier = Modifier.width(12.dp)) Spacer(modifier = Modifier.width(8.dp))
Column(modifier = Modifier.weight(1f)) { Column(modifier = Modifier.weight(1f)) {
Text( Text(
@@ -2,7 +2,6 @@
package com.collabtable.app.ui.screens package com.collabtable.app.ui.screens
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@@ -14,8 +13,9 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.Delete
@@ -194,13 +194,23 @@ fun ListsScreen(
.fillMaxSize() .fillMaxSize()
.reorderable(reorderState), .reorderable(reorderState),
state = reorderState.listState, state = reorderState.listState,
contentPadding = PaddingValues(16.dp), contentPadding = PaddingValues(horizontal = 8.dp, vertical = 8.dp),
verticalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(0.dp),
) { ) {
itemsIndexed(working, key = { _, it -> it.id }) { index, list -> // Interleave dividers as separate list items so they don't move with dragged rows
items(
count = working.size * 2 - 1,
key = { pos ->
if (pos % 2 == 0) working[pos / 2].id else "divider-$pos"
},
) { pos ->
if (pos % 2 == 1) {
Divider()
} else {
val index = pos / 2
val list = working[index]
ReorderableItem(reorderState, key = list.id) { _ -> ReorderableItem(reorderState, key = list.id) { _ ->
Box(modifier = Modifier.animateItemPlacement()) { Box(modifier = Modifier.animateItemPlacement()) {
if (index > 0) Divider()
ListItem( ListItem(
list = list, list = list,
onListClick = { onNavigateToList(list.id) }, onListClick = { onNavigateToList(list.id) },
@@ -222,6 +232,7 @@ fun ListsScreen(
} }
} }
} }
}
if (showCreateDialog) { if (showCreateDialog) {
CreateListDialog( CreateListDialog(
@@ -280,14 +291,14 @@ fun ListItem(
modifier = modifier =
Modifier Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp), .padding(horizontal = 12.dp, vertical = 8.dp),
horizontalArrangement = Arrangement.SpaceBetween, horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
// Drag handle on the far left // Drag handle on the far left
if (dragHandle != null) { if (dragHandle != null) {
dragHandle() dragHandle()
Spacer(modifier = Modifier.padding(start = 8.dp)) Spacer(modifier = Modifier.width(8.dp))
} }
// Table name centered/left and clickable // Table name centered/left and clickable