Skip to content

Commit 73e51a6

Browse files
author
Thomas Belin
authored
feat(core): Add edit, delete and quote to federated message sending (#12021)
1 parent aeddc84 commit 73e51a6

File tree

5 files changed

+92
-63
lines changed

5 files changed

+92
-63
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"dependencies": {
33
"@wireapp/antiscroll-2": "1.0.2",
44
"@wireapp/avs": "7.2.91",
5-
"@wireapp/core": "17.18.1",
5+
"@wireapp/core": "17.19.0",
66
"@wireapp/react-ui-kit": "7.54.0",
77
"@wireapp/store-engine-dexie": "1.6.7",
88
"@wireapp/store-engine-sqleet": "1.7.11",

src/script/components/message.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -216,15 +216,9 @@ class Message {
216216
const isRestrictedFileShare = !teamState.isFileSharingReceivingEnabled();
217217

218218
const canDelete =
219-
messageEntity.user().isMe &&
220-
!this.conversation().removed_from_conversation() &&
221-
messageEntity.isDeletable() &&
222-
!this.conversation().isFederated();
223-
224-
const canEdit =
225-
messageEntity.isEditable() &&
226-
!this.conversation().removed_from_conversation() &&
227-
!this.conversation().isFederated();
219+
messageEntity.user().isMe && !this.conversation().removed_from_conversation() && messageEntity.isDeletable();
220+
221+
const canEdit = messageEntity.isEditable() && !this.conversation().removed_from_conversation();
228222

229223
const hasDetails =
230224
!this.conversation().is1to1() &&

src/script/conversation/MessageRepository.ts

Lines changed: 83 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ import {isBackendError, isQualifiedUserClientEntityMap} from 'Util/TypePredicate
109109
import {BackendErrorLabel} from '@wireapp/api-client/src/http';
110110
import {Config} from '../Config';
111111
import {Core} from '../service/CoreSingleton';
112+
import {OtrMessage} from '@wireapp/core/src/main/conversation/message/OtrMessage';
112113

113114
type ConversationEvent = {conversation: string; id?: string};
114115
type EventJson = any;
@@ -254,16 +255,56 @@ export class MessageRepository {
254255
* @see https://github.com/wireapp/wire-docs/tree/master/src/understand/federation
255256
* @see https://docs.wire.com/understand/federation/index.html
256257
*/
257-
async sendFederatedMessage(conversation: Conversation, message: string): Promise<void> {
258-
const userIds: string[] | QualifiedId[] = conversation.domain
259-
? conversation.allUserEntities.map(user => user.qualifiedId)
260-
: conversation.allUserEntities.map(user => user.id);
258+
private async sendFederatedMessage(
259+
conversation: Conversation,
260+
message: string,
261+
mentions: MentionEntity[],
262+
quote?: QuoteEntity,
263+
): Promise<void> {
264+
const quoteData = quote && {quotedMessageId: quote.messageId, quotedMessageSha256: new Uint8Array(quote.hash)};
261265

262266
const textPayload = this.core
263267
.service!.conversation.messageBuilder.createText({conversationId: conversation.id, text: message})
268+
.withMentions(
269+
mentions.map(mention => ({length: mention.length, start: mention.startIndex, userId: mention.userId})),
270+
)
271+
.withReadConfirmation(this.expectReadReceipt(conversation))
272+
.withQuote(quoteData)
273+
.build();
274+
275+
return this.sendAndInjectGenericCoreMessage(textPayload, conversation);
276+
}
277+
278+
private async sendFederatedEditMessage(
279+
conversation: Conversation,
280+
message: string,
281+
originalMessageEntity: ContentMessage,
282+
mentions: MentionEntity[],
283+
) {
284+
const textPayload = this.core
285+
.service!.conversation.messageBuilder.createEditedText({
286+
conversationId: conversation.id,
287+
newMessageText: message,
288+
originalMessageId: originalMessageEntity.id,
289+
})
290+
.withMentions(
291+
mentions.map(mention => ({length: mention.length, start: mention.startIndex, userId: mention.userId})),
292+
)
293+
.withReadConfirmation(this.expectReadReceipt(conversation))
264294
.build();
265295

266-
return this.sendAndInjectGenericCoreMessage(textPayload, userIds, conversation);
296+
return this.sendAndInjectGenericCoreMessage(textPayload, conversation);
297+
}
298+
299+
private async deleteFederatedMessageForEveryone(conversation: Conversation, message: Message, precondition?: any) {
300+
const userIds = conversation.allUserEntities.map(user => user.qualifiedId);
301+
this.core.service!.conversation.deleteMessageEveryone(
302+
conversation.id,
303+
message.id,
304+
userIds,
305+
true,
306+
conversation.domain,
307+
);
267308
}
268309

269310
/**
@@ -280,17 +321,19 @@ export class MessageRepository {
280321
textMessage: string,
281322
mentionEntities: MentionEntity[],
282323
quoteEntity?: QuoteEntity,
283-
): Promise<ConversationEvent | undefined> {
324+
): Promise<void> {
284325
try {
326+
if (conversationEntity.isFederated()) {
327+
return await this.sendFederatedMessage(conversationEntity, textMessage, mentionEntities, quoteEntity);
328+
}
285329
const genericMessage = await this.sendText(conversationEntity, textMessage, mentionEntities, quoteEntity);
286-
return await this.sendLinkPreview(conversationEntity, textMessage, genericMessage, mentionEntities, quoteEntity);
330+
await this.sendLinkPreview(conversationEntity, textMessage, genericMessage, mentionEntities, quoteEntity);
287331
} catch (error) {
288332
if (!this.isUserCancellationError(error)) {
289333
this.logger.error(`Error while sending text message: ${error.message}`, error);
290334
throw error;
291335
}
292336
}
293-
return undefined;
294337
}
295338

296339
/**
@@ -307,7 +350,7 @@ export class MessageRepository {
307350
textMessage: string,
308351
originalMessageEntity: ContentMessage,
309352
mentionEntities: MentionEntity[],
310-
): Promise<ConversationEvent | undefined> {
353+
): Promise<void> {
311354
const hasDifferentText = isTextDifferent(originalMessageEntity, textMessage);
312355
const hasDifferentMentions = areMentionsDifferent(originalMessageEntity, mentionEntities);
313356
const wasEdited = hasDifferentText || hasDifferentMentions;
@@ -318,6 +361,9 @@ export class MessageRepository {
318361
ConversationError.MESSAGE.NO_MESSAGE_CHANGES,
319362
);
320363
}
364+
if (conversationEntity.isFederated()) {
365+
return this.sendFederatedEditMessage(conversationEntity, textMessage, originalMessageEntity, mentionEntities);
366+
}
321367

322368
const messageId = createRandomUuid();
323369

@@ -338,14 +384,13 @@ export class MessageRepository {
338384

339385
try {
340386
await this._sendAndInjectGenericMessage(conversationEntity, genericMessage, false);
341-
return await this.sendLinkPreview(conversationEntity, textMessage, genericMessage, mentionEntities);
387+
await this.sendLinkPreview(conversationEntity, textMessage, genericMessage, mentionEntities);
342388
} catch (error) {
343389
if (!this.isUserCancellationError(error)) {
344390
this.logger.error(`Error while editing message: ${error.message}`, error);
345391
throw error;
346392
}
347393
}
348-
return undefined;
349394
}
350395

351396
/**
@@ -733,11 +778,9 @@ export class MessageRepository {
733778
return errorTypes.includes(error.type);
734779
}
735780

736-
private async sendAndInjectGenericCoreMessage(
737-
payload: any,
738-
userIds: string[] | QualifiedId[],
739-
conversation: Conversation,
740-
) {
781+
private async sendAndInjectGenericCoreMessage(payload: OtrMessage, conversation: Conversation) {
782+
const users = conversation.allUserEntities;
783+
const userIds = conversation.isFederated() ? users.map(user => user.qualifiedId) : users.map(user => user.id);
741784
const injectOptimisticEvent: MessageSendingCallbacks['onStart'] = genericMessage => {
742785
const senderId = this.clientState.currentClient().id;
743786
const currentTimestamp = this.serverTimeHandler.toServerTimestamp();
@@ -753,7 +796,7 @@ export class MessageRepository {
753796

754797
await this.core.service!.conversation.send({
755798
callbacks: {onStart: injectOptimisticEvent, onSuccess: updateOptimisticEvent},
756-
conversationDomain: conversation.domain,
799+
conversationDomain: conversation.isFederated() ? conversation.domain : undefined,
757800
payloadBundle: payload,
758801
userIds,
759802
});
@@ -1014,34 +1057,39 @@ export class MessageRepository {
10141057
conversationEntity: Conversation,
10151058
messageEntity: Message,
10161059
precondition?: string[] | boolean,
1017-
): Promise<number> {
1060+
): Promise<void> {
10181061
const conversationId = conversationEntity.id;
10191062
const messageId = messageEntity.id;
10201063

10211064
try {
10221065
if (!messageEntity.user().isMe && !messageEntity.ephemeral_expires()) {
10231066
throw new ConversationError(ConversationError.TYPE.WRONG_USER, ConversationError.MESSAGE.WRONG_USER);
10241067
}
1025-
1026-
const protoMessageDelete = new MessageDelete({messageId});
1027-
const genericMessage = new GenericMessage({
1028-
[GENERIC_MESSAGE_TYPE.DELETED]: protoMessageDelete,
1029-
messageId: createRandomUuid(),
1030-
});
1031-
await this.messageSender.queueMessage(() => {
1032-
const userIds = Array.isArray(precondition) ? precondition : undefined;
1033-
return this.createRecipients(conversationEntity, false, userIds).then(recipients => {
1034-
const options = {precondition, recipients};
1035-
const eventInfoEntity = new EventInfoEntity(genericMessage, conversationEntity.qualifiedId, options);
1036-
this.sendGenericMessage(eventInfoEntity, true);
1068+
if (conversationEntity.isFederated()) {
1069+
await this.deleteFederatedMessageForEveryone(conversationEntity, messageEntity, precondition);
1070+
} else {
1071+
const protoMessageDelete = new MessageDelete({messageId});
1072+
const genericMessage = new GenericMessage({
1073+
[GENERIC_MESSAGE_TYPE.DELETED]: protoMessageDelete,
1074+
messageId: createRandomUuid(),
10371075
});
1038-
});
1039-
return await this.deleteMessageById(conversationEntity, messageId);
1076+
await this.messageSender.queueMessage(() => {
1077+
const userIds = Array.isArray(precondition) ? precondition : undefined;
1078+
return this.createRecipients(conversationEntity, false, userIds).then(recipients => {
1079+
const options = {precondition, recipients};
1080+
const eventInfoEntity = new EventInfoEntity(genericMessage, conversationEntity.qualifiedId, options);
1081+
this.sendGenericMessage(eventInfoEntity, true);
1082+
});
1083+
});
1084+
}
1085+
1086+
await this.deleteMessageById(conversationEntity, messageId);
10401087
} catch (error) {
10411088
const isConversationNotFound = error.code === HTTP_STATUS.NOT_FOUND;
10421089
if (isConversationNotFound) {
10431090
this.logger.warn(`Conversation '${conversationId}' not found. Deleting message for self user only.`);
1044-
return this.deleteMessage(conversationEntity, messageEntity);
1091+
this.deleteMessage(conversationEntity, messageEntity);
1092+
return;
10451093
}
10461094
const message = `Failed to delete message '${messageId}' in conversation '${conversationId}' for everyone`;
10471095
this.logger.info(message, error);
@@ -1056,7 +1104,7 @@ export class MessageRepository {
10561104
* @param messageEntity Message to delete
10571105
* @returns Resolves when message was deleted
10581106
*/
1059-
public async deleteMessage(conversationEntity: Conversation, messageEntity: Message): Promise<number> {
1107+
public async deleteMessage(conversationEntity: Conversation, messageEntity: Message): Promise<void> {
10601108
try {
10611109
const protoMessageHide = new MessageHide({
10621110
conversationId: conversationEntity.id,
@@ -1072,7 +1120,7 @@ export class MessageRepository {
10721120
this.conversationState.self_conversation()?.qualifiedId,
10731121
);
10741122
await this.sendGenericMessageToConversation(eventInfoEntity);
1075-
return await this.deleteMessageById(conversationEntity, messageEntity.id);
1123+
await this.deleteMessageById(conversationEntity, messageEntity.id);
10761124
} catch (error) {
10771125
this.logger.info(
10781126
`Failed to send delete message with id '${messageEntity.id}' for conversation '${conversationEntity.id}'`,

src/script/view_model/content/InputBarViewModel.ts

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -636,8 +636,6 @@ export class InputBarViewModel {
636636

637637
if (this.isEditing()) {
638638
this.sendMessageEdit(messageText, this.editMessageEntity());
639-
} else if (this.disableControls()) {
640-
this.sendFederatedMessage(messageText);
641639
} else {
642640
this.sendMessage(messageText, this.replyMessageEntity());
643641
}
@@ -653,9 +651,7 @@ export class InputBarViewModel {
653651
switch (keyboardEvent.key) {
654652
case KEY.ARROW_UP: {
655653
if (!isFunctionKey(keyboardEvent) && !this.input().length) {
656-
if (!this.conversationEntity()?.isFederated()) {
657-
this.editMessage(this.conversationEntity().getLastEditableMessage() as ContentMessage);
658-
}
654+
this.editMessage(this.conversationEntity().getLastEditableMessage() as ContentMessage);
659655
this.updateMentions(data, keyboardEvent);
660656
}
661657
break;
@@ -837,15 +833,6 @@ export class InputBarViewModel {
837833
});
838834
};
839835

840-
readonly sendFederatedMessage = (messageText: string): void => {
841-
if (!messageText.length) {
842-
return;
843-
}
844-
845-
this.messageRepository.sendFederatedMessage(this.conversationEntity(), messageText);
846-
this.cancelMessageReply();
847-
};
848-
849836
readonly sendMessage = (messageText: string, replyMessageEntity: ContentMessage): void => {
850837
if (!messageText.length) {
851838
return;

yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2964,10 +2964,10 @@
29642964
logdown "3.3.1"
29652965
rimraf "3.0.2"
29662966

2967-
"@wireapp/core@17.18.1":
2968-
version "17.18.1"
2969-
resolved "https://registry.yarnpkg.com/@wireapp/core/-/core-17.18.1.tgz#3e0fd6ef7704d7e4d137f096a585d9b42646aaf6"
2970-
integrity sha512-MqqIM5ymBM7xRtoo54YFxuhElHC07tT4iRCf+Pg3V4QaF8vV1VyBj1WZQ2eamhpOWUdhyj3za0ZsosVkAb83fw==
2967+
"@wireapp/core@17.19.0":
2968+
version "17.19.0"
2969+
resolved "https://registry.yarnpkg.com/@wireapp/core/-/core-17.19.0.tgz#82f56b391dc1f33e071acdb7234b7ac01787ac23"
2970+
integrity sha512-/8cvv2NiYlgA0u2LyeDbXhvW/Ya1b7yPHF/eebBAbPVc/p4caFeSuxMPr+O7QdhTXXwFRZh8/pBfZ0XX/J2eGg==
29712971
dependencies:
29722972
"@types/long" "4.0.1"
29732973
"@types/node" "~14"

0 commit comments

Comments
 (0)