From 33d13c74d3b1b20bfecbf6ae8a03e55ce203ab85 Mon Sep 17 00:00:00 2001 From: tapframe Date: Thu, 30 Oct 2025 18:33:57 +0530 Subject: [PATCH] playback control optimization --- src/components/player/AndroidVideoPlayer.tsx | 28 ++++++++++++++++++-- src/components/player/KSPlayerCore.tsx | 27 +++++++++++++++++-- src/screens/StreamsScreen.tsx | 6 ++--- src/services/stremioService.ts | 19 +++++++------ 4 files changed, 65 insertions(+), 15 deletions(-) diff --git a/src/components/player/AndroidVideoPlayer.tsx b/src/components/player/AndroidVideoPlayer.tsx index fdb8f83e..77436517 100644 --- a/src/components/player/AndroidVideoPlayer.tsx +++ b/src/components/player/AndroidVideoPlayer.tsx @@ -786,15 +786,37 @@ const AndroidVideoPlayer: React.FC = () => { } }, [isSpeedBoosted, playbackSpeed, holdToSpeedEnabled, holdToSpeedValue, speedActivatedOverlayOpacity]); - const onLongPressEnd = useCallback(() => { + const restoreSpeedSafely = useCallback(() => { if (isSpeedBoosted) { setPlaybackSpeed(originalSpeed); setIsSpeedBoosted(false); - logger.log('[AndroidVideoPlayer] Speed boost deactivated, restored to:', originalSpeed); } }, [isSpeedBoosted, originalSpeed]); + const onLongPressEnd = useCallback(() => { + restoreSpeedSafely(); + }, [restoreSpeedSafely]); + + const onLongPressStateChange = useCallback((event: LongPressGestureHandlerGestureEvent) => { + // Fallback: ensure we restore on cancel/fail transitions as well + // @ts-ignore - event.nativeEvent.state uses numeric State enum + const state = event?.nativeEvent?.state; + if (state === State.CANCELLED || state === State.FAILED || state === State.END) { + restoreSpeedSafely(); + } + }, [restoreSpeedSafely]); + + // Safety: if component unmounts while boosted, restore speed + useEffect(() => { + return () => { + if (isSpeedBoosted) { + // best-effort restoration on unmount + try { setPlaybackSpeed(originalSpeed); } catch {} + } + }; + }, [isSpeedBoosted, originalSpeed]); + const resetZoom = () => { const targetZoom = is16by9Content ? 1.1 : 1; setZoomScale(targetZoom); @@ -3147,6 +3169,7 @@ const AndroidVideoPlayer: React.FC = () => { { { } }, [isSpeedBoosted, playbackSpeed, holdToSpeedEnabled, holdToSpeedValue, speedActivatedOverlayOpacity]); - const onLongPressEnd = useCallback(() => { + const restoreSpeedSafely = useCallback(() => { if (isSpeedBoosted) { setPlaybackSpeed(originalSpeed); setIsSpeedBoosted(false); - logger.log('[KSPlayerCore] Speed boost deactivated, restored to:', originalSpeed); } }, [isSpeedBoosted, originalSpeed]); + const onLongPressEnd = useCallback(() => { + restoreSpeedSafely(); + }, [restoreSpeedSafely]); + + const onLongPressStateChange = useCallback((event: LongPressGestureHandlerGestureEvent) => { + // Ensure restoration on cancel/fail/end as well + // @ts-ignore - numeric State enum + const state = event?.nativeEvent?.state; + if (state === State.CANCELLED || state === State.FAILED || state === State.END) { + restoreSpeedSafely(); + } + }, [restoreSpeedSafely]); + + // Safety: restore speed on unmount if still boosted + useEffect(() => { + return () => { + if (isSpeedBoosted) { + try { setPlaybackSpeed(originalSpeed); } catch {} + } + }; + }, [isSpeedBoosted, originalSpeed]); + useEffect(() => { if (videoAspectRatio && effectiveDimensions.width > 0 && effectiveDimensions.height > 0) { const styles = calculateVideoStyles( @@ -2535,6 +2556,7 @@ const KSPlayerCore: React.FC = () => { { { try { if (stream.url) { // Block magnet links - not supported yet - if (stream.url.startsWith('magnet:')) { + if (typeof stream.url === 'string' && stream.url.startsWith('magnet:')) { try { openAlert('Not supported', 'Torrent streaming is not supported yet.'); } catch (_e) {} @@ -1032,7 +1032,7 @@ export const StreamsScreen = () => { if (__DEV__) console.log('Opening stream with Android native app chooser'); // For Android, determine if the URL is a direct http/https URL or a magnet link - const isMagnet = stream.url.startsWith('magnet:'); + const isMagnet = typeof stream.url === 'string' && stream.url.startsWith('magnet:'); if (isMagnet) { // For magnet links, open directly which will trigger the torrent app chooser @@ -1884,7 +1884,7 @@ export const StreamsScreen = () => { )} - {metadata?.videos && metadata.videos.length > 1 && selectedEpisode && ( +{currentEpisode && (