Refactor VideoPlayer component to improve loading animations and state management

This update disables the debug mode for production and introduces a new state to track video loading status. The opening animation sequence has been modified to wait for the video to load before displaying the player, enhancing the user experience during playback. Additionally, unnecessary code related to seeking has been removed for clarity and performance improvements.
This commit is contained in:
tapframe 2025-06-08 16:12:33 +05:30
parent 45b2d4a124
commit 0d2b33a995

View file

@ -22,7 +22,7 @@ import AsyncStorage from '@react-native-async-storage/async-storage';
// Debug flag - set back to false to disable verbose logging // Debug flag - set back to false to disable verbose logging
// WARNING: Setting this to true currently causes infinite render loops // WARNING: Setting this to true currently causes infinite render loops
// Use selective logging instead if debugging is needed // Use selective logging instead if debugging is needed
const DEBUG_MODE = true; const DEBUG_MODE = false;
// Safer debug function that won't cause render loops // Safer debug function that won't cause render loops
// Call this with any debugging info you need instead of using inline DEBUG_MODE checks // Call this with any debugging info you need instead of using inline DEBUG_MODE checks
@ -276,6 +276,9 @@ const VideoPlayer: React.FC = () => {
const pendingSeekValue = useRef<number | null>(null); const pendingSeekValue = useRef<number | null>(null);
const lastSeekTime = useRef<number>(0); const lastSeekTime = useRef<number>(0);
// Add state for tracking if the video is loaded
const [isVideoLoaded, setIsVideoLoaded] = useState(false);
// Lock screen to landscape when component mounts // Lock screen to landscape when component mounts
useEffect(() => { useEffect(() => {
// Since orientation is now locked before navigation, we can start immediately // Since orientation is now locked before navigation, we can start immediately
@ -299,40 +302,44 @@ const VideoPlayer: React.FC = () => {
}; };
}, []); }, []);
// Opening animation sequence // Opening animation sequence - modified to wait for video load
const startOpeningAnimation = () => { const startOpeningAnimation = () => {
// Much shorter delay since rotation is already handled // Keep everything black until video loads
setTimeout(() => { // Only show loading indicator, no video player fade-in yet
// Start the main animation sequence // Note: All animations will be triggered by onLoad when video is ready
Animated.parallel([ };
// Fade in the video player
Animated.timing(openingFadeAnim, { // Complete the opening animation when video loads
toValue: 1, const completeOpeningAnimation = () => {
duration: 600, // Reduced back to original duration // Start all animations together when video is ready
useNativeDriver: true, Animated.parallel([
}), // Fade in the video player
// Scale up from 80% to 100% Animated.timing(openingFadeAnim, {
Animated.timing(openingScaleAnim, { toValue: 1,
toValue: 1, duration: 600,
duration: 700, // Reduced back to original duration useNativeDriver: true,
useNativeDriver: true, }),
}), // Scale up from 80% to 100%
// Fade out the black background overlay Animated.timing(openingScaleAnim, {
Animated.timing(backgroundFadeAnim, { toValue: 1,
toValue: 0, duration: 700,
duration: 800, // Reduced back to original duration useNativeDriver: true,
useNativeDriver: true, }),
}), // Fade out the black background overlay
]).start(() => { Animated.timing(backgroundFadeAnim, {
// Animation is complete toValue: 0,
setIsOpeningAnimationComplete(true); duration: 800,
useNativeDriver: true,
// Hide the background overlay completely after animation }),
setTimeout(() => { ]).start(() => {
backgroundFadeAnim.setValue(0); // Animation is complete
}, 100); setIsOpeningAnimationComplete(true);
});
}, 150); // Much shorter delay since no rotation is needed // Hide the background overlay completely after animation
setTimeout(() => {
backgroundFadeAnim.setValue(0);
}, 100);
});
}; };
// Load saved watch progress on mount // Load saved watch progress on mount
@ -465,19 +472,6 @@ const VideoPlayer: React.FC = () => {
} }
}; };
// Replace the reset seek value effect
// useEffect(() => {
// if (seekValue !== undefined) {
// const timer = setTimeout(() => {
// if (isMounted.current) {
// setSeekValue(undefined);
// }
// }, 1000); // Longer timeout to ensure VLC processes the seek properly
// return () => clearTimeout(timer);
// }
// }, [seekValue]);
// Simplify the seekToTime function to use VLC's direct methods // Simplify the seekToTime function to use VLC's direct methods
const seekToTime = (timeInSeconds: number) => { const seekToTime = (timeInSeconds: number) => {
if (!isPlayerReady || duration <= 0 || !vlcRef.current) return; if (!isPlayerReady || duration <= 0 || !vlcRef.current) return;
@ -501,11 +495,6 @@ const VideoPlayer: React.FC = () => {
} else { } else {
logger.error('[VideoPlayer] No seek method available on VLC player'); logger.error('[VideoPlayer] No seek method available on VLC player');
} }
// Update UI immediately for responsiveness
const progressPercent = timeInSeconds / duration;
progressAnim.setValue(progressPercent);
} catch (error) { } catch (error) {
logger.error('[VideoPlayer] Error during seek operation:', error); logger.error('[VideoPlayer] Error during seek operation:', error);
} }
@ -586,13 +575,16 @@ const VideoPlayer: React.FC = () => {
} }
}, 1000); }, 1000);
} }
// Mark video as loaded and complete opening animation
setIsVideoLoaded(true);
completeOpeningAnimation();
}; };
const skip = (seconds: number) => { const skip = (seconds: number) => {
if (vlcRef.current) { if (vlcRef.current) {
const newTime = Math.max(0, Math.min(currentTime + seconds, duration)); const newTime = Math.max(0, Math.min(currentTime + seconds, duration));
seekToTime(newTime); seekToTime(newTime);
// Let seekToTime handle all state updates
} }
}; };
@ -679,24 +671,6 @@ const VideoPlayer: React.FC = () => {
} }
}, [showSubtitleModal, textTracks]); }, [showSubtitleModal, textTracks]);
// Attempt to seek once vlcRef is available
useEffect(() => {
if (initialPosition !== null && !isInitialSeekComplete && vlcRef.current) {
if (DEBUG_MODE) {
logger.log(`[VideoPlayer] vlcRef is now available, attempting to seek to: ${initialPosition}`);
}
try {
seekToTime(initialPosition);
setIsInitialSeekComplete(true);
if (DEBUG_MODE) {
logger.log(`[VideoPlayer] Successfully seeked to position: ${initialPosition}`);
}
} catch (error) {
logger.error('[VideoPlayer] Error seeking to position on ref available:', error);
}
}
}, [vlcRef.current, initialPosition, isInitialSeekComplete]);
// Load resume preference on mount // Load resume preference on mount
useEffect(() => { useEffect(() => {
const loadResumePreference = async () => { const loadResumePreference = async () => {