fix: chat starts scrolled to bottom instead of visibly scrolling down

- Use onContentSizeChange to scroll after FlashList renders content
- Scroll without animation on initial load via needsInitialScroll ref
- Remove unreliable 100ms timeout scrollToEnd from message loading
This commit is contained in:
2026-02-09 19:23:45 +01:00
parent aabce1a5b0
commit 3ad4a77951
2 changed files with 13 additions and 7 deletions

View File

@@ -64,11 +64,11 @@ const Chat = () => {
string | undefined
>();
const [hasLoadedMessages, setHasLoadedMessages] = useState(false);
const needsInitialScroll = useRef(false);
useEffect(() => {
const keyboardDidShow = Keyboard.addListener(
"keyboardDidShow",
scrollToEnd,
const keyboardDidShow = Keyboard.addListener("keyboardDidShow", () =>
scrollToEnd(),
);
return () => keyboardDidShow.remove();
}, []);
@@ -90,7 +90,7 @@ const Chat = () => {
await ChatService.getConversation(conversationId);
const clientMessages = serverMessages.map(chatMessageToMessageData);
addMessages(clientMessages);
scrollToEnd();
needsInitialScroll.current = true;
}
} catch (error) {
console.error("Failed to load messages:", error);
@@ -102,9 +102,9 @@ const Chat = () => {
}, [isAuthLoading, isAuthenticated, hasLoadedMessages]),
);
const scrollToEnd = () => {
const scrollToEnd = (animated = true) => {
setTimeout(() => {
listRef.current?.scrollToEnd({ animated: true });
listRef.current?.scrollToEnd({ animated });
}, 100);
};
@@ -277,6 +277,12 @@ const Chat = () => {
keyExtractor={(item) => item.id}
keyboardDismissMode="interactive"
keyboardShouldPersistTaps="handled"
onContentSizeChange={() => {
if (needsInitialScroll.current) {
needsInitialScroll.current = false;
listRef.current?.scrollToEnd({ animated: false });
}
}}
ListFooterComponent={
isWaitingForResponse ? <TypingIndicator /> : null
}