Image viewer: a copy that cannot be drawn says so, on the image it copied
Summary
The image viewer's Copy button now always gives an answer, and that answer only shows on the image it copied. This follows up a review of #18200.
- No silent hang: Copy draws the image to a canvas, then hands the PNG to the clipboard as a promise. If drawing threw, that promise never settled, so the button never said anything. That happens on a tainted canvas, for example an SVG with HTML inside. Now a draw that throws, a canvas with no 2D context, or an image with no size fails the copy, and the button says "Couldn't copy image".
- No blank copy: an image with no size used to be copied as a blank 1x1 PNG, reported as "Copied". It now fails instead.
- Right image: if you copy an image, then step to the next one before the copy finishes, the result no longer shows on the new image.
Follows #18200 (the image viewer), which landed as f2eb10ffe91.
Testing
- Red commit 4672c0ff1ae. Tests run in
webviews/on the local machine.bun test src/agent-session/acpmux/conversation/clipboard.test.ts: 1 pass, 1 fail at the red commit (the draw error escaped instead of failing the copy); 2 pass after the fix.bun test src/agent-session/acpmux/conversation/imageViewer.test.tsx: 11 pass, 1 fail at the red commit (the late result showed "Copied" on the next image); 12 pass after the fix.
bun test src/agent-session/acpmux/conversation test/ui-rules.test.ts test/gallery-coverage.test.ts test/pane-english.test.ts: 194 pass.vp checkpasses on the changed files, and the typecheck passes on all 1023 files.
Changelog
none (the image viewer has not shipped yet; #18200 carries its changelog line)
Proof
No visual change: the button's labels and icons are the ones #18200 added. The tests above cover the behavior.
Checklist
- Behavior changes have added or updated tests, or Testing says why not
- UI, settings, menu, schema, help-text or user-facing docs change: localization audited. No new strings; the change reuses
image.copyFailedandimage.copy.
🤖 Generated with Claude Code
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.
Summary by cubic
The image viewer's Copy button now always answers, and its answer stays on the image it copied.
- A copy that cannot be drawn or encoded (tainted canvas, no 2D context, zero size) fails and shows "Couldn't copy image" instead of hanging; a zero-size image used to be copied as a blank 1x1 PNG and reported "Copied".
- If you step to another image before a copy finishes, the result no longer appears on the new image.
[!NOTE]
Low Risk
Localized clipboard and UI feedback in the unreleased image viewer; no auth or data-path changes.
Overview
Image viewer copy now always resolves and ties success/failure feedback to the image that was copied.
copyImage rejects when the source cannot be turned into a PNG (zero dimensions, missing 2D context, tainted canvas / draw or encode errors) instead of leaving the clipboard promise pending or copying a blank 1×1 PNG as “Copied”. The Copy handler records the clicked src and only updates the button label when that same image is still on screen when the async copy finishes, so stepping to another image before copy completes no longer shows “Copied” on the wrong slide.
Adds unit tests for copyImage failure paths and a viewer test for the late-completion case.
Reviewed by Cursor Bugbot for commit 84e78d77d14d53a32f06a6ae58712a4d4a82b8d5. Bugbot is set up for automated code reviews on this repo. Configure here.