From 26957b5ca7cf2e6f52cd1fdaeaf6670ebe9fc5de Mon Sep 17 00:00:00 2001 From: Botzy Date: Thu, 30 Jul 2026 16:57:25 +0300 Subject: [PATCH 1/3] fix: reset subs when next episode is loaded --- src/routes/Player/useSubtitles.ts | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/routes/Player/useSubtitles.ts b/src/routes/Player/useSubtitles.ts index 16a6f2a57..80cc6f974 100644 --- a/src/routes/Player/useSubtitles.ts +++ b/src/routes/Player/useSubtitles.ts @@ -1,6 +1,6 @@ // Copyright (C) 2017-2026 Smart code 203358507 -import { useCallback, useEffect, useMemo, useRef } from 'react'; +import { useCallback, useLayoutEffect, useEffect, useMemo, useRef } from 'react'; import { useTranslation } from 'react-i18next'; import { CONSTANTS, languages, onFileDrop, onShortcut, useToast } from 'stremio/common'; @@ -51,10 +51,23 @@ const useSubtitles = ({ const settingsRef = useRef(settings); const defaultTrackSelected = useRef(false); const lastSelectedTrack = useRef(null); + const appliedForStream = useRef<{ embeddedId: string | null; extraId: string | null }>({ embeddedId: null, extraId: null }); + const lastStreamKey = useRef(null); videoRef.current = video; settingsRef.current = settings; + const streamKey = video.state.stream?.url ?? video.state.stream?.ytId ?? null; + + useLayoutEffect(() => { + if (streamKey !== null && streamKey !== lastStreamKey.current) { + lastStreamKey.current = streamKey; + defaultTrackSelected.current = false; + lastSelectedTrack.current = null; + appliedForStream.current = { embeddedId: null, extraId: null }; + } + }, [streamKey]); + const streamSubtitles = useMemo(() => { return withFallbackLabels(player.selected?.stream.subtitles); }, [player.selected]); @@ -185,11 +198,10 @@ const useSubtitles = ({ findTrackById(video.state.extraSubtitlesTracks, savedTrackId) : findTrackByLanguage(video.state.extraSubtitlesTracks, savedLanguage ?? settings.subtitlesLanguage); - if (embeddedTrack?.id) { - if (video.state.selectedSubtitlesTrackId !== embeddedTrack.id || - video.state.selectedExtraSubtitlesTrackId !== null) { + if (appliedForStream.current.embeddedId !== embeddedTrack.id) { video.setSubtitlesTrack(embeddedTrack.id); + appliedForStream.current.embeddedId = embeddedTrack.id; } defaultTrackSelected.current = true; @@ -199,8 +211,9 @@ const useSubtitles = ({ if (extraTrack?.id) { // Keep the first external match while waiting for an embedded track. // Add-on subtitle results can arrive in stages and reorder `extraTrack`. - if (video.state.selectedExtraSubtitlesTrackId === null) { + if (appliedForStream.current.extraId === null) { video.setExtraSubtitlesTrack(extraTrack.id); + appliedForStream.current.extraId = extraTrack.id; } if (savedExternalTrack) { @@ -237,11 +250,6 @@ const useSubtitles = ({ } }, [player.streamState, video.state.stream]); - useEffect(() => { - defaultTrackSelected.current = false; - lastSelectedTrack.current = null; - }, [video.state.stream]); - useEffect(() => { if (!hasTracks) { closeSubtitlesMenu(); From 659c6e5542f74d6f14b7e7e5ec42fec922840819 Mon Sep 17 00:00:00 2001 From: Botzy Date: Thu, 30 Jul 2026 16:58:12 +0300 Subject: [PATCH 2/3] fix: reset audio when next episode loads --- src/routes/Player/Player.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 0e1ac9295..346209c02 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -177,6 +177,13 @@ const Player = () => { const nextVideoPopupDismissed = React.useRef(false); const defaultAudioTrackSelected = React.useRef(false); const playingOnExternalDevice = React.useRef(false); + + React.useLayoutEffect(() => { + defaultAudioTrackSelected.current = false; + nextVideoPopupDismissed.current = false; + playingOnExternalDevice.current = false; + }, [video.state.stream]); + const [error, setError] = React.useState(null); const VIDEO_SCALES = ['contain', 'cover', 'fill']; @@ -570,11 +577,6 @@ const Player = () => { } }, [video.state.audioTracks, player.streamState]); - React.useEffect(() => { - defaultAudioTrackSelected.current = false; - nextVideoPopupDismissed.current = false; - playingOnExternalDevice.current = false; - }, [video.state.stream]); React.useEffect(() => { if (!Array.isArray(video.state.audioTracks) || video.state.audioTracks.length === 0) { From d4ca70552d11dded10c3b2bc744785b7fef50059 Mon Sep 17 00:00:00 2001 From: Botzy Date: Fri, 31 Jul 2026 15:45:23 +0300 Subject: [PATCH 3/3] fix: linting --- src/routes/Player/Player.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 346209c02..69ea6a286 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -577,7 +577,6 @@ const Player = () => { } }, [video.state.audioTracks, player.streamState]); - React.useEffect(() => { if (!Array.isArray(video.state.audioTracks) || video.state.audioTracks.length === 0) { closeAudioMenu();