diff --git a/package.json b/package.json index 3ce3bd130..cfab74133 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "deploy:production": "npm run build:production && git add -A && git commit -a -m '[Build]' --no-verify && git push", "inc_version": "echo $((`cat .patch-version` + 1)) > .patch-version && echo \"$(node -p -e \"require('./package.json').version.match(/^\\d+\\.\\d+/)[0]\").$(cat .patch-version)\"", "perf:serve": "cross-env APP_ENV=perf parcel src/index-perf.html", - "lint": "eslint . --ext .ts,.tsx --ignore-pattern src/lib/gramjs", + "lint": "tsc && eslint . --ext .ts,.tsx --ignore-pattern src/lib/gramjs", "lint:fix": "npm run lint -- --fix", "gramjs:tl": "node ./src/lib/gramjs/tl/generateModules.js", "gramjs:lint:fix": "eslint ./src/lib/gramjs --ignore-path=src/lib/gramjs/.eslintignore --fix", diff --git a/src/api/gramjs/apiBuilders/chats.ts b/src/api/gramjs/apiBuilders/chats.ts index 35f802cb1..cba2bbe0e 100644 --- a/src/api/gramjs/apiBuilders/chats.ts +++ b/src/api/gramjs/apiBuilders/chats.ts @@ -1,3 +1,4 @@ +import BigInt from 'big-integer'; import { Api as GramJs } from '../../../lib/gramjs'; import { ApiChat, @@ -10,7 +11,7 @@ import { } from '../../types'; import { pick, pickTruthy } from '../../../util/iteratees'; import { - isInputPeerChannel, isInputPeerChat, isInputPeerUser, isPeerChat, isPeerUser, + buildApiPeerId, getApiChatIdFromMtpPeer, isPeerChat, isPeerUser, } from './peers'; import { omitVirtualClassFields } from './helpers'; import { getServerTime } from '../../../util/serverTime'; @@ -93,11 +94,13 @@ function buildApiChatPermissions(peerEntity: GramJs.TypeUser | GramJs.TypeChat): } return { - adminRights: omitVirtualClassFields(peerEntity.adminRights), - currentUserBannedRights: peerEntity instanceof GramJs.Channel + adminRights: peerEntity.adminRights ? omitVirtualClassFields(peerEntity.adminRights) : undefined, + currentUserBannedRights: peerEntity instanceof GramJs.Channel && peerEntity.bannedRights ? omitVirtualClassFields(peerEntity.bannedRights) : undefined, - defaultBannedRights: omitVirtualClassFields(peerEntity.defaultBannedRights), + defaultBannedRights: peerEntity.defaultBannedRights + ? omitVirtualClassFields(peerEntity.defaultBannedRights) + : undefined, }; } @@ -146,7 +149,7 @@ function buildApiChatRestrictions(peerEntity: GramJs.TypeUser | GramJs.TypeChat) function buildApiChatMigrationInfo(peerEntity: GramJs.TypeChat): { migratedTo?: { - chatId: number; + chatId: string; accessHash?: string; }; } { @@ -159,7 +162,7 @@ function buildApiChatMigrationInfo(peerEntity: GramJs.TypeChat): { migratedTo: { chatId: getApiChatIdFromMtpPeer(peerEntity.migratedTo), ...(peerEntity.migratedTo instanceof GramJs.InputChannel && { - accessHash: peerEntity.migratedTo.accessHash.toString(), + accessHash: String(peerEntity.migratedTo.accessHash), }), }, }; @@ -200,34 +203,13 @@ export function buildApiChatFromPreview( } return { - id: preview instanceof GramJs.User ? preview.id : -preview.id, + id: buildApiPeerId(preview.id, preview instanceof GramJs.User ? 'user' : 'chat'), type: getApiChatTypeFromPeerEntity(preview), title: preview instanceof GramJs.User ? getUserName(preview) : preview.title, ...buildApiChatFieldsFromPeerEntity(preview, isSupport), }; } -export function getApiChatIdFromMtpPeer(peer: GramJs.TypePeer): number { - if (isPeerUser(peer)) { - return peer.userId; - } else if (isPeerChat(peer)) { - return -peer.chatId; - } else { - return -peer.channelId; - } -} - -export function getApiChatIdFromInputMtpPeer(peer: GramJs.TypeInputPeer): number | undefined { - if (isInputPeerUser(peer)) { - return peer.userId; - } else if (isInputPeerChat(peer)) { - return -peer.chatId; - } else if (isInputPeerChannel(peer)) { - return -peer.channelId; - } - return undefined; -} - export function getApiChatTypeFromPeerEntity(peerEntity: GramJs.TypeChat | GramJs.TypeUser) { if (peerEntity instanceof GramJs.User || peerEntity instanceof GramJs.UserEmpty) { return 'chatTypePrivate'; @@ -268,7 +250,7 @@ function getUserName(user: GramJs.User) { export function buildAvatarHash(photo: GramJs.TypeUserProfilePhoto | GramJs.TypeChatPhoto) { if ('photoId' in photo) { - return photo.photoId.toString(); + return String(photo.photoId); } return undefined; @@ -279,14 +261,14 @@ export function buildChatMember( ): ApiChatMember | undefined { const userId = (member instanceof GramJs.ChannelParticipantBanned || member instanceof GramJs.ChannelParticipantLeft) ? getApiChatIdFromMtpPeer(member.peer) - : member.userId; + : buildApiPeerId(member.userId, 'user'); return { userId, - inviterId: 'inviterId' in member ? member.inviterId : undefined, + inviterId: 'inviterId' in member ? buildApiPeerId(member.inviterId as BigInt.BigInteger, 'user') : undefined, joinedDate: 'date' in member ? member.date : undefined, - kickedByUserId: 'kickedBy' in member ? member.kickedBy : undefined, - promotedByUserId: 'promotedBy' in member ? member.promotedBy : undefined, + kickedByUserId: 'kickedBy' in member ? buildApiPeerId(member.kickedBy, 'user') : undefined, + promotedByUserId: 'promotedBy' in member ? 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, @@ -362,9 +344,9 @@ export function buildApiChatFolder(filter: GramJs.DialogFilter): ApiChatFolder { 'excludeMuted', 'excludeRead', 'excludeArchived', ]), channels: filter.broadcasts, - pinnedChatIds: filter.pinnedPeers.map(getApiChatIdFromInputMtpPeer).filter(Boolean as any), - includedChatIds: filter.includePeers.map(getApiChatIdFromInputMtpPeer).filter(Boolean as any), - excludedChatIds: filter.excludePeers.map(getApiChatIdFromInputMtpPeer).filter(Boolean as any), + pinnedChatIds: filter.pinnedPeers.map(getApiChatIdFromMtpPeer).filter(Boolean as any), + includedChatIds: filter.includePeers.map(getApiChatIdFromMtpPeer).filter(Boolean as any), + excludedChatIds: filter.excludePeers.map(getApiChatIdFromMtpPeer).filter(Boolean as any), }; } @@ -382,8 +364,10 @@ export function buildApiChatFolderFromSuggested({ export function buildApiChatBotCommands(botInfos: GramJs.BotInfo[]) { return botInfos.reduce((botCommands, botInfo) => { + const botId = buildApiPeerId(botInfo.userId, 'user'); + botCommands = botCommands.concat(botInfo.commands.map((mtpCommand) => ({ - botId: botInfo.userId, + botId, ...omitVirtualClassFields(mtpCommand), }))); diff --git a/src/api/gramjs/apiBuilders/helpers.ts b/src/api/gramjs/apiBuilders/helpers.ts index 5aff17a80..ba654b0af 100644 --- a/src/api/gramjs/apiBuilders/helpers.ts +++ b/src/api/gramjs/apiBuilders/helpers.ts @@ -1,20 +1,29 @@ +import { Api as GramJs } from '../../../lib/gramjs'; + +type VirtualFields = + 'flags' + | 'CONSTRUCTOR_ID' + | 'SUBCLASS_OF_ID' + | 'className' + | 'classType' + | 'getBytes'; + export function bytesToDataUri(bytes: Buffer, shouldOmitPrefix = false, mimeType: string = 'image/jpeg') { const prefix = shouldOmitPrefix ? '' : `data:${mimeType};base64,`; return `${prefix}${btoa(String.fromCharCode(...bytes))}`; } -export function omitVirtualClassFields(instance: any) { - if (!instance) { - return undefined; - } - +export function omitVirtualClassFields & { flags?: any }>( + instance: T, +): Omit { const { flags, CONSTRUCTOR_ID, SUBCLASS_OF_ID, className, classType, + getBytes, ...rest } = instance; diff --git a/src/api/gramjs/apiBuilders/messages.ts b/src/api/gramjs/apiBuilders/messages.ts index fa2ec54c6..037642763 100644 --- a/src/api/gramjs/apiBuilders/messages.ts +++ b/src/api/gramjs/apiBuilders/messages.ts @@ -32,21 +32,20 @@ import { VIDEO_MOV_TYPE, } from '../../../config'; import { pick } from '../../../util/iteratees'; -import { getApiChatIdFromMtpPeer } from './chats'; import { buildStickerFromDocument } from './symbols'; import { buildApiPhoto, buildApiPhotoSize, buildApiThumbnailFromStripped } from './common'; import { interpolateArray } from '../../../util/waveform'; import { buildPeer } from '../gramjsBuilders'; import { addPhotoToLocalDb, resolveMessageApiChatId } from '../helpers'; +import { buildApiPeerId, getApiChatIdFromMtpPeer } from './peers'; -const LOCAL_IMAGE_UPLOADING_TEMP_ID = 'temp'; -const LOCAL_VIDEO_UPLOADING_TEMP_ID = 'temp'; +const LOCAL_MEDIA_UPLOADING_TEMP_ID = 'temp'; const INPUT_WAVEFORM_LENGTH = 63; let localMessageCounter = LOCAL_MESSAGE_ID_BASE; -let currentUserId!: number; +let currentUserId!: string; -export function setMessageBuilderCurrentUserId(_currentUserId: number) { +export function setMessageBuilderCurrentUserId(_currentUserId: string) { currentUserId = _currentUserId; } @@ -62,20 +61,20 @@ export function buildApiMessage(mtpMessage: GramJs.TypeMessage): ApiMessage | un } export function buildApiMessageFromShort(mtpMessage: GramJs.UpdateShortMessage): ApiMessage { - const chatId = getApiChatIdFromMtpPeer({ userId: mtpMessage.userId } as GramJs.TypePeer); + const chatId = buildApiPeerId(mtpMessage.userId, 'user'); return buildApiMessageWithChatId(chatId, { ...mtpMessage, - fromId: buildPeer(mtpMessage.out ? currentUserId : mtpMessage.userId), + fromId: buildPeer(mtpMessage.out ? currentUserId : buildApiPeerId(mtpMessage.userId, 'user')), }); } export function buildApiMessageFromShortChat(mtpMessage: GramJs.UpdateShortChatMessage): ApiMessage { - const chatId = getApiChatIdFromMtpPeer({ chatId: mtpMessage.chatId } as GramJs.TypePeer); + const chatId = buildApiPeerId(mtpMessage.chatId, 'chat'); return buildApiMessageWithChatId(chatId, { ...mtpMessage, - fromId: buildPeer(mtpMessage.fromId), + fromId: buildPeer(buildApiPeerId(mtpMessage.fromId, 'user')), }); } @@ -117,7 +116,7 @@ type UniversalMessage = ( )> ); -export function buildApiMessageWithChatId(chatId: number, mtpMessage: UniversalMessage): ApiMessage { +export function buildApiMessageWithChatId(chatId: string, mtpMessage: UniversalMessage): ApiMessage { const fromId = mtpMessage.fromId ? getApiChatIdFromMtpPeer(mtpMessage.fromId) : undefined; const peerId = mtpMessage.peerId ? getApiChatIdFromMtpPeer(mtpMessage.peerId) : undefined; const isChatWithSelf = !fromId && chatId === currentUserId; @@ -151,7 +150,7 @@ export function buildApiMessageWithChatId(chatId: number, mtpMessage: UniversalM } = buildReplyButtons(mtpMessage) || {}; const forwardInfo = mtpMessage.fwdFrom && buildApiMessageForwardInfo(mtpMessage.fwdFrom, isChatWithSelf); const { replies, mediaUnread: isMediaUnread, postAuthor } = mtpMessage; - const groupedId = mtpMessage.groupedId && mtpMessage.groupedId.toString(); + const groupedId = mtpMessage.groupedId && String(mtpMessage.groupedId); const isInAlbum = Boolean(groupedId) && !(content.document || content.audio); const shouldHideKeyboardButtons = mtpMessage.replyMarkup instanceof GramJs.ReplyKeyboardHide; @@ -179,7 +178,7 @@ export function buildApiMessageWithChatId(chatId: number, mtpMessage: UniversalM inlineButtons, ...(keyboardButtons && { keyboardButtons, keyboardPlaceholder, isKeyboardSingleUse }), ...(shouldHideKeyboardButtons && { shouldHideKeyboardButtons }), - ...(mtpMessage.viaBotId && { viaBotId: mtpMessage.viaBotId }), + ...(mtpMessage.viaBotId && { viaBotId: buildApiPeerId(mtpMessage.viaBotId, 'user') }), ...(replies?.comments && { threadInfo: buildThreadInfo(replies, mtpMessage.id, chatId) }), ...(postAuthor && { adminTitle: postAuthor }), }; @@ -463,12 +462,13 @@ function buildContact(media: GramJs.TypeMessageMedia): ApiContact | undefined { return undefined; } - return pick(media, [ - 'firstName', - 'lastName', - 'phoneNumber', - 'userId', - ]); + const { + firstName, lastName, phoneNumber, userId, + } = media; + + return { + firstName, lastName, phoneNumber, userId: buildApiPeerId(userId, 'user'), + }; } function buildPollFromMedia(media: GramJs.TypeMessageMedia): ApiPoll | undefined { @@ -495,7 +495,7 @@ export function buildPoll(poll: GramJs.Poll, pollResults: GramJs.PollResults): A })); return { - id: id.toString(), + id: String(id), summary: { isPublic: poll.publicVoters, ...pick(poll, [ @@ -543,7 +543,7 @@ export function buildPollResults(pollResults: GramJs.PollResults): ApiPoll['resu return { totalVoters, - recentVoterIds: recentVoters, + recentVoterIds: recentVoters?.map((id) => buildApiPeerId(id, 'user')), results, solution, ...(entities && { solutionEntities: entities.map(buildApiMessageEntity) }), @@ -584,8 +584,8 @@ export function buildWebPage(media: GramJs.TypeMessageMedia): ApiWebPage | undef function buildAction( action: GramJs.TypeMessageAction, - senderId: number | undefined, - targetPeerId: number | undefined, + senderId: string | undefined, + targetPeerId: string | undefined, isChannelPost: boolean, isOutgoing: boolean, ): ApiAction | undefined { @@ -601,9 +601,9 @@ function buildAction( let photo: ApiPhoto | undefined; const targetUserIds = 'users' in action - ? action.users && action.users - : ('userId' in action && [action.userId]) || []; - let targetChatId: number | undefined; + ? action.users && action.users.map((id) => buildApiPeerId(id, 'user')) + : ('userId' in action && [buildApiPeerId(action.userId, 'user')]) || []; + let targetChatId: string | undefined; if (action instanceof GramJs.MessageActionChatCreate) { text = 'Notification.CreatedChatWithTitle'; @@ -908,7 +908,7 @@ function buildUploadingMedia( if (mimeType.startsWith('image/')) { return { photo: { - id: LOCAL_IMAGE_UPLOADING_TEMP_ID, + id: LOCAL_MEDIA_UPLOADING_TEMP_ID, sizes: [], thumbnail: { width, height, dataUri: '' }, // Used only for dimensions blobUrl, @@ -917,7 +917,7 @@ function buildUploadingMedia( } else { return { video: { - id: LOCAL_VIDEO_UPLOADING_TEMP_ID, + id: LOCAL_MEDIA_UPLOADING_TEMP_ID, mimeType, duration: duration || 0, fileName, @@ -962,7 +962,7 @@ function buildUploadingMedia( function buildNewPoll(poll: ApiNewPoll, localId: number) { return { poll: { - id: localId.toString(), + id: String(localId), summary: pick(poll.summary, ['question', 'answers']), results: {}, }, @@ -981,22 +981,26 @@ function buildApiMessageEntity(entity: GramJs.TypeMessageEntity): ApiMessageEnti } function buildThreadInfo( - messageReplies: GramJs.TypeMessageReplies, messageId: number, chatId: number, + messageReplies: GramJs.TypeMessageReplies, messageId: number, chatId: string, ): ApiThreadInfo | undefined { const { channelId, replies, maxId, readMaxId, recentRepliers, } = messageReplies; - - if (channelId === DELETED_COMMENTS_CHANNEL_ID) { + if (!channelId) { return undefined; } - const isPostThread = chatId !== channelId; + const apiChannelId = buildApiPeerId(channelId, 'channel'); + if (apiChannelId === DELETED_COMMENTS_CHANNEL_ID) { + return undefined; + } + + const isPostThread = chatId !== apiChannelId; return { threadId: messageId, ...(isPostThread ? { - chatId: getApiChatIdFromMtpPeer({ channelId } as GramJs.TypePeer), + chatId: apiChannelId, originChannelId: chatId, } : { chatId, diff --git a/src/api/gramjs/apiBuilders/misc.ts b/src/api/gramjs/apiBuilders/misc.ts index 89cff69b4..63942ce2a 100644 --- a/src/api/gramjs/apiBuilders/misc.ts +++ b/src/api/gramjs/apiBuilders/misc.ts @@ -4,7 +4,7 @@ import { ApiCountry, ApiSession, ApiWallpaper } from '../../types'; import { ApiPrivacySettings, ApiPrivacyKey, PrivacyVisibility } from '../../../types'; import { buildApiDocument } from './messages'; -import { getApiChatIdFromMtpPeer } from './chats'; +import { buildApiPeerId, getApiChatIdFromMtpPeer } from './peers'; import { flatten, pick } from '../../../util/iteratees'; import { getServerTime } from '../../../util/serverTime'; @@ -60,10 +60,10 @@ export function buildPrivacyKey(key: GramJs.TypePrivacyKey): ApiPrivacyKey | und export function buildPrivacyRules(rules: GramJs.TypePrivacyRule[]): ApiPrivacySettings { let visibility: PrivacyVisibility | undefined; - let allowUserIds: number[] | undefined; - let allowChatIds: number[] | undefined; - let blockUserIds: number[] | undefined; - let blockChatIds: number[] | undefined; + let allowUserIds: string[] | undefined; + let allowChatIds: string[] | undefined; + let blockUserIds: string[] | undefined; + let blockChatIds: string[] | undefined; rules.forEach((rule) => { if (rule instanceof GramJs.PrivacyValueAllowAll) { @@ -75,13 +75,13 @@ export function buildPrivacyRules(rules: GramJs.TypePrivacyRule[]): ApiPrivacySe } else if (rule instanceof GramJs.PrivacyValueDisallowAll) { visibility = visibility || 'nobody'; } else if (rule instanceof GramJs.PrivacyValueAllowUsers) { - allowUserIds = rule.users; + allowUserIds = rule.users.map((chatId) => buildApiPeerId(chatId, 'user')); } else if (rule instanceof GramJs.PrivacyValueDisallowUsers) { - blockUserIds = rule.users; + blockUserIds = rule.users.map((chatId) => buildApiPeerId(chatId, 'user')); } else if (rule instanceof GramJs.PrivacyValueAllowChatParticipants) { - allowChatIds = rule.chats.map((id) => -id); + allowChatIds = rule.chats.map((chatId) => buildApiPeerId(chatId, 'chat')); } else if (rule instanceof GramJs.PrivacyValueDisallowChatParticipants) { - blockChatIds = rule.chats.map((id) => -id); + blockChatIds = rule.chats.map((chatId) => buildApiPeerId(chatId, 'chat')); } }); @@ -113,6 +113,7 @@ export function buildApiNotifyException( ...(showPreviews !== undefined && { shouldShowPreviews: Boolean(showPreviews) }), }; } + function buildApiCountry(country: GramJs.help.Country, code?: GramJs.help.CountryCode) { const { hidden, iso2, defaultName, name, diff --git a/src/api/gramjs/apiBuilders/payments.ts b/src/api/gramjs/apiBuilders/payments.ts index b2156432a..08f0f12ef 100644 --- a/src/api/gramjs/apiBuilders/payments.ts +++ b/src/api/gramjs/apiBuilders/payments.ts @@ -96,7 +96,7 @@ export function buildPaymentForm(form: GramJs.payments.PaymentForm) { canSaveCredentials, passwordMissing, formId: String(formId), - providerId, + providerId: String(providerId), nativeProvider, savedInfo, invoice: { diff --git a/src/api/gramjs/apiBuilders/peers.ts b/src/api/gramjs/apiBuilders/peers.ts index 0dd8bac29..883e332e6 100644 --- a/src/api/gramjs/apiBuilders/peers.ts +++ b/src/api/gramjs/apiBuilders/peers.ts @@ -1,25 +1,29 @@ +import BigInt from 'big-integer'; + import { Api as GramJs } from '../../../lib/gramjs'; -export function isPeerUser(peer: GramJs.TypePeer): peer is GramJs.PeerUser { +export function isPeerUser(peer: GramJs.TypePeer | GramJs.TypeInputPeer): peer is GramJs.PeerUser { return peer.hasOwnProperty('userId'); } -export function isPeerChat(peer: GramJs.TypePeer): peer is GramJs.PeerChat { +export function isPeerChat(peer: GramJs.TypePeer | GramJs.TypeInputPeer): peer is GramJs.PeerChat { return peer.hasOwnProperty('chatId'); } -export function isPeerChannel(peer: GramJs.TypePeer): peer is GramJs.PeerChannel { +export function isPeerChannel(peer: GramJs.TypePeer | GramJs.TypeInputPeer): peer is GramJs.PeerChannel { return peer.hasOwnProperty('channelId'); } -export function isInputPeerUser(peer: GramJs.TypeInputPeer): peer is GramJs.InputPeerUser { - return peer.hasOwnProperty('userId'); +export function buildApiPeerId(id: BigInt.BigInteger, type: 'user' | 'chat' | 'channel') { + return type === 'user' ? String(id) : `-${id}`; } -export function isInputPeerChat(peer: GramJs.TypeInputPeer): peer is GramJs.InputPeerChat { - return peer.hasOwnProperty('chatId'); -} - -export function isInputPeerChannel(peer: GramJs.TypeInputPeer): peer is GramJs.InputPeerChannel { - return peer.hasOwnProperty('channelId'); +export function getApiChatIdFromMtpPeer(peer: GramJs.TypePeer | GramJs.TypeInputPeer) { + if (isPeerUser(peer)) { + return buildApiPeerId(peer.userId, 'user'); + } else if (isPeerChat(peer)) { + return buildApiPeerId(peer.chatId, 'chat'); + } else { + return buildApiPeerId((peer as GramJs.InputPeerChannel).channelId, 'channel'); + } } diff --git a/src/api/gramjs/apiBuilders/symbols.ts b/src/api/gramjs/apiBuilders/symbols.ts index ca675bc63..793f95146 100644 --- a/src/api/gramjs/apiBuilders/symbols.ts +++ b/src/api/gramjs/apiBuilders/symbols.ts @@ -72,7 +72,6 @@ export function buildStickerSet(set: GramJs.StickerSet): ApiStickerSet { title, thumbs, count, - hash, shortName, } = set; @@ -85,7 +84,6 @@ export function buildStickerSet(set: GramJs.StickerSet): ApiStickerSet { title, hasThumbnail: Boolean(thumbs?.length), count, - hash, shortName, }; } diff --git a/src/api/gramjs/apiBuilders/users.ts b/src/api/gramjs/apiBuilders/users.ts index bd304df82..cd2dafebb 100644 --- a/src/api/gramjs/apiBuilders/users.ts +++ b/src/api/gramjs/apiBuilders/users.ts @@ -2,21 +2,24 @@ import { Api as GramJs } from '../../../lib/gramjs'; import { ApiBotCommand, ApiUser, ApiUserStatus, ApiUserType, } from '../../types'; +import { buildApiPeerId } from './peers'; export function buildApiUserFromFull(mtpUserFull: GramJs.UserFull): ApiUser { const { about, commonChatsCount, pinnedMsgId, botInfo, blocked, } = mtpUserFull; + const user = buildApiUser(mtpUserFull.user)!; + return { - ...(buildApiUser(mtpUserFull.user) as ApiUser), + ...user, fullInfo: { bio: about, commonChatsCount, pinnedMessageId: pinnedMsgId, isBlocked: Boolean(blocked), ...(botInfo && { botDescription: botInfo.description }), - ...(botInfo && botInfo.commands.length && { botCommands: buildApiBotCommands(mtpUserFull.user.id, botInfo) }), + ...(botInfo && botInfo.commands.length && { botCommands: buildApiBotCommands(user.id, botInfo) }), }, }; } @@ -33,7 +36,7 @@ export function buildApiUser(mtpUser: GramJs.TypeUser): ApiUser | undefined { const userType = buildApiUserType(mtpUser); return { - id, + id: buildApiPeerId(id, 'user'), isMin: Boolean(mtpUser.min), ...(mtpUser.self && { isSelf: true }), ...(mtpUser.verified && { isVerified: true }), @@ -78,7 +81,7 @@ export function buildApiUserStatus(mtpStatus?: GramJs.TypeUserStatus): ApiUserSt } } -function buildApiBotCommands(botId: number, botInfo: GramJs.BotInfo) { +function buildApiBotCommands(botId: string, botInfo: GramJs.BotInfo) { return botInfo.commands.map(({ command, description }) => ({ botId, command, diff --git a/src/api/gramjs/gramjsBuilders/index.ts b/src/api/gramjs/gramjsBuilders/index.ts index b13bf2091..56e29798e 100644 --- a/src/api/gramjs/gramjsBuilders/index.ts +++ b/src/api/gramjs/gramjsBuilders/index.ts @@ -18,7 +18,24 @@ import { import localDb from '../localDb'; import { pick } from '../../../util/iteratees'; -export function getEntityTypeById(chatOrUserId: number) { +const CHANNEL_ID_MIN_LENGTH = 11; // Example: -1000000000 + +export function getEntityTypeById(chatOrUserId: string) { + if (typeof chatOrUserId === 'number') { + return getEntityTypeByDeprecatedId(chatOrUserId); + } + + if (!chatOrUserId.startsWith('-')) { + return 'user'; + } else if (chatOrUserId.length >= CHANNEL_ID_MIN_LENGTH) { + return 'channel'; + } else { + return 'chat'; + } +} + +// Workaround for old-fashioned IDs stored locally +export function getEntityTypeByDeprecatedId(chatOrUserId: number) { if (chatOrUserId > 0) { return 'user'; } else if (chatOrUserId <= -1000000000) { @@ -28,81 +45,78 @@ export function getEntityTypeById(chatOrUserId: number) { } } -export function buildPeer(chatOrUserId: number): GramJs.TypePeer { - if (chatOrUserId > 0) { +export function buildPeer(chatOrUserId: string): GramJs.TypePeer { + const type = getEntityTypeById(chatOrUserId); + + if (type === 'user') { return new GramJs.PeerUser({ - userId: chatOrUserId, + userId: buildMtpPeerId(chatOrUserId, 'user'), }); - } else if (chatOrUserId <= -1000000000) { + } else if (type === 'channel') { return new GramJs.PeerChannel({ - channelId: -chatOrUserId, + channelId: buildMtpPeerId(chatOrUserId, 'channel'), }); } else { return new GramJs.PeerChat({ - chatId: -chatOrUserId, + chatId: buildMtpPeerId(chatOrUserId, 'chat'), }); } } -export function buildInputPeer(chatOrUserId: number, accessHash?: string): GramJs.TypeInputPeer { - if (chatOrUserId > 0 || chatOrUserId <= -1000000000) { - return chatOrUserId > 0 - ? new GramJs.InputPeerUser({ - userId: chatOrUserId, - accessHash: BigInt(accessHash!), - }) - : new GramJs.InputPeerChannel({ - channelId: -chatOrUserId, - accessHash: BigInt(accessHash!), - }); +export function buildInputPeer(chatOrUserId: string, accessHash?: string): GramJs.TypeInputPeer { + const type = getEntityTypeById(chatOrUserId); + + if (type === 'user') { + return new GramJs.InputPeerUser({ + userId: buildMtpPeerId(chatOrUserId, 'user'), + accessHash: BigInt(accessHash!), + }); + } else if (type === 'channel') { + return new GramJs.InputPeerChannel({ + channelId: buildMtpPeerId(chatOrUserId, 'channel'), + accessHash: BigInt(accessHash!), + }); } else { return new GramJs.InputPeerChat({ - chatId: -chatOrUserId, + chatId: buildMtpPeerId(chatOrUserId, 'chat'), }); } } -export function buildInputPeerFromLocalDb(chatOrUserId: number): GramJs.TypeInputPeer | undefined { - if (chatOrUserId > 0) { - const { accessHash } = localDb.users[chatOrUserId] || {}; +export function buildInputPeerFromLocalDb(chatOrUserId: string): GramJs.TypeInputPeer | undefined { + const type = getEntityTypeById(chatOrUserId); + let accessHash: BigInt.BigInteger | undefined; - return accessHash - ? new GramJs.InputPeerUser({ - userId: chatOrUserId, - accessHash, - }) - : undefined; + if (type === 'user') { + accessHash = localDb.users[chatOrUserId]?.accessHash; + if (!accessHash) { + return undefined; + } + } else if (type === 'channel') { + accessHash = (localDb.chats[chatOrUserId] as GramJs.Channel)?.accessHash; + if (!accessHash) { + return undefined; + } } - if (chatOrUserId <= -1000000000) { - const { accessHash } = (localDb.chats[-chatOrUserId] as GramJs.Channel) || {}; - - return accessHash - ? new GramJs.InputPeerChannel({ - channelId: -chatOrUserId, - accessHash, - }) - : undefined; - } - - return new GramJs.InputPeerChat({ - chatId: -chatOrUserId, - }); + return buildInputPeer(chatOrUserId, String(accessHash)); } -export function buildInputEntity(chatOrUserId: number, accessHash?: string) { - if (chatOrUserId > 0) { +export function buildInputEntity(chatOrUserId: string, accessHash?: string) { + const type = getEntityTypeById(chatOrUserId); + + if (type === 'user') { return new GramJs.InputUser({ - userId: chatOrUserId, + userId: buildMtpPeerId(chatOrUserId, 'user'), accessHash: BigInt(accessHash!), }); - } else if (chatOrUserId <= -1000000000) { + } else if (type === 'channel') { return new GramJs.InputChannel({ - channelId: -chatOrUserId, + channelId: buildMtpPeerId(chatOrUserId, 'channel'), accessHash: BigInt(accessHash!), }); } else { - return -chatOrUserId; + return buildMtpPeerId(chatOrUserId, 'chat'); } } @@ -225,7 +239,7 @@ export function generateRandomBigInt() { export function buildMessageFromUpdate( id: number, - chatId: number, + chatId: string, update: GramJs.UpdateShortSentMessage | GramJs.UpdateServiceNotification, ) { // This is not a proper message, but we only need these fields for downloading media through `localDb`. @@ -269,24 +283,13 @@ export function buildMtpMessageEntity(entity: ApiMessageEntity): GramJs.TypeMess return new GramJs.InputMessageEntityMentionName({ offset, length, - userId: new GramJs.InputUser({ userId: userId!, accessHash: user!.accessHash! }), + userId: new GramJs.InputUser({ userId: BigInt(userId!), accessHash: user!.accessHash! }), }); default: return new GramJs.MessageEntityUnknown({ offset, length }); } } -// TODO: This formula is taken from API docs, but doesn't seem to calculate hash correctly -export function calculateResultHash(ids: number[]) { - let hash = 0; - ids.forEach((id) => { - // eslint-disable-next-line no-bitwise - hash = (((hash * 0x4F25) & 0x7FFFFFFF) + id) & 0x7FFFFFFF; - }); - - return hash; -} - export function isMessageWithMedia(message: GramJs.Message | GramJs.UpdateServiceNotification) { const { media } = message; if (!media) { @@ -412,3 +415,12 @@ export function buildInputReportReason(reason: ApiReportReason) { return undefined; } + +function buildMtpPeerId(id: string, type: 'user' | 'chat' | 'channel') { + // Workaround for old-fashioned IDs stored locally + if (typeof id === 'number') { + return BigInt(Math.abs(id)); + } + + return type === 'user' ? BigInt(id) : BigInt(id.slice(1)); +} diff --git a/src/api/gramjs/helpers.ts b/src/api/gramjs/helpers.ts index 8a7fca1b6..f9754d908 100644 --- a/src/api/gramjs/helpers.ts +++ b/src/api/gramjs/helpers.ts @@ -1,6 +1,6 @@ import { Api as GramJs } from '../../lib/gramjs'; import localDb from './localDb'; -import { getApiChatIdFromMtpPeer } from './apiBuilders/chats'; +import { getApiChatIdFromMtpPeer } from './apiBuilders/peers'; export function resolveMessageApiChatId(mtpMessage: GramJs.TypeMessage) { if (!(mtpMessage instanceof GramJs.Message || mtpMessage instanceof GramJs.MessageService)) { diff --git a/src/api/gramjs/localDb.ts b/src/api/gramjs/localDb.ts index 91a5ac0f5..589a5fc9f 100644 --- a/src/api/gramjs/localDb.ts +++ b/src/api/gramjs/localDb.ts @@ -4,8 +4,8 @@ import { ApiMessage } from '../types'; interface LocalDb { localMessages: Record; // Used for loading avatars and media through in-memory Gram JS instances. - chats: Record; - users: Record; + chats: Record; + users: Record; messages: Record; documents: Record; stickerSets: Record; diff --git a/src/api/gramjs/methods/bots.ts b/src/api/gramjs/methods/bots.ts index ee31d2963..e1cc37d29 100644 --- a/src/api/gramjs/methods/bots.ts +++ b/src/api/gramjs/methods/bots.ts @@ -5,10 +5,11 @@ import { ApiChat, ApiUser } from '../../types'; import localDb from '../localDb'; import { invokeRequest } from './client'; -import { buildInputPeer, calculateResultHash, generateRandomBigInt } from '../gramjsBuilders'; +import { buildInputPeer, generateRandomBigInt } from '../gramjsBuilders'; import { buildApiUser } from '../apiBuilders/users'; import { buildApiBotInlineMediaResult, buildApiBotInlineResult, buildBotSwitchPm } from '../apiBuilders/bots'; import { buildApiChatFromPreview } from '../apiBuilders/chats'; +import { buildApiPeerId } from '../apiBuilders/peers'; export function init() { } @@ -17,7 +18,7 @@ export function answerCallbackButton( { chatId, accessHash, messageId, data, }: { - chatId: number; accessHash?: string; messageId: number; data: string; + chatId: string; accessHash?: string; messageId: number; data: string; }, ) { return invokeRequest(new GramJs.messages.GetBotCallbackAnswer({ @@ -27,9 +28,8 @@ export function answerCallbackButton( })); } -export async function fetchTopInlineBots({ hash = 0 }: { hash?: number }) { +export async function fetchTopInlineBots() { const topPeers = await invokeRequest(new GramJs.contacts.GetTopPeers({ - hash, botsInline: true, })); @@ -41,7 +41,6 @@ export async function fetchTopInlineBots({ hash = 0 }: { hash?: number }) { const ids = users.map(({ id }) => id); return { - hash: calculateResultHash(ids), ids, users, }; @@ -160,7 +159,7 @@ function getInlineBotResultsNextOffset(username: string, nextOffset?: string) { } function addUserToLocalDb(user: GramJs.User) { - localDb.users[user.id] = user; + localDb.users[buildApiPeerId(user.id, 'user')] = user; } function addDocumentToLocalDb(document: GramJs.Document) { diff --git a/src/api/gramjs/methods/chats.ts b/src/api/gramjs/methods/chats.ts index 13ef1d90e..945b01b26 100644 --- a/src/api/gramjs/methods/chats.ts +++ b/src/api/gramjs/methods/chats.ts @@ -1,3 +1,4 @@ +import BigInt from 'big-integer'; import { Api as GramJs } from '../../../lib/gramjs'; import { OnApiUpdate, @@ -21,7 +22,6 @@ import { getPeerKey, buildChatMembers, buildApiChatFromPreview, - getApiChatIdFromMtpPeer, buildApiChatFolder, buildApiChatFolderFromSuggested, buildApiChatBotCommands, @@ -40,6 +40,7 @@ import { buildChatAdminRights, } from '../gramjsBuilders'; import { addMessageToLocalDb } from '../helpers'; +import { buildApiPeerId, getApiChatIdFromMtpPeer } from '../apiBuilders/peers'; const MAX_INT_32 = 2 ** 31 - 1; let onUpdate: OnApiUpdate; @@ -96,12 +97,12 @@ export async function fetchChats({ ...preparePeers(result), }; const chats: ApiChat[] = []; - const draftsById: Record = {}; - const replyingToById: Record = {}; + const draftsById: Record = {}; + const replyingToById: Record = {}; const dialogs = (resultPinned ? resultPinned.dialogs : []).concat(result.dialogs); - const orderedPinnedIds: number[] = []; + const orderedPinnedIds: string[] = []; dialogs.forEach((dialog) => { if ( @@ -325,12 +326,12 @@ export function clearDraft(chat: ApiChat) { })); } -async function getFullChatInfo(chatId: number): Promise<{ +async function getFullChatInfo(chatId: string): Promise<{ fullInfo: ApiChatFullInfo; users?: ApiUser[]; } | undefined> { const result = await invokeRequest(new GramJs.messages.GetFullChat({ - chatId: buildInputEntity(chatId) as number, + chatId: buildInputEntity(chatId) as BigInt.BigInteger, })); if (!result || !(result.fullChat instanceof GramJs.ChatFull)) { @@ -366,7 +367,7 @@ async function getFullChatInfo(chatId: number): Promise<{ } async function getFullChannelInfo( - id: number, + id: string, accessHash: string, adminRights?: ApiChatAdminRights, ) { @@ -430,7 +431,7 @@ async function getFullChannelInfo( nextSendDate: slowmodeNextSendDate, } : undefined, migratedFrom: migratedFromChatId ? { - chatId: getApiChatIdFromMtpPeer({ chatId: migratedFromChatId } as GramJs.TypePeer), + chatId: buildApiPeerId(migratedFromChatId, 'chat'), maxMessageId: migratedFromMaxId, } : undefined, canViewMembers: canViewParticipants, @@ -438,8 +439,8 @@ async function getFullChannelInfo( members, kickedMembers, adminMembers, - groupCallId: call ? call.id.toString() : undefined, - linkedChatId: linkedChatId ? getApiChatIdFromMtpPeer({ chatId: linkedChatId } as GramJs.TypePeer) : undefined, + groupCallId: call ? String(call.id) : undefined, + linkedChatId: linkedChatId ? buildApiPeerId(linkedChatId, 'chat') : undefined, botCommands, }, users: [...(users || []), ...(bannedUsers || []), ...(adminUsers || [])], @@ -515,7 +516,7 @@ export async function createChannel({ export function joinChannel({ channelId, accessHash, }: { - channelId: number; accessHash: string; + channelId: string; accessHash: string; }) { return invokeRequest(new GramJs.channels.JoinChannel({ channel: buildInputEntity(channelId, accessHash) as GramJs.InputChannel, @@ -529,7 +530,7 @@ export function deleteChatUser({ }) { if (chat.type !== 'chatTypeBasicGroup') return undefined; return invokeRequest(new GramJs.messages.DeleteChatUser({ - chatId: buildInputEntity(chat.id, chat.accessHash) as number, + chatId: buildInputEntity(chat.id, chat.accessHash) as BigInt.BigInteger, userId: buildInputEntity(user.id, user.accessHash) as GramJs.InputUser, }), true); } @@ -537,17 +538,17 @@ export function deleteChatUser({ export function deleteChat({ chatId, }: { - chatId: number; + chatId: string; }) { return invokeRequest(new GramJs.messages.DeleteChat({ - chatId: buildInputEntity(chatId) as number, + chatId: buildInputEntity(chatId) as BigInt.BigInteger, }), true); } export function leaveChannel({ channelId, accessHash, }: { - channelId: number; accessHash: string; + channelId: string; accessHash: string; }) { return invokeRequest(new GramJs.channels.LeaveChannel({ channel: buildInputEntity(channelId, accessHash) as GramJs.InputChannel, @@ -557,7 +558,7 @@ export function leaveChannel({ export function deleteChannel({ channelId, accessHash, }: { - channelId: number; accessHash: string; + channelId: string; accessHash: string; }) { return invokeRequest(new GramJs.channels.DeleteChannel({ channel: buildInputEntity(channelId, accessHash) as GramJs.InputChannel, @@ -600,7 +601,7 @@ export async function createGroupChat({ export async function editChatPhoto({ chatId, accessHash, photo, }: { - chatId: number; accessHash?: string; photo: File; + chatId: string; accessHash?: string; photo: File; }) { const uploadedPhoto = await uploadFile(photo); const inputEntity = buildInputEntity(chatId, accessHash); @@ -614,7 +615,7 @@ export async function editChatPhoto({ }), }) : new GramJs.messages.EditChatPhoto({ - chatId: inputEntity as number, + chatId: inputEntity as BigInt.BigInteger, photo: new GramJs.InputChatUploadedPhoto({ file: uploadedPhoto, }), @@ -837,7 +838,7 @@ export async function updateChatTitle(chat: ApiChat, title: string) { channel: inputEntity as GramJs.InputChannel, title, }) : new GramJs.messages.EditChatTitle({ - chatId: inputEntity as number, + chatId: inputEntity as BigInt.BigInteger, title, }), true, @@ -881,7 +882,7 @@ type ChannelMembersFilter = | 'recent'; export async function fetchMembers( - chatId: number, + chatId: string, accessHash: string, memberFilter: ChannelMembersFilter = 'recent', offset?: number, @@ -946,7 +947,7 @@ export function setDiscussionGroup({ export async function migrateChat(chat: ApiChat) { const result = await invokeRequest( - new GramJs.messages.MigrateChat({ chatId: buildInputEntity(chat.id) as number }), true, + new GramJs.messages.MigrateChat({ chatId: buildInputEntity(chat.id) as BigInt.BigInteger }), true, ); // `migrateChat` can return a lot of different update types according to docs, @@ -1014,7 +1015,7 @@ export function addChatMembers(chat: ApiChat, users: ApiUser[]) { return Promise.all(users.map((user) => { return invokeRequest(new GramJs.messages.AddChatUser({ - chatId: buildInputEntity(chat.id) as number, + chatId: buildInputEntity(chat.id) as BigInt.BigInteger, userId: buildInputEntity(user.id, user.accessHash) as GramJs.InputUser, }), true); })); @@ -1043,7 +1044,7 @@ export function deleteChatMember(chat: ApiChat, user: ApiUser) { }); } else { return invokeRequest(new GramJs.messages.DeleteChatUser({ - chatId: buildInputEntity(chat.id) as number, + chatId: buildInputEntity(chat.id) as BigInt.BigInteger, userId: buildInputEntity(user.id, user.accessHash) as GramJs.InputUser, }), true); } @@ -1074,7 +1075,7 @@ function updateLocalDb(result: ( if ('users' in result) { result.users.forEach((user) => { if (user instanceof GramJs.User) { - localDb.users[user.id] = user; + localDb.users[buildApiPeerId(user.id, 'user')] = user; } }); } @@ -1082,7 +1083,7 @@ function updateLocalDb(result: ( if ('chats' in result) { result.chats.forEach((chat) => { if (chat instanceof GramJs.Chat || chat instanceof GramJs.Channel) { - localDb.chats[chat.id] = chat; + localDb.chats[buildApiPeerId(chat.id, chat instanceof GramJs.Chat ? 'chat' : 'channel')] = chat; } }); } @@ -1102,7 +1103,5 @@ export async function importChatInvite({ hash }: { hash: string }) { return undefined; } - const chat = buildApiChatFromPreview(updates.chats[0]); - - return chat; + return buildApiChatFromPreview(updates.chats[0]); } diff --git a/src/api/gramjs/methods/client.ts b/src/api/gramjs/methods/client.ts index 3a0029c19..271951be1 100644 --- a/src/api/gramjs/methods/client.ts +++ b/src/api/gramjs/methods/client.ts @@ -24,6 +24,7 @@ import { setMessageBuilderCurrentUserId } from '../apiBuilders/messages'; import downloadMediaWithClient from './media'; import { buildApiUserFromFull } from '../apiBuilders/users'; import localDb from '../localDb'; +import { buildApiPeerId } from '../apiBuilders/peers'; const DEFAULT_USER_AGENT = 'Unknown UserAgent'; const APP_CODE_NAME = 'Z'; @@ -254,7 +255,7 @@ export async function fetchCurrentUser() { return; } - localDb.users[userFull.user.id] = userFull.user; + localDb.users[buildApiPeerId(userFull.user.id, 'user')] = userFull.user; const currentUser = buildApiUserFromFull(userFull); setMessageBuilderCurrentUserId(currentUser.id); diff --git a/src/api/gramjs/methods/media.ts b/src/api/gramjs/methods/media.ts index 5bed8d693..3528c9e59 100644 --- a/src/api/gramjs/methods/media.ts +++ b/src/api/gramjs/methods/media.ts @@ -91,16 +91,16 @@ async function download( } let entityType: EntityType; - let entityId: string | number = mediaMatch[2]; + const entityId: string | number = mediaMatch[2]; const sizeType = mediaMatch[3] ? mediaMatch[3].replace('?size=', '') : undefined; let entity: ( GramJs.User | GramJs.Chat | GramJs.Channel | GramJs.Photo | - GramJs.Message | GramJs.Document | GramJs.StickerSet | GramJs.TypeWebDocument | undefined + GramJs.Message | GramJs.MessageService | + GramJs.Document | GramJs.StickerSet | GramJs.TypeWebDocument | undefined ); if (mediaMatch[1] === 'avatar' || mediaMatch[1] === 'profile') { - entityType = getEntityTypeById(Number(entityId)); - entityId = Math.abs(Number(entityId)); + entityType = getEntityTypeById(entityId); } else { entityType = mediaMatch[1] as 'msg' | 'sticker' | 'wallpaper' | 'gif' | 'stickerSet' | 'photo' | 'webDocument'; } @@ -108,27 +108,27 @@ async function download( switch (entityType) { case 'channel': case 'chat': - entity = localDb.chats[entityId as number]; + entity = localDb.chats[entityId]; break; case 'user': - entity = localDb.users[entityId as number]; + entity = localDb.users[entityId]; break; case 'msg': - entity = localDb.messages[entityId as string]; + entity = localDb.messages[entityId]; break; case 'sticker': case 'gif': case 'wallpaper': - entity = localDb.documents[entityId as string]; + entity = localDb.documents[entityId]; break; case 'photo': - entity = localDb.photos[entityId as string]; + entity = localDb.photos[entityId]; break; case 'stickerSet': - entity = localDb.stickerSets[entityId as string]; + entity = localDb.stickerSets[entityId]; break; case 'webDocument': - entity = localDb.webDocuments[entityId as string]; + entity = localDb.webDocuments[entityId]; break; } diff --git a/src/api/gramjs/methods/messages.ts b/src/api/gramjs/methods/messages.ts index 5a92b8d0a..8cce84926 100644 --- a/src/api/gramjs/methods/messages.ts +++ b/src/api/gramjs/methods/messages.ts @@ -43,7 +43,6 @@ import { buildMtpMessageEntity, isMessageWithMedia, isServiceMessageWithMedia, - calculateResultHash, buildInputReportReason, } from '../gramjsBuilders'; import localDb from '../localDb'; @@ -52,6 +51,7 @@ import { fetchFile } from '../../../util/files'; import { addMessageToLocalDb, resolveMessageApiChatId } from '../helpers'; import { interpolateArray } from '../../../util/waveform'; import { requestChatUpdate } from './chats'; +import { buildApiPeerId } from '../apiBuilders/peers'; const FAST_SEND_TIMEOUT = 1000; const INPUT_WAVEFORM_LENGTH = 63; @@ -238,7 +238,7 @@ export function sendMessage( }, FAST_SEND_TIMEOUT); const randomId = generateRandomBigInt(); - localDb.localMessages[randomId.toString()] = localMessage; + localDb.localMessages[String(randomId)] = localMessage; if (groupedId) { return sendGroupedMedia({ @@ -1078,12 +1078,11 @@ export async function findFirstMessageIdAfterDate({ return result.messages[0].id; } -export async function fetchScheduledHistory({ chat, hash = 0 }: { chat: ApiChat; hash?: number }) { +export async function fetchScheduledHistory({ chat }: { chat: ApiChat }) { const { id, accessHash } = chat; const result = await invokeRequest(new GramJs.messages.GetScheduledHistory({ peer: buildInputPeer(id, accessHash), - hash, })); if ( @@ -1100,7 +1099,6 @@ export async function fetchScheduledHistory({ chat, hash = 0 }: { chat: ApiChat; return { messages, - hash: calculateResultHash(messages.map((message) => message.id)), }; } @@ -1119,13 +1117,13 @@ function updateLocalDb(result: ( )) { result.users.forEach((user) => { if (user instanceof GramJs.User) { - localDb.users[user.id] = user; + localDb.users[buildApiPeerId(user.id, 'user')] = user; } }); result.chats.forEach((chat) => { if (chat instanceof GramJs.Chat || chat instanceof GramJs.Channel) { - localDb.chats[chat.id] = chat; + localDb.chats[buildApiPeerId(chat.id, chat instanceof GramJs.Chat ? 'chat' : 'channel')] = chat; } }); diff --git a/src/api/gramjs/methods/settings.ts b/src/api/gramjs/methods/settings.ts index 14b7a9be0..a741e87f5 100644 --- a/src/api/gramjs/methods/settings.ts +++ b/src/api/gramjs/methods/settings.ts @@ -4,7 +4,7 @@ import { Api as GramJs } from '../../../lib/gramjs'; import { ApiChat, ApiLangString, ApiLanguage, ApiNotifyException, ApiUser, ApiWallpaper, } from '../../types'; -import { ApiPrivacyKey, IInputPrivacyRules } from '../../../types'; +import { ApiPrivacyKey, InputPrivacyRules } from '../../../types'; import { BLOCKED_LIST_LIMIT, DEFAULT_LANG_PACK, LANG_PACKS } from '../../../config'; import { @@ -12,13 +12,14 @@ import { } from '../apiBuilders/misc'; import { buildApiUser } from '../apiBuilders/users'; -import { buildApiChatFromPreview, getApiChatIdFromMtpPeer } from '../apiBuilders/chats'; -import { buildInputPrivacyKey, buildInputPeer } from '../gramjsBuilders'; +import { buildApiChatFromPreview } from '../apiBuilders/chats'; +import { buildInputPrivacyKey, buildInputPeer, buildInputEntity } from '../gramjsBuilders'; import { invokeRequest, uploadFile, getClient } from './client'; import { omitVirtualClassFields } from '../apiBuilders/helpers'; import { buildCollectionByKey } from '../../../util/iteratees'; import localDb from '../localDb'; import { getServerTime } from '../../../util/serverTime'; +import { buildApiPeerId, getApiChatIdFromMtpPeer } from '../apiBuilders/peers'; const MAX_INT_32 = 2 ** 31 - 1; const BETA_LANG_CODES = ['ar', 'fa', 'id', 'ko', 'uz']; @@ -61,8 +62,8 @@ export async function uploadProfilePhoto(file: File) { })); } -export async function fetchWallpapers(hash: number) { - const result = await invokeRequest(new GramJs.account.GetWallPapers({ hash })); +export async function fetchWallpapers() { + const result = await invokeRequest(new GramJs.account.GetWallPapers({ hash: BigInt('0') })); if (!result || result instanceof GramJs.account.WallPapersNotModified) { return undefined; @@ -84,7 +85,6 @@ export async function fetchWallpapers(hash: number) { }); return { - hash: result.hash, wallpapers: filteredWallpapers.map(buildApiWallpaper).filter(Boolean as any), }; } @@ -130,13 +130,13 @@ export async function fetchBlockedContacts() { }; } -export function blockContact(chatOrUserId: number, accessHash?: string) { +export function blockContact(chatOrUserId: string, accessHash?: string) { return invokeRequest(new GramJs.contacts.Block({ id: buildInputPeer(chatOrUserId, accessHash), })); } -export function unblockContact(chatOrUserId: number, accessHash?: string) { +export function unblockContact(chatOrUserId: string, accessHash?: string) { return invokeRequest(new GramJs.contacts.Unblock({ id: buildInputPeer(chatOrUserId, accessHash), })); @@ -353,29 +353,29 @@ export function unregisterDevice(token: string) { } export async function setPrivacySettings( - privacyKey: ApiPrivacyKey, rules: IInputPrivacyRules, + privacyKey: ApiPrivacyKey, rules: InputPrivacyRules, ) { const key = buildInputPrivacyKey(privacyKey); const privacyRules: GramJs.TypeInputPrivacyRule[] = []; if (rules.allowedUsers) { privacyRules.push(new GramJs.InputPrivacyValueAllowUsers({ - users: rules.allowedUsers.map(({ id, accessHash }) => buildInputPeer(id, accessHash)), + users: rules.allowedUsers.map(({ id, accessHash }) => buildInputEntity(id, accessHash) as GramJs.InputUser), })); } if (rules.allowedChats) { privacyRules.push(new GramJs.InputPrivacyValueAllowChatParticipants({ - chats: rules.allowedChats.map(({ id }) => -id), + chats: rules.allowedChats.map(({ id }) => buildInputEntity(id) as BigInt.BigInteger), })); } if (rules.blockedUsers) { privacyRules.push(new GramJs.InputPrivacyValueDisallowUsers({ - users: rules.blockedUsers.map(({ id, accessHash }) => buildInputPeer(id, accessHash)), + users: rules.blockedUsers.map(({ id, accessHash }) => buildInputEntity(id, accessHash) as GramJs.InputUser), })); } if (rules.blockedChats) { privacyRules.push(new GramJs.InputPrivacyValueDisallowChatParticipants({ - chats: rules.blockedChats.map(({ id }) => -id), + chats: rules.blockedChats.map(({ id }) => buildInputEntity(id) as BigInt.BigInteger), })); } switch (rules.visibility) { @@ -437,13 +437,13 @@ function updateLocalDb( ) { result.users.forEach((user) => { if (user instanceof GramJs.User) { - localDb.users[user.id] = user; + localDb.users[buildApiPeerId(user.id, 'user')] = user; } }); result.chats.forEach((chat) => { if (chat instanceof GramJs.Chat || chat instanceof GramJs.Channel) { - localDb.chats[chat.id] = chat; + localDb.chats[buildApiPeerId(chat.id, chat instanceof GramJs.Chat ? 'chat' : 'channel')] = chat; } }); } diff --git a/src/api/gramjs/methods/symbols.ts b/src/api/gramjs/methods/symbols.ts index 0c7514b86..922db3970 100644 --- a/src/api/gramjs/methods/symbols.ts +++ b/src/api/gramjs/methods/symbols.ts @@ -1,3 +1,4 @@ +import BigInt from 'big-integer'; import { Api as GramJs } from '../../../lib/gramjs'; import { ApiSticker, ApiVideo, OnApiUpdate } from '../../types'; @@ -15,8 +16,8 @@ export function init(_onUpdate: OnApiUpdate) { onUpdate = _onUpdate; } -export async function fetchStickerSets({ hash }: { hash: number }) { - const allStickers = await invokeRequest(new GramJs.messages.GetAllStickers({ hash })); +export async function fetchStickerSets({ hash = '0' }: { hash?: string }) { + const allStickers = await invokeRequest(new GramJs.messages.GetAllStickers({ hash: BigInt(hash) })); if (!allStickers || allStickers instanceof GramJs.messages.AllStickersNotModified) { return undefined; @@ -29,46 +30,46 @@ export async function fetchStickerSets({ hash }: { hash: number }) { }); return { - hash: allStickers.hash, + hash: String(allStickers.hash), sets: allStickers.sets.map(buildStickerSet), }; } -export async function fetchRecentStickers({ hash }: { hash: number }) { - const result = await invokeRequest(new GramJs.messages.GetRecentStickers({ hash })); +export async function fetchRecentStickers({ hash = '0' }: { hash?: string }) { + const result = await invokeRequest(new GramJs.messages.GetRecentStickers({ hash: BigInt(hash) })); if (!result || result instanceof GramJs.messages.RecentStickersNotModified) { return undefined; } return { - hash: result.hash, + hash: String(result.hash), stickers: processStickerResult(result.stickers.slice(0, RECENT_STICKERS_LIMIT)), }; } -export async function fetchFavoriteStickers({ hash }: { hash: number }) { - const result = await invokeRequest(new GramJs.messages.GetFavedStickers({ hash })); +export async function fetchFavoriteStickers({ hash = '0' }: { hash?: string }) { + const result = await invokeRequest(new GramJs.messages.GetFavedStickers({ hash: BigInt(hash) })); if (!result || result instanceof GramJs.messages.FavedStickersNotModified) { return undefined; } return { - hash: result.hash, + hash: String(result.hash), stickers: processStickerResult(result.stickers), }; } -export async function fetchFeaturedStickers({ hash }: { hash: number }) { - const result = await invokeRequest(new GramJs.messages.GetFeaturedStickers({ hash })); +export async function fetchFeaturedStickers({ hash = '0' }: { hash?: string }) { + const result = await invokeRequest(new GramJs.messages.GetFeaturedStickers({ hash: BigInt(hash) })); if (!result || result instanceof GramJs.messages.FeaturedStickersNotModified) { return undefined; } return { - hash: result.hash, + hash: String(result.hash), sets: result.sets.map(buildStickerSetCovered), }; } @@ -93,8 +94,10 @@ export async function faveSticker({ } } -export async function fetchStickers({ stickerSetShortName, stickerSetId, accessHash }: -{ stickerSetShortName?: string; stickerSetId?: string; accessHash: string }) { +export async function fetchStickers( + { stickerSetShortName, stickerSetId, accessHash }: + { stickerSetShortName?: string; stickerSetId?: string; accessHash: string }, +) { const result = await invokeRequest(new GramJs.messages.GetStickerSet({ stickerset: stickerSetId ? buildInputStickerSet(stickerSetId, accessHash) @@ -127,10 +130,10 @@ export async function fetchAnimatedEmojis() { }; } -export async function searchStickers({ query, hash }: { query: string; hash: number }) { +export async function searchStickers({ query, hash = '0' }: { query: string; hash?: string }) { const result = await invokeRequest(new GramJs.messages.SearchStickerSets({ q: query, - hash, + hash: BigInt(hash), })); if (!result || result instanceof GramJs.messages.FoundStickerSetsNotModified) { @@ -138,20 +141,20 @@ export async function searchStickers({ query, hash }: { query: string; hash: num } return { - hash: result.hash, + hash: String(result.hash), sets: result.sets.map(buildStickerSetCovered), }; } -export async function fetchSavedGifs({ hash }: { hash: number }) { - const result = await invokeRequest(new GramJs.messages.GetSavedGifs({ hash })); +export async function fetchSavedGifs({ hash = '0' }: { hash?: string }) { + const result = await invokeRequest(new GramJs.messages.GetSavedGifs({ hash: BigInt(hash) })); if (!result || result instanceof GramJs.messages.SavedGifsNotModified) { return undefined; } return { - hash: result.hash, + hash: String(result.hash), gifs: processGifResult(result.gifs), }; } @@ -233,11 +236,11 @@ export async function searchGifs({ query, offset = '' }: { query: string; offset } export async function fetchStickersForEmoji({ - emoji, hash = 0, -}: { emoji: string; hash?: number }) { + emoji, hash = '0', +}: { emoji: string; hash?: string }) { const result = await invokeRequest(new GramJs.messages.GetStickers({ emoticon: emoji, - hash, + hash: BigInt(hash), })); if (!result || result instanceof GramJs.messages.StickersNotModified) { @@ -246,7 +249,7 @@ export async function fetchStickersForEmoji({ return { stickers: processStickerResult(result.stickers), - hash: result.hash, + hash: String(result.hash), }; } diff --git a/src/api/gramjs/methods/users.ts b/src/api/gramjs/methods/users.ts index 19121ec01..5bc44b6e3 100644 --- a/src/api/gramjs/methods/users.ts +++ b/src/api/gramjs/methods/users.ts @@ -10,7 +10,6 @@ import { invokeRequest } from './client'; import { searchMessagesLocal } from './messages'; import { buildInputEntity, - calculateResultHash, buildInputPeer, buildInputContact, } from '../gramjsBuilders'; @@ -20,6 +19,7 @@ import { buildApiPhoto } from '../apiBuilders/common'; import localDb from '../localDb'; import { addPhotoToLocalDb } from '../helpers'; import { buildApiCountryList } from '../apiBuilders/misc'; +import { buildApiPeerId } from '../apiBuilders/peers'; let onUpdate: OnApiUpdate; @@ -31,7 +31,7 @@ export async function fetchFullUser({ id, accessHash, }: { - id: number; + id: string; accessHash?: string; }) { const input = buildInputEntity(id, accessHash); @@ -73,9 +73,8 @@ export async function fetchCountryList({ langCode = 'en' }: { langCode?: LangCod return buildApiCountryList(countryList.countries); } -export async function fetchTopUsers({ hash = 0 }: { hash?: number }) { +export async function fetchTopUsers() { const topPeers = await invokeRequest(new GramJs.contacts.GetTopPeers({ - hash, correspondents: true, })); if (!(topPeers instanceof GramJs.contacts.TopPeers)) { @@ -86,29 +85,24 @@ export async function fetchTopUsers({ hash = 0 }: { hash?: number }) { const ids = users.map(({ id }) => id); return { - hash: calculateResultHash(ids), ids, users, }; } -export async function fetchContactList({ hash = 0 }: { hash?: number }) { - const result = await invokeRequest(new GramJs.contacts.GetContacts({ hash })); +export async function fetchContactList() { + const result = await invokeRequest(new GramJs.contacts.GetContacts({ hash: BigInt('0') })); if (!result || result instanceof GramJs.contacts.ContactsNotModified) { return undefined; } result.users.forEach((user) => { if (user instanceof GramJs.User) { - localDb.users[user.id] = user; + localDb.users[buildApiPeerId(user.id, 'user')] = user; } }); return { - hash: calculateResultHash([ - result.savedCount, - ...result.contacts.map(({ userId }) => userId), - ]), users: result.users.map(buildApiUser).filter(Boolean as any), chats: result.users.map((user) => buildApiChatFromPreview(user)).filter(Boolean as any), }; @@ -124,7 +118,7 @@ export async function fetchUsers({ users }: { users: ApiUser[] }) { result.forEach((user) => { if (user instanceof GramJs.User) { - localDb.users[user.id] = user; + localDb.users[buildApiPeerId(user.id, 'user')] = user; } }); @@ -156,7 +150,7 @@ export function addContact({ firstName = '', lastName = '', }: { - id: number; + id: string; accessHash?: string; phoneNumber?: string; firstName?: string; @@ -174,7 +168,7 @@ export async function deleteUser({ id, accessHash, }: { - id: number; + id: string; accessHash?: string; }) { const input = buildInputEntity(id, accessHash); diff --git a/src/api/gramjs/updater.ts b/src/api/gramjs/updater.ts index 8485830a5..713eef467 100644 --- a/src/api/gramjs/updater.ts +++ b/src/api/gramjs/updater.ts @@ -14,14 +14,12 @@ import { buildMessageDraft, } from './apiBuilders/messages'; import { - getApiChatIdFromMtpPeer, buildChatMember, buildChatMembers, buildChatTypingStatus, buildAvatarHash, buildApiChatFromPreview, buildApiChatFolder, - getApiChatIdFromInputMtpPeer, } from './apiBuilders/chats'; import { buildApiUser, buildApiUserStatus } from './apiBuilders/users'; import { @@ -35,6 +33,7 @@ import { DEBUG } from '../../config'; import { addMessageToLocalDb, addPhotoToLocalDb, resolveMessageApiChatId } from './helpers'; import { buildApiNotifyException, buildPrivacyKey, buildPrivacyRules } from './apiBuilders/misc'; import { buildApiPhoto } from './apiBuilders/common'; +import { buildApiPeerId, getApiChatIdFromMtpPeer } from './apiBuilders/peers'; type Update = ( (GramJs.TypeUpdate | GramJs.TypeUpdates) & { _entities?: (GramJs.TypeUser | GramJs.TypeChat)[] } @@ -178,7 +177,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) { const photo = buildChatPhotoForLocalDb(action.photo); const avatarHash = buildAvatarHash(photo); - const localDbChatId = Math.abs(resolveMessageApiChatId(update.message)!); + const localDbChatId = resolveMessageApiChatId(update.message)!; if (localDb.chats[localDbChatId]) { localDb.chats[localDbChatId].photo = photo; } @@ -195,7 +194,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) { }); } } else if (action instanceof GramJs.MessageActionChatDeletePhoto) { - const localDbChatId = Math.abs(resolveMessageApiChatId(update.message)!); + const localDbChatId = resolveMessageApiChatId(update.message)!; if (localDb.chats[localDbChatId]) { localDb.chats[localDbChatId].photo = new GramJs.ChatPhotoEmpty(); } @@ -270,10 +269,10 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) { onUpdate({ '@type': 'deleteScheduledMessages', ids: update.messages, - chatId: getApiChatIdFromInputMtpPeer(update.peer), + chatId: getApiChatIdFromMtpPeer(update.peer), }); } else if (update instanceof GramJs.UpdateDeleteChannelMessages) { - const chatId = getApiChatIdFromMtpPeer({ channelId: update.channelId } as GramJs.PeerChannel); + const chatId = buildApiPeerId(update.channelId, 'channel'); const ids = update.messages; const existingIds = ids.filter((id) => localDb.messages[`${chatId}-${id}`]); const missingIds = ids.filter((id) => !localDb.messages[`${chatId}-${id}`]); @@ -339,7 +338,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) { randomId = originRequest.randomId; } - const localMessage = randomId && localDb.localMessages[randomId.toString()]; + const localMessage = randomId && localDb.localMessages[String(randomId)]; if (!localMessage) { throw new Error('Local message not found'); } @@ -400,7 +399,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) { } else if (update instanceof GramJs.UpdateChannelReadMessagesContents) { onUpdate({ '@type': 'updateChannelMessages', - channelId: update.channelId, + channelId: buildApiPeerId(update.channelId, 'channel'), ids: update.messages, messageUpdate: { hasUnreadMention: false, @@ -414,28 +413,28 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) { onUpdate({ '@type': 'updateMessagePoll', - pollId: pollId.toString(), + pollId: String(pollId), pollUpdate: apiPoll, }); } else { const pollResults = buildPollResults(results); onUpdate({ '@type': 'updateMessagePoll', - pollId: pollId.toString(), + pollId: String(pollId), pollUpdate: { results: pollResults }, }); } } else if (update instanceof GramJs.UpdateMessagePollVote) { onUpdate({ '@type': 'updateMessagePollVote', - pollId: update.pollId.toString(), - userId: update.userId, + pollId: String(update.pollId), + userId: buildApiPeerId(update.userId, 'user'), options: update.options.map((option) => String.fromCharCode(...option)), }); } else if (update instanceof GramJs.UpdateChannelMessageViews) { onUpdate({ '@type': 'updateMessage', - chatId: getApiChatIdFromMtpPeer({ channelId: update.channelId } as GramJs.PeerChannel), + chatId: buildApiPeerId(update.channelId, 'channel'), id: update.id, message: { views: update.views }, }); @@ -461,7 +460,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) { } else if (update instanceof GramJs.UpdateReadChannelInbox) { onUpdate({ '@type': 'updateChat', - id: getApiChatIdFromMtpPeer({ channelId: update.channelId } as GramJs.PeerChannel), + id: buildApiPeerId(update.channelId, 'channel'), chat: { lastReadInboxMessageId: update.maxId, unreadCount: update.stillUnreadCount, @@ -470,7 +469,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) { } else if (update instanceof GramJs.UpdateReadChannelOutbox) { onUpdate({ '@type': 'updateChat', - id: getApiChatIdFromMtpPeer({ channelId: update.channelId } as GramJs.PeerChannel), + id: buildApiPeerId(update.channelId, 'channel'), chat: { lastReadOutboxMessageId: update.maxId, }, @@ -525,7 +524,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) { onUpdate({ '@type': 'updateChatMembers', - id: getApiChatIdFromMtpPeer({ chatId: update.participants.chatId } as GramJs.TypePeer), + id: buildApiPeerId(update.participants.chatId, 'chat'), replacedMembers, }); } else if (update instanceof GramJs.UpdateChatParticipantAdd) { @@ -535,25 +534,22 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) { onUpdate({ '@type': 'updateChatMembers', - id: getApiChatIdFromMtpPeer({ chatId: update.chatId } as GramJs.PeerChat), + id: buildApiPeerId(update.chatId, 'chat'), addedMember, }); } else if (update instanceof GramJs.UpdateChatParticipantDelete) { - const { userId: deletedMemberId } = update; - onUpdate({ '@type': 'updateChatMembers', - id: getApiChatIdFromMtpPeer({ chatId: update.chatId } as GramJs.PeerChat), - deletedMemberId, + id: buildApiPeerId(update.chatId, 'chat'), + deletedMemberId: buildApiPeerId(update.userId, 'user'), }); } else if ( update instanceof GramJs.UpdatePinnedMessages || update instanceof GramJs.UpdatePinnedChannelMessages ) { - const peer = update instanceof GramJs.UpdatePinnedMessages - ? update.peer - : { channelId: update.channelId } as GramJs.PeerChannel; - const chatId = getApiChatIdFromMtpPeer(peer); + const chatId = update instanceof GramJs.UpdatePinnedMessages + ? getApiChatIdFromMtpPeer(update.peer) + : buildApiPeerId(update.channelId, 'channel'); onUpdate({ '@type': 'updatePinnedIds', @@ -574,8 +570,8 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) { || update instanceof GramJs.UpdateChatUserTyping ) { const id = update instanceof GramJs.UpdateUserTyping - ? update.userId - : getApiChatIdFromMtpPeer({ chatId: update.chatId } as GramJs.PeerChat); + ? buildApiPeerId(update.userId, 'user') + : buildApiPeerId(update.chatId, 'chat'); onUpdate({ '@type': 'updateChatTypingStatus', @@ -583,7 +579,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) { typingStatus: buildChatTypingStatus(update, serverTimeOffset), }); } else if (update instanceof GramJs.UpdateChannelUserTyping) { - const id = getApiChatIdFromMtpPeer({ channelId: update.channelId } as GramJs.PeerChannel); + const id = buildApiPeerId(update.channelId, 'channel'); onUpdate({ '@type': 'updateChatTypingStatus', @@ -612,11 +608,11 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) { onUpdate({ '@type': chat.isNotJoined ? 'updateChatLeave' : 'updateChatJoin', - id: getApiChatIdFromMtpPeer({ channelId: update.channelId } as GramJs.PeerChannel), + id: buildApiPeerId(update.channelId, 'channel'), }); } } else if (channel instanceof GramJs.ChannelForbidden) { - const chatId = getApiChatIdFromMtpPeer({ channelId: update.channelId } as GramJs.PeerChannel); + const chatId = buildApiPeerId(update.channelId, 'channel'); onUpdate({ '@type': 'updateChat', @@ -635,7 +631,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) { // No corresponding update available at this moment https://core.telegram.org/type/Updates onUpdate({ '@type': 'resetMessages', - id: getApiChatIdFromMtpPeer({ chatId: update.channelId } as GramJs.PeerChat), + id: buildApiPeerId(update.channelId, 'channel'), }); } } else if ( @@ -660,35 +656,35 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) { // Users } else if (update instanceof GramJs.UpdateUserStatus) { - const { userId, status } = update; - onUpdate({ '@type': 'updateUserStatus', - userId, - status: buildApiUserStatus(status), + userId: buildApiPeerId(update.userId, 'user'), + status: buildApiUserStatus(update.status), }); } else if (update instanceof GramJs.UpdateUserName) { - const updatedUser = localDb.users[update.userId]; + const apiUserId = buildApiPeerId(update.userId, 'user'); + const updatedUser = localDb.users[apiUserId]; const user = updatedUser?.mutualContact && !updatedUser.self ? pick(update, ['username']) : pick(update, ['firstName', 'lastName', 'username']); onUpdate({ '@type': 'updateUser', - id: update.userId, + id: apiUserId, user, }); } else if (update instanceof GramJs.UpdateUserPhoto) { const { userId, photo } = update; + const apiUserId = buildApiPeerId(userId, 'user'); const avatarHash = buildAvatarHash(photo); - if (localDb.users[userId]) { - localDb.users[userId].photo = photo; + if (localDb.users[apiUserId]) { + localDb.users[apiUserId].photo = photo; } onUpdate({ '@type': 'updateUser', - id: userId, + id: apiUserId, user: { avatarHash }, }); } else if (update instanceof GramJs.UpdateUserPhone) { @@ -696,7 +692,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) { onUpdate({ '@type': 'updateUser', - id: userId, + id: buildApiPeerId(userId, 'user'), user: { phoneNumber: phone }, }); } else if (update instanceof GramJs.UpdatePeerSettings) { @@ -712,7 +708,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) { .forEach((user) => { onUpdate({ '@type': 'deleteUser', - id: user.id, + id: buildApiPeerId(user.id, 'user'), }); }); diff --git a/src/api/types/bots.ts b/src/api/types/bots.ts index 2ac6cf358..1f92df016 100644 --- a/src/api/types/bots.ts +++ b/src/api/types/bots.ts @@ -40,7 +40,7 @@ export interface ApiBotInlineSwitchPm { } export interface ApiBotCommand { - botId: number; + botId: string; command: string; description: string; } diff --git a/src/api/types/chats.ts b/src/api/types/chats.ts index f662de452..0f1b24ed3 100644 --- a/src/api/types/chats.ts +++ b/src/api/types/chats.ts @@ -8,7 +8,7 @@ type ApiChatType = ( ); export interface ApiChat { - id: number; + id: string; folderId?: number; type: ApiChatType; title?: string; @@ -47,7 +47,7 @@ export interface ApiChat { defaultBannedRights?: ApiChatBannedRights; migratedTo?: { - chatId: number; + chatId: string; accessHash?: string; }; @@ -58,26 +58,11 @@ export interface ApiChat { } export interface ApiTypingStatus { - userId?: number; + userId?: string; action: string; timestamp: number; } -export interface ApiTypeGroupCall { - joinMuted?: true; - canChangeJoinMuted?: true; - joinDateAsc?: true; - scheduleStartSubscribed?: true; - id: number; - participantsCount: number; - params?: any; - title?: string; - streamDcId?: number; - recordStartDate?: number; - scheduleDate?: number; - version: number; -} - export interface ApiChatFullInfo { about?: string; onlineCount?: number; @@ -93,19 +78,19 @@ export interface ApiChatFullInfo { nextSendDate?: number; }; migratedFrom?: { - chatId: number; + chatId: string; maxMessageId?: number; }; - linkedChatId?: number; + linkedChatId?: string; botCommands?: ApiBotCommand[]; } export interface ApiChatMember { - userId: number; - inviterId?: number; + userId: string; + inviterId?: string; joinedDate?: number; - kickedByUserId?: number; - promotedByUserId?: number; + kickedByUserId?: string; + promotedByUserId?: string; bannedRights?: ApiChatBannedRights; adminRights?: ApiChatAdminRights; customTitle?: string; @@ -159,7 +144,7 @@ export interface ApiChatFolder { excludeMuted?: true; excludeRead?: true; excludeArchived?: true; - pinnedChatIds?: number[]; - includedChatIds: number[]; - excludedChatIds: number[]; + pinnedChatIds?: string[]; + includedChatIds: string[]; + excludedChatIds: string[]; } diff --git a/src/api/types/messages.ts b/src/api/types/messages.ts index 74d6520a2..af8c8ac15 100644 --- a/src/api/types/messages.ts +++ b/src/api/types/messages.ts @@ -39,7 +39,6 @@ export interface ApiStickerSet { title: string; hasThumbnail?: boolean; count: number; - hash: number; stickers?: ApiSticker[]; packs?: Record; covers?: ApiSticker[]; @@ -92,7 +91,7 @@ export interface ApiContact { firstName: string; lastName: string; phoneNumber: string; - userId: number; + userId: string; } export interface ApiPollAnswer { @@ -122,7 +121,7 @@ export interface ApiPoll { results: { results?: ApiPollResult[]; totalVoters?: number; - recentVoterIds?: number[]; + recentVoterIds?: string[]; solution?: string; solutionEntities?: ApiMessageEntity[]; }; @@ -149,8 +148,8 @@ export type ApiNewPoll = { export interface ApiAction { text: string; - targetUserIds?: number[]; - targetChatId?: number; + targetUserIds?: string[]; + targetChatId?: string; type: 'historyClear' | 'contactSignUp' | 'chatCreate' | 'other'; photo?: ApiPhoto; amount?: number; @@ -176,8 +175,8 @@ export interface ApiMessageForwardInfo { isChannelPost: boolean; channelPostId?: number; isLinkedChannelPost?: boolean; - fromChatId?: number; - senderUserId?: number; + fromChatId?: string; + senderUserId?: string; fromMessageId?: number; hiddenUserName?: string; adminTitle?: string; @@ -187,7 +186,7 @@ export interface ApiMessageEntity { type: string; offset: number; length: number; - userId?: number; + userId?: string; url?: string; } @@ -218,7 +217,7 @@ export interface ApiFormattedText { export interface ApiMessage { id: number; - chatId: number; + chatId: string; content: { text?: ApiFormattedText; photo?: ApiPhoto; @@ -235,8 +234,8 @@ export interface ApiMessage { }; date: number; isOutgoing: boolean; - senderId?: number; - replyToChatId?: number; + senderId?: string; + replyToChatId?: string; replyToMessageId?: number; replyToTopMessageId?: number; sendingState?: 'messageSendingStatePending' | 'messageSendingStateFailed'; @@ -254,7 +253,7 @@ export interface ApiMessage { keyboardButtons?: ApiKeyboardButtons; keyboardPlaceholder?: string; isKeyboardSingleUse?: boolean; - viaBotId?: number; + viaBotId?: string; threadInfo?: ApiThreadInfo; adminTitle?: string; isScheduled?: boolean; @@ -264,13 +263,13 @@ export interface ApiMessage { export interface ApiThreadInfo { threadId: number; - chatId: number; + chatId: string; topMessageId?: number; - originChannelId?: number; + originChannelId?: string; messagesCount: number; lastMessageId?: number; lastReadInboxMessageId?: number; - recentReplierIds?: number[]; + recentReplierIds?: string[]; } export type ApiMessageOutgoingStatus = 'read' | 'succeeded' | 'pending' | 'failed'; diff --git a/src/api/types/misc.ts b/src/api/types/misc.ts index 7bc61f43b..e137f5849 100644 --- a/src/api/types/misc.ts +++ b/src/api/types/misc.ts @@ -64,7 +64,7 @@ export interface ApiSessionData { } export type ApiNotifyException = { - chatId: number; + chatId: string; isMuted: boolean; isSilent?: boolean; shouldShowPreviews?: boolean; diff --git a/src/api/types/payments.ts b/src/api/types/payments.ts index 4f8d1460e..1ded688e8 100644 --- a/src/api/types/payments.ts +++ b/src/api/types/payments.ts @@ -17,7 +17,7 @@ export interface ApiPaymentSavedInfo { export interface ApiPaymentForm { canSaveCredentials?: boolean; passwordMissing?: boolean; - providerId: number; + providerId: string; nativeProvider?: string; savedInfo: any; invoice: { diff --git a/src/api/types/updates.ts b/src/api/types/updates.ts index b43037e72..7ca4693af 100644 --- a/src/api/types/updates.ts +++ b/src/api/types/updates.ts @@ -65,7 +65,7 @@ export type ApiUpdateCurrentUser = { export type ApiUpdateChat = { '@type': 'updateChat'; - id: number; + id: string; chat: Partial; newProfilePhoto?: ApiPhoto; noTopChatsRequest?: boolean; @@ -73,7 +73,7 @@ export type ApiUpdateChat = { export type ApiUpdateChatJoin = { '@type': 'updateChatJoin'; - id: number; + id: string; }; export type ApiUpdateShowInvite = { @@ -83,50 +83,50 @@ export type ApiUpdateShowInvite = { export type ApiUpdateChatLeave = { '@type': 'updateChatLeave'; - id: number; + id: string; }; export type ApiUpdateChatInbox = { '@type': 'updateChatInbox'; - id: number; + id: string; chat: Partial; }; export type ApiUpdateChatTypingStatus = { '@type': 'updateChatTypingStatus'; - id: number; + id: string; typingStatus: ApiTypingStatus | undefined; }; export type ApiUpdateChatFullInfo = { '@type': 'updateChatFullInfo'; - id: number; + id: string; fullInfo: Partial; }; export type ApiUpdateChatMembers = { '@type': 'updateChatMembers'; - id: number; + id: string; replacedMembers?: ApiChatMember[]; addedMember?: ApiChatMember; - deletedMemberId?: number; + deletedMemberId?: string; }; export type ApiUpdatePinnedChatIds = { '@type': 'updatePinnedChatIds'; - ids: number[]; + ids: string[]; folderId?: number; }; export type ApiUpdateChatListType = { '@type': 'updateChatListType'; - id: number; + id: string; folderId: number; }; export type ApiUpdateChatPinned = { '@type': 'updateChatPinned'; - id: number; + id: string; isPinned: boolean; }; @@ -148,14 +148,14 @@ export type ApiUpdateRecommendedChatFolders = { export type ApiUpdateNewScheduledMessage = { '@type': 'newScheduledMessage'; - chatId: number; + chatId: string; id: number; message: Partial; }; export type ApiUpdateNewMessage = { '@type': 'newMessage'; - chatId: number; + chatId: string; id: number; message: Partial; shouldForceReply?: boolean; @@ -163,28 +163,28 @@ export type ApiUpdateNewMessage = { export type ApiUpdateMessage = { '@type': 'updateMessage'; - chatId: number; + chatId: string; id: number; message: Partial; }; export type ApiUpdateScheduledMessage = { '@type': 'updateScheduledMessage'; - chatId: number; + chatId: string; id: number; message: Partial; }; export type ApiUpdatePinnedMessageIds = { '@type': 'updatePinnedIds'; - chatId: number; + chatId: string; isPinned?: boolean; messageIds: number[]; }; export type ApiUpdateThreadInfo = { '@type': 'updateThreadInfo'; - chatId: number; + chatId: string; threadId: number; threadInfo: Partial; firstMessageId?: number; @@ -192,21 +192,21 @@ export type ApiUpdateThreadInfo = { export type ApiUpdateScheduledMessageSendSucceeded = { '@type': 'updateScheduledMessageSendSucceeded'; - chatId: number; + chatId: string; localId: number; message: ApiMessage; }; export type ApiUpdateMessageSendSucceeded = { '@type': 'updateMessageSendSucceeded'; - chatId: number; + chatId: string; localId: number; message: ApiMessage; }; export type ApiUpdateMessageSendFailed = { '@type': 'updateMessageSendFailed'; - chatId: number; + chatId: string; localId: number; sendingState: { '@type': 'messageSendingStateFailed'; @@ -221,7 +221,7 @@ export type ApiUpdateCommonBoxMessages = { export type ApiUpdateChannelMessages = { '@type': 'updateChannelMessages'; - channelId: number; + channelId: string; ids: number[]; messageUpdate: Partial; }; @@ -235,7 +235,7 @@ export type ApiUpdateMessagePoll = { export type ApiUpdateMessagePollVote = { '@type': 'updateMessagePollVote'; pollId: string; - userId: number; + userId: string; options: string[]; }; @@ -247,34 +247,34 @@ export type ApiUpdateServiceNotification = { export type ApiUpdateDeleteMessages = { '@type': 'deleteMessages'; ids: number[]; - chatId?: number; + chatId?: string; }; export type ApiUpdateDeleteScheduledMessages = { '@type': 'deleteScheduledMessages'; ids: number[]; - chatId?: number; + chatId?: string; }; export type ApiUpdateDeleteHistory = { '@type': 'deleteHistory'; - chatId: number; + chatId: string; }; export type ApiUpdateDeleteProfilePhotos = { '@type': 'deleteProfilePhotos'; ids: string[]; - chatId: number; + chatId: string; }; export type ApiUpdateResetMessages = { '@type': 'resetMessages'; - id: number; + id: string; }; export type ApiUpdateDraftMessage = { '@type': 'draftMessage'; - chatId: number; + chatId: string; formattedText?: ApiFormattedText; date?: number; replyingToId?: number; @@ -282,30 +282,30 @@ export type ApiUpdateDraftMessage = { export type ApiDeleteUser = { '@type': 'deleteUser'; - id: number; + id: string; }; export type ApiUpdateUser = { '@type': 'updateUser'; - id: number; + id: string; user: Partial; }; export type ApiUpdateUserStatus = { '@type': 'updateUserStatus'; - userId: number; + userId: string; status: ApiUserStatus; }; export type ApiUpdateUserFullInfo = { '@type': 'updateUserFullInfo'; - id: number; + id: string; fullInfo: Partial; }; export type ApiUpdateAvatar = { '@type': 'updateAvatar'; - chatId: number; + chatId: string; dataUri: string; }; @@ -357,7 +357,7 @@ export type ApiUpdateTwoFaStateWaitCode = { export type ApiUpdatePeerBlocked = { '@type': 'updatePeerBlocked'; - id: number; + id: string; isBlocked: boolean; }; @@ -366,10 +366,10 @@ export type ApiUpdatePrivacy = { key: 'phoneNumber' | 'lastSeen' | 'profilePhoto' | 'forwards' | 'chatInvite'; rules: { visibility: 'everybody' | 'contacts' | 'nonContacts' | 'nobody'; - allowUserIds: number[]; - allowChatIds: number[]; - blockUserIds: number[]; - blockChatIds: number[]; + allowUserIds: string[]; + allowChatIds: string[]; + blockUserIds: string[]; + blockChatIds: string[]; }; }; diff --git a/src/api/types/users.ts b/src/api/types/users.ts index 4f9c15d3f..a766e8408 100644 --- a/src/api/types/users.ts +++ b/src/api/types/users.ts @@ -2,7 +2,7 @@ import { ApiPhoto } from './messages'; import { ApiBotCommand } from './bots'; export interface ApiUser { - id: number; + id: string; isMin: boolean; isSelf?: true; isVerified?: true; diff --git a/src/components/common/Audio.tsx b/src/components/common/Audio.tsx index 4bcb704ec..b9689b4ea 100644 --- a/src/components/common/Audio.tsx +++ b/src/components/common/Audio.tsx @@ -51,10 +51,10 @@ type OwnProps = { isSelectable?: boolean; isSelected?: boolean; isDownloading: boolean; - onPlay: (messageId: number, chatId: number) => void; + onPlay: (messageId: number, chatId: string) => void; onReadMedia?: () => void; onCancelUpload?: () => void; - onDateClick?: (messageId: number, chatId: number) => void; + onDateClick?: (messageId: number, chatId: string) => void; }; const AVG_VOICE_DURATION = 10; diff --git a/src/components/common/Avatar.tsx b/src/components/common/Avatar.tsx index dfc9a34d8..7e8261902 100644 --- a/src/components/common/Avatar.tsx +++ b/src/components/common/Avatar.tsx @@ -9,7 +9,7 @@ import { getChatTitle, getUserColorKey, getUserFullName, - isChatPrivate, + isUserId, isChatWithRepliesBot, isDeletedUser, isUserOnline, @@ -78,7 +78,7 @@ const Avatar: FC = ({ content = userFullName ? getFirstLetters(userFullName, 2) : undefined; } else if (chat) { const title = getChatTitle(lang, chat); - content = title && getFirstLetters(title, isChatPrivate(chat.id) ? 2 : 1); + content = title && getFirstLetters(title, isUserId(chat.id) ? 2 : 1); } else if (text) { content = getFirstLetters(text, 2); } diff --git a/src/components/common/ChatExtra.tsx b/src/components/common/ChatExtra.tsx index d47a51967..e7458ea63 100644 --- a/src/components/common/ChatExtra.tsx +++ b/src/components/common/ChatExtra.tsx @@ -10,7 +10,7 @@ import { selectChat, selectNotifyExceptions, selectNotifySettings, selectUser, } from '../../modules/selectors'; import { - getChatDescription, getChatLink, getHasAdminRight, isChatChannel, isChatPrivate, isUserRightBanned, selectIsChatMuted, + getChatDescription, getChatLink, getHasAdminRight, isChatChannel, isUserId, isUserRightBanned, selectIsChatMuted, } from '../../modules/helpers'; import renderText from './helpers/renderText'; import { pick } from '../../util/iteratees'; @@ -22,7 +22,7 @@ import ListItem from '../ui/ListItem'; import Switcher from '../ui/Switcher'; type OwnProps = { - chatOrUserId: number; + chatOrUserId: string; forceShowSelf?: boolean; }; @@ -140,7 +140,7 @@ export default memo(withGlobal( const { lastSyncTime, countryList: { phoneCodes: phoneCodeList } } = global; const chat = chatOrUserId ? selectChat(global, chatOrUserId) : undefined; - const user = isChatPrivate(chatOrUserId) ? selectUser(global, chatOrUserId) : undefined; + const user = isUserId(chatOrUserId) ? selectUser(global, chatOrUserId) : undefined; const isMuted = chat && selectIsChatMuted(chat, selectNotifySettings(global), selectNotifyExceptions(global)); const canInviteUsers = chat && !user && ( diff --git a/src/components/common/ChatLink.tsx b/src/components/common/ChatLink.tsx index 06f8afab3..d8ce8b04a 100644 --- a/src/components/common/ChatLink.tsx +++ b/src/components/common/ChatLink.tsx @@ -10,7 +10,7 @@ import Link from '../ui/Link'; type OwnProps = { className?: string; - chatId?: number; + chatId?: string; children: any; }; diff --git a/src/components/common/ChatOrUserPicker.tsx b/src/components/common/ChatOrUserPicker.tsx index eea951b9f..c77ff4274 100644 --- a/src/components/common/ChatOrUserPicker.tsx +++ b/src/components/common/ChatOrUserPicker.tsx @@ -7,7 +7,7 @@ import useInfiniteScroll from '../../hooks/useInfiniteScroll'; import useLang from '../../hooks/useLang'; import useKeyboardListNavigation from '../../hooks/useKeyboardListNavigation'; import useInputFocusOnOpen from '../../hooks/useInputFocusOnOpen'; -import { isChatPrivate } from '../../modules/helpers'; +import { isUserId } from '../../modules/helpers'; import Loading from '../ui/Loading'; import Modal from '../ui/Modal'; @@ -21,15 +21,15 @@ import PrivateChatInfo from './PrivateChatInfo'; import './ChatOrUserPicker.scss'; export type OwnProps = { - currentUserId?: number; - chatOrUserIds: number[]; + currentUserId?: string; + chatOrUserIds: string[]; isOpen: boolean; filterRef: RefObject; filterPlaceholder: string; filter: string; onFilterChange: (filter: string) => void; loadMore: NoneToVoidFunction; - onSelectChatOrUser: (chatOrUserId: number) => void; + onSelectChatOrUser: (chatOrUserId: string) => void; onClose: NoneToVoidFunction; }; @@ -104,7 +104,7 @@ const ChatOrUserPicker: FC = ({ className="chat-item-clickable force-rounded-corners" onClick={() => onSelectChatOrUser(id)} > - {isChatPrivate(id) ? ( + {isUserId(id) ? ( ) : ( diff --git a/src/components/common/DeleteChatModal.tsx b/src/components/common/DeleteChatModal.tsx index a0a84275c..622106099 100644 --- a/src/components/common/DeleteChatModal.tsx +++ b/src/components/common/DeleteChatModal.tsx @@ -6,7 +6,7 @@ import { GlobalActions } from '../../global/types'; import { selectIsChatWithSelf, selectUser } from '../../modules/selectors'; import { - isChatPrivate, + isUserId, isUserBot, getUserFirstOrLastName, getPrivateChatUserId, @@ -39,7 +39,7 @@ type StateProps = { isPrivateChat: boolean; isBasicGroup: boolean; isSuperGroup: boolean; - currentUserId: number | undefined; + currentUserId: string | undefined; canDeleteForAll?: boolean; contactName?: string; }; @@ -196,7 +196,7 @@ const DeleteChatModal: FC = ({ export default memo(withGlobal( (global, { chat }): StateProps => { - const isPrivateChat = isChatPrivate(chat.id); + const isPrivateChat = isUserId(chat.id); const isChatWithSelf = selectIsChatWithSelf(global, chat.id); const user = isPrivateChat && selectUser(global, getPrivateChatUserId(chat)!); const isBot = user && isUserBot(user) && !chat.isSupport; diff --git a/src/components/common/DeleteMessageModal.tsx b/src/components/common/DeleteMessageModal.tsx index 8e9fac1ea..aa6bc396f 100644 --- a/src/components/common/DeleteMessageModal.tsx +++ b/src/components/common/DeleteMessageModal.tsx @@ -13,7 +13,7 @@ import { selectUser, } from '../../modules/selectors'; import { - isChatPrivate, + isUserId, getUserFirstOrLastName, getPrivateChatUserId, isChatBasicGroup, @@ -115,7 +115,7 @@ export default memo(withGlobal( const { threadId } = selectCurrentMessageList(global) || {}; const { canDeleteForAll } = (threadId && selectAllowedMessageActions(global, message, threadId)) || {}; const chat = selectChat(global, message.chatId); - const contactName = chat && isChatPrivate(chat.id) + const contactName = chat && isUserId(chat.id) ? getUserFirstOrLastName(selectUser(global, getPrivateChatUserId(chat)!)) : undefined; diff --git a/src/components/common/Document.tsx b/src/components/common/Document.tsx index 75c736b10..77c1bbc81 100644 --- a/src/components/common/Document.tsx +++ b/src/components/common/Document.tsx @@ -32,7 +32,7 @@ type OwnProps = { isDownloading: boolean; onCancelUpload?: () => void; onMediaClick?: () => void; - onDateClick?: (messageId: number, chatId: number) => void; + onDateClick?: (messageId: number, chatId: string) => void; }; const Document: FC = ({ diff --git a/src/components/common/GroupChatInfo.tsx b/src/components/common/GroupChatInfo.tsx index 7c623e340..fde76670b 100644 --- a/src/components/common/GroupChatInfo.tsx +++ b/src/components/common/GroupChatInfo.tsx @@ -23,7 +23,7 @@ import VerifiedIcon from './VerifiedIcon'; import TypingStatus from './TypingStatus'; type OwnProps = { - chatId: number; + chatId: string; typingStatus?: ApiTypingStatus; avatarSize?: 'small' | 'medium' | 'large' | 'jumbo'; withMediaViewer?: boolean; diff --git a/src/components/common/Media.tsx b/src/components/common/Media.tsx index 20f56289d..94857cb4b 100644 --- a/src/components/common/Media.tsx +++ b/src/components/common/Media.tsx @@ -16,7 +16,7 @@ import './Media.scss'; type OwnProps = { message: ApiMessage; idPrefix?: string; - onClick?: (messageId: number, chatId: number) => void; + onClick?: (messageId: number, chatId: string) => void; }; const Media: FC = ({ message, idPrefix = 'shared-media', onClick }) => { diff --git a/src/components/common/Picker.tsx b/src/components/common/Picker.tsx index 2d6bcad8d..91c304ddf 100644 --- a/src/components/common/Picker.tsx +++ b/src/components/common/Picker.tsx @@ -2,7 +2,7 @@ import React, { FC, useCallback, useRef, useEffect, memo, } from '../../lib/teact/teact'; -import { isChatPrivate } from '../../modules/helpers'; +import { isUserId } from '../../modules/helpers'; import InfiniteScroll from '../ui/InfiniteScroll'; import Checkbox from '../ui/Checkbox'; @@ -19,15 +19,15 @@ import Loading from '../ui/Loading'; import './Picker.scss'; type OwnProps = { - itemIds: number[]; - selectedIds: number[]; + itemIds: string[]; + selectedIds: string[]; filterValue?: string; filterPlaceholder?: string; notFoundText?: string; searchInputId?: string; isLoading?: boolean; noScrollRestore?: boolean; - onSelectedIdsChange: (ids: number[]) => void; + onSelectedIdsChange: (ids: string[]) => void; onFilterChange: (value: string) => void; onLoadMore?: () => void; }; @@ -63,7 +63,7 @@ const Picker: FC = ({ }, FOCUS_DELAY_MS); }, []); - const handleItemClick = useCallback((id: number) => { + const handleItemClick = useCallback((id: string) => { const newSelectedIds = [...selectedIds]; if (newSelectedIds.includes(id)) { newSelectedIds.splice(newSelectedIds.indexOf(id), 1); @@ -119,7 +119,7 @@ const Picker: FC = ({ ripple > - {isChatPrivate(id) ? ( + {isUserId(id) ? ( ) : ( diff --git a/src/components/common/PickerSelectedItem.tsx b/src/components/common/PickerSelectedItem.tsx index 3b73b6fb6..c2f2ee2e4 100644 --- a/src/components/common/PickerSelectedItem.tsx +++ b/src/components/common/PickerSelectedItem.tsx @@ -4,7 +4,7 @@ import { withGlobal } from '../../lib/teact/teactn'; import { ApiChat, ApiUser } from '../../api/types'; import { selectChat, selectUser } from '../../modules/selectors'; -import { getChatTitle, getUserFirstOrLastName, isChatPrivate } from '../../modules/helpers'; +import { getChatTitle, getUserFirstOrLastName, isUserId } from '../../modules/helpers'; import renderText from './helpers/renderText'; import buildClassName from '../../util/buildClassName'; import useLang from '../../hooks/useLang'; @@ -14,7 +14,7 @@ import Avatar from './Avatar'; import './PickerSelectedItem.scss'; type OwnProps = { - chatOrUserId?: number; + chatOrUserId?: string; icon?: string; title?: string; isMinimized?: boolean; @@ -106,7 +106,7 @@ export default memo(withGlobal( } const chat = chatOrUserId ? selectChat(global, chatOrUserId) : undefined; - const user = isChatPrivate(chatOrUserId) ? selectUser(global, chatOrUserId) : undefined; + const user = isUserId(chatOrUserId) ? selectUser(global, chatOrUserId) : undefined; return { chat, diff --git a/src/components/common/PinMessageModal.tsx b/src/components/common/PinMessageModal.tsx index f99a91bf4..ca28b6eae 100644 --- a/src/components/common/PinMessageModal.tsx +++ b/src/components/common/PinMessageModal.tsx @@ -5,7 +5,7 @@ import { GlobalActions } from '../../global/types'; import { selectChat, selectIsChatWithSelf, selectUser } from '../../modules/selectors'; import { - isChatPrivate, + isUserId, getUserFirstOrLastName, getPrivateChatUserId, isChatBasicGroup, @@ -21,7 +21,7 @@ import Button from '../ui/Button'; export type OwnProps = { isOpen: boolean; - chatId: number; + chatId: string; messageId: number; onClose: () => void; }; @@ -103,14 +103,14 @@ const PinMessageModal: FC = ({ export default memo(withGlobal( (global, { chatId }): StateProps => { - const isPrivateChat = isChatPrivate(chatId); + const isPrivateChat = isUserId(chatId); const isChatWithSelf = selectIsChatWithSelf(global, chatId); const chat = selectChat(global, chatId); const isChannel = !!chat && isChatChannel(chat); const isGroup = !!chat && isChatBasicGroup(chat); const isSuperGroup = !!chat && isChatSuperGroup(chat); const canPinForAll = (isPrivateChat && !isChatWithSelf) || isSuperGroup || isGroup; - const contactName = chat && isChatPrivate(chat.id) + const contactName = chat && isUserId(chat.id) ? getUserFirstOrLastName(selectUser(global, getPrivateChatUserId(chat)!)) : undefined; diff --git a/src/components/common/PrivateChatInfo.tsx b/src/components/common/PrivateChatInfo.tsx index 9c6527f72..d15a7d39d 100644 --- a/src/components/common/PrivateChatInfo.tsx +++ b/src/components/common/PrivateChatInfo.tsx @@ -19,7 +19,7 @@ import VerifiedIcon from './VerifiedIcon'; import TypingStatus from './TypingStatus'; type OwnProps = { - userId: number; + userId: string; typingStatus?: ApiTypingStatus; avatarSize?: 'tiny' | 'small' | 'medium' | 'large' | 'jumbo'; forceShowSelf?: boolean; diff --git a/src/components/common/ProfileInfo.tsx b/src/components/common/ProfileInfo.tsx index ea0e31cdc..f90a3e463 100644 --- a/src/components/common/ProfileInfo.tsx +++ b/src/components/common/ProfileInfo.tsx @@ -26,7 +26,7 @@ import Transition from '../ui/Transition'; import './ProfileInfo.scss'; type OwnProps = { - userId: number; + userId: string; forceShowSelf?: boolean; }; diff --git a/src/components/common/ProfilePhoto.tsx b/src/components/common/ProfilePhoto.tsx index d685f15f0..5ab947a6b 100644 --- a/src/components/common/ProfilePhoto.tsx +++ b/src/components/common/ProfilePhoto.tsx @@ -9,7 +9,7 @@ import { getChatTitle, getUserColorKey, getUserFullName, - isChatPrivate, + isUserId, isChatWithRepliesBot, isDeletedUser, } from '../../modules/helpers'; @@ -87,7 +87,7 @@ const ProfilePhoto: FC = ({ content = userFullName ? getFirstLetters(userFullName, 2) : undefined; } else if (!imageSrc && chat) { const title = getChatTitle(lang, chat); - content = title && getFirstLetters(title, isChatPrivate(chat.id) ? 2 : 1); + content = title && getFirstLetters(title, isUserId(chat.id) ? 2 : 1); } else { content = (
diff --git a/src/components/common/UnpinAllMessagesModal.tsx b/src/components/common/UnpinAllMessagesModal.tsx index cc983fca7..b7e553ebe 100644 --- a/src/components/common/UnpinAllMessagesModal.tsx +++ b/src/components/common/UnpinAllMessagesModal.tsx @@ -7,7 +7,7 @@ import Button from '../ui/Button'; export type OwnProps = { isOpen: boolean; - chatId?: number; + chatId?: string; pinnedMessagesCount?: number; onClose: () => void; onUnpin: () => void; diff --git a/src/components/common/WebLink.tsx b/src/components/common/WebLink.tsx index 0b88dde13..99ca19340 100644 --- a/src/components/common/WebLink.tsx +++ b/src/components/common/WebLink.tsx @@ -20,7 +20,7 @@ const MAX_TEXT_LENGTH = 170; // symbols type OwnProps = { message: ApiMessage; senderTitle?: string; - onMessageClick: (messageId: number, chatId: number) => void; + onMessageClick: (messageId: number, chatId: string) => void; }; const WebLink: FC = ({ diff --git a/src/components/common/helpers/renderActionMessageText.tsx b/src/components/common/helpers/renderActionMessageText.tsx index 07c35c8fb..c02adcca0 100644 --- a/src/components/common/helpers/renderActionMessageText.tsx +++ b/src/components/common/helpers/renderActionMessageText.tsx @@ -7,7 +7,7 @@ import { getMessageContent, getMessageSummaryText, getUserFullName, - isChatPrivate, + isUserId, } from '../../../modules/helpers'; import trimText from '../../../util/trimText'; import { formatCurrency } from '../../../util/formatCurrency'; @@ -32,7 +32,7 @@ export function renderActionMessageText( actionOrigin?: ApiUser | ApiChat, targetUsers?: ApiUser[], targetMessage?: ApiMessage, - targetChatId?: number, + targetChatId?: string, options: ActionMessageTextOptions = {}, ) { if (!message.content.action) { @@ -167,7 +167,7 @@ function renderMessageContent(lang: LangFn, message: ApiMessage, options: Action } function renderOriginContent(lang: LangFn, origin: ApiUser | ApiChat, asPlain?: boolean) { - return isChatPrivate(origin.id) + return isUserId(origin.id) ? renderUserContent(origin as ApiUser, asPlain) : renderChatContent(lang, origin as ApiChat, asPlain); } @@ -192,7 +192,7 @@ function renderChatContent(lang: LangFn, chat: ApiChat, asPlain?: boolean): stri return {chat && renderText(text!)}; } -function renderMigratedContent(chatId: number, asPlain?: boolean): string | TextPart | undefined { +function renderMigratedContent(chatId: string, asPlain?: boolean): string | TextPart | undefined { const text = 'another chat'; if (asPlain) { diff --git a/src/components/left/ChatFolderModal.tsx b/src/components/left/ChatFolderModal.tsx index d0564802f..0fa7b9fc9 100644 --- a/src/components/left/ChatFolderModal.tsx +++ b/src/components/left/ChatFolderModal.tsx @@ -15,7 +15,7 @@ import CheckboxGroup from '../ui/CheckboxGroup'; export type OwnProps = { isOpen: boolean; - chatId: number; + chatId: string; onClose: () => void; onCloseAnimationEnd?: () => void; }; @@ -63,8 +63,8 @@ const ChatFolderModal: FC = ({ }, [folderOrderedIds, foldersById]); const handleSubmit = useCallback(() => { - const idsToRemove = initialSelectedFolderIds.filter((id) => !selectedFolderIds.includes(id)).map(Number); - const idsToAdd = selectedFolderIds.filter((id) => !initialSelectedFolderIds.includes(id)).map(Number); + const idsToRemove = initialSelectedFolderIds.filter((id) => !selectedFolderIds.includes(id)); + const idsToAdd = selectedFolderIds.filter((id) => !initialSelectedFolderIds.includes(id)); editChatFolders({ chatId, idsToRemove, idsToAdd }); onClose(); diff --git a/src/components/left/main/Chat.tsx b/src/components/left/main/Chat.tsx index 890d3d196..f4de20aa7 100644 --- a/src/components/left/main/Chat.tsx +++ b/src/components/left/main/Chat.tsx @@ -14,7 +14,7 @@ import { ANIMATION_END_DELAY } from '../../../config'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment'; import { getChatTitle, - isChatPrivate, + isUserId, isActionMessage, getPrivateChatUserId, getMessageAction, @@ -56,7 +56,7 @@ import './Chat.scss'; type OwnProps = { style?: string; - chatId: number; + chatId: string; folderId?: number; orderDiff: number; animationType: ChatAnimationTypes; @@ -67,10 +67,10 @@ type StateProps = { chat?: ApiChat; isMuted?: boolean; privateChatUser?: ApiUser; - actionTargetUserIds?: number[]; - usersById?: Record; + actionTargetUserIds?: string[]; + usersById?: Record; actionTargetMessage?: ApiMessage; - actionTargetChatId?: number; + actionTargetChatId?: string; lastMessageSender?: ApiUser; lastMessageOutgoingStatus?: ApiMessageOutgoingStatus; draft?: ApiFormattedText; @@ -264,7 +264,7 @@ const Chat: FC = ({ const className = buildClassName( 'Chat chat-item-clickable', - isChatPrivate(chatId) ? 'private' : 'group', + isUserId(chatId) ? 'private' : 'group', isSelected && 'selected', ); diff --git a/src/components/left/main/ChatFolders.tsx b/src/components/left/main/ChatFolders.tsx index 989b5eb40..250595ac1 100644 --- a/src/components/left/main/ChatFolders.tsx +++ b/src/components/left/main/ChatFolders.tsx @@ -30,14 +30,14 @@ type OwnProps = { }; type StateProps = { - chatsById: Record; - usersById: Record; + chatsById: Record; + usersById: Record; chatFoldersById: Record; notifySettings: NotifySettings; notifyExceptions?: Record; orderedFolderIds?: number[]; activeChatFolder: number; - currentUserId?: number; + currentUserId?: string; lastSyncTime?: number; shouldSkipHistoryAnimations?: boolean; }; @@ -86,7 +86,7 @@ const ChatFolders: FC = ({ return undefined; } - const chatIds = Object.keys(chatsById).map(Number); + const chatIds = Object.keys(chatsById); const counters = displayedFolders.map((folder) => { const { unreadDialogsCount, hasActiveDialogs, diff --git a/src/components/left/main/ChatList.tsx b/src/components/left/main/ChatList.tsx index 7f153aef8..f91a0c91e 100644 --- a/src/components/left/main/ChatList.tsx +++ b/src/components/left/main/ChatList.tsx @@ -35,11 +35,11 @@ type OwnProps = { }; type StateProps = { - chatsById: Record; - usersById: Record; + chatsById: Record; + usersById: Record; chatFolder?: ApiChatFolder; - listIds?: number[]; - orderedPinnedIds?: number[]; + listIds?: string[]; + orderedPinnedIds?: string[]; lastSyncTime?: number; notifySettings: NotifySettings; notifyExceptions?: Record; diff --git a/src/components/left/main/ContactList.tsx b/src/components/left/main/ContactList.tsx index a427eabe9..f98abc588 100644 --- a/src/components/left/main/ContactList.tsx +++ b/src/components/left/main/ContactList.tsx @@ -26,8 +26,8 @@ export type OwnProps = { }; type StateProps = { - usersById: Record; - contactIds?: number[]; + usersById: Record; + contactIds?: string[]; serverTimeOffset: number; }; @@ -49,12 +49,9 @@ const ContactList: FC = ({ useHistoryBack(isActive, onReset); - const handleClick = useCallback( - (id: number) => { - openChat({ id, shouldReplaceHistory: true }); - }, - [openChat], - ); + const handleClick = useCallback((id: string) => { + openChat({ id, shouldReplaceHistory: true }); + }, [openChat]); const listIds = useMemo(() => { if (!contactIds) { diff --git a/src/components/left/main/LeftMainHeader.tsx b/src/components/left/main/LeftMainHeader.tsx index a12a1dbcb..c760272b1 100644 --- a/src/components/left/main/LeftMainHeader.tsx +++ b/src/components/left/main/LeftMainHeader.tsx @@ -43,12 +43,12 @@ type OwnProps = { type StateProps = { searchQuery?: string; isLoading: boolean; - currentUserId?: number; - globalSearchChatId?: number; + currentUserId?: string; + globalSearchChatId?: string; searchDate?: number; theme: ISettings['theme']; animationLevel: 0 | 1 | 2; - chatsById?: Record; + chatsById?: Record; }; type DispatchProps = Pick) { - const movesUp = useCallback((id: number) => orderDiffById[id] < 0, [orderDiffById]); - const movesDown = useCallback((id: number) => orderDiffById[id] > 0, [orderDiffById]); +export function useChatAnimationType(orderDiffById: Record) { + const movesUp = useCallback((id: string) => orderDiffById[id] < 0, [orderDiffById]); + const movesDown = useCallback((id: string) => orderDiffById[id] > 0, [orderDiffById]); - const orderDiffIds = Object.keys(orderDiffById).map(Number); + const orderDiffIds = Object.keys(orderDiffById); const numberOfUp = orderDiffIds.filter(movesUp).length; const numberOfDown = orderDiffIds.filter(movesDown).length; - return useCallback((chatId: number): ChatAnimationTypes => { + return useCallback((chatId: string): ChatAnimationTypes => { const orderDiff = orderDiffById[chatId]; if (orderDiff === 0) { diff --git a/src/components/left/newChat/NewChat.tsx b/src/components/left/newChat/NewChat.tsx index f1b8e88e5..d4604771b 100644 --- a/src/components/left/newChat/NewChat.tsx +++ b/src/components/left/newChat/NewChat.tsx @@ -29,7 +29,7 @@ const NewChat: FC = ({ onContentChange, onReset, }) => { - const [newChatMemberIds, setNewChatMemberIds] = useState([]); + const [newChatMemberIds, setNewChatMemberIds] = useState([]); const handleNextStep = useCallback(() => { onContentChange(isChannel ? LeftColumnContent.NewChannelStep2 : LeftColumnContent.NewGroupStep2); diff --git a/src/components/left/newChat/NewChatStep1.tsx b/src/components/left/newChat/NewChatStep1.tsx index 9956ccb10..51275addb 100644 --- a/src/components/left/newChat/NewChatStep1.tsx +++ b/src/components/left/newChat/NewChatStep1.tsx @@ -20,21 +20,21 @@ import Button from '../../ui/Button'; export type OwnProps = { isChannel?: boolean; isActive: boolean; - selectedMemberIds: number[]; - onSelectedMemberIdsChange: (ids: number[]) => void; + selectedMemberIds: string[]; + onSelectedMemberIdsChange: (ids: string[]) => void; onNextStep: () => void; onReset: () => void; }; type StateProps = { - currentUserId?: number; - usersById: Record; - chatsById: Record; - localContactIds?: number[]; + currentUserId?: string; + usersById: Record; + chatsById: Record; + localContactIds?: string[]; searchQuery?: string; isSearching?: boolean; - localUserIds?: number[]; - globalUserIds?: number[]; + localUserIds?: string[]; + globalUserIds?: string[]; }; type DispatchProps = Pick; diff --git a/src/components/left/newChat/NewChatStep2.tsx b/src/components/left/newChat/NewChatStep2.tsx index 71db28680..92e7b02f3 100644 --- a/src/components/left/newChat/NewChatStep2.tsx +++ b/src/components/left/newChat/NewChatStep2.tsx @@ -21,7 +21,7 @@ import PrivateChatInfo from '../../common/PrivateChatInfo'; export type OwnProps = { isChannel?: boolean; isActive: boolean; - memberIds: number[]; + memberIds: string[]; onReset: (forceReturnToChatList?: boolean) => void; }; diff --git a/src/components/left/search/AudioResults.tsx b/src/components/left/search/AudioResults.tsx index 082665c4d..c903eb7e8 100644 --- a/src/components/left/search/AudioResults.tsx +++ b/src/components/left/search/AudioResults.tsx @@ -66,17 +66,17 @@ const AudioResults: FC = ({ } return foundIds.map((id) => { - const [chatId, messageId] = id.split('_').map(Number); + const [chatId, messageId] = id.split('_'); - return globalMessagesByChatId[chatId]?.byId[messageId]; + return globalMessagesByChatId[chatId]?.byId[Number(messageId)]; }).filter(Boolean); }, [globalMessagesByChatId, foundIds]); - const handleMessageFocus = useCallback((messageId: number, chatId: number) => { + const handleMessageFocus = useCallback((messageId: number, chatId: string) => { focusMessage({ chatId, messageId }); }, [focusMessage]); - const handlePlayAudio = useCallback((messageId: number, chatId: number) => { + const handlePlayAudio = useCallback((messageId: number, chatId: string) => { openAudioPlayer({ chatId, messageId, origin: AudioOrigin.Search }); }, [openAudioPlayer]); diff --git a/src/components/left/search/ChatMessage.tsx b/src/components/left/search/ChatMessage.tsx index 3e5eb9274..a982bedae 100644 --- a/src/components/left/search/ChatMessage.tsx +++ b/src/components/left/search/ChatMessage.tsx @@ -36,7 +36,7 @@ import './ChatMessage.scss'; type OwnProps = { searchQuery?: string; message: ApiMessage; - chatId: number; + chatId: string; }; type StateProps = { diff --git a/src/components/left/search/ChatMessageResults.tsx b/src/components/left/search/ChatMessageResults.tsx index a163f1dd9..ee9bd0c41 100644 --- a/src/components/left/search/ChatMessageResults.tsx +++ b/src/components/left/search/ChatMessageResults.tsx @@ -26,10 +26,10 @@ export type OwnProps = { }; type StateProps = { - currentUserId?: number; + currentUserId?: string; foundIds?: string[]; - globalMessagesByChatId?: Record }>; - chatsById: Record; + globalMessagesByChatId?: Record }>; + chatsById: Record; fetchingStatus?: { chats?: boolean; messages?: boolean }; lastSyncTime?: number; }; @@ -70,9 +70,9 @@ const ChatMessageResults: FC = ({ return foundIds .map((id) => { - const [chatId, messageId] = id.split('_').map(Number); + const [chatId, messageId] = id.split('_'); - return globalMessagesByChatId?.[chatId]?.byId[messageId]; + return globalMessagesByChatId?.[chatId]?.byId[Number(messageId)]; }) .filter(Boolean as any) .sort((a, b) => b.date - a.date); diff --git a/src/components/left/search/ChatResults.tsx b/src/components/left/search/ChatResults.tsx index 19ddf171e..d2820e7c2 100644 --- a/src/components/left/search/ChatResults.tsx +++ b/src/components/left/search/ChatResults.tsx @@ -33,16 +33,16 @@ export type OwnProps = { }; type StateProps = { - currentUserId?: number; - localContactIds?: number[]; - localChatIds?: number[]; - localUserIds?: number[]; - globalChatIds?: number[]; - globalUserIds?: number[]; + currentUserId?: string; + localContactIds?: string[]; + localChatIds?: string[]; + localUserIds?: string[]; + globalChatIds?: string[]; + globalUserIds?: string[]; foundIds?: string[]; - globalMessagesByChatId?: Record }>; - chatsById: Record; - usersById: Record; + globalMessagesByChatId?: Record }>; + chatsById: Record; + usersById: Record; fetchingStatus?: { chats?: boolean; messages?: boolean }; lastSyncTime?: number; }; @@ -79,7 +79,7 @@ const ChatResults: FC = ({ }, [lastSyncTime, searchMessagesGlobal, searchQuery]); const handleChatClick = useCallback( - (id: number) => { + (id: string) => { openChat({ id, shouldReplaceHistory: true }); if (id !== currentUserId) { @@ -93,7 +93,7 @@ const ChatResults: FC = ({ [currentUserId, openChat, addRecentlyFoundChatId, onReset], ); - const handlePickerItemClick = useCallback((id: number) => { + const handlePickerItemClick = useCallback((id: string) => { setGlobalSearchChatId({ id }); }, [setGlobalSearchChatId]); @@ -142,9 +142,9 @@ const ChatResults: FC = ({ return foundIds .map((id) => { - const [chatId, messageId] = id.split('_').map(Number); + const [chatId, messageId] = id.split('_'); - return globalMessagesByChatId?.[chatId]?.byId[messageId]; + return globalMessagesByChatId?.[chatId]?.byId[Number(messageId)]; }) .filter(Boolean as any) .sort((a, b) => b.date - a.date); diff --git a/src/components/left/search/FileResults.tsx b/src/components/left/search/FileResults.tsx index 7cf9429d0..e77a7f5d3 100644 --- a/src/components/left/search/FileResults.tsx +++ b/src/components/left/search/FileResults.tsx @@ -64,14 +64,14 @@ const FileResults: FC = ({ } return foundIds.map((id) => { - const [chatId, messageId] = id.split('_').map(Number); - const message = globalMessagesByChatId[chatId]?.byId[messageId]; + const [chatId, messageId] = id.split('_'); + const message = globalMessagesByChatId[chatId]?.byId[Number(messageId)]; return message && getMessageDocument(message) ? message : undefined; }).filter(Boolean) as ApiMessage[]; }, [globalMessagesByChatId, foundIds]); - const handleMessageFocus = useCallback((messageId: number, chatId: number) => { + const handleMessageFocus = useCallback((messageId: number, chatId: string) => { focusMessage({ chatId, messageId }); }, [focusMessage]); diff --git a/src/components/left/search/LeftSearch.tsx b/src/components/left/search/LeftSearch.tsx index 00ca71cd1..7523c0271 100644 --- a/src/components/left/search/LeftSearch.tsx +++ b/src/components/left/search/LeftSearch.tsx @@ -32,7 +32,7 @@ export type OwnProps = { type StateProps = { currentContent?: GlobalSearchContent; - chatId?: number; + chatId?: string; }; type DispatchProps = Pick; diff --git a/src/components/left/search/LeftSearchResultChat.tsx b/src/components/left/search/LeftSearchResultChat.tsx index 27d353bc4..232f5df5b 100644 --- a/src/components/left/search/LeftSearchResultChat.tsx +++ b/src/components/left/search/LeftSearchResultChat.tsx @@ -7,7 +7,7 @@ import { ApiChat, ApiUser } from '../../../api/types'; import useChatContextActions from '../../../hooks/useChatContextActions'; import useFlag from '../../../hooks/useFlag'; -import { isChatPrivate, getPrivateChatUserId, selectIsChatMuted } from '../../../modules/helpers'; +import { isUserId, getPrivateChatUserId, selectIsChatMuted } from '../../../modules/helpers'; import { selectChat, selectUser, selectIsChatPinned, selectNotifySettings, selectNotifyExceptions, } from '../../../modules/selectors'; @@ -20,9 +20,9 @@ import ListItem from '../../ui/ListItem'; import ChatFolderModal from '../ChatFolderModal.async'; type OwnProps = { - chatId: number; + chatId: string; withUsername?: boolean; - onClick: (id: number) => void; + onClick: (id: string) => void; }; type StateProps = { @@ -70,7 +70,7 @@ const LeftSearchResultChat: FC = ({ contextActions={contextActions} buttonRef={buttonRef} > - {isChatPrivate(chatId) ? ( + {isUserId(chatId) ? ( ) : ( diff --git a/src/components/left/search/LinkResults.tsx b/src/components/left/search/LinkResults.tsx index 0ef35f2e8..258d5fcd7 100644 --- a/src/components/left/search/LinkResults.tsx +++ b/src/components/left/search/LinkResults.tsx @@ -61,13 +61,13 @@ const LinkResults: FC = ({ } return foundIds.map((id) => { - const [chatId, messageId] = id.split('_').map(Number); + const [chatId, messageId] = id.split('_'); - return globalMessagesByChatId[chatId]?.byId[messageId]; + return globalMessagesByChatId[chatId]?.byId[Number(messageId)]; }).filter(Boolean); }, [globalMessagesByChatId, foundIds]); - const handleMessageFocus = useCallback((messageId: number, chatId: number) => { + const handleMessageFocus = useCallback((messageId: number, chatId: string) => { focusMessage({ chatId, messageId }); }, [focusMessage]); diff --git a/src/components/left/search/MediaResults.tsx b/src/components/left/search/MediaResults.tsx index 8af94c62d..2862ef807 100644 --- a/src/components/left/search/MediaResults.tsx +++ b/src/components/left/search/MediaResults.tsx @@ -60,13 +60,13 @@ const MediaResults: FC = ({ } return foundIds.map((id) => { - const [chatId, messageId] = id.split('_').map(Number); + const [chatId, messageId] = id.split('_'); - return globalMessagesByChatId[chatId]?.byId[messageId]; + return globalMessagesByChatId[chatId]?.byId[Number(messageId)]; }).filter(Boolean); }, [globalMessagesByChatId, foundIds]); - const handleSelectMedia = useCallback((messageId: number, chatId: number) => { + const handleSelectMedia = useCallback((messageId: number, chatId: string) => { openMediaViewer({ chatId, messageId, diff --git a/src/components/left/search/RecentContacts.tsx b/src/components/left/search/RecentContacts.tsx index b3f368416..51d8bb784 100644 --- a/src/components/left/search/RecentContacts.tsx +++ b/src/components/left/search/RecentContacts.tsx @@ -24,9 +24,9 @@ type OwnProps = { }; type StateProps = { - topUserIds?: number[]; - usersById: Record; - recentlyFoundChatIds?: number[]; + topUserIds?: string[]; + usersById: Record; + recentlyFoundChatIds?: string[]; }; type DispatchProps = Pick = ({ useHorizontalScroll(topUsersRef.current, !topUserIds); - const handleClick = useCallback( - (id: number) => { - openChat({ id, shouldReplaceHistory: true }); - onReset(); - setTimeout(() => { - addRecentlyFoundChatId({ id }); - }, SEARCH_CLOSE_TIMEOUT_MS); - }, - [openChat, addRecentlyFoundChatId, onReset], - ); + const handleClick = useCallback((id: string) => { + openChat({ id, shouldReplaceHistory: true }); + onReset(); + setTimeout(() => { + addRecentlyFoundChatId({ id }); + }, SEARCH_CLOSE_TIMEOUT_MS); + }, [openChat, addRecentlyFoundChatId, onReset]); const lang = useLang(); diff --git a/src/components/left/search/helpers/createMapStateToProps.ts b/src/components/left/search/helpers/createMapStateToProps.ts index 6d3a9fe40..a07d95014 100644 --- a/src/components/left/search/helpers/createMapStateToProps.ts +++ b/src/components/left/search/helpers/createMapStateToProps.ts @@ -9,13 +9,13 @@ import { selectTheme } from '../../../../modules/selectors'; export type StateProps = { theme: ISettings['theme']; isLoading?: boolean; - chatsById: Record; - usersById: Record; - globalMessagesByChatId?: Record }>; + chatsById: Record; + usersById: Record; + globalMessagesByChatId?: Record }>; foundIds?: string[]; lastSyncTime?: number; - searchChatId?: number; - activeDownloads: Record; + searchChatId?: string; + activeDownloads: Record; }; export function createMapStateToProps(type: ApiGlobalMessageSearchType) { diff --git a/src/components/left/search/helpers/getSenderName.ts b/src/components/left/search/helpers/getSenderName.ts index 01f762412..6b3f766e2 100644 --- a/src/components/left/search/helpers/getSenderName.ts +++ b/src/components/left/search/helpers/getSenderName.ts @@ -2,26 +2,26 @@ import { ApiChat, ApiMessage, ApiUser } from '../../../../api/types'; import { getChatTitle, getSenderTitle, - isChatPrivate, + isUserId, isChatGroup, } from '../../../../modules/helpers'; import { LangFn } from '../../../../hooks/useLang'; export function getSenderName( - lang: LangFn, message: ApiMessage, chatsById: Record, usersById: Record, + lang: LangFn, message: ApiMessage, chatsById: Record, usersById: Record, ) { const { senderId } = message; if (!senderId) { return undefined; } - const sender = isChatPrivate(senderId) ? usersById[senderId] : chatsById[senderId]; + const sender = isUserId(senderId) ? usersById[senderId] : chatsById[senderId]; let senderName = getSenderTitle(lang, sender); const chat = chatsById[message.chatId]; if (chat) { - if (isChatPrivate(senderId) && (sender as ApiUser).isSelf) { + if (isUserId(senderId) && (sender as ApiUser).isSelf) { senderName = `${lang('FromYou')} → ${getChatTitle(lang, chat)}`; } else if (isChatGroup(chat)) { senderName += ` → ${getChatTitle(lang, chat)}`; diff --git a/src/components/left/settings/BlockUserModal.tsx b/src/components/left/settings/BlockUserModal.tsx index 9900f1ad6..5373f983c 100644 --- a/src/components/left/settings/BlockUserModal.tsx +++ b/src/components/left/settings/BlockUserModal.tsx @@ -19,11 +19,11 @@ export type OwnProps = { }; type StateProps = { - usersById: Record; - blockedIds: number[]; - contactIds?: number[]; - localContactIds?: number[]; - currentUserId?: number; + usersById: Record; + blockedIds: string[]; + contactIds?: string[]; + localContactIds?: string[]; + currentUserId?: string; }; type DispatchProps = Pick; @@ -54,7 +54,7 @@ const BlockUserModal: FC = ({ return !blockedIds.includes(contactId) && contactId !== currentUserId; }); - return unique(availableContactsId).reduce((acc, contactId) => { + return unique(availableContactsId).reduce((acc, contactId) => { if ( !filter || !usersById[contactId] @@ -65,7 +65,7 @@ const BlockUserModal: FC = ({ } return acc; - }, [] as number[]) + }, []) .sort((firstId, secondId) => { const firstName = getUserFullName(usersById[firstId]) || ''; const secondName = getUserFullName(usersById[secondId]) || ''; @@ -74,7 +74,7 @@ const BlockUserModal: FC = ({ }); }, [blockedIds, contactIds, currentUserId, filter, localContactIds, usersById]); - const handleRemoveUser = useCallback((userId: number) => { + const handleRemoveUser = useCallback((userId: string) => { const { id: contactId, accessHash } = usersById[userId] || {}; if (!contactId || !accessHash) { return; diff --git a/src/components/left/settings/SettingsPrivacyBlockedUsers.tsx b/src/components/left/settings/SettingsPrivacyBlockedUsers.tsx index 8b838c962..22138f354 100644 --- a/src/components/left/settings/SettingsPrivacyBlockedUsers.tsx +++ b/src/components/left/settings/SettingsPrivacyBlockedUsers.tsx @@ -11,7 +11,7 @@ import { CHAT_HEIGHT_PX } from '../../../config'; import { formatPhoneNumberWithCode } from '../../../util/phoneNumber'; import { pick } from '../../../util/iteratees'; import { - getChatTitle, getUserFullName, isChatPrivate, + getChatTitle, getUserFullName, isUserId, } from '../../../modules/helpers'; import renderText from '../../common/helpers/renderText'; import buildClassName from '../../../util/buildClassName'; @@ -32,9 +32,9 @@ type OwnProps = { }; type StateProps = { - chatsByIds: Record; - usersByIds: Record; - blockedIds: number[]; + chatsByIds: Record; + usersByIds: Record; + blockedIds: string[]; phoneCodeList: ApiCountryCode[]; }; @@ -52,14 +52,14 @@ const SettingsPrivacyBlockedUsers: FC = ( }) => { const lang = useLang(); const [isBlockUserModalOpen, openBlockUserModal, closeBlockUserModal] = useFlag(); - const handleUnblockClick = useCallback((contactId: number) => { + const handleUnblockClick = useCallback((contactId: string) => { unblockContact({ contactId }); }, [unblockContact]); useHistoryBack(isActive, onReset, onScreenSelect, SettingsScreens.PrivacyBlockedUsers); - function renderContact(contactId: number, i: number, viewportOffset: number) { - const isPrivate = isChatPrivate(contactId); + function renderContact(contactId: string, i: number, viewportOffset: number) { + const isPrivate = isUserId(contactId); const user = isPrivate ? usersByIds[contactId] : undefined; const chat = !isPrivate ? chatsByIds[contactId] : undefined; diff --git a/src/components/left/settings/SettingsPrivacyVisibility.tsx b/src/components/left/settings/SettingsPrivacyVisibility.tsx index b8369b14f..162f3d312 100644 --- a/src/components/left/settings/SettingsPrivacyVisibility.tsx +++ b/src/components/left/settings/SettingsPrivacyVisibility.tsx @@ -23,8 +23,8 @@ type OwnProps = { }; type StateProps = Partial & { - chatsById?: Record; - usersById?: Record; + chatsById?: Record; + usersById?: Record; }; type DispatchProps = Pick; diff --git a/src/components/left/settings/SettingsPrivacyVisibilityExceptionList.tsx b/src/components/left/settings/SettingsPrivacyVisibilityExceptionList.tsx index c030b433d..bae3cafc5 100644 --- a/src/components/left/settings/SettingsPrivacyVisibilityExceptionList.tsx +++ b/src/components/left/settings/SettingsPrivacyVisibilityExceptionList.tsx @@ -12,7 +12,7 @@ import { pick } from '../../../util/iteratees'; import searchWords from '../../../util/searchWords'; import { getPrivacyKey } from './helper/privacy'; import { - getChatTitle, isChatGroup, isChatPrivate, prepareChatList, + getChatTitle, isChatGroup, isUserId, prepareChatList, } from '../../../modules/helpers'; import useHistoryBack from '../../../hooks/useHistoryBack'; @@ -28,12 +28,12 @@ export type OwnProps = { }; type StateProps = { - currentUserId?: number; - chatsById: Record; - listIds?: number[]; - orderedPinnedIds?: number[]; - archivedListIds?: number[]; - archivedPinnedIds?: number[]; + currentUserId?: string; + chatsById: Record; + listIds?: string[]; + orderedPinnedIds?: string[]; + archivedListIds?: string[]; + archivedPinnedIds?: string[]; settings?: ApiPrivacySettings; }; @@ -69,7 +69,7 @@ const SettingsPrivacyVisibilityExceptionList: FC(''); const [isSubmitShown, setIsSubmitShown] = useState(false); - const [newSelectedContactIds, setNewSelectedContactIds] = useState(selectedContactIds); + const [newSelectedContactIds, setNewSelectedContactIds] = useState(selectedContactIds); const chats = useMemo(() => { const activeChatArrays = listIds @@ -102,7 +102,7 @@ const SettingsPrivacyVisibilityExceptionList: FC ( - ((isChatPrivate(chat.id) && chat.id !== currentUserId) || isChatGroup(chat)) + ((isUserId(chat.id) && chat.id !== currentUserId) || isChatGroup(chat)) && ( !searchQuery || searchWords(getChatTitle(lang, chat), searchQuery) @@ -112,7 +112,7 @@ const SettingsPrivacyVisibilityExceptionList: FC id); }, [chats, currentUserId, lang, searchQuery, selectedContactIds]); - const handleSelectedContactIdsChange = useCallback((value: number[]) => { + const handleSelectedContactIdsChange = useCallback((value: string[]) => { setNewSelectedContactIds(value); setIsSubmitShown(true); }, []); diff --git a/src/components/left/settings/folders/SettingsFoldersChatFilters.tsx b/src/components/left/settings/folders/SettingsFoldersChatFilters.tsx index 3c00687de..a49477c7f 100644 --- a/src/components/left/settings/folders/SettingsFoldersChatFilters.tsx +++ b/src/components/left/settings/folders/SettingsFoldersChatFilters.tsx @@ -32,11 +32,11 @@ type OwnProps = { }; type StateProps = { - chatsById: Record; - listIds?: number[]; - orderedPinnedIds?: number[]; - archivedListIds?: number[]; - archivedPinnedIds?: number[]; + chatsById: Record; + listIds?: string[]; + orderedPinnedIds?: string[]; + archivedListIds?: string[]; + archivedPinnedIds?: string[]; }; type DispatchProps = Pick; @@ -101,7 +101,7 @@ const SettingsFoldersChatFilters: FC = ({ }); }, [dispatch]); - const handleSelectedIdsChange = useCallback((ids: number[]) => { + const handleSelectedIdsChange = useCallback((ids: string[]) => { if (mode === 'included') { dispatch({ type: 'setIncludeFilters', diff --git a/src/components/left/settings/folders/SettingsFoldersChatsPicker.tsx b/src/components/left/settings/folders/SettingsFoldersChatsPicker.tsx index 74fd67dbe..0803df9cd 100644 --- a/src/components/left/settings/folders/SettingsFoldersChatsPicker.tsx +++ b/src/components/left/settings/folders/SettingsFoldersChatsPicker.tsx @@ -2,7 +2,7 @@ import React, { FC, useCallback, useRef, useEffect, memo, } from '../../../../lib/teact/teact'; -import { isChatPrivate } from '../../../../modules/helpers'; +import { isUserId } from '../../../../modules/helpers'; import { INCLUDED_CHAT_TYPES, EXCLUDED_CHAT_TYPES, @@ -25,11 +25,11 @@ import './SettingsFoldersChatsPicker.scss'; type OwnProps = { mode: 'included' | 'excluded'; - chatIds: number[]; - selectedIds: number[]; + chatIds: string[]; + selectedIds: string[]; selectedChatTypes: string[]; filterValue?: string; - onSelectedIdsChange: (ids: number[]) => void; + onSelectedIdsChange: (ids: string[]) => void; onSelectedChatTypesChange: (types: string[]) => void; onFilterChange: (value: string) => void; onLoadMore: () => void; @@ -67,7 +67,7 @@ const SettingsFoldersChatsPicker: FC = ({ }, FOCUS_DELAY_MS); }, []); - const handleItemClick = useCallback((id: number) => { + const handleItemClick = useCallback((id: string) => { const newSelectedIds = [...selectedIds]; if (newSelectedIds.includes(id)) { newSelectedIds.splice(newSelectedIds.indexOf(id), 1); @@ -131,7 +131,7 @@ const SettingsFoldersChatsPicker: FC = ({ ); } - function renderItem(id: number) { + function renderItem(id: string) { const isSelected = selectedIds.includes(id); return ( @@ -142,7 +142,7 @@ const SettingsFoldersChatsPicker: FC = ({ ripple disabled={!isSelected && hasMaxChats} > - {isChatPrivate(id) ? ( + {isUserId(id) ? ( ) : ( diff --git a/src/components/left/settings/folders/SettingsFoldersEdit.tsx b/src/components/left/settings/folders/SettingsFoldersEdit.tsx index d899f478a..f7acde910 100644 --- a/src/components/left/settings/folders/SettingsFoldersEdit.tsx +++ b/src/components/left/settings/folders/SettingsFoldersEdit.tsx @@ -8,7 +8,7 @@ import { SettingsScreens } from '../../../../types'; import { STICKER_SIZE_FOLDER_SETTINGS } from '../../../../config'; import { findIntersectionWithSet, pick } from '../../../../util/iteratees'; -import { isChatPrivate } from '../../../../modules/helpers'; +import { isUserId } from '../../../../modules/helpers'; import getAnimationData from '../../../common/helpers/animatedAssets'; import { EXCLUDED_CHAT_TYPES, @@ -41,8 +41,8 @@ type OwnProps = { }; type StateProps = { - loadedActiveChatIds?: number[]; - loadedArchivedChatIds?: number[]; + loadedActiveChatIds?: string[]; + loadedArchivedChatIds?: string[]; }; type DispatchProps = Pick; @@ -212,7 +212,7 @@ const SettingsFoldersEdit: FC = ({ narrow inactive > - {isChatPrivate(id) ? ( + {isUserId(id) ? ( ) : ( diff --git a/src/components/left/settings/folders/SettingsFoldersMain.tsx b/src/components/left/settings/folders/SettingsFoldersMain.tsx index 908e6ed93..487fef58c 100644 --- a/src/components/left/settings/folders/SettingsFoldersMain.tsx +++ b/src/components/left/settings/folders/SettingsFoldersMain.tsx @@ -30,8 +30,8 @@ type OwnProps = { }; type StateProps = { - chatsById: Record; - usersById: Record; + chatsById: Record; + usersById: Record; orderedFolderIds?: number[]; foldersById: Record; recommendedChatFolders?: ApiChatFolder[]; @@ -104,7 +104,7 @@ const SettingsFoldersMain: FC = ({ return undefined; } - const chatIds = Object.keys(chatsById).map(Number); + const chatIds = Object.keys(chatsById); return orderedFolderIds.map((id) => { const folder = foldersById[id]; diff --git a/src/components/main/ForwardPicker.tsx b/src/components/main/ForwardPicker.tsx index e8f7fe5b2..9b2784758 100644 --- a/src/components/main/ForwardPicker.tsx +++ b/src/components/main/ForwardPicker.tsx @@ -18,12 +18,12 @@ export type OwnProps = { }; type StateProps = { - chatsById: Record; - pinnedIds?: number[]; - activeListIds?: number[]; - archivedListIds?: number[]; - orderedPinnedIds?: number[]; - currentUserId?: number; + chatsById: Record; + pinnedIds?: string[]; + activeListIds?: string[]; + archivedListIds?: string[]; + orderedPinnedIds?: string[]; + currentUserId?: string; }; type DispatchProps = Pick; @@ -75,7 +75,7 @@ const ForwardPicker: FC = ({ ], chatsById, undefined, priorityIds); }, [activeListIds, archivedListIds, chatsById, currentUserId, filter, lang, pinnedIds]); - const handleSelectUser = useCallback((userId: number) => { + const handleSelectUser = useCallback((userId: string) => { setForwardChatId({ id: userId }); }, [setForwardChatId]); diff --git a/src/components/mediaViewer/MediaViewer.tsx b/src/components/mediaViewer/MediaViewer.tsx index 2681715b2..f375ecda6 100644 --- a/src/components/mediaViewer/MediaViewer.tsx +++ b/src/components/mediaViewer/MediaViewer.tsx @@ -74,10 +74,10 @@ import PanZoom from './PanZoom'; import './MediaViewer.scss'; type StateProps = { - chatId?: number; + chatId?: string; threadId?: number; messageId?: number; - senderId?: number; + senderId?: string; origin?: MediaViewerOrigin; avatarOwner?: ApiChat | ApiUser; profilePhotoIndex?: number; @@ -139,7 +139,7 @@ const MediaViewer: FC = ({ /* Animation */ const animationKey = useRef(); - const prevSenderId = usePrevious(senderId); + const prevSenderId = usePrevious(senderId); if (isOpen && (!prevSenderId || prevSenderId !== senderId || !animationKey.current)) { animationKey.current = selectedMediaMessageIndex; } diff --git a/src/components/mediaViewer/SenderInfo.tsx b/src/components/mediaViewer/SenderInfo.tsx index 0db8ac8fd..44b6bb617 100644 --- a/src/components/mediaViewer/SenderInfo.tsx +++ b/src/components/mediaViewer/SenderInfo.tsx @@ -4,7 +4,7 @@ import { withGlobal } from '../../lib/teact/teactn'; import { GlobalActions } from '../../global/types'; import { ApiChat, ApiMessage, ApiUser } from '../../api/types'; -import { getSenderTitle, isChatPrivate } from '../../modules/helpers'; +import { getSenderTitle, isUserId } from '../../modules/helpers'; import { formatMediaDateTime } from '../../util/dateFormat'; import renderText from '../common/helpers/renderText'; import { @@ -21,7 +21,7 @@ import Avatar from '../common/Avatar'; import './SenderInfo.scss'; type OwnProps = { - chatId?: number; + chatId?: string; messageId?: number; isAvatar?: boolean; }; @@ -53,15 +53,14 @@ const SenderInfo: FC = ({ return undefined; } - const isFromChat = sender.id < 0; const senderTitle = getSenderTitle(lang, sender); return (
- {isFromChat ? ( - - ) : ( + {isUserId(sender.id) ? ( + ) : ( + )}
@@ -81,7 +80,7 @@ export default withGlobal( (global, { chatId, messageId, isAvatar }): StateProps => { if (isAvatar && chatId) { return { - sender: isChatPrivate(chatId) ? selectUser(global, chatId) : selectChat(global, chatId), + sender: isUserId(chatId) ? selectUser(global, chatId) : selectChat(global, chatId), }; } diff --git a/src/components/middle/ActionMessage.tsx b/src/components/middle/ActionMessage.tsx index e47bdaccf..72e232ead 100644 --- a/src/components/middle/ActionMessage.tsx +++ b/src/components/middle/ActionMessage.tsx @@ -36,11 +36,11 @@ type OwnProps = { }; type StateProps = { - usersById: Record; + usersById: Record; sender?: ApiUser | ApiChat; - targetUserIds?: number[]; + targetUserIds?: string[]; targetMessage?: ApiMessage; - targetChatId?: number; + targetChatId?: string; isFocused: boolean; focusDirection?: FocusDirection; noFocusHighlight?: boolean; diff --git a/src/components/middle/ContactGreeting.tsx b/src/components/middle/ContactGreeting.tsx index b918ca9b2..7f8ed3e7b 100644 --- a/src/components/middle/ContactGreeting.tsx +++ b/src/components/middle/ContactGreeting.tsx @@ -10,13 +10,14 @@ import { pick } from '../../util/iteratees'; import { selectChat } from '../../modules/selectors'; import { useIntersectionObserver } from '../../hooks/useIntersectionObserver'; import useLang from '../../hooks/useLang'; +import { getUserIdDividend } from '../../modules/helpers'; import StickerButton from '../common/StickerButton'; import './ContactGreeting.scss'; type OwnProps = { - userId: number; + userId: string; }; type StateProps = { @@ -94,7 +95,8 @@ const ContactGreeting: FC = ({ export default memo(withGlobal( (global, { userId }): StateProps => { const { stickers } = global.stickers.greeting; - const sticker = stickers?.length ? stickers[userId % stickers.length] : undefined; + const dividend = getUserIdDividend(userId) + getUserIdDividend(global.currentUserId!); + const sticker = stickers?.length ? stickers[dividend % stickers.length] : undefined; const chat = selectChat(global, userId); if (!chat) { return {}; @@ -111,5 +113,4 @@ export default memo(withGlobal( (setGlobal, actions): DispatchProps => pick(actions, [ 'loadGreetingStickers', 'sendMessage', 'markMessageListRead', ]), - )(ContactGreeting)); diff --git a/src/components/middle/DeleteSelectedMessageModal.tsx b/src/components/middle/DeleteSelectedMessageModal.tsx index faaf4750c..705401999 100644 --- a/src/components/middle/DeleteSelectedMessageModal.tsx +++ b/src/components/middle/DeleteSelectedMessageModal.tsx @@ -7,7 +7,7 @@ import { GlobalActions } from '../../global/types'; import { selectCanDeleteSelectedMessages, selectCurrentChat, selectUser } from '../../modules/selectors'; import { - isChatPrivate, + isUserId, getUserFirstOrLastName, getPrivateChatUserId, isChatBasicGroup, @@ -115,7 +115,7 @@ export default memo(withGlobal( const { messageIds: selectedMessageIds } = global.selectedMessages || {}; const { canDeleteForAll } = selectCanDeleteSelectedMessages(global); const chat = selectCurrentChat(global); - const contactName = chat && isChatPrivate(chat.id) + const contactName = chat && isUserId(chat.id) ? getUserFirstOrLastName(selectUser(global, getPrivateChatUserId(chat)!)) : undefined; diff --git a/src/components/middle/HeaderActions.tsx b/src/components/middle/HeaderActions.tsx index 285accfb7..8f1fea7d0 100644 --- a/src/components/middle/HeaderActions.tsx +++ b/src/components/middle/HeaderActions.tsx @@ -29,7 +29,7 @@ import Button from '../ui/Button'; import HeaderMenuContainer from './HeaderMenuContainer.async'; interface OwnProps { - chatId: number; + chatId: string; threadId: number; messageListType: MessageListType; } diff --git a/src/components/middle/HeaderMenuContainer.tsx b/src/components/middle/HeaderMenuContainer.tsx index 0d104842c..3b9303868 100644 --- a/src/components/middle/HeaderMenuContainer.tsx +++ b/src/components/middle/HeaderMenuContainer.tsx @@ -14,7 +14,7 @@ import { } from '../../modules/selectors'; import { pick } from '../../util/iteratees'; import { - isChatPrivate, getCanDeleteChat, selectIsChatMuted, getCanAddContact, + isUserId, getCanDeleteChat, selectIsChatMuted, getCanAddContact, } from '../../modules/helpers'; import useShowTransition from '../../hooks/useShowTransition'; import useLang from '../../hooks/useLang'; @@ -31,7 +31,7 @@ type DispatchProps = Pick; export type OwnProps = { - chatId: number; + chatId: string; threadId: number; isOpen: boolean; anchor: IAnchorPosition; @@ -253,7 +253,7 @@ export default memo(withGlobal( if (!chat || chat.isRestricted) { return {}; } - const isPrivate = isChatPrivate(chat.id); + const isPrivate = isUserId(chat.id); const user = isPrivate ? selectUser(global, chatId) : undefined; const canAddContact = user && getCanAddContact(user); diff --git a/src/components/middle/MessageList.tsx b/src/components/middle/MessageList.tsx index 1ca2d906b..50260192e 100644 --- a/src/components/middle/MessageList.tsx +++ b/src/components/middle/MessageList.tsx @@ -28,7 +28,7 @@ import { } from '../../modules/selectors'; import { isChatChannel, - isChatPrivate, + isUserId, isChatWithRepliesBot, isChatGroup, } from '../../modules/helpers'; @@ -56,7 +56,7 @@ import NoMessages from './NoMessages'; import './MessageList.scss'; type OwnProps = { - chatId: number; + chatId: string; threadId: number; type: MessageListType; canPost: boolean; @@ -447,10 +447,10 @@ const MessageList: FC = ({ const lang = useLang(); - const isPrivate = Boolean(chatId && isChatPrivate(chatId)); + const isPrivate = Boolean(chatId && isUserId(chatId)); const withUsers = Boolean((!isPrivate && !isChannelChat) || isChatWithSelf || isRepliesChat); const noAvatars = Boolean(!withUsers || isChannelChat); - const shouldRenderGreeting = isChatPrivate(chatId) && !isChatWithSelf && !isBot + const shouldRenderGreeting = isUserId(chatId) && !isChatWithSelf && !isBot && ( ( !messageGroups && !lastMessage && messageIds diff --git a/src/components/middle/MiddleColumn.tsx b/src/components/middle/MiddleColumn.tsx index 76cab54a4..a6fe339a9 100644 --- a/src/components/middle/MiddleColumn.tsx +++ b/src/components/middle/MiddleColumn.tsx @@ -37,7 +37,7 @@ import { selectPinnedIds, selectTheme, } from '../../modules/selectors'; -import { getCanPostInChat, getMessageSendingRestrictionReason, isChatPrivate } from '../../modules/helpers'; +import { getCanPostInChat, getMessageSendingRestrictionReason, isUserId } from '../../modules/helpers'; import captureEscKeyListener from '../../util/captureEscKeyListener'; import { pick } from '../../util/iteratees'; import buildClassName from '../../util/buildClassName'; @@ -64,7 +64,7 @@ import ReceiptModal from '../payment/ReceiptModal.async'; import './MiddleColumn.scss'; type StateProps = { - chatId?: number; + chatId?: string; threadId?: number; messageListType?: MessageListType; isPrivate?: boolean; @@ -477,7 +477,7 @@ export default memo(withGlobal( chatId, threadId, messageListType, - isPrivate: isChatPrivate(chatId), + isPrivate: isUserId(chatId), canPost: !isPinnedMessageList && (!chat || canPost) && !isBotNotStarted, isPinnedMessageList, isScheduledMessageList, diff --git a/src/components/middle/MiddleHeader.tsx b/src/components/middle/MiddleHeader.tsx index 062e95eb0..51b6fd12e 100644 --- a/src/components/middle/MiddleHeader.tsx +++ b/src/components/middle/MiddleHeader.tsx @@ -23,7 +23,7 @@ import { } from '../../config'; import { IS_SINGLE_COLUMN_LAYOUT, IS_TABLET_COLUMN_LAYOUT } from '../../util/environment'; import { - isChatPrivate, + isUserId, getMessageKey, getChatTitle, getSenderTitle, @@ -68,7 +68,7 @@ const ANIMATION_DURATION = 350; const BACK_BUTTON_INACTIVE_TIME = 450; type OwnProps = { - chatId: number; + chatId: string; threadId: number; messageListType: MessageListType; isReady?: boolean; @@ -85,7 +85,7 @@ type StateProps = { isLeftColumnShown?: boolean; isRightColumnShown?: boolean; audioMessage?: ApiMessage; - chatsById?: Record; + chatsById?: Record; messagesCount?: number; isChatWithSelf?: boolean; isChatWithBot?: boolean; @@ -348,7 +348,7 @@ const MiddleHeader: FC = ({ <> {(isLeftColumnHideable || currentTransitionKey > 0) && renderBackButton(shouldShowCloseButton, true)}
- {isChatPrivate(chatId) ? ( + {isUserId(chatId) ? ( ; + usersById?: Record; recentEmojis: string[]; baseEmojiKeywords?: Record; emojiKeywords?: Record; diff --git a/src/components/middle/composer/BotCommandTooltip.tsx b/src/components/middle/composer/BotCommandTooltip.tsx index 78250db70..a70e60098 100644 --- a/src/components/middle/composer/BotCommandTooltip.tsx +++ b/src/components/middle/composer/BotCommandTooltip.tsx @@ -26,7 +26,7 @@ export type OwnProps = { }; type StateProps = { - usersById: Record; + usersById: Record; }; type DispatchProps = Pick; diff --git a/src/components/middle/composer/Composer.tsx b/src/components/middle/composer/Composer.tsx index 27db8bd40..410083a54 100644 --- a/src/components/middle/composer/Composer.tsx +++ b/src/components/middle/composer/Composer.tsx @@ -41,7 +41,7 @@ import { import { getAllowedAttachmentOptions, getChatSlowModeOptions, - isChatPrivate, + isUserId, isChatAdmin, } from '../../../modules/helpers'; import { formatMediaDuration, formatVoiceRecordDuration, getDayStartAt } from '../../../util/dateFormat'; @@ -98,7 +98,7 @@ import CalendarModal from '../../common/CalendarModal.async'; import './Composer.scss'; type OwnProps = { - chatId: number; + chatId: string; threadId: number; messageListType: MessageListType; dropAreaState: string; @@ -123,8 +123,8 @@ type StateProps = { canScheduleUntilOnline?: boolean; stickersForEmoji?: ApiSticker[]; groupChatMembers?: ApiChatMember[]; - currentUserId?: number; - usersById?: Record; + currentUserId?: string; + usersById?: Record; recentEmojis: string[]; lastSyncTime?: number; contentToBeScheduled?: GlobalState['messages']['contentToBeScheduled']; @@ -132,7 +132,7 @@ type StateProps = { baseEmojiKeywords?: Record; emojiKeywords?: Record; serverTimeOffset: number; - topInlineBotIds?: number[]; + topInlineBotIds?: string[]; isInlineBotLoading: boolean; inlineBots?: Record; botCommands?: ApiBotCommand[] | false; @@ -1069,7 +1069,7 @@ export default memo(withGlobal( isChatWithSelf, canScheduleUntilOnline: ( !isChatWithSelf && !isChatWithBot - && (chat && chatUser && isChatPrivate(chatId) && chatUser.status && Boolean(chatUser.status.wasOnline)) + && (chat && chatUser && isUserId(chatId) && chatUser.status && Boolean(chatUser.status.wasOnline)) ), isRightColumnShown: selectIsRightColumnShown(global), isSelectModeActive: selectIsInSelectMode(global), diff --git a/src/components/middle/composer/ComposerEmbeddedMessage.tsx b/src/components/middle/composer/ComposerEmbeddedMessage.tsx index 8619bc26c..69c96d86a 100644 --- a/src/components/middle/composer/ComposerEmbeddedMessage.tsx +++ b/src/components/middle/composer/ComposerEmbeddedMessage.tsx @@ -23,7 +23,7 @@ import { pick } from '../../../util/iteratees'; import useAsyncRendering from '../../right/hooks/useAsyncRendering'; import useShowTransition from '../../../hooks/useShowTransition'; import buildClassName from '../../../util/buildClassName'; -import { isChatPrivate } from '../../../modules/helpers'; +import { isUserId } from '../../../modules/helpers'; import Button from '../../ui/Button'; import EmbeddedMessage from '../../common/EmbeddedMessage'; @@ -154,7 +154,7 @@ export default memo(withGlobal( sender = selectSender(global, message); } } else if (isForwarding) { - sender = isChatPrivate(fromChatId!) ? selectUser(global, fromChatId!) : selectChat(global, fromChatId!); + sender = isUserId(fromChatId!) ? selectUser(global, fromChatId!) : selectChat(global, fromChatId!); } return { diff --git a/src/components/middle/composer/InlineBotTooltip.tsx b/src/components/middle/composer/InlineBotTooltip.tsx index d04555c89..931310c02 100644 --- a/src/components/middle/composer/InlineBotTooltip.tsx +++ b/src/components/middle/composer/InlineBotTooltip.tsx @@ -32,7 +32,7 @@ const runThrottled = throttle((cb) => cb(), 500, true); export type OwnProps = { isOpen: boolean; - botId?: number; + botId?: string; isGallery?: boolean; allowedAttachmentOptions: IAllowedAttachmentOptions; inlineBotResults?: (ApiBotInlineResult | ApiBotInlineMediaResult)[]; diff --git a/src/components/middle/composer/MentionTooltip.tsx b/src/components/middle/composer/MentionTooltip.tsx index e5e83ee1d..973bbc374 100644 --- a/src/components/middle/composer/MentionTooltip.tsx +++ b/src/components/middle/composer/MentionTooltip.tsx @@ -20,7 +20,7 @@ export type OwnProps = { onClose: () => void; onInsertUserName: (user: ApiUser, forceFocus?: boolean) => void; filteredUsers?: ApiUser[]; - usersById?: Record; + usersById?: Record; }; const MentionTooltip: FC = ({ @@ -34,7 +34,7 @@ const MentionTooltip: FC = ({ const containerRef = useRef(null); const { shouldRender, transitionClassNames } = useShowTransition(isOpen, undefined, undefined, false); - const handleUserSelect = useCallback((userId: number, forceFocus = false) => { + const handleUserSelect = useCallback((userId: string, forceFocus = false) => { const user = usersById?.[userId]; if (!user) { return; diff --git a/src/components/middle/composer/MessageInput.tsx b/src/components/middle/composer/MessageInput.tsx index d40f53c58..bb312de93 100644 --- a/src/components/middle/composer/MessageInput.tsx +++ b/src/components/middle/composer/MessageInput.tsx @@ -47,7 +47,7 @@ type OwnProps = { }; type StateProps = { - currentChatId?: number; + currentChatId?: string; replyingToId?: number; noTabCapture?: boolean; messageSendKeyCombo?: ISettings['messageSendKeyCombo']; diff --git a/src/components/middle/composer/WebPagePreview.tsx b/src/components/middle/composer/WebPagePreview.tsx index 557b60e2d..1d4bd4c04 100644 --- a/src/components/middle/composer/WebPagePreview.tsx +++ b/src/components/middle/composer/WebPagePreview.tsx @@ -22,7 +22,7 @@ import Button from '../../ui/Button'; import './WebPagePreview.scss'; type OwnProps = { - chatId: number; + chatId: string; threadId: number; messageText: string; disabled?: boolean; diff --git a/src/components/middle/composer/hooks/useDraft.ts b/src/components/middle/composer/hooks/useDraft.ts index 59d44c09e..f78b43727 100644 --- a/src/components/middle/composer/hooks/useDraft.ts +++ b/src/components/middle/composer/hooks/useDraft.ts @@ -14,12 +14,12 @@ import useBeforeUnload from '../../../../hooks/useBeforeUnload'; import { IS_TOUCH_ENV } from '../../../../util/environment'; // Used to avoid running debounced callbacks when chat changes. -let currentChatId: number | undefined; +let currentChatId: string | undefined; let currentThreadId: number | undefined; export default ( draft: ApiFormattedText | undefined, - chatId: number, + chatId: string, threadId: number, html: string, htmlRef: { current: string }, @@ -28,7 +28,7 @@ export default ( saveDraft: GlobalActions['saveDraft'], clearDraft: GlobalActions['clearDraft'], ) => { - const updateDraft = useCallback((draftChatId: number, draftThreadId: number) => { + const updateDraft = useCallback((draftChatId: string, draftThreadId: number) => { if (htmlRef.current.length && !editedMessage) { saveDraft({ chatId: draftChatId, threadId: draftThreadId, draft: parseMessageInput(htmlRef.current!) }); } else { diff --git a/src/components/middle/composer/hooks/useInlineBotTooltip.ts b/src/components/middle/composer/hooks/useInlineBotTooltip.ts index bbe3de96b..c4ae6365e 100644 --- a/src/components/middle/composer/hooks/useInlineBotTooltip.ts +++ b/src/components/middle/composer/hooks/useInlineBotTooltip.ts @@ -10,7 +10,7 @@ const HAS_NEW_LINE = /^@([a-z0-9_]{1,32})[\u00A0\u0020]+\n{2,}/i; export default function useInlineBotTooltip( isAllowed: boolean, - chatId: number, + chatId: string, html: string, inlineBots?: Record, ) { diff --git a/src/components/middle/composer/hooks/useMentionTooltip.ts b/src/components/middle/composer/hooks/useMentionTooltip.ts index dfe57e23a..218f17940 100644 --- a/src/components/middle/composer/hooks/useMentionTooltip.ts +++ b/src/components/middle/composer/hooks/useMentionTooltip.ts @@ -28,9 +28,9 @@ export default function useMentionTooltip( onUpdateHtml: (html: string) => void, inputId: string = EDITABLE_INPUT_ID, groupChatMembers?: ApiChatMember[], - topInlineBotIds?: number[], - currentUserId?: number, - usersById?: Record, + topInlineBotIds?: string[], + currentUserId?: string, + usersById?: Record, ) { const [isOpen, markIsOpen, unmarkIsOpen] = useFlag(); const [usersToMention, setUsersToMention] = useState(); diff --git a/src/components/middle/message/CommentButton.tsx b/src/components/middle/message/CommentButton.tsx index 79283c29c..caa1fc619 100644 --- a/src/components/middle/message/CommentButton.tsx +++ b/src/components/middle/message/CommentButton.tsx @@ -9,7 +9,7 @@ import { import { GlobalActions } from '../../../global/types'; import { pick } from '../../../util/iteratees'; -import { isChatPrivate } from '../../../modules/helpers'; +import { isUserId } from '../../../modules/helpers'; import { formatIntegerCompact } from '../../../util/textFormat'; import buildClassName from '../../../util/buildClassName'; import { selectThreadInfo } from '../../../modules/selectors'; @@ -26,8 +26,8 @@ type OwnProps = { type StateProps = { threadInfo: ApiThreadInfo; - usersById?: Record; - chatsById?: Record; + usersById?: Record; + chatsById?: Record; }; type DispatchProps = Pick; @@ -53,7 +53,7 @@ const CommentButton: FC = ({ } const recentRepliers = recentReplierIds && recentReplierIds.map((peerId) => { - return isChatPrivate(peerId) ? usersById![peerId] : chatsById![peerId]; + return isUserId(peerId) ? usersById![peerId] : chatsById![peerId]; }).filter(Boolean); function renderRecentRepliers() { @@ -64,8 +64,8 @@ const CommentButton: FC = ({ ))}
diff --git a/src/components/middle/message/ContextMenuContainer.tsx b/src/components/middle/message/ContextMenuContainer.tsx index bde911743..fe2faa01e 100644 --- a/src/components/middle/message/ContextMenuContainer.tsx +++ b/src/components/middle/message/ContextMenuContainer.tsx @@ -215,7 +215,7 @@ const ContextMenuContainer: FC = ({ }, [message.chatId, message.id, rescheduleMessage]); const handleCopyLink = useCallback(() => { - copyTextToClipboard(`https://t.me/${chatUsername || `c/${Math.abs(message.chatId)}`}/${message.id}`); + copyTextToClipboard(`https://t.me/${chatUsername || `c/${message.chatId.replace('-', '')}`}/${message.id}`); closeMenu(); }, [chatUsername, closeMenu, message.chatId, message.id]); diff --git a/src/components/middle/message/MentionLink.tsx b/src/components/middle/message/MentionLink.tsx index be1d45e10..48fb32b83 100644 --- a/src/components/middle/message/MentionLink.tsx +++ b/src/components/middle/message/MentionLink.tsx @@ -8,7 +8,7 @@ import { pick } from '../../../util/iteratees'; import { selectUser } from '../../../modules/selectors'; type OwnProps = { - userId?: number; + userId?: string; username?: string; children: any; }; diff --git a/src/components/middle/message/Message.tsx b/src/components/middle/message/Message.tsx index d667d061f..66289a81a 100644 --- a/src/components/middle/message/Message.tsx +++ b/src/components/middle/message/Message.tsx @@ -52,7 +52,7 @@ import { isReplyMessage, isAnonymousOwnMessage, isMessageLocal, - isChatPrivate, + isUserId, isChatWithRepliesBot, getMessageCustomShape, isChatChannel, @@ -447,7 +447,7 @@ const Message: FC = ({ } function renderAvatar() { - const isAvatarPeerUser = avatarPeer && isChatPrivate(avatarPeer.id); + const isAvatarPeerUser = avatarPeer && isUserId(avatarPeer.id); const avatarUser = (avatarPeer && isAvatarPeerUser) ? avatarPeer as ApiUser : undefined; const avatarChat = (avatarPeer && !isAvatarPeerUser) ? avatarPeer as ApiChat : undefined; const hiddenName = (!avatarPeer && forwardInfo) ? forwardInfo.hiddenUserName : undefined; diff --git a/src/components/middle/message/Poll.tsx b/src/components/middle/message/Poll.tsx index deacd7804..bb37c614f 100644 --- a/src/components/middle/message/Poll.tsx +++ b/src/components/middle/message/Poll.tsx @@ -37,7 +37,7 @@ type OwnProps = { type StateProps = { recentVoterIds?: number[]; - usersById: Record; + usersById: Record; serverTimeOffset: number; }; diff --git a/src/components/middle/message/hooks/useFocusMessage.ts b/src/components/middle/message/hooks/useFocusMessage.ts index 8ce337872..10bc5a667 100644 --- a/src/components/middle/message/hooks/useFocusMessage.ts +++ b/src/components/middle/message/hooks/useFocusMessage.ts @@ -9,7 +9,7 @@ const FOCUS_MARGIN = 20; export default function useFocusMessage( elementRef: { current: HTMLDivElement | null }, - chatId: number, + chatId: string, isFocused?: boolean, focusDirection?: FocusDirection, noFocusHighlight?: boolean, diff --git a/src/components/middle/message/hooks/useInnerHandlers.ts b/src/components/middle/message/hooks/useInnerHandlers.ts index 8d4b0b43a..3a79cc945 100644 --- a/src/components/middle/message/hooks/useInnerHandlers.ts +++ b/src/components/middle/message/hooks/useInnerHandlers.ts @@ -1,7 +1,7 @@ import React, { useCallback } from '../../../../lib/teact/teact'; import { getDispatch } from '../../../../lib/teact/teactn'; -import { isChatPrivate } from '../../../../modules/helpers'; +import { isUserId } from '../../../../modules/helpers'; import { AudioOrigin, IAlbum, MediaViewerOrigin } from '../../../../types'; import { ApiChat, ApiMessage, ApiUser, MAIN_THREAD_ID, @@ -12,7 +12,7 @@ export default function useInnerHandlers( lang: LangFn, selectMessage: (e: React.MouseEvent, groupedId?: string) => void, message: ApiMessage, - chatId: number, + chatId: string, threadId: number, isInDocumentGroup: boolean, isScheduled?: boolean, @@ -36,7 +36,7 @@ export default function useInnerHandlers( return; } - if (isChatPrivate(avatarPeer.id)) { + if (isUserId(avatarPeer.id)) { openUserInfo({ id: avatarPeer.id }); } else { openChat({ id: avatarPeer.id }); @@ -50,7 +50,7 @@ export default function useInnerHandlers( return; } - if (isChatPrivate(senderPeer.id)) { + if (isUserId(senderPeer.id)) { openUserInfo({ id: senderPeer.id }); } else { openChat({ id: senderPeer.id }); diff --git a/src/components/right/AddChatMembers.tsx b/src/components/right/AddChatMembers.tsx index 0a1bca012..e381341c5 100644 --- a/src/components/right/AddChatMembers.tsx +++ b/src/components/right/AddChatMembers.tsx @@ -26,9 +26,9 @@ import Spinner from '../ui/Spinner'; import './AddChatMembers.scss'; export type OwnProps = { - chatId: number; + chatId: string; isActive: boolean; - onNextStep: (memberIds: number[]) => void; + onNextStep: (memberIds: string[]) => void; onClose: NoneToVoidFunction; }; @@ -36,15 +36,15 @@ type StateProps = { connectionState?: ApiUpdateConnectionStateType; isChannel?: boolean; members?: ApiChatMember[]; - currentUserId?: number; - usersById: Record; - chatsById: Record; - localContactIds?: number[]; + currentUserId?: string; + usersById: Record; + chatsById: Record; + localContactIds?: string[]; searchQuery?: string; isLoading: boolean; isSearching?: boolean; - localUserIds?: number[]; - globalUserIds?: number[]; + localUserIds?: string[]; + globalUserIds?: string[]; }; type DispatchProps = Pick; @@ -69,7 +69,7 @@ const AddChatMembers: FC = ({ loadContactList, }) => { const lang = useLang(); - const [selectedMemberIds, setSelectedMemberIds] = useState([]); + const [selectedMemberIds, setSelectedMemberIds] = useState([]); const prevSelectedMemberIds = usePrevious(selectedMemberIds); const noPickerScrollRestore = prevSelectedMemberIds === selectedMemberIds; diff --git a/src/components/right/DeleteMemberModal.tsx b/src/components/right/DeleteMemberModal.tsx index 84da59dc5..1bf6e3d5f 100644 --- a/src/components/right/DeleteMemberModal.tsx +++ b/src/components/right/DeleteMemberModal.tsx @@ -15,7 +15,7 @@ import Button from '../ui/Button'; export type OwnProps = { isOpen: boolean; - userId?: number; + userId?: string; onClose: () => void; }; diff --git a/src/components/right/PollAnswerResults.tsx b/src/components/right/PollAnswerResults.tsx index 8e04c5c79..9e5073587 100644 --- a/src/components/right/PollAnswerResults.tsx +++ b/src/components/right/PollAnswerResults.tsx @@ -30,7 +30,7 @@ type OwnProps = { }; type StateProps = { - voters?: number[]; + voters?: string[]; offset: string; }; @@ -78,7 +78,7 @@ const PollAnswerResults: FC = ({ setIsLoading(false); }, [voters]); - const handleMemberClick = useCallback((id: number) => { + const handleMemberClick = useCallback((id: string) => { openChat({ id }); closePollResults(); }, [closePollResults, openChat]); diff --git a/src/components/right/Profile.tsx b/src/components/right/Profile.tsx index bd00dc9b5..28aad9e41 100644 --- a/src/components/right/Profile.tsx +++ b/src/components/right/Profile.tsx @@ -22,7 +22,7 @@ import { } from '../../config'; import { IS_TOUCH_ENV } from '../../util/environment'; import { - getHasAdminRight, isChatAdmin, isChatChannel, isChatGroup, isChatPrivate, + getHasAdminRight, isChatAdmin, isChatChannel, isChatGroup, isUserId, } from '../../modules/helpers'; import { selectChatMessages, @@ -61,8 +61,8 @@ import DeleteMemberModal from './DeleteMemberModal'; import './Profile.scss'; type OwnProps = { - chatId: number; - userId?: number; + chatId: string; + userId?: string; profileState: ProfileState; onProfileStateChange: (state: ProfileState) => void; }; @@ -70,8 +70,8 @@ type OwnProps = { type StateProps = { theme: ISettings['theme']; isChannel?: boolean; - currentUserId?: number; - resolvedUserId?: number; + currentUserId?: string; + resolvedUserId?: string; chatMessages?: Record; foundIds?: number[]; mediaSearchType?: SharedMediaType; @@ -80,8 +80,8 @@ type StateProps = { canAddMembers?: boolean; canDeleteMembers?: boolean; members?: ApiChatMember[]; - chatsById: Record; - usersById: Record; + chatsById: Record; + usersById: Record; isRightColumnShown: boolean; isRestricted?: boolean; lastSyncTime?: number; @@ -143,7 +143,7 @@ const Profile: FC = ({ const transitionRef = useRef(null); const lang = useLang(); const [activeTab, setActiveTab] = useState(0); - const [deletingUserId, setDeletingUserId] = useState(); + const [deletingUserId, setDeletingUserId] = useState(); const tabs = useMemo(() => ([ ...(hasMembersTab ? [{ @@ -200,7 +200,7 @@ const Profile: FC = ({ openAudioPlayer({ chatId: profileId, messageId, origin: AudioOrigin.SharedMedia }); }, [profileId, openAudioPlayer]); - const handleMemberClick = useCallback((id: number) => { + const handleMemberClick = useCallback((id: string) => { openUserInfo({ id }); }, [openUserInfo]); @@ -244,12 +244,12 @@ const Profile: FC = ({ } const canRenderContents = useAsyncRendering([chatId, resultType], renderingDelay); - function getMemberContextAction(id: number) { - return id === currentUserId || !canDeleteMembers ? undefined : [{ + function getMemberContextAction(memberId: string) { + return memberId === currentUserId || !canDeleteMembers ? undefined : [{ title: lang('lng_context_remove_from_group'), icon: 'stop', handler: () => { - setDeletingUserId(id); + setDeletingUserId(memberId); }, }]; } @@ -303,7 +303,7 @@ const Profile: FC = ({ teactFastList > {resultType === 'media' ? ( - viewportIds!.map((id) => chatMessages[id] && ( + (viewportIds as number[])!.map((id) => chatMessages[id] && ( = ({ /> )) ) : resultType === 'documents' ? ( - viewportIds!.map((id) => chatMessages[id] && ( + (viewportIds as number[])!.map((id) => chatMessages[id] && ( = ({ /> )) ) : resultType === 'links' ? ( - viewportIds!.map((id) => chatMessages[id] && ( + (viewportIds as number[])!.map((id) => chatMessages[id] && ( = ({ /> )) ) : resultType === 'audio' ? ( - viewportIds!.map((id) => chatMessages[id] && ( + (viewportIds as number[])!.map((id) => chatMessages[id] && (