Skip to content

Feature/template cleanups - #5

Draft
tuj wants to merge 22 commits into
release/3.0.0from
feature/template-cleanups
Draft

Feature/template cleanups#5
tuj wants to merge 22 commits into
release/3.0.0from
feature/template-cleanups

Conversation

@tuj

@tuj tuj commented Jun 2, 2026

Copy link
Copy Markdown

@tuj tuj self-assigned this Jun 2, 2026
tuj added 5 commits August 28, 2026 07:10
useMultipleEntrySlideExecution initialised entryIndex to 0, so showEntry(0)
set a value React bailed out of and consumers could not tell "not started"
from "showing the first entry". slideshow.jsx's [index] effect therefore only
ever fired on mount, anchoring the first image's fade and zoom to mount rather
than to run, and rss.jsx rendered "1 / 5" before the slide started. entryIndex
is now null until cycling starts, and is cleared again when run goes falsy so
a paused slide does not keep a stale entry rendered.

video.jsx called finish() when play() was rejected, which browsers always do
for a sound-enabled (unmuted) video — the slide was dropped instantly instead
of showing controls. The catch now only offers controls; a metadata guard
covers a source that neither loads nor errors, and the duration guard allows a
flat five seconds on top of the 10% overshoot for buffering stalls.

Both hooks assign their refs in a useLayoutEffect rather than during render.

Also updates .claude/skills/add-slide-template/SKILL.md and
.claude/agents/slide-template-reviewer.md, which still taught the deleted
BaseSlideExecution class, and documents its removal in UPGRADE.md for
out-of-tree custom templates.

Replaces the Playwright template-slide-execution spec with vitest unit tests
covering both hooks, including the empty-entries, reset and unmount cases.
Some sources (fragmented WebM, streams) report an infinite duration at
loadedmetadata and only resolve it later. loadedmetadata fires once, so the
duration guard was never installed and the load guard cut the slide mid
playback. Listening for durationchange as well installs the guard whenever a
usable duration appears.

Raises the load guard from 15 to 30 seconds, which the previous value made
tight for a large file over a slow link.
The "before" snippet was wrong in four ways. The real pre-hook shape
constructed the instance during render, called start(duration) rather than
start(), and depended on [run] alone. Restoring it matters because the
render-phase construction is the latent bug the hooks fix — a fresh instance
every render meant cleanup called stop() on an object whose slideTimeout was
already null, so the timer was never cleared. The snippet as written hid that.

The 15000 fallback was also described as parity with the class. It is not: the
fallback was added on this branch, in the same commit that introduced the hook,
and the class was deleted before it ever shipped. What upgraders actually have
passed duration straight to setTimeout, so a missing duration advanced the
slide immediately.

Also records why the video duration guard is installed only once.
@tuj
tuj requested a review from turegjorup August 28, 2026 08:30
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