mirror of
https://github.com/penpot/penpot.git
synced 2026-10-29 05:50:35 +00:00
🐛 Record user undo changes before starting derived component sync
Hand applied transitions to the component watcher only after the workspace records their undo entry. Keep the handoff synchronous with the captured prior file data. This preserves transaction order when nesting triggers several component syncs. Fix F137. The minimal replay failed both undo and redo before the fix; its 4 checks now pass. Existing sync scenarios pass their behavior and undo checks; 60 golden digests need review for the accumulated Phase 4 fixes. Common benchmark ratios against Phase 1e: main 10/100/1000 0.46/0.52/0.53; levels 0.47; chain 0.51; library 0.51; many 0.49; switch 0.61. This handoff changes no common benchmark code. AI-assisted-by: GPT-6
This commit is contained in:
parent
84affc15c0
commit
67550ebb5c
@ -19,11 +19,16 @@
|
||||
|
||||
- `commit-changes` refuses to create commits unless `:permissions :can-edit` is true. It captures file revn/vern, selected-before, features, tags, undo group, and translation flag into a `::commit` event. A refusal answers with an empty stream, never nil, so callers subscribe uniformly instead of branching on nil.
|
||||
- Applying a remote commit first rolls back pending local commits, applies the remote changes, then replays pending local redo changes. Index updates are emitted for undo, remote redo, and replayed redo paths.
|
||||
- Local commits are independently consumed by undo, persistence, WASM model updates, thumbnail/library watchers, and text position-data recalculation.
|
||||
- Persistence, WASM model updates, thumbnails and text position-data watchers
|
||||
consume local commits independently. Undo records applied transitions first.
|
||||
- `dch/changes-applied?` follows local application and carries the commit
|
||||
with its prior file data. The component watcher syncs each transition
|
||||
before the next user commit, keeping undo groups adjacent. Its barrier
|
||||
remains open through the event turn. Foreign file cascades stay in common.
|
||||
with its prior file data. The workspace records the undo entry, then emits
|
||||
`dch/changes-recorded?` synchronously with that same transition. Component
|
||||
sync starts from this handoff, after history records the original edit.
|
||||
Syncing from `changes-applied?` can record derived commits before the user
|
||||
commit and reverse the undo/redo order inside a transaction (F137).
|
||||
The watcher syncs before the next user commit; its barrier remains open
|
||||
through the event turn. Foreign file cascades stay in common.
|
||||
- Undo changes carry `:app.main.data.workspace.undo/file-id`, separate from
|
||||
change payload fields named `:file-id` (e.g. `:set-tokens-source`). Undo
|
||||
and redo replay consecutive runs per destination in order; old entries
|
||||
|
||||
@ -38,6 +38,15 @@
|
||||
(def changes-applied?
|
||||
(ptk/type? ::changes-applied))
|
||||
|
||||
(def changes-recorded?
|
||||
(ptk/type? ::changes-recorded))
|
||||
|
||||
(defn changes-recorded
|
||||
"The commit has applied and its undo entry has been recorded. Derived
|
||||
edits can now follow it without reversing transaction history."
|
||||
[transition]
|
||||
(ptk/data-event ::changes-recorded transition))
|
||||
|
||||
(defn- fix-page-id
|
||||
"For events that modifies the page, page-id does not comes
|
||||
as a property so we assign it from the `id` property."
|
||||
|
||||
@ -494,18 +494,22 @@
|
||||
(rx/take-until stopper-s)))
|
||||
|
||||
(->> stream
|
||||
(rx/filter dch/commit?)
|
||||
(rx/filter dch/changes-applied?)
|
||||
(rx/map deref)
|
||||
(rx/mapcat
|
||||
(fn [{:keys [file-id save-undo? undo-changes redo-changes undo-group tags stack-undo? selected-before]}]
|
||||
(if (and save-undo? (seq undo-changes))
|
||||
(let [entry {:undo-changes (mapv #(assoc % ::dwu/file-id file-id) undo-changes)
|
||||
:redo-changes (mapv #(assoc % ::dwu/file-id file-id) redo-changes)
|
||||
:undo-group undo-group
|
||||
:tags tags
|
||||
:selected-before selected-before}]
|
||||
(rx/of (dwu/append-undo entry stack-undo?)))
|
||||
(rx/empty))))))
|
||||
(fn [{:keys [commit] :as transition}]
|
||||
(let [{:keys [file-id save-undo? undo-changes redo-changes undo-group
|
||||
tags stack-undo? selected-before]} commit]
|
||||
(rx/concat
|
||||
(if (and save-undo? (seq undo-changes))
|
||||
(let [entry {:undo-changes (mapv #(assoc % ::dwu/file-id file-id) undo-changes)
|
||||
:redo-changes (mapv #(assoc % ::dwu/file-id file-id) redo-changes)
|
||||
:undo-group undo-group
|
||||
:tags tags
|
||||
:selected-before selected-before}]
|
||||
(rx/of (dwu/append-undo entry stack-undo?)))
|
||||
(rx/empty))
|
||||
(rx/of (dch/changes-recorded transition))))))))
|
||||
(rx/take-until stopper-s)))))))
|
||||
|
||||
(defn initialize-workspace
|
||||
|
||||
@ -1420,7 +1420,7 @@
|
||||
|
||||
local-commits-s
|
||||
(->> stream
|
||||
(rx/filter dch/changes-applied?)
|
||||
(rx/filter dch/changes-recorded?)
|
||||
(rx/map deref)
|
||||
(rx/filter #(= :local (get-in % [:commit :source])))
|
||||
;; Keep waits pending while component changes are checked.
|
||||
|
||||
@ -86,3 +86,6 @@
|
||||
(t/deftest ^:async nested-text-rotation-shrunk-regression
|
||||
(await (replay {:world [2 0 {:text true}]
|
||||
:ops [[:nest 0] [:detach 0] [:rotate 0]]})))
|
||||
|
||||
(t/deftest ^:async nesting-restores-default-constraints-on-undo
|
||||
(await (replay {:world [2 0] :ops [[:nest 0]]})))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user