From 6d8f415bc1872c25a2e6e4864771103e685aa755 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Wed, 5 Jul 2023 13:16:04 +0200 Subject: [PATCH] Message: Fix failed messages' context menu (#3458) --- src/api/gramjs/methods/messages.ts | 44 ++++++++++++------- .../middle/message/ContextMenuContainer.tsx | 3 +- src/global/actions/api/messages.ts | 17 +++++-- src/global/actions/apiUpdaters/messages.ts | 2 +- src/global/helpers/messages.ts | 4 ++ src/global/selectors/messages.ts | 9 ++-- 6 files changed, 54 insertions(+), 25 deletions(-) diff --git a/src/api/gramjs/methods/messages.ts b/src/api/gramjs/methods/messages.ts index 34775b22d..38d500033 100644 --- a/src/api/gramjs/methods/messages.ts +++ b/src/api/gramjs/methods/messages.ts @@ -1319,22 +1319,34 @@ export async function forwardMessages({ await lastSendMessagePromise; - const update = await invokeRequest(new GramJs.messages.ForwardMessages({ - fromPeer: buildInputPeer(fromChat.id, fromChat.accessHash), - toPeer: buildInputPeer(toChat.id, toChat.accessHash), - randomId: randomIds, - id: messageIds, - withMyScore: withMyScore || undefined, - silent: isSilent || undefined, - dropAuthor: noAuthors || undefined, - dropMediaCaptions: noCaptions || undefined, - ...(toThreadId && { topMsgId: toThreadId }), - ...(scheduledAt && { scheduleDate: scheduledAt }), - ...(sendAs && { sendAs: buildInputPeer(sendAs.id, sendAs.accessHash) }), - }), { - shouldIgnoreUpdates: true, - }); - if (update) handleMultipleLocalMessagesUpdate(localMessages, update); + try { + const update = await invokeRequest(new GramJs.messages.ForwardMessages({ + fromPeer: buildInputPeer(fromChat.id, fromChat.accessHash), + toPeer: buildInputPeer(toChat.id, toChat.accessHash), + randomId: randomIds, + id: messageIds, + withMyScore: withMyScore || undefined, + silent: isSilent || undefined, + dropAuthor: noAuthors || undefined, + dropMediaCaptions: noCaptions || undefined, + ...(toThreadId && { topMsgId: toThreadId }), + ...(scheduledAt && { scheduleDate: scheduledAt }), + ...(sendAs && { sendAs: buildInputPeer(sendAs.id, sendAs.accessHash) }), + }), { + shouldThrow: true, + shouldIgnoreUpdates: true, + }); + if (update) handleMultipleLocalMessagesUpdate(localMessages, update); + } catch (error: any) { + Object.values(localMessages).forEach((localMessage) => { + onUpdate({ + '@type': 'updateMessageSendFailed', + chatId: toChat.id, + localId: localMessage.id, + error: error.message, + }); + }); + } } export async function findFirstMessageIdAfterDate({ diff --git a/src/components/middle/message/ContextMenuContainer.tsx b/src/components/middle/message/ContextMenuContainer.tsx index 4028e9c2f..f4c04e04a 100644 --- a/src/components/middle/message/ContextMenuContainer.tsx +++ b/src/components/middle/message/ContextMenuContainer.tsx @@ -611,7 +611,8 @@ export default memo(withGlobal( const isChannel = chat && isChatChannel(chat); const isLocal = isMessageLocal(message); const isServiceNotification = isServiceNotificationMessage(message); - const canShowSeenBy = Boolean(chat + const canShowSeenBy = Boolean(!isLocal + && chat && seenByMaxChatMembers && seenByExpiresAt && isChatGroup(chat) diff --git a/src/global/actions/api/messages.ts b/src/global/actions/api/messages.ts index 98324bd41..034dc4bb1 100644 --- a/src/global/actions/api/messages.ts +++ b/src/global/actions/api/messages.ts @@ -96,8 +96,8 @@ import { import { debounce, onTickEnd, rafPromise } from '../../../util/schedulers'; import { getMessageOriginalId, - getUserFullName, - isDeletedUser, + getUserFullName, isChatChannel, + isDeletedUser, isMessageLocal, isServiceNotificationMessage, isUserBot, } from '../../helpers'; @@ -105,6 +105,7 @@ import { translate } from '../../../util/langProvider'; import { ensureProtocol } from '../../../util/ensureProtocol'; import { updateTabState } from '../../reducers/tabs'; import { getCurrentTabId } from '../../../util/establishMultitabRole'; +import { deleteMessages } from '../apiUpdaters/messages'; const AUTOLOGIN_TOKEN_KEY = 'autologin_token'; @@ -484,8 +485,18 @@ addActionHandler('deleteMessages', (global, actions, payload): ActionReturnType } const { chatId, threadId } = currentMessageList; const chat = selectChat(global, chatId)!; + const messageIdsToDelete = messageIds.filter((id) => { + const message = selectChatMessage(global, chatId, id); + return message && !isMessageLocal(message); + }); - void callApi('deleteMessages', { chat, messageIds, shouldDeleteForAll }); + // Only local messages + if (!messageIdsToDelete.length && messageIds.length) { + deleteMessages(global, isChatChannel(chat) ? chatId : undefined, messageIds, actions); + return; + } + + void callApi('deleteMessages', { chat, messageIds: messageIdsToDelete, shouldDeleteForAll }); const editingId = selectEditingId(global, chatId, threadId); if (editingId && messageIds.includes(editingId)) { diff --git a/src/global/actions/apiUpdaters/messages.ts b/src/global/actions/apiUpdaters/messages.ts index a0462bfcd..2fbdc727a 100644 --- a/src/global/actions/apiUpdaters/messages.ts +++ b/src/global/actions/apiUpdaters/messages.ts @@ -894,7 +894,7 @@ function findLastMessage(global: T, chatId: string) { return undefined; } -function deleteMessages( +export function deleteMessages( global: T, chatId: string | undefined, ids: number[], actions: RequiredGlobalActions, ) { // Channel update diff --git a/src/global/helpers/messages.ts b/src/global/helpers/messages.ts index 62da57b36..10bb27885 100644 --- a/src/global/helpers/messages.ts +++ b/src/global/helpers/messages.ts @@ -197,6 +197,10 @@ export function isMessageLocal(message: ApiMessage) { return isLocalMessageId(message.id); } +export function isMessageFailed(message: ApiMessage) { + return message.sendingState === 'messageSendingStateFailed'; +} + export function isLocalMessageId(id: number) { return !Number.isInteger(id); } diff --git a/src/global/selectors/messages.ts b/src/global/selectors/messages.ts index 2e0e398f6..3f3f92b49 100644 --- a/src/global/selectors/messages.ts +++ b/src/global/selectors/messages.ts @@ -50,7 +50,7 @@ import { isUserRightBanned, canSendReaction, getAllowedAttachmentOptions, - isLocalMessageId, + isLocalMessageId, isMessageFailed, } from '../helpers'; import { findLast } from '../../util/iteratees'; import { selectIsStickerFavorite } from './symbols'; @@ -538,6 +538,7 @@ export function selectAllowedMessageActions(global: T, me const isChannel = isChatChannel(chat); const isBotChat = Boolean(selectBot(global, chat.id)); const isLocal = isMessageLocal(message); + const isFailed = isMessageFailed(message); const isServiceNotification = isServiceNotificationMessage(message); const isOwn = isOwnMessage(message); const isAction = isActionMessage(message); @@ -582,7 +583,7 @@ export function selectAllowedMessageActions(global: T, me canPin = !canUnpin; } - const canDelete = !isLocal && !isServiceNotification && ( + const canDelete = (!isLocal || isFailed) && !isServiceNotification && ( isPrivate || isOwn || isBasicGroup @@ -614,8 +615,8 @@ export function selectAllowedMessageActions(global: T, me const canFaveSticker = !isAction && hasSticker && !hasFavoriteSticker; const canUnfaveSticker = !isAction && hasFavoriteSticker; const canCopy = !isAction; - const canCopyLink = !isAction && (isChannel || isSuperGroup); - const canSelect = !isAction; + const canCopyLink = !isLocal && !isAction && (isChannel || isSuperGroup); + const canSelect = !isLocal && !isAction; const canDownload = Boolean(content.webPage?.document || content.webPage?.video || content.webPage?.photo || content.audio || content.voice || content.photo || content.video || content.document || content.sticker);