Skip to content

feat(R3.8): resume + up-next + autoplay + "needs transcode" notice#61

Merged
detain merged 1 commit into
masterfrom
feat/R3-8-resume-upnext-transcode
Jun 2, 2026
Merged

feat(R3.8): resume + up-next + autoplay + "needs transcode" notice#61
detain merged 1 commit into
masterfrom
feat/R3-8-resume-upnext-transcode

Conversation

@detain

@detain detain commented Jun 2, 2026

Copy link
Copy Markdown
Owner

R3.8 — Resume + Up-Next + autoplay + mkv/hevc "needs transcode" notice

The player's three closing moments, extracted from the locked R0 mockup (player-chrome.html:184-197). Part of the R3 player-surface redo; consumers stay pinned to #v0.7.0 until the aligned R6.6 release.

Added

  • ResumePrompt.vue — on-open glass prompt ("Resume from {time}" / "Start over") shown when the persisted resume map holds an in-band (30s–95%) position for the current media. Resume seeks to the stored second (deferred to loadedmetadata when the duration isn't known yet) + plays; Start over seeks 0 + clearResume + plays. Auto-dismisses once playback begins.
  • UpNext.vue — end-of-video card (poster thumb, "Up next" eyebrow, title, amber depleting countdown ring). On ended with a queued item it counts down 8s and auto-advances via usePlayerStore.next(...) when prefs.autoplay is on; static card with a manual Play now (+ Cancel) when off.
  • TranscodeNotice.vue — opaque role=alert notice that replaces the silent black frame when a file can't direct-play: detected proactively by container extension (mkv/avi/wmv/ts/… on the stream URL or the library path) and reactively on a fatal <video> error (decode / src-not-supported). Center play + controls are suppressed under it.
  • playback.ts — pure, DOM-free helpers: extensionOf, needsTranscode, isFatalMediaError, ringDashoffset + the up-next / ring constants.
  • Player.vue: new optional streamUrlFor prop + play-next(media) emit; resume + transcode state is initialized synchronously in setup() (no first-frame black flash). New components + helpers exported.

Fixed

  • usePlayerStore.next(resolveStreamUrl?) now threads a fresh stream URL into setCurrent (or clears it to '' when unresolved), so advancing the queue no longer leaves the previous item's streamUrl behind (the R3.7-noted stale-URL bug).

Review

Reviewer subagent → 3 LOW findings. #1 (real bug: replaying a just-ended video let the countdown advance the queue mid-replay) fixed — the playing watch now cancels the up-next too, with a new test. #2 accepted (forward-note for R3.9). #3 fixed (loading="lazy" on the up-next thumb). Re-verify: NO NEW FINDINGS.

Gates

  • vue-tsc --noEmit clean · npm run build (vite 8) clean (dist rebuilt) · vitest run 1315 passing (+52) · components/player 99.6% lines (playback.ts 100%), Player.vue 98.18% lines · overall 97.23% lines · anti-slop clean.

Out of scope (R3.9)

PlayerPage.vue integration: real /media/:id/stream URL resolution + the streamUrlFor resolver wiring, the route-leave→showMiniPlayer() toggle, ambient backdrop, loading/error states.

🤖 Generated with Claude Code

The player's three closing moments, extracted from the locked R0 mockup
(player-chrome.html:184-197):

- ResumePrompt.vue — on-open "Resume from {time}" / "Start over" when the
  persisted resume map holds an in-band (30s–95%) position; Resume seeks
  (deferred to loadedmetadata when duration is unknown) + plays, Start over
  clears + restarts; auto-dismisses once playing.
- UpNext.vue — end-of-video card (poster thumb, amber depleting countdown
  ring) shown on `ended` with a queued item; counts down 8s + auto-advances
  via usePlayerStore.next() when prefs.autoplay is on, static + manual
  Play now when off; Cancel/replay stop it.
- TranscodeNotice.vue — opaque role=alert notice instead of a silent black
  frame when a file can't direct-play (mkv/avi/… by extension on the stream
  URL or library path, or a fatal <video> decode/src error); center +
  controls are suppressed under it.
- playback.ts — pure helpers (extensionOf, needsTranscode, isFatalMediaError,
  ringDashoffset + up-next/ring constants).
- usePlayerStore.next(resolveStreamUrl?) now threads/clears streamUrl so
  advancing the queue never leaves a stale URL (fixes the R3.7 note).
- Player.vue: new optional `streamUrlFor` prop + `play-next` emit; resume +
  transcode state initialized synchronously in setup (no first-frame flash).

1315 vitest passing (+52); components/player 99.6% lines; vue-tsc + vite 8
build clean; anti-slop clean. Consumers stay pinned (R6.6).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@detain detain merged commit b678581 into master Jun 2, 2026
@detain detain deleted the feat/R3-8-resume-upnext-transcode branch June 2, 2026 23:02
detain added a commit that referenced this pull request Jun 4, 2026
The player's three closing moments, extracted from the locked R0 mockup
(player-chrome.html:184-197):

- ResumePrompt.vue — on-open "Resume from {time}" / "Start over" when the
  persisted resume map holds an in-band (30s–95%) position; Resume seeks
  (deferred to loadedmetadata when duration is unknown) + plays, Start over
  clears + restarts; auto-dismisses once playing.
- UpNext.vue — end-of-video card (poster thumb, amber depleting countdown
  ring) shown on `ended` with a queued item; counts down 8s + auto-advances
  via usePlayerStore.next() when prefs.autoplay is on, static + manual
  Play now when off; Cancel/replay stop it.
- TranscodeNotice.vue — opaque role=alert notice instead of a silent black
  frame when a file can't direct-play (mkv/avi/… by extension on the stream
  URL or library path, or a fatal <video> decode/src error); center +
  controls are suppressed under it.
- playback.ts — pure helpers (extensionOf, needsTranscode, isFatalMediaError,
  ringDashoffset + up-next/ring constants).
- usePlayerStore.next(resolveStreamUrl?) now threads/clears streamUrl so
  advancing the queue never leaves a stale URL (fixes the R3.7 note).
- Player.vue: new optional `streamUrlFor` prop + `play-next` emit; resume +
  transcode state initialized synchronously in setup (no first-frame flash).

1315 vitest passing (+52); components/player 99.6% lines; vue-tsc + vite 8
build clean; anti-slop clean. Consumers stay pinned (R6.6).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant