diff --git a/src/store/workflowStore.ts b/src/store/workflowStore.ts index 7a959909..4c630e5b 100644 --- a/src/store/workflowStore.ts +++ b/src/store/workflowStore.ts @@ -205,6 +205,21 @@ interface WorkflowStore { setNavigationTarget: (nodeId: string | null) => void; setFocusedCommentNodeId: (nodeId: string | null) => void; resetViewedComments: () => void; + + // AI change snapshot state + previousWorkflowSnapshot: { + nodes: WorkflowNode[]; + edges: WorkflowEdge[]; + groups: Record; + edgeStyle: EdgeStyle; + } | null; + manualChangeCount: number; + + // AI change snapshot actions + captureSnapshot: () => void; + revertToSnapshot: () => void; + clearSnapshot: () => void; + incrementManualChangeCount: () => void; } let nodeIdCounter = 0; @@ -343,6 +358,10 @@ export const useWorkflowStore = create((set, get) => ({ navigationTarget: null, focusedCommentNodeId: null, + // AI change snapshot initial state + previousWorkflowSnapshot: null, + manualChangeCount: 0, + setEdgeStyle: (style: EdgeStyle) => { set({ edgeStyle: style }); }, @@ -389,6 +408,8 @@ export const useWorkflowStore = create((set, get) => ({ hasUnsavedChanges: true, })); + get().incrementManualChangeCount(); + return id; }, @@ -411,6 +432,7 @@ export const useWorkflowStore = create((set, get) => ({ ), hasUnsavedChanges: true, })); + get().incrementManualChangeCount(); }, onNodesChange: (changes: NodeChange[]) => { @@ -418,19 +440,33 @@ export const useWorkflowStore = create((set, get) => ({ const hasMeaningfulChange = changes.some( (c) => c.type !== "select" && c.type !== "dimensions" ); + // Track manual changes only for remove operations (not position/selection/dimensions) + const hasRemoveChange = changes.some((c) => c.type === "remove"); + set((state) => ({ nodes: applyNodeChanges(changes, state.nodes), ...(hasMeaningfulChange ? { hasUnsavedChanges: true } : {}), })); + + if (hasRemoveChange) { + get().incrementManualChangeCount(); + } }, onEdgesChange: (changes: EdgeChange[]) => { // Only mark as unsaved for meaningful changes (not selection changes) const hasMeaningfulChange = changes.some((c) => c.type !== "select"); + // Track manual changes only for remove operations (not selection) + const hasRemoveChange = changes.some((c) => c.type === "remove"); + set((state) => ({ edges: applyEdgeChanges(changes, state.edges), ...(hasMeaningfulChange ? { hasUnsavedChanges: true } : {}), })); + + if (hasRemoveChange) { + get().incrementManualChangeCount(); + } }, onConnect: (connection: Connection) => { @@ -444,6 +480,7 @@ export const useWorkflowStore = create((set, get) => ({ ), hasUnsavedChanges: true, })); + get().incrementManualChangeCount(); }, addEdgeWithType: (connection: Connection, edgeType: string) => { @@ -465,6 +502,7 @@ export const useWorkflowStore = create((set, get) => ({ edges: state.edges.filter((edge) => edge.id !== edgeId), hasUnsavedChanges: true, })); + get().incrementManualChangeCount(); }, toggleEdgePause: (edgeId: string) => { @@ -2489,6 +2527,9 @@ export const useWorkflowStore = create((set, get) => ({ // Reset viewed comments when loading new workflow viewedCommentNodeIds: new Set(), }); + + // Clear any snapshot when user manually loads a workflow + get().clearSnapshot(); }, clearWorkflow: () => { @@ -2512,6 +2553,7 @@ export const useWorkflowStore = create((set, get) => ({ // Reset viewed comments when clearing workflow viewedCommentNodeIds: new Set(), }); + get().clearSnapshot(); }, addToGlobalHistory: (item: Omit) => { @@ -2904,4 +2946,57 @@ export const useWorkflowStore = create((set, get) => ({ resetViewedComments: () => { set({ viewedCommentNodeIds: new Set() }); }, + + // AI change snapshot actions + captureSnapshot: () => { + const state = get(); + // Deep copy the current workflow state to avoid reference sharing + const snapshot = { + nodes: JSON.parse(JSON.stringify(state.nodes)), + edges: JSON.parse(JSON.stringify(state.edges)), + groups: JSON.parse(JSON.stringify(state.groups)), + edgeStyle: state.edgeStyle, + }; + set({ + previousWorkflowSnapshot: snapshot, + manualChangeCount: 0, + }); + }, + + revertToSnapshot: () => { + const state = get(); + if (state.previousWorkflowSnapshot) { + set({ + nodes: state.previousWorkflowSnapshot.nodes, + edges: state.previousWorkflowSnapshot.edges, + groups: state.previousWorkflowSnapshot.groups, + edgeStyle: state.previousWorkflowSnapshot.edgeStyle, + previousWorkflowSnapshot: null, + manualChangeCount: 0, + hasUnsavedChanges: true, + }); + } + }, + + clearSnapshot: () => { + set({ + previousWorkflowSnapshot: null, + manualChangeCount: 0, + }); + }, + + incrementManualChangeCount: () => { + const state = get(); + const newCount = state.manualChangeCount + 1; + + // Automatically clear snapshot after 3 manual changes + if (newCount >= 3) { + set({ + previousWorkflowSnapshot: null, + manualChangeCount: 0, + }); + } else { + set({ manualChangeCount: newCount }); + } + }, }));