This commit is contained in:
tapframe 2025-08-03 12:42:23 +05:30
parent 2d3ece7dc4
commit b21f13c283
6 changed files with 154 additions and 13 deletions

@ -1 +1 @@
Subproject commit ff60b52232d79636656476b4057bbd7b479cd6c7
Subproject commit cfd669df2258d217c90c58ce9455676c60abd1ac

17
package-lock.json generated
View file

@ -21,7 +21,7 @@
"@sentry/react-native": "^6.15.1",
"@types/lodash": "^4.17.16",
"@types/react-native-video": "^5.0.20",
"axios": "^1.10.0",
"axios": "^1.11.0",
"axios-cookiejar-support": "^6.0.4",
"cheerio-without-node-native": "^0.20.2",
"date-fns": "^4.1.0",
@ -5321,13 +5321,13 @@
"optional": true
},
"node_modules/axios": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz",
"integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==",
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz",
"integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
"form-data": "^4.0.4",
"proxy-from-env": "^1.1.0"
}
},
@ -5386,14 +5386,15 @@
}
},
"node_modules/axios/node_modules/form-data": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.2",
"mime-types": "^2.1.12"
},
"engines": {

View file

@ -22,7 +22,7 @@
"@sentry/react-native": "^6.15.1",
"@types/lodash": "^4.17.16",
"@types/react-native-video": "^5.0.20",
"axios": "^1.10.0",
"axios": "^1.11.0",
"axios-cookiejar-support": "^6.0.4",
"cheerio-without-node-native": "^0.20.2",
"date-fns": "^4.1.0",

View file

@ -15,6 +15,7 @@ import { useTraktAutosync } from '../../hooks/useTraktAutosync';
import { useTraktAutosyncSettings } from '../../hooks/useTraktAutosyncSettings';
import { useMetadata } from '../../hooks/useMetadata';
import { useSettings } from '../../hooks/useSettings';
import { testVideoStreamUrl } from '../../utils/httpInterceptor';
import {
DEFAULT_SUBTITLE_SIZE,
@ -497,6 +498,17 @@ const AndroidVideoPlayer: React.FC = () => {
const onLoad = (data: any) => {
try {
// Enhanced HTTP response logging
console.log('\n✅ [AndroidVideoPlayer] HTTP RESPONSE SUCCESS:');
console.log('📍 URL:', currentStreamUrl);
console.log('📊 Status: 200 OK (Video Stream Loaded)');
console.log('📺 Duration:', data?.duration ? `${data.duration.toFixed(2)}s` : 'Unknown');
console.log('📐 Resolution:', data?.naturalSize ? `${data.naturalSize.width}x${data.naturalSize.height}` : 'Unknown');
console.log('🎵 Audio Tracks:', data?.audioTracks?.length || 0);
console.log('📝 Text Tracks:', data?.textTracks?.length || 0);
console.log('⏰ Response Time:', new Date().toISOString());
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
if (DEBUG_MODE) {
logger.log('[AndroidVideoPlayer] Video loaded:', data);
}
@ -619,7 +631,7 @@ const AndroidVideoPlayer: React.FC = () => {
NativeModules.StatusBarManager.setHidden(true);
}
} catch (error) {
console.log('Immersive mode error:', error);
// Immersive mode error - silently handled
}
}
};
@ -712,6 +724,16 @@ const AndroidVideoPlayer: React.FC = () => {
const handleError = (error: any) => {
try {
// Enhanced HTTP error response logging
console.log('\n❌ [AndroidVideoPlayer] HTTP RESPONSE ERROR:');
console.log('📍 URL:', currentStreamUrl);
console.log('📊 Status:', error?.error?.code ? `${error.error.code} (${error.error.domain || 'Unknown Domain'})` : 'Unknown Error Code');
console.log('💬 Error Message:', error?.error?.localizedDescription || error?.message || 'Unknown error');
console.log('🔍 Error Type:', error?.error?.domain || 'Unknown');
console.log('📋 Full Error Object:', JSON.stringify(error, null, 2));
console.log('⏰ Error Time:', new Date().toISOString());
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
logger.error('AndroidVideoPlayer error: ', error);
// Early return if component is unmounted to prevent iOS crashes
@ -1046,6 +1068,24 @@ const AndroidVideoPlayer: React.FC = () => {
}
}, [pendingSeek, isPlayerReady, isVideoLoaded, duration]);
// HTTP stream testing with logging
useEffect(() => {
if (currentStreamUrl && currentStreamUrl.trim() !== '') {
const testStream = async () => {
try {
console.log('\n🔍 [AndroidVideoPlayer] Testing video stream URL...');
const isValid = await testVideoStreamUrl(currentStreamUrl, headers || {});
console.log(`✅ [AndroidVideoPlayer] Stream test result: ${isValid ? 'VALID' : 'INVALID'}`);
} catch (error) {
console.log('❌ [AndroidVideoPlayer] Stream test failed:', error);
}
};
// Test the stream URL when it changes
testStream();
}
}, [currentStreamUrl, headers]);
const handleSelectStream = async (newStream: any) => {
if (newStream.url === currentStreamUrl) {
setShowSourcesModal(false);
@ -1247,7 +1287,16 @@ const AndroidVideoPlayer: React.FC = () => {
headers: headers
} : { uri: currentStreamUrl };
console.log('[AndroidVideoPlayer] FORCEFULLY using headers from route params:', headers);
// Enhanced HTTP request logging
console.log('\n🌐 [AndroidVideoPlayer] HTTP REQUEST DETAILS:');
console.log('📍 URL:', currentStreamUrl);
console.log('🔧 Method: GET (Video Stream)');
console.log('📋 Headers:', headers ? JSON.stringify(headers, null, 2) : 'No headers');
console.log('🎬 Stream Provider:', currentStreamProvider || 'Unknown');
console.log('📺 Stream Name:', currentStreamName || 'Unknown');
console.log('🎯 Quality:', currentQuality || 'Unknown');
console.log('⏰ Timestamp:', new Date().toISOString());
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
return sourceWithHeaders;
})()}

View file

@ -567,6 +567,7 @@ const VideoPlayer: React.FC = () => {
const onLoad = (data: any) => {
try {
if (DEBUG_MODE) {
logger.log('[VideoPlayer] Video loaded:', data);
}
@ -796,6 +797,16 @@ const VideoPlayer: React.FC = () => {
};
const handleError = (error: any) => {
// Enhanced HTTP error response logging
console.log('\n❌ [VideoPlayer] HTTP RESPONSE ERROR:');
console.log('📍 URL:', currentStreamUrl);
console.log('📊 Status:', error?.error?.code ? `${error.error.code} (${error.error.domain || 'Unknown Domain'})` : 'Unknown Error Code');
console.log('💬 Error Message:', error?.error?.localizedDescription || error?.message || 'Unknown error');
console.log('🔍 Error Type:', error?.error?.domain || 'Unknown');
console.log('📋 Full Error Object:', JSON.stringify(error, null, 2));
console.log('⏰ Error Time:', new Date().toISOString());
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
logger.error('[VideoPlayer] Playback Error:', error);
// Format error details for user display
@ -1270,7 +1281,16 @@ const VideoPlayer: React.FC = () => {
headers: headers
} : { uri: currentStreamUrl };
console.log('[VideoPlayer] FORCEFULLY using headers from route params:', headers);
// Enhanced HTTP request logging
console.log('\n🌐 [VideoPlayer] HTTP REQUEST DETAILS:');
console.log('📍 URL:', currentStreamUrl);
console.log('🔧 Method: GET (Video Stream)');
console.log('📋 Headers:', headers ? JSON.stringify(headers, null, 2) : 'No headers');
console.log('🎬 Stream Provider:', currentStreamProvider || streamProvider || 'Unknown');
console.log('📺 Stream Name:', currentStreamName || streamName || 'Unknown');
console.log('🎯 Quality:', currentQuality || quality || 'Unknown');
console.log('⏰ Timestamp:', new Date().toISOString());
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
return sourceWithHeaders;
})()}

View file

@ -0,0 +1,71 @@
import { logger } from './logger';
// Enhanced HTTP logging function specifically for AndroidVideoPlayer
export const logHttpRequest = async (url: string, options: RequestInit = {}): Promise<Response> => {
const method = options.method || 'GET';
const headers = options.headers || {};
// Log HTTP request
console.log('\n🌐 [AndroidVideoPlayer] HTTP REQUEST:');
console.log('📍 URL:', url);
console.log('🔧 Method:', method);
console.log('📋 Headers:', JSON.stringify(headers, null, 2));
console.log('⏰ Request Time:', new Date().toISOString());
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
const startTime = Date.now();
try {
// Make the actual request
const response = await fetch(url, options);
const endTime = Date.now();
const duration = endTime - startTime;
// Log HTTP response success
console.log('\n✅ [AndroidVideoPlayer] HTTP RESPONSE SUCCESS:');
console.log('📍 URL:', url);
console.log('📊 Status:', `${response.status} ${response.statusText}`);
console.log('📋 Response Headers:', JSON.stringify(Object.fromEntries(response.headers.entries()), null, 2));
console.log('⏱️ Duration:', `${duration}ms`);
console.log('📦 Content-Type:', response.headers.get('content-type') || 'Unknown');
console.log('📏 Content-Length:', response.headers.get('content-length') || 'Unknown');
console.log('🔒 CORS:', response.headers.get('access-control-allow-origin') || 'Not specified');
console.log('⏰ Response Time:', new Date().toISOString());
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
return response;
} catch (error: any) {
const endTime = Date.now();
const duration = endTime - startTime;
// Log HTTP response error
console.log('\n❌ [AndroidVideoPlayer] HTTP RESPONSE ERROR:');
console.log('📍 URL:', url);
console.log('📊 Status: Network Error');
console.log('💬 Error Message:', error.message || 'Unknown error');
console.log('🔍 Error Type:', error.name || 'Unknown');
console.log('⏱️ Duration:', `${duration}ms`);
console.log('📋 Full Error:', JSON.stringify(error, null, 2));
console.log('⏰ Error Time:', new Date().toISOString());
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
throw error;
}
};
// Test function to validate video stream URLs with HTTP logging
export const testVideoStreamUrl = async (url: string, headers: Record<string, string> = {}): Promise<boolean> => {
try {
const response = await logHttpRequest(url, {
method: 'HEAD',
headers: {
'Range': 'bytes=0-1',
...headers
}
});
return response.ok || response.status === 206; // 206 for partial content
} catch (error) {
return false;
}
};