feat(plex): subtitles rise above the control bar while it shows

On an iPad the bar covered the text whenever it was up: the browser places a
native cue by its line, which nothing animates. The track now stays loaded as
hidden and PlexSubtitles draws the active cues, measured against the bar and
lifted above it in 200 ms, back down when it hides. The viewer's size, colour,
background and outline settings style the text directly. Also fixes a test
typing slip from the search pill change.
This commit is contained in:
2026-10-08 02:59:13 +02:00
parent 5db6dc8ee6
commit 75093458c9
8 changed files with 333 additions and 58 deletions
@@ -42,7 +42,6 @@ function mount(qc: QueryClient, { sessionK = 0, abs = 3600, loadStart = 0 } = {}
detail: detail(),
sessionK,
subOffset: 0,
subPos: 88,
restartSession: () => {},
setAudioTrack: () => false,
patchPrefs: () => {},
@@ -316,7 +315,6 @@ function TrackHarness() {
detail: detail(),
sessionK: 0,
subOffset: 0,
subPos: 88,
restartSession: () => {},
setAudioTrack: () => false,
patchPrefs: () => {},
@@ -417,7 +415,6 @@ describe("usePlexTracks — the debounced A/V-offset restart", () => {
detail: detail(),
sessionK: 0,
subOffset: 0,
subPos: 88,
restartSession: (at) => restart(id, at),
setAudioTrack: () => false,
patchPrefs: () => {},
@@ -439,3 +436,35 @@ describe("usePlexTracks — the debounced A/V-offset restart", () => {
expect(restart).not.toHaveBeenCalled();
});
});
// The browser no longer draws the cues: its rendering sat under the control bar on an iPad, and a cue
// placed by `line` cannot move out of the way. The track stays loaded, as `hidden`, for PlexSubtitles.
describe("usePlexTracks — who draws the cues", () => {
it("keeps the mounted track hidden: loaded and tracked, not drawn by the browser", () => {
const track = { mode: "disabled" as TextTrackMode };
const video = document.createElement("video");
Object.defineProperty(video, "textTracks", { value: [track] });
const wrapper = ({ children }: { children: ReactNode }) => (
<QueryClientProvider client={client()}>{children}</QueryClientProvider>
);
const { unmount } = renderHook(
() =>
usePlexTracks({
id: RK,
detail: detail(),
sessionK: 0,
subOffset: 0,
restartSession: () => {},
setAudioTrack: () => false,
patchPrefs: () => {},
videoRef: { current: video },
audioRef: { current: 0 } as RefObject<number | null>,
aoffRef: { current: 0 },
playhead: () => 0,
}),
{ wrapper },
);
expect(track.mode).toBe("hidden");
unmount();
});
});