Skip to content

Commit

Permalink
fix: scroll bottom issue (#4308)
Browse files Browse the repository at this point in the history
  • Loading branch information
urmauur authored Dec 20, 2024
1 parent 4e43f97 commit af84a3a
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 27 deletions.
4 changes: 2 additions & 2 deletions web/containers/ModelDropdown/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -378,14 +378,14 @@ const ModelDropdown = ({
!selectedModel && 'text-[hsla(var(--text-tertiary))]'
)}
>
{selectedModel?.name || 'Select Model'}
{selectedModel?.name || 'Select a model'}
</span>
</Badge>
) : (
<Input
value={selectedModel?.name || ''}
className="cursor-pointer"
placeholder="Select Model"
placeholder="Select a model"
disabled={disabled}
readOnly
suffixIcon={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ const EmptyThread = () => {
<LogoMark className="mx-auto mb-2 animate-wave" width={32} height={32} />
{showOnboardingStep ? (
<>
<p className="mt-1 font-medium">
{`You don't have a local model yet.`}
</p>
<p className="mt-1 font-medium">{`You don't have any model`}</p>
<Button
onClick={() => setMainViewState(MainViewState.Hub)}
variant="soft"
Expand Down
66 changes: 44 additions & 22 deletions web/screens/Thread/ThreadCenterPanel/ChatBody/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ import LoadModelError from '../LoadModelError'
import EmptyThread from './EmptyThread'

import { getCurrentChatMessagesAtom } from '@/helpers/atoms/ChatMessage.atom'
import { activeThreadAtom } from '@/helpers/atoms/Thread.atom'
import {
activeThreadAtom,
isGeneratingResponseAtom,
threadStatesAtom,
} from '@/helpers/atoms/Thread.atom'

const ChatConfigurator = memo(() => {
const messages = useAtomValue(getCurrentChatMessagesAtom)
Expand Down Expand Up @@ -61,6 +65,12 @@ const ChatBody = memo(
const prevScrollTop = useRef(0)
const isUserManuallyScrollingUp = useRef(false)
const currentThread = useAtomValue(activeThreadAtom)
const threadStates = useAtomValue(threadStatesAtom)
const isGeneratingResponse = useAtomValue(isGeneratingResponseAtom)

const isStreamingResponse = Object.values(threadStates).some(
(threadState) => threadState.waitingForResponse
)

const count = useMemo(
() => (messages?.length ?? 0) + (loadModelError ? 1 : 0),
Expand All @@ -76,15 +86,23 @@ const ChatBody = memo(
})

useEffect(() => {
// Delay the scroll until the DOM is updated
if (parentRef.current) {
if (parentRef.current && isGeneratingResponse) {
requestAnimationFrame(() => {
if (parentRef.current) {
parentRef.current.scrollTo({ top: parentRef.current.scrollHeight })
virtualizer.scrollToIndex(count - 1)
}
})
}
}, [count, virtualizer, isGeneratingResponse])

useEffect(() => {
isUserManuallyScrollingUp.current = false
requestAnimationFrame(() => {
if (parentRef.current) {
parentRef.current.scrollTo({ top: parentRef.current.scrollHeight })
virtualizer.scrollToIndex(count - 1)
}
})
}, [count, currentThread?.id, virtualizer])

const items = virtualizer.getVirtualItems()
Expand All @@ -94,34 +112,38 @@ const ChatBody = memo(
_,
instance
) => {
if (isUserManuallyScrollingUp.current === true) return false
if (isUserManuallyScrollingUp.current === true && isStreamingResponse)
return false
return (
// item.start < (instance.scrollOffset ?? 0) &&
instance.scrollDirection !== 'backward'
)
}

const handleScroll = useCallback((event: React.UIEvent<HTMLElement>) => {
const currentScrollTop = event.currentTarget.scrollTop

if (prevScrollTop.current > currentScrollTop) {
isUserManuallyScrollingUp.current = true
} else {
const handleScroll = useCallback(
(event: React.UIEvent<HTMLElement>) => {
const currentScrollTop = event.currentTarget.scrollTop
const scrollHeight = event.currentTarget.scrollHeight
const clientHeight = event.currentTarget.clientHeight

if (currentScrollTop + clientHeight >= scrollHeight) {
isUserManuallyScrollingUp.current = false
if (prevScrollTop.current > currentScrollTop && isStreamingResponse) {
isUserManuallyScrollingUp.current = true
} else {
const currentScrollTop = event.currentTarget.scrollTop
const scrollHeight = event.currentTarget.scrollHeight
const clientHeight = event.currentTarget.clientHeight

if (currentScrollTop + clientHeight >= scrollHeight) {
isUserManuallyScrollingUp.current = false
}
}
}

if (isUserManuallyScrollingUp.current === true) {
event.preventDefault()
event.stopPropagation()
}
prevScrollTop.current = currentScrollTop
}, [])
if (isUserManuallyScrollingUp.current === true) {
event.preventDefault()
event.stopPropagation()
}
prevScrollTop.current = currentScrollTop
},
[isStreamingResponse]
)

return (
<div className="flex h-full w-full flex-col overflow-x-hidden">
Expand Down

0 comments on commit af84a3a

Please sign in to comment.