diff --git a/app/soapbox/features/chats/components/chat_message_list.tsx b/app/soapbox/features/chats/components/chat_message_list.tsx index 41f0c1f12..a6719271a 100644 --- a/app/soapbox/features/chats/components/chat_message_list.tsx +++ b/app/soapbox/features/chats/components/chat_message_list.tsx @@ -6,7 +6,7 @@ import { } from 'immutable'; import escape from 'lodash/escape'; import throttle from 'lodash/throttle'; -import React, { useState, useEffect, useRef } from 'react'; +import React, { useState, useEffect, useRef, useLayoutEffect, useMemo } from 'react'; import { useIntl, defineMessages } from 'react-intl'; import { createSelector } from 'reselect'; @@ -78,7 +78,10 @@ const ChatMessageList: React.FC = ({ chatId, chatMessageIds }) const node = useRef(null); const messagesEnd = useRef(null); - const lastComputedScroll = useRef(0); + const lastComputedScroll = useRef(undefined); + const scrollBottom = useRef(undefined); + + const initialCount = useMemo(() => chatMessages.count(), []); const scrollToBottom = () => { messagesEnd.current?.scrollIntoView(false); @@ -141,37 +144,45 @@ const ChatMessageList: React.FC = ({ chatId, chatMessageIds }) }; }, []); - // const getScrollBottom = (): number | undefined => { - // if (node.current) { - // const { scrollHeight, scrollTop } = node.current; - // return scrollHeight - scrollTop; - // } - // - // return undefined; - // }; + useLayoutEffect(() => { + if (node.current) { + const { scrollHeight, scrollTop } = node.current; + scrollBottom.current = scrollHeight - scrollTop; + } + }); - // const restoreScrollPosition = (scrollBottom: number) => { - // if (node.current) { - // lastComputedScroll.current = node.current.scrollHeight - scrollBottom; - // node.current.scrollTop = lastComputedScroll.current; - // } - // }; + const restoreScrollPosition = () => { + if (node.current && scrollBottom.current) { + lastComputedScroll.current = node.current.scrollHeight - scrollBottom.current; + node.current.scrollTop = lastComputedScroll.current; + } + }; // Stick scrollbar to bottom. useEffect(() => { - if (isNearBottom() || initialLoad) { + if (isNearBottom()) { + scrollToBottom(); + } + + // First load. + if (chatMessages.count() !== initialCount) { + setInitialLoad(false); + setIsLoading(false); scrollToBottom(); } }, [chatMessages.count()]); + useEffect(() => { + scrollToBottom(); + }, [messagesEnd.current]); + // History added. useEffect(() => { - // Retain scroll bar position when loading old messages - // restoreScrollPosition(scrollBottom); - - setIsLoading(false); - setInitialLoad(false); - }, [chatMessages.getIn([0, 'id'])]); + // Retain scroll bar position when loading old messages. + if (!initialLoad) { + restoreScrollPosition(); + } + }, [chatMessageIds.first()]); const handleLoadMore = () => { const maxId = chatMessages.getIn([0, 'id']) as string;