1- import { useEffect , useMemo , useRef } from 'react'
2- import { useQueryClient } from '@tanstack/react-query'
1+ import { useMemo } from 'react'
32import { hasWorkflowChanged } from '@/lib/workflows/comparison'
43import { mergeSubblockStateWithValues } from '@/lib/workflows/subblocks'
5- import { deploymentKeys } from '@/hooks/queries/deployments'
64import { useVariablesStore } from '@/stores/panel/variables/store'
75import { useSubBlockStore } from '@/stores/workflows/subblock/store'
86import { useWorkflowStore } from '@/stores/workflows/workflow/store'
@@ -12,34 +10,23 @@ interface UseChangeDetectionProps {
1210 workflowId : string | null
1311 deployedState : WorkflowState | null
1412 isLoadingDeployedState : boolean
15- serverNeedsRedeployment : boolean | undefined
16- isServerLoading : boolean
1713}
1814
1915/**
2016 * Detects meaningful changes between current workflow state and deployed state.
21- *
22- * Uses the server-side needsRedeployment (from useDeploymentInfo) as the
23- * authoritative signal. The server compares the persisted DB state to the
24- * deployed version state, which avoids false positives from client-side
25- * representation differences.
26- *
27- * When the workflow store is updated (e.g. after auto-save), the deployment
28- * info query is invalidated so the server can recheck for changes.
17+ * Performs comparison entirely on the client using hasWorkflowChanged — no API
18+ * calls needed. The deployed state snapshot is fetched once via React Query and
19+ * refreshed after deploy/undeploy/version-activate mutations.
2920 */
3021export function useChangeDetection ( {
3122 workflowId,
3223 deployedState,
3324 isLoadingDeployedState,
34- serverNeedsRedeployment,
35- isServerLoading,
3625} : UseChangeDetectionProps ) {
37- const queryClient = useQueryClient ( )
3826 const blocks = useWorkflowStore ( ( state ) => state . blocks )
3927 const edges = useWorkflowStore ( ( state ) => state . edges )
4028 const loops = useWorkflowStore ( ( state ) => state . loops )
4129 const parallels = useWorkflowStore ( ( state ) => state . parallels )
42- const lastSaved = useWorkflowStore ( ( state ) => state . lastSaved )
4330 const subBlockValues = useSubBlockStore ( ( state ) =>
4431 workflowId ? state . workflowValues [ workflowId ] : null
4532 )
@@ -55,50 +42,8 @@ export function useChangeDetection({
5542 return vars
5643 } , [ workflowId , allVariables ] )
5744
58- // Tracks the lastSaved timestamp at mount to distinguish real saves from initial hydration.
59- const initialLastSavedRef = useRef < number | undefined > ( undefined )
60- const workflowIdRef = useRef ( workflowId )
61-
62- // Must run before the lastSaved effect to prevent stale-ref invalidation on workflow switch.
63- useEffect ( ( ) => {
64- workflowIdRef . current = workflowId
65- initialLastSavedRef . current = undefined
66- } , [ workflowId ] )
67-
68- useEffect ( ( ) => {
69- if ( lastSaved !== undefined && initialLastSavedRef . current === undefined ) {
70- initialLastSavedRef . current = lastSaved
71- return
72- }
73-
74- if (
75- lastSaved === undefined ||
76- initialLastSavedRef . current === undefined ||
77- lastSaved === initialLastSavedRef . current ||
78- ! workflowId
79- ) {
80- return
81- }
82-
83- initialLastSavedRef . current = lastSaved
84-
85- const capturedWorkflowId = workflowId
86- const timer = setTimeout ( ( ) => {
87- if ( workflowIdRef . current !== capturedWorkflowId ) return
88- queryClient . invalidateQueries ( {
89- queryKey : deploymentKeys . info ( capturedWorkflowId ) ,
90- } )
91- } , 500 )
92-
93- return ( ) => clearTimeout ( timer )
94- } , [ lastSaved , workflowId , queryClient ] )
95-
96- // Skip expensive state merge when server result is available (the common path).
97- // Only build currentState for the client-side fallback comparison.
98- const needsClientFallback = serverNeedsRedeployment === undefined && ! isServerLoading
99-
10045 const currentState = useMemo ( ( ) : WorkflowState | null => {
101- if ( ! needsClientFallback || ! workflowId || ! deployedState ) return null
46+ if ( ! workflowId || ! deployedState ) return null
10247
10348 const mergedBlocks = mergeSubblockStateWithValues ( blocks , subBlockValues ?? { } )
10449
@@ -110,7 +55,6 @@ export function useChangeDetection({
11055 variables : workflowVariables ,
11156 } as WorkflowState & { variables : Record < string , any > }
11257 } , [
113- needsClientFallback ,
11458 workflowId ,
11559 deployedState ,
11660 blocks ,
@@ -122,21 +66,9 @@ export function useChangeDetection({
12266 ] )
12367
12468 const changeDetected = useMemo ( ( ) => {
125- if ( isServerLoading ) return false
126-
127- if ( serverNeedsRedeployment !== undefined ) {
128- return serverNeedsRedeployment
129- }
130-
13169 if ( ! currentState || ! deployedState || isLoadingDeployedState ) return false
13270 return hasWorkflowChanged ( currentState , deployedState )
133- } , [
134- currentState ,
135- deployedState ,
136- isLoadingDeployedState ,
137- serverNeedsRedeployment ,
138- isServerLoading ,
139- ] )
71+ } , [ currentState , deployedState , isLoadingDeployedState ] )
14072
14173 return { changeDetected }
14274}
0 commit comments