fix(player): restore the subtitle sidecar work dropped by the previous commit

The previous commit was assembled from a tree read before 13264e22 landed,
so committing it reverted that commit's changes: the image-based subtitle
filtering in device_profile/types, subtitleTracks and its tests, the
regenerated bindings, and the VideoPlayer menu wiring.

Nothing was lost — the working tree held both changes throughout. This
restores those files to the merged state, leaving both the subtitle fix and
the play-session fix in place.

TRACES: UR-020, UR-004 | DR-176 | UT-168
This commit is contained in:
2026-08-16 10:20:22 +02:00
parent 2d67b0e4f5
commit 5096c01960
9 changed files with 5442 additions and 4416 deletions
@@ -53,6 +53,68 @@ describe("subtitleStreamsOf", () => {
expect(subtitleStreamsOf(null)).toEqual([]);
expect(subtitleStreamsOf(undefined)).toEqual([]);
});
/**
* A subtitle the app cannot draw must not reach the picker. Image-based
* tracks (PGS/DVD/DVB) are bitmaps: the only way to show one is for the server
* to composite it into the video, which this app deliberately never asks for
* (DR-176). Offering it anyway produced the reported symptom's twin — a menu
* entry that selects, ticks, and shows nothing.
*
* The verdict is the backend's (`supportsExternalDelivery`); the codec
* vocabulary behind it stays in Rust.
*
* TRACES: UR-020 | DR-176 | UT-168
*/
it("drops subtitles the backend says it cannot deliver as a sidecar", () => {
const streams: SubtitleStreamLike[] = [
{ index: 2, kind: "subtitle", displayTitle: "English PGS SDH", supportsExternalDelivery: false },
{ index: 3, kind: "subtitle", displayTitle: "English Text SDH", supportsExternalDelivery: true },
];
expect(subtitleStreamsOf(streams).map((s) => s.index)).toEqual([3]);
});
/**
* Only an explicit "no" hides a track. A stream that carries no verdict at all
* predates the field (or came from somewhere that does not set it), and
* hiding those would silently empty the menu for sources that work today.
*
* TRACES: UR-020 | DR-176 | UT-168
*/
it("keeps subtitles that carry no verdict", () => {
const streams: SubtitleStreamLike[] = [
{ index: 2, kind: "subtitle", displayTitle: "English" },
{ index: 3, kind: "subtitle", displayTitle: "French", supportsExternalDelivery: null },
];
expect(subtitleStreamsOf(streams).map((s) => s.index)).toEqual([2, 3]);
});
/**
* The same list feeds the `<track>` children and the native play request, so
* an undeliverable track must not even have its URL fetched — that request is
* the one that 404s, and the sideloaded track it would produce is the dead
* entry all over again.
*
* TRACES: UR-020 | DR-176 | UT-168
*/
it("never resolves a URL for a subtitle it dropped", async () => {
const asked: number[] = [];
const tracks = await resolveSubtitleTracks(
[
{ index: 2, kind: "subtitle", displayTitle: "PGS", supportsExternalDelivery: false },
{ index: 3, kind: "subtitle", displayTitle: "SRT", supportsExternalDelivery: true },
],
async (index) => {
asked.push(index);
return url(index);
},
);
expect(asked).toEqual([3]);
expect(tracks.map((t) => t.streamIndex)).toEqual([3]);
});
});
describe("subtitleTrackLabel", () => {