230fc12025fd
fix: long-press enters multi-select — unify tap gestures (v2.9.28)
- time
- 2026-08-01 22:48 UTC · 2 months ago
- machine
- koh2
- parent
- 15358ca53de8
↓ peach-android-230fc120.tar.gzatlas at this save
files changed2 files
VERSION+1 −1app/src/main/java/com/peachpasswords/ui/vault/VaultListScreen.kt+23 −20app/src/main/java/com/peachpasswords/ui/vault/VaultListScreen.kt+23 −20
@@ -11,8 +11,9 @@1111 import androidx.compose.foundation.background1212 import androidx.compose.foundation.border1313 import androidx.compose.foundation.clickable14+import androidx.compose.foundation.combinedClickable15+import androidx.compose.foundation.ExperimentalFoundationApi1416 import androidx.compose.foundation.gestures.detectHorizontalDragGestures15-import androidx.compose.foundation.gestures.detectTapGestures1617 import androidx.compose.foundation.gestures.detectVerticalDragGestures1718 import androidx.compose.foundation.interaction.MutableInteractionSource1819 import androidx.compose.foundation.interaction.collectIsPressedAsState@@ -562,6 +563,7 @@562563 }563564 }564565 566+@OptIn(ExperimentalFoundationApi::class)565567 @Composable566568 private fun EntryRow(567569 entry: VaultEntry,@@ -593,25 +595,26 @@593595 .fillMaxWidth()594596 .clip(RoundedCornerShape(7.dp))595597 .background(rowBg)596- // Modifier order matters here, even though it looks incidental.597- // detectTapGestures needs to be the OUTERMOST pointer modifier so598- // its onLongPress gets first chance to fire (~500ms with no599- // movement past its slop). The downstream detectHorizontalDragGestures600- // has a smaller slop and will claim a touch with even a few pixels601- // of motion during a long-press, swallowing the gesture — that is602- // why long-press on a real device "did nothing" with the prior603- // arrangement, where the swipe detector was outermost. Putting604- // tap detection first lets it decide intent before movement605- // arbitration kicks in.606- .pointerInput(entry.id, multiSelect) {607- detectTapGestures(608- onLongPress = {609- PeachHaptics.onLongPress(context)610- onLongPress()611- },612- )613- }614- .clickable(interactionSource = interaction, indication = null, onClick = onTap)598+ // Click + long-press live in ONE combinedClickable, not a599+ // Modifier.clickable plus a separate detectTapGestures(onLongPress).600+ // Those ran two independent tap detectors on the same pointer that601+ // raced for the gesture — clickable's detector tended to win, so the602+ // separate onLongPress never reliably fired and long-press-to-multi-603+ // select "did nothing" on a real device (re-reported ~5x; an emulator604+ // input-injection "fix" once gave a false green). combinedClickable605+ // arbitrates click vs long-press correctly, keeps the interactionSource606+ // that drives the pressed row background, and coexists with the607+ // horizontal swipe-to-copy detector below.608+ .combinedClickable(609+ interactionSource = interaction,610+ indication = null,611+ onClick = onTap,612+ onLongClickLabel = "Select",613+ onLongClick = {614+ PeachHaptics.onLongPress(context)615+ onLongPress()616+ },617+ )615618 .pointerInput(entry.id, canSwipeCopy) {616619 if (!canSwipeCopy) return@pointerInput617620 var dx = 0f