* Take screenshots on the web beta, and of cloud strategies anywhere The screenshot button read the open strategy back from the local Hive box after a forced save. Cloud strategies are never in that box, so a screenshot of one silently did nothing, on desktop as well as web. It then wrote the PNG with dart:io, which a browser cannot do, which is why the web beta hid the button behind "desktop-only". The capture now reads the page as it is on the canvas (the editor's live providers, drawings copied so their cached paths stay the editor's), so local and cloud strategies capture the same way and nothing waits on a save or a sync. The PNG goes out through FilePicker.saveFile(bytes:), which writes the chosen file on desktop and downloads it in a browser. Images: the capture renders in its own provider container, which has no live cloud page, upload queue or pending bytes. Before it starts, every image on the page is resolved to what it will paint and handed in through captureImageSourcesProvider: files and in-memory bytes as they are, cloud URLs fetched to bytes (downloadCloudImageBytes, shared with the desktop media cache, including its one signed-URL refresh), and images the editor shows as unavailable stay unavailable. An image still loading or a fetch that fails stops the capture with a message instead of saving a picture with the image missing. PendingImageBytes becomes ImageBytes, since bytes fetched for a capture are not an upload. Screenshot leaves PlatformPolicy.webBeta.desktopOnly. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Copy the page and decode its images before a screenshot waits Review follow-up. A capture awaits image downloads before it renders, and the editor keeps editing its own objects in place meanwhile, so the page snapshot now clones agents, abilities, text, images and utilities (and deep-copies the lineup graph) instead of sharing them; an edit made while a slow image downloads can no longer land in half the picture. Fetched bytes were also never proven to be an image: a 200 with truncated bytes, or a decode slower than the 800 ms settle, would have saved a PNG with the picture missing. resolveCaptureImages now decodes every image that paints into the image cache and holds it there (keepAlive) until the capture releases it, so the capture's widgets find each picture already decoded, and a decode failure stops the capture with the same message as a failed fetch. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Refresh a screenshot's image URLs through the reader's share link A signed-out reader who opened a strategy link (#225) can take a screenshot too. Their only access to its images is that link, so the capture's signed-URL refresh carries the link's token, as the media cache does. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Keep a capture's images live until it is done, and bound their downloads Review follow-up. A keepAlive handle keeps a decoded image's completer alive, but once the last listener goes the image cache stops tracking it as live, so with enough large images an earlier one could be evicted and decoded again mid-capture, which is the missing-image timing the decode step exists to prevent. Each image now stays listened to until the capture releases it, which keeps it among the cache's live images. A stalled image request could also hold a capture forever: each download now times out after 60 s and fails the capture like any failed fetch. resolveCaptureImages takes a checkpoint, run before each image, so a caller can stop the work between images. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Let go of a capture image only once Review follow-up: an image whose later frame failed to decode let go of its stream in the error handler, and release() then removed the listener again, which throws once the stream is disposed and would have stopped the cleanup of the images after it. Letting go is now idempotent. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Keep a capture from signing the editor out of cloud sync Found in the browser run: each screenshot was followed by "Cloud connection lost". A capture renders in its own provider container, and hydrating its strategy provider builds that container's own auth provider, since the strategy provider listens to auth. A real auth provider configures the one Convex client the app syncs through: built with no session it clears that client's auth, with one it replaces the editor's token fetcher, and disposing it tears the auth down. Either way the editor's session ends. createCaptureContainer now builds every capture's container with an inert signed-out auth provider (nothing a capture paints needs auth) and the capture's image sources. A test records every call a capture makes to the Convex auth API and requires none; before this change it saw clearAuth. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Download a capture's images together, and take one screenshot at a time Greptile follow-ups. A page's cloud images downloaded one after another, so the wait was the sum of them; they now start together and decode in order, with the same checkpoints and cleanup, and an image still loading stops the capture before any download starts. And the screenshot guard cleared before the save dialog closed, so a second click could capture again and open a second dialog; the guard now holds until the save is done. Both have tests; the second fails without the fix. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Abort a capture's other downloads when it stops early Greptile follow-up: when one image failed or the capture was cancelled, the downloads already started for the others kept running, and a retry started them again alongside. A capture's downloads now share one HTTP client that is closed when resolution ends, which aborts whatever is still in flight (BrowserClient and IOClient both abort on close). A test fails one image while another waits and requires the client closed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
13 files changedLine totals unavailable