From fce5a981a292bcd4058a32521d2964d18cb5db03 Mon Sep 17 00:00:00 2001 From: Barnabas Balogh Date: Tue, 3 Mar 2026 10:34:38 +0100 Subject: [PATCH] fix: use absolute seek position for gesture seeking to prevent snap-back Capture the player position when the horizontal drag starts and compute an absolute seek target instead of using relative seekBy, which could drift or snap back due to playback advancing during the gesture. --- .../main/java/hu/bbara/purefin/player/ui/PlayerScreen.kt | 8 ++++---- .../purefin/player/ui/components/PlayerGesturesLayer.kt | 8 ++++++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/hu/bbara/purefin/player/ui/PlayerScreen.kt b/app/src/main/java/hu/bbara/purefin/player/ui/PlayerScreen.kt index fc080e5..4a67aa2 100644 --- a/app/src/main/java/hu/bbara/purefin/player/ui/PlayerScreen.kt +++ b/app/src/main/java/hu/bbara/purefin/player/ui/PlayerScreen.kt @@ -120,10 +120,10 @@ fun PlayerScreen( onHorizontalDragPreview = { horizontalSeekFeedback = it }, - onHorizontalDrag = { - viewModel.seekBy(it) - horizontalSeekFeedback = it - } + onHorizontalDragSeekTo = { + viewModel.seekTo(it) + }, + currentPositionProvider = { uiState.positionMs } ) EmptyValueTimedVisibility( diff --git a/app/src/main/java/hu/bbara/purefin/player/ui/components/PlayerGesturesLayer.kt b/app/src/main/java/hu/bbara/purefin/player/ui/components/PlayerGesturesLayer.kt index b6c1861..2e47fb7 100644 --- a/app/src/main/java/hu/bbara/purefin/player/ui/components/PlayerGesturesLayer.kt +++ b/app/src/main/java/hu/bbara/purefin/player/ui/components/PlayerGesturesLayer.kt @@ -29,7 +29,8 @@ fun PlayerGesturesLayer( onVerticalDragLeft: (delta: Float) -> Unit, onVerticalDragRight: (delta: Float) -> Unit, onHorizontalDragPreview: (deltaMs: Long?) -> Unit = {}, - onHorizontalDrag: (deltaMs: Long) -> Unit, + onHorizontalDragSeekTo: (positionMs: Long) -> Unit, + currentPositionProvider: () -> Long, ) { val density = LocalDensity.current val horizontalThresholdPx = with(density) { HorizontalSeekGestureHelper.START_THRESHOLD.toPx() } @@ -67,6 +68,7 @@ fun PlayerGesturesLayer( var accumulatedHorizontalDrag = 0f var isHorizontalDragActive = false var lastPreviewDelta: Long? = null + var startPositionMs = 0L drag(down.id) { change -> val delta = change.positionChange() @@ -86,6 +88,7 @@ fun PlayerGesturesLayer( accumulatedHorizontalDrag += delta.x if (!isHorizontalDragActive && abs(accumulatedHorizontalDrag) >= horizontalThresholdPx) { isHorizontalDragActive = true + startPositionMs = currentPositionProvider() } if (isHorizontalDragActive) { change.consume() @@ -112,7 +115,8 @@ fun PlayerGesturesLayer( if (dragDirection == DragDirection.HORIZONTAL && isHorizontalDragActive) { val deltaMs = HorizontalSeekGestureHelper.deltaMs(accumulatedHorizontalDrag) if (deltaMs != 0L) { - onHorizontalDrag(deltaMs) + val targetMs = (startPositionMs + deltaMs).coerceAtLeast(0L) + onHorizontalDragSeekTo(targetMs) onHorizontalDragPreview(deltaMs) } }