From 556ec2ecf00dae11a486a75b860c860fa9766ef9 Mon Sep 17 00:00:00 2001 From: Calvin Liang Date: Thu, 12 Dec 2024 01:24:08 -0800 Subject: [PATCH] fix #57 --- .../reorderable/ReorderableLazyCollection.kt | 31 +++++++++++++------ .../kotlin/sh/calvin/reorderable/util.kt | 6 ++++ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/reorderable/src/commonMain/kotlin/sh/calvin/reorderable/ReorderableLazyCollection.kt b/reorderable/src/commonMain/kotlin/sh/calvin/reorderable/ReorderableLazyCollection.kt index 1e29d5a..f3eb127 100644 --- a/reorderable/src/commonMain/kotlin/sh/calvin/reorderable/ReorderableLazyCollection.kt +++ b/reorderable/src/commonMain/kotlin/sh/calvin/reorderable/ReorderableLazyCollection.kt @@ -511,26 +511,39 @@ open class ReorderableLazyCollectionState internal constructor( .reverseAxisWithLayoutDirectionIfLazyVerticalStaggeredGridRtlFix() val startOffset = draggingItem.offset.toOffset() + dragOffset val endOffset = startOffset + draggingItem.size.toSize() - val draggingItemRect = Rect(startOffset, endOffset).maxOutAxis(orientation) + val draggingItemRect = Rect(startOffset, endOffset).maxOutAxis(orientation.opposite) + val itemsInContentArea = state.layoutInfo.getItemsInContentArea(scrollThresholdPadding) + // if we can't find an item in the content area but still need to move the dragging item + // we will need to search outside the content area + .ifEmpty { state.layoutInfo.visibleItemsInfo } val targetItem = findTargetItem( draggingItemRect, - items = state.layoutInfo.getItemsInContentArea(scrollThresholdPadding), + items = itemsInContentArea, direction.opposite, - ) ?: state.layoutInfo.getItemsInContentArea( - scrollThresholdPadding - ).let { + ) ?: itemsInContentArea.let { val targetItemFunc = { item: LazyCollectionItemInfo -> - item.key in reorderableKeys && item.index != state.firstVisibleItemIndex + item.key in reorderableKeys } when (direction) { Scroller.Direction.FORWARD -> it.findLast(targetItemFunc) Scroller.Direction.BACKWARD -> it.find(targetItemFunc) } } + if (targetItem == null) { + onMoveStateMutex.unlock() + return + } + // this solves https://github.com/Calvin-LL/Reorderable/issues/57 + val isTargetDirectionCorrect = when (direction) { + Scroller.Direction.FORWARD -> targetItem.index > draggingItem.index + Scroller.Direction.BACKWARD -> targetItem.index < draggingItem.index + } + if (!isTargetDirectionCorrect) { + onMoveStateMutex.unlock() + return + } val job = scope.launch { - if (targetItem != null) { - moveItems(draggingItem, targetItem) - } + moveItems(draggingItem, targetItem) } onMoveStateMutex.unlock() job.join() diff --git a/reorderable/src/commonMain/kotlin/sh/calvin/reorderable/util.kt b/reorderable/src/commonMain/kotlin/sh/calvin/reorderable/util.kt index df945a9..6aa3676 100644 --- a/reorderable/src/commonMain/kotlin/sh/calvin/reorderable/util.kt +++ b/reorderable/src/commonMain/kotlin/sh/calvin/reorderable/util.kt @@ -7,6 +7,12 @@ import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.IntSize import kotlinx.coroutines.sync.Mutex +internal val Orientation.opposite + get() = when (this) { + Orientation.Vertical -> Orientation.Horizontal + Orientation.Horizontal -> Orientation.Vertical + } + internal fun Offset.getAxis(orientation: Orientation) = when (orientation) { Orientation.Vertical -> y Orientation.Horizontal -> x