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
@@ -39,9 +39,13 @@ export const plexAddLabelKey = (c: PlexCard): string =>
const isPlexPlayable = (c: PlexCard): boolean => c.type !== "show";
/** Has a resume point: the click continues it, and "from the start" is a choice. A watched item is
* stored at 0, so it never counts. */
* stored at 0, so it never counts. A show has one when an episode does (`resumable`, the episode its
* click plays): part watched with its next episode untouched, Continue and Restart would be the same
* thing, so it is not "started" here — its in-progress badge says how far it has got. */
export const plexStarted = (c: PlexCard): boolean =>
isPlexPlayable(c) && c.status !== "watched" && (c.position_seconds ?? 0) > 0;
isPlexPlayable(c)
? c.status !== "watched" && (c.position_seconds ?? 0) > 0
: c.resumable === true;
/** `open` is the host menu's own flag (the shelf is fetched only once a menu opened). Returns the
* item builder, `add` for the card's own hover button, and the dialog to render beside the menu
@@ -78,8 +82,7 @@ export function usePlexCardActions(handlers: PlexActionHandlers, open: boolean)
const playable = isPlexPlayable(c);
const isShow = c.type === "show";
const watched = c.status === "watched";
// A show continues where its rollup says it stands, as its card's Continue + Restart do.
const started = isShow ? c.status === "in_progress" : plexStarted(c);
const started = plexStarted(c);
return [
...(play
? [