diff --git a/frontend/src/components/common/ProgressModal.tsx b/frontend/src/components/common/ProgressModal.tsx index 76b5b585..e8833026 100644 --- a/frontend/src/components/common/ProgressModal.tsx +++ b/frontend/src/components/common/ProgressModal.tsx @@ -197,7 +197,7 @@ export default function ProgressModal({ const stepCompletionTimersRef = useRef>(new Map()); const visuallyCompletedStepsRef = useRef>(new Set()); const lastProcessedStepLogsHashRef = useRef(''); - const lastVisuallyCompletedCountRef = useRef(0); + const lastProcessedPhaseRef = useRef(''); // Sync ref with state useEffect(() => { @@ -334,6 +334,9 @@ export default function ProgressModal({ const allStepsVisuallyCompleted = steps.length > 0 && steps.every(step => visuallyCompletedSteps.has(step.phase)); + // Track the count of visually completed steps to detect changes without causing infinite loops + const visuallyCompletedCount = visuallyCompletedSteps.size; + // Track step completions with 2-second delay between each step useEffect(() => { if (!isOpen) { @@ -341,29 +344,13 @@ export default function ProgressModal({ setVisuallyCompletedSteps(new Set()); visuallyCompletedStepsRef.current = new Set(); lastProcessedStepLogsHashRef.current = ''; - lastVisuallyCompletedCountRef.current = 0; + lastProcessedPhaseRef.current = ''; stepCompletionTimersRef.current.forEach(timer => clearTimeout(timer)); stepCompletionTimersRef.current.clear(); return; } const phaseOrder = ['INIT', 'PREP', 'AI_CALL', 'PARSE', 'SAVE', 'DONE']; - const currentVisuallyCompletedCount = visuallyCompletedSteps.size; - - // Check if we need to process: - // 1. Backend progress changed (stepLogsHash or currentPhase) - // 2. A step just completed visually (count increased) - const currentHash = `${stepLogsHash}|${currentPhase}`; - const hashChanged = currentHash !== lastProcessedStepLogsHashRef.current; - const countChanged = currentVisuallyCompletedCount > lastVisuallyCompletedCountRef.current; - - if (!hashChanged && !countChanged) { - return; // Nothing changed, skip processing - } - - // Update tracking refs - lastProcessedStepLogsHashRef.current = currentHash; - lastVisuallyCompletedCountRef.current = currentVisuallyCompletedCount; // Process steps sequentially - find the first step that should be completed but isn't visually completed yet for (let index = 0; index < steps.length; index++) { @@ -385,6 +372,7 @@ export default function ProgressModal({ // Only schedule if previous step is completed (or this is first step) if (previousStepCompleted) { // Calculate delay: 2 seconds after previous step visually completed (or 0 for first step) + // For subsequent steps, add 2 seconds delay const delay = previousStep ? 2000 : 0; // Schedule completion @@ -412,7 +400,7 @@ export default function ProgressModal({ stepCompletionTimersRef.current.forEach(timer => clearTimeout(timer)); stepCompletionTimersRef.current.clear(); }; - }, [isOpen, currentPhase, stepLogsHash, steps, stepLogs, visuallyCompletedSteps.size]); // Use .size instead of the Set + }, [isOpen, currentPhase, stepLogsHash, steps, stepLogs, visuallyCompletedCount]); // Use count instead of Set to avoid infinite loops // Don't auto-close - user must click close button