Pulastya B commited on
Commit
c10fec5
·
1 Parent(s): ff2d6c4

Fix progress polling to only occur during active workflows - use useEffect with proper cleanup

Browse files
FRRONTEEEND/components/ChatInterface.tsx CHANGED
@@ -51,35 +51,39 @@ export const ChatInterface: React.FC<{ onBack: () => void }> = ({ onBack }) => {
51
  const [showAssets, setShowAssets] = useState(false);
52
  const fileInputRef = useRef<HTMLInputElement>(null);
53
  const scrollRef = useRef<HTMLDivElement>(null);
 
54
 
55
  const activeSession = sessions.find(s => s.id === activeSessionId) || sessions[0];
56
 
 
 
 
 
 
 
 
 
 
57
  useEffect(() => {
58
  if (scrollRef.current) {
59
  scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
60
  }
61
  }, [activeSession.messages, isTyping]);
62
 
63
- const handleSend = async () => {
64
- if ((!input.trim() && !uploadedFile) || isTyping) return;
65
-
66
- const userMessage: Message = {
67
- id: Date.now().toString(),
68
- role: 'user',
69
- content: input || (uploadedFile ? `Uploaded: ${uploadedFile.name}` : ''),
70
- timestamp: new Date(),
71
- file: uploadedFile ? { name: uploadedFile.name, size: uploadedFile.size } : undefined,
72
- };
 
73
 
74
- const newMessages = [...activeSession.messages, userMessage];
75
- updateSession(activeSessionId, newMessages);
76
- setInput('');
77
- setIsTyping(true);
78
-
79
- // Start polling for progress updates
80
  const sessionKey = activeSessionId || 'default';
81
- let progressInterval: NodeJS.Timeout | null = null;
82
-
83
  const pollProgress = async () => {
84
  try {
85
  const API_URL = window.location.origin;
@@ -87,7 +91,7 @@ export const ChatInterface: React.FC<{ onBack: () => void }> = ({ onBack }) => {
87
  if (progressResponse.ok) {
88
  const progressData = await progressResponse.json();
89
  const steps = progressData.steps || [];
90
-
91
  if (steps.length > 0) {
92
  const latestStep = steps[steps.length - 1];
93
  const toolName = latestStep.tool
@@ -106,15 +110,42 @@ export const ChatInterface: React.FC<{ onBack: () => void }> = ({ onBack }) => {
106
  }
107
  };
108
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  try {
110
- // Start polling every 1 second
111
- progressInterval = setInterval(pollProgress, 1000);
112
 
113
  // Use the current origin if running on same server, otherwise use env variable
114
  const API_URL = window.location.origin;
115
  console.log('API URL:', API_URL);
116
 
117
  let response;
 
118
 
119
  // Check if there's a recent file analysis in the conversation
120
  const recentFileMessage = newMessages.slice(-5).find(m => m.file || m.content.includes('Uploaded:'));
@@ -172,12 +203,6 @@ export const ChatInterface: React.FC<{ onBack: () => void }> = ({ onBack }) => {
172
 
173
  const data = await response.json();
174
 
175
- // Stop progress polling and clear indicator
176
- if (progressInterval) {
177
- clearInterval(progressInterval);
178
- }
179
- setCurrentStep('');
180
-
181
  let assistantContent = '';
182
  let reports: Array<{name: string, path: string}> = [];
183
  let plots: Array<{title: string, url: string, type?: 'image' | 'html'}> = [];
@@ -272,12 +297,6 @@ export const ChatInterface: React.FC<{ onBack: () => void }> = ({ onBack }) => {
272
  } catch (error: any) {
273
  console.error("Chat Error:", error);
274
 
275
- // Stop progress polling
276
- if (progressInterval) {
277
- clearInterval(progressInterval);
278
- }
279
- setCurrentStep('');
280
-
281
  let errorMessage = "I'm sorry, I encountered an error processing your request.";
282
 
283
  if (error.message) {
@@ -304,11 +323,7 @@ export const ChatInterface: React.FC<{ onBack: () => void }> = ({ onBack }) => {
304
  timestamp: new Date()
305
  }]);
306
  } finally {
307
- // Stop progress polling
308
- if (progressInterval) {
309
- clearInterval(progressInterval);
310
- }
311
- setCurrentStep('');
312
  setIsTyping(false);
313
  }
314
  };
 
51
  const [showAssets, setShowAssets] = useState(false);
52
  const fileInputRef = useRef<HTMLInputElement>(null);
53
  const scrollRef = useRef<HTMLDivElement>(null);
54
+ const progressIntervalRef = useRef<NodeJS.Timeout | null>(null);
55
 
56
  const activeSession = sessions.find(s => s.id === activeSessionId) || sessions[0];
57
 
58
+ // Cleanup progress interval on unmount
59
+ useEffect(() => {
60
+ return () => {
61
+ if (progressIntervalRef.current) {
62
+ clearInterval(progressIntervalRef.current);
63
+ }
64
+ };
65
+ }, []);
66
+
67
  useEffect(() => {
68
  if (scrollRef.current) {
69
  scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
70
  }
71
  }, [activeSession.messages, isTyping]);
72
 
73
+ // Setup progress polling only when typing is active
74
+ useEffect(() => {
75
+ if (!isTyping) {
76
+ // Stop polling when not typing
77
+ if (progressIntervalRef.current) {
78
+ clearInterval(progressIntervalRef.current);
79
+ progressIntervalRef.current = null;
80
+ }
81
+ setCurrentStep('');
82
+ return;
83
+ }
84
 
 
 
 
 
 
 
85
  const sessionKey = activeSessionId || 'default';
86
+
 
87
  const pollProgress = async () => {
88
  try {
89
  const API_URL = window.location.origin;
 
91
  if (progressResponse.ok) {
92
  const progressData = await progressResponse.json();
93
  const steps = progressData.steps || [];
94
+
95
  if (steps.length > 0) {
96
  const latestStep = steps[steps.length - 1];
97
  const toolName = latestStep.tool
 
110
  }
111
  };
112
 
113
+ // Start polling only when isTyping is true
114
+ progressIntervalRef.current = setInterval(pollProgress, 1000);
115
+
116
+ // Cleanup on unmount or when isTyping becomes false
117
+ return () => {
118
+ if (progressIntervalRef.current) {
119
+ clearInterval(progressIntervalRef.current);
120
+ progressIntervalRef.current = null;
121
+ }
122
+ };
123
+ }, [isTyping, activeSessionId]);
124
+
125
+ const handleSend = async () => {
126
+ if ((!input.trim() && !uploadedFile) || isTyping) return;
127
+
128
+ const userMessage: Message = {
129
+ id: Date.now().toString(),
130
+ role: 'user',
131
+ content: input || (uploadedFile ? `Uploaded: ${uploadedFile.name}` : ''),
132
+ timestamp: new Date(),
133
+ file: uploadedFile ? { name: uploadedFile.name, size: uploadedFile.size } : undefined,
134
+ };
135
+
136
+ const newMessages = [...activeSession.messages, userMessage];
137
+ updateSession(activeSessionId, newMessages);
138
+ setInput('');
139
+ setIsTyping(true);
140
+
141
  try {
 
 
142
 
143
  // Use the current origin if running on same server, otherwise use env variable
144
  const API_URL = window.location.origin;
145
  console.log('API URL:', API_URL);
146
 
147
  let response;
148
+ const sessionKey = activeSessionId || 'default';
149
 
150
  // Check if there's a recent file analysis in the conversation
151
  const recentFileMessage = newMessages.slice(-5).find(m => m.file || m.content.includes('Uploaded:'));
 
203
 
204
  const data = await response.json();
205
 
 
 
 
 
 
 
206
  let assistantContent = '';
207
  let reports: Array<{name: string, path: string}> = [];
208
  let plots: Array<{title: string, url: string, type?: 'image' | 'html'}> = [];
 
297
  } catch (error: any) {
298
  console.error("Chat Error:", error);
299
 
 
 
 
 
 
 
300
  let errorMessage = "I'm sorry, I encountered an error processing your request.";
301
 
302
  if (error.message) {
 
323
  timestamp: new Date()
324
  }]);
325
  } finally {
326
+ // Setting isTyping to false will trigger useEffect to stop polling
 
 
 
 
327
  setIsTyping(false);
328
  }
329
  };