fix race conditions

This commit is contained in:
chrisk325 2026-03-01 15:06:50 +05:30 committed by GitHub
parent 5b6554ff37
commit c764faf2a7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -75,6 +75,11 @@ const TrailerPlayer = React.forwardRef<any, TrailerPlayerProps>(({
const [isFullscreen, setIsFullscreen] = useState(false);
const [isComponentMounted, setIsComponentMounted] = useState(true);
// FIX: Track whether this player has ever been in a playing state.
// This prevents the globalTrailerPlaying effect from suppressing the
// very first play attempt before the global state has been set to true.
const hasBeenPlayingRef = useRef(false);
// Animated values
const controlsOpacity = useSharedValue(0);
const loadingOpacity = useSharedValue(1);
@ -150,6 +155,7 @@ const TrailerPlayer = React.forwardRef<any, TrailerPlayerProps>(({
useEffect(() => {
if (isComponentMounted && paused === undefined) {
setIsPlaying(autoPlay);
if (autoPlay) hasBeenPlayingRef.current = true;
}
}, [autoPlay, isComponentMounted, paused]);
@ -163,18 +169,23 @@ const TrailerPlayer = React.forwardRef<any, TrailerPlayerProps>(({
// Handle external paused prop to override playing state (highest priority)
useEffect(() => {
if (paused !== undefined) {
setIsPlaying(!paused);
logger.info('TrailerPlayer', `External paused prop changed: ${paused}, setting isPlaying to ${!paused}`);
const shouldPlay = !paused;
setIsPlaying(shouldPlay);
if (shouldPlay) hasBeenPlayingRef.current = true;
logger.info('TrailerPlayer', `External paused prop changed: ${paused}, setting isPlaying to ${shouldPlay}`);
}
}, [paused]);
// Respond to global trailer state changes (e.g., when modal opens)
// Only apply if no external paused prop is controlling this
// Only apply if no external paused prop is controlling this.
// FIX: Only pause if this player has previously been in a playing state.
// This avoids the race condition where globalTrailerPlaying is still false
// at mount time (before the parent has called setTrailerPlaying(true)),
// which was causing the trailer to be immediately paused on every load.
useEffect(() => {
if (isComponentMounted && paused === undefined) {
// Always sync with global trailer state when pausing
// This ensures all trailers pause when one screen loses focus
if (!globalTrailerPlaying) {
if (!globalTrailerPlaying && hasBeenPlayingRef.current) {
// Only suppress if the player was previously playing — not on initial mount
logger.info('TrailerPlayer', 'Global trailer paused - pausing this trailer');
setIsPlaying(false);
}
@ -364,10 +375,10 @@ const TrailerPlayer = React.forwardRef<any, TrailerPlayerProps>(({
ref={videoRef}
source={(() => {
const androidHeaders = Platform.OS === 'android' ? { 'User-Agent': 'Nuvio/1.0 (Android)' } : {} as any;
// Help ExoPlayer select proper MediaSource
const lower = (trailerUrl || '').toLowerCase();
const looksLikeHls = /\.m3u8(\b|$)/.test(lower) || /hls|applehlsencryption|playlist|m3u/.test(lower);
const looksLikeDash = /\.mpd(\b|$)/.test(lower) || /dash|manifest/.test(lower);
// Detect both .mpd URLs and inline data: DASH manifests
const looksLikeDash = /\.mpd(\b|$)/.test(lower) || /dash|manifest/.test(lower) || lower.startsWith('data:application/dash');
if (Platform.OS === 'android') {
if (looksLikeHls) {
return { uri: trailerUrl, type: 'm3u8', headers: androidHeaders } as any;
@ -595,4 +606,4 @@ const styles = StyleSheet.create({
},
});
export default TrailerPlayer;
export default TrailerPlayer;