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,
   };
 }