Add sending file to thread support

** Important while this feature depends on local echo, should be added local echo support in threads to work 100%
This commit is contained in:
ariskotsomitopoulos 2021-11-18 15:48:17 +02:00
parent 3d9350091e
commit 3de0f7bf37
5 changed files with 64 additions and 25 deletions

View File

@ -149,7 +149,10 @@ class RxRoom(private val room: Room) {
}
fun sendMedia(attachment: ContentAttachmentData, compressBeforeSending: Boolean, roomIds: Set<String>): Completable = rxCompletable {
room.sendMedia(attachment, compressBeforeSending, roomIds)
room.sendMedia(
attachment = attachment,
compressBeforeSending = compressBeforeSending,
roomIds = roomIds)
}
}

View File

@ -63,11 +63,13 @@ interface SendService {
* @param compressBeforeSending set to true to compress images before sending them
* @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
* @return a [Cancelable]
*/
fun sendMedia(attachment: ContentAttachmentData,
compressBeforeSending: Boolean,
roomIds: Set<String>): Cancelable
roomIds: Set<String>,
rootThreadEventId: String? = null): Cancelable
/**
* Method to send a list of media asynchronously.
@ -75,11 +77,13 @@ interface SendService {
* @param compressBeforeSending set to true to compress images before sending them
* @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, all the Media will be sent in this specific thread
* @return a [Cancelable]
*/
fun sendMedias(attachments: List<ContentAttachmentData>,
compressBeforeSending: Boolean,
roomIds: Set<String>): Cancelable
roomIds: Set<String>,
rootThreadEventId: String? = null): Cancelable
/**
* Send a poll to the room.

View File

@ -236,22 +236,38 @@ internal class DefaultSendService @AssistedInject constructor(
override fun sendMedias(attachments: List<ContentAttachmentData>,
compressBeforeSending: Boolean,
roomIds: Set<String>): Cancelable {
roomIds: Set<String>,
rootThreadEventId: String?
): Cancelable {
return attachments.mapTo(CancelableBag()) {
sendMedia(it, compressBeforeSending, roomIds)
sendMedia(
attachment = it,
compressBeforeSending = compressBeforeSending,
roomIds = roomIds,
rootThreadEventId = rootThreadEventId)
}
}
override fun sendMedia(attachment: ContentAttachmentData,
compressBeforeSending: Boolean,
roomIds: Set<String>): Cancelable {
roomIds: Set<String>,
rootThreadEventId: String?
): Cancelable {
// Ensure that the event will not be send in a thread if we are a different flow.
// Like sending files to multiple rooms
val rootThreadId = if (roomIds.isNotEmpty()) null else rootThreadEventId
// Create an event with the media file path
// Ensure current roomId is included in the set
val allRoomIds = (roomIds + roomId).toList()
// Create local echo for each room
val allLocalEchoes = allRoomIds.map {
localEchoEventFactory.createMediaEvent(it, attachment).also { event ->
localEchoEventFactory.createMediaEvent(
roomId = it,
attachment = attachment,
rootThreadEventId = rootThreadId).also { event ->
createLocalEcho(event)
}
}

View File

@ -197,12 +197,15 @@ internal class LocalEchoEventFactory @Inject constructor(
))
}
fun createMediaEvent(roomId: String, attachment: ContentAttachmentData): Event {
fun createMediaEvent(roomId: String,
attachment: ContentAttachmentData,
rootThreadEventId: String?
): Event {
return when (attachment.type) {
ContentAttachmentData.Type.IMAGE -> createImageEvent(roomId, attachment)
ContentAttachmentData.Type.VIDEO -> createVideoEvent(roomId, attachment)
ContentAttachmentData.Type.AUDIO -> createAudioEvent(roomId, attachment)
ContentAttachmentData.Type.FILE -> createFileEvent(roomId, attachment)
ContentAttachmentData.Type.IMAGE -> createImageEvent(roomId, attachment, rootThreadEventId)
ContentAttachmentData.Type.VIDEO -> createVideoEvent(roomId, attachment, rootThreadEventId)
ContentAttachmentData.Type.AUDIO -> createAudioEvent(roomId, attachment, rootThreadEventId)
ContentAttachmentData.Type.FILE -> createFileEvent(roomId, attachment, rootThreadEventId)
}
}
@ -225,7 +228,7 @@ internal class LocalEchoEventFactory @Inject constructor(
unsignedData = UnsignedData(age = null, transactionId = localId))
}
private fun createImageEvent(roomId: String, attachment: ContentAttachmentData): Event {
private fun createImageEvent(roomId: String, attachment: ContentAttachmentData, rootThreadEventId: String?): Event {
var width = attachment.width
var height = attachment.height
@ -249,12 +252,13 @@ internal class LocalEchoEventFactory @Inject constructor(
height = height?.toInt() ?: 0,
size = attachment.size
),
url = attachment.queryUri.toString()
url = attachment.queryUri.toString(),
relatesTo = rootThreadEventId?.let { RelationDefaultContent(RelationType.THREAD, it) }
)
return createMessageEvent(roomId, content)
}
private fun createVideoEvent(roomId: String, attachment: ContentAttachmentData): Event {
private fun createVideoEvent(roomId: String, attachment: ContentAttachmentData, rootThreadEventId: String?): Event {
val mediaDataRetriever = MediaMetadataRetriever()
mediaDataRetriever.setDataSource(context, attachment.queryUri)
@ -285,12 +289,13 @@ internal class LocalEchoEventFactory @Inject constructor(
thumbnailUrl = attachment.queryUri.toString(),
thumbnailInfo = thumbnailInfo
),
url = attachment.queryUri.toString()
url = attachment.queryUri.toString(),
relatesTo = rootThreadEventId?.let { RelationDefaultContent(RelationType.THREAD, it) }
)
return createMessageEvent(roomId, content)
}
private fun createAudioEvent(roomId: String, attachment: ContentAttachmentData): Event {
private fun createAudioEvent(roomId: String, attachment: ContentAttachmentData, rootThreadEventId: String?): Event {
val isVoiceMessage = attachment.waveform != null
val content = MessageAudioContent(
msgType = MessageType.MSGTYPE_AUDIO,
@ -305,12 +310,13 @@ internal class LocalEchoEventFactory @Inject constructor(
duration = attachment.duration?.toInt(),
waveform = waveformSanitizer.sanitize(attachment.waveform)
),
voiceMessageIndicator = if (!isVoiceMessage) null else emptyMap()
voiceMessageIndicator = if (!isVoiceMessage) null else emptyMap(),
relatesTo = rootThreadEventId?.let { RelationDefaultContent(RelationType.THREAD, it) }
)
return createMessageEvent(roomId, content)
}
private fun createFileEvent(roomId: String, attachment: ContentAttachmentData): Event {
private fun createFileEvent(roomId: String, attachment: ContentAttachmentData, rootThreadEventId: String?): Event {
val content = MessageFileContent(
msgType = MessageType.MSGTYPE_FILE,
body = attachment.name ?: "file",
@ -318,7 +324,8 @@ internal class LocalEchoEventFactory @Inject constructor(
mimeType = attachment.getSafeMimeType()?.takeIf { it.isNotBlank() },
size = attachment.size
),
url = attachment.queryUri.toString()
url = attachment.queryUri.toString(),
relatesTo = rootThreadEventId?.let { RelationDefaultContent(RelationType.THREAD, it) }
)
return createMessageEvent(roomId, content)
}

View File

@ -626,7 +626,11 @@ class RoomDetailViewModel @AssistedInject constructor(
} else {
voiceMessageHelper.stopRecording()?.let { audioType ->
if (audioType.duration > 1000) {
room.sendMedia(audioType.toContentAttachmentData(), false, emptySet())
room.sendMedia(
attachment = audioType.toContentAttachmentData(),
compressBeforeSending = false,
roomIds = emptySet(),
rootThreadEventId = initialState.rootThreadEventId)
} else {
voiceMessageHelper.deleteRecording()
}
@ -705,7 +709,12 @@ class RoomDetailViewModel @AssistedInject constructor(
}
private fun handleSendMedia(action: RoomDetailAction.SendMedia) {
room.sendMedias(action.attachments, action.compressBeforeSending, emptySet())
room.sendMedias(
action.attachments,
action.compressBeforeSending,
emptySet(),
initialState.rootThreadEventId
)
}
private fun handleEventVisible(action: RoomDetailAction.TimelineEventTurnsVisible) {