From fb7b58b97c45272d76759e902b8978914a7bc1f8 Mon Sep 17 00:00:00 2001 From: tapframe Date: Thu, 19 Jun 2025 21:50:42 +0530 Subject: [PATCH] Enhance video player components with detailed logging and resume functionality This update improves the AndroidVideoPlayer and VideoPlayer components by adding comprehensive logging for watch progress loading, resume preferences, and playback events. It also refines the handling of resume overlays based on user preferences and saved progress, ensuring a smoother user experience. Additionally, the ResumeOverlay component now logs its rendering state, providing better insights during debugging. --- src/components/player/AndroidVideoPlayer.tsx | 41 ++++++++++++++-- src/components/player/VideoPlayer.tsx | 49 +++++++++++++++++-- .../player/modals/ResumeOverlay.tsx | 14 +++++- 3 files changed, 95 insertions(+), 9 deletions(-) diff --git a/src/components/player/AndroidVideoPlayer.tsx b/src/components/player/AndroidVideoPlayer.tsx index dc3f16d7..d54fa18f 100644 --- a/src/components/player/AndroidVideoPlayer.tsx +++ b/src/components/player/AndroidVideoPlayer.tsx @@ -260,24 +260,42 @@ const AndroidVideoPlayer: React.FC = () => { const loadWatchProgress = async () => { if (id && type) { try { + logger.log(`[AndroidVideoPlayer] Loading watch progress for ${type}:${id}${episodeId ? `:${episodeId}` : ''}`); const savedProgress = await storageService.getWatchProgress(id, type, episodeId); + logger.log(`[AndroidVideoPlayer] Saved progress:`, savedProgress); + if (savedProgress) { const progressPercent = (savedProgress.currentTime / savedProgress.duration) * 100; + logger.log(`[AndroidVideoPlayer] Progress: ${progressPercent.toFixed(1)}% (${savedProgress.currentTime}/${savedProgress.duration})`); + if (progressPercent < 95) { setResumePosition(savedProgress.currentTime); + logger.log(`[AndroidVideoPlayer] Set resume position to: ${savedProgress.currentTime}`); + const pref = await AsyncStorage.getItem(RESUME_PREF_KEY); + logger.log(`[AndroidVideoPlayer] Resume preference: ${pref}`); + if (pref === RESUME_PREF.ALWAYS_RESUME) { setInitialPosition(savedProgress.currentTime); + logger.log(`[AndroidVideoPlayer] Auto-resuming due to preference`); } else if (pref === RESUME_PREF.ALWAYS_START_OVER) { setInitialPosition(0); + logger.log(`[AndroidVideoPlayer] Auto-starting over due to preference`); } else { setShowResumeOverlay(true); + logger.log(`[AndroidVideoPlayer] Showing resume overlay`); } + } else { + logger.log(`[AndroidVideoPlayer] Progress too high (${progressPercent.toFixed(1)}%), not showing resume overlay`); } + } else { + logger.log(`[AndroidVideoPlayer] No saved progress found`); } } catch (error) { logger.error('[AndroidVideoPlayer] Error loading watch progress:', error); } + } else { + logger.log(`[AndroidVideoPlayer] Missing id or type: id=${id}, type=${type}`); } }; loadWatchProgress(); @@ -420,8 +438,9 @@ const AndroidVideoPlayer: React.FC = () => { logger.log('[AndroidVideoPlayer] Video loaded:', data); } if (isMounted.current) { + const videoDuration = data.duration; if (data.duration > 0) { - setDuration(data.duration); + setDuration(videoDuration); } // Set aspect ratio from video dimensions @@ -452,14 +471,20 @@ const AndroidVideoPlayer: React.FC = () => { setIsVideoLoaded(true); setIsPlayerReady(true); - // Start Trakt watching session when video loads - traktAutosync.handlePlaybackStart(currentTime, data.duration || duration); + // Start Trakt watching session when video loads with proper duration + if (videoDuration > 0) { + traktAutosync.handlePlaybackStart(currentTime, videoDuration); + } if (initialPosition && !isInitialSeekComplete) { + logger.log(`[AndroidVideoPlayer] Seeking to initial position: ${initialPosition}s (duration: ${videoDuration}s)`); setTimeout(() => { - if (videoRef.current && duration > 0 && isMounted.current) { + if (videoRef.current && videoDuration > 0 && isMounted.current) { seekToTime(initialPosition); setIsInitialSeekComplete(true); + logger.log(`[AndroidVideoPlayer] Initial seek completed to: ${initialPosition}s`); + } else { + logger.error(`[AndroidVideoPlayer] Initial seek failed: videoRef=${!!videoRef.current}, duration=${videoDuration}, mounted=${isMounted.current}`); } }, 1000); } @@ -544,16 +569,24 @@ const AndroidVideoPlayer: React.FC = () => { useEffect(() => { const loadResumePreference = async () => { try { + logger.log(`[AndroidVideoPlayer] Loading resume preference, resumePosition=${resumePosition}`); const pref = await AsyncStorage.getItem(RESUME_PREF_KEY); + logger.log(`[AndroidVideoPlayer] Resume preference loaded: ${pref}`); + if (pref) { setResumePreference(pref); if (pref === RESUME_PREF.ALWAYS_RESUME && resumePosition !== null) { + logger.log(`[AndroidVideoPlayer] Auto-resuming due to preference`); setShowResumeOverlay(false); setInitialPosition(resumePosition); } else if (pref === RESUME_PREF.ALWAYS_START_OVER) { + logger.log(`[AndroidVideoPlayer] Auto-starting over due to preference`); setShowResumeOverlay(false); setInitialPosition(0); } + // Don't override overlay if no specific preference or preference doesn't match + } else { + logger.log(`[AndroidVideoPlayer] No resume preference found, keeping overlay state`); } } catch (error) { logger.error('[AndroidVideoPlayer] Error loading resume preference:', error); diff --git a/src/components/player/VideoPlayer.tsx b/src/components/player/VideoPlayer.tsx index feeb5598..89cd404a 100644 --- a/src/components/player/VideoPlayer.tsx +++ b/src/components/player/VideoPlayer.tsx @@ -255,24 +255,48 @@ const VideoPlayer: React.FC = () => { const loadWatchProgress = async () => { if (id && type) { try { + logger.log(`[VideoPlayer] Loading watch progress for ${type}:${id}${episodeId ? `:${episodeId}` : ''}`); const savedProgress = await storageService.getWatchProgress(id, type, episodeId); + logger.log(`[VideoPlayer] Saved progress:`, savedProgress); + if (savedProgress) { const progressPercent = (savedProgress.currentTime / savedProgress.duration) * 100; + logger.log(`[VideoPlayer] Progress: ${progressPercent.toFixed(1)}% (${savedProgress.currentTime}/${savedProgress.duration})`); + if (progressPercent < 95) { setResumePosition(savedProgress.currentTime); + logger.log(`[VideoPlayer] Set resume position to: ${savedProgress.currentTime}`); + const pref = await AsyncStorage.getItem(RESUME_PREF_KEY); - if (pref === RESUME_PREF.ALWAYS_RESUME) { + 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) { setInitialPosition(savedProgress.currentTime); + logger.log(`[VideoPlayer] Auto-resuming due to preference`); } else if (pref === RESUME_PREF.ALWAYS_START_OVER) { setInitialPosition(0); + logger.log(`[VideoPlayer] Auto-starting over due to preference`); } else { setShowResumeOverlay(true); + logger.log(`[VideoPlayer] Showing resume overlay`); } + } else { + logger.log(`[VideoPlayer] Progress too high (${progressPercent.toFixed(1)}%), not showing resume overlay`); } + } else { + logger.log(`[VideoPlayer] No saved progress found`); } } catch (error) { logger.error('[VideoPlayer] Error loading watch progress:', error); } + } else { + logger.log(`[VideoPlayer] Missing id or type: id=${id}, type=${type}`); } }; loadWatchProgress(); @@ -441,8 +465,9 @@ const VideoPlayer: React.FC = () => { logger.log('[VideoPlayer] Video loaded:', data); } if (isMounted.current) { + const videoDuration = data.duration / 1000; if (data.duration > 0) { - setDuration(data.duration / 1000); + setDuration(videoDuration); } setVideoAspectRatio(data.videoSize.width / data.videoSize.height); @@ -455,11 +480,21 @@ const VideoPlayer: React.FC = () => { setIsVideoLoaded(true); setIsPlayerReady(true); + + // Start Trakt watching session when video loads with proper duration + if (videoDuration > 0) { + traktAutosync.handlePlaybackStart(currentTime, videoDuration); + } + if (initialPosition && !isInitialSeekComplete) { + logger.log(`[VideoPlayer] Seeking to initial position: ${initialPosition}s (duration: ${videoDuration}s)`); setTimeout(() => { - if (vlcRef.current && duration > 0 && isMounted.current) { + if (vlcRef.current && videoDuration > 0 && isMounted.current) { seekToTime(initialPosition); setIsInitialSeekComplete(true); + logger.log(`[VideoPlayer] Initial seek completed to: ${initialPosition}s`); + } else { + logger.error(`[VideoPlayer] Initial seek failed: vlcRef=${!!vlcRef.current}, duration=${videoDuration}, mounted=${isMounted.current}`); } }, 1000); } @@ -552,16 +587,24 @@ const VideoPlayer: React.FC = () => { useEffect(() => { const loadResumePreference = async () => { try { + logger.log(`[VideoPlayer] Loading resume preference, resumePosition=${resumePosition}`); const pref = await AsyncStorage.getItem(RESUME_PREF_KEY); + logger.log(`[VideoPlayer] Resume preference loaded: ${pref}`); + if (pref) { setResumePreference(pref); if (pref === RESUME_PREF.ALWAYS_RESUME && resumePosition !== null) { + logger.log(`[VideoPlayer] Auto-resuming due to preference`); setShowResumeOverlay(false); setInitialPosition(resumePosition); } else if (pref === RESUME_PREF.ALWAYS_START_OVER) { + logger.log(`[VideoPlayer] Auto-starting over due to preference`); setShowResumeOverlay(false); setInitialPosition(0); } + // Don't override overlay if no specific preference or preference doesn't match + } else { + logger.log(`[VideoPlayer] No resume preference found, keeping overlay state`); } } catch (error) { logger.error('[VideoPlayer] Error loading resume preference:', error); diff --git a/src/components/player/modals/ResumeOverlay.tsx b/src/components/player/modals/ResumeOverlay.tsx index 0c1f4e09..09451652 100644 --- a/src/components/player/modals/ResumeOverlay.tsx +++ b/src/components/player/modals/ResumeOverlay.tsx @@ -1,9 +1,10 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import { View, Text, TouchableOpacity } from 'react-native'; import { Ionicons } from '@expo/vector-icons'; import { LinearGradient } from 'expo-linear-gradient'; import { styles } from '../utils/playerStyles'; import { formatTime } from '../utils/playerUtils'; +import { logger } from '../../../utils/logger'; interface ResumeOverlayProps { showResumeOverlay: boolean; @@ -34,7 +35,16 @@ export const ResumeOverlay: React.FC = ({ handleResume, handleStartFromBeginning, }) => { - if (!showResumeOverlay || resumePosition === null) return null; + useEffect(() => { + logger.log(`[ResumeOverlay] Props changed: showOverlay=${showResumeOverlay}, resumePosition=${resumePosition}, duration=${duration}, title=${title}`); + }, [showResumeOverlay, resumePosition, duration, title]); + + if (!showResumeOverlay || resumePosition === null) { + logger.log(`[ResumeOverlay] Not showing overlay: showOverlay=${showResumeOverlay}, resumePosition=${resumePosition}`); + return null; + } + + logger.log(`[ResumeOverlay] Rendering overlay for ${title} at ${resumePosition}s`); return (