Message: Show admin and owner marks (#2156)

This commit is contained in:
Alexander Zinchuk 2022-11-27 19:16:54 +01:00
parent 365a021dda
commit 5c510a91a4
20 changed files with 139 additions and 64 deletions

View File

@ -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,

View File

@ -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,
};
}

View File

@ -385,7 +385,7 @@ async function getFullChatInfo(chatId: string): Promise<FullChatData | undefined
...(chatPhoto instanceof GramJs.Photo && { profilePhoto: buildApiPhoto(chatPhoto) }),
about,
members,
adminMembers,
adminMembersById: adminMembers ? buildCollectionByKey(adminMembers, 'userId') : undefined,
canViewMembers: true,
botCommands,
...(exportedInvite instanceof GramJs.ChatInviteExported && {
@ -463,7 +463,7 @@ async function getFullChannelInfo(
canViewParticipants && adminRights && await fetchMembers(id, accessHash, 'kicked')
) || {};
const { members: adminMembers, users: adminUsers, userStatusesById: adminStatusesById } = (
canViewParticipants && adminRights && await fetchMembers(id, accessHash, 'admin')
canViewParticipants && await fetchMembers(id, accessHash, 'admin')
) || {};
const botCommands = botInfo ? buildApiChatBotCommands(botInfo) : undefined;
@ -506,7 +506,7 @@ async function getFullChannelInfo(
isPreHistoryHidden: hiddenPrehistory,
members,
kickedMembers,
adminMembers,
adminMembersById: adminMembers ? buildCollectionByKey(adminMembers, 'userId') : undefined,
groupCallId: call ? String(call.id) : undefined,
linkedChatId: linkedChatId ? buildApiPeerId(linkedChatId, 'chat') : undefined,
botCommands,

View File

@ -86,7 +86,7 @@ export interface ApiChatFullInfo {
onlineCount?: number;
members?: ApiChatMember[];
kickedMembers?: ApiChatMember[];
adminMembers?: ApiChatMember[];
adminMembersById?: Record<string, ApiChatMember>;
canViewMembers?: boolean;
isPreHistoryHidden?: boolean;
inviteLink?: string;

View File

@ -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;

View File

@ -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<OwnProps & StateProps> = ({
animationLevel,
lastSyncTime,
serverTimeOffset,
adminMember,
}) => {
const {
loadFullUser,
@ -131,6 +135,10 @@ const PrivateChatInfo: FC<OwnProps & StateProps> = ({
);
}
const customTitle = adminMember
? adminMember.customTitle || lang(adminMember.isOwner ? 'GroupInfo.LabelOwner' : 'GroupInfo.LabelAdmin')
: undefined;
return (
<div className="ChatInfo" dir={!noRtl && lang.isRtl ? 'rtl' : undefined}>
<Avatar
@ -143,12 +151,15 @@ const PrivateChatInfo: FC<OwnProps & StateProps> = ({
animationLevel={animationLevel}
/>
<div className="info">
<FullNameTitle
peer={user}
withEmojiStatus
emojiStatusSize={emojiStatusSize}
isSavedMessages={isSavedMessages}
/>
<div className="info-name-title">
<FullNameTitle
peer={user}
withEmojiStatus
emojiStatusSize={emojiStatusSize}
isSavedMessages={isSavedMessages}
/>
{customTitle && <span className="custom-title">{customTitle}</span>}
</div>
{(status || (!isSavedMessages && !noStatusOrTyping)) && renderStatusOrTyping()}
</div>
</div>

View File

@ -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<StateProps> = ({
activeEmojiInteractions,
shouldJoinToSend,
shouldSendJoinRequest,
shouldLoadFullChat,
lastSyncTime,
}) => {
const {
@ -168,6 +170,7 @@ const MiddleColumn: FC<StateProps> = ({
sendBotCommand,
restartBot,
showNotification,
loadFullChat,
} = getActions();
const { width: windowWidth } = useWindowSize();
@ -264,6 +267,12 @@ const MiddleColumn: FC<StateProps> = ({
}
}, [chatId, isPrivate, areChatSettingsLoaded, lastSyncTime, loadChatSettings]);
useEffect(() => {
if (chatId && shouldLoadFullChat && isReady) {
loadFullChat({ chatId });
}
}, [shouldLoadFullChat, chatId, isReady, loadFullChat]);
const handleDragEnter = useCallback((e: React.DragEvent<HTMLDivElement>) => {
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));

View File

@ -280,7 +280,6 @@ const Composer: FC<OwnProps & StateProps> = ({
addRecentEmoji,
sendInlineBotResult,
loadSendAs,
loadFullChat,
resetOpenChatWithDraft,
callAttachBot,
openLimitReachedModal,
@ -334,12 +333,6 @@ const Composer: FC<OwnProps & StateProps> = ({
}
}, [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

View File

@ -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<OwnProps & StateProps> = ({
isChatWithSelf,
isRepliesChat,
isChannel,
isGroup,
canReply,
lastSyncTime,
serverTimeOffset,
@ -301,6 +307,7 @@ const Message: FC<OwnProps & StateProps> = ({
hasUnreadReaction,
memoFirstUnreadIdRef,
animationLevel,
senderAdminMember,
}) => {
const {
toggleMessageSelection,
@ -615,7 +622,9 @@ const Message: FC<OwnProps & StateProps> = ({
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<OwnProps & StateProps> = ({
)}
{forwardInfo?.isLinkedChannelPost ? (
<span className="admin-title" dir="auto">{lang('DiscussChannel')}</span>
) : message.adminTitle && !isChannel ? (
<span className="admin-title" dir="auto">{message.adminTitle}</span>
) : message.forwardInfo?.postAuthorTitle && isGroup && asForwarded ? (
<span className="admin-title" dir="auto">{message.forwardInfo?.postAuthorTitle}</span>
) : message.postAuthorTitle && isGroup && !asForwarded ? (
<span className="admin-title" dir="auto">{message.postAuthorTitle}</span>
) : senderAdminMember && !asForwarded ? (
<span className="admin-title" dir="auto">
{senderAdminMember.customTitle || lang(
senderAdminMember.isOwner ? 'GroupInfo.LabelOwner' : 'GroupInfo.LabelAdmin',
)}
</span>
) : undefined}
</div>
);
}
const forwardAuthor = isGroup && asForwarded ? message.postAuthorTitle : undefined;
return (
<div
ref={ref}
@ -1040,7 +1059,10 @@ const Message: FC<OwnProps & StateProps> = ({
dir="auto"
>
{asForwarded && !isInDocumentGroupNotFirst && (
<div className="message-title">{lang('ForwardedMessage')}</div>
<div className="message-title">
{lang('ForwardedMessage')}
{forwardAuthor && <span className="admin-title" dir="auto">{forwardAuthor}</span>}
</div>
)}
{renderContent()}
{!isInDocumentGroupNotLast && metaPosition === 'standalone' && renderReactionsAndMeta()}
@ -1124,13 +1146,18 @@ export default memo(withGlobal<OwnProps>(
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<OwnProps>(
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<OwnProps>(
isChatWithSelf,
isRepliesChat,
isChannel,
isGroup,
canReply,
lastSyncTime,
serverTimeOffset,
@ -1239,6 +1265,7 @@ export default memo(withGlobal<OwnProps>(
transcribedText: transcriptionId !== undefined ? global.transcriptions[transcriptionId]?.text : undefined,
isPremium: selectIsCurrentUserPremium(global),
animationLevel: global.settings.byKey.animationLevel,
senderAdminMember,
};
},
)(Message));

View File

@ -85,6 +85,7 @@ type StateProps = {
canAddMembers?: boolean;
canDeleteMembers?: boolean;
members?: ApiChatMember[];
adminMembersById?: Record<string, ApiChatMember>;
commonChatIds?: string[];
chatsById: Record<string, ApiChat>;
usersById: Record<string, ApiUser>;
@ -126,6 +127,7 @@ const Profile: FC<OwnProps & StateProps> = ({
canDeleteMembers,
commonChatIds,
members,
adminMembersById,
usersById,
userStatusesById,
chatsById,
@ -416,7 +418,7 @@ const Profile: FC<OwnProps & StateProps> = ({
onClick={() => handleMemberClick(id)}
contextActions={getMemberContextAction(id)}
>
<PrivateChatInfo userId={id} forceShowSelf />
<PrivateChatInfo userId={id} adminMember={adminMembersById?.[id]} forceShowSelf />
</ListItem>
))
) : resultType === 'commonChats' ? (
@ -524,6 +526,7 @@ export default memo(withGlobal<OwnProps>(
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<OwnProps>(
userStatusesById,
chatsById,
isChatProtected: chat?.isProtected,
...(hasMembersTab && members && { members }),
...(hasMembersTab && members && { members, adminMembersById }),
...(hasCommonChatsTab && user && { commonChatIds: user.commonChats?.ids }),
};
},

View File

@ -108,7 +108,7 @@ const ManageChannel: FC<OwnProps & StateProps> = ({
}
}, [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(() => {

View File

@ -49,11 +49,11 @@ const ManageChatAdministrators: FC<OwnProps & StateProps> = ({
}, [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) {

View File

@ -236,7 +236,9 @@ const ManageGroup: FC<OwnProps & StateProps> = ({
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) {

View File

@ -70,7 +70,7 @@ const ManageGroupAdminRights: FC<OwnProps & StateProps> = ({
});
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<OwnProps & StateProps> = ({
}
return selectedAdminMember;
}, [chat.fullInfo?.adminMembers, defaultRights, isNewAdmin, lang, selectedUserId]);
}, [chat.fullInfo?.adminMembersById, defaultRights, isNewAdmin, lang, selectedUserId]);
useEffect(() => {
if (chat?.fullInfo && selectedUserId && !selectedChatMember) {

View File

@ -37,7 +37,7 @@ type OwnProps = {
type StateProps = {
userStatusesById: Record<string, ApiUserStatus>;
members?: ApiChatMember[];
adminMembers?: ApiChatMember[];
adminMembersById?: Record<string, ApiChatMember>;
isChannel?: boolean;
localContactIds?: string[];
searchQuery?: string;
@ -52,7 +52,7 @@ type StateProps = {
const ManageGroupMembers: FC<OwnProps & StateProps> = ({
noAdmins,
members,
adminMembers,
adminMembersById,
userStatusesById,
isChannel,
isActive,
@ -78,8 +78,8 @@ const ManageGroupMembers: FC<OwnProps & StateProps> = ({
const [deletingUserId, setDeletingUserId] = useState<string | undefined>();
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<OwnProps>(
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<OwnProps>(
return {
members,
adminMembers,
adminMembersById,
userStatusesById,
isChannel,
localContactIds,

View File

@ -30,11 +30,11 @@ const ManageGroupRecentActions: FC<OwnProps & StateProps> = ({ 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) {

View File

@ -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;

View File

@ -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<string, ApiChatMember> | 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 }),
},
}));
});

View File

@ -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'),
},
});
}

View File

@ -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'),
},
});
}