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
17 changes: 9 additions & 8 deletions src/features/Conversation/components/VirtualizedList/index.tsx
Expand Up @@ -20,12 +20,10 @@ const itemContent = (index: number, id: string) => {
);
};

interface VirtualizedListProps {
mobile?: boolean;
}
const VirtualizedList = memo<VirtualizedListProps>(({ mobile }) => {
const VirtualizedList = memo(() => {
const virtuosoRef = useRef<VirtuosoHandle>(null);
const [atBottom, setAtBottom] = useState(true);
const [isScrolling, setIsScrolling] = useState(false);

const data = useChatStore(
(s) => ['empty', ...chatSelectors.currentChatIDsWithGuideMessage(s)],
Expand All @@ -40,7 +38,7 @@ const VirtualizedList = memo<VirtualizedListProps>(({ mobile }) => {
if (virtuosoRef.current) {
virtuosoRef.current.scrollToIndex({ align: 'end', behavior: 'auto', index: 'LAST' });
}
}, [id]);
}, [id, data.length]);
arvinxx marked this conversation as resolved.
Show resolved Hide resolved

// overscan should be 1.5 times the height of the window
const overscan = typeof window !== 'undefined' ? window.innerHeight * 1.5 : 0;
Expand All @@ -49,17 +47,20 @@ const VirtualizedList = memo<VirtualizedListProps>(({ mobile }) => {
<Flexbox height={'100%'}>
<Virtuoso
atBottomStateChange={setAtBottom}
atBottomThreshold={60 * (mobile ? 2 : 1)}
atBottomThreshold={50}
arvinxx marked this conversation as resolved.
Show resolved Hide resolved
computeItemKey={(_, item) => item}
data={data}
followOutput={'auto'}
// followOutput={'auto'}
sxjeru marked this conversation as resolved.
Show resolved Hide resolved
// increaseViewportBy={overscan}
initialTopMostItemIndex={data?.length - 1}
isScrolling={setIsScrolling}
itemContent={itemContent}
overscan={overscan}
overscan={{ main: overscan, reverse: overscan / 2 }}
arvinxx marked this conversation as resolved.
Show resolved Hide resolved
ref={virtuosoRef}
/>
<AutoScroll
atBottom={atBottom}
isScrolling={isScrolling}
onScrollToBottom={(type) => {
const virtuoso = virtuosoRef.current;
switch (type) {
Expand Down
4 changes: 1 addition & 3 deletions src/features/Conversation/index.tsx
Expand Up @@ -40,9 +40,7 @@ const Conversation = memo<ConversationProps>(({ chatInput, mobile }) => {
// `relative` is required, ChatInput's absolute position needs it
style={{ position: 'relative' }}
>
<div className={styles}>
{messagesInit ? <ChatList mobile={mobile} /> : <SkeletonList mobile={mobile} />}
</div>
<div className={styles}>{messagesInit ? <ChatList /> : <SkeletonList mobile={mobile} />}</div>
{chatInput}
<ChatHydration />
</Flexbox>
Expand Down