The chapters payload now carries resume_rewind_seconds (server-side per-user setting); the player applies it at two events, each rewinding once from where playback currently sits — never stacked: - open-resume: restorePosition starts the rewind early from the saved spot (percentage and chapter+offset branches, clamped at the book start). Deep links (?loc=) stay exempt — an explicit jump is not a resume. - unpause: a genuine pause→play steps back again (the re-orientation gap). Programmatic plays — post-restore autoplay and track-switch autoplays — set a suppress flag: their play event is the session start the open-rewind already positioned, not an unpause. Math lives in audio-rewind.ts (pure, unit-tested) after the audio-scrubber pattern; payload values gate through the 0/5/10 allow-list so stale or foreign servers degrade to exact resume.
42 lines
1.3 KiB
TypeScript
42 lines
1.3 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import { applyResumeRewind, normalizeResumeRewind } from "./audio-rewind";
|
|
|
|
describe("applyResumeRewind", () => {
|
|
it("steps back by the rewind amount", () => {
|
|
expect(applyResumeRewind(754, 5)).toBe(749);
|
|
expect(applyResumeRewind(754, 10)).toBe(744);
|
|
});
|
|
|
|
it("clamps at the start of the book", () => {
|
|
expect(applyResumeRewind(3, 5)).toBe(0);
|
|
expect(applyResumeRewind(0, 10)).toBe(0);
|
|
});
|
|
|
|
it("treats rewind 0 (setting off) as exact resume", () => {
|
|
expect(applyResumeRewind(754, 0)).toBe(754);
|
|
});
|
|
|
|
it("tolerates non-finite input", () => {
|
|
expect(applyResumeRewind(Number.NaN, 5)).toBe(0);
|
|
expect(applyResumeRewind(754, Number.NaN)).toBe(754);
|
|
expect(applyResumeRewind(Number.POSITIVE_INFINITY, 5)).toBe(0);
|
|
});
|
|
});
|
|
|
|
describe("normalizeResumeRewind", () => {
|
|
it("passes the allow-listed amounts", () => {
|
|
expect(normalizeResumeRewind(0)).toBe(0);
|
|
expect(normalizeResumeRewind(5)).toBe(5);
|
|
expect(normalizeResumeRewind(10)).toBe(10);
|
|
});
|
|
|
|
it("maps anything else to off", () => {
|
|
expect(normalizeResumeRewind(7)).toBe(0);
|
|
expect(normalizeResumeRewind(-5)).toBe(0);
|
|
expect(normalizeResumeRewind("12")).toBe(0);
|
|
expect(normalizeResumeRewind(undefined)).toBe(0);
|
|
expect(normalizeResumeRewind(Number.NaN)).toBe(0);
|
|
});
|
|
});
|