From 7627de32a9d0861a06cefc2d0e72cdf348cf6c80 Mon Sep 17 00:00:00 2001 From: tapframe Date: Sat, 21 Jun 2025 12:11:51 +0530 Subject: [PATCH] Add saved duration state to video player components for improved resume functionality This update introduces a new state variable, savedDuration, in both AndroidVideoPlayer and VideoPlayer components to track the duration of the video when setting the resume position. Additionally, logging has been enhanced to provide clearer information about the resume process and seeking actions, improving debugging and user experience. The seek timeout has also been extended to ensure smoother transitions during playback. --- src/components/player/AndroidVideoPlayer.tsx | 38 ++++++++++------ src/components/player/VideoPlayer.tsx | 47 ++++++++++++-------- 2 files changed, 53 insertions(+), 32 deletions(-) diff --git a/src/components/player/AndroidVideoPlayer.tsx b/src/components/player/AndroidVideoPlayer.tsx index 74f1c3bd..84876c52 100644 --- a/src/components/player/AndroidVideoPlayer.tsx +++ b/src/components/player/AndroidVideoPlayer.tsx @@ -106,6 +106,7 @@ const AndroidVideoPlayer: React.FC = () => { const [isInitialSeekComplete, setIsInitialSeekComplete] = useState(false); const [showResumeOverlay, setShowResumeOverlay] = useState(false); const [resumePosition, setResumePosition] = useState(null); + const [savedDuration, setSavedDuration] = useState(null); const [rememberChoice, setRememberChoice] = useState(false); const [resumePreference, setResumePreference] = useState(null); const fadeAnim = useRef(new Animated.Value(1)).current; @@ -279,7 +280,8 @@ const AndroidVideoPlayer: React.FC = () => { if (progressPercent < 85) { setResumePosition(savedProgress.currentTime); - logger.log(`[AndroidVideoPlayer] Set resume position to: ${savedProgress.currentTime}`); + setSavedDuration(savedProgress.duration); + logger.log(`[AndroidVideoPlayer] Set resume position to: ${savedProgress.currentTime} of ${savedProgress.duration}`); const pref = await AsyncStorage.getItem(RESUME_PREF_KEY); logger.log(`[AndroidVideoPlayer] Resume preference: ${pref}`); @@ -357,22 +359,25 @@ const AndroidVideoPlayer: React.FC = () => { const seekToTime = (timeInSeconds: number) => { if (videoRef.current && duration > 0 && !isSeeking.current) { if (DEBUG_MODE) { - logger.log(`[AndroidVideoPlayer] Seeking to ${timeInSeconds.toFixed(2)}s`); + logger.log(`[AndroidVideoPlayer] Seeking to ${timeInSeconds.toFixed(2)}s out of ${duration.toFixed(2)}s`); } isSeeking.current = true; setSeekTime(timeInSeconds); - // Clear seek state after seek + // Clear seek state after seek with longer timeout setTimeout(() => { if (isMounted.current) { setSeekTime(null); isSeeking.current = false; + if (DEBUG_MODE) { + logger.log(`[AndroidVideoPlayer] Seek completed to ${timeInSeconds.toFixed(2)}s`); + } } - }, 100); + }, 500); } else { if (DEBUG_MODE) { - logger.error('[AndroidVideoPlayer] Seek failed: Player not ready, duration is zero, or already seeking.'); + logger.error(`[AndroidVideoPlayer] Seek failed: videoRef=${!!videoRef.current}, duration=${duration}, seeking=${isSeeking.current}`); } } }; @@ -615,7 +620,9 @@ const AndroidVideoPlayer: React.FC = () => { }; const handleResume = async () => { - if (resumePosition !== null && videoRef.current) { + if (resumePosition !== null) { + logger.log(`[AndroidVideoPlayer] Resume requested to position: ${resumePosition}s, duration: ${duration}, isPlayerReady: ${isPlayerReady}`); + if (rememberChoice) { try { await AsyncStorage.setItem(RESUME_PREF_KEY, RESUME_PREF.ALWAYS_RESUME); @@ -623,13 +630,18 @@ const AndroidVideoPlayer: React.FC = () => { logger.error('[AndroidVideoPlayer] Error saving resume preference:', error); } } - setInitialPosition(resumePosition); + setShowResumeOverlay(false); - setTimeout(() => { - if (videoRef.current) { - seekToTime(resumePosition); - } - }, 500); + + // If video is already loaded and ready, seek immediately + if (isPlayerReady && duration > 0 && videoRef.current) { + logger.log(`[AndroidVideoPlayer] Video ready, seeking immediately to: ${resumePosition}s`); + seekToTime(resumePosition); + } else { + // Otherwise, set initial position for when video loads + logger.log(`[AndroidVideoPlayer] Video not ready, setting initial position: ${resumePosition}s`); + setInitialPosition(resumePosition); + } } }; @@ -1091,7 +1103,7 @@ const AndroidVideoPlayer: React.FC = () => { { const [isInitialSeekComplete, setIsInitialSeekComplete] = useState(false); const [showResumeOverlay, setShowResumeOverlay] = useState(false); const [resumePosition, setResumePosition] = useState(null); + const [savedDuration, setSavedDuration] = useState(null); const [rememberChoice, setRememberChoice] = useState(false); const [resumePreference, setResumePreference] = useState(null); const fadeAnim = useRef(new Animated.Value(1)).current; @@ -274,18 +275,13 @@ const VideoPlayer: React.FC = () => { if (progressPercent < 85) { setResumePosition(savedProgress.currentTime); - logger.log(`[VideoPlayer] Set resume position to: ${savedProgress.currentTime}`); + setSavedDuration(savedProgress.duration); + logger.log(`[VideoPlayer] Set resume position to: ${savedProgress.currentTime} of ${savedProgress.duration}`); const pref = await AsyncStorage.getItem(RESUME_PREF_KEY); logger.log(`[VideoPlayer] Resume preference: ${pref}`); - // TEMPORARY: Clear the preference to test overlay - if (pref) { - await AsyncStorage.removeItem(RESUME_PREF_KEY); - logger.log(`[VideoPlayer] CLEARED resume preference for testing`); - setShowResumeOverlay(true); - logger.log(`[VideoPlayer] Showing resume overlay after clearing preference`); - } else if (pref === RESUME_PREF.ALWAYS_RESUME) { + if (pref === RESUME_PREF.ALWAYS_RESUME) { setInitialPosition(savedProgress.currentTime); logger.log(`[VideoPlayer] Auto-resuming due to preference`); } else if (pref === RESUME_PREF.ALWAYS_START_OVER) { @@ -375,7 +371,7 @@ const VideoPlayer: React.FC = () => { const seekToTime = (timeInSeconds: number) => { if (vlcRef.current && duration > 0 && !isSeeking.current) { if (DEBUG_MODE) { - logger.log(`[VideoPlayer] Seeking to ${timeInSeconds.toFixed(2)}s`); + logger.log(`[VideoPlayer] Seeking to ${timeInSeconds.toFixed(2)}s out of ${duration.toFixed(2)}s`); } isSeeking.current = true; @@ -390,8 +386,11 @@ const VideoPlayer: React.FC = () => { setTimeout(() => { if (isMounted.current) { isSeeking.current = false; + if (DEBUG_MODE) { + logger.log(`[VideoPlayer] Android seek completed to ${timeInSeconds.toFixed(2)}s`); + } } - }, 300); + }, 500); } else { // iOS fallback - use seek prop const position = timeInSeconds / duration; @@ -401,12 +400,15 @@ const VideoPlayer: React.FC = () => { if (isMounted.current) { setSeekPosition(null); isSeeking.current = false; + if (DEBUG_MODE) { + logger.log(`[VideoPlayer] iOS seek completed to ${timeInSeconds.toFixed(2)}s`); + } } }, 500); } } else { if (DEBUG_MODE) { - logger.error('[VideoPlayer] Seek failed: Player not ready, duration is zero, or already seeking.'); + logger.error(`[VideoPlayer] Seek failed: vlcRef=${!!vlcRef.current}, duration=${duration}, seeking=${isSeeking.current}`); } } }; @@ -633,7 +635,9 @@ const VideoPlayer: React.FC = () => { }; const handleResume = async () => { - if (resumePosition !== null && vlcRef.current) { + if (resumePosition !== null) { + logger.log(`[VideoPlayer] Resume requested to position: ${resumePosition}s, duration: ${duration}, isPlayerReady: ${isPlayerReady}`); + if (rememberChoice) { try { await AsyncStorage.setItem(RESUME_PREF_KEY, RESUME_PREF.ALWAYS_RESUME); @@ -641,13 +645,18 @@ const VideoPlayer: React.FC = () => { logger.error('[VideoPlayer] Error saving resume preference:', error); } } - setInitialPosition(resumePosition); + setShowResumeOverlay(false); - setTimeout(() => { - if (vlcRef.current) { - seekToTime(resumePosition); - } - }, 500); + + // If video is already loaded and ready, seek immediately + if (isPlayerReady && duration > 0 && vlcRef.current) { + logger.log(`[VideoPlayer] Video ready, seeking immediately to: ${resumePosition}s`); + seekToTime(resumePosition); + } else { + // Otherwise, set initial position for when video loads + logger.log(`[VideoPlayer] Video not ready, setting initial position: ${resumePosition}s`); + setInitialPosition(resumePosition); + } } }; @@ -1110,7 +1119,7 @@ const VideoPlayer: React.FC = () => {