fix(player): the resume position reaches the playlist page and live search, not just the feed
Deep-review R4. 1630a3df wrote the YT player's stored position into the react-query cache so a
reopen could not rewind it — but only the feed actually read it back:
- Playlists renders from its own undoable copy of the list, re-seeded only when the SET of ids
changes, so the patched position never reached it: close a video at 830 s, reopen it from the
playlist, and it resumed at the old spot and the next checkpoint wrote that over the 830. A detail
with the same membership now rebases its fresh rows into every snapshot, keeping order and undo
history. (The ids-only guard is older than this round; the write that depended on it was new.)
- Live YouTube search results carry the same per-user position and open the same player, but their
cache was never patched. It is now — patched only, never invalidated, since refetching an
API-sourced search page spends 100 quota units.
Tests for what had none: a Playlists harness (PlayerModal stubbed to record its launch props) and a
PlayerModal harness with a fake IFrame API that records where each item is started — the latter pins
that stepping back to an item watched earlier in the same session resumes at THIS session's position.
3 mutations, each red on its assertion.
This commit is contained in:
@@ -152,6 +152,19 @@ describe("patchCachedProgress", () => {
|
||||
expect(after.items[1]?.position_seconds).toBe(12);
|
||||
});
|
||||
|
||||
it("patches a live YouTube search too — its rows open the same player", () => {
|
||||
// Left out, reopening a search result resumed from the position the search was fetched with
|
||||
// (0 for a fresh find) and the next checkpoint wrote that over the stored one.
|
||||
const qc = new QueryClient();
|
||||
const key = qk.ytSearch("melyik szállás", 20);
|
||||
qc.setQueryData(key, { pages: [{ items: [video()], next_cursor: null }], pageParams: [null] });
|
||||
|
||||
patchCachedProgress(qc, new Map([[VID, 830]]));
|
||||
|
||||
const after = qc.getQueryData(key) as { pages: { items: Video[] }[] };
|
||||
expect(after.pages[0]?.items[0]?.position_seconds).toBe(830);
|
||||
});
|
||||
|
||||
it("is a no-op when nothing was stored", () => {
|
||||
const qc = new QueryClient();
|
||||
seedFeed(qc, video());
|
||||
|
||||
@@ -61,7 +61,11 @@ export function patchCachedProgress(qc: QueryClient, positions: Map<string, numb
|
||||
return old;
|
||||
};
|
||||
|
||||
// Prefix keys: every filter combination of the feed, and every playlist detail.
|
||||
// Prefix keys: every filter combination of the feed, every playlist detail, and every live YouTube
|
||||
// search — its rows come from the same projection, carry the same per-user position, and open the
|
||||
// same player, so leaving it out left the rewind in place on that surface. (Patched, never
|
||||
// invalidated: a refetch of an API-sourced search page spends 100 quota units.)
|
||||
qc.setQueriesData<Cached>({ queryKey: qk.feed() }, patch);
|
||||
qc.setQueriesData<Cached>({ queryKey: qk.playlist() }, patch);
|
||||
qc.setQueriesData<Cached>({ queryKey: qk.ytSearch() }, patch);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user