fix: resolve tab long-press context menu blocked by drag gesture

The detectDragGesturesAfterLongPress modifier was consuming the
long-press event before combinedClickable.onLongClick could fire.
Replace combinedClickable with movement-tracking inside the drag
handler — small movement on release shows the context menu, large
movement commits the reorder. Move tap handling into Tab.onClick.

Made-with: Cursor
This commit is contained in:
cottongin
2026-03-11 17:12:14 -04:00
parent 5f7cb050e5
commit 8872b9de96

View File

@@ -390,14 +390,10 @@ private fun DragReorderTabRow(
key(tab.playlist?.id ?: -1L) {
val isDraggable = tab.playlist != null
var showTabMenu by remember(tab) { mutableStateOf(false) }
var totalDragDistance by remember { mutableFloatStateOf(0f) }
val dragThreshold = swapThresholdPx / 3
val tabModifier = Modifier
.combinedClickable(
onClick = { onSelectTab(index) },
onLongClick = {
if (isDraggable) showTabMenu = true
}
)
.then(
if (dragState.isDragging && dragState.draggedIndex == index) {
Modifier.graphicsLayer { translationX = dragState.dragOffset }
@@ -410,6 +406,7 @@ private fun DragReorderTabRow(
Modifier.pointerInput(tabs) {
detectDragGesturesAfterLongPress(
onDragStart = {
totalDragDistance = 0f
dragState.isDragging = true
dragState.draggedIndex = index
dragState.dragOffset = 0f
@@ -417,6 +414,7 @@ private fun DragReorderTabRow(
},
onDrag = { change, dragAmount ->
change.consume()
totalDragDistance += kotlin.math.abs(dragAmount.x) + kotlin.math.abs(dragAmount.y)
val currentIndex = dragState.draggedIndex
val newOffset = dragState.dragOffset + dragAmount.x
val groupStart = if (currentIndex < pinnedEnd) 0 else unpinnedStart
@@ -443,20 +441,27 @@ private fun DragReorderTabRow(
}
},
onDragEnd = {
val reordered = dragState.currentTabs
val playlists = if (dragState.draggedIndex < pinnedEnd) {
reordered.subList(0, pinnedEnd).mapNotNull { it.playlist }
if (totalDragDistance < dragThreshold) {
showTabMenu = true
} else {
reordered.subList(unpinnedStart, reordered.size).mapNotNull { it.playlist }
}
if (playlists.isNotEmpty()) {
onReorderTabs(playlists)
val reordered = dragState.currentTabs
val playlists = if (dragState.draggedIndex < pinnedEnd) {
reordered.subList(0, pinnedEnd).mapNotNull { it.playlist }
} else {
reordered.subList(unpinnedStart, reordered.size).mapNotNull { it.playlist }
}
if (playlists.isNotEmpty()) {
onReorderTabs(playlists)
}
}
dragState.isDragging = false
dragState.draggedIndex = -1
dragState.dragOffset = 0f
},
onDragCancel = {
if (totalDragDistance < dragThreshold) {
showTabMenu = true
}
dragState.isDragging = false
dragState.draggedIndex = -1
dragState.dragOffset = 0f
@@ -471,7 +476,7 @@ private fun DragReorderTabRow(
Box {
Tab(
selected = selectedTabIndex == index,
onClick = {},
onClick = { onSelectTab(index) },
text = {
Text(
text = tab.label,