Skip to content

Commit a0a5b1d

Browse files
committed
fix: stream state + scrolling bugs?
1 parent b96f2b7 commit a0a5b1d

File tree

2 files changed

+18
-17
lines changed

2 files changed

+18
-17
lines changed

src/components/AIView.tsx

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -242,20 +242,16 @@ const AIViewInner: React.FC<AIViewProps> = ({ workspaceId, projectName, branch,
242242
// Get the aggregator for this workspace
243243
const aggregator = getAggregator(workspaceId);
244244

245+
// Clear stale streaming state before subscribing - backend replay is source of truth
246+
aggregator.clearActiveStreams();
247+
245248
// Load existing messages for this workspace
246249
setDisplayedMessages(aggregator.getDisplayedMessages());
247-
setCanInterrupt(aggregator.getActiveStreams().length > 0);
248-
249-
// Enable auto-scroll when switching workspaces
250-
setAutoScroll(true);
250+
setCanInterrupt(false); // Will be set correctly by replay if stream is active
251251

252252
// Set loading state based on whether we have messages
253253
// This preserves streaming state when switching workspaces
254-
if (aggregator.hasMessages()) {
255-
setLoading(false); // Clear loading if we have messages
256-
} else {
257-
setLoading(true); // Show loading only if empty
258-
}
254+
setLoading(!aggregator.hasMessages());
259255

260256
// Subscribe to workspace-specific chat channel
261257
// This will automatically send historical messages then stream new ones
@@ -266,14 +262,20 @@ const AIViewInner: React.FC<AIViewProps> = ({ workspaceId, projectName, branch,
266262
// Batch-load all historical messages at once for efficiency
267263
if (historicalMessages.length > 0) {
268264
aggregator.loadHistoricalMessages(historicalMessages);
269-
updateUIAndScroll();
270265
}
271266
isCaughtUp = true;
272267
setLoading(false);
273-
// Scroll to bottom once caught up
268+
updateUIAndScroll();
269+
270+
// After rendering, sync autoScroll with actual scroll position
274271
requestAnimationFrame(() => {
275272
if (contentRef.current) {
276-
contentRef.current.scrollTop = contentRef.current.scrollHeight;
273+
const isAtBottom =
274+
contentRef.current.scrollHeight -
275+
contentRef.current.scrollTop -
276+
contentRef.current.clientHeight <
277+
100;
278+
setAutoScroll(isAtBottom);
277279
}
278280
});
279281
return;
@@ -371,11 +373,6 @@ const AIViewInner: React.FC<AIViewProps> = ({ workspaceId, projectName, branch,
371373
// After caught-up: handle messages normally
372374
aggregator.handleMessage(data);
373375
updateUIAndScroll();
374-
375-
// Auto-scroll for new messages after caught up
376-
if (contentRef.current) {
377-
contentRef.current.scrollTop = contentRef.current.scrollHeight;
378-
}
379376
}
380377
}
381378
);

src/utils/messages/StreamingMessageAggregator.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ export class StreamingMessageAggregator {
9191
return Array.from(this.activeStreams.values());
9292
}
9393

94+
clearActiveStreams(): void {
95+
this.activeStreams.clear();
96+
}
97+
9498
clear(): void {
9599
this.messages.clear();
96100
this.activeStreams.clear();

0 commit comments

Comments
 (0)