From 2e5a2d700073161967334f10a5a0c57c868f6632 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Tue, 25 May 2021 22:14:35 +0300 Subject: [PATCH] Message List: Fix jumping scroll when playing audio on mobile --- src/components/middle/MessageList.tsx | 26 +++++++++++++++++---- src/components/middle/MessageScroll.tsx | 30 +------------------------ 2 files changed, 23 insertions(+), 33 deletions(-) diff --git a/src/components/middle/MessageList.tsx b/src/components/middle/MessageList.tsx index b373f7d6..1ad1fddf 100644 --- a/src/components/middle/MessageList.tsx +++ b/src/components/middle/MessageList.tsx @@ -350,6 +350,27 @@ const MessageList: FC = ({ } }, [isChatLoaded, messageIds, loadMoreAround, focusingId, isRestricted]); + // Remember scroll position before repositioning it + useOnChange(() => { + if (!messageIds || !listItemElementsRef.current) { + return; + } + + const preservedItemElements = listItemElementsRef.current + .filter((element) => messageIds.includes(Number(element.dataset.messageId))); + + // We avoid the very first item as it may be a partly-loaded album + // and also because it may be removed when messages limit is reached + const anchor = preservedItemElements[1] || preservedItemElements[0]; + if (!anchor) { + return; + } + + anchorIdRef.current = anchor.id; + anchorTopRef.current = anchor.getBoundingClientRect().top; + // This should match deps for `useLayoutEffectWithPrevDeps` below + }, [messageIds, isViewportNewest, containerHeight, hasTools]); + // Handles updated message list, takes care of scroll repositioning useLayoutEffectWithPrevDeps(([ prevMessageIds, prevIsViewportNewest, prevContainerHeight, @@ -471,6 +492,7 @@ const MessageList: FC = ({ // eslint-disable-next-line no-console console.timeEnd('scrollTop'); } + // This should match deps for `useOnChange` above }, [messageIds, isViewportNewest, containerHeight, hasTools]); useEffect(() => { @@ -512,11 +534,7 @@ const MessageList: FC = ({ containerRef={containerRef} className="messages-container" messageIds={messageIds || [lastMessage!.id]} - containerHeight={containerHeight} - listItemElementsRef={listItemElementsRef} focusingId={focusingId} - anchorIdRef={anchorIdRef} - anchorTopRef={anchorTopRef} loadMoreForwards={loadMoreForwards} loadMoreBackwards={loadMoreBackwards} isViewportNewest={isViewportNewest} diff --git a/src/components/middle/MessageScroll.tsx b/src/components/middle/MessageScroll.tsx index 00923d87..983b743b 100644 --- a/src/components/middle/MessageScroll.tsx +++ b/src/components/middle/MessageScroll.tsx @@ -13,15 +13,11 @@ type OwnProps = { containerRef: MutableRefObject; className: string; messageIds: number[]; - containerHeight?: number; - listItemElementsRef: MutableRefObject; - anchorIdRef: MutableRefObject; - anchorTopRef: MutableRefObject; + focusingId?: number; loadMoreForwards?: NoneToVoidFunction; loadMoreBackwards?: NoneToVoidFunction; isViewportNewest?: boolean; firstUnreadId?: number; - focusingId?: number; onFabToggle: AnyToVoidFunction; children: any; }; @@ -36,11 +32,7 @@ const MessageScroll: FC = ({ containerRef, className, messageIds, - containerHeight, - listItemElementsRef, focusingId, - anchorIdRef, - anchorTopRef, loadMoreForwards, loadMoreBackwards, isViewportNewest, @@ -133,26 +125,6 @@ const MessageScroll: FC = ({ } }, [focusingId]); - // Remember scroll position before updating height - useOnChange(() => { - if (!listItemElementsRef.current) { - return; - } - - const preservedItemElements = listItemElementsRef.current - .filter((element) => messageIds.includes(Number(element.dataset.messageId))); - - // We avoid the very first item as it may be a partly-loaded album - // and also because it may be removed when messages limit is reached - const anchor = preservedItemElements[1] || preservedItemElements[0]; - if (!anchor) { - return; - } - - anchorIdRef.current = anchor.id; - anchorTopRef.current = anchor.getBoundingClientRect().top; - }, [messageIds, containerHeight]); - // Workaround for FAB flickering with tall incoming message useOnChange(() => { isFabFrozen = true;