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.
This commit is contained in:
tapframe 2025-06-19 21:50:42 +05:30
parent 235a7eff24
commit fb7b58b97c
3 changed files with 95 additions and 9 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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<ResumeOverlayProps> = ({
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 (
<View style={styles.resumeOverlay}>