fix: make the preview stage visible to session replay - #37
Draft
posthog[bot] wants to merge 1 commit into
Draft
Conversation
The preview canvas is handed to a worker with transferControlToOffscreen(), so its pixels never live on the main thread and session replay (rrweb) records the editor stage blank. Every editor recording looked like media rendered as empty/purple placeholder boxes, which sent Replay Vision scanners chasing a render bug that does not exist. Mirror the canvas into a DOM <img> that replay can record: a new useCanvasReplaySnapshot hook draws the current frame through the worker's existing captureThumbnail into a low-rate JPEG data URL. The image sits behind the live canvas, which clears to opaque black, so the user keeps seeing the live preview while replay (which reconstructs the canvas without pixels) shows the snapshot. Capture is skipped while unchanged and during playback to keep it off the live render path. Also fix a real image-render race in preview-panel: image textures were flagged uploaded before the fire-and-forget uploadBitmap resolved, and img.onload never asked for a re-render, so a freshly decoded image could fail to appear until an unrelated edit. Await the upload before flagging it, and re-render on decode. Generated-By: PostHog Desktop Task-Id: e9cb72a8-4128-4b8e-98b0-49a9a3c0cf04
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
<canvas>is handed to a worker withtransferControlToOffscreen(), so its pixels never live on the main thread. Session replay (rrweb) can only record main-thread DOM, so it captures the editor stage blank, with just the#8b5cf6transform overlay on top — which reads exactly like "imported media renders as purple placeholder boxes".captureCanvasalone would not help: rrweb instruments the canvas element's own context, and an offscreen-transferred canvas no longer has one on the main thread.Changes
<img>replay can record. A newuseCanvasReplaySnapshothook draws the current frame through the worker's existingcaptureThumbnailinto a low-rate JPEG data URL and writes it to an<img>.bg-backgroundmoved from the<canvas>to its wrapper so the canvas stays transparent-in-replay; visually a no-op live.preview-panel.tsx(unrelated to replay, in the same file):uploadBitmapresolved — a failed upload stayed flagged and never retried. Now the upload is awaited before flagging.img.onloadnever asked for a re-render, so a freshly decoded image could fail to appear until an unrelated edit. It now re-renders the current frame on decode (while paused).Why
Two Replay Vision signals reported imported media never rendering on the stage. The media renders fine — our own recordings just cannot see the canvas, so the "bug" was self-inflicted replay blindness on a core render path.
Test plan
pnpm --filter @tooscut/ui typecheck— no new errors (only the pre-existing missing-WASM module error, present onmainin this environment)oxlint --type-awareandoxfmt --checkclean on changed filespnpm --filter @tooscut/ui testpassescrates/compositorrender_frame→Color::BLACK) so the img is hidden live; the imgsrcis a self-contained data URL that rrweb records verbatim.Agent context
captureCanvas— rejected: does not work for an offscreen-transferred canvas./simplifypass applied the playback-skip guard; skipped a suggested shared-helper extraction (would widen the change intouse-auto-save.ts) and a wrapper-<div>removal (false positive — the wrapper is needed so the<img>aligns to the canvas content box inside thep-3padding).Created with PostHog Desktop from this inbox report.