diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt index de9bcfbf0d..7bd6337548 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt @@ -21,6 +21,7 @@ import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.room.model.message.MessageType import org.matrix.android.sdk.api.session.room.model.message.PollType +import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.util.Cancelable @@ -81,13 +82,15 @@ interface SendService { * @param roomIds set of roomIds to where the media will be sent. The current roomId will be add to this set if not present. * It can be useful to send media to multiple room. It's safe to include the current roomId in this set * @param rootThreadEventId when this param is not null, the Media will be sent in this specific thread + * @param relatesTo add a relation content to the media event * @return a [Cancelable] */ fun sendMedia( attachment: ContentAttachmentData, compressBeforeSending: Boolean, roomIds: Set, - rootThreadEventId: String? = null + rootThreadEventId: String? = null, + relatesTo: RelationDefaultContent? = null ): Cancelable /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt index a3f2825a0c..aa305e6067 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt @@ -39,6 +39,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageVideoContent import org.matrix.android.sdk.api.session.room.model.message.MessageWithAttachmentContent import org.matrix.android.sdk.api.session.room.model.message.PollType import org.matrix.android.sdk.api.session.room.model.message.getFileUrl +import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent import org.matrix.android.sdk.api.session.room.send.SendService import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent @@ -280,7 +281,8 @@ internal class DefaultSendService @AssistedInject constructor( attachment: ContentAttachmentData, compressBeforeSending: Boolean, roomIds: Set, - rootThreadEventId: String? + rootThreadEventId: String?, + relatesTo: RelationDefaultContent?, ): Cancelable { // Ensure that the event will not be send in a thread if we are a different flow. // Like sending files to multiple rooms @@ -295,7 +297,8 @@ internal class DefaultSendService @AssistedInject constructor( localEchoEventFactory.createMediaEvent( roomId = it, attachment = attachment, - rootThreadEventId = rootThreadId + rootThreadEventId = rootThreadId, + relatesTo, ).also { event -> createLocalEcho(event) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt index afff51a4a5..0fb2c9506a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt @@ -347,14 +347,21 @@ internal class LocalEchoEventFactory @Inject constructor( fun createMediaEvent( roomId: String, attachment: ContentAttachmentData, - rootThreadEventId: String? + rootThreadEventId: String?, + relatesTo: RelationDefaultContent?, ): Event { return when (attachment.type) { - ContentAttachmentData.Type.IMAGE -> createImageEvent(roomId, attachment, rootThreadEventId) - ContentAttachmentData.Type.VIDEO -> createVideoEvent(roomId, attachment, rootThreadEventId) - ContentAttachmentData.Type.AUDIO -> createAudioEvent(roomId, attachment, isVoiceMessage = false, rootThreadEventId = rootThreadEventId) - ContentAttachmentData.Type.VOICE_MESSAGE -> createAudioEvent(roomId, attachment, isVoiceMessage = true, rootThreadEventId = rootThreadEventId) - ContentAttachmentData.Type.FILE -> createFileEvent(roomId, attachment, rootThreadEventId) + ContentAttachmentData.Type.IMAGE -> createImageEvent(roomId, attachment, rootThreadEventId, relatesTo) + ContentAttachmentData.Type.VIDEO -> createVideoEvent(roomId, attachment, rootThreadEventId, relatesTo) + ContentAttachmentData.Type.AUDIO -> createAudioEvent(roomId, attachment, isVoiceMessage = false, rootThreadEventId = rootThreadEventId, relatesTo) + ContentAttachmentData.Type.VOICE_MESSAGE -> createAudioEvent( + roomId, + attachment, + isVoiceMessage = true, + rootThreadEventId = rootThreadEventId, + relatesTo + ) + ContentAttachmentData.Type.FILE -> createFileEvent(roomId, attachment, rootThreadEventId, relatesTo) } } @@ -378,7 +385,7 @@ internal class LocalEchoEventFactory @Inject constructor( ) } - private fun createImageEvent(roomId: String, attachment: ContentAttachmentData, rootThreadEventId: String?): Event { + private fun createImageEvent(roomId: String, attachment: ContentAttachmentData, rootThreadEventId: String?, relatesTo: RelationDefaultContent?): Event { var width = attachment.width var height = attachment.height @@ -403,12 +410,12 @@ internal class LocalEchoEventFactory @Inject constructor( size = attachment.size ), url = attachment.queryUri.toString(), - relatesTo = rootThreadEventId?.let { generateThreadRelationContent(it) } + relatesTo = relatesTo ?: rootThreadEventId?.let { generateThreadRelationContent(it) } ) return createMessageEvent(roomId, content) } - private fun createVideoEvent(roomId: String, attachment: ContentAttachmentData, rootThreadEventId: String?): Event { + private fun createVideoEvent(roomId: String, attachment: ContentAttachmentData, rootThreadEventId: String?, relatesTo: RelationDefaultContent?): Event { val mediaDataRetriever = MediaMetadataRetriever() mediaDataRetriever.setDataSource(context, attachment.queryUri) @@ -440,7 +447,7 @@ internal class LocalEchoEventFactory @Inject constructor( thumbnailInfo = thumbnailInfo ), url = attachment.queryUri.toString(), - relatesTo = rootThreadEventId?.let { generateThreadRelationContent(it) } + relatesTo = relatesTo ?: rootThreadEventId?.let { generateThreadRelationContent(it) } ) return createMessageEvent(roomId, content) } @@ -449,7 +456,8 @@ internal class LocalEchoEventFactory @Inject constructor( roomId: String, attachment: ContentAttachmentData, isVoiceMessage: Boolean, - rootThreadEventId: String? + rootThreadEventId: String?, + relatesTo: RelationDefaultContent?, ): Event { val content = MessageAudioContent( msgType = MessageType.MSGTYPE_AUDIO, @@ -465,12 +473,12 @@ internal class LocalEchoEventFactory @Inject constructor( waveform = waveformSanitizer.sanitize(attachment.waveform) ), voiceMessageIndicator = if (!isVoiceMessage) null else emptyMap(), - relatesTo = rootThreadEventId?.let { generateThreadRelationContent(it) } + relatesTo = relatesTo ?: rootThreadEventId?.let { generateThreadRelationContent(it) } ) return createMessageEvent(roomId, content) } - private fun createFileEvent(roomId: String, attachment: ContentAttachmentData, rootThreadEventId: String?): Event { + private fun createFileEvent(roomId: String, attachment: ContentAttachmentData, rootThreadEventId: String?, relatesTo: RelationDefaultContent?): Event { val content = MessageFileContent( msgType = MessageType.MSGTYPE_FILE, body = attachment.name ?: "file", @@ -479,7 +487,7 @@ internal class LocalEchoEventFactory @Inject constructor( size = attachment.size ), url = attachment.queryUri.toString(), - relatesTo = rootThreadEventId?.let { generateThreadRelationContent(it) } + relatesTo = relatesTo ?: rootThreadEventId?.let { generateThreadRelationContent(it) } ) return createMessageEvent(roomId, content) }