From cd9a9754873d67d423921250206b63cc073ad91e Mon Sep 17 00:00:00 2001 From: song zhen qi <523254474@qq.com> Date: Tue, 21 Nov 2023 22:18:43 +0800 Subject: [PATCH] fix #4 Ignore patches whose path does not start with the targetStore's path. --- __tests__/undo-manager.test.ts | 88 +++++++++++++++++++++++++++++++++- src/undo-manager.ts | 7 ++- 2 files changed, 93 insertions(+), 2 deletions(-) diff --git a/__tests__/undo-manager.test.ts b/__tests__/undo-manager.test.ts index 7cd0dc6..d2c03e1 100644 --- a/__tests__/undo-manager.test.ts +++ b/__tests__/undo-manager.test.ts @@ -1,5 +1,5 @@ import { UndoManager } from "../src" -import { types, clone, getSnapshot, flow, Instance } from "mobx-state-tree" +import { types, clone, getSnapshot, flow, Instance, destroy } from "mobx-state-tree" import { configure } from "mobx" let undoManager: any = {} @@ -596,3 +596,89 @@ test("#15 - rollback by recorder.undo() should not be an UndoState", () => { expect(model.value).toBe(1) expect(_undoManager.history).toHaveLength(0) }) + +test('#4 - should not saves patches from non-targeted store', () => { + let UID = 1; + const Box = types + .model("Box", { + id: types.optional(types.identifier, ''), + }) + + const BoxStore = types + .model("BoxStore", { + boxes: types.array(Box) + }) + .actions((self) => ({ + afterCreate() { + setUndoManager(self); + }, + addRandomBox() { + const randomBox = Box.create({ id: `box-${UID++}` }) + self.boxes.push(randomBox) + return randomBox; + }, + remove(box: any) { + destroy(box) + } + })) + + const Focus = types + .model("Focus", { + focusedBoxes: types.array(types.safeReference(Box)) + }) + .actions(self => ({ + toggleBoxFocus(box: any) { + if (self.focusedBoxes.includes(box)) { + self.focusedBoxes.remove(box) + } else { + self.focusedBoxes.push(box) + } + } + })) + + const RootStore = types + .model("RootStore", { + boxStore: BoxStore, + focus: Focus, + }) + + const store = RootStore.create({ + boxStore: { boxes: [] }, + focus: { focusedBoxes: [] } + }); + + let _undoManager: any = null + const setUndoManager = (targetStore: any) => { + _undoManager = UndoManager.create({}, { targetStore }) + }; + + const box = store.boxStore.addRandomBox() + store.focus.toggleBoxFocus(box) + + // don't record `focusedBoxes.push(box)` + expect(getSnapshot(_undoManager)).toEqual({ + history: [ + { + patches: [{ op: "add", path: "/boxStore/boxes/0", value: { id: "box-1" } }], + inversePatches: [{ op: "remove", path: "/boxStore/boxes/0" }] + } + ], + undoIdx: 1 + }); + + store.boxStore.remove(box) + // don't record safeReference's side effect : `focusedBoxes.remove(box)` + expect(getSnapshot(_undoManager)).toEqual({ + history: [ + { + patches: [{ op: "add", path: "/boxStore/boxes/0", value: { id: "box-1" } }], + inversePatches: [{ op: "remove", path: "/boxStore/boxes/0" }] + }, + { + patches: [{ op: "remove", path: "/boxStore/boxes/0" }], + inversePatches: [{ op: "add", path: "/boxStore/boxes/0", value: { id: "box-1" } }] + } + ], + undoIdx: 2 + }); +}) diff --git a/src/undo-manager.ts b/src/undo-manager.ts index f80bde4..dc7a616 100644 --- a/src/undo-manager.ts +++ b/src/undo-manager.ts @@ -12,7 +12,8 @@ import { addMiddleware, addDisposer, decorate, - isActionContextThisOrChildOf + isActionContextThisOrChildOf, + getPath } from "mobx-state-tree" import { atomic } from "." @@ -72,6 +73,10 @@ const UndoManager = types if (recordingDisabled) { return false } + // only record patches that were generated by targetStore + if (!_patch.path.startsWith(getPath(targetStore))) { + return false + } // only record patches that were generated by this action or children of this action return ( !!actionContext && isActionContextThisOrChildOf(actionContext, call.id)