[Perf] Comment Button: Detach from global
This commit is contained in:
parent
b80a1e0ee9
commit
17b6afb368
@ -1,18 +1,16 @@
|
|||||||
import React, {
|
import React, {
|
||||||
FC, memo, useCallback,
|
FC, memo, useCallback, useMemo,
|
||||||
} from '../../../lib/teact/teact';
|
} from '../../../lib/teact/teact';
|
||||||
import { withGlobal } from '../../../lib/teact/teactn';
|
import { getGlobal } from '../../../lib/teact/teactn';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ApiChat, ApiMessage, ApiThreadInfo, ApiUser,
|
ApiChat, ApiThreadInfo, ApiUser,
|
||||||
} from '../../../api/types';
|
} from '../../../api/types';
|
||||||
import { GlobalActions } from '../../../global/types';
|
import { GlobalActions } from '../../../global/types';
|
||||||
|
|
||||||
import { pick } from '../../../util/iteratees';
|
|
||||||
import { isUserId } from '../../../modules/helpers';
|
import { isUserId } from '../../../modules/helpers';
|
||||||
import { formatIntegerCompact } from '../../../util/textFormat';
|
import { formatIntegerCompact } from '../../../util/textFormat';
|
||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
import { selectThreadInfo } from '../../../modules/selectors';
|
|
||||||
import useLang from '../../../hooks/useLang';
|
import useLang from '../../../hooks/useLang';
|
||||||
|
|
||||||
import Avatar from '../../common/Avatar';
|
import Avatar from '../../common/Avatar';
|
||||||
@ -20,23 +18,14 @@ import Avatar from '../../common/Avatar';
|
|||||||
import './CommentButton.scss';
|
import './CommentButton.scss';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
message: ApiMessage;
|
|
||||||
disabled?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
type StateProps = {
|
|
||||||
threadInfo: ApiThreadInfo;
|
threadInfo: ApiThreadInfo;
|
||||||
usersById?: Record<string, ApiUser>;
|
disabled?: boolean;
|
||||||
chatsById?: Record<string, ApiChat>;
|
openChat: GlobalActions['openChat'];
|
||||||
};
|
};
|
||||||
|
|
||||||
type DispatchProps = Pick<GlobalActions, 'openChat'>;
|
const CommentButton: FC<OwnProps> = ({
|
||||||
|
|
||||||
const CommentButton: FC<OwnProps & StateProps & DispatchProps> = ({
|
|
||||||
disabled,
|
|
||||||
threadInfo,
|
threadInfo,
|
||||||
usersById,
|
disabled,
|
||||||
chatsById,
|
|
||||||
openChat,
|
openChat,
|
||||||
}) => {
|
}) => {
|
||||||
const lang = useLang();
|
const lang = useLang();
|
||||||
@ -48,14 +37,23 @@ const CommentButton: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
openChat({ id: chatId, threadId });
|
openChat({ id: chatId, threadId });
|
||||||
}, [openChat, 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) {
|
if (messagesCount === undefined) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const recentRepliers = recentReplierIds && recentReplierIds.map((peerId) => {
|
|
||||||
return isUserId(peerId) ? usersById![peerId] : chatsById![peerId];
|
|
||||||
}).filter(Boolean);
|
|
||||||
|
|
||||||
function renderRecentRepliers() {
|
function renderRecentRepliers() {
|
||||||
return (
|
return (
|
||||||
recentRepliers && recentRepliers.length > 0 && (
|
recentRepliers && recentRepliers.length > 0 && (
|
||||||
@ -93,21 +91,4 @@ const CommentButton: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default memo(withGlobal<OwnProps>(
|
export default memo(CommentButton);
|
||||||
(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));
|
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import {
|
|||||||
ApiUser,
|
ApiUser,
|
||||||
ApiChat,
|
ApiChat,
|
||||||
ApiSticker,
|
ApiSticker,
|
||||||
|
ApiThreadInfo,
|
||||||
} from '../../../api/types';
|
} from '../../../api/types';
|
||||||
import {
|
import {
|
||||||
AudioOrigin, FocusDirection, IAlbum, ISettings,
|
AudioOrigin, FocusDirection, IAlbum, ISettings,
|
||||||
@ -44,6 +45,7 @@ import {
|
|||||||
selectTheme,
|
selectTheme,
|
||||||
selectAllowedMessageActions,
|
selectAllowedMessageActions,
|
||||||
selectIsDownloading,
|
selectIsDownloading,
|
||||||
|
selectThreadInfo,
|
||||||
} from '../../../modules/selectors';
|
} from '../../../modules/selectors';
|
||||||
import {
|
import {
|
||||||
getMessageContent,
|
getMessageContent,
|
||||||
@ -160,9 +162,12 @@ type StateProps = {
|
|||||||
canAutoPlayMedia?: boolean;
|
canAutoPlayMedia?: boolean;
|
||||||
shouldLoopStickers?: boolean;
|
shouldLoopStickers?: boolean;
|
||||||
autoLoadFileMaxSizeMb: number;
|
autoLoadFileMaxSizeMb: number;
|
||||||
|
threadInfo?: ApiThreadInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
type DispatchProps = Pick<GlobalActions, 'toggleMessageSelection' | 'clickInlineButton' | 'disableContextMenuHint'>;
|
type DispatchProps = Pick<GlobalActions, (
|
||||||
|
'toggleMessageSelection' | 'clickInlineButton' | 'disableContextMenuHint' | 'openChat'
|
||||||
|
)>;
|
||||||
|
|
||||||
const NBSP = '\u00A0';
|
const NBSP = '\u00A0';
|
||||||
const GROUP_MESSAGE_HOVER_ATTRIBUTE = 'data-is-document-group-hover';
|
const GROUP_MESSAGE_HOVER_ATTRIBUTE = 'data-is-document-group-hover';
|
||||||
@ -224,9 +229,11 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
canAutoPlayMedia,
|
canAutoPlayMedia,
|
||||||
shouldLoopStickers,
|
shouldLoopStickers,
|
||||||
autoLoadFileMaxSizeMb,
|
autoLoadFileMaxSizeMb,
|
||||||
|
threadInfo,
|
||||||
toggleMessageSelection,
|
toggleMessageSelection,
|
||||||
clickInlineButton,
|
clickInlineButton,
|
||||||
disableContextMenuHint,
|
disableContextMenuHint,
|
||||||
|
openChat,
|
||||||
}) => {
|
}) => {
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
@ -260,7 +267,7 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
}, [appearanceOrder, markShown, noAppearanceAnimation]);
|
}, [appearanceOrder, markShown, noAppearanceAnimation]);
|
||||||
const { transitionClassNames } = useShowTransition(isShown, undefined, noAppearanceAnimation, false);
|
const { transitionClassNames } = useShowTransition(isShown, undefined, noAppearanceAnimation, false);
|
||||||
|
|
||||||
const { id: messageId, chatId, threadInfo } = message;
|
const { id: messageId, chatId } = message;
|
||||||
|
|
||||||
const isLocal = isMessageLocal(message);
|
const isLocal = isMessageLocal(message);
|
||||||
const isOwn = isOwnMessage(message);
|
const isOwn = isOwnMessage(message);
|
||||||
@ -389,11 +396,12 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
asForwarded,
|
asForwarded,
|
||||||
hasThread,
|
hasThread,
|
||||||
forceSenderName,
|
forceSenderName,
|
||||||
hasComments: message.threadInfo && message.threadInfo.messagesCount > 0,
|
hasComments: threadInfo && threadInfo?.messagesCount > 0,
|
||||||
hasActionButton: canForward || canFocus,
|
hasActionButton: canForward || canFocus,
|
||||||
});
|
});
|
||||||
const withCommentButton = message.threadInfo && (!isInDocumentGroup || isLastInDocumentGroup)
|
const withCommentButton = (
|
||||||
&& messageListType === 'thread' && !noComments;
|
threadInfo && (!isInDocumentGroup || isLastInDocumentGroup) && messageListType === 'thread' && !noComments
|
||||||
|
);
|
||||||
const withAppendix = contentClassName.includes('has-appendix');
|
const withAppendix = contentClassName.includes('has-appendix');
|
||||||
|
|
||||||
useEnsureMessage(
|
useEnsureMessage(
|
||||||
@ -754,7 +762,7 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
<i className="icon-arrow-right" />
|
<i className="icon-arrow-right" />
|
||||||
</Button>
|
</Button>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
{withCommentButton && <CommentButton message={message} disabled={noComments} />}
|
{withCommentButton && <CommentButton threadInfo={threadInfo!} disabled={noComments} openChat={openChat} />}
|
||||||
{withAppendix && (
|
{withAppendix && (
|
||||||
<div className="svg-appendix" dangerouslySetInnerHTML={isOwn ? APPENDIX_OWN : APPENDIX_NOT_OWN} />
|
<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,
|
message, album, withSenderName, withAvatar, threadId, messageListType,
|
||||||
} = ownProps;
|
} = ownProps;
|
||||||
const {
|
const {
|
||||||
id, chatId, viaBotId, replyToChatId, replyToMessageId, isOutgoing,
|
id, chatId, viaBotId, replyToChatId, replyToMessageId, isOutgoing, threadInfo,
|
||||||
} = message;
|
} = message;
|
||||||
|
|
||||||
const chat = selectChat(global, chatId);
|
const chat = selectChat(global, chatId);
|
||||||
@ -860,6 +868,9 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
|
|
||||||
const { canReply } = (messageListType === 'thread' && selectAllowedMessageActions(global, message, threadId)) || {};
|
const { canReply } = (messageListType === 'thread' && selectAllowedMessageActions(global, message, threadId)) || {};
|
||||||
const isDownloading = selectIsDownloading(global, message);
|
const isDownloading = selectIsDownloading(global, message);
|
||||||
|
const actualThreadInfo = threadInfo
|
||||||
|
? selectThreadInfo(global, threadInfo.chatId, threadInfo.threadId) || threadInfo
|
||||||
|
: undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
theme: selectTheme(global),
|
theme: selectTheme(global),
|
||||||
@ -894,6 +905,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
canAutoPlayMedia: selectCanAutoPlayMedia(global, message),
|
canAutoPlayMedia: selectCanAutoPlayMedia(global, message),
|
||||||
autoLoadFileMaxSizeMb: global.settings.byKey.autoLoadFileMaxSizeMb,
|
autoLoadFileMaxSizeMb: global.settings.byKey.autoLoadFileMaxSizeMb,
|
||||||
shouldLoopStickers: selectShouldLoopStickers(global),
|
shouldLoopStickers: selectShouldLoopStickers(global),
|
||||||
|
threadInfo: actualThreadInfo,
|
||||||
...(isOutgoing && { outgoingStatus: selectOutgoingStatus(global, message, messageListType === 'scheduled') }),
|
...(isOutgoing && { outgoingStatus: selectOutgoingStatus(global, message, messageListType === 'scheduled') }),
|
||||||
...(typeof uploadProgress === 'number' && { uploadProgress }),
|
...(typeof uploadProgress === 'number' && { uploadProgress }),
|
||||||
...(isFocused && { focusDirection, noFocusHighlight, isResizingContainer }),
|
...(isFocused && { focusDirection, noFocusHighlight, isResizingContainer }),
|
||||||
@ -903,5 +915,6 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
'toggleMessageSelection',
|
'toggleMessageSelection',
|
||||||
'clickInlineButton',
|
'clickInlineButton',
|
||||||
'disableContextMenuHint',
|
'disableContextMenuHint',
|
||||||
|
'openChat',
|
||||||
]),
|
]),
|
||||||
)(Message));
|
)(Message));
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user