fix: refine drag-and-drop logic in ListsScreen and ManageColumnsDialog to correctly adjust indices during reordering
This commit is contained in:
+8
-12
@@ -2506,30 +2506,26 @@ fun ManageColumnsDialog(
|
|||||||
Divider()
|
Divider()
|
||||||
|
|
||||||
// Column list with drag-and-drop reordering
|
// Column list with drag-and-drop reordering
|
||||||
// Local extension mirroring the working behavior used in ListsScreen
|
// Local extension mirroring the working behavior used in ListsScreen,
|
||||||
|
// adjusting target index when moving downwards to account for prior removal.
|
||||||
fun <T> MutableList<T>.move(
|
fun <T> MutableList<T>.move(
|
||||||
from: Int,
|
from: Int,
|
||||||
to: Int,
|
to: Int,
|
||||||
) {
|
) {
|
||||||
if (from == to) return
|
if (from == to) return
|
||||||
if (isEmpty()) return
|
if (isEmpty() || from !in indices) return
|
||||||
if (from !in indices) return
|
|
||||||
val item = removeAt(from)
|
val item = removeAt(from)
|
||||||
val insertIndex =
|
val insertIndex = (if (to > from) to - 1 else to).coerceIn(0, size)
|
||||||
when {
|
|
||||||
to > size -> size
|
|
||||||
to < 0 -> 0
|
|
||||||
else -> to
|
|
||||||
}
|
|
||||||
add(insertIndex, item)
|
add(insertIndex, item)
|
||||||
}
|
}
|
||||||
|
|
||||||
val reorderState =
|
val reorderState =
|
||||||
rememberReorderableLazyListState(
|
rememberReorderableLazyListState(
|
||||||
onMove = { from, to ->
|
onMove = { from, to ->
|
||||||
// Map from Lazy positions (including dividers) to data indices
|
// Map from Lazy positions (with dividers) to data indices.
|
||||||
|
// Insert AFTER the upper item when hovering between rows.
|
||||||
val fromData = from.index / 2
|
val fromData = from.index / 2
|
||||||
val toData = to.index / 2
|
val toData = (to.index + 1) / 2
|
||||||
reorderedFields.move(fromData, toData)
|
reorderedFields.move(fromData, toData)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -2546,7 +2542,7 @@ fun ManageColumnsDialog(
|
|||||||
) {
|
) {
|
||||||
// Interleave dividers as separate Lazy items so dividers don't move with dragged rows
|
// Interleave dividers as separate Lazy items so dividers don't move with dragged rows
|
||||||
items(
|
items(
|
||||||
count = reorderedFields.size * 2 - 1,
|
count = if (reorderedFields.isEmpty()) 0 else reorderedFields.size * 2 - 1,
|
||||||
key = { pos ->
|
key = { pos ->
|
||||||
if (pos % 2 == 0) reorderedFields[pos / 2].id else "divider-$pos"
|
if (pos % 2 == 0) reorderedFields[pos / 2].id else "divider-$pos"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -161,17 +161,11 @@ fun ListsScreen(
|
|||||||
to: Int,
|
to: Int,
|
||||||
) {
|
) {
|
||||||
if (from == to) return
|
if (from == to) return
|
||||||
|
if (isEmpty() || from !in indices) return
|
||||||
val item = removeAt(from)
|
val item = removeAt(from)
|
||||||
add(
|
// When moving downwards, the target index shifts left by one after removal
|
||||||
if (to > size) {
|
val insertIndex = (if (to > from) to - 1 else to).coerceIn(0, size)
|
||||||
size
|
add(insertIndex, item)
|
||||||
} else if (to < 0) {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
to
|
|
||||||
},
|
|
||||||
item,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val reorderState =
|
val reorderState =
|
||||||
@@ -179,9 +173,10 @@ fun ListsScreen(
|
|||||||
onMove = { from, to ->
|
onMove = { from, to ->
|
||||||
dragging = true
|
dragging = true
|
||||||
val newList = working.toMutableList()
|
val newList = working.toMutableList()
|
||||||
// Map from Lazy positions (including dividers) to data indices
|
// Map from Lazy positions (with dividers) to data indices.
|
||||||
|
// to.index can be odd (between items). Insert AFTER the upper item for better feel.
|
||||||
val fromData = from.index / 2
|
val fromData = from.index / 2
|
||||||
val toData = to.index / 2
|
val toData = (to.index + 1) / 2
|
||||||
newList.move(fromData, toData)
|
newList.move(fromData, toData)
|
||||||
working = newList
|
working = newList
|
||||||
},
|
},
|
||||||
@@ -202,7 +197,7 @@ fun ListsScreen(
|
|||||||
) {
|
) {
|
||||||
// Interleave dividers as separate list items so they don't move with dragged rows
|
// Interleave dividers as separate list items so they don't move with dragged rows
|
||||||
items(
|
items(
|
||||||
count = working.size * 2 - 1,
|
count = if (working.isEmpty()) 0 else working.size * 2 - 1,
|
||||||
key = { pos ->
|
key = { pos ->
|
||||||
if (pos % 2 == 0) working[pos / 2].id else "divider-$pos"
|
if (pos % 2 == 0) working[pos / 2].id else "divider-$pos"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user