Skip to content

Commit

Permalink
refactor: store entire history to improve undo/redo robustness
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
chrisvxd committed Oct 16, 2023
1 parent 28920a2 commit ff726a2
Showing 1 changed file with 17 additions and 27 deletions.
44 changes: 17 additions & 27 deletions packages/core/lib/use-puck-history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);

Expand All @@ -68,6 +59,5 @@ export function usePuckHistory({
canRewind,
rewind,
forward,
record,
};
}

0 comments on commit ff726a2

Please sign in to comment.