mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-04 17:38:10 +00:00
The user critique on the original HistoryManager design was sharp: adding a new action kind required edits to four places (HistoryContext interface, deps wiring in editor.ts, entry factory, recorder method). Anything shared between kinds becomes a chokepoint that grows. Introduce the proper Command pattern: - UndoableAction interface — single shape every action class implements. HistoryManager's external API becomes record(action) + undo/redo. Future kinds add a new class file under engine/editor/actions/; HistoryManager itself never grows. - isReplaying flag — record() no-ops while undo/redo is mid-flight, so any side-effect chain inside an action's apply/revert (e.g. delete-undo reaching editor.deleteObject which calls history.recordDelete) can't poison the stack. Belt-and-suspenders with the per-kind silent-setter routes the action classes will use. - engine/editor/actions/snapshots.ts — shared ObjectSnap / TransformSnap types, snapshot helpers, transformsEqual, writeTransform, and recreateFromSnapshot. Used by the action classes added in the next commit. Legacy recordCreate / recordDelete / begin+endTransform / recordSetColor / recordSetLocked / recordSetVisible methods stay as thin wrappers that bind the current HistoryContext into an UndoableAction via wrap(). Call sites compile unchanged. They're removed once all sites migrate to record(new XAction(...)).