fix menu action for unsending messages

pull/1981/head
Audric Ackermann 3 years ago
parent 314b76388f
commit 5d9565a559
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -43,7 +43,7 @@ window.lokiFeatureFlags = {
useFileOnionRequestsV2: true, // more compact encoding of files in response useFileOnionRequestsV2: true, // more compact encoding of files in response
padOutgoingAttachments: true, padOutgoingAttachments: true,
enablePinConversations: true, enablePinConversations: true,
useCallMessage: true, useCallMessage: false,
}; };
window.isBeforeVersion = (toCheck, baseVersion) => { window.isBeforeVersion = (toCheck, baseVersion) => {

@ -32,7 +32,6 @@ async function unsendMessagesForEveryone(
} }
const unsendMsgObjects = getUnsendMessagesObjects(msgsToDelete); const unsendMsgObjects = getUnsendMessagesObjects(msgsToDelete);
let allDeleted = false;
if (conversation.isPrivate()) { if (conversation.isPrivate()) {
// sending to recipient all the messages separately for now // sending to recipient all the messages separately for now
await Promise.all( await Promise.all(
@ -49,7 +48,6 @@ async function unsendMessagesForEveryone(
.catch(window?.log?.error) .catch(window?.log?.error)
) )
); );
allDeleted = await deleteMessagesFromSwarmAndCompletelyLocally(conversation, msgsToDelete);
} else if (conversation.isClosedGroup()) { } else if (conversation.isClosedGroup()) {
// sending to recipient all the messages separately for now // sending to recipient all the messages separately for now
await Promise.all( await Promise.all(
@ -59,18 +57,11 @@ async function unsendMessagesForEveryone(
.catch(window?.log?.error) .catch(window?.log?.error)
) )
); );
allDeleted = await deleteMessagesFromSwarmAndCompletelyLocally(conversation, msgsToDelete);
return;
} }
await deleteMessagesFromSwarmAndCompletelyLocally(conversation, msgsToDelete);
window.inboxStore?.dispatch(resetSelectedMessageIds()); window.inboxStore?.dispatch(resetSelectedMessageIds());
if (allDeleted) { ToastUtils.pushDeleted();
ToastUtils.pushDeleted();
} else {
ToastUtils.someDeletionsFailed();
}
} }
function getUnsendMessagesObjects(messages: Array<MessageModel>) { function getUnsendMessagesObjects(messages: Array<MessageModel>) {
@ -119,7 +110,7 @@ export async function deleteMessagesFromSwarmOnly(messages: Array<MessageModel>)
* Delete the messages from the swarm with an unsend request and if it worked, delete those messages locally. * Delete the messages from the swarm with an unsend request and if it worked, delete those messages locally.
* If an error happened, we just return false, Toast an error, and do not remove the messages locally at all. * If an error happened, we just return false, Toast an error, and do not remove the messages locally at all.
*/ */
async function deleteMessagesFromSwarmAndCompletelyLocally( export async function deleteMessagesFromSwarmAndCompletelyLocally(
conversation: ConversationModel, conversation: ConversationModel,
messages: Array<MessageModel> messages: Array<MessageModel>
) { ) {
@ -128,14 +119,33 @@ async function deleteMessagesFromSwarmAndCompletelyLocally(
window.log.warn( window.log.warn(
'deleteMessagesFromSwarmAndCompletelyLocally: some messages failed to be deleted ' 'deleteMessagesFromSwarmAndCompletelyLocally: some messages failed to be deleted '
); );
return false;
} }
await Promise.all( await Promise.all(
messages.map(async message => { messages.map(async message => {
return deleteMessageLocallyOnly({ conversation, message, deletionType: 'complete' }); return deleteMessageLocallyOnly({ conversation, message, deletionType: 'complete' });
}) })
); );
return true; }
/**
* Delete the messages from the swarm with an unsend request and if it worked, mark those messages locally as deleted but do not remove them.
* If an error happened, we still mark the message locally as deleted.
*/
export async function deleteMessagesFromSwarmAndMarkAsDeletedLocally(
conversation: ConversationModel,
messages: Array<MessageModel>
) {
const deletedFromSwarm = await deleteMessagesFromSwarmOnly(messages);
if (!deletedFromSwarm) {
window.log.warn(
'deleteMessagesFromSwarmAndMarkAsDeletedLocally: some messages failed to be deleted but still removing the messages content... '
);
}
await Promise.all(
messages.map(async message => {
return deleteMessageLocallyOnly({ conversation, message, deletionType: 'markDeleted' });
})
);
} }
/** /**
@ -164,25 +174,32 @@ export async function deleteMessageLocallyOnly({
} }
/** /**
* Send an UnsendMessage synced message so our devices removes those messages locally,
* and send an unsend request on our swarm so this message is effectively removed.
* *
* Show a toast on error/success and reset the selection
*/ */
async function deleteJustForThisUser( async function unsendMessageJustForThisUser(
conversation: ConversationModel, conversation: ConversationModel,
msgsToDelete: Array<MessageModel> msgsToDelete: Array<MessageModel>
) { ) {
window?.log?.warn('Deleting messages just for this user'); window?.log?.warn('Deleting messages just for this user');
// is deleting on swarm sufficient or does it need to be unsent as well?
const deleteResult = await deleteMessagesFromSwarmAndCompletelyLocally( const unsendMsgObjects = getUnsendMessagesObjects(msgsToDelete);
conversation,
msgsToDelete // sending to recipient all the messages separately for now
await Promise.all(
unsendMsgObjects.map(unsendObject =>
getMessageQueue()
.sendSyncMessage(unsendObject)
.catch(window?.log?.error)
)
); );
await deleteMessagesFromSwarmAndCompletelyLocally(conversation, msgsToDelete);
// Update view and trigger update // Update view and trigger update
window.inboxStore?.dispatch(resetSelectedMessageIds()); window.inboxStore?.dispatch(resetSelectedMessageIds());
if (deleteResult) { ToastUtils.pushDeleted();
ToastUtils.pushDeleted();
} else {
ToastUtils.someDeletionsFailed();
}
} }
const doDeleteSelectedMessagesInSOGS = async ( const doDeleteSelectedMessagesInSOGS = async (
@ -233,11 +250,15 @@ const doDeleteSelectedMessagesInSOGS = async (
* *
* It does what needs to be done on a user action to delete messages for each conversation type * It does what needs to be done on a user action to delete messages for each conversation type
*/ */
const doDeleteSelectedMessages = async ( const doDeleteSelectedMessages = async ({
selectedMessages: Array<MessageModel>, conversation,
conversation: ConversationModel, selectedMessages,
shouldDeleteForEveryone: boolean deleteForEveryone,
) => { }: {
selectedMessages: Array<MessageModel>;
conversation: ConversationModel;
deleteForEveryone: boolean;
}) => {
const ourDevicePubkey = UserUtils.getOurPubKeyStrFromCache(); const ourDevicePubkey = UserUtils.getOurPubKeyStrFromCache();
if (!ourDevicePubkey) { if (!ourDevicePubkey) {
return; return;
@ -249,16 +270,16 @@ const doDeleteSelectedMessages = async (
} }
//#region deletion for 1-1 and closed groups //#region deletion for 1-1 and closed groups
if (!isAllOurs) {
ToastUtils.pushMessageDeleteForbidden();
window.inboxStore?.dispatch(resetSelectedMessageIds());
return;
}
if (shouldDeleteForEveryone) { if (deleteForEveryone) {
if (!isAllOurs) {
ToastUtils.pushMessageDeleteForbidden();
window.inboxStore?.dispatch(resetSelectedMessageIds());
return;
}
return unsendMessagesForEveryone(conversation, selectedMessages); return unsendMessagesForEveryone(conversation, selectedMessages);
} }
return deleteJustForThisUser(conversation, selectedMessages); return unsendMessageJustForThisUser(conversation, selectedMessages);
//#endregion //#endregion
}; };
@ -284,7 +305,7 @@ export async function deleteMessagesByIdForEveryone(
okText: window.i18n('deleteForEveryone'), okText: window.i18n('deleteForEveryone'),
okTheme: SessionButtonColor.Danger, okTheme: SessionButtonColor.Danger,
onClickOk: async () => { onClickOk: async () => {
await doDeleteSelectedMessages(selectedMessages, conversation, true); await doDeleteSelectedMessages({ selectedMessages, conversation, deleteForEveryone: true });
// explicity close modal for this case. // explicity close modal for this case.
window.inboxStore?.dispatch(updateConfirmModal(null)); window.inboxStore?.dispatch(updateConfirmModal(null));
@ -295,7 +316,6 @@ export async function deleteMessagesByIdForEveryone(
); );
} }
// tslint:disable-next-line: max-func-body-length
export async function deleteMessagesById(messageIds: Array<string>, conversationId: string) { export async function deleteMessagesById(messageIds: Array<string>, conversationId: string) {
const conversation = getConversationController().getOrThrow(conversationId); const conversation = getConversationController().getOrThrow(conversationId);
const selectedMessages = _.compact( const selectedMessages = _.compact(
@ -313,7 +333,12 @@ export async function deleteMessagesById(messageIds: Array<string>, conversation
okText: window.i18n('delete'), okText: window.i18n('delete'),
okTheme: SessionButtonColor.Danger, okTheme: SessionButtonColor.Danger,
onClickOk: async () => { onClickOk: async () => {
await doDeleteSelectedMessages(selectedMessages, conversation, false); await doDeleteSelectedMessages({
selectedMessages,
conversation,
deleteForEveryone: false,
});
window.inboxStore?.dispatch(updateConfirmModal(null));
}, },
closeAfterInput: false, closeAfterInput: false,
}) })

@ -20,8 +20,8 @@ import { getAllCachedECKeyPair } from './closedGroups';
import { getMessageBySenderAndTimestamp } from '../data/data'; import { getMessageBySenderAndTimestamp } from '../data/data';
import { handleCallMessage } from './callMessage'; import { handleCallMessage } from './callMessage';
import { import {
deleteMessageLocallyOnly, deleteMessagesFromSwarmAndCompletelyLocally,
deleteMessagesFromSwarmOnly, deleteMessagesFromSwarmAndMarkAsDeletedLocally,
} from '../interactions/conversations/unsendingInteractions'; } from '../interactions/conversations/unsendingInteractions';
export async function handleContentMessage(envelope: EnvelopePlus, messageHash?: string) { export async function handleContentMessage(envelope: EnvelopePlus, messageHash?: string) {
@ -499,21 +499,16 @@ async function handleTypingMessage(
* @param unsendMessage data required to delete message * @param unsendMessage data required to delete message
*/ */
async function handleUnsendMessage(envelope: EnvelopePlus, unsendMessage: SignalService.Unsend) { async function handleUnsendMessage(envelope: EnvelopePlus, unsendMessage: SignalService.Unsend) {
const { source: unsendSource } = envelope;
const { author: messageAuthor, timestamp } = unsendMessage; const { author: messageAuthor, timestamp } = unsendMessage;
await removeFromCache(envelope);
//#region early exit conditions //#region early exit conditions
if (!unsendMessage || !unsendSource) { if (!unsendMessage) {
window?.log?.error('UnsendMessageHandler:: Invalid parameters -- dropping message.'); window?.log?.error('handleUnsendMessage: Invalid parameters -- dropping message.');
} }
if (!timestamp) { if (!timestamp) {
window?.log?.error('UnsendMessageHander:: Invalid timestamp -- dropping message'); window?.log?.error('handleUnsendMessage: Invalid timestamp -- dropping message');
}
const conversation = getConversationController().get(unsendSource);
if (!conversation) {
return;
} }
const messageToDelete = await getMessageBySenderAndTimestamp({ const messageToDelete = await getMessageBySenderAndTimestamp({
source: messageAuthor, source: messageAuthor,
timestamp: Lodash.toNumber(timestamp), timestamp: Lodash.toNumber(timestamp),
@ -523,21 +518,22 @@ async function handleUnsendMessage(envelope: EnvelopePlus, unsendMessage: Signal
//#region executing deletion //#region executing deletion
if (messageHash && messageToDelete) { if (messageHash && messageToDelete) {
const wasDeleted = await deleteMessagesFromSwarmOnly([messageToDelete]); window.log.info('handleUnsendMessage: got a request to delete ', messageHash);
if (!wasDeleted) { const conversation = getConversationController().get(messageToDelete.get('conversationId'));
window.log.warn( if (!conversation) {
'handleUnsendMessage: got a request to delete ', await removeFromCache(envelope);
messageHash,
' but an error happened during deleting it from our swarm.' return;
); }
if (messageToDelete.getSource() === UserUtils.getOurPubKeyStrFromCache()) {
// a message we sent is completely removed when we get a unsend request
void deleteMessagesFromSwarmAndCompletelyLocally(conversation, [messageToDelete]);
} else {
void deleteMessagesFromSwarmAndMarkAsDeletedLocally(conversation, [messageToDelete]);
} }
// still, delete it locally
await deleteMessageLocallyOnly({
conversation,
message: messageToDelete,
deletionType: 'markDeleted',
});
} }
await removeFromCache(envelope);
//#endregion //#endregion
} }

@ -114,7 +114,11 @@ export class MessageQueue {
if (!message) { if (!message) {
return; return;
} }
if (!(message instanceof ConfigurationMessage) && !(message as any)?.syncTarget) { if (
!(message instanceof ConfigurationMessage) &&
!(message instanceof UnsendMessage) &&
!(message as any)?.syncTarget
) {
throw new Error('Invalid message given to sendSyncMessage'); throw new Error('Invalid message given to sendSyncMessage');
} }
@ -226,6 +230,7 @@ export class MessageQueue {
if ( if (
message instanceof ConfigurationMessage || message instanceof ConfigurationMessage ||
message instanceof ClosedGroupNewMessage || message instanceof ClosedGroupNewMessage ||
message instanceof UnsendMessage ||
(message as any).syncTarget?.length > 0 (message as any).syncTarget?.length > 0
) { ) {
window?.log?.warn('Processing sync message'); window?.log?.warn('Processing sync message');

@ -27,6 +27,7 @@ import { ExpirationTimerUpdateMessage } from '../messages/outgoing/controlMessag
import { getV2OpenGroupRoom } from '../../data/opengroups'; import { getV2OpenGroupRoom } from '../../data/opengroups';
import { getCompleteUrlFromRoom } from '../../opengroup/utils/OpenGroupUtils'; import { getCompleteUrlFromRoom } from '../../opengroup/utils/OpenGroupUtils';
import { DURATION } from '../constants'; import { DURATION } from '../constants';
import { UnsendMessage } from '../messages/outgoing/controlMessage/UnsendMessage';
const ITEM_ID_LAST_SYNC_TIMESTAMP = 'lastSyncedTimestamp'; const ITEM_ID_LAST_SYNC_TIMESTAMP = 'lastSyncedTimestamp';
@ -295,7 +296,11 @@ const buildSyncExpireTimerMessage = (
}); });
}; };
export type SyncMessageType = VisibleMessage | ExpirationTimerUpdateMessage | ConfigurationMessage; export type SyncMessageType =
| VisibleMessage
| ExpirationTimerUpdateMessage
| ConfigurationMessage
| UnsendMessage;
export const buildSyncMessage = ( export const buildSyncMessage = (
identifier: string, identifier: string,

Loading…
Cancel
Save