fix Android swipe gesture edge cases
This commit is contained in:
@@ -24,6 +24,7 @@ This is the canonical working plan and progress log for the project. Use this fi
|
||||
- iOS project scaffolding now exists as `mobile/ios-app/HermesApp.xcodeproj` with a shared scheme and XCTest target.
|
||||
- iOS sources and tests build and pass in Xcode on an iPhone simulator, and a standalone localization/error-mapping harness passes.
|
||||
- Android local unit tests now cover localization, error mapping, and analytics batch conversion, and `./gradlew testDebugUnitTest` passes with the Android SDK installed.
|
||||
- Android swipe-down gesture handling now uses cumulative drag distance, and edge-case tests cover upward drags, slow swipes, and per-gesture single-trigger behavior.
|
||||
|
||||
### Still Open
|
||||
|
||||
|
||||
+33
-2
@@ -4,9 +4,40 @@ import androidx.compose.foundation.gestures.detectVerticalDragGestures
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
|
||||
internal class HermesSwipeDownDetector(
|
||||
private val threshold: Float = 32f,
|
||||
) {
|
||||
private var totalDrag = 0f
|
||||
private var triggered = false
|
||||
|
||||
fun onDrag(dragAmount: Float): Boolean {
|
||||
if (triggered) {
|
||||
return false
|
||||
}
|
||||
|
||||
totalDrag = (totalDrag + dragAmount).coerceAtLeast(0f)
|
||||
if (totalDrag >= threshold) {
|
||||
triggered = true
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
totalDrag = 0f
|
||||
triggered = false
|
||||
}
|
||||
}
|
||||
|
||||
fun Modifier.hermesSwipeDown(onSwipeDown: () -> Unit): Modifier = pointerInput(onSwipeDown) {
|
||||
detectVerticalDragGestures { _, dragAmount ->
|
||||
if (dragAmount > 32f) {
|
||||
val detector = HermesSwipeDownDetector()
|
||||
detectVerticalDragGestures(
|
||||
onDragStart = { detector.reset() },
|
||||
onDragEnd = { detector.reset() },
|
||||
onDragCancel = { detector.reset() },
|
||||
) { _, dragAmount ->
|
||||
if (detector.onDrag(dragAmount)) {
|
||||
onSwipeDown()
|
||||
}
|
||||
}
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package com.hermes.app.core.gestures
|
||||
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class HermesSwipeDownDetectorTest {
|
||||
@Test
|
||||
fun triggersAfterCumulativeDownwardDrag() {
|
||||
val detector = HermesSwipeDownDetector(threshold = 32f)
|
||||
|
||||
assertFalse(detector.onDrag(10f))
|
||||
assertFalse(detector.onDrag(10f))
|
||||
assertTrue(detector.onDrag(12f))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun doesNotTriggerForSmallOrUpwardDrags() {
|
||||
val detector = HermesSwipeDownDetector(threshold = 32f)
|
||||
|
||||
assertFalse(detector.onDrag(20f))
|
||||
assertFalse(detector.onDrag(-15f))
|
||||
assertFalse(detector.onDrag(20f))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onlyTriggersOncePerGestureUntilReset() {
|
||||
val detector = HermesSwipeDownDetector(threshold = 32f)
|
||||
|
||||
assertTrue(detector.onDrag(40f))
|
||||
assertFalse(detector.onDrag(40f))
|
||||
|
||||
detector.reset()
|
||||
|
||||
assertTrue(detector.onDrag(40f))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user