Skip to content

fix: reset gestureActiveRef when pan or tap is cancelled - #2

Draft
skalthoff wants to merge 1 commit into
Jellify-Music:mainfrom
skalthoff:fix/gesture-active-ref-leak-on-cancel
Draft

skalthoff wants to merge 1 commit into
Jellify-Music:mainfrom
skalthoff:fix/gesture-active-ref-leak-on-cancel

Conversation

@skalthoff

Copy link
Copy Markdown

Summary

handleValueChange is the only place that resets gestureActiveRef.current to false, and it only runs after a successful gesture completion. If the pan or tap is cancelled — e.g. when the Gesture.Native() arm of the Race wins, or a parent gesture intercepts the touch — the ref leaks and stays true forever.

For consumers that drive UI off gestureActiveRef, this leaves them stuck in a "seeking" state. In Jellify this surfaces as: the progress bar visually moves on tap, then the timestamp display freezes and stops updating during playback because the consumer's "sync display position to actual playback" effect is gated on !isSeeking.current.

It's reproducible reliably on Waydroid (where mouse-derived events lose the Race to the Native arm more often than finger taps), and is a latent cause of rare "stuck scrubber" reports on real devices when a parent gesture steals mid-tap.

Changes

  • Pan: .onEnd(...) → .onFinalize(...), bail with a ref reset on !success.
  • Tap: reset the ref before the existing !success early return.

The success path is byte-identical to before — only the cancel/fail paths now clean up properly.

Test plan

  • Drag-scrub on a real device — bar tracks the finger, seek applies on release, ref clears.
  • Tap-scrub on a real device — bar jumps to tap position, seek applies, ref clears.
  • Start a drag on the slider then move vertically to dismiss a parent sheet — the slider gesture cancels cleanly without leaving the consumer stuck.
  • Waydroid (or any environment where the Native arm regularly wins the Race) — tap and drag both seek correctly, no frozen-timestamp aftermath.

handleValueChange is the only place that clears gestureActiveRef.current,
and it only runs on a successful gesture completion. If the pan or tap is
cancelled — for example when the Native arm of the Race wins, or a parent
gesture intercepts — the ref leaks and stays true forever, leaving the
consumer stuck in a "seeking" state and freezing any UI driven by it
(e.g. progress text, position sync effects).

- Pan: switch onEnd to onFinalize and bail with a ref reset on !success.
- Tap: reset the ref before the existing !success early return.

Behaviour on the success path is unchanged.
Copilot AI review requested due to automatic review settings April 30, 2026 23:25
@skalthoff
skalthoff marked this pull request as draft April 30, 2026 23:33

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants