Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions webview-ui/src/components/chat/ChatView.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react"
import { useDeepCompareEffect, useEvent, useMount } from "react-use"
import { useDeepCompareEffect, useEvent, useMount, useWindowSize } from "react-use"
import debounce from "debounce"
import { Virtuoso, type VirtuosoHandle } from "react-virtuoso"
import removeMd from "remove-markdown"
Expand Down Expand Up @@ -1743,6 +1743,22 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
}
}, [handleKeyDown])

// Use window size to calculate dynamic viewport
const { height: windowHeight } = useWindowSize()

// Calculate dynamic bottom viewport based on window height
// For smaller screens (< 800px), use a smaller viewport to prevent jumping
// For larger screens, use a larger viewport for smoother scrolling
const dynamicBottomViewport = useMemo(() => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The calculation will recalculate whenever changes. Since window resize events can fire frequently during resizing, could this cause performance issues? Would it be worth considering debouncing the window size changes to reduce recalculations?

if (!windowHeight) return 1000 // Default fallback
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it intentional that when is undefined, we fall back to 1000px - the same fixed value that was causing the original scrolling issues on smaller screens? Should we consider using a smaller default or calculating based on a typical small screen height?


// Scale the bottom viewport based on window height
// Minimum of 500px for very small screens, maximum of 2000px for large screens
const scaledViewport = Math.min(2000, Math.max(500, windowHeight * 0.8))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These magic numbers (0.8 for 80%, 500px min, 2000px max) work well but aren't self-documenting. Would it be helpful to extract these as named constants?


return Math.round(scaledViewport)
}, [windowHeight])

useImperativeHandle(ref, () => ({
acceptInput: () => {
if (enableButtons && primaryButtonText) {
Expand Down Expand Up @@ -1870,7 +1886,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
ref={virtuosoRef}
key={task.ts}
className="scrollable grow overflow-y-scroll mb-1"
increaseViewportBy={{ top: 3_000, bottom: 1000 }}
increaseViewportBy={{ top: 3_000, bottom: dynamicBottomViewport }}
data={groupedMessages}
itemContent={itemContent}
atBottomStateChange={(isAtBottom: boolean) => {
Expand Down
Loading