Refactor AndroidVideoPlayer and VideoPlayer components to simplify resume functionality and remove preference handling

This update streamlines the resume functionality in both the AndroidVideoPlayer and VideoPlayer components by removing the remember choice and resume preference states. The logic for showing the resume overlay has been simplified, enhancing the user experience. Additionally, the ResumeOverlay component has been updated to reflect these changes, removing unnecessary props related to user preferences. This refactor aims to create a more straightforward and efficient playback experience.
This commit is contained in:
tapframe 2025-06-21 19:30:05 +05:30
parent 87cd33b90b
commit 3fbec2c096
5 changed files with 20 additions and 213 deletions

View file

@ -107,8 +107,6 @@ const AndroidVideoPlayer: React.FC = () => {
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;
const [isOpeningAnimationComplete, setIsOpeningAnimationComplete] = useState(false);
const openingFadeAnim = useRef(new Animated.Value(0)).current;
@ -282,20 +280,8 @@ const AndroidVideoPlayer: React.FC = () => {
setResumePosition(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}`);
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`);
}
setShowResumeOverlay(true);
logger.log(`[AndroidVideoPlayer] Showing resume overlay`);
} else {
logger.log(`[AndroidVideoPlayer] Progress too high (${progressPercent.toFixed(1)}%), not showing resume overlay`);
}
@ -592,79 +578,17 @@ const AndroidVideoPlayer: React.FC = () => {
});
}, 100);
};
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);
}
};
loadResumePreference();
}, [resumePosition]);
const resetResumePreference = async () => {
try {
await AsyncStorage.removeItem(RESUME_PREF_KEY);
setResumePreference(null);
} catch (error) {
logger.error('[AndroidVideoPlayer] Error resetting resume preference:', error);
}
};
const handleResume = async () => {
if (resumePosition !== null) {
if (rememberChoice) {
try {
await AsyncStorage.setItem(RESUME_PREF_KEY, RESUME_PREF.ALWAYS_RESUME);
} catch (error) {
logger.error('[AndroidVideoPlayer] Error saving resume preference:', error);
}
}
setShowResumeOverlay(false);
// If video is already loaded and ready, seek immediately
if (isPlayerReady && duration > 0 && videoRef.current) {
seekToTime(resumePosition);
} else {
// Otherwise, set initial position for when video loads
setInitialPosition(resumePosition);
}
if (resumePosition) {
seekToTime(resumePosition);
}
setShowResumeOverlay(false);
};
const handleStartFromBeginning = async () => {
if (DEBUG_MODE) logger.log("[AndroidVideoPlayer] Starting from beginning.");
seekToTime(0);
setShowResumeOverlay(false);
if (videoRef.current) {
seekToTime(0);
}
await resetResumePreference();
setPaused(false);
// Start playback
if (isMounted.current) {
setIsInitialSeekComplete(true);
}
};
const toggleControls = () => {
@ -1113,13 +1037,9 @@ const AndroidVideoPlayer: React.FC = () => {
showResumeOverlay={showResumeOverlay}
resumePosition={resumePosition}
duration={savedDuration || duration}
title={title}
title={episodeTitle || title}
season={season}
episode={episode}
rememberChoice={rememberChoice}
setRememberChoice={setRememberChoice}
resumePreference={resumePreference}
resetResumePreference={resetResumePreference}
handleResume={handleResume}
handleStartFromBeginning={handleStartFromBeginning}
/>

View file

@ -102,8 +102,6 @@ const VideoPlayer: React.FC = () => {
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;
const [isOpeningAnimationComplete, setIsOpeningAnimationComplete] = useState(false);
const openingFadeAnim = useRef(new Animated.Value(0)).current;
@ -277,20 +275,8 @@ const VideoPlayer: React.FC = () => {
setResumePosition(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}`);
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`);
}
setShowResumeOverlay(true);
logger.log(`[VideoPlayer] Showing resume overlay`);
} else {
logger.log(`[VideoPlayer] Progress too high (${progressPercent.toFixed(1)}%), not showing resume overlay`);
}
@ -606,81 +592,17 @@ const VideoPlayer: React.FC = () => {
});
}, 100);
};
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);
}
};
loadResumePreference();
}, [resumePosition]);
const resetResumePreference = async () => {
try {
await AsyncStorage.removeItem(RESUME_PREF_KEY);
setResumePreference(null);
} catch (error) {
logger.error('[VideoPlayer] Error resetting resume preference:', error);
}
};
const handleResume = async () => {
if (resumePosition !== null) {
if (rememberChoice) {
try {
await AsyncStorage.setItem(RESUME_PREF_KEY, RESUME_PREF.ALWAYS_RESUME);
} catch (error) {
logger.error('[VideoPlayer] Error saving resume preference:', error);
}
}
setShowResumeOverlay(false);
// If video is already loaded and ready, seek immediately
if (isPlayerReady && duration > 0 && vlcRef.current) {
seekToTime(resumePosition);
} else {
// Otherwise, set initial position for when video loads
setInitialPosition(resumePosition);
}
if (resumePosition) {
seekToTime(resumePosition);
}
setShowResumeOverlay(false);
};
const handleStartFromBeginning = async () => {
if (rememberChoice) {
try {
await AsyncStorage.setItem(RESUME_PREF_KEY, RESUME_PREF.ALWAYS_START_OVER);
} catch (error) {
logger.error('[VideoPlayer] Error saving resume preference:', error);
}
}
seekToTime(0);
setShowResumeOverlay(false);
setInitialPosition(0);
if (vlcRef.current) {
seekToTime(0);
setCurrentTime(0);
}
};
const toggleControls = () => {
@ -1127,13 +1049,9 @@ const VideoPlayer: React.FC = () => {
showResumeOverlay={showResumeOverlay}
resumePosition={resumePosition}
duration={savedDuration || duration}
title={title}
title={episodeTitle || title}
season={season}
episode={episode}
rememberChoice={rememberChoice}
setRememberChoice={setRememberChoice}
resumePreference={resumePreference}
resetResumePreference={resetResumePreference}
handleResume={handleResume}
handleStartFromBeginning={handleStartFromBeginning}
/>

View file

@ -13,10 +13,6 @@ interface ResumeOverlayProps {
title: string;
season?: number;
episode?: number;
rememberChoice: boolean;
setRememberChoice: (remember: boolean) => void;
resumePreference: string | null;
resetResumePreference: () => void;
handleResume: () => void;
handleStartFromBeginning: () => void;
}
@ -28,10 +24,6 @@ export const ResumeOverlay: React.FC<ResumeOverlayProps> = ({
title,
season,
episode,
rememberChoice,
setRememberChoice,
resumePreference,
resetResumePreference,
handleResume,
handleStartFromBeginning,
}) => {
@ -78,29 +70,6 @@ export const ResumeOverlay: React.FC<ResumeOverlayProps> = ({
</View>
</View>
{/* Remember choice checkbox */}
<TouchableOpacity
style={styles.rememberChoiceContainer}
onPress={() => setRememberChoice(!rememberChoice)}
activeOpacity={0.7}
>
<View style={styles.checkboxContainer}>
<View style={[styles.checkbox, rememberChoice && styles.checkboxChecked]}>
{rememberChoice && <Ionicons name="checkmark" size={12} color="white" />}
</View>
<Text style={styles.rememberChoiceText}>Remember my choice</Text>
</View>
{resumePreference && (
<TouchableOpacity
onPress={resetResumePreference}
style={styles.resetPreferenceButton}
>
<Text style={styles.resetPreferenceText}>Reset</Text>
</TouchableOpacity>
)}
</TouchableOpacity>
<View style={styles.resumeButtons}>
<TouchableOpacity
style={styles.resumeButton}

View file

@ -333,7 +333,7 @@ const HomeScreen = () => {
.map(item => [item.poster, item.banner, item.logo])
.flat()
.filter(Boolean) as string[];
// Process in small batches to prevent memory pressure
for (let i = 0; i < allImages.length; i += BATCH_SIZE) {
const batch = allImages.slice(i, i + BATCH_SIZE);
@ -383,15 +383,15 @@ const HomeScreen = () => {
// Lock orientation to landscape before navigation to prevent glitches
try {
await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE);
await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE);
// Longer delay to ensure orientation is fully set before navigation
await new Promise(resolve => setTimeout(resolve, 200));
} catch (orientationError) {
// If orientation lock fails, continue anyway but log it
logger.warn('[HomeScreen] Orientation lock failed:', orientationError);
// Still add a small delay
await new Promise(resolve => setTimeout(resolve, 100));
await new Promise(resolve => setTimeout(resolve, 100));
}
navigation.navigate('Player', {

View file

@ -248,7 +248,7 @@ export const StreamsScreen = () => {
const loadStartTimeRef = useRef(0);
const hasDoneInitialLoadRef = useRef(false);
// Add timing logs
const [loadStartTime, setLoadStartTime] = useState(0);
@ -1022,7 +1022,7 @@ export const StreamsScreen = () => {
backgroundColor="transparent"
barStyle="light-content"
/>
<Animated.View
entering={FadeIn.duration(300)}