Repository navigation
fix(canvas): the edit lock resets at document boundaries and shows its state (v0.21.3) - #336
Merged
Merged
Conversation
…s state (v0.21.3) Part of #334 and #335. A new document no longer inherits the previous document's edit lock: File -> New, a temporary session started without the open diagram, and Delete work data leave an unlocked, empty document. Every whole-document replacement (New, a Template, a file, a share link, Open proposal as document) is a document boundary: the undo history starts empty, and the new document's own lock is written once, as part of the swap, so a locked Template or file never shows an unlocked moment. While locked, every user edit is refused, in the UI and at the stores. A new editPolicy module registers one guard on graphStore (it cannot import uiStore without a cycle); the graph's editing actions, the saved-frame changes and a revision Apply return without any change. Selection and size measurements still pass through onNodesChange / onEdgesChange, including a replace change that only flips `selected` (a panel reveal through setNodes). loadDoc takes a required mode, document-boundary or revision-apply, with no default; loadGraph takes the Template's lock. The palette, Undo / Redo, Insert module, the data import wizard, a data refresh, renaming a bound table and Review's Apply are disabled while locked. Run, Step, view settings, export and sharing stay available. The lock button now reads at a glance without colour: an open padlock with its shackle swung to the side (a 2 px gap at 1x) when unlocked, and the closed padlock with the rail's pressed tell when locked (Highlight in forced colours). Its accessible name is fixed ("Edit lock", one new string in 18 languages), aria-pressed carries the state and the tooltip names the next action. Tests: unit tests for the policy and the boundaries; e2e document-boundary and lock-control specs through the real UI; tests that relied on the removed "Undo restores the previous document" contract are replaced (4 titles), tests that edited a locked example through the dev bridge lift the lock first. Baselines: 6 new lock-button captures and 19 replaced ones whose only change is the lock button. Docs: docs/canvas-edit-lock.md; docs/bundled-module-label-localization.md follows the boundary rule. Release 0.21.3 with three release-note lines in 18 languages; the copy guards move only their exact pins (pt-PT's difference stays 277).
Deploying cozy-loop-studio with
|
| Latest commit: |
fb7ad93
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://a5f21b37.cozy-loop-studio.pages.dev |
| Branch Preview URL: | https://fix-edit-lock-boundaries.cozy-loop-studio.pages.dev |
3 tasks
This was referenced Oct 8, 2026
fix(canvas): a new document starts unlocked, and the edit lock blocks every user edit (v0.21.3)
#334
Closed
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.
Part of #334 and #335. Released as v0.21.3 (the release date is set to the actual merge day in Seoul before merging).
The bugs
graphStore.newGraph()never resetuiStore.canvasLocked; only the document loads did.aria-pressedalso did.The contract
The whole contract is in the new
docs/canvas-edit-lock.md.recommendedRunConfig.canvasLocked: trueopens locked, every other one, a new empty document included, unlocked.loadDoctakes a requiredmodewith no default (document-boundarywith the document'scanvasLocked, orrevision-apply), so a future caller cannot leave it out;loadGraph(a Template) takescanvasLocked.disabled) and at the stores:src/store/editPolicy.tsregisters one guard ongraphStore(it cannot importuiStorewithout a cycle), and the graph's editing actions, the saved-frame changes and a revision Apply return without any change (no state, no history, no autosave, nosimulationRev).onNodesChange/onEdgesChangekeepselectanddimensionschanges, and areplacechange that only flipsselected(a panel's reveal through React Flow'ssetNodes).Highlight/HighlightTextin forced colours). The accessible name is fixed, "Edit lock" (canvas.lock.name),aria-pressedcarries the state, and the tooltip names the next action. The phone stays view-only, with no lock button.Tests
src/store/editPolicy.test.ts: every refused action leaves the document, the frames, the history and the digest unchanged; selection, a selection-onlyreplace, a Step, export and unlocking work.src/store/graphStore.boundary.test.ts: each boundary empties the history; a revision Apply keeps one undo entry; the lock takes only its final value (a locked document never passes through unlocked).e2e/document-boundary.spec.ts: through the real UI, File → New, a temporary session, Delete work data, a Template, a file and a share link.e2e/canvas-lock.spec.ts: while locked the controls aredisabledand change nothing, Tab never lands on them, a menu's arrow keys skip the disabled rows, Enter and Space on a disabled chip do nothing; selecting, zooming, Focus, Step and export still work.e2e/lock-control.spec.ts: the 1× gap of the open icon and none for the closed one, measured on the rendered button; the fixed name,aria-pressedand the tooltip; the pressed tell in light and dark andHighlightin forced colours; the keyboard focus ring on the pressed button; and the six button baselines below.Tests replaced, not deleted
Four test titles of
mainare replaced, because the behaviour they assert is the one this pull request removes: an Undo right after New, a file or a Template load brought the previous document back. Under the new contract that history no longer exists; kept as they were, these tests would either fail or, retitled to pass, claim something they no longer check.main)large-graph-readability› Import adds ONE undo entry, never one-per-frame; pure Suggest / Dismiss / Clear suggested add none …module-label-localization› [P1] insert -> New -> Undo -> a locale switch still syncs the restored instancemodule-label-localization› [P1] insert -> loadDoc (Import) -> Undo -> …module-label-localization› [P1] insert -> loadGraph (Template-style load) -> Undo -> …Other tests adjusted: a few that edit a locked example (the early MMO and gacha templates open locked) through the dev bridge now lift the lock first, as a user has to; a few that compared
canUndoacross an import now assert the history directly;storage-sessionsuses the Focus preference, not the lock, as its "a preference survives Delete work data" example.The list: 2,030 tests (
main's 2,013, 21 added, 4 replaced as above), each in exactly one of the 5 shards, every shard within its budget.Visual baselines
A full run on the final code passed every existing baseline, but that only means each difference was inside its tolerance: a shadow capture that painted only the lock button found it in 35 of the 70 baselines. 25 PNGs change, by approval:
lock-{light,dark,forced}-{unlocked,locked}: the real 26 px button with its 14 px icon, captured from the product UI at 1×; the only captures of both states in every theme (forced colours locked existed nowhere).canvas-refresh-visualforced-colors-L2, matrix-dark-L0, matrix-dark-L2, matrix-light-L2;flow-colour-views-visualtemplate coffee and gacha, light and dark;flow-colour-visualdark-L2, light-L2, states;large-graph-readabilityauto-frames, auto-frames-mixed, run-distinction-states;model-nodes-visualregister-unit-row;playback-visualdepart dark, light and forced colours, travel-L0.Kept unchanged, byte for byte:
canvas-refresh-visualforced-colors-L0, matrix-dark-L1, matrix-light-L0, matrix-light-L1;flow-colour-visualdark-L0, light-L0;large-graph-readabilityframes-activity;flow-colour-views-visualtemplate mmo light and dark.i18n-visualko-desktop-app, ko-export-menu, ko-long-label-and-tip;large-graph-readabilityframe-colours, -dark, -forced, -overlap. A separate refresh, attributed againstmain, is left as a follow-up.Release
.changes/edit-lock-boundaries.json, release noterelease:0.21.3with three lines in 18 languages, 16 without native review, plus the button's name; no node kind is named.ustedregister; no ru line carries ё. No bound is widened.docs/canvas-edit-lock.md(new),docs/bundled-module-label-localization.md(rules 10 and 11 and MLS-D5 follow the boundary rule),CHANGELOG.md,README.md.Verification (local, at the head commit)
npx tsc -b, oxlint (39 warnings, the existing baseline, 0 errors), 3,270 unit tests, all 21 source checks of the CIchecksjob; the web, portable and PWA builds with their closure and notice checks;git diff --check.lock-controlon both projects twice in a row without an update, 330 passed, 5 skipped, both times.Not claimed