Message List: Fix jumping scroll when playing audio on mobile

This commit is contained in:
Alexander Zinchuk 2021-05-25 22:14:35 +03:00
parent 9564969311
commit 2e5a2d7000
2 changed files with 23 additions and 33 deletions

View File

@ -350,6 +350,27 @@ const MessageList: FC<OwnProps & StateProps & DispatchProps> = ({
} }
}, [isChatLoaded, messageIds, loadMoreAround, focusingId, isRestricted]); }, [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 // Handles updated message list, takes care of scroll repositioning
useLayoutEffectWithPrevDeps(([ useLayoutEffectWithPrevDeps(([
prevMessageIds, prevIsViewportNewest, prevContainerHeight, prevMessageIds, prevIsViewportNewest, prevContainerHeight,
@ -471,6 +492,7 @@ const MessageList: FC<OwnProps & StateProps & DispatchProps> = ({
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.timeEnd('scrollTop'); console.timeEnd('scrollTop');
} }
// This should match deps for `useOnChange` above
}, [messageIds, isViewportNewest, containerHeight, hasTools]); }, [messageIds, isViewportNewest, containerHeight, hasTools]);
useEffect(() => { useEffect(() => {
@ -512,11 +534,7 @@ const MessageList: FC<OwnProps & StateProps & DispatchProps> = ({
containerRef={containerRef} containerRef={containerRef}
className="messages-container" className="messages-container"
messageIds={messageIds || [lastMessage!.id]} messageIds={messageIds || [lastMessage!.id]}
containerHeight={containerHeight}
listItemElementsRef={listItemElementsRef}
focusingId={focusingId} focusingId={focusingId}
anchorIdRef={anchorIdRef}
anchorTopRef={anchorTopRef}
loadMoreForwards={loadMoreForwards} loadMoreForwards={loadMoreForwards}
loadMoreBackwards={loadMoreBackwards} loadMoreBackwards={loadMoreBackwards}
isViewportNewest={isViewportNewest} isViewportNewest={isViewportNewest}

View File

@ -13,15 +13,11 @@ type OwnProps = {
containerRef: MutableRefObject<HTMLDivElement | null>; containerRef: MutableRefObject<HTMLDivElement | null>;
className: string; className: string;
messageIds: number[]; messageIds: number[];
containerHeight?: number; focusingId?: number;
listItemElementsRef: MutableRefObject<HTMLDivElement[] | undefined>;
anchorIdRef: MutableRefObject<string | undefined>;
anchorTopRef: MutableRefObject<number | undefined>;
loadMoreForwards?: NoneToVoidFunction; loadMoreForwards?: NoneToVoidFunction;
loadMoreBackwards?: NoneToVoidFunction; loadMoreBackwards?: NoneToVoidFunction;
isViewportNewest?: boolean; isViewportNewest?: boolean;
firstUnreadId?: number; firstUnreadId?: number;
focusingId?: number;
onFabToggle: AnyToVoidFunction; onFabToggle: AnyToVoidFunction;
children: any; children: any;
}; };
@ -36,11 +32,7 @@ const MessageScroll: FC<OwnProps> = ({
containerRef, containerRef,
className, className,
messageIds, messageIds,
containerHeight,
listItemElementsRef,
focusingId, focusingId,
anchorIdRef,
anchorTopRef,
loadMoreForwards, loadMoreForwards,
loadMoreBackwards, loadMoreBackwards,
isViewportNewest, isViewportNewest,
@ -133,26 +125,6 @@ const MessageScroll: FC<OwnProps> = ({
} }
}, [focusingId]); }, [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 // Workaround for FAB flickering with tall incoming message
useOnChange(() => { useOnChange(() => {
isFabFrozen = true; isFabFrozen = true;