Repository navigation
Let an image show another image's picture - #276
Conversation
An image element may name the picture it shows (`assetId`); without one, its own id names it, as before. A copy of an image can then be a new element showing its original's picture, with nothing copied or uploaded, and nothing to wait for while the original is still uploading. References, upload placeholders and cleanup all read the picture through collectAssetIdFromElementPayload, so they follow. For builds from before the field, page and strategy snapshots also list each picture under the id of every image showing it, and a whole write that leaves the field out keeps it: an image never changes picture. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Merge Risk: 🔵 Low · up to In an ID-collision case, an older client can show the wrong picture. The change remains mergeable with owner awareness and follow-up on collision prevention. Pre-merge checks |
|
Three gaps for builds and rows from before picture ids: - Image payloads go without assetId to clients that don't ask for it (acceptsPictureIds on the snapshots and applyBatch): such a client keeps no assetId, so a copy would read to it as an unsaved change. - images:getAssetUrl answers for an image's own id with the picture it shows, as old builds ask when a picture's address expires. - A picture from before upload statuses is looked up among its own strategy's rows first: copies keep pictures' ids across strategies, so twenty copies could fill a lookup of every strategy's rows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A placed image's id is also the name of its picture. A copy of an image (cloud "+", copy to page, duplicate) needs a new id, so until now it also needed a new picture entry, and that entry can only point at bytes whose upload has finished. That is why "+" could leave out an image that was still uploading. This PR is the server half of fixing that at the root: an image can name the picture it shows.
What changes
assetId, the picture it shows. Without one, its own id names the picture, exactly as today.collectAssetIdFromElementPayloadreadsassetId ?? id, and references, upload placeholders and cleanup all go through it, so a picture several images show stays alive while any of them does.withPictureAliases). Shipped desktop builds and the live web build look a picture up by the image's own id, so they find it there. This is worked out when the snapshot is read and adds no database rows.assetIdout keeps the stored one (keepPictureId). Old builds rewrite an image's whole payload when it is moved, or brought back with undo, and don't know the field. An image never changes picture.acceptsPictureIds: trueget image payloads withoutassetId, in snapshots and in refused-op results. They keep no such field, so otherwise every copy would read to them as an unsaved change of their own.images:getAssetUrlanswers for an image's own id with the picture it shows. That's how old builds ask when a picture's link expires.assetIdyet. The client half (Find an image's picture by its picture id #277, stacked on this) teaches the app to read it, and the copy PRs start writing it.Ground truth
On dev, with every PR in this stack deployed, I built a web app from
main's client code, standing in for an old build. It opened pages full of copies made by the new code, and showed each copy's picture through the aliases:In the same old build, opening those pages rewrote nothing (every copy stayed at revision 1), and moving a copy kept its picture id on the server.
Tests
convex/pictureId.test.ts:The full Convex suite passes (276 tests).
Astra found the old-build payloads, the address lookup and the legacy lookup in its first review. A second review confirmed the first two fixes and found that my first legacy fix, ten rows per owner, could still be crowded out by failed attempts. Reading by status fixes that, and the test fails on the earlier version.
This changes how the server reads what an image shows, so it's a sync-format change: you look first, and it deploys before anything writes
assetId.ci: convex contract
🤖 Generated with Claude Code