[Perf] Comment Button: Detach from global

This commit is contained in:
Alexander Zinchuk 2021-12-10 18:33:03 +01:00
parent b80a1e0ee9
commit 17b6afb368
2 changed files with 41 additions and 47 deletions

View File

@ -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<string, ApiUser>;
chatsById?: Record<string, ApiChat>;
disabled?: boolean;
openChat: GlobalActions['openChat'];
};
type DispatchProps = Pick<GlobalActions, 'openChat'>;
const CommentButton: FC<OwnProps & StateProps & DispatchProps> = ({
disabled,
const CommentButton: FC<OwnProps> = ({
threadInfo,
usersById,
chatsById,
disabled,
openChat,
}) => {
const lang = useLang();
@ -48,14 +37,23 @@ const CommentButton: FC<OwnProps & StateProps & DispatchProps> = ({
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<OwnProps & StateProps & DispatchProps> = ({
);
};
export default memo(withGlobal<OwnProps>(
(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);

View File

@ -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<GlobalActions, 'toggleMessageSelection' | 'clickInlineButton' | 'disableContextMenuHint'>;
type DispatchProps = Pick<GlobalActions, (
'toggleMessageSelection' | 'clickInlineButton' | 'disableContextMenuHint' | 'openChat'
)>;
const NBSP = '\u00A0';
const GROUP_MESSAGE_HOVER_ATTRIBUTE = 'data-is-document-group-hover';
@ -224,9 +229,11 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
canAutoPlayMedia,
shouldLoopStickers,
autoLoadFileMaxSizeMb,
threadInfo,
toggleMessageSelection,
clickInlineButton,
disableContextMenuHint,
openChat,
}) => {
// eslint-disable-next-line no-null/no-null
const ref = useRef<HTMLDivElement>(null);
@ -260,7 +267,7 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
}, [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<OwnProps & StateProps & DispatchProps> = ({
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<OwnProps & StateProps & DispatchProps> = ({
<i className="icon-arrow-right" />
</Button>
) : undefined}
{withCommentButton && <CommentButton message={message} disabled={noComments} />}
{withCommentButton && <CommentButton threadInfo={threadInfo!} disabled={noComments} openChat={openChat} />}
{withAppendix && (
<div className="svg-appendix" dangerouslySetInnerHTML={isOwn ? APPENDIX_OWN : APPENDIX_NOT_OWN} />
)}
@ -810,7 +818,7 @@ export default memo(withGlobal<OwnProps>(
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<OwnProps>(
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<OwnProps>(
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<OwnProps>(
'toggleMessageSelection',
'clickInlineButton',
'disableContextMenuHint',
'openChat',
]),
)(Message));