streamscreen to player refactor

This commit is contained in:
tapframe 2025-12-11 14:42:05 +05:30
parent 6bdc998496
commit 3801e80dd9
5 changed files with 743 additions and 732 deletions

View file

@ -541,7 +541,7 @@ const SeriesContentComponent: React.FC<SeriesContentProps> = ({
return null;
}
if (__DEV__) console.log('[SeriesContent] renderSeasonSelector called, current view mode:', seasonViewMode);
const seasons = Object.keys(groupedEpisodes).map(Number).sort((a, b) => a - b);
@ -630,7 +630,7 @@ const SeriesContentComponent: React.FC<SeriesContentProps> = ({
if (seasonViewMode === 'text') {
// Text-only view
if (__DEV__) console.log('[SeriesContent] Rendering text view for season:', season, 'View mode ref:', seasonViewMode);
return (
<View
key={season}
@ -668,7 +668,7 @@ const SeriesContentComponent: React.FC<SeriesContentProps> = ({
}
// Poster view (current implementation)
if (__DEV__) console.log('[SeriesContent] Rendering poster view for season:', season, 'View mode ref:', seasonViewMode);
return (
<View
key={season}
@ -796,7 +796,7 @@ const SeriesContentComponent: React.FC<SeriesContentProps> = ({
const effectiveVote = imdbRating ?? tmdbRating ?? 0;
const isImdbRating = imdbRating !== null;
logger.log(`[SeriesContent] Vertical card S${episode.season_number}E${episode.episode_number}: IMDb=${imdbRating}, TMDB=${tmdbRating}, effective=${effectiveVote}, isImdb=${isImdbRating}`);
const effectiveRuntime = tmdbOverride?.runtime ?? (episode as any).runtime;
if (!episode.still_path && tmdbOverride?.still_path) {
@ -1067,8 +1067,6 @@ const SeriesContentComponent: React.FC<SeriesContentProps> = ({
const isImdbRating = imdbRating !== null;
const effectiveRuntime = tmdbOverride?.runtime ?? (episode as any).runtime;
logger.log(`[SeriesContent] Horizontal card S${episode.season_number}E${episode.episode_number}: IMDb=${imdbRating}, TMDB=${tmdbRating}, effective=${effectiveVote}, isImdb=${isImdbRating}`);
const formatDate = (dateString: string) => {
const date = new Date(dateString);
return date.toLocaleDateString('en-US', {

View file

@ -1,5 +1,5 @@
import React, { useState, useRef, useEffect, useMemo, useCallback } from 'react';
import { View, TouchableOpacity, TouchableWithoutFeedback, Dimensions, Animated, ActivityIndicator, Platform, NativeModules, StatusBar, Text, StyleSheet, Modal, AppState, Image } from 'react-native';
import { View, TouchableOpacity, TouchableWithoutFeedback, Dimensions, Animated, ActivityIndicator, Platform, NativeModules, StatusBar, Text, StyleSheet, Modal, AppState, Image, InteractionManager } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import Video, { VideoRef, SelectedTrack, SelectedTrackType, BufferingStrategyType, ViewType } from 'react-native-video';
import FastImage from '@d11/react-native-fast-image';
@ -641,6 +641,8 @@ const AndroidVideoPlayer: React.FC = () => {
// Prefetch backdrop and title logo for faster loading screen appearance
useEffect(() => {
// Defer prefetching until after navigation animation completes
const task = InteractionManager.runAfterInteractions(() => {
if (backdrop && typeof backdrop === 'string') {
// Reset loading state
setIsBackdropLoaded(false);
@ -667,9 +669,13 @@ const AndroidVideoPlayer: React.FC = () => {
setIsBackdropLoaded(true);
backdropImageOpacityAnim.setValue(0);
}
});
return () => task.cancel();
}, [backdrop]);
useEffect(() => {
// Defer logo prefetch until after navigation animation
const task = InteractionManager.runAfterInteractions(() => {
const logoUrl = (metadata && (metadata as any).logo) as string | undefined;
if (logoUrl && typeof logoUrl === 'string') {
try {
@ -678,6 +684,8 @@ const AndroidVideoPlayer: React.FC = () => {
// Silently ignore logo prefetch errors
}
}
});
return () => task.cancel();
}, [metadata]);
// Resolve current episode description for series

View file

@ -1,5 +1,5 @@
import React, { useState, useRef, useEffect, useMemo, useCallback } from 'react';
import { View, TouchableOpacity, Dimensions, Animated, ActivityIndicator, Platform, NativeModules, StatusBar, Text, StyleSheet, Modal, AppState } from 'react-native';
import { View, TouchableOpacity, Dimensions, Animated, ActivityIndicator, Platform, NativeModules, StatusBar, Text, StyleSheet, Modal, AppState, InteractionManager } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useNavigation, useRoute, RouteProp, useFocusEffect } from '@react-navigation/native';
import FastImage from '@d11/react-native-fast-image';
@ -342,6 +342,8 @@ const KSPlayerCore: React.FC = () => {
// Load custom backdrop on mount
// Prefetch backdrop and title logo for faster loading screen appearance
useEffect(() => {
// Defer prefetching until after navigation animation completes
const task = InteractionManager.runAfterInteractions(() => {
if (backdrop && typeof backdrop === 'string') {
// Reset loading state
setIsBackdropLoaded(false);
@ -368,9 +370,13 @@ const KSPlayerCore: React.FC = () => {
setIsBackdropLoaded(true);
backdropImageOpacityAnim.setValue(0);
}
});
return () => task.cancel();
}, [backdrop]);
useEffect(() => {
// Defer logo prefetch until after navigation animation
const task = InteractionManager.runAfterInteractions(() => {
const logoUrl = (metadata && (metadata as any).logo) as string | undefined;
if (logoUrl && typeof logoUrl === 'string') {
try {
@ -379,6 +385,8 @@ const KSPlayerCore: React.FC = () => {
// Silently ignore logo prefetch errors
}
}
});
return () => task.cancel();
}, [metadata]);
// Log video source configuration with headers

View file

@ -1210,7 +1210,7 @@ const InnerNavigator = ({ initialRouteName }: { initialRouteName?: keyof RootSta
options={{
animation: 'default',
animationDuration: 0,
// Force fullscreen presentation on iPad
// fullScreenModal required for proper video rendering on iOS
presentation: 'fullScreenModal',
// Disable gestures during video playback
gestureEnabled: false,

View file

@ -826,9 +826,6 @@ export const StreamsScreen = () => {
streamName: stream.name || stream.title
});
// Add 50ms delay before navigating to player
await new Promise(resolve => setTimeout(resolve, 50));
// Prepare available streams for the change source feature
const streamsToPass = (type === 'series' || (type === 'other' && selectedEpisode)) ? episodeStreams : groupedStreams;