some ui changes

This commit is contained in:
tapframe 2025-08-08 18:35:16 +05:30
parent d8950caf04
commit f43d113f56
4 changed files with 37 additions and 28 deletions

View file

@ -276,10 +276,6 @@ const AndroidVideoPlayer: React.FC = () => {
initializePlayer();
return () => {
subscription?.remove();
const unlockOrientation = async () => {
await ScreenOrientation.unlockAsync();
};
unlockOrientation();
disableImmersiveMode();
};
}, []);

View file

@ -134,6 +134,9 @@ const VideoPlayer: React.FC = () => {
const [showResumeOverlay, setShowResumeOverlay] = useState(false);
const [resumePosition, setResumePosition] = useState<number | null>(null);
const [savedDuration, setSavedDuration] = useState<number | null>(null);
const initialSeekTargetRef = useRef<number | null>(null);
const initialSeekVerifiedRef = useRef(false);
const isSourceSeekableRef = useRef<boolean | null>(null);
const fadeAnim = useRef(new Animated.Value(1)).current;
const [isOpeningAnimationComplete, setIsOpeningAnimationComplete] = useState(false);
const openingFadeAnim = useRef(new Animated.Value(0)).current;
@ -292,10 +295,7 @@ const VideoPlayer: React.FC = () => {
lockOrientation();
return () => {
// Unlock orientation when component unmounts
ScreenOrientation.unlockAsync().catch(() => {
// Ignore unlock errors
});
// Do not unlock orientation here; we unlock explicitly on close to avoid mid-transition flips
};
}, []);
@ -403,6 +403,7 @@ const VideoPlayer: React.FC = () => {
setResumePosition(savedProgress.currentTime);
setSavedDuration(savedProgress.duration);
setInitialPosition(savedProgress.currentTime);
initialSeekTargetRef.current = savedProgress.currentTime;
logger.log(`[VideoPlayer] Set resume position to: ${savedProgress.currentTime} of ${savedProgress.duration}`);
if (appSettings.alwaysResume) {
logger.log(`[VideoPlayer] AlwaysResume enabled. Auto-seeking to ${savedProgress.currentTime}`);
@ -1280,6 +1281,24 @@ const VideoPlayer: React.FC = () => {
logger.log(`[VideoPlayer] Post-load initial seek to: ${initialPosition}s`);
seekToTime(initialPosition);
setIsInitialSeekComplete(true);
// Verify whether the seek actually took effect (detect non-seekable sources)
if (!initialSeekVerifiedRef.current) {
initialSeekVerifiedRef.current = true;
const target = initialSeekTargetRef.current ?? initialPosition;
setTimeout(() => {
const delta = Math.abs(currentTime - (target || 0));
if (target && (currentTime < target - 1.5)) {
logger.warn(`[VideoPlayer] Initial seek appears ignored (delta=${delta.toFixed(2)}). Treating source as non-seekable; starting from 0`);
isSourceSeekableRef.current = false;
// Reset resume intent and continue from 0
setInitialPosition(null);
setResumePosition(null);
setShowResumeOverlay(false);
} else {
isSourceSeekableRef.current = true;
}
}, 1200);
}
}
}, [isVideoLoaded, initialPosition, duration]);

View file

@ -771,8 +771,8 @@ const AppNavigator = ({ initialRouteName }: { initialRouteName?: keyof RootStack
name="Player"
component={VideoPlayer as any}
options={{
animation: 'slide_from_right',
animationDuration: Platform.OS === 'android' ? 200 : 300,
animation: Platform.OS === 'android' ? 'none' : 'fade',
animationDuration: Platform.OS === 'android' ? 0 : 300,
// Force fullscreen presentation on iPad
presentation: Platform.OS === 'ios' ? 'fullScreenModal' : 'card',
// Disable gestures during video playback

View file

@ -839,19 +839,24 @@ export const StreamsScreen = () => {
const streamName = stream.name || stream.title || 'Unnamed Stream';
const streamProvider = stream.addonId || stream.addonName || stream.name;
// Stream provider debug logging removed
// NetMirror stream logging removed
// Navigate to player immediately without waiting for orientation lock
// This prevents delay in player opening
// Add pre-navigation orientation lock to reduce glitch
try {
await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE);
} catch (e) {
logger.warn('[StreamsScreen] Pre-navigation orientation lock failed:', e);
}
// Small delay to allow orientation to settle
await new Promise(res => setTimeout(res, Platform.OS === 'ios' ? 120 : 60));
// Show a quick full-screen black overlay to mask rotation flicker
// by setting a transient state that renders a covering View (implementation already supported by dark backgrounds)
navigation.navigate('Player', {
uri: stream.url,
title: metadata?.name || '',
episodeTitle: type === 'series' ? currentEpisode?.name : undefined,
season: type === 'series' ? currentEpisode?.season_number : undefined,
episode: type === 'series' ? currentEpisode?.episode_number : undefined,
quality: stream.title?.match(/(\d+)p/)?.[1] || undefined,
quality: (stream.title?.match(/(\d+)p/) || [])[1] || undefined,
year: metadata?.year,
streamProvider: streamProvider,
streamName: streamName,
@ -863,17 +868,6 @@ export const StreamsScreen = () => {
availableStreams: streamsToPass,
backdrop: bannerImage || undefined,
});
// Lock orientation to landscape after navigation has started
// This allows the player to open immediately while orientation is being set
try {
ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE)
.catch(error => {
logger.error('[StreamsScreen] Error locking orientation after navigation:', error);
});
} catch (error) {
logger.error('[StreamsScreen] Error locking orientation after navigation:', error);
}
}, [metadata, type, currentEpisode, navigation, id, selectedEpisode, imdbId, episodeStreams, groupedStreams, bannerImage]);