fix: subtitles no longer depend on the Settings preference

Verified in the running app: captions render on a downloaded video and
on a stream, and the player's menu lists them under SUBTITLES beside
AUDIO.

Three things were wrong.

The preference decided whether subtitles were fetched at all, so "Off"
— the old default, which nobody had to choose — silently emptied the
subtitle menu as well. Fetching now happens regardless; the preference
only says which language switches itself on.

Choosing a track from the menu moved the preference from "off" to that
language, which re-ran the fetch, tore down the tracks and stalled the
stream mid-play. The fetch keys on the language it would ask for, not
on the preference, and that value does not change when "off" becomes
the language it already stood for.

The preference was re-applied on every poll of the track list, so a
choice made in the menu was undone a second later. It now applies once
per set of tracks, which also makes "Off" mean off.

Anyone still carrying the old "off" default is moved to English once.
An Off chosen deliberately after this is left alone.
This commit is contained in:
vincent
2026-08-29 16:46:34 +02:00
parent 967bcdde93
commit 62110b28fc
5 changed files with 76 additions and 62 deletions
+7
View File
@@ -80,6 +80,8 @@ export default function PlayerControls({
const [subs, setSubs] = useState<TextTrack[]>([]);
const [, bump] = useState(0);
const menuRef = useRef<HTMLDivElement>(null);
// How many text tracks the preference was last applied to.
const applied = useRef(-1);
// Tracks arrive with the manifest, after metadata rather than on mount.
useEffect(() => {
@@ -94,8 +96,13 @@ export default function PlayerControls({
// Subtitles follow the language chosen in Settings and nothing else.
// WebKit will otherwise switch on whatever matches the system language,
// which is the same unwanted auto-selection as a dubbed audio track.
// Applied once per set of tracks. Re-applying on every poll would undo a
// choice made in the menu a second after it was made.
applied.current = -1;
const applyPreference = () => {
const tracks = Array.from(v.textTracks);
if (tracks.length === applied.current) return;
applied.current = tracks.length;
const wanted =
subLang === "off"
? undefined