From 63359532a38e0fad4345c5da6f53b1c02eb64756 Mon Sep 17 00:00:00 2001 From: Saif Shaikh Date: Fri, 2 Jan 2026 11:44:50 -0800 Subject: [PATCH] patch: incremental 10 sec skip/rewind on multiple taps --- .../android/hooks/useDebounceCallback.ts | 33 +++++++++++++++++++ .../player/controls/PlayerControls.tsx | 16 ++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 src/components/player/android/hooks/useDebounceCallback.ts diff --git a/src/components/player/android/hooks/useDebounceCallback.ts b/src/components/player/android/hooks/useDebounceCallback.ts new file mode 100644 index 0000000..57762a7 --- /dev/null +++ b/src/components/player/android/hooks/useDebounceCallback.ts @@ -0,0 +1,33 @@ +import { useCallback, useRef, useEffect } from 'react'; + +export function useDebounceCallback void>( + callback: T, + delay: number +) { + const timeoutRef = useRef | null>(null); + const callbackRef = useRef(callback); + + // Sync latest callback to avoid stale closures + useEffect(() => { + callbackRef.current = callback; + }, [callback]); + + const debouncedFunction = useCallback( + (...args: Parameters) => { + if (timeoutRef.current) clearTimeout(timeoutRef.current); + timeoutRef.current = setTimeout(() => { + callbackRef.current(...args); + }, delay); + }, + [delay] + ); + + // Cleanup on unmount to prevent memory leaks + useEffect(() => { + return () => { + if (timeoutRef.current) clearTimeout(timeoutRef.current); + }; + }, []); + + return debouncedFunction; +} diff --git a/src/components/player/controls/PlayerControls.tsx b/src/components/player/controls/PlayerControls.tsx index 444666c..b558cd4 100644 --- a/src/components/player/controls/PlayerControls.tsx +++ b/src/components/player/controls/PlayerControls.tsx @@ -7,6 +7,7 @@ import Slider from '@react-native-community/slider'; import { styles } from '../utils/playerStyles'; // Updated styles import { getTrackDisplayName } from '../utils/playerUtils'; import { useTheme } from '../../../contexts/ThemeContext'; +import { useDebounceCallback } from '../android/hooks/useDebounceCallback'; interface PlayerControlsProps { showControls: boolean; @@ -134,6 +135,15 @@ export const PlayerControls: React.FC = ({ const playIconOpacity = React.useRef(new Animated.Value(1)).current; /* Handle Seek with Animation */ + const [skipRewindSeconds, setSkipRewindSeconds] = React.useState(0); + const finalSkipRewind = (finalValue: number) => { + console.log(`Final value processed: ${finalValue}`); + skip(finalValue); + setSkipRewindSeconds(0); + } + const debouncedSkip = useDebounceCallback((val: number) => { + finalSkipRewind(val); + }, 800); const handleSeekWithAnimation = (seconds: number) => { const isForward = seconds > 0; @@ -212,7 +222,11 @@ export const PlayerControls: React.FC = ({ arcRotation.setValue(0); }); - skip(seconds); + setSkipRewindSeconds(prev => { + const nextVal = prev + seconds; + debouncedSkip(nextVal); + return nextVal; + }); }; /* Handle Play/Pause with Animation */