[Perf] Message: Extract selectCanReplyToMessage from selectAllowedMessageActionsSlow

This commit is contained in:
Alexander Zinchuk 2024-09-06 15:42:48 +02:00
parent 67bdfe318b
commit 692cf8b270
8 changed files with 49 additions and 40 deletions

View File

@ -22,7 +22,7 @@ import {
isUserId, isUserId,
} from '../../global/helpers'; } from '../../global/helpers';
import { import {
selectAllowedMessageActions, selectAllowedMessageActionsSlow,
selectBot, selectBot,
selectChat, selectChatFullInfo, selectCurrentMessageIds, selectChat, selectChatFullInfo, selectCurrentMessageIds,
selectCurrentMessageList, selectSenderFromMessage, selectTabState, selectCurrentMessageList, selectSenderFromMessage, selectTabState,
@ -434,7 +434,7 @@ export default memo(withGlobal<OwnProps>(
const chatFullInfo = chat && selectChatFullInfo(global, chat.id); const chatFullInfo = chat && selectChatFullInfo(global, chat.id);
const { threadId, type } = selectCurrentMessageList(global) || {}; const { threadId, type } = selectCurrentMessageList(global) || {};
const { canDeleteForAll } = (deleteMessageModal && deleteMessageModal.message && threadId const { canDeleteForAll } = (deleteMessageModal && deleteMessageModal.message && threadId
&& selectAllowedMessageActions(global, deleteMessageModal.message, threadId)) || {}; && selectAllowedMessageActionsSlow(global, deleteMessageModal.message, threadId)) || {};
const adminMembersById = chatFullInfo && chatFullInfo?.adminMembersById; const adminMembersById = chatFullInfo && chatFullInfo?.adminMembersById;
const messageIdList = chat && selectCurrentMessageIds(global, chat.id, threadId!, type!); const messageIdList = chat && selectCurrentMessageIds(global, chat.id, threadId!, type!);
const isGroup = Boolean(chat) && isChatBasicGroup(chat); const isGroup = Boolean(chat) && isChatBasicGroup(chat);

View File

@ -16,7 +16,7 @@ import {
} from '../../global/helpers'; } from '../../global/helpers';
import { import {
selectActiveDownloads, selectActiveDownloads,
selectAllowedMessageActions, selectAllowedMessageActionsSlow,
selectCurrentMessageList, selectCurrentMessageList,
selectIsChatProtected, selectIsChatProtected,
selectIsMessageProtected, selectIsMessageProtected,
@ -398,7 +398,7 @@ export default memo(withGlobal<OwnProps>(
const activeDownloads = selectActiveDownloads(global); const activeDownloads = selectActiveDownloads(global);
const isChatProtected = message && selectIsChatProtected(global, message?.chatId); const isChatProtected = message && selectIsChatProtected(global, message?.chatId);
const { canDelete: canDeleteMessage } = (threadId const { canDelete: canDeleteMessage } = (threadId
&& message && selectAllowedMessageActions(global, message, threadId)) || {}; && message && selectAllowedMessageActionsSlow(global, message, threadId)) || {};
const isCurrentAvatar = avatarPhoto && (avatarPhoto.id === avatarOwner?.avatarPhotoId); const isCurrentAvatar = avatarPhoto && (avatarPhoto.id === avatarOwner?.avatarPhotoId);
const canDeleteAvatar = canUpdateMedia && Boolean(avatarPhoto); const canDeleteAvatar = canUpdateMedia && Boolean(avatarPhoto);
const canDelete = canDeleteMessage || canDeleteAvatar; const canDelete = canDeleteMessage || canDeleteAvatar;

View File

@ -31,7 +31,7 @@ import {
isUserId, isUserId,
} from '../../global/helpers'; } from '../../global/helpers';
import { import {
selectAllowedMessageActions, selectAllowedMessageActionsSlow,
selectChat, selectChat,
selectChatMessage, selectChatMessage,
selectChatMessages, selectChatMessages,
@ -633,7 +633,7 @@ export default memo(withGlobal<OwnProps>(
} = ( } = (
firstPinnedMessage firstPinnedMessage
&& pinnedMessageIds.length === 1 && pinnedMessageIds.length === 1
&& selectAllowedMessageActions(global, firstPinnedMessage, threadId) && selectAllowedMessageActionsSlow(global, firstPinnedMessage, threadId)
) || {}; ) || {};
return { return {

View File

@ -34,7 +34,7 @@ import {
} from '../../../global/helpers'; } from '../../../global/helpers';
import { import {
selectActiveDownloads, selectActiveDownloads,
selectAllowedMessageActions, selectAllowedMessageActionsSlow,
selectCanPlayAnimatedEmojis, selectCanPlayAnimatedEmojis,
selectCanScheduleUntilOnline, selectCanScheduleUntilOnline,
selectCanTranslateMessage, selectCanTranslateMessage,
@ -702,7 +702,7 @@ export default memo(withGlobal<OwnProps>(
canSaveGif, canSaveGif,
canRevote, canRevote,
canClosePoll, canClosePoll,
} = (threadId && selectAllowedMessageActions(global, message, threadId)) || {}; } = (threadId && selectAllowedMessageActionsSlow(global, message, threadId)) || {};
const userStatus = isPrivate ? selectUserStatus(global, chat.id) : undefined; const userStatus = isPrivate ? selectUserStatus(global, chat.id) : undefined;
const isOwn = isOwnMessage(message); const isOwn = isOwnMessage(message);

View File

@ -64,10 +64,9 @@ import {
import { getMessageReplyInfo, getStoryReplyInfo } from '../../../global/helpers/replies'; import { getMessageReplyInfo, getStoryReplyInfo } from '../../../global/helpers/replies';
import { import {
selectActiveDownloads, selectActiveDownloads,
selectAllowedMessageActions,
selectAnimatedEmoji, selectAnimatedEmoji,
selectCanAutoLoadMedia, selectCanAutoLoadMedia,
selectCanAutoPlayMedia, selectCanAutoPlayMedia, selectCanReplyToMessage,
selectChat, selectChat,
selectChatFullInfo, selectChatFullInfo,
selectChatMessage, selectChatMessage,
@ -1754,7 +1753,7 @@ export default memo(withGlobal<OwnProps>(
isSelected = selectIsMessageSelected(global, id); isSelected = selectIsMessageSelected(global, id);
} }
const { canReply } = (messageListType === 'thread' && selectAllowedMessageActions(global, message, threadId)) || {}; const canReply = messageListType === 'thread' && selectCanReplyToMessage(global, message, threadId);
const activeDownloads = selectActiveDownloads(global); const activeDownloads = selectActiveDownloads(global);
const downloadableMedia = getMessageDownloadableMedia(message); const downloadableMedia = getMessageDownloadableMedia(message);
const isDownloading = downloadableMedia && getIsDownloading(activeDownloads, downloadableMedia); const isDownloading = downloadableMedia && getIsDownloading(activeDownloads, downloadableMedia);

View File

@ -48,7 +48,7 @@ import {
} from '../../reducers'; } from '../../reducers';
import { updateTabState } from '../../reducers/tabs'; import { updateTabState } from '../../reducers/tabs';
import { import {
selectAllowedMessageActions, selectAllowedMessageActionsSlow,
selectChat, selectChat,
selectChatLastMessageId, selectChatLastMessageId,
selectChatMessages, selectChatMessages,
@ -127,7 +127,7 @@ addActionHandler('editLastMessage', (global, actions, payload): ActionReturnType
} }
const lastOwnEditableMessageId = findLast(viewportIds, (id) => { const lastOwnEditableMessageId = findLast(viewportIds, (id) => {
return Boolean(chatMessages[id] && selectAllowedMessageActions(global, chatMessages[id], threadId).canEdit); return Boolean(chatMessages[id] && selectAllowedMessageActionsSlow(global, chatMessages[id], threadId).canEdit);
}); });
if (!lastOwnEditableMessageId) { if (!lastOwnEditableMessageId) {
@ -655,7 +655,7 @@ addActionHandler('downloadSelectedMessages', (global, actions, payload): ActionR
const chatMessages = selectChatMessages(global, chatId); const chatMessages = selectChatMessages(global, chatId);
if (!chatMessages || !threadId) return; if (!chatMessages || !threadId) return;
const messages = messageIds.map((id) => chatMessages[id]) const messages = messageIds.map((id) => chatMessages[id])
.filter((message) => selectAllowedMessageActions(global, message, threadId).canDownload); .filter((message) => selectAllowedMessageActionsSlow(global, message, threadId).canDownload);
messages.forEach((message) => { messages.forEach((message) => {
const media = getMessageDownloadableMedia(message); const media = getMessageDownloadableMedia(message);
if (!media) return; if (!media) return;
@ -955,7 +955,7 @@ function copyTextForMessages(global: GlobalState, chatId: string, messageIds: nu
const messages = messageIds const messages = messageIds
.map((id) => chatMessages[id]) .map((id) => chatMessages[id])
.filter((message) => selectAllowedMessageActions(global, message, threadId).canCopy) .filter((message) => selectAllowedMessageActionsSlow(global, message, threadId).canCopy)
.sort((message1, message2) => message1.id - message2.id); .sort((message1, message2) => message1.id - message2.id);
const resultHtml: string[] = []; const resultHtml: string[] = [];

View File

@ -127,7 +127,7 @@ export function isChatAdmin(chat: ApiChat) {
} }
export function getHasAdminRight(chat: ApiChat, key: keyof ApiChatAdminRights) { export function getHasAdminRight(chat: ApiChat, key: keyof ApiChatAdminRights) {
return chat.adminRights ? chat.adminRights[key] : false; return chat.adminRights?.[key] || false;
} }
export function getCanManageTopic(chat: ApiChat, topic: ApiTopic) { export function getCanManageTopic(chat: ApiChat, topic: ApiTopic) {

View File

@ -11,14 +11,12 @@ import type {
import type { ThreadId } from '../../types'; import type { ThreadId } from '../../types';
import type { IAllowedAttachmentOptions } from '../helpers'; import type { IAllowedAttachmentOptions } from '../helpers';
import type { import type {
ChatTranslatedMessages, ChatTranslatedMessages, GlobalState, MessageListType, TabArgs, TabThread, Thread,
GlobalState, MessageListType, TabArgs, TabThread, Thread,
} from '../types'; } from '../types';
import { ApiMessageEntityTypes, MAIN_THREAD_ID } from '../../api/types'; import { ApiMessageEntityTypes, MAIN_THREAD_ID } from '../../api/types';
import { import {
ANONYMOUS_USER_ID, ANONYMOUS_USER_ID, GENERAL_TOPIC_ID, REPLIES_USER_ID, SERVICE_NOTIFICATIONS_USER_ID,
GENERAL_TOPIC_ID, REPLIES_USER_ID, SERVICE_NOTIFICATIONS_USER_ID,
} from '../../config'; } from '../../config';
import { getCurrentTabId } from '../../util/establishMultitabRole'; import { getCurrentTabId } from '../../util/establishMultitabRole';
import { findLast } from '../../util/iteratees'; import { findLast } from '../../util/iteratees';
@ -33,7 +31,10 @@ import {
getHasAdminRight, getHasAdminRight,
getIsSavedDialog, getIsSavedDialog,
getMessageAudio, getMessageAudio,
getMessageDocument, getMessageLink, getMessagePaidMedia, getMessagePhoto, getMessageDocument,
getMessageLink,
getMessagePaidMedia,
getMessagePhoto,
getMessageVideo, getMessageVideo,
getMessageVoice, getMessageVoice,
getMessageWebPagePhoto, getMessageWebPagePhoto,
@ -70,10 +71,7 @@ import { selectPeerStory } from './stories';
import { selectIsStickerFavorite } from './symbols'; import { selectIsStickerFavorite } from './symbols';
import { selectTabState } from './tabs'; import { selectTabState } from './tabs';
import { import {
selectBot, selectBot, selectIsCurrentUserPremium, selectUser, selectUserStatus,
selectIsCurrentUserPremium,
selectUser,
selectUserStatus,
} from './users'; } from './users';
const MESSAGE_EDIT_ALLOWED_TIME = 172800; // 48 hours const MESSAGE_EDIT_ALLOWED_TIME = 172800; // 48 hours
@ -608,7 +606,29 @@ export function selectTopicFromMessage<T extends GlobalState>(global: T, message
return chat.topics?.[threadId]; return chat.topics?.[threadId];
} }
export function selectAllowedMessageActions<T extends GlobalState>(global: T, message: ApiMessage, threadId: ThreadId) { export function selectCanReplyToMessage<T extends GlobalState>(global: T, message: ApiMessage, threadId: ThreadId) {
const chat = selectChat(global, message.chatId);
if (!chat || chat.isRestricted || chat.isForbidden) return false;
const isLocal = isMessageLocal(message);
const isServiceNotification = isServiceNotificationMessage(message);
if (isLocal || isServiceNotification) return false;
const threadInfo = selectThreadInfo(global, message.chatId, threadId);
const isMessageThread = Boolean(!threadInfo?.isCommentsInfo && threadInfo?.fromChannelId);
const chatFullInfo = selectChatFullInfo(global, chat.id);
const canPostInChat = getCanPostInChat(chat, threadId, isMessageThread, chatFullInfo);
if (!canPostInChat) return false;
const messageTopic = selectTopicFromMessage(global, message);
return !messageTopic || !messageTopic.isClosed || messageTopic.isOwner || getHasAdminRight(chat, 'manageTopics');
}
// This selector is slow and not to be used within lists (e.g. Message component)
export function selectAllowedMessageActionsSlow<T extends GlobalState>(
global: T, message: ApiMessage, threadId: ThreadId,
) {
const chat = selectChat(global, message.chatId); const chat = selectChat(global, message.chatId);
if (!chat || chat.isRestricted) { if (!chat || chat.isRestricted) {
return {}; return {};
@ -628,9 +648,7 @@ export function selectAllowedMessageActions<T extends GlobalState>(global: T, me
const isAction = isActionMessage(message); const isAction = isActionMessage(message);
const hasTtl = hasMessageTtl(message); const hasTtl = hasMessageTtl(message);
const { content } = message; const { content } = message;
const messageTopic = selectTopicFromMessage(global, message);
const isDocumentSticker = isMessageDocumentSticker(message); const isDocumentSticker = isMessageDocumentSticker(message);
const chatFullInfo = selectChatFullInfo(global, chat.id);
const isBoostMessage = message.content.action?.type === 'chatBoost'; const isBoostMessage = message.content.action?.type === 'chatBoost';
const canEditMessagesIndefinitely = isChatWithSelf const canEditMessagesIndefinitely = isChatWithSelf
@ -652,15 +670,7 @@ export function selectAllowedMessageActions<T extends GlobalState>(global: T, me
const isSavedDialog = getIsSavedDialog(chat.id, threadId, global.currentUserId); const isSavedDialog = getIsSavedDialog(chat.id, threadId, global.currentUserId);
const threadInfo = selectThreadInfo(global, message.chatId, threadId); const canReply = selectCanReplyToMessage(global, message, threadId);
const isMessageThread = Boolean(!threadInfo?.isCommentsInfo && threadInfo?.fromChannelId);
const canPostInChat = getCanPostInChat(chat, threadId, isMessageThread, chatFullInfo);
const canReply = (() => {
if (isLocal || isServiceNotification) return false;
if (!canPostInChat || chat.isForbidden) return false;
return !messageTopic || !messageTopic.isClosed || messageTopic.isOwner || getHasAdminRight(chat, 'manageTopics');
})();
const canReplyGlobally = canReply || (!isSavedDialog && !isLocal && !isServiceNotification const canReplyGlobally = canReply || (!isSavedDialog && !isLocal && !isServiceNotification
&& (isSuperGroup || isBasicGroup || isChatChannel(chat))); && (isSuperGroup || isBasicGroup || isChatChannel(chat)));
@ -793,7 +803,7 @@ export function selectCanDeleteSelectedMessages<T extends GlobalState>(
} }
const messageActions = selectedMessageIds const messageActions = selectedMessageIds
.map((id) => chatMessages[id] && selectAllowedMessageActions(global, chatMessages[id], threadId)) .map((id) => chatMessages[id] && selectAllowedMessageActionsSlow(global, chatMessages[id], threadId))
.filter(Boolean); .filter(Boolean);
return { return {
@ -814,7 +824,7 @@ export function selectCanReportSelectedMessages<T extends GlobalState>(
} }
const messageActions = selectedMessageIds const messageActions = selectedMessageIds
.map((id) => chatMessages[id] && selectAllowedMessageActions(global, chatMessages[id], threadId)) .map((id) => chatMessages[id] && selectAllowedMessageActionsSlow(global, chatMessages[id], threadId))
.filter(Boolean); .filter(Boolean);
return messageActions.every((actions) => actions.canReport); return messageActions.every((actions) => actions.canReport);
@ -832,7 +842,7 @@ export function selectCanDownloadSelectedMessages<T extends GlobalState>(
} }
const messageActions = selectedMessageIds const messageActions = selectedMessageIds
.map((id) => chatMessages[id] && selectAllowedMessageActions(global, chatMessages[id], threadId)) .map((id) => chatMessages[id] && selectAllowedMessageActionsSlow(global, chatMessages[id], threadId))
.filter(Boolean); .filter(Boolean);
return messageActions.some((actions) => actions.canDownload); return messageActions.some((actions) => actions.canDownload);