Skip to content

Animate GIFs in the presentation window#55

Merged
boomzero merged 2 commits into
mainfrom
add-animated-gif-presentation
May 15, 2026
Merged

Animate GIFs in the presentation window#55
boomzero merged 2 commits into
mainfrom
add-animated-gif-presentation

Conversation

@boomzero

@boomzero boomzero commented May 15, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds GifAnimationManager (src/renderer/src/lib/gif.ts) — a per-canvas manager that decodes GIF data URLs via gifuct-js after the first paint and ticks frames through a scratch-canvas compositor so transparent patches do not erase prior pixels.
  • Wires the manager into Presentation.svelte: one instance alongside presentationCanvas, reset() at the top of renderSlide, fire-and-forget register() after each static image load, start() after image loads settle (works for one-GIF slides too), dispose() before canvas disposal, and full canvas/state cleanup in the no-slide branch.
  • Editor canvas, GIF slide backgrounds, storage format, DB schema, IPC, and App.svelte are unchanged.

Guardrails (warn-once, fall back to static)

  • 25 MB encoded size cap
  • 4096 px logical-dimension cap
  • 300 frame cap
  • 2 s post-hoc decode wallclock cap (does not interrupt synchronous decode)
  • 64 MB per-canvas memory budget, token-based reservation, reconcile-on-actual
  • Generation guard blocks stale decode/tick mutation after reset()
  • document.visibilityState pauses scheduling; resumes when visible

Test Plan

  • npm run typecheck — clean
  • npm run lint — clean
  • npm test — 131/131 pass (31 new in tests/renderer/lib/gif.test.ts)
  • Manual: editor GIF remains static
  • Manual: presentation GIF animates, including one-GIF slide
  • Manual: slide changes reset timers and stop old playback
  • Manual: clearing presentation state stops timers and clears visuals
  • Manual: page visibility pauses work; resumes on return
  • Manual: transitions capture the current composited frame
  • Manual: oversize / over-budget / malformed GIFs fall back to static without breaking the slide

🤖 Generated with Claude Code

boomzero and others added 2 commits May 15, 2026 18:40
Adds GifAnimationManager (src/renderer/src/lib/gif.ts), a per-canvas
manager that decodes GIF data URLs via gifuct-js after the first paint
and ticks frames through a scratch-canvas compositor so transparent
patches do not erase prior pixels. The editor canvas, GIF backgrounds,
and storage stay unchanged.

Guardrails: 25 MB encoded size cap, 4096 px logical-dimension cap,
300-frame cap, 2 s post-hoc decode wallclock cap, 64 MB per-canvas
memory budget with token-based reservation and reconcile-on-actual.
Decode is gated by document.visibilityState; reset()/dispose() cancel
schedulers, timers, and refund accounting.

Presentation.svelte instantiates one manager next to presentationCanvas,
calls reset() at the top of renderSlide(), registers each GIF image
after its static frame loads, and start()s playback after image loads
settle (including for one-GIF slides). Disposal runs before canvas
disposal. The no-slide branch now also clears canvas state and resets
the manager so stale visuals/timers do not survive a wipe.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Fixes two issues surfaced during QA:

1. The properties panel background preview uses a native <img> tag, so
   browsers animated the GIF in the editor sidebar even though the canvas
   GIF stays static. PropertiesPanel.svelte now detects GIF backgrounds
   and shows the decoded first frame instead, matching the editor canvas.

2. Adds getGifFirstFrameDataUrl(src) in lib/gif.ts — a small async helper
   that parses the GIF, renders frame 0 through a scratch canvas onto a
   composite, and returns a PNG data URL. Results are cached by source so
   repeated previews don't re-decode. Falls back to the original URL on
   any error so the preview never goes blank.

This is a small editor-side affordance; presentation playback is
unchanged. (The plan kept App.svelte and presentation behavior fixed;
this only touches PropertiesPanel preview rendering and the gif module.)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@boomzero boomzero merged commit 12573cf into main May 15, 2026
3 checks passed
@boomzero boomzero deleted the add-animated-gif-presentation branch May 15, 2026 12:56
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