mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-03-11 17:45:38 +00:00
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.
This commit is contained in:
parent
0d7882d565
commit
7627de32a9
2 changed files with 53 additions and 32 deletions
|
|
@ -106,6 +106,7 @@ const AndroidVideoPlayer: React.FC = () => {
|
|||
const [isInitialSeekComplete, setIsInitialSeekComplete] = useState(false);
|
||||
const [showResumeOverlay, setShowResumeOverlay] = useState(false);
|
||||
const [resumePosition, setResumePosition] = useState<number | null>(null);
|
||||
const [savedDuration, setSavedDuration] = useState<number | null>(null);
|
||||
const [rememberChoice, setRememberChoice] = useState(false);
|
||||
const [resumePreference, setResumePreference] = useState<string | null>(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 = () => {
|
|||
<ResumeOverlay
|
||||
showResumeOverlay={showResumeOverlay}
|
||||
resumePosition={resumePosition}
|
||||
duration={duration}
|
||||
duration={savedDuration || duration}
|
||||
title={title}
|
||||
season={season}
|
||||
episode={episode}
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ const VideoPlayer: React.FC = () => {
|
|||
const [isInitialSeekComplete, setIsInitialSeekComplete] = useState(false);
|
||||
const [showResumeOverlay, setShowResumeOverlay] = useState(false);
|
||||
const [resumePosition, setResumePosition] = useState<number | null>(null);
|
||||
const [savedDuration, setSavedDuration] = useState<number | null>(null);
|
||||
const [rememberChoice, setRememberChoice] = useState(false);
|
||||
const [resumePreference, setResumePreference] = useState<string | null>(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 = () => {
|
|||
<ResumeOverlay
|
||||
showResumeOverlay={showResumeOverlay}
|
||||
resumePosition={resumePosition}
|
||||
duration={duration}
|
||||
duration={savedDuration || duration}
|
||||
title={title}
|
||||
season={season}
|
||||
episode={episode}
|
||||
|
|
|
|||
Loading…
Reference in a new issue