From 17b6afb368d2a1d029575b91ce603f0fc0219afb Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Fri, 10 Dec 2021 18:33:03 +0100 Subject: [PATCH] [Perf] Comment Button: Detach from global --- .../middle/message/CommentButton.tsx | 61 +++++++------------ src/components/middle/message/Message.tsx | 27 +++++--- 2 files changed, 41 insertions(+), 47 deletions(-) diff --git a/src/components/middle/message/CommentButton.tsx b/src/components/middle/message/CommentButton.tsx index caa1fc619..84973bb3c 100644 --- a/src/components/middle/message/CommentButton.tsx +++ b/src/components/middle/message/CommentButton.tsx @@ -1,18 +1,16 @@ import React, { - FC, memo, useCallback, + FC, memo, useCallback, useMemo, } from '../../../lib/teact/teact'; -import { withGlobal } from '../../../lib/teact/teactn'; +import { getGlobal } from '../../../lib/teact/teactn'; import { - ApiChat, ApiMessage, ApiThreadInfo, ApiUser, + ApiChat, ApiThreadInfo, ApiUser, } from '../../../api/types'; import { GlobalActions } from '../../../global/types'; -import { pick } from '../../../util/iteratees'; import { isUserId } from '../../../modules/helpers'; import { formatIntegerCompact } from '../../../util/textFormat'; import buildClassName from '../../../util/buildClassName'; -import { selectThreadInfo } from '../../../modules/selectors'; import useLang from '../../../hooks/useLang'; import Avatar from '../../common/Avatar'; @@ -20,23 +18,14 @@ import Avatar from '../../common/Avatar'; import './CommentButton.scss'; type OwnProps = { - message: ApiMessage; - disabled?: boolean; -}; - -type StateProps = { threadInfo: ApiThreadInfo; - usersById?: Record; - chatsById?: Record; + disabled?: boolean; + openChat: GlobalActions['openChat']; }; -type DispatchProps = Pick; - -const CommentButton: FC = ({ - disabled, +const CommentButton: FC = ({ threadInfo, - usersById, - chatsById, + disabled, openChat, }) => { const lang = useLang(); @@ -48,14 +37,23 @@ const CommentButton: FC = ({ openChat({ id: chatId, threadId }); }, [openChat, chatId, threadId]); + const recentRepliers = useMemo(() => { + if (!recentReplierIds?.length) { + return undefined; + } + + // No need for expensive global updates on chats and users, so we avoid them + const { users: { byId: usersById }, chats: { byId: chatsById } } = getGlobal(); + + return recentReplierIds.map((peerId) => { + return isUserId(peerId) ? usersById[peerId] : chatsById[peerId]; + }).filter(Boolean); + }, [recentReplierIds]); + if (messagesCount === undefined) { return undefined; } - const recentRepliers = recentReplierIds && recentReplierIds.map((peerId) => { - return isUserId(peerId) ? usersById![peerId] : chatsById![peerId]; - }).filter(Boolean); - function renderRecentRepliers() { return ( recentRepliers && recentRepliers.length > 0 && ( @@ -93,21 +91,4 @@ const CommentButton: FC = ({ ); }; -export default memo(withGlobal( - (global, { message }) => { - const { threadId, chatId } = message.threadInfo!; - - const threadInfo = selectThreadInfo(global, chatId, threadId) || message.threadInfo!; - const { byId: usersById } = global.users; - const { byId: chatsById } = global.chats; - - return { - threadInfo, - usersById, - chatsById, - }; - }, - (setGlobal, actions): DispatchProps => pick(actions, [ - 'openChat', - ]), -)(CommentButton)); +export default memo(CommentButton); diff --git a/src/components/middle/message/Message.tsx b/src/components/middle/message/Message.tsx index 2c3f4a9ca..c9a284072 100644 --- a/src/components/middle/message/Message.tsx +++ b/src/components/middle/message/Message.tsx @@ -15,6 +15,7 @@ import { ApiUser, ApiChat, ApiSticker, + ApiThreadInfo, } from '../../../api/types'; import { AudioOrigin, FocusDirection, IAlbum, ISettings, @@ -44,6 +45,7 @@ import { selectTheme, selectAllowedMessageActions, selectIsDownloading, + selectThreadInfo, } from '../../../modules/selectors'; import { getMessageContent, @@ -160,9 +162,12 @@ type StateProps = { canAutoPlayMedia?: boolean; shouldLoopStickers?: boolean; autoLoadFileMaxSizeMb: number; + threadInfo?: ApiThreadInfo; }; -type DispatchProps = Pick; +type DispatchProps = Pick; const NBSP = '\u00A0'; const GROUP_MESSAGE_HOVER_ATTRIBUTE = 'data-is-document-group-hover'; @@ -224,9 +229,11 @@ const Message: FC = ({ canAutoPlayMedia, shouldLoopStickers, autoLoadFileMaxSizeMb, + threadInfo, toggleMessageSelection, clickInlineButton, disableContextMenuHint, + openChat, }) => { // eslint-disable-next-line no-null/no-null const ref = useRef(null); @@ -260,7 +267,7 @@ const Message: FC = ({ }, [appearanceOrder, markShown, noAppearanceAnimation]); const { transitionClassNames } = useShowTransition(isShown, undefined, noAppearanceAnimation, false); - const { id: messageId, chatId, threadInfo } = message; + const { id: messageId, chatId } = message; const isLocal = isMessageLocal(message); const isOwn = isOwnMessage(message); @@ -389,11 +396,12 @@ const Message: FC = ({ asForwarded, hasThread, forceSenderName, - hasComments: message.threadInfo && message.threadInfo.messagesCount > 0, + hasComments: threadInfo && threadInfo?.messagesCount > 0, hasActionButton: canForward || canFocus, }); - const withCommentButton = message.threadInfo && (!isInDocumentGroup || isLastInDocumentGroup) - && messageListType === 'thread' && !noComments; + const withCommentButton = ( + threadInfo && (!isInDocumentGroup || isLastInDocumentGroup) && messageListType === 'thread' && !noComments + ); const withAppendix = contentClassName.includes('has-appendix'); useEnsureMessage( @@ -754,7 +762,7 @@ const Message: FC = ({ ) : undefined} - {withCommentButton && } + {withCommentButton && } {withAppendix && (
)} @@ -810,7 +818,7 @@ export default memo(withGlobal( message, album, withSenderName, withAvatar, threadId, messageListType, } = ownProps; const { - id, chatId, viaBotId, replyToChatId, replyToMessageId, isOutgoing, + id, chatId, viaBotId, replyToChatId, replyToMessageId, isOutgoing, threadInfo, } = message; const chat = selectChat(global, chatId); @@ -860,6 +868,9 @@ export default memo(withGlobal( const { canReply } = (messageListType === 'thread' && selectAllowedMessageActions(global, message, threadId)) || {}; const isDownloading = selectIsDownloading(global, message); + const actualThreadInfo = threadInfo + ? selectThreadInfo(global, threadInfo.chatId, threadInfo.threadId) || threadInfo + : undefined; return { theme: selectTheme(global), @@ -894,6 +905,7 @@ export default memo(withGlobal( canAutoPlayMedia: selectCanAutoPlayMedia(global, message), autoLoadFileMaxSizeMb: global.settings.byKey.autoLoadFileMaxSizeMb, shouldLoopStickers: selectShouldLoopStickers(global), + threadInfo: actualThreadInfo, ...(isOutgoing && { outgoingStatus: selectOutgoingStatus(global, message, messageListType === 'scheduled') }), ...(typeof uploadProgress === 'number' && { uploadProgress }), ...(isFocused && { focusDirection, noFocusHighlight, isResizingContainer }), @@ -903,5 +915,6 @@ export default memo(withGlobal( 'toggleMessageSelection', 'clickInlineButton', 'disableContextMenuHint', + 'openChat', ]), )(Message));