mirror of
https://github.com/penpot/penpot.git
synced 2026-10-29 05:50:35 +00:00
🐛 Keep update-main and deferred text sync in one undo group
Use the same explicit group for inverse sync and every copy sync. Text reflow can finish after the update transaction closes; one undo must still restore the main, its copies and the source overrides together (F152). The five-operation text regression fails before this change. All 12 frontend generated replays pass: 865 assertions. Common and frontend lint and format pass. Shared benchmark ratios: mains 0.47/0.53/0.55; levels 0.51; chain 0.64; library 0.64; many shapes 0.96; switch 0.68, no flags. AI-assisted-by: GPT-6
This commit is contained in:
parent
00f5d621b0
commit
d1e0f80265
@ -51,6 +51,9 @@
|
||||
- `leave-signals` (document `visibilitychange`→hidden, window `blur`) emits `::force-persist` when edits are buffered, so leaving the tab/window sends the 3 s batch at once; tests mock `dps/leave-signals` BEFORE `initialize-persistence` runs. pagehide/beforeunload are too late for an async save.
|
||||
- Exports and the `.penpot` download call `force-persist-files-and-wait file-ids timeout` (waits only for those files, ends on `:error` or timeout, never raises) and then `unsaved-changes? state file-ids` to warn; it reads `refs/persistence`, so tests mock it with `(l/derived :persistence store)`.
|
||||
- `persistence-failed` emits a `save-failed` audit event (`:cause-type :code :retrying :queued-commits`) whenever the user is notified (`notify-failure?`, same rule as the toast), including delegated auth/not-found failures.
|
||||
- Updating a component main passes one explicit undo group through the
|
||||
inverse sync and all copy syncs. Deferred text reflow may commit after
|
||||
the transaction closes; its changes must still join the user action (F152).
|
||||
- Undo transactions can stay open only temporarily; timed-out pending transactions are force-committed after about 20s. Undo entries are capped at 50.
|
||||
- Undo/redo are ignored while a normal editor/drawing interaction is active, except grid-layout edition handles undo through this path.
|
||||
- After local commits and when render-wasm is active, text shapes get derived `:position-data` recomputed in a separate commit tagged `#{:position-data}`; that tag is excluded from the position-data watcher to avoid loops.
|
||||
|
||||
@ -845,7 +845,7 @@
|
||||
NOTE: It's possible that the component to update is defined in an
|
||||
external library file, so this function may cause to modify a file
|
||||
different of that the one we are currently editing."
|
||||
[id]
|
||||
[id & {:keys [undo-group]}]
|
||||
(dm/assert! (uuid? id))
|
||||
(ptk/reify ::update-component
|
||||
ptk/WatchEvent
|
||||
@ -863,6 +863,7 @@
|
||||
(when (ctk/instance-head? shape)
|
||||
(let [[local-changes nonlocal-changes]
|
||||
(-> (pcb/empty-changes it)
|
||||
(cond-> undo-group (pcb/set-undo-group undo-group))
|
||||
(pcb/with-container container)
|
||||
(cll/generate-sync-shape-inverse libraries container id)
|
||||
(cll/split-local-changes))]
|
||||
@ -922,17 +923,18 @@
|
||||
(let [page (dsh/lookup-page state)
|
||||
shape (ctn/get-shape page shape-id)
|
||||
component-id (:component-id shape)
|
||||
undo-id (js/Symbol)]
|
||||
undo-id (js/Symbol)
|
||||
undo-group (uuid/next)]
|
||||
(apply rx/of
|
||||
(concat
|
||||
[(dwu/start-undo-transaction undo-id)
|
||||
(update-component shape-id)
|
||||
(update-component shape-id :undo-group undo-group)
|
||||
|
||||
;; These calls are necessary for properly sync thumbnails
|
||||
;; when a main component does not live in the same page.
|
||||
(update-component-thumbnail-sync state component-id file-id "frame")
|
||||
(update-component-thumbnail-sync state component-id file-id "component")]
|
||||
(component-sync-events state component-id file-id nil)
|
||||
(component-sync-events state component-id file-id undo-group)
|
||||
[(dwu/commit-undo-transaction undo-id)]))))))
|
||||
|
||||
(defn update-component-thumbnail
|
||||
|
||||
@ -89,3 +89,8 @@
|
||||
|
||||
(t/deftest ^:async nesting-restores-default-constraints-on-undo
|
||||
(await (replay {:world [2 0] :ops [[:nest 0]]})))
|
||||
|
||||
(t/deftest ^:async update-main-after-nesting-a-rotated-text-copy-undoes-together
|
||||
(await (replay {:world [2 0 {:text true}]
|
||||
:ops [[:duplicate 0] [:nest 0] [:rotate 0 0 0]
|
||||
[:edit 0 0 1 1] [:update-main 0]]})))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user