Message List: Fix flick when opening chat on message (#6715)

This commit is contained in:
zubiden 2026-02-22 23:43:52 +01:00 committed by Alexander Zinchuk
parent b5903e9594
commit 42c86e50a5
3 changed files with 42 additions and 6 deletions

View File

@ -13,7 +13,7 @@ import {
MESSAGE_LIST_SLICE,
SERVICE_NOTIFICATIONS_USER_ID,
} from '../../config';
import { forceMeasure, requestForcedReflow, requestMeasure, requestMutation } from '../../lib/fasterdom/fasterdom';
import { forceMeasure, requestMeasure, requestMutation } from '../../lib/fasterdom/fasterdom';
import {
getIsSavedDialog,
getMessageHtmlId,
@ -66,6 +66,7 @@ import { debounce, onTickEnd } from '../../util/schedulers';
import getOffsetToContainer from '../../util/visibility/getOffsetToContainer';
import { REM } from '../common/helpers/mediaDimensions';
import { groupMessages } from './helpers/groupMessages';
import { requestMessageListReflow } from './helpers/messageListReflow';
import { preventMessageInputBlur } from './helpers/preventMessageInputBlur';
import useInterval from '../../hooks/schedulers/useInterval';
@ -677,7 +678,7 @@ const MessageList = ({
}, MESSAGE_ANIMATION_DURATION);
}
requestForcedReflow(() => {
requestMessageListReflow(() => {
const { scrollTop, scrollHeight, offsetHeight } = container;
const scrollOffset = scrollOffsetRef.current;

View File

@ -0,0 +1,24 @@
import { requestForcedReflow } from '../../../lib/fasterdom/fasterdom';
type ReflowCallback = () => (NoneToVoidFunction | void);
let afterReflowCallbacks: ReflowCallback[] = [];
// For children effects that need to run after the message list reflow
export function requestAfterMessageListReflow(cb: ReflowCallback) {
afterReflowCallbacks.push(cb);
}
export function requestMessageListReflow(cb: ReflowCallback) {
requestForcedReflow(() => {
const mutationFn = cb();
const callbacks = afterReflowCallbacks;
afterReflowCallbacks = [];
for (const afterCb of callbacks) {
requestForcedReflow(afterCb);
}
return mutationFn;
});
}

View File

@ -1,5 +1,5 @@
import type { ElementRef } from '../../../../lib/teact/teact';
import { useLayoutEffect } from '../../../../lib/teact/teact';
import { useLayoutEffect, useRef } from '../../../../lib/teact/teact';
import { addExtraClass } from '../../../../lib/teact/teact-dom';
import type { FocusDirection, ScrollTargetPosition } from '../../../../types';
@ -10,6 +10,7 @@ import {
} from '../../../../lib/fasterdom/fasterdom';
import animateScroll from '../../../../util/animateScroll';
import { REM } from '../../../common/helpers/mediaDimensions';
import { requestAfterMessageListReflow } from '../../helpers/messageListReflow';
// This is used when the viewport was replaced.
const BOTTOM_FOCUS_OFFSET = 500;
@ -36,7 +37,12 @@ export default function useFocusMessageListElement({
isQuote?: boolean;
scrollTargetPosition?: ScrollTargetPosition;
}) {
const isRelocatedRef = useRef(!isJustAdded);
useLayoutEffect(() => {
const isRelocated = isRelocatedRef.current;
isRelocatedRef.current = false;
if (isFocused && elementRef.current) {
const messagesContainer = elementRef.current.closest<HTMLDivElement>('.MessageList');
if (!messagesContainer) return;
@ -72,9 +78,14 @@ export default function useFocusMessageListElement({
return result;
};
requestMeasure(() => {
requestMutation(exec()!);
});
if (isRelocated) {
// We need this to override scroll setting from Message List layout effect
requestAfterMessageListReflow(exec);
} else {
requestMeasure(() => {
requestMutation(exec()!);
});
}
}
}, [
elementRef, isFocused, focusDirection, noFocusHighlight, isResizingContainer, isQuote, scrollTargetPosition,