Skip to content

Commit a81dc52

Browse files
committed
fix: preserve scroll position when reading LLM output
- Added userHasScrolledUpRef to track when user manually scrolls up - Modified wheel event handler to detect scroll direction - Only re-enable auto-scroll when user explicitly scrolls down to bottom - Prevent auto-scroll from re-enabling when reaching bottom passively - Reset scroll state when starting new tasks Fixes #7974
1 parent 9ea7173 commit a81dc52

File tree

1 file changed

+27
-8
lines changed

1 file changed

+27
-8
lines changed

webview-ui/src/components/chat/ChatView.tsx

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
188188
const prevExpandedRowsRef = useRef<Record<number, boolean>>()
189189
const scrollContainerRef = useRef<HTMLDivElement>(null)
190190
const disableAutoScrollRef = useRef(false)
191+
const userHasScrolledUpRef = useRef(false)
191192
const [showScrollToBottom, setShowScrollToBottom] = useState(false)
192193
const [isAtBottom, setIsAtBottom] = useState(false)
193194
const lastTtsRef = useRef<string>("")
@@ -477,6 +478,9 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
477478
}
478479
// Reset user response flag for new task
479480
userRespondedRef.current = false
481+
// Reset scroll state for new task
482+
disableAutoScrollRef.current = false
483+
userHasScrolledUpRef.current = false
480484
}, [task?.ts])
481485

482486
useEffect(() => {
@@ -508,6 +512,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
508512

509513
if (wasAnyRowExpandedByUser) {
510514
disableAutoScrollRef.current = true
515+
userHasScrolledUpRef.current = true
511516
}
512517
prevExpandedRowsRef.current = expandedRows // Store current state for next comparison
513518
}, [expandedRows])
@@ -582,6 +587,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
582587
// setPrimaryButtonText(undefined)
583588
// setSecondaryButtonText(undefined)
584589
disableAutoScrollRef.current = false
590+
userHasScrolledUpRef.current = false
585591
}, [])
586592

587593
/**
@@ -1407,16 +1413,25 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
14071413
}
14081414
}, [groupedMessages.length, scrollToBottomSmooth])
14091415

1410-
const handleWheel = useCallback((event: Event) => {
1411-
const wheelEvent = event as WheelEvent
1416+
const handleWheel = useCallback(
1417+
(event: Event) => {
1418+
const wheelEvent = event as WheelEvent
14121419

1413-
if (wheelEvent.deltaY && wheelEvent.deltaY < 0) {
14141420
if (scrollContainerRef.current?.contains(wheelEvent.target as Node)) {
1415-
// User scrolled up
1416-
disableAutoScrollRef.current = true
1421+
if (wheelEvent.deltaY < 0) {
1422+
// User scrolled up - disable auto-scroll and mark that user has scrolled up
1423+
disableAutoScrollRef.current = true
1424+
userHasScrolledUpRef.current = true
1425+
} else if (wheelEvent.deltaY > 0 && isAtBottom) {
1426+
// User scrolled down while at bottom - re-enable auto-scroll
1427+
// This indicates intentional scrolling to bottom to resume following output
1428+
disableAutoScrollRef.current = false
1429+
userHasScrolledUpRef.current = false
1430+
}
14171431
}
1418-
}
1419-
}, [])
1432+
},
1433+
[isAtBottom],
1434+
)
14201435

14211436
useEvent("wheel", handleWheel, window, { passive: true }) // passive improves scrolling performance
14221437

@@ -1880,7 +1895,9 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
18801895
itemContent={itemContent}
18811896
atBottomStateChange={(isAtBottom: boolean) => {
18821897
setIsAtBottom(isAtBottom)
1883-
if (isAtBottom) {
1898+
// Only re-enable auto-scroll if user hasn't manually scrolled up
1899+
// When user manually scrolls to bottom, the wheel handler will re-enable it
1900+
if (isAtBottom && !userHasScrolledUpRef.current) {
18841901
disableAutoScrollRef.current = false
18851902
}
18861903
setShowScrollToBottom(disableAutoScrollRef.current && !isAtBottom)
@@ -1905,7 +1922,9 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
19051922
className="flex-[2]"
19061923
onClick={() => {
19071924
scrollToBottomSmooth()
1925+
// User explicitly clicked to scroll to bottom - re-enable auto-scroll
19081926
disableAutoScrollRef.current = false
1927+
userHasScrolledUpRef.current = false
19091928
}}>
19101929
<span className="codicon codicon-chevron-down"></span>
19111930
</VSCodeButton>

0 commit comments

Comments
 (0)