Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 fix: Effectively interrupt auto scrolling #2223

Merged
merged 18 commits into from Apr 30, 2024
Merged
5 changes: 3 additions & 2 deletions src/features/Conversation/components/AutoScroll.tsx
Expand Up @@ -7,14 +7,15 @@ import BackBottom from './BackBottom';

interface AutoScrollProps {
atBottom: boolean;
isScrolling: boolean;
onScrollToBottom: (type: 'auto' | 'click') => void;
}
const AutoScroll = memo<AutoScrollProps>(({ atBottom, onScrollToBottom }) => {
const AutoScroll = memo<AutoScrollProps>(({ atBottom, isScrolling, onScrollToBottom }) => {
const trackVisibility = useChatStore((s) => !!s.chatLoadingId);
const str = useChatStore(chatSelectors.chatsMessageString);

useEffect(() => {
if (atBottom && trackVisibility) {
if (atBottom && trackVisibility && !isScrolling) {
onScrollToBottom?.('auto');
}
}, [atBottom, trackVisibility, str]);
Expand Down
18 changes: 15 additions & 3 deletions src/features/Conversation/components/VirtualizedList/index.tsx
@@ -1,5 +1,5 @@
import isEqual from 'fast-deep-equal';
import React, { memo, useEffect, useRef, useState } from 'react';
import React, { memo, useCallback, useEffect, useRef, useState } from 'react';
import { Flexbox } from 'react-layout-kit';
import { Virtuoso, VirtuosoHandle } from 'react-virtuoso';

Expand Down Expand Up @@ -35,6 +35,7 @@ const VirtualizedList = memo<VirtualizedListProps>(({ mobile }) => {

const virtuosoRef = useRef<VirtuosoHandle>(null);
const [atBottom, setAtBottom] = useState(true);
const [isScrolling, setIsScrolling] = useState(false);

const [id, chatLoading] = useChatStore((s) => [
chatSelectors.currentChatKey(s),
Expand All @@ -53,6 +54,14 @@ const VirtualizedList = memo<VirtualizedListProps>(({ mobile }) => {
}
}, [id]);

const prevDataLengthRef = useRef(data.length);

const getFollowOutput = useCallback(() => {
const newFollowOutput = data.length > prevDataLengthRef.current ? 'auto' : false;
prevDataLengthRef.current = data.length;
return newFollowOutput;
}, [data.length]);

// overscan should be 1.5 times the height of the window
const overscan = typeof window !== 'undefined' ? window.innerHeight * 1.5 : 0;

Expand All @@ -62,17 +71,20 @@ const VirtualizedList = memo<VirtualizedListProps>(({ mobile }) => {
<Flexbox height={'100%'}>
<Virtuoso
atBottomStateChange={setAtBottom}
atBottomThreshold={60 * (mobile ? 2 : 1)}
atBottomThreshold={50 * (mobile ? 2 : 1)}
computeItemKey={(_, item) => item}
data={data}
followOutput={'auto'}
followOutput={getFollowOutput}
// increaseViewportBy={overscan}
initialTopMostItemIndex={data?.length - 1}
isScrolling={setIsScrolling}
itemContent={itemContent}
overscan={overscan}
ref={virtuosoRef}
/>
<AutoScroll
atBottom={atBottom}
isScrolling={isScrolling}
onScrollToBottom={(type) => {
const virtuoso = virtuosoRef.current;
switch (type) {
Expand Down