use-agent-history-manager.ts
Overview
This file implements a history management system for a graph-based React application, allowing users to undo and redo changes made to graph nodes and edges. It provides a HistoryManager class that internally tracks changes to the graph's state and exposes undo/redo functionality. Additionally, the file defines a custom React hook useAgentHistoryManager which integrates the HistoryManager with React's component lifecycle and event handling, enabling seamless state history tracking and keyboard shortcut support.
The primary purpose of the file is to maintain a limited-size history stack of graph states, detect changes, and apply past states upon user commands (undo/redo). It also manages keyboard shortcuts (Ctrl/Cmd + Z and Ctrl/Cmd + Shift + Z) for undo and redo actions while respecting text input focus to avoid interfering with user typing.
Classes and Functions
Class: HistoryManager
Manages the history stack of graph states, allowing pushing new states, undoing, redoing, and resetting history.
Properties
Property | Type | Description |
|---|---|---|
| Array storing snapshots of graph states (nodes and edges). | |
|
| The index pointing to the current state in the history stack. |
|
| Maximum number of states kept in history (default 50). |
|
| Function to update the graph nodes in the application state. |
|
| Function to update the graph edges in the application state. |
|
| JSON string of the last saved state, used for change detection. |
Constructor
constructor(setNodes: (nodes: any[]) => void, setEdges: (edges: any[]) => void)
Parameters:
setNodes: Function to update nodes state.setEdges: Function to update edges state.
Description:
Initializes a newHistoryManagerinstance with functions to update the graph state.
Methods
private statesEqual(state1, state2): boolean
Parameters:
state1,state2: Objects containingnodesandedgesarrays.
Returns:
boolean—trueif the two states are deeply equal, elsefalse.Description: Compares two graph states by serializing them to JSON strings.
Usage: Used internally to check if the current state differs from the last saved state.
push(nodes: any[], edges: any[]): void
Parameters:
nodes: Current array of nodes.edges: Current array of edges.
Returns:
voidDescription: Adds a new state to the history stack if it differs from the current state. If the current index is not at the end of the history, it removes any "future" states before pushing the new one. Ensures the history size does not exceed
maxSizeby removing the oldest entries.Usage Example:
historyManager.push(currentNodes, currentEdges);
undo(): boolean
Returns:
trueif undo was successful,falseif no earlier state exists.Description: Moves the current index one step back and updates the application state to the previous graph state.
Usage Example:
if (historyManager.canUndo()) {
historyManager.undo();
}
redo(): boolean
Returns:
trueif redo was successful,falseif no later state exists.Description: Moves the current index one step forward and updates the application state to the next graph state.
Usage Example:
if (historyManager.canRedo()) {
historyManager.redo();
}
canUndo(): boolean
Returns:
trueif there is a previous state to undo to.Description: Indicates if undo is possible.
canRedo(): boolean
Returns:
trueif there is a next state to redo to.Description: Indicates if redo is possible.
reset(): void
Returns:
voidDescription: Clears the entire history stack and resets the current index and last saved state.
Function: useAgentHistoryManager
A React custom hook that integrates the HistoryManager with the application's graph state and keyboard event handling.
Description
Connects to the global graph state store (
useGraphStore) to access current nodes and edges and their setters.Initializes and persists a single
HistoryManagerinstance usinguseRef.Uses
useEffectto push new states to the history whenever nodes or edges change.Sets up a global keyboard listener to handle undo (Ctrl/Cmd + Z) and redo (Ctrl/Cmd + Shift + Z) shortcuts, ignoring inputs when focus is in text fields or contenteditable elements.
Usage Example
import React from 'react';
import { useAgentHistoryManager } from './use-agent-history-manager';
const GraphComponent = () => {
useAgentHistoryManager();
// ...rest of component logic
return <GraphVisualization />;
};
Implementation Details and Algorithms
State Equality Check: Uses JSON serialization to perform deep equality checks between graph states (
nodesandedges). This ensures that only meaningful changes create new history entries.History Management:
Maintains a linear history stack with a
currentIndexpointer.When pushing a new state, if the current index is not at the end, it truncates any "future" states to maintain a consistent timeline.
Limits history size to 50 states to avoid excessive memory usage.
Undo/Redo operations move the
currentIndexbackward or forward and update the graph state accordingly.
React Integration:
Uses
useRefto hold a persistentHistoryManagerinstance across renders.Leverages
useEffectto push new graph states after every state change.Adds global keyboard event listeners for undo/redo shortcuts, carefully avoiding interference with text input elements.
Interaction with Other Parts of the System
Graph State Store (
useGraphStore):The hook accesses the global graph state store to get and set nodes and edges.
The
HistoryManagerdepends on setters (setNodes,setEdges) to apply undo/redo changes.
User Interface Components:
Components displaying or editing the graph nodes and edges rely on the global state managed by
useGraphStore.The history functionality provides undo/redo capabilities triggered by keyboard shortcuts or potentially UI buttons (not in this file).
Keyboard Event Handling:
The file listens to global keyboard events to implement undo/redo shortcuts.
Ensures shortcuts do not trigger during text input or content-editable interactions.
Visual Diagram
classDiagram
class HistoryManager {
-history: Array<{nodes: any[], edges: any[]}>
-currentIndex: number
-maxSize: number
-setNodes(nodes: any[]): void
-setEdges(edges: any[]): void
-lastSavedState: string
-statesEqual(state1, state2): boolean
+constructor(setNodes, setEdges)
+push(nodes, edges): void
+undo(): boolean
+redo(): boolean
+canUndo(): boolean
+canRedo(): boolean
+reset(): void
}
class useAgentHistoryManager {
+(): void
}
useAgentHistoryManager --> HistoryManager : uses
HistoryManager --> "setNodes, setEdges" : callbacks
Summary
use-agent-history-manager.ts provides a robust history management utility for graph editing applications, encapsulating undo/redo logic in the HistoryManager class and integrating it with React through the useAgentHistoryManager hook. It ensures efficient state tracking, respects user input contexts, and offers a user-friendly way to revert or reapply graph changes with keyboard shortcuts. This file plays a crucial role in enhancing the user experience by enabling state history management in the graph state ecosystem.