cmux NEXT composer: a pasted screenshot shows its chip in the paste's frame
Summary
Leo, on nightly 3a63d6d: "ME PASTING IT DOESN'T JUST PASTE RIGHT INTO THE COMPOSER IMMEDIATELY".
A pasted screenshot showed no chip until the composer had finished preparing it. useAttachmentIntake awaited intakeFiles before adding the chip, and for a full-screen Retina capture that means:
- decoding it;
- re-encoding it as a PNG at 2000 px (then as JPEG if that's still too big);
- base64-encoding it.
That takes hundreds of milliseconds, in one long task on the main thread.
Now:
- A paste or drop puts a placeholder chip in the strip at once. It's added in the paste's own task, so React draws it before the next paint. An image gets a thumbnail-sized tile with a dimmed picture glyph; any other file gets its name. The chip is marked
aria-busy. - The file is read, scaled and saved in the background. The chip it becomes, or the refusal's note, takes the placeholder's place in the same render.
- A prompt sent meanwhile (Return or the send button) waits. It goes once, when its chips are ready, with them. It never goes to another chat: switching chats drops the held prompt.
- Batches count each other. A second paste during a read leaves room for the first one's chips.
- The chat composer and the New Tab page share all of this (
composer/attachmentIntake.tsx).
Paste to visible chip: before and after
Measured with the repo's interaction-latency harness (bun scripts/latency/run.ts), using a production build in headless Chromium and WebKit on Huge Blue, 7 runs each. The input is the new "paste screenshot" case in test/latency/actions.ts: a 3456×2234 PNG (window chrome, code text and a photo-like patch, a few MB) pasted on the prompt the way WebKit delivers it. The response is the chip in the strip.
| engine | before (d935e42c): work / paint, ms | long tasks | after (bec4608b): work / paint, ms | long tasks |
|---|---|---|---|---|
| Chromium | 248.1 / 259.2 | 7/7 | 6.3 / 9.2 | 0/7 |
| WebKit (the app's engine) | 537.0 / 543.0 | 7/7 | 7.0 / 9.0 | 1/7 |
After the fix, both engines pass the harness's one-frame budget at 60 Hz and 120 Hz. In WebKit, one of 7 runs still had a long task (402 ms max). The CI latency-scoreboard job could not measure this: every dispatched run, base ones included (39222347431, 39218991217), is cancelled at its 20-minute limit.
Testing
webviews/test/composer-paste-instant.test.tsx uses a screenshot whose bytes arrive only when the test releases them:
- the chip is in the strip before anything is read;
- two screenshots show two chips at once;
- a prompt sent during the read goes once, with the image;
- a held prompt never goes to the chat the composer moved to.
Fleet webview suite (cmux-ci run --class light --script scripts/ci/run-webviews-tests.sh):
- Failing test first (d935e42c):
composer-paste-instant.test.tsxfails, because no chip is shown before the read. - With the fix (bec4608b): it passes, across 757 files.
- Other reds: the 5 failing files (check-system-blue, gallery-coverage, hairline-rims, tooltip-rules, ui-rules) fail the same way at the red commit and on base. tooltip-rules now owns
attachmentIntake.tsx, so its existing pasted-text tooltip got atooltip-allowreason, and the file no longer appears in that test's output.
Observed / Not run
- Observed:
- Not run:
- the native app. Pasting in a running cmux NEXT was not tried; the harness drives the same composer in WebKit.
- ⌘Return in the Quick composer while a paste is being read. The held prompt then goes as a plain send, without opening the window. Not covered.
Changelog
Fixed: a pasted or dropped screenshot shows in the composer the moment you paste it, instead of after it is processed.
Agent session: cosmic-gray
🤖 Generated with Claude Code
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Fixes the composer so a pasted or dropped screenshot shows its chip the moment it lands, instead of after the file is read, scaled, and re-encoded. Paste-to-visible-chip latency drops from 248/537 ms (Chromium/WebKit) in one long main-thread task to single-digit milliseconds with no long tasks.
Behavior
- A placeholder chip (thumbnail tile for images, filename otherwise) is added synchronously on paste or drop; the real chip or a refusal note replaces it when the background read finishes.
- A prompt sent while files are still being read waits and goes once, with the chips, when they are ready; switching chats drops the held prompt so it never goes to another chat.
- Batches count each other, so a second paste during a read leaves room for the first batch's chips.
- The chat composer and the New Tab page share this in
composer/attachmentIntake.tsx.