Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | 290582x 290582x 290582x 290582x 2974x 2944x 2944x 2944x 30x 290582x 69x 69x 290582x 2x 2x 2x 2x 2x 2x 2x 290582x 2x 2x 2x 2x 2x 2x 2x 290582x 290582x 290582x 290582x | import { useSyncExternalStore, useCallback, useEffect, useRef } from "react";
import { undoRedoStore } from "@/utils/UndoRedoStore";
import { commandExecutor } from "@/utils/commandExecutor";
import { Command } from "@/types/commands";
import { useProjectId } from "./project";
export function useUndoRedoStore() {
const flowsheetId = useProjectId();
const prevFlowsheetIdRef = useRef<number | null>(null);
// Subscribe to external store using React's useSyncExternalStore
const snapshot = useSyncExternalStore(
undoRedoStore.subscribe,
undoRedoStore.getSnapshot,
undoRedoStore.getSnapshot, // Same for server-side rendering
);
// Automatically set flowsheet context when available
useEffect(() => {
if (flowsheetId && Number.isFinite(flowsheetId) && flowsheetId > 0) {
// Only update if flowsheet actually changed (prevent unnecessary operations)
if (prevFlowsheetIdRef.current !== flowsheetId) {
prevFlowsheetIdRef.current = flowsheetId;
undoRedoStore.setFlowsheet(String(flowsheetId));
}
} else {
// Clear previous flowsheet reference if invalid
Iif (prevFlowsheetIdRef.current !== null) {
prevFlowsheetIdRef.current = null;
}
}
}, [flowsheetId]);
// Command execution methods - memoized to prevent unnecessary re-renders
const addHistory = useCallback(
(command: Command) => {
Iif (!snapshot.isReady) {
console.warn("[useUndoRedoStore] Cannot add command: Store not ready");
return;
}
undoRedoStore.addCommand(command);
},
[snapshot.isReady],
);
const executeUndo = useCallback(async (): Promise<boolean> => {
Iif (!snapshot.canUndo) {
console.warn("[useUndoRedoStore] Cannot undo: No commands available");
return false;
}
const command = undoRedoStore.undo();
Iif (!command) {
return false;
}
try {
// Execute the undo command using the command executor
const success = await commandExecutor.executeCommand(command, true);
Iif (!success) {
// Restore command on failure
undoRedoStore.restoreFailedUndo(command);
return false;
}
return true;
} catch (error) {
console.error("[useUndoRedoStore] Undo execution failed:", error);
// Restore command on failure
undoRedoStore.restoreFailedUndo(command);
return false;
}
}, [snapshot.canUndo]);
const executeRedo = useCallback(async (): Promise<boolean> => {
Iif (!snapshot.canRedo) {
console.warn("[useUndoRedoStore] Cannot redo: No commands available");
return false;
}
const command = undoRedoStore.redo();
Iif (!command) {
return false;
}
try {
// Execute the redo command using the command executor
const success = await commandExecutor.executeCommand(command, false);
Iif (!success) {
// Restore command on failure
undoRedoStore.restoreFailedRedo(command);
return false;
}
return true;
} catch (error) {
console.error("[useUndoRedoStore] Redo execution failed:", error);
// Restore command on failure
undoRedoStore.restoreFailedRedo(command);
return false;
}
}, [snapshot.canRedo]);
// Utility methods
const resetHistory = useCallback(() => {
undoRedoStore.resetStacks();
}, []);
const removeFlowsheet = useCallback((id: string) => {
undoRedoStore.removeFlowsheet(id);
}, []);
const getDebugInfo = useCallback(() => {
return undoRedoStore.getDebugInfo();
}, []);
// Return clean API following React patterns
return {
// State (directly from external store snapshot)
canUndo: snapshot.canUndo,
canRedo: snapshot.canRedo,
isReady: snapshot.isReady,
undoStackSize: snapshot.undoStackSize,
redoStackSize: snapshot.redoStackSize,
currentFlowsheetId: snapshot.flowsheetId,
// Actions
addHistory,
executeUndo,
executeRedo,
resetHistory,
removeFlowsheet,
getDebugInfo,
// Legacy compatibility aliases (to ease migration)
onUndo: executeUndo,
onRedo: executeRedo,
resetUndoRedoHistory: resetHistory,
};
}
|