@@ -109,6 +109,7 @@ import {isBackendError, isQualifiedUserClientEntityMap} from 'Util/TypePredicate
109109import { BackendErrorLabel } from '@wireapp/api-client/src/http' ;
110110import { Config } from '../Config' ;
111111import { Core } from '../service/CoreSingleton' ;
112+ import { OtrMessage } from '@wireapp/core/src/main/conversation/message/OtrMessage' ;
112113
113114type ConversationEvent = { conversation : string ; id ?: string } ;
114115type 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 } '` ,
0 commit comments