Skip to content

Commit b38df3f

Browse files
committed
refactor: address PR review feedback
- Extract magic numbers into named constants (VIEWPORT_BUFFER_AT_BOTTOM, VIEWPORT_BUFFER_SCROLLED_UP, VIEWPORT_BUFFER_TOP) - Add detailed comments explaining how followOutput='smooth' relates to the scroll lock fix - Implement debouncing (300ms) for isAtBottom state to prevent rapid viewport buffer changes - Add hysteresis to avoid performance issues during rapid scrolling This maintains the balance between memory efficiency and proper scroll lock behavior while addressing all reviewer concerns.
1 parent 93db129 commit b38df3f

File tree

1 file changed

+27
-4
lines changed

1 file changed

+27
-4
lines changed

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

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ export interface ChatViewRef {
7070

7171
export const MAX_IMAGES_PER_MESSAGE = 20 // Anthropic limits to 20 images
7272

73+
// Viewport buffer constants for memory-efficient scroll behavior
74+
const VIEWPORT_BUFFER_AT_BOTTOM = 10_000 // Larger buffer when at bottom to maintain scroll lock
75+
const VIEWPORT_BUFFER_SCROLLED_UP = 1_000 // Smaller buffer when scrolled up to preserve memory efficiency
76+
const VIEWPORT_BUFFER_TOP = 3_000 // Top buffer for smooth scrolling
77+
7378
const isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0
7479

7580
const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewProps> = (
@@ -174,6 +179,8 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
174179
const disableAutoScrollRef = useRef(false)
175180
const [showScrollToBottom, setShowScrollToBottom] = useState(false)
176181
const [isAtBottom, setIsAtBottom] = useState(false)
182+
// Debounced version of isAtBottom to prevent rapid viewport buffer changes
183+
const [debouncedIsAtBottom, setDebouncedIsAtBottom] = useState(false)
177184
const lastTtsRef = useRef<string>("")
178185
const [wasStreaming, setWasStreaming] = useState<boolean>(false)
179186
const [showCheckpointWarning, setShowCheckpointWarning] = useState<boolean>(false)
@@ -1430,6 +1437,16 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
14301437

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

1440+
// Debounce the isAtBottom state to prevent rapid viewport buffer changes
1441+
// This adds hysteresis to avoid performance issues when users quickly scroll between top and bottom
1442+
useEffect(() => {
1443+
const timer = setTimeout(() => {
1444+
setDebouncedIsAtBottom(isAtBottom)
1445+
}, 300) // 300ms delay provides good balance between responsiveness and stability
1446+
1447+
return () => clearTimeout(timer)
1448+
}, [isAtBottom])
1449+
14331450
// Effect to handle showing the checkpoint warning after a delay
14341451
useEffect(() => {
14351452
// Only show the warning when there's a task but no visible messages yet
@@ -1888,10 +1905,13 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
18881905
key={task.ts}
18891906
className="scrollable grow overflow-y-scroll mb-1"
18901907
increaseViewportBy={{
1891-
top: 3_000,
1892-
// Use a dynamic bottom value: larger when at bottom to maintain scroll lock,
1893-
// smaller when scrolled up to preserve memory efficiency
1894-
bottom: isAtBottom ? 10_000 : 1000,
1908+
top: VIEWPORT_BUFFER_TOP,
1909+
// Dynamic bottom buffer based on scroll position:
1910+
// - When at bottom: Use larger buffer to maintain scroll lock behavior
1911+
// - When scrolled up: Use smaller buffer to preserve memory efficiency
1912+
// This balances the memory leak fix from PR #6697 with proper scroll lock functionality
1913+
// Using debounced state to prevent rapid toggling during quick scrolling
1914+
bottom: debouncedIsAtBottom ? VIEWPORT_BUFFER_AT_BOTTOM : VIEWPORT_BUFFER_SCROLLED_UP,
18951915
}}
18961916
data={groupedMessages}
18971917
itemContent={itemContent}
@@ -1904,6 +1924,9 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
19041924
}}
19051925
atBottomThreshold={10}
19061926
initialTopMostItemIndex={groupedMessages.length - 1}
1927+
// followOutput='smooth' ensures smooth scrolling animation when new content arrives,
1928+
// working in conjunction with the dynamic viewport buffer to maintain scroll lock
1929+
// when the user is at the bottom of the chat
19071930
followOutput="smooth"
19081931
/>
19091932
</div>

0 commit comments

Comments
 (0)