mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-01-11 20:10:25 +00:00
Fix: Player orientation now correctly resets when exiting video player
This commit is contained in:
parent
0a1e008d5f
commit
a61c1e6456
9 changed files with 77 additions and 39 deletions
13
package-lock.json
generated
13
package-lock.json
generated
|
|
@ -51,7 +51,7 @@
|
|||
"expo-glass-effect": "~0.1.4",
|
||||
"expo-haptics": "~15.0.7",
|
||||
"expo-intent-launcher": "~13.0.7",
|
||||
"expo-libvlc-player": "^2.2.3",
|
||||
"expo-keep-awake": "~15.0.8",
|
||||
"expo-linear-gradient": "~15.0.7",
|
||||
"expo-localization": "~17.0.7",
|
||||
"expo-navigation-bar": "~5.0.10",
|
||||
|
|
@ -6512,17 +6512,6 @@
|
|||
"react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-libvlc-player": {
|
||||
"version": "2.2.5",
|
||||
"resolved": "https://registry.npmjs.org/expo-libvlc-player/-/expo-libvlc-player-2.2.5.tgz",
|
||||
"integrity": "sha512-Hl0XiRNK5iwPMDRWYouA7+Xzf804GZ/AMVTU87ktUlQMU5bgTUFgmi8QjlOLGEF5LpVp7LDFfQwsDpXP1ggpag==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"expo": "*",
|
||||
"react": "*",
|
||||
"react-native": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-linear-gradient": {
|
||||
"version": "15.0.8",
|
||||
"resolved": "https://registry.npmjs.org/expo-linear-gradient/-/expo-linear-gradient-15.0.8.tgz",
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
"expo-glass-effect": "~0.1.4",
|
||||
"expo-haptics": "~15.0.7",
|
||||
"expo-intent-launcher": "~13.0.7",
|
||||
"expo-keep-awake": "~15.0.8",
|
||||
"expo-linear-gradient": "~15.0.7",
|
||||
"expo-localization": "~17.0.7",
|
||||
"expo-navigation-bar": "~5.0.10",
|
||||
|
|
@ -103,4 +104,4 @@
|
|||
"xcode": "^3.0.1"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,13 +10,14 @@ import {
|
|||
usePlayerState,
|
||||
usePlayerModals,
|
||||
useSpeedControl,
|
||||
useOpeningAnimation
|
||||
useOpeningAnimation,
|
||||
useWatchProgress
|
||||
} from './hooks';
|
||||
|
||||
// Android-specific hooks
|
||||
import { usePlayerSetup } from './android/hooks/usePlayerSetup';
|
||||
import { usePlayerTracks } from './android/hooks/usePlayerTracks';
|
||||
import { useWatchProgress } from './android/hooks/useWatchProgress';
|
||||
|
||||
import { usePlayerControls } from './android/hooks/usePlayerControls';
|
||||
import { useNextEpisode } from './android/hooks/useNextEpisode';
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import EpisodesModal from './modals/EpisodesModal';
|
|||
import { EpisodeStreamsModal } from './modals/EpisodeStreamsModal';
|
||||
import { ErrorModal } from './modals/ErrorModal';
|
||||
import CustomSubtitles from './subtitles/CustomSubtitles';
|
||||
import ResumeOverlay from './modals/ResumeOverlay';
|
||||
import { SpeedActivatedOverlay, PauseOverlay, GestureControls } from './components';
|
||||
|
||||
// Platform-specific components
|
||||
|
|
@ -30,7 +31,8 @@ import {
|
|||
usePlayerTracks,
|
||||
useCustomSubtitles,
|
||||
usePlayerControls,
|
||||
usePlayerSetup
|
||||
usePlayerSetup,
|
||||
useWatchProgress
|
||||
} from './hooks';
|
||||
|
||||
// Platform-specific hooks
|
||||
|
|
@ -137,6 +139,15 @@ const KSPlayerCore: React.FC = () => {
|
|||
isMounted
|
||||
});
|
||||
|
||||
const watchProgress = useWatchProgress(
|
||||
id, type, episodeId,
|
||||
currentTime,
|
||||
duration,
|
||||
paused,
|
||||
traktAutosync,
|
||||
controls.seekToTime
|
||||
);
|
||||
|
||||
// Gestures
|
||||
const fadeAnim = useRef(new Animated.Value(1)).current;
|
||||
|
||||
|
|
@ -157,9 +168,6 @@ const KSPlayerCore: React.FC = () => {
|
|||
const [brightness, setBrightnessState] = useState(0.5);
|
||||
const [isSliderDragging, setIsSliderDragging] = useState(false);
|
||||
|
||||
// Watch Progress State
|
||||
const [initialPosition, setInitialPosition] = useState<number | null>(routeInitialPosition || null);
|
||||
|
||||
// Shared Gesture Hook
|
||||
const gestureControls = usePlayerGestureControls({
|
||||
volume: volume,
|
||||
|
|
@ -173,7 +181,8 @@ const KSPlayerCore: React.FC = () => {
|
|||
setScreenDimensions,
|
||||
setVolume: setVolumeState,
|
||||
setBrightness: setBrightnessState,
|
||||
isOpeningAnimationComplete: openingAnim.isOpeningAnimationComplete
|
||||
isOpeningAnimationComplete: openingAnim.isOpeningAnimationComplete,
|
||||
paused: paused
|
||||
});
|
||||
|
||||
// Refs for Logic
|
||||
|
|
@ -328,9 +337,10 @@ const KSPlayerCore: React.FC = () => {
|
|||
openingAnim.completeOpeningAnimation();
|
||||
|
||||
// Initial Seek
|
||||
if (initialPosition && initialPosition > 0) {
|
||||
const resumeTarget = routeInitialPosition || watchProgress.initialPosition || watchProgress.initialSeekTargetRef?.current;
|
||||
if (resumeTarget && resumeTarget > 0 && !watchProgress.showResumeOverlay && data.duration > 0) {
|
||||
setTimeout(() => {
|
||||
controls.seekToTime(initialPosition);
|
||||
controls.seekToTime(resumeTarget);
|
||||
}, 500);
|
||||
}
|
||||
|
||||
|
|
@ -602,6 +612,23 @@ const KSPlayerCore: React.FC = () => {
|
|||
speed={speedControl.holdToSpeedValue}
|
||||
/>
|
||||
|
||||
<ResumeOverlay
|
||||
showResumeOverlay={watchProgress.showResumeOverlay}
|
||||
resumePosition={watchProgress.resumePosition}
|
||||
duration={watchProgress.savedDuration || duration}
|
||||
title={title}
|
||||
season={season}
|
||||
episode={episode}
|
||||
handleResume={() => {
|
||||
watchProgress.setShowResumeOverlay(false);
|
||||
if (watchProgress.resumePosition) controls.seekToTime(watchProgress.resumePosition);
|
||||
}}
|
||||
handleStartFromBeginning={() => {
|
||||
watchProgress.setShowResumeOverlay(false);
|
||||
controls.seekToTime(0);
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Pause Overlay */}
|
||||
<PauseOverlay
|
||||
visible={paused && !showControls}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { StatusBar, Platform, Dimensions, AppState } from 'react-native';
|
|||
import RNImmersiveMode from 'react-native-immersive-mode';
|
||||
import * as NavigationBar from 'expo-navigation-bar';
|
||||
import * as Brightness from 'expo-brightness';
|
||||
import { activateKeepAwakeAsync, deactivateKeepAwake } from 'expo-keep-awake';
|
||||
import { logger } from '../../../../utils/logger';
|
||||
import { useFocusEffect } from '@react-navigation/native';
|
||||
import { useCallback } from 'react';
|
||||
|
|
@ -19,6 +20,19 @@ export const usePlayerSetup = (
|
|||
const originalSystemBrightnessModeRef = useRef<number | null>(null);
|
||||
const isAppBackgrounded = useRef(false);
|
||||
|
||||
// Prevent screen sleep while playing
|
||||
// Prevent screen sleep while playing
|
||||
useEffect(() => {
|
||||
if (!paused) {
|
||||
activateKeepAwakeAsync();
|
||||
} else {
|
||||
deactivateKeepAwake();
|
||||
}
|
||||
return () => {
|
||||
deactivateKeepAwake();
|
||||
};
|
||||
}, [paused]);
|
||||
|
||||
const enableImmersiveMode = async () => {
|
||||
if (Platform.OS === 'android') {
|
||||
// Standard immersive mode
|
||||
|
|
|
|||
|
|
@ -19,3 +19,4 @@ export { usePlayerSetup } from './usePlayerSetup';
|
|||
|
||||
// Content
|
||||
export { useNextEpisode } from './useNextEpisode';
|
||||
export { useWatchProgress } from './useWatchProgress';
|
||||
|
|
|
|||
|
|
@ -46,10 +46,7 @@ export const usePlayerControls = (config: PlayerControlsConfig) => {
|
|||
isSeeking.current = true;
|
||||
|
||||
// iOS optimization: pause while seeking for smoother experience
|
||||
if (Platform.OS === 'ios') {
|
||||
iosWasPausedDuringSeekRef.current = paused;
|
||||
if (!paused) setPaused(true);
|
||||
}
|
||||
|
||||
|
||||
// Actually perform the seek
|
||||
playerRef.current.seek(timeInSeconds);
|
||||
|
|
@ -59,10 +56,7 @@ export const usePlayerControls = (config: PlayerControlsConfig) => {
|
|||
if (isMounted.current && isSeeking.current) {
|
||||
isSeeking.current = false;
|
||||
// Resume if it was playing (iOS specific)
|
||||
if (Platform.OS === 'ios' && iosWasPausedDuringSeekRef.current === false) {
|
||||
setPaused(false);
|
||||
iosWasPausedDuringSeekRef.current = null;
|
||||
}
|
||||
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,8 @@
|
|||
/**
|
||||
* Shared Player Setup Hook
|
||||
* Used by both Android (VLC) and iOS (KSPlayer) players
|
||||
* Handles StatusBar, orientation, brightness, and app state
|
||||
*/
|
||||
import { useEffect, useRef, useCallback } from 'react';
|
||||
import { StatusBar, Dimensions, AppState, InteractionManager, Platform } from 'react-native';
|
||||
import * as Brightness from 'expo-brightness';
|
||||
import * as ScreenOrientation from 'expo-screen-orientation';
|
||||
import { activateKeepAwakeAsync, deactivateKeepAwake } from 'expo-keep-awake';
|
||||
import { logger } from '../../../utils/logger';
|
||||
import { useFocusEffect } from '@react-navigation/native';
|
||||
|
||||
|
|
@ -15,6 +11,7 @@ interface PlayerSetupConfig {
|
|||
setVolume: (vol: number) => void;
|
||||
setBrightness: (bri: number) => void;
|
||||
isOpeningAnimationComplete: boolean;
|
||||
paused: boolean;
|
||||
}
|
||||
|
||||
export const usePlayerSetup = (config: PlayerSetupConfig) => {
|
||||
|
|
@ -22,9 +19,23 @@ export const usePlayerSetup = (config: PlayerSetupConfig) => {
|
|||
setScreenDimensions,
|
||||
setVolume,
|
||||
setBrightness,
|
||||
isOpeningAnimationComplete
|
||||
isOpeningAnimationComplete,
|
||||
paused
|
||||
} = config;
|
||||
|
||||
// Prevent screen sleep while playing
|
||||
// Prevent screen sleep while playing
|
||||
useEffect(() => {
|
||||
if (!paused) {
|
||||
activateKeepAwakeAsync();
|
||||
} else {
|
||||
deactivateKeepAwake();
|
||||
}
|
||||
return () => {
|
||||
deactivateKeepAwake();
|
||||
};
|
||||
}, [paused]);
|
||||
|
||||
const isAppBackgrounded = useRef(false);
|
||||
|
||||
const enableImmersiveMode = () => {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useState, useEffect, useRef } from 'react';
|
||||
import { storageService } from '../../../../services/storageService';
|
||||
import { logger } from '../../../../utils/logger';
|
||||
import { useSettings } from '../../../../hooks/useSettings';
|
||||
import { storageService } from '../../../services/storageService';
|
||||
import { logger } from '../../../utils/logger';
|
||||
import { useSettings } from '../../../hooks/useSettings';
|
||||
|
||||
export const useWatchProgress = (
|
||||
id: string | undefined,
|
||||
Loading…
Reference in a new issue