The ThystTV gesture system provides intuitive touch controls for video playback, including volume, brightness, seeking, and playback speed adjustments.
- Location:
ui/player/PlayerGestureListener.kt - Role: The central state machine. It extends
GestureDetector.SimpleOnGestureListenerto handle raw touch events from the AndroidGestureDetector. - Responsibilities:
- Detects gesture types based on screen zones (Left/Right for Volume/Brightness, Top/Bottom for Seek/Speed).
- Manages the gesture lifecycle (Down -> Scroll -> Up/Cancel).
- Prevents conflicts with other gestures (e.g., tap controls, minimize gesture).
- Applies settings (sensitivity, zone split, haptics).
- Updates the UI via
PlayerGestureCallback.
- Location:
ui/player/PlayerGestureHelper.kt - Role: A stateless helper class for pure logic and calculations.
- Responsibilities:
- Calculating new volume/brightness values.
- Formatting time durations strings.
- Mapping percentages to icon levels.
- Determining swipe directionality (Horizontal vs Vertical).
- Checking zone boundaries.
- Location:
ui/player/PlayerGestureListener.kt(Interface) - Role: Interface implemented by
PlayerFragmentto expose player state and control methods to the listener. - Key Methods:
seek(position),setPlaybackSpeed(speed)showController(),hideController()setWindowAttributes()(for brightness)getGestureFeedbackView()(for visual feedback overlay)
- Preferences: Defined in
xml/player_preferences.xml. - Constants: Keys in
util/C.kt. - Flow:
PlayerFragmentreadsSharedPreferencesand passes configuration (gesturesEnabled,sensitivity,zoneSplit,hapticEnabled) to thePlayerGestureListenerconstructor.
The PlayerGestureListener uses a set of boolean flags to track the current gesture state during a scroll event sequence (ACTION_DOWN -> ACTION_MOVE... -> ACTION_UP):
isVolume,isBrightness,isSeek,isSpeed: Mutually exclusive flags set on the first significant scroll movement. Once set, the gesture is "locked" to that mode untilACTION_UP.isScrolling: General flag indicating a scroll is active. Used to prevent single-tap actions (toggle controls) from firing immediately after a scroll.hasNotifiedGestureStart: EnsuresonSwipeGestureStarted()callback is fired only once per gesture.
- Vertical Swipes:
- Left 50%: Brightness
- Right 50%: Volume
- Horizontal Swipes (VoD Only):
- Top X%: Seek (Configurable via
zoneSplit) - Bottom Y%: Playback Speed
- Top X%: Seek (Configurable via
- Add a new state flag in
PlayerGestureListener. - Define the detection logic in
onScroll(e.g., a new zone or direction). - Add necessary methods to
PlayerGestureCallbackif the gesture requires new player interactions. - Implement the feedback visualization in
layout_player_gesture_feedback.xmlif needed.
PlayerGestureHelperTest: Unit tests for the math and logic (pure functions). MocksContextforAudioManager.- Integration: Currently,
PlayerGestureListenerlogic is verified via manual testing due toMotionEventmocking complexities in unit tests.