Skip to content

Commit cdde996

Browse files
authored
Merge pull request #44 from RonasIT/PRD-2153-modify-auto-scroll-behavior
PRD-2153: Allow user to scroll up while response is generating
2 parents 9c6350b + e91293d commit cdde996

1 file changed

Lines changed: 30 additions & 10 deletions

File tree

  • libs/mobile/chat/features/chat/src/lib/components/messages-list

libs/mobile/chat/features/chat/src/lib/components/messages-list/component.tsx

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { FlashList } from '@shopify/flash-list';
22
import { useLocalSearchParams } from 'expo-router';
33
import { delay } from 'lodash-es';
4-
import React, { ReactElement, useCallback, useRef, useState } from 'react';
5-
import { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';
4+
import React, { ReactElement, useCallback, useRef } from 'react';
5+
import { GestureResponderEvent, NativeScrollEvent, NativeSyntheticEvent } from 'react-native';
66
import { useSharedValue, withTiming } from 'react-native-reanimated';
77
import { AiMessageActions } from '@open-webui-react-native/mobile/chat/features/ai-message-actions';
88
import { useManageMessageSiblings } from '@open-webui-react-native/mobile/chat/features/use-manage-messages-siblings';
@@ -62,7 +62,8 @@ export default function ChatMessagesList({
6262
const isScrollToBottomAvailableTimeout = useRef<NodeJS.Timeout | null | number>(null); //NOTE: number needs to fix pipeline lint error
6363
const isScrollToBottomVisible = useSharedValue(0);
6464
const previousScrollY = useRef(0);
65-
const [autoscrollToBottomThreshold, setAutoscrollToBottomThreshold] = useState<number | undefined>(1);
65+
const shouldAutoscrollToBottomRef = useRef(true);
66+
const previousTouchY = useRef(0);
6667

6768
const { showPreviousSibling, showNextSibling, getSiblingsInfo } = useManageMessageSiblings(chatId, history);
6869
const { mutate: completeChat } = chatApi.useCompleteChat();
@@ -80,6 +81,12 @@ export default function ChatMessagesList({
8081
isScrollToBottomAvailable.current = true;
8182
}, 500);
8283

84+
if (shouldAutoscrollToBottomRef.current) {
85+
requestAnimationFrame(() => {
86+
listRef.current?.scrollToEnd({ animated: true });
87+
});
88+
}
89+
8390
if (!isMessagesListLoaded && listRef.current && messages?.length > 0) {
8491
delay(() => {
8592
listRef.current?.scrollToIndex({
@@ -120,6 +127,7 @@ export default function ChatMessagesList({
120127
//NOTE: Needs to hide scroll to bottom button to avoid its jumping while scrolling to bottom
121128
animateScrollToBottom(0);
122129
isScrollToBottomAvailable.current = false;
130+
123131
delay(() => {
124132
isScrollToBottomAvailable.current = true;
125133
}, 1000);
@@ -128,7 +136,6 @@ export default function ChatMessagesList({
128136
};
129137

130138
const handleEditPress = (index: number, messageId: string, content: string): void => {
131-
setAutoscrollToBottomThreshold(undefined);
132139
onEditPress(messageId, content);
133140
delay(() => {
134141
listRef.current?.scrollToIndex({
@@ -137,9 +144,6 @@ export default function ChatMessagesList({
137144
animated: true,
138145
});
139146
}, 500);
140-
delay(() => {
141-
setAutoscrollToBottomThreshold(1);
142-
}, 1000);
143147
};
144148

145149
const handleContinueResponsePress = (messageId: string): void => {
@@ -171,6 +175,23 @@ export default function ChatMessagesList({
171175
onFollowUpPress(text);
172176
};
173177

178+
const handleTouchStart = (e: GestureResponderEvent): void => {
179+
if (!isResponseGenerating) return;
180+
181+
shouldAutoscrollToBottomRef.current = false;
182+
previousTouchY.current = e.nativeEvent.pageY;
183+
};
184+
185+
const handleTouchMove = (e: GestureResponderEvent): void => {
186+
if (!isResponseGenerating) return;
187+
188+
const { pageY } = e.nativeEvent;
189+
const deltaY = pageY - previousTouchY.current;
190+
191+
previousTouchY.current = pageY;
192+
shouldAutoscrollToBottomRef.current = deltaY < 0;
193+
};
194+
174195
const renderItem = useCallback(
175196
({ item, index }: { item: Message; index: number }) => {
176197
const message = history?.messages[item.id];
@@ -244,14 +265,13 @@ export default function ChatMessagesList({
244265
ItemSeparatorComponent={() => <View className='h-20' />}
245266
data={messages}
246267
renderItem={renderItem}
247-
// TODO: Add autoscrollToBottom logic when it implemented in lib
248268
maintainVisibleContentPosition={{
249269
startRenderingFromBottom: true,
250-
animateAutoScrollToBottom: true,
251-
autoscrollToBottomThreshold,
252270
}}
253271
onContentSizeChange={handleContentSizeChange}
254272
onScroll={handleScroll}
273+
onTouchStart={handleTouchStart}
274+
onTouchMove={handleTouchMove}
255275
scrollEventThrottle={16}
256276
/>
257277
<ChatBottomButton isVisible={isScrollToBottomVisible} onPress={scrollToBottom} />

0 commit comments

Comments
 (0)