diff --git a/ts/components/conversation/header/ConversationHeaderSelectionOverlay.tsx b/ts/components/conversation/header/ConversationHeaderSelectionOverlay.tsx index deb3fcf9d..66032e816 100644 --- a/ts/components/conversation/header/ConversationHeaderSelectionOverlay.tsx +++ b/ts/components/conversation/header/ConversationHeaderSelectionOverlay.tsx @@ -3,11 +3,7 @@ import React from 'react'; import { useDispatch, useSelector } from 'react-redux'; import useKey from 'react-use/lib/useKey'; -import { - deleteMessagesById, - deleteMessagesByIdForEveryone, - deleteMessagesForX, -} from '../../../interactions/conversations/unsendingInteractions'; +import { deleteMessagesForX } from '../../../interactions/conversations/unsendingInteractions'; import { resetSelectedMessageIds } from '../../../state/ducks/conversations'; import { getSelectedMessageIds } from '../../../state/selectors/conversations'; import { @@ -22,15 +18,6 @@ import { } from '../../basic/SessionButton'; import { SessionIconButton } from '../../icon'; -function onDeleteSelectedMessagesForEveryone( - selectedConversationKey: string, - selectedMessageIds: Array -) { - if (selectedConversationKey) { - void deleteMessagesByIdForEveryone(selectedMessageIds, selectedConversationKey); - } -} - export const SelectionOverlay = () => { const selectedMessageIds = useSelector(getSelectedMessageIds); const selectedConversationKey = useSelectedConversationKey(); @@ -73,7 +60,11 @@ export const SelectionOverlay = () => { } ); - const isOnlyServerDeletable = isPublic; + // `enforceDeleteServerSide` should check for message statuses too, but when we have multiple selected, + // some might be sent and some in an error state. We default to trying to delete all of them server side first, + // which might fail. If that fails, the user will need to do a delete for all the ones sent already, and a manual delete + // for each ones which is in an error state. + const enforceDeleteServerSide = isPublic; const classNameAndId = 'message-selection-overlay'; @@ -90,16 +81,13 @@ export const SelectionOverlay = () => { buttonShape={SessionButtonShape.Square} buttonType={SessionButtonType.Solid} text={window.i18n('delete')} - onClick={() => { + onClick={async () => { if (selectedConversationKey) { - if (isOnlyServerDeletable) { - void onDeleteSelectedMessagesForEveryone( - selectedConversationKey, - selectedMessageIds - ); - } else { - void deleteMessagesById(selectedMessageIds, selectedConversationKey); - } + await deleteMessagesForX( + selectedMessageIds, + selectedConversationKey, + enforceDeleteServerSide + ); } }} /> diff --git a/ts/components/conversation/message/message-content/MessageContextMenu.tsx b/ts/components/conversation/message/message-content/MessageContextMenu.tsx index 78f46450b..d8112c676 100644 --- a/ts/components/conversation/message/message-content/MessageContextMenu.tsx +++ b/ts/components/conversation/message/message-content/MessageContextMenu.tsx @@ -91,12 +91,15 @@ const DeleteItem = ({ messageId }: { messageId: string }) => { const isDeletable = useMessageIsDeletable(messageId); const isDeletableForEveryone = useMessageIsDeletableForEveryone(messageId); + const messageStatus = useMessageStatus(messageId); + + const enforceDeleteServerSide = isPublic && messageStatus !== 'error'; const onDelete = useCallback(() => { if (convoId) { - void deleteMessagesForX([messageId], convoId, isPublic); + void deleteMessagesForX([messageId], convoId, enforceDeleteServerSide); } - }, [convoId, isPublic, messageId]); + }, [convoId, enforceDeleteServerSide, messageId]); if (!convoId || (isPublic && !isDeletableForEveryone) || (!isPublic && !isDeletable)) { return null; diff --git a/ts/interactions/conversations/unsendingInteractions.ts b/ts/interactions/conversations/unsendingInteractions.ts index 16e33e1a7..828c05903 100644 --- a/ts/interactions/conversations/unsendingInteractions.ts +++ b/ts/interactions/conversations/unsendingInteractions.ts @@ -303,7 +303,7 @@ const doDeleteSelectedMessages = async ({ } const isAllOurs = selectedMessages.every(message => ourDevicePubkey === message.getSource()); - if (conversation.isPublic()) { + if (conversation.isPublic() && deleteForEveryone) { await doDeleteSelectedMessagesInSOGS(selectedMessages, conversation, isAllOurs); return; } @@ -341,14 +341,14 @@ const doDeleteSelectedMessages = async ({ export async function deleteMessagesForX( messageIds: Array, conversationId: string, - isPublic: boolean + /** should only be enforced for messages successfully sent on communities */ + enforceDeleteServerSide: boolean ) { if (conversationId) { - if (!isPublic) { - void deleteMessagesById(messageIds, conversationId); - } - if (isPublic) { - void deleteMessagesByIdForEveryone(messageIds, conversationId); + if (enforceDeleteServerSide) { + await deleteMessagesByIdForEveryone(messageIds, conversationId); + } else { + await deleteMessagesById(messageIds, conversationId); } } }