From cdec19db1f04ea175c4f06fedb971d001d57bb23 Mon Sep 17 00:00:00 2001 From: tapframe Date: Mon, 22 Sep 2025 23:02:01 +0530 Subject: [PATCH] some changes --- ios/Nuvio.xcodeproj/project.pbxproj | 14 +- ios/Nuvio/Info.plist | 192 ++++++------ ios/Nuvio/Nuvio.entitlements | 9 +- ios/Nuvio/NuvioRelease.entitlements | 5 + src/components/player/AndroidVideoPlayer.tsx | 295 ++++++++++++------- 5 files changed, 292 insertions(+), 223 deletions(-) create mode 100644 ios/Nuvio/NuvioRelease.entitlements diff --git a/ios/Nuvio.xcodeproj/project.pbxproj b/ios/Nuvio.xcodeproj/project.pbxproj index 1d25850..baaf2b7 100644 --- a/ios/Nuvio.xcodeproj/project.pbxproj +++ b/ios/Nuvio.xcodeproj/project.pbxproj @@ -430,7 +430,7 @@ ); OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; PRODUCT_BUNDLE_IDENTIFIER = com.nuvio.app; - PRODUCT_NAME = "Nuvio"; + PRODUCT_NAME = Nuvio; SWIFT_OBJC_BRIDGING_HEADER = "Nuvio/Nuvio-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -464,7 +464,7 @@ ); OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.nuvio.app; - PRODUCT_NAME = "Nuvio"; + PRODUCT_NAME = Nuvio; SWIFT_OBJC_BRIDGING_HEADER = "Nuvio/Nuvio-Bridging-Header.h"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -527,10 +527,7 @@ LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\""; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; - OTHER_LDFLAGS = ( - "$(inherited)", - " ", - ); + OTHER_LDFLAGS = "$(inherited) "; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG"; @@ -585,10 +582,7 @@ ); LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\""; MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ( - "$(inherited)", - " ", - ); + OTHER_LDFLAGS = "$(inherited) "; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; USE_HERMES = true; diff --git a/ios/Nuvio/Info.plist b/ios/Nuvio/Info.plist index 543797e..3c8708e 100644 --- a/ios/Nuvio/Info.plist +++ b/ios/Nuvio/Info.plist @@ -1,99 +1,99 @@ - - CADisableMinimumFrameDurationOnPhone - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Nuvio - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - 1.2.0 - CFBundleSignature - ???? - CFBundleURLTypes - - - CFBundleURLSchemes - - nuvio - com.nuvio.app - - - - CFBundleURLSchemes - - exp+nuvio - - - - CFBundleVersion - 16 - LSMinimumSystemVersion - 12.0 - LSRequiresIPhoneOS - - LSSupportsOpeningDocumentsInPlace - - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - - NSBonjourServices - - _http._tcp - - NSLocalNetworkUsageDescription - Allow $(PRODUCT_NAME) to access your local network - NSMicrophoneUsageDescription - This app does not require microphone access. - RCTRootViewBackgroundColor - 4278322180 - UIBackgroundModes - - audio - - UIFileSharingEnabled - - UILaunchStoryboardName - SplashScreen - UIRequiredDeviceCapabilities - - arm64 - - UIRequiresFullScreen - - UIStatusBarStyle - UIStatusBarStyleDefault - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIUserInterfaceStyle - Dark - UIViewControllerBasedStatusBarAppearance - - - \ No newline at end of file + + CADisableMinimumFrameDurationOnPhone + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Nuvio + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.2.0 + CFBundleSignature + ???? + CFBundleURLTypes + + + CFBundleURLSchemes + + nuvio + com.nuvio.app + + + + CFBundleURLSchemes + + exp+nuvio + + + + CFBundleVersion + 15 + LSMinimumSystemVersion + 12.0 + LSRequiresIPhoneOS + + LSSupportsOpeningDocumentsInPlace + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + NSBonjourServices + + _http._tcp + + NSLocalNetworkUsageDescription + Allow $(PRODUCT_NAME) to access your local network + NSMicrophoneUsageDescription + This app does not require microphone access. + RCTRootViewBackgroundColor + 4278322180 + UIBackgroundModes + + audio + + UIFileSharingEnabled + + UILaunchStoryboardName + SplashScreen + UIRequiredDeviceCapabilities + + arm64 + + UIRequiresFullScreen + + UIStatusBarStyle + UIStatusBarStyleDefault + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIUserInterfaceStyle + Dark + UIViewControllerBasedStatusBarAppearance + + + diff --git a/ios/Nuvio/Nuvio.entitlements b/ios/Nuvio/Nuvio.entitlements index a0bc443..0c67376 100644 --- a/ios/Nuvio/Nuvio.entitlements +++ b/ios/Nuvio/Nuvio.entitlements @@ -1,10 +1,5 @@ - - aps-environment - development - com.apple.developer.associated-domains - - - \ No newline at end of file + + diff --git a/ios/Nuvio/NuvioRelease.entitlements b/ios/Nuvio/NuvioRelease.entitlements new file mode 100644 index 0000000..0c67376 --- /dev/null +++ b/ios/Nuvio/NuvioRelease.entitlements @@ -0,0 +1,5 @@ + + + + + diff --git a/src/components/player/AndroidVideoPlayer.tsx b/src/components/player/AndroidVideoPlayer.tsx index a8b09b8..ee24732 100644 --- a/src/components/player/AndroidVideoPlayer.tsx +++ b/src/components/player/AndroidVideoPlayer.tsx @@ -231,6 +231,12 @@ const AndroidVideoPlayer: React.FC = () => { const [vlcRestoreTime, setVlcRestoreTime] = useState(undefined); // Time to restore after remount const [forceVlcRemount, setForceVlcRemount] = useState(false); // Force complete unmount/remount + // Debounce track updates to prevent excessive processing + const trackUpdateTimeoutRef = useRef(null); + + // Debounce resize operations to prevent rapid successive clicks + const resizeTimeoutRef = useRef(null); + // Memoize VLC tracks prop to prevent unnecessary re-renders const vlcTracks = useMemo(() => ({ audio: vlcSelectedAudioTrack, @@ -238,8 +244,9 @@ const AndroidVideoPlayer: React.FC = () => { subtitle: vlcSelectedSubtitleTrack }), [vlcSelectedAudioTrack, vlcSelectedSubtitleTrack]); - // Format VLC tracks to match RN Video format + // Format VLC tracks to match RN Video format - optimized version const formatVlcTracks = useCallback((vlcTracks: Array<{id: number, name: string}>) => { + if (!Array.isArray(vlcTracks)) return []; return vlcTracks.map(track => ({ id: track.id, name: track.name || `Track ${track.id + 1}`, @@ -247,18 +254,96 @@ const AndroidVideoPlayer: React.FC = () => { })); }, []); + // Optimized VLC track processing function + const processVlcTracks = useCallback((tracks: any, source: string) => { + if (!tracks) return; + + // Clear any pending updates + if (trackUpdateTimeoutRef.current) { + clearTimeout(trackUpdateTimeoutRef.current); + } + + // Debounce track updates to prevent excessive processing + trackUpdateTimeoutRef.current = setTimeout(() => { + const { audio = [], subtitle = [] } = tracks; + let hasUpdates = false; + + // Process audio tracks + if (Array.isArray(audio) && audio.length > 0) { + const formattedAudio = formatVlcTracks(audio); + if (formattedAudio.length !== vlcAudioTracks.length || + JSON.stringify(formattedAudio) !== JSON.stringify(vlcAudioTracks)) { + setVlcAudioTracks(formattedAudio); + hasUpdates = true; + // Only log in debug mode or when tracks actually change + if (DEBUG_MODE) { + console.log(`🎬 [VLC] ${source} - Audio tracks updated:`, formattedAudio.length); + } + } + } + + // Process subtitle tracks + if (Array.isArray(subtitle) && subtitle.length > 0) { + const formattedSubs = formatVlcTracks(subtitle); + if (formattedSubs.length !== vlcSubtitleTracks.length || + JSON.stringify(formattedSubs) !== JSON.stringify(vlcSubtitleTracks)) { + setVlcSubtitleTracks(formattedSubs); + hasUpdates = true; + if (DEBUG_MODE) { + console.log(`🎬 [VLC] ${source} - Subtitle tracks updated:`, formattedSubs.length); + } + } + } + + // Log summary only if tracks were actually updated + if (hasUpdates && DEBUG_MODE) { + logger.log(`[AndroidVideoPlayer][VLC] ${source} - Track processing complete. Audio: ${vlcAudioTracks.length}, Subs: ${vlcSubtitleTracks.length}`); + } + + trackUpdateTimeoutRef.current = null; + }, 100); // 100ms debounce + }, [formatVlcTracks, vlcAudioTracks, vlcSubtitleTracks]); + // Use VLC tracks directly (they only update when tracks change) const vlcAudioTracksForModal = vlcAudioTracks; const vlcSubtitleTracksForModal = vlcSubtitleTracks; - // Debug: log when VLC tracks change - useEffect(() => { - console.log('🎬 [VLC] vlcAudioTracks changed:', vlcAudioTracks); - }, [vlcAudioTracks]); + // Memoized computed props for child components + const ksAudioTracks = useMemo(() => + useVLC ? vlcAudioTracksForModal : rnVideoAudioTracks, + [useVLC, vlcAudioTracksForModal, rnVideoAudioTracks] + ); + const computedSelectedAudioTrack = useMemo(() => + useVLC + ? (vlcSelectedAudioTrack ?? null) + : (selectedAudioTrack?.type === SelectedTrackType.INDEX && selectedAudioTrack.value !== undefined + ? Number(selectedAudioTrack.value) + : null), + [useVLC, vlcSelectedAudioTrack, selectedAudioTrack] + ); + + const ksTextTracks = useMemo(() => + useVLC ? vlcSubtitleTracksForModal : rnVideoTextTracks, + [useVLC, vlcSubtitleTracksForModal, rnVideoTextTracks] + ); + + const computedSelectedTextTrack = useMemo(() => + useVLC ? (vlcSelectedSubtitleTrack ?? -1) : selectedTextTrack, + [useVLC, vlcSelectedSubtitleTrack, selectedTextTrack] + ); + + // Clean up timeouts on unmount useEffect(() => { - console.log('🎬 [VLC] vlcSubtitleTracks changed:', vlcSubtitleTracks); - }, [vlcSubtitleTracks]); + return () => { + if (trackUpdateTimeoutRef.current) { + clearTimeout(trackUpdateTimeoutRef.current); + } + if (resizeTimeoutRef.current) { + clearTimeout(resizeTimeoutRef.current); + } + }; + }, []); // Reset forceVlcRemount when VLC becomes inactive useEffect(() => { @@ -290,6 +375,40 @@ const AndroidVideoPlayer: React.FC = () => { const [isVideoLoaded, setIsVideoLoaded] = useState(false); const [videoAspectRatio, setVideoAspectRatio] = useState(null); const [is16by9Content, setIs16by9Content] = useState(false); + + const calculateVideoStyles = (videoWidth: number, videoHeight: number, screenWidth: number, screenHeight: number) => { + return { + position: 'absolute', + top: 0, + left: 0, + width: screenWidth, + height: screenHeight, + }; + }; + + // Memoize expensive video style calculations + const videoStyles = useMemo(() => { + if (videoAspectRatio && screenDimensions.width > 0 && screenDimensions.height > 0) { + return calculateVideoStyles( + videoAspectRatio * 1000, + 1000, + screenDimensions.width, + screenDimensions.height + ); + } + return {}; + }, [videoAspectRatio, screenDimensions.width, screenDimensions.height]); + + // Memoize zoom factor calculations to prevent expensive recalculations + const zoomFactor = useMemo(() => { + if (resizeMode === 'cover' && videoAspectRatio && screenDimensions.width > 0 && screenDimensions.height > 0) { + const screenAspect = screenDimensions.width / screenDimensions.height; + return Math.max(screenAspect / videoAspectRatio, videoAspectRatio / screenAspect); + } else if (resizeMode === 'none') { + return 1; + } + return 1; // Default for other modes + }, [resizeMode, videoAspectRatio, screenDimensions.width, screenDimensions.height]); const [customVideoStyles, setCustomVideoStyles] = useState({}); const [zoomScale, setZoomScale] = useState(1); const [zoomTranslateX, setZoomTranslateX] = useState(0); @@ -479,7 +598,7 @@ const AndroidVideoPlayer: React.FC = () => { }, [metadata]); // Resolve current episode description for series - const currentEpisodeDescription = (() => { + const currentEpisodeDescription = useMemo(() => { try { if ((type as any) !== 'series') return ''; const allEpisodes = Object.values(groupedEpisodes || {}).flat() as any[]; @@ -495,7 +614,7 @@ const AndroidVideoPlayer: React.FC = () => { } catch { return ''; } - })(); + }, [type, groupedEpisodes, episodeId, season, episode]); // Find next episode for series const nextEpisode = useMemo(() => { @@ -538,15 +657,6 @@ const AndroidVideoPlayer: React.FC = () => { }).start(() => setShowControls(false)); }; - const calculateVideoStyles = (videoWidth: number, videoHeight: number, screenWidth: number, screenHeight: number) => { - return { - position: 'absolute', - top: 0, - left: 0, - width: screenWidth, - height: screenHeight, - }; - }; const onPinchGestureEvent = (event: PinchGestureHandlerGestureEvent) => { const { scale } = event.nativeEvent; @@ -677,34 +787,15 @@ const AndroidVideoPlayer: React.FC = () => { } }; + // Apply memoized calculations to state useEffect(() => { - if (videoAspectRatio && screenDimensions.width > 0 && screenDimensions.height > 0) { - const styles = calculateVideoStyles( - videoAspectRatio * 1000, - 1000, - screenDimensions.width, - screenDimensions.height - ); - setCustomVideoStyles(styles); + setCustomVideoStyles(videoStyles); + setZoomScale(zoomFactor); - // Recalculate zoom for cover mode when video aspect ratio changes - if (resizeMode === 'cover') { - const screenAspect = screenDimensions.width / screenDimensions.height; - const zoomFactor = Math.max(screenAspect / videoAspectRatio, videoAspectRatio / screenAspect); - setZoomScale(zoomFactor); - if (DEBUG_MODE) { - logger.log(`[AndroidVideoPlayer] Cover zoom updated: ${zoomFactor.toFixed(2)}x (video AR: ${videoAspectRatio.toFixed(2)})`); - } - } else if (resizeMode === 'none') { - // Ensure none mode has no zoom - setZoomScale(1); - } - - if (DEBUG_MODE) { - if (__DEV__) logger.log(`[AndroidVideoPlayer] Screen dimensions changed, recalculated styles:`, styles); - } + if (DEBUG_MODE && resizeMode === 'cover') { + logger.log(`[AndroidVideoPlayer] Cover zoom updated: ${zoomFactor.toFixed(2)}x (video AR: ${videoAspectRatio?.toFixed(2)})`); } - }, [screenDimensions, videoAspectRatio, resizeMode]); + }, [videoStyles, zoomFactor, resizeMode, videoAspectRatio]); useEffect(() => { const subscription = Dimensions.addEventListener('change', ({ screen }) => { @@ -1063,15 +1154,15 @@ const AndroidVideoPlayer: React.FC = () => { }; // Slider callback functions for React Native Community Slider - const handleSliderValueChange = (value: number) => { + const handleSliderValueChange = useCallback((value: number) => { if (isDragging && duration > 0) { const seekTime = Math.min(value, duration - END_EPSILON); - + pendingSeekValue.current = seekTime; } - }; + }, [isDragging, duration]); - const handleSlidingStart = () => { + const handleSlidingStart = useCallback(() => { setIsDragging(true); // Keep controls visible while dragging and cancel any hide timeout if (!showControls) setShowControls(true); @@ -1085,9 +1176,9 @@ const AndroidVideoPlayer: React.FC = () => { if (!paused) setPaused(true); logger.log('[AndroidVideoPlayer] handleSlidingStart: pausing for iOS drag'); } - }; + }, [showControls, paused]); - const handleSlidingComplete = (value: number) => { + const handleSlidingComplete = useCallback((value: number) => { setIsDragging(false); if (duration > 0) { const seekTime = Math.min(value, duration - END_EPSILON); @@ -1108,7 +1199,7 @@ const AndroidVideoPlayer: React.FC = () => { // Ensure controls are visible, then schedule auto-hide if (!showControls) setShowControls(true); controlsTimeout.current = setTimeout(hideControls, 5000); - }; + }, [duration, showControls]); // Ensure auto-hide resumes after drag ends useEffect(() => { @@ -1367,12 +1458,19 @@ const AndroidVideoPlayer: React.FC = () => { } }; - const skip = (seconds: number) => { + const skip = useCallback((seconds: number) => { const newTime = Math.max(0, Math.min(currentTime + seconds, duration - END_EPSILON)); seekToTime(newTime); - }; + }, [currentTime, duration]); - const cycleAspectRatio = () => { + const cycleAspectRatio = useCallback(() => { + // Prevent rapid successive resize operations + if (resizeTimeoutRef.current) { + if (DEBUG_MODE) { + logger.log('[AndroidVideoPlayer] Resize operation debounced - ignoring rapid click'); + } + return; + } // Cycle through allowed resize modes per platform // Android: exclude 'contain' for both VLC and RN Video (not well supported) let resizeModes: ResizeModeType[]; @@ -1414,7 +1512,12 @@ const AndroidVideoPlayer: React.FC = () => { if (DEBUG_MODE) { logger.log(`[AndroidVideoPlayer] Resize mode changed to: ${newResizeMode}`); } - }; + + // Debounce for 300ms to prevent rapid successive operations + resizeTimeoutRef.current = setTimeout(() => { + resizeTimeoutRef.current = null; + }, 300); + }, [resizeMode]); const enableImmersiveMode = () => { StatusBar.setHidden(true, 'none'); @@ -1439,7 +1542,7 @@ const AndroidVideoPlayer: React.FC = () => { } }; - const handleClose = async () => { + const handleClose = useCallback(async () => { // Prevent multiple close attempts if (isSyncingBeforeClose) { logger.log('[AndroidVideoPlayer] Close already in progress, ignoring duplicate call'); @@ -1515,7 +1618,7 @@ const AndroidVideoPlayer: React.FC = () => { // Start background sync without blocking UI backgroundSync(); - }; + }, [isSyncingBeforeClose, currentTime, duration, traktAutosync, navigation, metadata, imdbId, backdrop]); const handleResume = async () => { if (resumePosition) { @@ -1831,7 +1934,7 @@ const AndroidVideoPlayer: React.FC = () => { }; // Wrapper function to convert number to SelectedTrack for modal usage - const selectAudioTrackById = (trackId: number) => { + const selectAudioTrackById = useCallback((trackId: number) => { if (useVLC) { // For VLC, directly set the selected track selectVlcAudioTrack(trackId); @@ -1840,9 +1943,9 @@ const AndroidVideoPlayer: React.FC = () => { const trackSelection: SelectedTrack = { type: SelectedTrackType.INDEX, value: trackId }; selectAudioTrack(trackSelection); } - }; + }, [useVLC, selectVlcAudioTrack, selectAudioTrack]); - const selectTextTrack = (trackId: number) => { + const selectTextTrack = useCallback((trackId: number) => { if (useVLC) { // For VLC, directly set the selected subtitle track and disable custom subtitles if (trackId === -999) { @@ -1866,7 +1969,7 @@ const AndroidVideoPlayer: React.FC = () => { setSelectedTextTrack(trackId); } } - }; + }, [useVLC, selectVlcSubtitleTrack]); const loadSubtitleSize = async () => { try { @@ -2071,7 +2174,7 @@ const AndroidVideoPlayer: React.FC = () => { } }; - const togglePlayback = () => { + const togglePlayback = useCallback(() => { const newPausedState = !paused; if (useVLC && vlcRef.current) { try { @@ -2089,7 +2192,7 @@ const AndroidVideoPlayer: React.FC = () => { if (duration > 0) { traktAutosync.handleProgressUpdate(currentTime, duration, true); } - }; + }, [paused, useVLC, currentTime, duration, traktAutosync]); // Handle next episode button press const handlePlayNextEpisode = useCallback(async () => { @@ -2906,29 +3009,14 @@ const AndroidVideoPlayer: React.FC = () => { autoplay={!paused} onFirstPlay={(info: any) => { try { - console.log('🎬 [VLC] Video loaded, extracting tracks...'); + if (DEBUG_MODE) { + console.log('🎬 [VLC] Video loaded, extracting tracks...'); + } logger.log('[AndroidVideoPlayer][VLC] Video loaded successfully'); - // Extract and format VLC tracks + // Process VLC tracks using optimized function if (info?.tracks) { - const { audio = [], subtitle = [] } = info.tracks; - - // Format audio tracks - if (Array.isArray(audio) && audio.length > 0) { - const formattedAudio = formatVlcTracks(audio); - setVlcAudioTracks(formattedAudio); - console.log('🎬 [VLC] Audio tracks loaded:', formattedAudio.length, formattedAudio); - console.log('🎬 [VLC] Setting vlcAudioTracks state:', formattedAudio); - } else { - console.log('🎬 [VLC] No audio tracks to set'); - } - - // Format subtitle tracks - if (Array.isArray(subtitle) && subtitle.length > 0) { - const formattedSubs = formatVlcTracks(subtitle); - setVlcSubtitleTracks(formattedSubs); - console.log('🎬 [VLC] Subtitle tracks loaded:', formattedSubs.length); - } + processVlcTracks(info.tracks, 'onFirstPlay'); } const lenSec = (info?.length ?? 0) / 1000; @@ -2938,12 +3026,16 @@ const AndroidVideoPlayer: React.FC = () => { // Restore playback position after remount (workaround for surface detach) if (vlcRestoreTime !== undefined && vlcRestoreTime > 0) { - console.log('🎬 [VLC] Restoring playback position:', vlcRestoreTime); + if (DEBUG_MODE) { + console.log('🎬 [VLC] Restoring playback position:', vlcRestoreTime); + } setTimeout(() => { if (vlcRef.current && typeof vlcRef.current.seek === 'function') { const seekPosition = Math.min(vlcRestoreTime / lenSec, 0.999); // Convert to fraction vlcRef.current.seek(seekPosition); - console.log('🎬 [VLC] Seeked to restore position'); + if (DEBUG_MODE) { + console.log('🎬 [VLC] Seeked to restore position'); + } } }, 500); // Small delay to ensure player is ready setVlcRestoreTime(undefined); // Clear restore time @@ -2973,24 +3065,13 @@ const AndroidVideoPlayer: React.FC = () => { }} onESAdded={(tracks: any) => { try { - console.log('🎬 [VLC] ES Added - processing tracks...'); + if (DEBUG_MODE) { + console.log('🎬 [VLC] ES Added - processing tracks...'); + } + // Process VLC tracks using optimized function if (tracks) { - const { audio = [], subtitle = [] } = tracks; - - // Format audio tracks - if (Array.isArray(audio) && audio.length > 0) { - const formattedAudio = formatVlcTracks(audio); - setVlcAudioTracks(formattedAudio); - console.log('🎬 [VLC] ES Added - Audio tracks loaded:', formattedAudio.length); - } - - // Format subtitle tracks - if (Array.isArray(subtitle) && subtitle.length > 0) { - const formattedSubs = formatVlcTracks(subtitle); - setVlcSubtitleTracks(formattedSubs); - console.log('🎬 [VLC] ES Added - Subtitle tracks loaded:', formattedSubs.length); - } + processVlcTracks(tracks, 'onESAdded'); } } catch (e) { console.error('🎬 [VLC] onESAdded error:', e); @@ -3102,8 +3183,8 @@ const AndroidVideoPlayer: React.FC = () => { duration={duration} zoomScale={zoomScale} currentResizeMode={resizeMode} - ksAudioTracks={useVLC ? vlcAudioTracksForModal : rnVideoAudioTracks} - selectedAudioTrack={useVLC ? (vlcSelectedAudioTrack ?? null) : (selectedAudioTrack?.type === SelectedTrackType.INDEX && selectedAudioTrack.value !== undefined ? Number(selectedAudioTrack.value) : null)} + ksAudioTracks={ksAudioTracks} + selectedAudioTrack={computedSelectedAudioTrack} availableStreams={availableStreams} togglePlayback={togglePlayback} skip={skip} @@ -3698,12 +3779,6 @@ const AndroidVideoPlayer: React.FC = () => { <> - {console.log('🎬 [AndroidVideoPlayer] AudioTrackModal props:', { - useVLC, - vlcAudioTracksForModal, - rnVideoAudioTracks, - finalTracks: useVLC ? vlcAudioTracksForModal : rnVideoAudioTracks - })} { isLoadingSubtitles={isLoadingSubtitles} customSubtitles={customSubtitles} availableSubtitles={availableSubtitles} - ksTextTracks={useVLC ? vlcSubtitleTracksForModal : rnVideoTextTracks} - selectedTextTrack={useVLC ? (vlcSelectedSubtitleTrack ?? -1) : selectedTextTrack} + ksTextTracks={ksTextTracks} + selectedTextTrack={computedSelectedTextTrack} useCustomSubtitles={useCustomSubtitles} subtitleSize={subtitleSize} subtitleBackground={subtitleBackground}