fix(player): make lockscreen transport reach background audio (DR-097)
Pausing from the lockscreen did nothing while a video's audio played in the background. The handoff starts native ExoPlayer audio and only then tears the WebView <video> down, and that teardown fires a DOM `pause` the frontend reports like any other — leaving html5_playing = Some(false). Transport therefore stayed aimed at the element: the lockscreen pause emitted a ControlCommand into a <video> that no longer existed while the native player carried on. The controller now tracks a background-audio handoff explicitly. Entering one hands transport authority to the native backend and drops the dying element's state/position/media-loaded reports, which also stop flipping the UI to paused and dragging the position backwards. Exiting restores the element as the player. A lockscreen pause also has to survive the return to the foreground: the video used to resume from a snapshot taken at handoff time, undoing the pause on the way back in. shouldResumeOnForeground() lets an explicit `paused` from the player override that snapshot. TRACES: UR-040, UR-005 | DR-052, DR-097
This commit is contained in:
@@ -4,6 +4,7 @@ import {
|
||||
initialHandoffState,
|
||||
shouldEnterBackgroundAudio,
|
||||
shouldExitBackgroundAudio,
|
||||
shouldResumeOnForeground,
|
||||
type BackgroundAudioState,
|
||||
} from "./backgroundAudioHandoff";
|
||||
|
||||
@@ -58,4 +59,27 @@ describe("backgroundAudioHandoff", () => {
|
||||
expect(shouldExitBackgroundAudio(active)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("shouldResumeOnForeground", () => {
|
||||
it("resumes when it was playing and the native audio still is", () => {
|
||||
expect(shouldResumeOnForeground(true, "playing")).toBe(true);
|
||||
});
|
||||
|
||||
it("stays paused when the lockscreen paused the native audio", () => {
|
||||
// The whole point of the lockscreen pause: coming back to the app must not
|
||||
// undo it just because the video was playing when we handed off.
|
||||
expect(shouldResumeOnForeground(true, "paused")).toBe(false);
|
||||
});
|
||||
|
||||
it("stays paused when the video was already paused at handoff", () => {
|
||||
expect(shouldResumeOnForeground(false, "playing")).toBe(false);
|
||||
});
|
||||
|
||||
it("falls back to the captured state when native state is unknown", () => {
|
||||
// Loading/seeking/idle say nothing about intent — the handoff snapshot is
|
||||
// the best evidence we have, so a playing video still resumes.
|
||||
expect(shouldResumeOnForeground(true, "loading")).toBe(true);
|
||||
expect(shouldResumeOnForeground(true, undefined)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user