The persisted subtitle preference only ever had an owner behind the default-off
shared web-controls flag, so with the shipping controls it did nothing: Video.js
never read it, ArtPlayer declared the input but never used it, and the HTML5
player only ran a one-shot pass after play() resolved — before hls.js had added
its text tracks. No portal host bound the input at all, so it never reached
Xtream or Stalker pages either.
Extract the source-local track controllers into the adapter-free
WebVideoSourceTracks and have WebVideoSourceControlsBridge wrap it, so both
controls modes apply the preference through the same code. The preference-off
players bind it directly (VjsLegacyTracks for Video.js), and
WebPlayerViewComponent reads the preference from SettingsStore instead of an
input so every host inherits it.
The preference means different things depending on who renders the caption UI:
shared controls stay authoritative for the session, while vendor chrome is
source-default — the preference seeds each new source and is released once the
media reports playing, so the engine own caption menu keeps working. Mode
selection is an optional playbackStarted probe passed to the HLS, native and
Shaka helpers; in that mode the HLS helper deselects the track rather than
hiding it, since subtitleDisplay would silently override the vendor menu.
Closes#1155
Closes 13 runtime-scope Dependabot advisories that Dependabot cannot fix itself:
every vulnerable package here is transitive, so the bot has no lever until each
parent publishes a release widening its own pin.
Overrides added (pinned-source form, matching existing convention):
- @xmldom/xmldom 0.8.11 -> 0.8.13 (5 high) via video.js -> mpd-parser
- fast-uri 3.1.0 -> 3.1.4 (4 high) via electron-conf -> ajv
- js-yaml 4.1.1 -> 4.3.0 (2) via electron-updater
- form-data 4.0.5 -> 4.0.6 (1 high) via axios
- ajv 8.17.1 -> 8.18.0 (1) via electron-conf
Every target stays inside its parent's declared semver range. For xmldom,
fast-uri and js-yaml the newest published version is outside that range
(0.9.x / 4.x / 5.x), so "latest" would have broken them; the new doc
records that constraint.
Deliberately excluded: axios and uuid are direct deps already covered by open
Dependabot PRs (#1251, #1252). undici is labelled runtime scope but every path
to it is build tooling (electron -> @electron/get, @angular/build,
@module-federation/dts-plugin) and it is not in the packaged app.
Reachability: xmldom arrives via video.js -> VHS -> mpd-parser, but the app
routes every .mpd to Shaka, which uses its own DASH parser, so that one is
defence in depth. The genuinely reachable one is js-yaml, which
electron-updater uses to parse latest.yml from releases.
Adds docs/architecture/dependency-security-overrides.md and a .changes note.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>