[Perf] Message: Delay some effects while opening message list
This commit is contained in:
parent
62d3d7cc42
commit
6a57908045
@ -22,6 +22,7 @@ import { preventMessageInputBlur } from './helpers/preventMessageInputBlur';
|
||||
import useScrollHooks from './hooks/useScrollHooks';
|
||||
import useMessageObservers from './hooks/useMessageObservers';
|
||||
import usePrevious from '../../hooks/usePrevious';
|
||||
import useDerivedSignal from '../../hooks/useDerivedSignal';
|
||||
|
||||
import Message from './message/Message';
|
||||
import SponsoredMessage from './message/SponsoredMessage';
|
||||
@ -89,6 +90,8 @@ const MessageListContent: FC<OwnProps> = ({
|
||||
}) => {
|
||||
const { openHistoryCalendar } = getActions();
|
||||
|
||||
const getIsReady = useDerivedSignal(isReady);
|
||||
|
||||
const {
|
||||
observeIntersectionForReading,
|
||||
observeIntersectionForLoading,
|
||||
@ -237,6 +240,7 @@ const MessageListContent: FC<OwnProps> = ({
|
||||
isLastInList={position.isLastInList}
|
||||
memoFirstUnreadIdRef={memoFirstUnreadIdRef}
|
||||
onPinnedIntersectionChange={onPinnedIntersectionChange}
|
||||
getIsMessageListReady={getIsReady}
|
||||
/>,
|
||||
message.id === threadTopMessageId && (
|
||||
<div className="local-action-message" key="discussion-started">
|
||||
|
||||
@ -1,11 +1,6 @@
|
||||
import type { FC } from '../../../lib/teact/teact';
|
||||
import React, {
|
||||
memo,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
memo, useCallback, useEffect, useMemo, useRef, useState,
|
||||
} from '../../../lib/teact/teact';
|
||||
import { getActions, withGlobal } from '../../../global';
|
||||
import type {
|
||||
@ -33,6 +28,7 @@ import { AudioOrigin } from '../../../types';
|
||||
import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
||||
import { useOnIntersect } from '../../../hooks/useIntersectionObserver';
|
||||
import type { PinnedIntersectionChangedCallback } from '../hooks/usePinnedMessage';
|
||||
import type { Signal } from '../../../util/signals';
|
||||
|
||||
import { IS_ANDROID, IS_TRANSLATION_SUPPORTED } from '../../../util/windowEnvironment';
|
||||
import { EMOJI_STATUS_LOOP_LIMIT, GENERAL_TOPIC_ID, IS_ELECTRON } from '../../../config';
|
||||
@ -191,6 +187,7 @@ type OwnProps =
|
||||
isJustAdded: boolean;
|
||||
memoFirstUnreadIdRef: { current: number | undefined };
|
||||
onPinnedIntersectionChange: PinnedIntersectionChangedCallback;
|
||||
getIsMessageListReady: Signal<boolean>;
|
||||
}
|
||||
& MessagePositionProperties;
|
||||
|
||||
@ -366,6 +363,7 @@ const Message: FC<OwnProps & StateProps> = ({
|
||||
withStickerEffects,
|
||||
isConnected,
|
||||
onPinnedIntersectionChange,
|
||||
getIsMessageListReady,
|
||||
}) => {
|
||||
const {
|
||||
toggleMessageSelection,
|
||||
@ -400,7 +398,13 @@ const Message: FC<OwnProps & StateProps> = ({
|
||||
handleContextMenu: onContextMenu,
|
||||
handleContextMenuClose,
|
||||
handleContextMenuHide,
|
||||
} = useContextMenuHandlers(ref, isTouchScreen && isInSelectMode, !IS_ELECTRON, IS_ANDROID);
|
||||
} = useContextMenuHandlers(
|
||||
ref,
|
||||
isTouchScreen && isInSelectMode,
|
||||
!IS_ELECTRON,
|
||||
IS_ANDROID,
|
||||
getIsMessageListReady,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (isContextMenuOpen) {
|
||||
@ -512,6 +516,7 @@ const Message: FC<OwnProps & StateProps> = ({
|
||||
isContextMenuShown,
|
||||
quickReactionRef,
|
||||
isInDocumentGroupNotLast,
|
||||
getIsMessageListReady,
|
||||
);
|
||||
|
||||
const {
|
||||
@ -716,11 +721,6 @@ const Message: FC<OwnProps & StateProps> = ({
|
||||
}
|
||||
}, [hasUnreadReaction, messageId, animateUnreadReaction]);
|
||||
|
||||
let style = '';
|
||||
let calculatedWidth;
|
||||
let reactionsMaxWidth;
|
||||
let contentWidth: number | undefined;
|
||||
let noMediaCorners = false;
|
||||
const albumLayout = useMemo(() => {
|
||||
return isAlbum
|
||||
? calculateAlbumLayout(isOwn, Boolean(asForwarded), Boolean(noAvatars), album!, isMobile)
|
||||
@ -728,56 +728,76 @@ const Message: FC<OwnProps & StateProps> = ({
|
||||
}, [isAlbum, isOwn, asForwarded, noAvatars, album, isMobile]);
|
||||
|
||||
const extraPadding = asForwarded ? 28 : 0;
|
||||
if (!isAlbum && (photo || video || invoice?.extendedMedia)) {
|
||||
let width: number | undefined;
|
||||
if (photo) {
|
||||
width = calculateMediaDimensions(message, asForwarded, noAvatars, isMobile).width;
|
||||
} else if (video) {
|
||||
if (video.isRound) {
|
||||
width = ROUND_VIDEO_DIMENSIONS_PX;
|
||||
} else {
|
||||
width = calculateMediaDimensions(message, asForwarded, noAvatars, isMobile).width;
|
||||
}
|
||||
} else if (invoice?.extendedMedia && (
|
||||
invoice.extendedMedia.width && invoice.extendedMedia.height
|
||||
)) {
|
||||
const { width: previewWidth, height: previewHeight } = invoice.extendedMedia;
|
||||
width = calculateDimensionsForMessageMedia({
|
||||
width: previewWidth,
|
||||
height: previewHeight,
|
||||
fromOwnMessage: isOwn,
|
||||
asForwarded,
|
||||
noAvatars,
|
||||
isMobile,
|
||||
}).width;
|
||||
}
|
||||
|
||||
if (width) {
|
||||
if (width < MIN_MEDIA_WIDTH_WITH_TEXT) {
|
||||
contentWidth = width;
|
||||
const sizeCalculations = useMemo(() => {
|
||||
let calculatedWidth;
|
||||
let contentWidth: number | undefined;
|
||||
let noMediaCorners = false;
|
||||
let style = '';
|
||||
let reactionsMaxWidth;
|
||||
|
||||
if (!isAlbum && (photo || video || invoice?.extendedMedia)) {
|
||||
let width: number | undefined;
|
||||
if (photo) {
|
||||
width = calculateMediaDimensions(message, asForwarded, noAvatars, isMobile).width;
|
||||
} else if (video) {
|
||||
if (video.isRound) {
|
||||
width = ROUND_VIDEO_DIMENSIONS_PX;
|
||||
} else {
|
||||
width = calculateMediaDimensions(message, asForwarded, noAvatars, isMobile).width;
|
||||
}
|
||||
} else if (invoice?.extendedMedia && (
|
||||
invoice.extendedMedia.width && invoice.extendedMedia.height
|
||||
)) {
|
||||
const { width: previewWidth, height: previewHeight } = invoice.extendedMedia;
|
||||
width = calculateDimensionsForMessageMedia({
|
||||
width: previewWidth,
|
||||
height: previewHeight,
|
||||
fromOwnMessage: isOwn,
|
||||
asForwarded,
|
||||
noAvatars,
|
||||
isMobile,
|
||||
}).width;
|
||||
}
|
||||
calculatedWidth = Math.max(getMinMediaWidth(text?.text, isMediaWithCommentButton), width);
|
||||
if (invoice?.extendedMedia && calculatedWidth - width > NO_MEDIA_CORNERS_THRESHOLD) {
|
||||
|
||||
if (width) {
|
||||
if (width < MIN_MEDIA_WIDTH_WITH_TEXT) {
|
||||
contentWidth = width;
|
||||
}
|
||||
calculatedWidth = Math.max(getMinMediaWidth(text?.text, isMediaWithCommentButton), width);
|
||||
if (invoice?.extendedMedia && calculatedWidth - width > NO_MEDIA_CORNERS_THRESHOLD) {
|
||||
noMediaCorners = true;
|
||||
}
|
||||
}
|
||||
} else if (albumLayout) {
|
||||
calculatedWidth = Math.max(
|
||||
getMinMediaWidth(text?.text, isMediaWithCommentButton), albumLayout.containerStyle.width,
|
||||
);
|
||||
if (calculatedWidth - albumLayout.containerStyle.width > NO_MEDIA_CORNERS_THRESHOLD) {
|
||||
noMediaCorners = true;
|
||||
}
|
||||
}
|
||||
} else if (albumLayout) {
|
||||
calculatedWidth = Math.max(
|
||||
getMinMediaWidth(text?.text, isMediaWithCommentButton), albumLayout.containerStyle.width,
|
||||
);
|
||||
if (calculatedWidth - albumLayout.containerStyle.width > NO_MEDIA_CORNERS_THRESHOLD) {
|
||||
noMediaCorners = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (calculatedWidth) {
|
||||
style = `width: ${calculatedWidth + extraPadding}px`;
|
||||
reactionsMaxWidth = calculatedWidth + EXTRA_SPACE_FOR_REACTIONS;
|
||||
} else if (sticker && !hasSubheader) {
|
||||
const { width } = getStickerDimensions(sticker, isMobile);
|
||||
style = `width: ${width + extraPadding}px`;
|
||||
reactionsMaxWidth = width + EXTRA_SPACE_FOR_REACTIONS;
|
||||
}
|
||||
if (calculatedWidth) {
|
||||
style = `width: ${calculatedWidth + extraPadding}px`;
|
||||
reactionsMaxWidth = calculatedWidth + EXTRA_SPACE_FOR_REACTIONS;
|
||||
} else if (sticker && !hasSubheader) {
|
||||
const { width } = getStickerDimensions(sticker, isMobile);
|
||||
style = `width: ${width + extraPadding}px`;
|
||||
reactionsMaxWidth = width + EXTRA_SPACE_FOR_REACTIONS;
|
||||
}
|
||||
|
||||
return {
|
||||
contentWidth, noMediaCorners, style, reactionsMaxWidth,
|
||||
};
|
||||
}, [
|
||||
albumLayout, asForwarded, extraPadding, hasSubheader, invoice?.extendedMedia, isAlbum, isMediaWithCommentButton,
|
||||
isMobile, isOwn, message, noAvatars, photo, sticker, text?.text, video,
|
||||
]);
|
||||
|
||||
const {
|
||||
contentWidth, noMediaCorners, style, reactionsMaxWidth,
|
||||
} = sizeCalculations;
|
||||
|
||||
function renderAvatar() {
|
||||
const hiddenName = (!avatarPeer && forwardInfo) ? forwardInfo.hiddenUserName : undefined;
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import type { RefObject } from 'react';
|
||||
import type React from '../../../../lib/teact/teact';
|
||||
import type { Signal } from '../../../../util/signals';
|
||||
|
||||
import { useEffect, useRef } from '../../../../lib/teact/teact';
|
||||
import { requestMeasure } from '../../../../lib/fasterdom/fasterdom';
|
||||
import { getActions } from '../../../../global';
|
||||
@ -33,6 +35,7 @@ export default function useOuterHandlers(
|
||||
isContextMenuShown: boolean,
|
||||
quickReactionRef: RefObject<HTMLDivElement>,
|
||||
shouldHandleMouseLeave: boolean,
|
||||
getIsMessageListReady: Signal<boolean>,
|
||||
) {
|
||||
const { setReplyingToId, sendDefaultReaction } = getActions();
|
||||
|
||||
@ -142,7 +145,7 @@ export default function useOuterHandlers(
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!IS_TOUCH_ENV || isInSelectMode || !canReply || isContextMenuShown) {
|
||||
if (!IS_TOUCH_ENV || isInSelectMode || !canReply || isContextMenuShown || !getIsMessageListReady()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@ -176,6 +179,7 @@ export default function useOuterHandlers(
|
||||
});
|
||||
}, [
|
||||
containerRef, isInSelectMode, messageId, setReplyingToId, markSwiped, unmarkSwiped, canReply, isContextMenuShown,
|
||||
getIsMessageListReady,
|
||||
]);
|
||||
|
||||
function handleMouseLeave(e: React.MouseEvent<HTMLDivElement>) {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import type { RefObject } from 'react';
|
||||
import type { Signal } from '../util/signals';
|
||||
import { useState, useEffect } from '../lib/teact/teact';
|
||||
import { addExtraClass, removeExtraClass } from '../lib/teact/teact-dom';
|
||||
import { requestMutation } from '../lib/fasterdom/fasterdom';
|
||||
@ -23,6 +24,7 @@ const useContextMenuHandlers = (
|
||||
isMenuDisabled?: boolean,
|
||||
shouldDisableOnLink?: boolean,
|
||||
shouldDisableOnLongTap?: boolean,
|
||||
getIsReady?: Signal<boolean>,
|
||||
) => {
|
||||
const [isContextMenuOpen, setIsContextMenuOpen] = useState(false);
|
||||
const [contextMenuPosition, setContextMenuPosition] = useState<IAnchorPosition | undefined>(undefined);
|
||||
@ -65,7 +67,7 @@ const useContextMenuHandlers = (
|
||||
|
||||
// Support context menu on touch devices
|
||||
useEffect(() => {
|
||||
if (isMenuDisabled || !IS_TOUCH_ENV || shouldDisableOnLongTap) {
|
||||
if (isMenuDisabled || !IS_TOUCH_ENV || shouldDisableOnLongTap || (getIsReady && !getIsReady())) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@ -149,7 +151,9 @@ const useContextMenuHandlers = (
|
||||
element.removeEventListener('touchend', clearLongPressTimer, true);
|
||||
element.removeEventListener('touchmove', clearLongPressTimer);
|
||||
};
|
||||
}, [contextMenuPosition, isMenuDisabled, shouldDisableOnLongTap, elementRef, shouldDisableOnLink]);
|
||||
}, [
|
||||
contextMenuPosition, isMenuDisabled, shouldDisableOnLongTap, elementRef, shouldDisableOnLink, getIsReady,
|
||||
]);
|
||||
|
||||
return {
|
||||
isContextMenuOpen,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user