From 7c86f02c7ea48fad9bdf65d317cabe81f22e10a6 Mon Sep 17 00:00:00 2001 From: Scott Nonnenberg Date: Wed, 14 Dec 2022 14:45:39 -0800 Subject: [PATCH] ConversationView: Move deleteMessage to redux --- ts/background.ts | 16 ++++++- .../conversation/TimelineMessage.tsx | 28 +++++++++++- ts/state/ducks/conversations.ts | 43 ++++++++++++++++++- ts/state/smart/Timeline.tsx | 1 - ts/views/conversation_view.tsx | 33 +------------- 5 files changed, 83 insertions(+), 38 deletions(-) diff --git a/ts/background.ts b/ts/background.ts index a83761851a..8c11d7b6da 100644 --- a/ts/background.ts +++ b/ts/background.ts @@ -1677,10 +1677,22 @@ export async function startApp(): Promise { const { selectedMessage } = state.conversations; if (selectedMessage) { - conversation.trigger('delete-message', selectedMessage); - event.preventDefault(); event.stopPropagation(); + + window.showConfirmationDialog({ + dialogName: 'deleteMessage', + confirmStyle: 'negative', + message: window.i18n('deleteWarning'), + okText: window.i18n('delete'), + resolve: () => { + window.reduxActions.conversations.deleteMessage({ + conversationId: conversation.id, + messageId: selectedMessage, + }); + }, + }); + return; } } diff --git a/ts/components/conversation/TimelineMessage.tsx b/ts/components/conversation/TimelineMessage.tsx index d6f04af439..9e869880e4 100644 --- a/ts/components/conversation/TimelineMessage.tsx +++ b/ts/components/conversation/TimelineMessage.tsx @@ -39,7 +39,10 @@ export type PropsData = { } & Omit; export type PropsActions = { - deleteMessage: (id: string) => void; + deleteMessage: (options: { + conversationId: string; + messageId: string; + }) => void; deleteMessageForEveryone: (id: string) => void; toggleForwardMessageModal: (id: string) => void; reactToMessage: ( @@ -233,6 +236,7 @@ export function TimelineMessage(props: Props): JSX.Element { const handleReact = canReact ? () => toggleReactionPicker() : undefined; const [hasDOEConfirmation, setHasDOEConfirmation] = useState(false); + const [hasDeleteConfirmation, setHasDeleteConfirmation] = useState(false); const toggleReactionPickerKeyboard = useToggleReactionPicker( handleReact || noop @@ -266,6 +270,26 @@ export function TimelineMessage(props: Props): JSX.Element { {i18n('deleteForEveryoneWarning')} )} + {hasDeleteConfirmation && ( + + deleteMessage({ + conversationId, + messageId: id, + }), + style: 'negative', + text: i18n('delete'), + }, + ]} + dialogName="TimelineMessage/deleteMessage" + i18n={i18n} + onClose={() => setHasDeleteConfirmation(false)} + > + {i18n('deleteWarning')} + + )} toggleForwardMessageModal(id) : undefined} - onDeleteForMe={() => deleteMessage(id)} + onDeleteForMe={() => setHasDeleteConfirmation(true)} onDeleteForEveryone={ canDeleteForEveryone ? () => setHasDOEConfirmation(true) : undefined } diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index b94f8d88b5..b039b6ae84 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -101,7 +101,7 @@ import { missingCaseError } from '../../util/missingCaseError'; import { viewedReceiptsJobQueue } from '../../jobs/viewedReceiptsJobQueue'; import { viewSyncJobQueue } from '../../jobs/viewSyncJobQueue'; import { ReadStatus } from '../../messages/MessageReadStatus'; -import { isIncoming } from '../selectors/message'; +import { isIncoming, isOutgoing } from '../selectors/message'; import { sendDeleteForEveryoneMessage } from '../../util/sendDeleteForEveryoneMessage'; import type { ShowToastActionType } from './toast'; import { SHOW_TOAST, ToastType } from './toast'; @@ -882,6 +882,7 @@ export const actions = { deleteAvatarFromDisk, deleteConversation, deleteMessageForEveryone, + deleteMessage, destroyMessages, discardMessages, doubleCheckMissingQuoteReference, @@ -1211,6 +1212,46 @@ function setPinned( }; } +function deleteMessage({ + conversationId, + messageId, +}: { + conversationId: string; + messageId: string; +}): ThunkAction { + return async (dispatch, getState) => { + const message = await getMessageById(messageId); + if (!message) { + throw new Error(`deleteMessage: Message ${messageId} missing!`); + } + + const conversation = window.ConversationController.get(conversationId); + if (!conversation) { + throw new Error('deleteMessage: No conversation found'); + } + + const messageConversationId = message.get('conversationId'); + if (conversationId !== messageConversationId) { + throw new Error( + `deleteMessage: message conversation ${messageConversationId} doesn't match provided conversation ${conversationId}` + ); + } + + window.Signal.Data.removeMessage(messageId); + if (isOutgoing(message.attributes)) { + conversation.decrementSentMessageCount(); + } else { + conversation.decrementMessageCount(); + } + popPanelForConversation(conversationId)(dispatch, getState, undefined); + + dispatch({ + type: 'NOOP', + payload: null, + }); + }; +} + function destroyMessages( conversationId: string ): ThunkAction { diff --git a/ts/state/smart/Timeline.tsx b/ts/state/smart/Timeline.tsx index 0ce81b87da..1e31a381eb 100644 --- a/ts/state/smart/Timeline.tsx +++ b/ts/state/smart/Timeline.tsx @@ -65,7 +65,6 @@ export type TimelinePropsType = ExternalProps & | 'acknowledgeGroupMemberNameCollisions' | 'contactSupport' | 'blockGroupLinkRequests' - | 'deleteMessage' | 'downloadNewVersion' | 'kickOffAttachmentDownload' | 'learnMoreAboutDeliveryIssue' diff --git a/ts/views/conversation_view.tsx b/ts/views/conversation_view.tsx index 4f2f213cc1..9c1b198322 100644 --- a/ts/views/conversation_view.tsx +++ b/ts/views/conversation_view.tsx @@ -20,7 +20,7 @@ import { enqueueReactionForSend } from '../reactions/enqueueReactionForSend'; import type { GroupNameCollisionsWithIdsByTitle } from '../util/groupMemberNameCollisions'; import { isGroup } from '../util/whatTypeOfConversation'; import { getPreferredBadgeSelector } from '../state/selectors/badges'; -import { isIncoming, isOutgoing } from '../state/selectors/message'; +import { isIncoming } from '../state/selectors/message'; import { getActiveCallState } from '../state/selectors/calling'; import { getTheme } from '../state/selectors/user'; import { ReactWrapperView } from './ReactWrapperView'; @@ -73,7 +73,6 @@ const { getAbsoluteAttachmentPath, upgradeMessageSchema } = const { getMessagesBySentAt } = window.Signal.Data; type MessageActionsType = { - deleteMessage: (messageId: string) => unknown; downloadNewVersion: () => unknown; kickOffAttachmentDownload: ( options: Readonly<{ messageId: string }> @@ -147,7 +146,6 @@ export class ConversationView extends window.Backbone.View { window.reduxActions.conversations.popPanelForConversation(this.model.id); }); this.listenTo(this.model, 'show-message-details', this.showMessageDetail); - this.listenTo(this.model, 'delete-message', this.deleteMessage); this.listenTo(this.model, 'pushPanel', this.pushPanel); this.listenTo(this.model, 'popPanel', this.popPanel); @@ -410,9 +408,6 @@ export class ConversationView extends window.Backbone.View { } }; const retrySend = retryMessageSend; - const deleteMessage = (messageId: string) => { - this.deleteMessage(messageId); - }; const showMessageDetail = (messageId: string) => { this.showMessageDetail(messageId); }; @@ -471,7 +466,6 @@ export class ConversationView extends window.Backbone.View { }; return { - deleteMessage, downloadNewVersion, kickOffAttachmentDownload, markAttachmentAsCorrupted, @@ -862,31 +856,6 @@ export class ConversationView extends window.Backbone.View { return view; } - deleteMessage(messageId: string): void { - const message = window.MessageController.getById(messageId); - if (!message) { - throw new Error(`deleteMessage: Message ${messageId} missing!`); - } - - window.showConfirmationDialog({ - dialogName: 'deleteMessage', - confirmStyle: 'negative', - message: window.i18n('deleteWarning'), - okText: window.i18n('delete'), - resolve: () => { - window.Signal.Data.removeMessage(message.id); - if (isOutgoing(message.attributes)) { - this.model.decrementSentMessageCount(); - } else { - this.model.decrementMessageCount(); - } - window.reduxActions.conversations.popPanelForConversation( - this.model.id - ); - }, - }); - } - showGroupLinkManagement(): void { window.reduxActions.conversations.pushPanelForConversation(this.model.id, { type: PanelType.GroupLinkManagement,