made some chanegs for xprime support

This commit is contained in:
tapframe 2025-07-30 00:45:58 +05:30
parent 6547d38c0e
commit a7e7c86f18
3 changed files with 279 additions and 3 deletions

@ -1 +1 @@
Subproject commit d2eb5507001e031aaa5d258c390ec56ecfa8f9c8
Subproject commit d129a1d2799397738c6e4848a6b80314a3326bd9

View file

@ -1,5 +1,5 @@
import React, { useState, useRef, useEffect } from 'react';
import { View, TouchableOpacity, Dimensions, Animated, ActivityIndicator, Platform, NativeModules, StatusBar, Text, Image, StyleSheet } from 'react-native';
import { View, TouchableOpacity, Dimensions, Animated, ActivityIndicator, Platform, NativeModules, StatusBar, Text, Image, StyleSheet, Modal } from 'react-native';
import Video, { VideoRef, SelectedTrack, SelectedTrackType, BufferingStrategyType } from 'react-native-video';
import { useNavigation, useRoute, RouteProp } from '@react-navigation/native';
import { RootStackParamList } from '../../navigation/AppNavigator';
@ -162,6 +162,9 @@ const AndroidVideoPlayer: React.FC = () => {
const isMounted = useRef(true);
const controlsTimeout = useRef<NodeJS.Timeout | null>(null);
const [isSyncingBeforeClose, setIsSyncingBeforeClose] = useState(false);
const [showErrorModal, setShowErrorModal] = useState(false);
const [errorDetails, setErrorDetails] = useState<string>('');
const errorTimeoutRef = useRef<NodeJS.Timeout | null>(null);
// Get metadata to access logo (only if we have a valid id)
const shouldLoadMetadata = Boolean(id && type);
const metadataResult = useMetadata({
@ -709,6 +712,44 @@ const AndroidVideoPlayer: React.FC = () => {
const handleError = (error: any) => {
logger.error('AndroidVideoPlayer error: ', error);
// Format error details for user display
let errorMessage = 'An unknown error occurred';
if (error) {
if (typeof error === 'string') {
errorMessage = error;
} else if (error.message) {
errorMessage = error.message;
} else if (error.error && error.error.message) {
errorMessage = error.error.message;
} else if (error.code) {
errorMessage = `Error Code: ${error.code}`;
} else {
errorMessage = JSON.stringify(error, null, 2);
}
}
setErrorDetails(errorMessage);
setShowErrorModal(true);
// Clear any existing timeout
if (errorTimeoutRef.current) {
clearTimeout(errorTimeoutRef.current);
}
// Auto-exit after 5 seconds if user doesn't dismiss
errorTimeoutRef.current = setTimeout(() => {
handleErrorExit();
}, 5000);
};
const handleErrorExit = () => {
if (errorTimeoutRef.current) {
clearTimeout(errorTimeoutRef.current);
errorTimeoutRef.current = null;
}
setShowErrorModal(false);
handleClose();
};
const onBuffer = (data: any) => {
@ -851,6 +892,9 @@ const AndroidVideoPlayer: React.FC = () => {
if (seekDebounceTimer.current) {
clearTimeout(seekDebounceTimer.current);
}
if (errorTimeoutRef.current) {
clearTimeout(errorTimeoutRef.current);
}
};
}, []);
@ -1254,6 +1298,100 @@ const AndroidVideoPlayer: React.FC = () => {
onSelectStream={handleSelectStream}
isChangingSource={isChangingSource}
/>
{/* Error Modal */}
<Modal
visible={showErrorModal}
transparent
animationType="fade"
onRequestClose={handleErrorExit}
>
<View style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0,0,0,0.8)'
}}>
<View style={{
backgroundColor: '#1a1a1a',
borderRadius: 14,
width: '85%',
maxHeight: '70%',
padding: 20,
shadowColor: '#000',
shadowOffset: { width: 0, height: 6 },
shadowOpacity: 0.25,
shadowRadius: 8,
elevation: 5,
}}>
<View style={{
flexDirection: 'row',
alignItems: 'center',
marginBottom: 16
}}>
<MaterialIcons name="error" size={24} color="#ff4444" style={{ marginRight: 8 }} />
<Text style={{
fontSize: 18,
fontWeight: 'bold',
color: '#ffffff',
flex: 1
}}>Playback Error</Text>
<TouchableOpacity onPress={handleErrorExit}>
<MaterialIcons name="close" size={24} color="#ffffff" />
</TouchableOpacity>
</View>
<Text style={{
fontSize: 14,
color: '#cccccc',
marginBottom: 16,
lineHeight: 20
}}>The video player encountered an error and cannot continue playback:</Text>
<View style={{
backgroundColor: '#2a2a2a',
borderRadius: 8,
padding: 12,
marginBottom: 20,
maxHeight: 200
}}>
<Text style={{
fontSize: 12,
color: '#ff8888',
fontFamily: Platform.OS === 'ios' ? 'Courier' : 'monospace'
}}>{errorDetails}</Text>
</View>
<View style={{
flexDirection: 'row',
justifyContent: 'flex-end'
}}>
<TouchableOpacity
style={{
backgroundColor: '#ff4444',
borderRadius: 8,
paddingVertical: 10,
paddingHorizontal: 20
}}
onPress={handleErrorExit}
>
<Text style={{
color: '#ffffff',
fontWeight: '600',
fontSize: 16
}}>Exit Player</Text>
</TouchableOpacity>
</View>
<Text style={{
fontSize: 12,
color: '#888888',
textAlign: 'center',
marginTop: 12
}}>This dialog will auto-close in 5 seconds</Text>
</View>
</View>
</Modal>
</View>
);
};

View file

@ -1,5 +1,5 @@
import React, { useState, useRef, useEffect } from 'react';
import { View, TouchableOpacity, Dimensions, Animated, ActivityIndicator, Platform, NativeModules, StatusBar, Text, Image, StyleSheet } from 'react-native';
import { View, TouchableOpacity, Dimensions, Animated, ActivityIndicator, Platform, NativeModules, StatusBar, Text, Image, StyleSheet, Modal } from 'react-native';
import { VLCPlayer } from 'react-native-vlc-media-player';
import { useNavigation, useRoute, RouteProp } from '@react-navigation/native';
import { RootStackParamList, RootStackNavigationProp } from '../../navigation/AppNavigator';
@ -167,6 +167,9 @@ const VideoPlayer: React.FC = () => {
const [availableStreams, setAvailableStreams] = useState<{ [providerId: string]: { streams: any[]; addonName: string } }>(passedAvailableStreams || {});
const [currentStreamUrl, setCurrentStreamUrl] = useState<string>(uri);
const [isChangingSource, setIsChangingSource] = useState<boolean>(false);
const [showErrorModal, setShowErrorModal] = useState(false);
const [errorDetails, setErrorDetails] = useState<string>('');
const errorTimeoutRef = useRef<NodeJS.Timeout | null>(null);
const [pendingSeek, setPendingSeek] = useState<{ position: number; shouldPlay: boolean } | null>(null);
const [currentQuality, setCurrentQuality] = useState<string | undefined>(quality);
const [currentStreamProvider, setCurrentStreamProvider] = useState<string | undefined>(streamProvider);
@ -794,6 +797,44 @@ const VideoPlayer: React.FC = () => {
const handleError = (error: any) => {
logger.error('[VideoPlayer] Playback Error:', error);
// Format error details for user display
let errorMessage = 'An unknown error occurred';
if (error) {
if (typeof error === 'string') {
errorMessage = error;
} else if (error.message) {
errorMessage = error.message;
} else if (error.error && error.error.message) {
errorMessage = error.error.message;
} else if (error.code) {
errorMessage = `Error Code: ${error.code}`;
} else {
errorMessage = JSON.stringify(error, null, 2);
}
}
setErrorDetails(errorMessage);
setShowErrorModal(true);
// Clear any existing timeout
if (errorTimeoutRef.current) {
clearTimeout(errorTimeoutRef.current);
}
// Auto-exit after 5 seconds if user doesn't dismiss
errorTimeoutRef.current = setTimeout(() => {
handleErrorExit();
}, 5000);
};
const handleErrorExit = () => {
if (errorTimeoutRef.current) {
clearTimeout(errorTimeoutRef.current);
errorTimeoutRef.current = null;
}
setShowErrorModal(false);
handleClose();
};
const onBuffering = (event: any) => {
@ -929,6 +970,9 @@ const VideoPlayer: React.FC = () => {
if (seekDebounceTimer.current) {
clearTimeout(seekDebounceTimer.current);
}
if (errorTimeoutRef.current) {
clearTimeout(errorTimeoutRef.current);
}
};
}, []);
@ -1337,6 +1381,100 @@ const VideoPlayer: React.FC = () => {
onSelectStream={handleSelectStream}
isChangingSource={isChangingSource}
/>
{/* Error Modal */}
<Modal
visible={showErrorModal}
transparent
animationType="fade"
onRequestClose={handleErrorExit}
>
<View style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0,0,0,0.8)'
}}>
<View style={{
backgroundColor: '#1a1a1a',
borderRadius: 14,
width: '85%',
maxHeight: '70%',
padding: 20,
shadowColor: '#000',
shadowOffset: { width: 0, height: 6 },
shadowOpacity: 0.25,
shadowRadius: 8,
elevation: 5,
}}>
<View style={{
flexDirection: 'row',
alignItems: 'center',
marginBottom: 16
}}>
<MaterialIcons name="error" size={24} color="#ff4444" style={{ marginRight: 8 }} />
<Text style={{
fontSize: 18,
fontWeight: 'bold',
color: '#ffffff',
flex: 1
}}>Playback Error</Text>
<TouchableOpacity onPress={handleErrorExit}>
<MaterialIcons name="close" size={24} color="#ffffff" />
</TouchableOpacity>
</View>
<Text style={{
fontSize: 14,
color: '#cccccc',
marginBottom: 16,
lineHeight: 20
}}>The video player encountered an error and cannot continue playback:</Text>
<View style={{
backgroundColor: '#2a2a2a',
borderRadius: 8,
padding: 12,
marginBottom: 20,
maxHeight: 200
}}>
<Text style={{
fontSize: 12,
color: '#ff8888',
fontFamily: Platform.OS === 'ios' ? 'Courier' : 'monospace'
}}>{errorDetails}</Text>
</View>
<View style={{
flexDirection: 'row',
justifyContent: 'flex-end'
}}>
<TouchableOpacity
style={{
backgroundColor: '#ff4444',
borderRadius: 8,
paddingVertical: 10,
paddingHorizontal: 20
}}
onPress={handleErrorExit}
>
<Text style={{
color: '#ffffff',
fontWeight: '600',
fontSize: 16
}}>Exit Player</Text>
</TouchableOpacity>
</View>
<Text style={{
fontSize: 12,
color: '#888888',
textAlign: 'center',
marginTop: 12
}}>This dialog will auto-close in 5 seconds</Text>
</View>
</View>
</Modal>
</View>
);
};