fix(player): a step onto an unplayable video carries on the way it went

Previous onto an embed-blocked or removed video skipped forward again (the
auto-advance direction), straight back to the item just left. The player now
remembers the direction of the step that reached the item and the videos
YouTube refused this session: an error carries on that way, Previous / Next
pass over known-dead items without loading them, and go dark when only those
are left. A step of your own skips with auto-advance off too.
This commit is contained in:
2026-11-01 01:14:50 +01:00
parent c430558ab3
commit 15a3603513
9 changed files with 225 additions and 59 deletions
+23 -1
View File
@@ -1,5 +1,5 @@
import { describe, it, expect } from "vitest";
import { afterRemoval } from "./playerQueue";
import { afterRemoval, stepIndex } from "./playerQueue";
import type { Video } from "./api";
// "Delete" from inside the player (the owner asked for it: today the only way to drop a video from a
@@ -51,3 +51,25 @@ describe("afterRemoval", () => {
expect(next!.playingId).toBe("a");
});
});
describe("stepIndex", () => {
const q = [v("a"), v("b"), v("c"), v("d")];
const none = new Set<string>();
it("steps to the neighbour that way", () => {
expect(stepIndex(q, 1, 1, none)).toBe(2);
expect(stepIndex(q, 1, -1, none)).toBe(0);
});
it("passes over a video known dead", () => {
expect(stepIndex(q, 3, -1, new Set(["c", "b"]))).toBe(0);
expect(stepIndex(q, 0, 1, new Set(["b"]))).toBe(2);
});
it("is -1 at the end, or when only dead videos are left that way", () => {
expect(stepIndex(q, 3, 1, none)).toBe(-1);
expect(stepIndex(q, 2, -1, new Set(["a", "b"]))).toBe(-1);
});
it("wraps when asked, and never lands on where it started", () => {
expect(stepIndex(q, 3, 1, none, true)).toBe(0);
expect(stepIndex(q, 0, -1, new Set(["d"]), true)).toBe(2);
expect(stepIndex(q, 1, 1, new Set(["a", "c", "d"]), true)).toBe(-1);
});
});