Skip to content

Add mobile touch gestures for video/scene playback#784

Open
my-alt-gh-acct wants to merge 10 commits intodamontecres:mainfrom
my-alt-gh-acct:main
Open

Add mobile touch gestures for video/scene playback#784
my-alt-gh-acct wants to merge 10 commits intodamontecres:mainfrom
my-alt-gh-acct:main

Conversation

@my-alt-gh-acct
Copy link
Copy Markdown

@my-alt-gh-acct my-alt-gh-acct commented Mar 25, 2026

This PR is intended to add a few QOL upgrades to the video playback experience for mobile users in the form of touch gestures for the video playback experience. Since the app is primarily Android TV, I gated it behind a settings flag in the advanced settings so as to not risk degrading the default experience.

If it is not already clear from commits, I should make clear that this code was developed with Claude code. I am a software developer by trade, but I am not and never have been an android developer. I've done my best to make sure the PR is small and targeted, and have reviewed the code myself, but admittedly I don't have the expertise to say with 100% confidence the code is exactly what an android developer would do.

I can say I've tested it on my own mobile android device (Samsung Galaxy s25) and it works as expected. The feature set is as follows:

  • Double-tap center to toggle 2x zoom
  • Pinch-to-zoom and drag-to-pan on the video surface
  • Double-tap left/right edges to skip back/forward
  • Long-press left/right edges for 0.5x/2x speed (releases on finger up)
  • Horizontal swipe to navigate to previous/next queue item
  • New "Mobile touch gestures" toggle in playback settings

Cheers and thanks for your time maintaining the project, and any time you put into reviewing the work.

my-alt-gh-acct and others added 10 commits March 24, 2026 23:21
- Pinch-to-zoom and drag-to-pan on the video surface (Compose path)
- Double-tap left/right edges to skip back/forward
- Double-tap center to toggle 2x zoom
- Long-press left/right edges for 0.5x/2x speed (releases on finger up)
- Horizontal swipe to navigate to previous/next queue item
- New "Mobile touch gestures" toggle in playback settings
- Defaults to enabled on non-TV devices for fresh installs
- Legacy XML playback path also wired up via MobileGestureHandler

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Moves the gesture modifier chain into mobileTouchGestureModifier before
the Box, keeping the PlayerSurface if/else branches clean and readable.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Let users opt in rather than enabling by default on fresh installs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Moves all gesture state and modifier chain into a dedicated
MobileGestureModifier.kt composable, keeping PlaybackPageContent focused
on playback UI layout.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add DisposableEffect to MobileGestureModifier to reset playback speed
  if the composable leaves composition mid-long-press
- Use @string/ references in advanced_preferences.xml instead of inline
  literals, matching the string resources already defined in strings.xml

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove surface_type=texture_view from video_playback.xml so the legacy
  path (primarily TV) keeps the default SurfaceView renderer
- Move rememberMobileGestureModifier call inside the mobileTouchGesturesEnabled
  branch so gesture state is never allocated on TV devices

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The Compose path (PlaybackPageContent) is the active mobile UI. Anyone
wanting mobile touch gestures will be on the Compose path, making
MobileGestureHandler dead code in practice.

Removes MobileGestureHandler, reverts PlaybackFragment and StashPlayerView
to their original state, and drops the legacy settings XML entry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix return@detectTapGestures in onLongPress else branch; center
  long-press was aborting the entire gesture detection coroutine,
  breaking all subsequent taps/swipes — changed to return@onLongPress
- Use pointerInput(zoomFactor > 1f) instead of pointerInput(zoomFactor)
  so the drag coroutine only restarts on zoom state transitions, not on
  every incremental zoom change
- Remove scaledModifier parameter from rememberMobileGestureModifier;
  caller chains with scaledModifier.then(...) — cleaner API boundary
- Add ControllerViewState.toggleControls() and use it everywhere to
  eliminate the duplicated show/hide conditional

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Multiply pan offset by zoomFactor so finger movement maps correctly
to screen position at any zoom level.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaced detectDragGestures with a manual swipe detector using
PointerEventPass.Initial to observe move events before transformable()
consumes them in the Main pass, which was causing intermittent
gesture cancellation. Also uses awaitFirstDown(requireUnconsumed=false)
so detectTapGestures' down.consume() doesn't block swipe detection.
Added abs(dragX) > abs(dragY) guard to prevent vertical gestures from
accidentally triggering next/prev.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

1 participant