From 58dd1dedc964a886acd50a0e6e6d1f9c3eca9aa2 Mon Sep 17 00:00:00 2001 From: SpiritCroc Date: Thu, 10 Nov 2022 10:38:04 +0100 Subject: [PATCH] Render MSC2530 captions Change-Id: I10f875121e90102a0518d9bd39d87b3daa68ef2e --- FEATURES.md | 1 + .../room/model/message/MessageAudioContent.kt | 5 +++ .../room/model/message/MessageFileContent.kt | 2 +- .../room/model/message/MessageImageContent.kt | 5 +++ .../model/message/MessageStickerContent.kt | 5 +++ .../room/model/message/MessageVideoContent.kt | 5 +++ .../message/MessageWithAttachmentContent.kt | 7 +++- .../timeline/factory/MessageItemFactory.kt | 17 ++++++--- .../image/ImageContentRendererFactory.kt | 8 +++- .../detail/timeline/item/MessageAudioItem.kt | 21 +++++++++++ .../detail/timeline/item/MessageFileItem.kt | 21 +++++++++++ .../timeline/item/MessageImageVideoItem.kt | 37 +++++++++++++++++-- .../style/TimelineMessageLayoutFactory.kt | 3 ++ .../features/media/ImageContentRenderer.kt | 2 + .../media/RoomEventsAttachmentProvider.kt | 14 +++++-- .../features/media/VideoContentRenderer.kt | 1 + .../uploads/media/RoomUploadsMediaFragment.kt | 11 ++++-- .../uploads/media/UploadsMediaController.kt | 11 ++++-- .../layout/item_timeline_event_audio_stub.xml | 11 ++++++ .../layout/item_timeline_event_file_stub.xml | 11 ++++++ ...item_timeline_event_media_message_stub.xml | 17 ++++++++- 21 files changed, 192 insertions(+), 23 deletions(-) diff --git a/FEATURES.md b/FEATURES.md index f7786b5855..e142c9eaf2 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -32,6 +32,7 @@ Here you can find some extra features and changes compared to Element Android (w - Render inline images / custom emojis in the timeline - Render image reactions - Send freeform reactions +- Render media captions ([MSC2530](https://github.com/matrix-org/matrix-spec-proposals/pull/2530)) - Branding (name, app icon, links) - Show a toast instead of a snackbar after copying text, in order to not block the input area right after copying diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageAudioContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageAudioContent.kt index 76a612b51b..f53a618834 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageAudioContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageAudioContent.kt @@ -45,6 +45,11 @@ data class MessageAudioContent( */ @Json(name = "url") override val url: String? = null, + /** + * MSC 2530: filename as filename, using body as caption instead + */ + @Json(name = "filename") override val filename: String? = null, + @Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null, @Json(name = "m.new_content") override val newContent: Content? = null, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageFileContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageFileContent.kt index b5303e6c5d..a463d22941 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageFileContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageFileContent.kt @@ -38,7 +38,7 @@ data class MessageFileContent( /** * The original filename of the uploaded file. */ - @Json(name = "filename") val filename: String? = null, + @Json(name = "filename") override val filename: String? = null, /** * Information about the file referred to in url. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageImageContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageImageContent.kt index f0caf52041..0aea3cca5b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageImageContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageImageContent.kt @@ -45,6 +45,11 @@ data class MessageImageContent( */ @Json(name = "url") override val url: String? = null, + /** + * MSC 2530: filename as filename, using body as caption instead + */ + @Json(name = "filename") override val filename: String? = null, + @Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null, @Json(name = "m.new_content") override val newContent: Content? = null, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageStickerContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageStickerContent.kt index f8c1c0d798..828949f13c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageStickerContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageStickerContent.kt @@ -46,6 +46,11 @@ data class MessageStickerContent( */ @Json(name = "url") override val url: String? = null, + /** + * MSC 2530: filename as filename, using body as caption instead + */ + @Json(name = "filename") override val filename: String? = null, + @Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null, @Json(name = "m.new_content") override val newContent: Content? = null, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVideoContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVideoContent.kt index 9b657971b9..9a82a4b49f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVideoContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVideoContent.kt @@ -44,6 +44,11 @@ data class MessageVideoContent( */ @Json(name = "url") override val url: String? = null, + /** + * MSC 2530: filename as filename, using body as caption instead + */ + @Json(name = "filename") override val filename: String? = null, + @Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null, @Json(name = "m.new_content") override val newContent: Content? = null, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageWithAttachmentContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageWithAttachmentContent.kt index 8d9dbee6b3..b73a706abe 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageWithAttachmentContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageWithAttachmentContent.kt @@ -33,6 +33,9 @@ interface MessageWithAttachmentContent : MessageContent { val encryptedFileInfo: EncryptedFileInfo? val mimeType: String? + + // MSC 2530 adds filename for other media types than m.file as well + val filename: String? } /** @@ -40,4 +43,6 @@ interface MessageWithAttachmentContent : MessageContent { */ fun MessageWithAttachmentContent.getFileUrl() = encryptedFileInfo?.url ?: url -fun MessageWithAttachmentContent.getFileName() = (this as? MessageFileContent)?.getFileName() ?: body +fun MessageWithAttachmentContent.getFileName() = (this as? MessageFileContent)?.getFileName() ?: filename ?: body + +fun MessageWithAttachmentContent.getCaption() = body.takeIf { filename != null && filename != it } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt index 4f255837f5..654fbef20c 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt @@ -108,6 +108,8 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageType import org.matrix.android.sdk.api.session.room.model.message.MessageVerificationRequestContent import org.matrix.android.sdk.api.session.room.model.message.MessageVideoContent import org.matrix.android.sdk.api.session.room.model.message.asMessageAudioEvent +import org.matrix.android.sdk.api.session.room.model.message.getCaption +import org.matrix.android.sdk.api.session.room.model.message.getFileName import org.matrix.android.sdk.api.session.room.model.message.getFileUrl import org.matrix.android.sdk.api.session.room.model.message.getThumbnailUrl import org.matrix.android.sdk.api.settings.LightweightSettingsStorage @@ -285,7 +287,8 @@ class MessageItemFactory @Inject constructor( return MessageAudioItem_() .attributes(attributes) - .filename(messageContent.body) + .filename(messageContent.getFileName()) + .caption(messageContent.getCaption()) .duration(messageContent.audioInfo?.duration ?: 0) .playbackControlButtonClickListener(playbackControlButtonClickListener) .audioMessagePlaybackTracker(audioMessagePlaybackTracker) @@ -418,7 +421,8 @@ class MessageItemFactory @Inject constructor( .contentUploadStateTrackerBinder(contentUploadStateTrackerBinder) .contentDownloadStateTrackerBinder(contentDownloadStateTrackerBinder) .highlighted(highlight) - .filename(messageContent.body) + .filename(messageContent.getFileName()) + .caption(messageContent.getCaption()) .iconRes(R.drawable.ic_paperclip) } @@ -456,7 +460,8 @@ class MessageItemFactory @Inject constructor( val (maxWidth, maxHeight) = timelineMediaSizeProvider.getMaxSize() val data = ImageContentRenderer.Data( eventId = informationData.eventId, - filename = messageContent.body, + filename = messageContent.getFileName(), + caption = messageContent.getCaption(), mimeType = messageContent.mimeType, url = messageContent.getFileUrl(), elementToDecrypt = messageContent.encryptedFileInfo?.toElementToDecrypt(), @@ -505,7 +510,8 @@ class MessageItemFactory @Inject constructor( val (maxWidth, maxHeight) = timelineMediaSizeProvider.getMaxSize() val thumbnailData = ImageContentRenderer.Data( eventId = informationData.eventId, - filename = messageContent.body, + filename = messageContent.getFileName(), + caption = messageContent.getCaption(), mimeType = messageContent.mimeType, url = messageContent.videoInfo?.getThumbnailUrl(), elementToDecrypt = messageContent.videoInfo?.thumbnailFile?.toElementToDecrypt(), @@ -522,7 +528,8 @@ class MessageItemFactory @Inject constructor( val videoData = VideoContentRenderer.Data( eventId = informationData.eventId, - filename = messageContent.body, + filename = messageContent.getFileName(), + caption = messageContent.getCaption(), mimeType = messageContent.mimeType, url = messageContent.getFileUrl(), elementToDecrypt = messageContent.encryptedFileInfo?.toElementToDecrypt(), diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/image/ImageContentRendererFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/image/ImageContentRendererFactory.kt index f1e05c7b5a..1f79d7936c 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/image/ImageContentRendererFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/image/ImageContentRendererFactory.kt @@ -23,6 +23,8 @@ import org.matrix.android.sdk.api.session.events.model.isVideoMessage import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.model.message.MessageImageContent import org.matrix.android.sdk.api.session.room.model.message.MessageVideoContent +import org.matrix.android.sdk.api.session.room.model.message.getCaption +import org.matrix.android.sdk.api.session.room.model.message.getFileName import org.matrix.android.sdk.api.session.room.model.message.getFileUrl import org.matrix.android.sdk.api.session.room.model.message.getThumbnailUrl import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent @@ -33,7 +35,8 @@ fun TimelineEvent.buildImageContentRendererData(maxHeight: Int, generateMissingV ?.let { messageImageContent -> ImageContentRenderer.Data( eventId = eventId, - filename = messageImageContent.body, + filename = messageImageContent.getFileName(), + caption = messageImageContent.getCaption(), mimeType = messageImageContent.mimeType, url = messageImageContent.getFileUrl(), elementToDecrypt = messageImageContent.encryptedFileInfo?.toElementToDecrypt(), @@ -49,7 +52,8 @@ fun TimelineEvent.buildImageContentRendererData(maxHeight: Int, generateMissingV val videoInfo = messageVideoContent.videoInfo ImageContentRenderer.Data( eventId = eventId, - filename = messageVideoContent.body, + filename = messageVideoContent.getFileName(), + caption = messageVideoContent.getCaption(), mimeType = videoInfo?.thumbnailInfo?.mimeType, url = videoInfo?.getThumbnailUrl(), elementToDecrypt = videoInfo?.thumbnailFile?.toElementToDecrypt(), diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageAudioItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageAudioItem.kt index 4da7ec72f7..921f0cebfd 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageAudioItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageAudioItem.kt @@ -30,11 +30,14 @@ import com.airbnb.epoxy.EpoxyModelClass import im.vector.app.R import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.epoxy.onClick +import im.vector.app.core.extensions.setTextOrHide +import im.vector.app.core.ui.views.FooteredTextView import im.vector.app.core.utils.TextUtils import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlaybackTracker import im.vector.app.features.home.room.detail.timeline.helper.ContentDownloadStateTrackerBinder import im.vector.app.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayout +import im.vector.app.features.home.room.detail.timeline.view.ScMessageBubbleWrapView import im.vector.app.features.themes.ThemeUtils @EpoxyModelClass @@ -43,6 +46,9 @@ abstract class MessageAudioItem : AbsMessageItem() { @EpoxyAttribute var filename: String = "" + @EpoxyAttribute + var caption: String? = null + @EpoxyAttribute var mxcUrl: String = "" @@ -115,6 +121,7 @@ abstract class MessageAudioItem : AbsMessageItem() { holder.fileSize.text = holder.rootLayout.context.getString( R.string.audio_message_file_size, formattedFileSize ) + holder.captionView.setTextOrHide(caption) holder.mainLayout.contentDescription = holder.rootLayout.context.getString( R.string.a11y_audio_message_item, filename, durationContentDescription, formattedFileSize ) @@ -195,6 +202,19 @@ abstract class MessageAudioItem : AbsMessageItem() { audioMessagePlaybackTracker.untrack(attributes.informationData.eventId) } + private fun hasCaption() = !caption.isNullOrBlank() + + override fun allowFooterOverlay(holder: Holder, bubbleWrapView: ScMessageBubbleWrapView): Boolean = hasCaption() + + override fun needsFooterReservation(): Boolean { + return hasCaption() + } + + override fun reserveFooterSpace(holder: Holder, width: Int, height: Int) { + holder.captionView.footerWidth = width + holder.captionView.footerHeight = height + } + override fun getViewStubId() = STUB_ID class Holder : AbsMessageItem.Holder(STUB_ID) { @@ -205,6 +225,7 @@ abstract class MessageAudioItem : AbsMessageItem() { val audioPlaybackTime by bind(R.id.audioPlaybackTime) val progressLayout by bind(R.id.messageFileUploadProgressLayout) val fileSize by bind(R.id.fileSize) + val captionView by bind(R.id.messageCaptionView) val audioPlaybackDuration by bind(R.id.audioPlaybackDuration) val audioSeekBar by bind(R.id.audioSeekBar) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageFileItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageFileItem.kt index ebb7c2b89e..a00d69b72d 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageFileItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageFileItem.kt @@ -29,9 +29,12 @@ import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.app.R import im.vector.app.core.epoxy.onClick +import im.vector.app.core.extensions.setTextOrHide +import im.vector.app.core.ui.views.FooteredTextView import im.vector.app.features.home.room.detail.timeline.helper.ContentDownloadStateTrackerBinder import im.vector.app.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayout +import im.vector.app.features.home.room.detail.timeline.view.ScMessageBubbleWrapView import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.themes.guessTextWidth import kotlin.math.ceil @@ -43,6 +46,9 @@ abstract class MessageFileItem : AbsMessageItem() { @EpoxyAttribute var filename: String = "" + @EpoxyAttribute + var caption: String? = null + @EpoxyAttribute var mxcUrl: String = "" @@ -74,6 +80,7 @@ abstract class MessageFileItem : AbsMessageItem() { } holder.filenameView.text = filename + holder.captionView.setTextOrHide(caption) if (attributes.informationData.sendState.isSending()) { holder.fileImageView.setImageResource(iconRes) @@ -124,6 +131,19 @@ abstract class MessageFileItem : AbsMessageItem() { holder.mainLayout.setPadding(0, 0, 0, 0) } + private fun hasCaption() = !caption.isNullOrBlank() + + override fun allowFooterOverlay(holder: Holder, bubbleWrapView: ScMessageBubbleWrapView): Boolean = hasCaption() + + override fun needsFooterReservation(): Boolean { + return hasCaption() + } + + override fun reserveFooterSpace(holder: Holder, width: Int, height: Int) { + holder.captionView.footerWidth = width + holder.captionView.footerHeight = height + } + override fun getViewStubId() = STUB_ID class Holder : AbsMessageItem.Holder(STUB_ID) { @@ -134,6 +154,7 @@ abstract class MessageFileItem : AbsMessageItem() { val fileImageWrapper by bind(R.id.messageFileImageView) val fileDownloadProgress by bind(R.id.messageFileProgressbar) val filenameView by bind(R.id.messageFilenameView) + val captionView by bind(R.id.messageCaptionView) } companion object { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt index 5b2228f2f8..60bc6f14e9 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt @@ -31,8 +31,10 @@ import com.bumptech.glide.load.resource.bitmap.RoundedCorners import im.vector.app.R import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.epoxy.onClick +import im.vector.app.core.extensions.setTextOrHide import im.vector.app.core.files.LocalFilesHelper import im.vector.app.core.glide.GlideApp +import im.vector.app.core.ui.views.FooteredTextView import im.vector.app.core.utils.DimensionConverter import im.vector.app.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayout @@ -130,6 +132,8 @@ abstract class MessageImageVideoItem : AbsMessageItem, imageWidth: Int, imageHeight: Int): Boolean { + if (hasCaption()) { + return true + } val footerWidth = footerMeasures[0] val footerHeight = footerMeasures[1] // We need enough space in both directions to remain within the image bounds. @@ -159,6 +168,9 @@ abstract class MessageImageVideoItem : AbsMessageItem, imageWidth: Int, imageHeight: Int): Boolean { + if (hasCaption()) { + return false + } // Only show footer bellow if the width is not the limiting factor (or it will get cut). // Otherwise, we can not be sure in this place that we'll have enough space on the side // Also, prefer footer on the side if possible (i.e. enough height available) @@ -168,6 +180,9 @@ abstract class MessageImageVideoItem : AbsMessageItem width of the ImageView not adapted to the actual content // -> Align image within ImageView to same side as message bubbles @@ -208,13 +238,13 @@ abstract class MessageImageVideoItem : AbsMessageItem { + !(messageLayout.isRealBubble || messageLayout.isPseudoBubble) || hasCaption() || mode != ImageContentRenderer.Mode.THUMBNAIL -> { holder.mediaContentView.background = null } - attributes.informationData.sentByMe -> { + attributes.informationData.sentByMe -> { holder.mediaContentView.setBackgroundResource(messageLayout.bubbleAppearance.imageBorderOutgoing) } - else -> { + else -> { holder.mediaContentView.setBackgroundResource(messageLayout.bubbleAppearance.imageBorderIncoming) } } @@ -223,6 +253,7 @@ abstract class MessageImageVideoItem : AbsMessageItem(R.id.messageMediaUploadProgressLayout) val imageView by bind(R.id.messageThumbnailView) + val captionView by bind(R.id.messageCaptionView) val playContentView by bind(R.id.messageMediaPlayView) val mediaContentView by bind(R.id.messageContentMedia) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayoutFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayoutFactory.kt index 565a1dca76..6300d3d892 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayoutFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayoutFactory.kt @@ -31,6 +31,8 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.model.message.MessageNoticeContent import org.matrix.android.sdk.api.session.room.model.message.MessageType import org.matrix.android.sdk.api.session.room.model.message.MessageVerificationRequestContent +import org.matrix.android.sdk.api.session.room.model.message.MessageWithAttachmentContent +import org.matrix.android.sdk.api.session.room.model.message.getCaption import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent import org.matrix.android.sdk.api.session.room.timeline.isEdition @@ -209,6 +211,7 @@ class TimelineMessageLayoutFactory @Inject constructor( private fun MessageContent?.isPseudoBubble(event: TimelineEvent): Boolean { if (this == null) return false if (event.root.isRedacted()) return false + if (this is MessageWithAttachmentContent && !getCaption().isNullOrBlank()) return false return this.msgType in MSG_TYPES_WITH_PSEUDO_BUBBLE_LAYOUT } diff --git a/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt b/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt index 4b4409e1ac..c1fb65c79a 100644 --- a/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt +++ b/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt @@ -52,6 +52,7 @@ import kotlin.math.min interface AttachmentData : Parcelable { val eventId: String val filename: String + val caption: String? val mimeType: String? val url: String? val elementToDecrypt: ElementToDecrypt? @@ -73,6 +74,7 @@ class ImageContentRenderer @Inject constructor( data class Data( override val eventId: String, override val filename: String, + override val caption: String?, override val mimeType: String?, override val url: String?, override val elementToDecrypt: ElementToDecrypt?, diff --git a/vector/src/main/java/im/vector/app/features/media/RoomEventsAttachmentProvider.kt b/vector/src/main/java/im/vector/app/features/media/RoomEventsAttachmentProvider.kt index e18a13a3e6..66f7f7ede1 100644 --- a/vector/src/main/java/im/vector/app/features/media/RoomEventsAttachmentProvider.kt +++ b/vector/src/main/java/im/vector/app/features/media/RoomEventsAttachmentProvider.kt @@ -29,6 +29,8 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageImageContent import org.matrix.android.sdk.api.session.room.model.message.MessageStickerContent 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.getCaption +import org.matrix.android.sdk.api.session.room.model.message.getFileName import org.matrix.android.sdk.api.session.room.model.message.getFileUrl import org.matrix.android.sdk.api.session.room.model.message.getThumbnailUrl import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent @@ -60,7 +62,8 @@ class RoomEventsAttachmentProvider( if (content is MessageImageContent) { val data = ImageContentRenderer.Data( eventId = it.eventId, - filename = content.body, + filename = content.getFileName(), + caption = content.getCaption(), mimeType = content.mimeType, url = content.getFileUrl(), elementToDecrypt = content.encryptedFileInfo?.toElementToDecrypt(), @@ -87,7 +90,8 @@ class RoomEventsAttachmentProvider( } else if (content is MessageStickerContent) { val data = ImageContentRenderer.Data( eventId = it.eventId, - filename = content.body, + filename = content.getFileName(), + caption = content.getCaption(), mimeType = content.mimeType, url = content.getFileUrl(), elementToDecrypt = content.encryptedFileInfo?.toElementToDecrypt(), @@ -114,7 +118,8 @@ class RoomEventsAttachmentProvider( } else if (content is MessageVideoContent) { val thumbnailData = ImageContentRenderer.Data( eventId = it.eventId, - filename = content.body, + filename = content.getFileName(), + caption = content.getCaption(), mimeType = content.mimeType, url = content.videoInfo?.getThumbnailUrl(), elementToDecrypt = content.videoInfo?.thumbnailFile?.toElementToDecrypt(), @@ -126,7 +131,8 @@ class RoomEventsAttachmentProvider( ) val data = VideoContentRenderer.Data( eventId = it.eventId, - filename = content.body, + filename = content.getFileName(), + caption = content.getCaption(), mimeType = content.mimeType, url = content.getFileUrl(), elementToDecrypt = content.encryptedFileInfo?.toElementToDecrypt(), diff --git a/vector/src/main/java/im/vector/app/features/media/VideoContentRenderer.kt b/vector/src/main/java/im/vector/app/features/media/VideoContentRenderer.kt index cdfa3d2e28..572545b0f4 100644 --- a/vector/src/main/java/im/vector/app/features/media/VideoContentRenderer.kt +++ b/vector/src/main/java/im/vector/app/features/media/VideoContentRenderer.kt @@ -49,6 +49,7 @@ class VideoContentRenderer @Inject constructor( data class Data( override val eventId: String, override val filename: String, + override val caption: String?, override val mimeType: String?, override val url: String?, override val elementToDecrypt: ElementToDecrypt?, diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/RoomUploadsMediaFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/RoomUploadsMediaFragment.kt index 98a28557ae..e6b5bbb53e 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/RoomUploadsMediaFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/RoomUploadsMediaFragment.kt @@ -50,6 +50,8 @@ import im.vector.app.features.roomprofile.uploads.RoomUploadsViewState import org.matrix.android.sdk.api.session.crypto.attachments.toElementToDecrypt import org.matrix.android.sdk.api.session.room.model.message.MessageImageContent import org.matrix.android.sdk.api.session.room.model.message.MessageVideoContent +import org.matrix.android.sdk.api.session.room.model.message.getCaption +import org.matrix.android.sdk.api.session.room.model.message.getFileName import org.matrix.android.sdk.api.session.room.model.message.getFileUrl import org.matrix.android.sdk.api.session.room.model.message.getThumbnailUrl import javax.inject.Inject @@ -132,7 +134,8 @@ class RoomUploadsMediaFragment : is MessageImageContent -> { ImageContentRenderer.Data( eventId = it.eventId, - filename = content.body, + filename = content.getFileName(), + caption = content.getCaption(), mimeType = content.mimeType, url = content.getFileUrl(), elementToDecrypt = content.encryptedFileInfo?.toElementToDecrypt(), @@ -145,7 +148,8 @@ class RoomUploadsMediaFragment : is MessageVideoContent -> { val thumbnailData = ImageContentRenderer.Data( eventId = it.eventId, - filename = content.body, + filename = content.getFileName(), + caption = content.getCaption(), mimeType = content.mimeType, url = content.videoInfo?.getThumbnailUrl(), elementToDecrypt = content.videoInfo?.thumbnailFile?.toElementToDecrypt(), @@ -156,7 +160,8 @@ class RoomUploadsMediaFragment : ) VideoContentRenderer.Data( eventId = it.eventId, - filename = content.body, + filename = content.getFileName(), + caption = content.getCaption(), mimeType = content.mimeType, url = content.getFileUrl(), elementToDecrypt = content.encryptedFileInfo?.toElementToDecrypt(), diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/UploadsMediaController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/UploadsMediaController.kt index 94d29b3078..4e251df56a 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/UploadsMediaController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/UploadsMediaController.kt @@ -30,6 +30,8 @@ import org.matrix.android.sdk.api.session.crypto.attachments.toElementToDecrypt import org.matrix.android.sdk.api.session.room.model.message.MessageImageContent import org.matrix.android.sdk.api.session.room.model.message.MessageType import org.matrix.android.sdk.api.session.room.model.message.MessageVideoContent +import org.matrix.android.sdk.api.session.room.model.message.getCaption +import org.matrix.android.sdk.api.session.room.model.message.getFileName import org.matrix.android.sdk.api.session.room.model.message.getFileUrl import org.matrix.android.sdk.api.session.room.model.message.getThumbnailUrl import org.matrix.android.sdk.api.session.room.uploads.UploadEvent @@ -108,7 +110,8 @@ class UploadsMediaController @Inject constructor( return ImageContentRenderer.Data( eventId = eventId, - filename = messageContent.body, + filename = messageContent.getFileName(), + caption = messageContent.getCaption(), url = messageContent.getFileUrl(), mimeType = messageContent.mimeType, elementToDecrypt = messageContent.encryptedFileInfo?.toElementToDecrypt(), @@ -124,7 +127,8 @@ class UploadsMediaController @Inject constructor( val thumbnailData = ImageContentRenderer.Data( eventId = eventId, - filename = messageContent.body, + filename = messageContent.getFileName(), + caption = messageContent.getCaption(), mimeType = messageContent.mimeType, url = messageContent.videoInfo?.getThumbnailUrl(), elementToDecrypt = messageContent.videoInfo?.thumbnailFile?.toElementToDecrypt(), @@ -136,7 +140,8 @@ class UploadsMediaController @Inject constructor( return VideoContentRenderer.Data( eventId = eventId, - filename = messageContent.body, + filename = messageContent.getFileName(), + caption = messageContent.getCaption(), mimeType = messageContent.mimeType, url = messageContent.getFileUrl(), elementToDecrypt = messageContent.encryptedFileInfo?.toElementToDecrypt(), diff --git a/vector/src/main/res/layout/item_timeline_event_audio_stub.xml b/vector/src/main/res/layout/item_timeline_event_audio_stub.xml index f62564a11e..a317edc055 100644 --- a/vector/src/main/res/layout/item_timeline_event_audio_stub.xml +++ b/vector/src/main/res/layout/item_timeline_event_audio_stub.xml @@ -95,6 +95,17 @@ + + + + + +