fix(plex): Restart only where an episode has a resume point; the Surprise draw is re-read, not redrawn

Show cards carry resumable (ShowState, from the same rollup) so a part-watched
show whose next episode is untouched offers Play, not a Continue and a Restart
that do the same thing; plexStarted is the one rule for cards and menus. The
Surprise rail's key sits under the discover root: whatever refreshes the rails
re-reads the draw (keep=) with its watch state now, kept past the 5-minute gc,
and only the reshuffle deals. Closing the player refreshes the Discover rails.
A show card's play acts on the last click only, and only where it was made.
This commit is contained in:
2026-10-09 22:01:28 +02:00
parent 5572499b56
commit 6df257d7df
26 changed files with 433 additions and 80 deletions
+7 -3
View File
@@ -49,6 +49,8 @@ export interface PlexCard {
status?: string; // new | watched | hidden
position_seconds?: number;
season_count?: number | null; // show
// show: an unwatched episode holds a resume point (Continue resumes it, Restart replays it)
resumable?: boolean;
season_number?: number | null; // episode
episode_number?: number | null; // episode
show_title?: string | null; // episode (in a mixed playlist)
@@ -626,18 +628,20 @@ export const plexApi = {
if (filters) appendPlexFilters(u, filters);
return req(`/api/plex/discover?${u.toString()}`);
},
// A fresh random sample for the Surprise-me rail — a new draw every call (the ↻ refetch), narrowed by
// the active filters like the other rails. `exclude` is the previous draw: dealt last, not first.
// A fresh random sample for the Surprise-me rail — a new draw every call (the ↻), narrowed by the
// active filters like the other rails. `exclude` is the previous draw: dealt last, not first. `keep`
// asks for no draw at all: those titles again, in that order, with their watch state as it is now.
plexSurprise: (
scope: string,
limit?: number,
filters?: PlexFilters,
lang?: string,
exclude: string[] = [],
{ exclude = [], keep = [] }: { exclude?: string[]; keep?: string[] } = {},
): Promise<{ scope: string; items: PlexCard[] }> => {
const u = new URLSearchParams({ scope });
if (limit) u.set("limit", String(limit));
for (const id of exclude) u.append("exclude", id);
for (const id of keep) u.append("keep", id);
if (lang === "hu") u.set("lang", "hu");
if (filters) appendPlexFilters(u, filters);
return req(`/api/plex/surprise?${u.toString()}`);