From 1211315259d388eda3bb587272e0eabc331ef4bf Mon Sep 17 00:00:00 2001 From: Chris Villa <chrisvilla@me.com> Date: Mon, 16 Oct 2023 13:45:12 +0100 Subject: [PATCH] refactor: store entire history to improve undo/redo robustness Some scenarios were tripping up undo/redo history when implementing array field reordering. Presumably a race condition, as could not reproduce during unit tests. It turns out that we were storing the entire object for the forward history, anyway, so this needs revisiting. --- packages/core/lib/use-puck-history.ts | 44 +++++++++++---------------- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/packages/core/lib/use-puck-history.ts b/packages/core/lib/use-puck-history.ts index b3b124259..4fd8cc053 100644 --- a/packages/core/lib/use-puck-history.ts +++ b/packages/core/lib/use-puck-history.ts @@ -5,14 +5,24 @@ import { useActionHistory } from "./use-action-history"; import { useHotkeys } from "react-hotkeys-hook"; import EventEmitter from "event-emitter"; import { useDebouncedCallback, useDebounce } from "use-debounce"; -import { diff, applyChange, revertChange } from "deep-diff"; const DEBOUNCE_TIME = 250; -const RECORD_DIFF = "RECORD_DIFF"; +export const RECORD_DIFF = "RECORD_DIFF"; export const historyEmitter = EventEmitter(); export const recordDiff = (newAppData: AppData) => historyEmitter.emit(RECORD_DIFF, newAppData); +export const _recordHistory = ({ snapshot, newSnapshot, record, dispatch }) => { + record({ + forward: () => { + dispatch({ type: "set", appData: newSnapshot }); + }, + rewind: () => { + dispatch({ type: "set", appData: snapshot }); + }, + }); +}; + export function usePuckHistory({ appData, dispatch, @@ -29,30 +39,11 @@ export function usePuckHistory({ const [snapshot] = useDebounce(appData, DEBOUNCE_TIME); const handleRecordDiff = useDebouncedCallback((newAppData: AppData) => { - const _diff = diff(snapshot, newAppData); - - if (!_diff) { - return; - } - - record({ - forward: () => { - const target = structuredClone(appData); - _diff.reduce((target, change) => { - applyChange(target, true, change); - return target; - }, target); - dispatch({ type: "set", appData: target }); - }, - rewind: () => { - const target = structuredClone(appData); - _diff.reduce((target, change) => { - revertChange(target, true, change); - return target; - }, target); - - dispatch({ type: "set", appData: target }); - }, + return _recordHistory({ + snapshot, + newSnapshot: newAppData, + record, + dispatch, }); }, DEBOUNCE_TIME); @@ -68,6 +59,5 @@ export function usePuckHistory({ canRewind, rewind, forward, - record, }; }