Repository navigation
Copy the page when "+" is pressed on a cloud strategy - #274
Open
SunkenInTime wants to merge 42 commits into
Open
SunkenInTime wants to merge 42 commits into
SunkenInTime wants to merge 42 commits into
Conversation
Lineup right-click menus gain Move to page and Copy to page, each listing every other page. The lineups at the clicked spot go to that page under new ids, with their names, notes and screenshots; a spot one of them shares with a lineup that stays is copied, so that lineup keeps it. They go on the other page before they leave this one. On cloud strategies the other page is read first and the new groups are queued as work the canvas never drew, so they are not deleted when they land while that page is on screen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A move took the lineups off this page whenever they still existed after the other page was read, so a teammate's edit made meanwhile was deleted here while the other page got the older version. It now compares the lineups and their spots with what was sent and keeps changed ones here. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A local write that failed while putting lineups on another page threw past the menu, so the user saw a generic error rather than being told nothing was moved. It now reports notSaved. A move also compares the lineups it sent by id, so the same lineups redrawn in another order no longer count as changed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hive can store a write and then throw while compacting its file, so a thrown put does not mean the lineups are missing from the other page. The box decides: if the copy is there, the move or copy went through. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The lineups at one spot share it, so they always make one group row. A copy that would need more than one row is now refused before anything is queued, so a failure after the first row can no longer leave part of a copy on the other page while the toast says nothing was moved. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Lineup menus offered Move to page and Copy to page with every page listed, unlike every other placed item. They now get the same "Copy to next page" and "Copy to previous page" items, in the same place and with the same toasts. A copied lineup and its spots get ids that carry the originals' (page_copy_id.dart), so a page that already has the lineup, or a copy of it, is not offered and gets no other, locally and on cloud. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A lineup imported with a very long id was offered "Copy to next page" on a cloud strategy, and choosing it did nothing, because the copy's outbox key would pass Hive's 255-character limit. The menu now leaves it out. A test also pins that a throw spot whose other lineup is already on the next page doesn't offer it, while that lineup still can go from its own landing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…up-page-move # Conflicts: # test/strategy_page_session_provider_test.dart
A duplicate gave every item and lineup a fresh random id, so items the source had copied between pages were no longer copies of each other in the duplicate: its page transitions faded them instead of gliding. Each now gets a copy id that keeps its root (lib/pageCopyId.ts, mirroring the app's page_copy_id.dart), unless the root is too long for the app to store a change under. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ud-page-duplicate
On a local strategy "+" adds a copy of the page on screen; on a cloud strategy it added a blank page, because the server keeps item ids unique across every strategy. The new cloud page now gets a copy of every item and lineup as the canvas draws them, each under a copy id that keeps its root, so turning to the page glides rather than fades. Images have their pictures copied first (images:copyAsset); one that can't be copied yet is left out and the "+" caller says so. The page opens once the copies land, waiting at most three seconds. A copied stroke now counts as its original when deciding whether the drawing layer changes between pages. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Astra's review: - "+" checked once for the new page's ack, so a busy queue or a dropped connection meant the page landed later, empty, with nothing said. It now waits for the page within the three seconds, keeping the queue sending; past them the copy follows once the page lands, and a toast says the page is on its way. - Copies queue through the queue of the strategy open now, so leaving the strategy while one was copied sent the rest to the wrong one. Each copy now checks the strategy first, and a stopped copy says so. - The three seconds didn't cover the send or the image picture copies. They now bound everything; an image that takes longer is left out. - Lineup copy ids skipped the storage-length check items get. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Waiting for a late page in the background nudged the queue every half second, which resets its own retry backoff while offline, and kept polling after the provider was disposed. The background wait now only watches, less often, and stops on dispose. The existing page-add test now expects "+" to wait out its window when the server answers nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Astra's second review found the copy inferring that the new page existed from the queue: an op leaves the queue when it lands, but also when it is discarded, replaced, or not yet written, so copies could go to a page that wasn't there. "+" on a cloud strategy now adds the page with a direct server call (pages:add), retrying once after a teammate's change, and copies onto it only once that call succeeds; offline, no page is added and a toast says so. enqueueOffCanvas checks, as it writes, that the strategy the copy belongs to is still the active one. The page read before turning to the new page is bound by the same three seconds, and a failed turn is logged rather than thrown. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A queued page.add may name a page to copy. The server copies that page's live items and lineups onto the new page, under copy ids that keep their roots, in the same transaction that adds it, so the page never appears without its content. A placed image still uploading is left out; a page too large to copy refuses the add before anything is written. "Duplicate strategy" now copies through the same code (lib/contentCopy). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…3/cloud-page-duplicate
… t3/cloud-page-duplicate
"+" queues the page add with the page on screen as its source; the server copies that page's content as it adds the page. Edits made just before are queued ahead of the add. Once the page lands the app turns to it, and says when images still uploading were left out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A batch is one transaction, so every page it copies now draws on one budget: two large copies can no longer push the batch past Convex's limits, where it would fail, and fail again on every retry. A lineup image several pages show is charged to a copy once, as it is copied once, so "Duplicate strategy" refuses no strategy it accepted before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
"+" waits for its own add's answer rather than only the first send's, so a page added behind other work still opens; with no answer in five seconds it says the page will appear once it reaches the cloud. Edits to the copied page the server refused are named, since they aren't in the copy. Images left out are counted, not matched by id, as a copy of an item with a long id gets a plain one. Switching strategies mid-add stops it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… t3/cloud-page-duplicate
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copies in one batch share a budget. A copy after it is spent failed only after reading a row, so many copies could still read past Convex's limit. A spent budget now refuses before reading. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What the copy may lack is known when "+" is pressed, from the page on screen: images still uploading, which the server leaves out, and edits to the page the server refused, which it never had. Saying so then, rather than guessing afterwards from what landed, holds whether the add lands at once or later, and isn't fooled by a teammate's changes. The wait for the server's answer now starts before sending, so a stalled send still answers "+" in time. A page copy too large to make gets its own message in the sync panel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… t3/cloud-page-duplicate
Edits sent ahead of the add have their answers once the add does, so "+" checks again then for refusals its copy won't have. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e-add-copies-content
A copied placed image now names its source's picture (assetId) rather
than getting a picture of its own. Within a strategy nothing is copied
or uploaded, so "+" no longer leaves out an image still uploading: the
copy shows the picture whenever the upload lands. A copy into another
strategy ("Duplicate strategy") brings each picture once, under the same
id.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ud-page-duplicate
… t3/cloud-page-duplicate
Copies show their original's pictures now, so "+" leaves no image out and has nothing to warn about: a copy of an image still uploading shows it once the upload lands. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e-add-copies-content
…e-add-copies-content
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ud-page-duplicate
… t3/cloud-page-duplicate
…e-add-copies-content
…ud-page-duplicate
… t3/cloud-page-duplicate
This branch has not been deployed
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.
On a local strategy, "+" adds a copy of the page on screen right after it. On a cloud strategy (the web beta and signed-in desktop), it added a blank page. With this PR and #275, cloud "+" copies the page too.
What changes
TransitionPlanner.drawingsChanged).Why the server copies (changed since the first version of this PR)
The first version copied on the client: it added the page with a direct call, then queued a copy of every item. Three rounds of review kept finding races between "the page exists" and "the copies land", the worst being a timed-out add that could still create a blank page after the app said none was added. Having the server copy in one transaction removes that whole class of problem. The field-merge work (#269) set the pattern: an optional op field, so no protocol bump.
Ground truth
Ran the web build in Edge against the dev deployment, which was running this branch's server code, signed in as a test account.
d8b91641-…~cp1~…), and its asset row points at the original's stored file.Then, with #276/#277: I placed a new image with its upload held for 20 seconds and pressed "+" during the hold. Frames: placed, then the copy during the hold, then after the upload landed:
The "changes didn't save" toast was only exercised in tests, not in the browser.
Tests
strategy_page_session_provider_test, group '"+" on a cloud strategy':cloud_sync_error_message_test: a page copy too large to make has its own explanation.collab_sync_models_test: the field survives storage andwithOpId, and an add without it sends no field.strategy_op_queue_provider_test: the field survives a restart through the durable outbox.page_copy_id_test: a copied stroke counts as its original.Astra reviewed it three times. Round 1 found six issues, all fixed. Round 2 showed my fixes to three of them were still guessing what the server had done; they're now worked out when "+" is pressed. Round 3 found one more case, an edit refused in the same send as the add, which is now fixed. The "still uploading" warning those rounds were about is gone now that copies share pictures.
Known limit
Two copies of very large pages (over 6 MiB each) sent in the same batch share one budget, so the second is refused. "Keep mine" in the sync panel sends it again. It may need pressing twice, because a refused add is retried at the revision it was first sent with. I left the core queue alone for a case this rare.
Merge order
This PR contains every PR below it and needs the server ones deployed first. Order: #276 and #273 (server), #277, #267 (you look first), #268 and #272, #275, then this. #271 is closed: copies share pictures instead.
ci: test web analyze
🤖 Generated with Claude Code