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]);
// 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<OwnProps & StateProps & DispatchProps> = ({
// 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<OwnProps & StateProps & DispatchProps> = ({
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}

View File

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