diff --git a/src/api/gramjs/apiBuilders/chats.ts b/src/api/gramjs/apiBuilders/chats.ts index 428d72270..fc4189f00 100644 --- a/src/api/gramjs/apiBuilders/chats.ts +++ b/src/api/gramjs/apiBuilders/chats.ts @@ -274,10 +274,14 @@ export function buildChatMember( return { userId, - inviterId: 'inviterId' in member ? buildApiPeerId(member.inviterId as BigInt.BigInteger, 'user') : undefined, + inviterId: 'inviterId' in member && member.inviterId + ? buildApiPeerId(member.inviterId as BigInt.BigInteger, 'user') + : undefined, joinedDate: 'date' in member ? member.date : undefined, - kickedByUserId: 'kickedBy' in member ? buildApiPeerId(member.kickedBy, 'user') : undefined, - promotedByUserId: 'promotedBy' in member ? buildApiPeerId(member.promotedBy, 'user') : undefined, + kickedByUserId: 'kickedBy' in member && member.kickedBy ? buildApiPeerId(member.kickedBy, 'user') : undefined, + promotedByUserId: 'promotedBy' in member && member.promotedBy + ? buildApiPeerId(member.promotedBy, 'user') + : undefined, bannedRights: 'bannedRights' in member ? omitVirtualClassFields(member.bannedRights) : undefined, adminRights: 'adminRights' in member ? omitVirtualClassFields(member.adminRights) : undefined, customTitle: 'rank' in member ? member.rank : undefined, diff --git a/src/api/gramjs/apiBuilders/messages.ts b/src/api/gramjs/apiBuilders/messages.ts index 93e1a428f..2167e05e9 100644 --- a/src/api/gramjs/apiBuilders/messages.ts +++ b/src/api/gramjs/apiBuilders/messages.ts @@ -210,7 +210,7 @@ export function buildApiMessageWithChatId(chatId: string, mtpMessage: UniversalM ...(shouldHideKeyboardButtons && { shouldHideKeyboardButtons }), ...(mtpMessage.viaBotId && { viaBotId: buildApiPeerId(mtpMessage.viaBotId, 'user') }), ...(replies?.comments && { threadInfo: buildThreadInfo(replies, mtpMessage.id, chatId) }), - ...(postAuthor && { adminTitle: postAuthor }), + ...(postAuthor && { postAuthorTitle: postAuthor }), isProtected, isForwardingAllowed, }; @@ -399,7 +399,7 @@ function buildApiMessageForwardInfo(fwdFrom: GramJs.MessageFwdHeader, isChatWith fromMessageId: fwdFrom.savedFromMsgId || fwdFrom.channelPost, senderUserId: fromId, hiddenUserName: fwdFrom.fromName, - adminTitle: fwdFrom.postAuthor, + postAuthorTitle: fwdFrom.postAuthor, }; } diff --git a/src/api/gramjs/methods/chats.ts b/src/api/gramjs/methods/chats.ts index 6507aa75d..719d53a9b 100644 --- a/src/api/gramjs/methods/chats.ts +++ b/src/api/gramjs/methods/chats.ts @@ -385,7 +385,7 @@ async function getFullChatInfo(chatId: string): Promise; canViewMembers?: boolean; isPreHistoryHidden?: boolean; inviteLink?: string; diff --git a/src/api/types/messages.ts b/src/api/types/messages.ts index a02104793..6f72da25e 100644 --- a/src/api/types/messages.ts +++ b/src/api/types/messages.ts @@ -293,7 +293,7 @@ export interface ApiMessageForwardInfo { senderUserId?: string; fromMessageId?: number; hiddenUserName?: string; - adminTitle?: string; + postAuthorTitle?: string; } export type ApiMessageEntityDefault = { @@ -408,7 +408,7 @@ export interface ApiMessage { isKeyboardSingleUse?: boolean; viaBotId?: string; threadInfo?: ApiThreadInfo; - adminTitle?: string; + postAuthorTitle?: string; isScheduled?: boolean; shouldHideKeyboardButtons?: boolean; isFromScheduled?: boolean; diff --git a/src/components/common/PrivateChatInfo.tsx b/src/components/common/PrivateChatInfo.tsx index 9bf477267..43f518c56 100644 --- a/src/components/common/PrivateChatInfo.tsx +++ b/src/components/common/PrivateChatInfo.tsx @@ -2,7 +2,9 @@ import React, { useEffect, useCallback, memo } from '../../lib/teact/teact'; import { getActions, withGlobal } from '../../global'; import type { FC } from '../../lib/teact/teact'; -import type { ApiUser, ApiTypingStatus, ApiUserStatus } from '../../api/types'; +import type { + ApiUser, ApiTypingStatus, ApiUserStatus, ApiChatMember, +} from '../../api/types'; import type { GlobalState } from '../../global/types'; import type { AnimationLevel } from '../../types'; import { MediaViewerOrigin } from '../../types'; @@ -34,6 +36,7 @@ type OwnProps = { emojiStatusSize?: number; noStatusOrTyping?: boolean; noRtl?: boolean; + adminMember?: ApiChatMember; }; type StateProps = @@ -67,6 +70,7 @@ const PrivateChatInfo: FC = ({ animationLevel, lastSyncTime, serverTimeOffset, + adminMember, }) => { const { loadFullUser, @@ -131,6 +135,10 @@ const PrivateChatInfo: FC = ({ ); } + const customTitle = adminMember + ? adminMember.customTitle || lang(adminMember.isOwner ? 'GroupInfo.LabelOwner' : 'GroupInfo.LabelAdmin') + : undefined; + return (
= ({ animationLevel={animationLevel} />
- +
+ + {customTitle && {customTitle}} +
{(status || (!isSavedMessages && !noStatusOrTyping)) && renderStatusOrTyping()}
diff --git a/src/components/middle/MiddleColumn.tsx b/src/components/middle/MiddleColumn.tsx index 9a432200b..6f045f7af 100644 --- a/src/components/middle/MiddleColumn.tsx +++ b/src/components/middle/MiddleColumn.tsx @@ -45,7 +45,7 @@ import { selectTheme, } from '../../global/selectors'; import { - getCanPostInChat, getMessageSendingRestrictionReason, isChatChannel, isChatSuperGroup, isUserId, + getCanPostInChat, getMessageSendingRestrictionReason, isChatChannel, isChatGroup, isChatSuperGroup, isUserId, } from '../../global/helpers'; import captureEscKeyListener from '../../util/captureEscKeyListener'; import buildClassName from '../../util/buildClassName'; @@ -108,6 +108,7 @@ type StateProps = { canSubscribe?: boolean; canStartBot?: boolean; canRestartBot?: boolean; + shouldLoadFullChat?: boolean; activeEmojiInteractions?: ActiveEmojiInteraction[]; shouldJoinToSend?: boolean; shouldSendJoinRequest?: boolean; @@ -154,6 +155,7 @@ const MiddleColumn: FC = ({ activeEmojiInteractions, shouldJoinToSend, shouldSendJoinRequest, + shouldLoadFullChat, lastSyncTime, }) => { const { @@ -168,6 +170,7 @@ const MiddleColumn: FC = ({ sendBotCommand, restartBot, showNotification, + loadFullChat, } = getActions(); const { width: windowWidth } = useWindowSize(); @@ -264,6 +267,12 @@ const MiddleColumn: FC = ({ } }, [chatId, isPrivate, areChatSettingsLoaded, lastSyncTime, loadChatSettings]); + useEffect(() => { + if (chatId && shouldLoadFullChat && isReady) { + loadFullChat({ chatId }); + } + }, [shouldLoadFullChat, chatId, isReady, loadFullChat]); + const handleDragEnter = useCallback((e: React.DragEvent) => { if (IS_TOUCH_ENV) { return; @@ -616,6 +625,7 @@ export default memo(withGlobal( const shouldSendJoinRequest = Boolean(chat?.isNotJoined && chat.isJoinRequest); const canRestartBot = Boolean(bot && selectIsUserBlocked(global, bot.id)); const canStartBot = !canRestartBot && isBotNotStarted; + const shouldLoadFullChat = Boolean(chat && isChatGroup(chat) && !chat.fullInfo && lastSyncTime); return { ...state, @@ -645,6 +655,7 @@ export default memo(withGlobal( canRestartBot, shouldJoinToSend, shouldSendJoinRequest, + shouldLoadFullChat, }; }, )(MiddleColumn)); diff --git a/src/components/middle/composer/Composer.tsx b/src/components/middle/composer/Composer.tsx index f2cff7341..1515c5cb7 100644 --- a/src/components/middle/composer/Composer.tsx +++ b/src/components/middle/composer/Composer.tsx @@ -280,7 +280,6 @@ const Composer: FC = ({ addRecentEmoji, sendInlineBotResult, loadSendAs, - loadFullChat, resetOpenChatWithDraft, callAttachBot, openLimitReachedModal, @@ -334,12 +333,6 @@ const Composer: FC = ({ } }, [chat, chatId, isReady, lastSyncTime, loadSendAs, sendAsPeerIds]); - useEffect(() => { - if (chatId && chat && lastSyncTime && !chat.fullInfo && isReady && isChatSuperGroup(chat)) { - loadFullChat({ chatId }); - } - }, [chat, chatId, isReady, lastSyncTime, loadFullChat]); - const shouldAnimateSendAsButtonRef = useRef(false); useOnChange(([prevChatId, prevSendAsPeerIds]) => { // We only animate send-as button if `sendAsPeerIds` was missing when opening the chat diff --git a/src/components/middle/message/Message.tsx b/src/components/middle/message/Message.tsx index f9921e950..409c55581 100644 --- a/src/components/middle/message/Message.tsx +++ b/src/components/middle/message/Message.tsx @@ -17,6 +17,7 @@ import type { ApiChat, ApiThreadInfo, ApiAvailableReaction, + ApiChatMember, } from '../../../api/types'; import type { AnimationLevel, FocusDirection, IAlbum, ISettings, @@ -74,7 +75,9 @@ import { areReactionsEmpty, getMessageHtmlId, isGeoLiveExpired, - getMessageSingleCustomEmoji, hasMessageText, + getMessageSingleCustomEmoji, + hasMessageText, + isChatGroup, } from '../../../global/helpers'; import buildClassName from '../../../util/buildClassName'; import useEnsureMessage from '../../../hooks/useEnsureMessage'; @@ -183,6 +186,7 @@ type StateProps = { isChatWithSelf?: boolean; isRepliesChat?: boolean; isChannel?: boolean; + isGroup?: boolean; canReply?: boolean; lastSyncTime?: number; serverTimeOffset: number; @@ -211,6 +215,7 @@ type StateProps = { isTranscriptionError?: boolean; isPremium: boolean; animationLevel: AnimationLevel; + senderAdminMember?: ApiChatMember; }; type MetaPosition = @@ -275,6 +280,7 @@ const Message: FC = ({ isChatWithSelf, isRepliesChat, isChannel, + isGroup, canReply, lastSyncTime, serverTimeOffset, @@ -301,6 +307,7 @@ const Message: FC = ({ hasUnreadReaction, memoFirstUnreadIdRef, animationLevel, + senderAdminMember, }) => { const { toggleMessageSelection, @@ -615,7 +622,9 @@ const Message: FC = ({ style = `width: ${calculatedWidth + extraPadding}px`; } - const signature = (isChannel && message.adminTitle) || (!asForwarded && forwardInfo?.adminTitle) || undefined; + const signature = (isChannel && message.postAuthorTitle) + || (!asForwarded && forwardInfo?.postAuthorTitle) + || undefined; const metaSafeAuthorWidth = useMemo(() => { return signature ? calculateAuthorWidth(signature) : undefined; }, [signature]); @@ -984,13 +993,23 @@ const Message: FC = ({ )} {forwardInfo?.isLinkedChannelPost ? ( {lang('DiscussChannel')} - ) : message.adminTitle && !isChannel ? ( - {message.adminTitle} + ) : message.forwardInfo?.postAuthorTitle && isGroup && asForwarded ? ( + {message.forwardInfo?.postAuthorTitle} + ) : message.postAuthorTitle && isGroup && !asForwarded ? ( + {message.postAuthorTitle} + ) : senderAdminMember && !asForwarded ? ( + + {senderAdminMember.customTitle || lang( + senderAdminMember.isOwner ? 'GroupInfo.LabelOwner' : 'GroupInfo.LabelAdmin', + )} + ) : undefined} ); } + const forwardAuthor = isGroup && asForwarded ? message.postAuthorTitle : undefined; + return (
= ({ dir="auto" > {asForwarded && !isInDocumentGroupNotFirst && ( -
{lang('ForwardedMessage')}
+
+ {lang('ForwardedMessage')} + {forwardAuthor && {forwardAuthor}} +
)} {renderContent()} {!isInDocumentGroupNotLast && metaPosition === 'standalone' && renderReactionsAndMeta()} @@ -1124,13 +1146,18 @@ export default memo(withGlobal( const isChatWithSelf = selectIsChatWithSelf(global, chatId); const isRepliesChat = isChatWithRepliesBot(chatId); const isChannel = chat && isChatChannel(chat); + const isGroup = chat && isChatGroup(chat); const chatUsername = chat?.username; + const isForwarding = forwardMessages.messageIds && forwardMessages.messageIds.includes(id); const forceSenderName = !isChatWithSelf && isAnonymousOwnMessage(message); const canShowSender = withSenderName || withAvatar || forceSenderName; const sender = selectSender(global, message); const originSender = selectForwardedSender(global, message); const botSender = viaBotId ? selectUser(global, viaBotId) : undefined; + const senderAdminMember = sender?.id && isGroup + ? chat.fullInfo?.adminMembersById?.[sender?.id] + : undefined; const threadTopMessageId = threadId ? selectThreadTopMessageId(global, chatId, threadId) : undefined; const isThreadTop = message.id === threadTopMessageId; @@ -1152,8 +1179,6 @@ export default memo(withGlobal( direction: focusDirection, noHighlight: noFocusHighlight, isResizingContainer, } = (isFocused && focusedMessage) || {}; - const isForwarding = forwardMessages.messageIds && forwardMessages.messageIds.includes(id); - const { query: highlight } = selectCurrentTextSearch(global) || {}; const singleEmoji = getMessageSingleRegularEmoji(message); @@ -1206,6 +1231,7 @@ export default memo(withGlobal( isChatWithSelf, isRepliesChat, isChannel, + isGroup, canReply, lastSyncTime, serverTimeOffset, @@ -1239,6 +1265,7 @@ export default memo(withGlobal( transcribedText: transcriptionId !== undefined ? global.transcriptions[transcriptionId]?.text : undefined, isPremium: selectIsCurrentUserPremium(global), animationLevel: global.settings.byKey.animationLevel, + senderAdminMember, }; }, )(Message)); diff --git a/src/components/right/Profile.tsx b/src/components/right/Profile.tsx index 42bf538e1..0c40fcc86 100644 --- a/src/components/right/Profile.tsx +++ b/src/components/right/Profile.tsx @@ -85,6 +85,7 @@ type StateProps = { canAddMembers?: boolean; canDeleteMembers?: boolean; members?: ApiChatMember[]; + adminMembersById?: Record; commonChatIds?: string[]; chatsById: Record; usersById: Record; @@ -126,6 +127,7 @@ const Profile: FC = ({ canDeleteMembers, commonChatIds, members, + adminMembersById, usersById, userStatusesById, chatsById, @@ -416,7 +418,7 @@ const Profile: FC = ({ onClick={() => handleMemberClick(id)} contextActions={getMemberContextAction(id)} > - + )) ) : resultType === 'commonChats' ? ( @@ -524,6 +526,7 @@ export default memo(withGlobal( const isChannel = chat && isChatChannel(chat); const hasMembersTab = isGroup || (isChannel && isChatAdmin(chat!)); const members = chat?.fullInfo?.members; + const adminMembersById = chat?.fullInfo?.adminMembersById; const areMembersHidden = hasMembersTab && chat && (chat.isForbidden || (chat.fullInfo && !chat.fullInfo.canViewMembers)); const canAddMembers = hasMembersTab && chat @@ -562,7 +565,7 @@ export default memo(withGlobal( userStatusesById, chatsById, isChatProtected: chat?.isProtected, - ...(hasMembersTab && members && { members }), + ...(hasMembersTab && members && { members, adminMembersById }), ...(hasCommonChatsTab && user && { commonChatIds: user.commonChats?.ids }), }; }, diff --git a/src/components/right/management/ManageChannel.tsx b/src/components/right/management/ManageChannel.tsx index 4d5abb7cf..d721c099a 100644 --- a/src/components/right/management/ManageChannel.tsx +++ b/src/components/right/management/ManageChannel.tsx @@ -108,7 +108,7 @@ const ManageChannel: FC = ({ } }, [progress]); - const adminsCount = (chat?.fullInfo?.adminMembers?.length) || 0; + const adminsCount = Object.keys(chat.fullInfo?.adminMembersById || {}).length; const removedUsersCount = (chat?.fullInfo?.kickedMembers?.length) || 0; const handleClickEditType = useCallback(() => { diff --git a/src/components/right/management/ManageChatAdministrators.tsx b/src/components/right/management/ManageChatAdministrators.tsx index 4331aae92..aad931005 100644 --- a/src/components/right/management/ManageChatAdministrators.tsx +++ b/src/components/right/management/ManageChatAdministrators.tsx @@ -49,11 +49,11 @@ const ManageChatAdministrators: FC = ({ }, [onScreenSelect]); const adminMembers = useMemo(() => { - if (!chat.fullInfo || !chat.fullInfo.adminMembers) { + if (!chat.fullInfo?.adminMembersById) { return []; } - return chat.fullInfo.adminMembers.sort((a, b) => { + return Object.values(chat.fullInfo.adminMembersById).sort((a, b) => { if (a.isOwner) { return -1; } else if (b.isOwner) { diff --git a/src/components/right/management/ManageGroup.tsx b/src/components/right/management/ManageGroup.tsx index 5a9eaeb1b..3715df660 100644 --- a/src/components/right/management/ManageGroup.tsx +++ b/src/components/right/management/ManageGroup.tsx @@ -236,7 +236,9 @@ const ManageGroup: FC = ({ return totalCount; }, [chat]); - const adminsCount = (chat.fullInfo?.adminMembers?.length) || 0; + const adminsCount = useMemo(() => { + return Object.keys(chat.fullInfo?.adminMembersById || {}).length; + }, [chat.fullInfo?.adminMembersById]); const handleDeleteGroup = useCallback(() => { if (isBasicGroup) { diff --git a/src/components/right/management/ManageGroupAdminRights.tsx b/src/components/right/management/ManageGroupAdminRights.tsx index 1400f10b9..fe33ab6d5 100644 --- a/src/components/right/management/ManageGroupAdminRights.tsx +++ b/src/components/right/management/ManageGroupAdminRights.tsx @@ -70,7 +70,7 @@ const ManageGroupAdminRights: FC = ({ }); const selectedChatMember = useMemo(() => { - const selectedAdminMember = chat.fullInfo?.adminMembers?.find(({ userId }) => userId === selectedUserId); + const selectedAdminMember = selectedUserId ? chat.fullInfo?.adminMembersById?.[selectedUserId] : undefined; // If `selectedAdminMember` variable is filled with a value, then we have already saved the administrator, // so now we need to return to the list of administrators @@ -91,7 +91,7 @@ const ManageGroupAdminRights: FC = ({ } return selectedAdminMember; - }, [chat.fullInfo?.adminMembers, defaultRights, isNewAdmin, lang, selectedUserId]); + }, [chat.fullInfo?.adminMembersById, defaultRights, isNewAdmin, lang, selectedUserId]); useEffect(() => { if (chat?.fullInfo && selectedUserId && !selectedChatMember) { diff --git a/src/components/right/management/ManageGroupMembers.tsx b/src/components/right/management/ManageGroupMembers.tsx index 0105ba41a..fa03c92f4 100644 --- a/src/components/right/management/ManageGroupMembers.tsx +++ b/src/components/right/management/ManageGroupMembers.tsx @@ -37,7 +37,7 @@ type OwnProps = { type StateProps = { userStatusesById: Record; members?: ApiChatMember[]; - adminMembers?: ApiChatMember[]; + adminMembersById?: Record; isChannel?: boolean; localContactIds?: string[]; searchQuery?: string; @@ -52,7 +52,7 @@ type StateProps = { const ManageGroupMembers: FC = ({ noAdmins, members, - adminMembers, + adminMembersById, userStatusesById, isChannel, isActive, @@ -78,8 +78,8 @@ const ManageGroupMembers: FC = ({ const [deletingUserId, setDeletingUserId] = useState(); const adminIds = useMemo(() => { - return noAdmins ? adminMembers?.map(({ userId }) => userId) || [] : []; - }, [adminMembers, noAdmins]); + return noAdmins && adminMembersById ? Object.keys(adminMembersById) : []; + }, [adminMembersById, noAdmins]); const memberIds = useMemo(() => { // No need for expensive global updates on users, so we avoid them @@ -233,7 +233,7 @@ export default memo(withGlobal( const chat = selectChat(global, chatId); const { statusesById: userStatusesById } = global.users; const members = chat?.fullInfo?.members; - const adminMembers = chat?.fullInfo?.adminMembers; + const adminMembersById = chat?.fullInfo?.adminMembersById; const isChannel = chat && isChatChannel(chat); const { userIds: localContactIds } = global.contactList || {}; @@ -248,7 +248,7 @@ export default memo(withGlobal( return { members, - adminMembers, + adminMembersById, userStatusesById, isChannel, localContactIds, diff --git a/src/components/right/management/ManageGroupRecentActions.tsx b/src/components/right/management/ManageGroupRecentActions.tsx index 2b88de7c8..adea6f838 100644 --- a/src/components/right/management/ManageGroupRecentActions.tsx +++ b/src/components/right/management/ManageGroupRecentActions.tsx @@ -30,11 +30,11 @@ const ManageGroupRecentActions: FC = ({ chat, onClose, is }); const adminMembers = useMemo(() => { - if (!chat || !chat.fullInfo || !chat.fullInfo.adminMembers) { + if (!chat?.fullInfo?.adminMembersById) { return []; } - return chat.fullInfo.adminMembers.sort((a, b) => { + return Object.values(chat.fullInfo.adminMembersById).sort((a, b) => { if (a.isOwner) { return -1; } else if (b.isOwner) { diff --git a/src/components/ui/ListItem.scss b/src/components/ui/ListItem.scss index a6c598b9c..07bc081b1 100644 --- a/src/components/ui/ListItem.scss +++ b/src/components/ui/ListItem.scss @@ -165,6 +165,11 @@ overflow: hidden; } + .info-name-title { + display: flex; + align-items: center; + } + .info-row, .title, .subtitle { @@ -211,6 +216,17 @@ flex-grow: 1; overflow: hidden; + .custom-title { + padding-inline-start: 1rem; + font-size: 0.875rem; + color: var(--color-text-secondary); + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + margin-inline-start: auto; + flex-shrink: 0; + } + .status, .typing-status { font-size: 0.875rem; diff --git a/src/global/actions/api/chats.ts b/src/global/actions/api/chats.ts index 5143cc832..38bd07ef5 100644 --- a/src/global/actions/api/chats.ts +++ b/src/global/actions/api/chats.ts @@ -3,7 +3,7 @@ import { } from '../../index'; import type { - ApiChat, ApiUser, ApiChatFolder, ApiError, + ApiChat, ApiUser, ApiChatFolder, ApiError, ApiChatMember, } from '../../../api/types'; import { MAIN_THREAD_ID } from '../../../api/types'; import { NewChatMembersProgress, ChatCreationProgress, ManagementProgress } from '../../../types'; @@ -867,24 +867,31 @@ addActionHandler('updateChatAdmin', async (global, actions, payload) => { return; } - const { adminMembers } = chatAfterUpdate.fullInfo; + const { adminMembersById } = chatAfterUpdate.fullInfo; const isDismissed = !Object.keys(adminRights).length; + let newAdminMembersById: Record | undefined; + if (adminMembersById) { + if (isDismissed) { + const { [userId]: remove, ...rest } = adminMembersById; + newAdminMembersById = rest; + } else { + newAdminMembersById = { + ...adminMembersById, + [userId]: { + ...adminMembersById[userId], + adminRights, + customTitle, + }, + }; + } + } global = getGlobal(); setGlobal(updateChat(global, chatId, { fullInfo: { ...chatAfterUpdate.fullInfo, - ...(adminMembers && isDismissed && { - adminMembers: adminMembers.filter((m) => m.userId !== userId), - }), - ...(adminMembers && !isDismissed && { - adminMembers: adminMembers.map((m) => ( - m.userId === userId - ? { ...m, adminRights, customTitle } - : m - )), - }), + ...(newAdminMembersById && { adminMembersById: newAdminMembersById }), }, })); }); diff --git a/src/global/actions/apiUpdaters/chats.ts b/src/global/actions/apiUpdaters/chats.ts index ddfcbeb02..74a2584e9 100644 --- a/src/global/actions/apiUpdaters/chats.ts +++ b/src/global/actions/apiUpdaters/chats.ts @@ -3,7 +3,7 @@ import { addActionHandler, getGlobal, setGlobal } from '../../index'; import { MAIN_THREAD_ID } from '../../../api/types'; import { ARCHIVED_FOLDER_ID, MAX_ACTIVE_PINNED_CHATS } from '../../../config'; -import { pick } from '../../../util/iteratees'; +import { buildCollectionByKey, pick } from '../../../util/iteratees'; import { closeMessageNotifications, notifyAboutMessage } from '../../../util/notifications'; import { updateChat, @@ -326,7 +326,7 @@ addActionHandler('apiUpdate', (global, actions, update) => { fullInfo: { ...targetChat.fullInfo, members, - adminMembers, + adminMembersById: buildCollectionByKey(adminMembers, 'userId'), }, }); } diff --git a/src/global/reducers/chats.ts b/src/global/reducers/chats.ts index 1f5daaecb..063a364fc 100644 --- a/src/global/reducers/chats.ts +++ b/src/global/reducers/chats.ts @@ -2,7 +2,7 @@ import type { GlobalState } from '../types'; import type { ApiChat, ApiChatMember, ApiPhoto } from '../../api/types'; import { ARCHIVED_FOLDER_ID } from '../../config'; -import { areSortedArraysEqual, omit } from '../../util/iteratees'; +import { areSortedArraysEqual, buildCollectionByKey, omit } from '../../util/iteratees'; import { selectChatListType } from '../selectors'; export function replaceChatListIds( @@ -242,6 +242,7 @@ export function addChatMembers(global: GlobalState, chat: ApiChat, membersToAdd: fullInfo: { ...chat.fullInfo, members: updatedMembers, + adminMembersById: buildCollectionByKey(updatedMembers, 'userId'), }, }); }