From d49fcb80fc710b30c157f42c7cd081031538971c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 20 May 2020 23:52:41 +0200 Subject: [PATCH 1/7] "Seen by" uses 12h time (Fixes #1378) DateUtils.FORMAT_SHOW_TIME has to be used for i18n to be effective on DateUtils.getRelativeDateTimeString(), do not ask me why. Also internal switching of language does not have effect on this method, you'll have to restart the application. --- CHANGES.md | 1 + .../im/vector/riotx/core/date/VectorDateFormatter.kt | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index bb02b798e0..12d4d7a2ca 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,7 @@ Improvements 🙌: Bugfix 🐛: - After jump to unread, newer messages are never loaded (#1008) - Fix issues with FontScale switch (#69, #645) + - "Seen by" uses 12h time (#1378) Translations 🗣: - diff --git a/vector/src/main/java/im/vector/riotx/core/date/VectorDateFormatter.kt b/vector/src/main/java/im/vector/riotx/core/date/VectorDateFormatter.kt index 367615d765..344398b91e 100644 --- a/vector/src/main/java/im/vector/riotx/core/date/VectorDateFormatter.kt +++ b/vector/src/main/java/im/vector/riotx/core/date/VectorDateFormatter.kt @@ -45,11 +45,12 @@ class VectorDateFormatter @Inject constructor(private val context: Context, if (time == null) { return "" } - return DateUtils.getRelativeDateTimeString(context, - time, - DateUtils.DAY_IN_MILLIS, - 2 * DateUtils.DAY_IN_MILLIS, - DateUtils.FORMAT_SHOW_WEEKDAY + return DateUtils.getRelativeDateTimeString( + context, + time, + DateUtils.DAY_IN_MILLIS, + 2 * DateUtils.DAY_IN_MILLIS, + DateUtils.FORMAT_SHOW_WEEKDAY or DateUtils.FORMAT_SHOW_TIME ).toString() } } From 628439aa6512fa8f63a049e2f97b56402abfa288 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 21 May 2020 00:25:59 +0200 Subject: [PATCH 2/7] Mardown: sending "**text in bold** was sending extra paragraph and extra new line --- .../android/internal/extensions/Strings.kt | 24 +++++++++++++++++++ .../room/send/LocalEchoEventFactory.kt | 13 ++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/extensions/Strings.kt diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/extensions/Strings.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/extensions/Strings.kt new file mode 100644 index 0000000000..09913b9f04 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/extensions/Strings.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.matrix.android.internal.extensions + +/** + * Ex: "abcdef".subStringBetween("a", "f") -> "bcde" + * Ex: "abcdefff".subStringBetween("a", "f") -> "bcdeff" + * Ex: "aaabcdef".subStringBetween("a", "f") -> "aabcde" + */ +internal fun String.subStringBetween(prefix: String, suffix: String) = substringAfter(prefix).substringBeforeLast(suffix) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt index 5f0515e669..9a96e78b24 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt @@ -56,6 +56,7 @@ import im.vector.matrix.android.api.session.room.model.relation.ReplyToContent import im.vector.matrix.android.api.session.room.timeline.TimelineEvent import im.vector.matrix.android.api.session.room.timeline.getLastMessageContent import im.vector.matrix.android.internal.di.UserId +import im.vector.matrix.android.internal.extensions.subStringBetween import im.vector.matrix.android.internal.session.content.ThumbnailExtractor import im.vector.matrix.android.internal.session.room.send.pills.TextPillsUtils import im.vector.matrix.android.internal.task.TaskExecutor @@ -84,6 +85,7 @@ internal class LocalEchoEventFactory @Inject constructor( ) { // TODO Inject private val parser = Parser.builder().build() + // TODO Inject private val renderer = HtmlRenderer.builder().build() @@ -102,8 +104,15 @@ internal class LocalEchoEventFactory @Inject constructor( val document = parser.parse(source) val htmlText = renderer.render(document) - if (isFormattedTextPertinent(source, htmlText)) { - return TextContent(text.toString(), htmlText) + // Cleanup extra paragraph + val cleanHtmlText = if (htmlText.startsWith("

") && htmlText.endsWith("

\n")) { + htmlText.subStringBetween("

", "

\n") + } else { + htmlText + } + + if (isFormattedTextPertinent(source, cleanHtmlText)) { + return TextContent(text.toString(), cleanHtmlText) } } else { // Try to detect pills From e156a62e19294fd8d7c63722dbbfc284d59e6b5f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 21 May 2020 00:27:19 +0200 Subject: [PATCH 3/7] Enable markdown (if active) when sending emote (Fixes #734) --- CHANGES.md | 1 + .../riotx/features/home/room/detail/RoomDetailViewModel.kt | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 12d4d7a2ca..2c7e734600 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -13,6 +13,7 @@ Bugfix 🐛: - After jump to unread, newer messages are never loaded (#1008) - Fix issues with FontScale switch (#69, #645) - "Seen by" uses 12h time (#1378) + - Enable markdown (if active) when sending emote (#734) Translations 🗣: - diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt index 4a767a178e..df6f46b431 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt @@ -117,8 +117,10 @@ class RoomDetailViewModel @AssistedInject constructor( // Slot to keep a pending action during permission request var pendingAction: RoomDetailAction? = null + // Slot to keep a pending uri during permission request var pendingUri: Uri? = null + // Slot to store if we want to prevent preview of attachment var preventAttachmentPreview = false @@ -390,7 +392,7 @@ class RoomDetailViewModel @AssistedInject constructor( _viewEvents.post(RoomDetailViewEvents.SlashCommandNotImplemented) } is ParsedCommand.SendEmote -> { - room.sendTextMessage(slashCommandResult.message, msgType = MessageType.MSGTYPE_EMOTE) + room.sendTextMessage(slashCommandResult.message, msgType = MessageType.MSGTYPE_EMOTE, autoMarkdown = action.autoMarkdown) _viewEvents.post(RoomDetailViewEvents.SlashCommandHandled()) popDraft() } From 0e110b0794fae70599df7c921065365f4c9a3629 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 21 May 2020 00:39:46 +0200 Subject: [PATCH 4/7] Cleanup: use existing TextContent class instead of Pair<> --- .../ViewEditHistoryEpoxyController.kt | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt index 7ac0c8b1e8..329f66459b 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt @@ -27,6 +27,7 @@ import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.room.model.message.MessageTextContent import im.vector.matrix.android.api.util.ContentUtils.extractUsefulTextFromReply +import im.vector.matrix.android.internal.session.room.send.TextContent import im.vector.riotx.R import im.vector.riotx.core.date.VectorDateFormatter import im.vector.riotx.core.extensions.localDateTime @@ -90,17 +91,15 @@ class ViewEditHistoryEpoxyController(private val context: Context, } lastDate = evDate val cContent = getCorrectContent(timelineEvent, isOriginalReply) - val body = cContent.second?.let { eventHtmlRenderer.render(it) } - ?: cContent.first + val body = cContent.formattedText?.let { eventHtmlRenderer.render(it) } ?: cContent.text val nextEvent = sourceEvents.getOrNull(index + 1) var spannedDiff: Spannable? = null - if (nextEvent != null && cContent.second == null /*No diff for html*/) { + if (nextEvent != null && cContent.formattedText == null /*No diff for html*/) { // compares the body val nContent = getCorrectContent(nextEvent, isOriginalReply) - val nextBody = nContent.second?.let { eventHtmlRenderer.render(it) } - ?: nContent.first + val nextBody = nContent.formattedText?.let { eventHtmlRenderer.render(it) } ?: nContent.text val dmp = diff_match_patch() val diff = dmp.diff_main(nextBody.toString(), body.toString()) dmp.diff_cleanupSemantic(diff) @@ -138,15 +137,14 @@ class ViewEditHistoryEpoxyController(private val context: Context, } } - private fun getCorrectContent(event: Event, isOriginalReply: Boolean): Pair { + private fun getCorrectContent(event: Event, isOriginalReply: Boolean): TextContent { val clearContent = event.getClearContent().toModel() val newContent = clearContent ?.newContent ?.toModel() if (isOriginalReply) { - return extractUsefulTextFromReply(newContent?.body ?: clearContent?.body ?: "") to null + return TextContent(extractUsefulTextFromReply(newContent?.body ?: clearContent?.body ?: "")) } - return (newContent?.body ?: clearContent?.body ?: "") to (newContent?.formattedBody - ?: clearContent?.formattedBody) + return TextContent(newContent?.body ?: clearContent?.body ?: "", newContent?.formattedBody ?: clearContent?.formattedBody) } } From 7c59bcc928a0ba5fbbfa74f7f518c6eaaef55611 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 21 May 2020 00:41:36 +0200 Subject: [PATCH 5/7] Only "org.matrix.custom.html" is supported --- .../api/session/room/model/message/MessageTextContent.kt | 2 +- .../home/room/detail/timeline/factory/MessageItemFactory.kt | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageTextContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageTextContent.kt index cc5bb1f774..97923fa99e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageTextContent.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageTextContent.kt @@ -34,7 +34,7 @@ data class MessageTextContent( @Json(name = "body") override val body: String, /** - * The format used in the formatted_body. Currently only org.matrix.custom.html is supported. + * The format used in the formatted_body. Currently only "org.matrix.custom.html" is supported. */ @Json(name = "format") val format: String? = null, diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MessageItemFactory.kt index ffb71a38c5..9bca721df3 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MessageItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MessageItemFactory.kt @@ -31,6 +31,7 @@ import im.vector.matrix.android.api.session.room.model.message.MessageAudioConte import im.vector.matrix.android.api.session.room.model.message.MessageContent import im.vector.matrix.android.api.session.room.model.message.MessageEmoteContent import im.vector.matrix.android.api.session.room.model.message.MessageFileContent +import im.vector.matrix.android.api.session.room.model.message.MessageFormat import im.vector.matrix.android.api.session.room.model.message.MessageImageInfoContent import im.vector.matrix.android.api.session.room.model.message.MessageNoticeContent import im.vector.matrix.android.api.session.room.model.message.MessageOptionsContent @@ -350,7 +351,7 @@ class MessageItemFactory @Inject constructor( highlight: Boolean, callback: TimelineEventController.Callback?, attributes: AbsMessageItem.Attributes): VectorEpoxyModel<*>? { - val isFormatted = messageContent.formattedBody.isNullOrBlank().not() + val isFormatted = messageContent.formattedBody.takeIf { messageContent.format == MessageFormat.FORMAT_MATRIX_HTML }.isNullOrBlank().not() return if (isFormatted) { // First detect if the message contains some code block(s) or inline code val localFormattedBody = htmlRenderer.get().parse(messageContent.body) as Document From b75b29984792a59417418687e9c9d0b6246496c1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 21 May 2020 01:05:47 +0200 Subject: [PATCH 6/7] Create MessageContentWithFormattedBody interface --- .../MessageContentWithFormattedBody.kt | 35 +++++++++++++++++++ .../room/model/message/MessageEmoteContent.kt | 8 ++--- .../model/message/MessageNoticeContent.kt | 8 ++--- .../room/model/message/MessageTextContent.kt | 6 ++-- .../room/send/LocalEchoEventFactory.kt | 7 ++-- .../timeline/factory/MessageItemFactory.kt | 3 +- 6 files changed, 50 insertions(+), 17 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageContentWithFormattedBody.kt diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageContentWithFormattedBody.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageContentWithFormattedBody.kt new file mode 100644 index 0000000000..cebaf9b8c8 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageContentWithFormattedBody.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.matrix.android.api.session.room.model.message + +interface MessageContentWithFormattedBody : MessageContent { + /** + * The format used in the formatted_body. Currently only "org.matrix.custom.html" is supported. + */ + val format: String? + + /** + * The formatted version of the body. This is required if format is specified. + */ + val formattedBody: String? + + /** + * Get the formattedBody, only if the format is equal to "org.matrix.custom.html" + */ + val matrixFormattedBody: String? + get() = formattedBody?.takeIf { format == MessageFormat.FORMAT_MATRIX_HTML } +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageEmoteContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageEmoteContent.kt index e7106a9755..7b63959f78 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageEmoteContent.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageEmoteContent.kt @@ -34,15 +34,15 @@ data class MessageEmoteContent( @Json(name = "body") override val body: String, /** - * The format used in the formatted_body. Currently only org.matrix.custom.html is supported. + * The format used in the formatted_body. Currently only "org.matrix.custom.html" is supported. */ - @Json(name = "format") val format: String? = null, + @Json(name = "format") override val format: String? = null, /** * The formatted version of the body. This is required if format is specified. */ - @Json(name = "formatted_body") val formattedBody: String? = null, + @Json(name = "formatted_body") override val formattedBody: String? = null, @Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null, @Json(name = "m.new_content") override val newContent: Content? = null -) : MessageContent +) : MessageContentWithFormattedBody diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageNoticeContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageNoticeContent.kt index e08e07e9da..41e63bb457 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageNoticeContent.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageNoticeContent.kt @@ -34,15 +34,15 @@ data class MessageNoticeContent( @Json(name = "body") override val body: String, /** - * The format used in the formatted_body. Currently only org.matrix.custom.html is supported. + * The format used in the formatted_body. Currently only "org.matrix.custom.html" is supported. */ - @Json(name = "format") val format: String? = null, + @Json(name = "format") override val format: String? = null, /** * The formatted version of the body. This is required if format is specified. */ - @Json(name = "formatted_body") val formattedBody: String? = null, + @Json(name = "formatted_body") override val formattedBody: String? = null, @Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null, @Json(name = "m.new_content") override val newContent: Content? = null -) : MessageContent +) : MessageContentWithFormattedBody diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageTextContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageTextContent.kt index 97923fa99e..d6c54e3ff5 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageTextContent.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageTextContent.kt @@ -36,13 +36,13 @@ data class MessageTextContent( /** * The format used in the formatted_body. Currently only "org.matrix.custom.html" is supported. */ - @Json(name = "format") val format: String? = null, + @Json(name = "format") override val format: String? = null, /** * The formatted version of the body. This is required if format is specified. */ - @Json(name = "formatted_body") val formattedBody: String? = null, + @Json(name = "formatted_body") override val formattedBody: String? = null, @Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null, @Json(name = "m.new_content") override val newContent: Content? = null -) : MessageContent +) : MessageContentWithFormattedBody diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt index 9a96e78b24..2a24094b5d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/LocalEchoEventFactory.kt @@ -35,6 +35,7 @@ import im.vector.matrix.android.api.session.room.model.message.FileInfo import im.vector.matrix.android.api.session.room.model.message.ImageInfo import im.vector.matrix.android.api.session.room.model.message.MessageAudioContent import im.vector.matrix.android.api.session.room.model.message.MessageContent +import im.vector.matrix.android.api.session.room.model.message.MessageContentWithFormattedBody import im.vector.matrix.android.api.session.room.model.message.MessageFileContent import im.vector.matrix.android.api.session.room.model.message.MessageFormat import im.vector.matrix.android.api.session.room.model.message.MessageImageContent @@ -442,10 +443,8 @@ internal class LocalEchoEventFactory @Inject constructor( MessageType.MSGTYPE_TEXT, MessageType.MSGTYPE_NOTICE -> { var formattedText: String? = null - if (content is MessageTextContent) { - if (content.format == MessageFormat.FORMAT_MATRIX_HTML) { - formattedText = content.formattedBody - } + if (content is MessageContentWithFormattedBody) { + formattedText = content.matrixFormattedBody } val isReply = content.isReply() || originalContent.isReply() return if (isReply) { diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MessageItemFactory.kt index 9bca721df3..9601327861 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MessageItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MessageItemFactory.kt @@ -31,7 +31,6 @@ import im.vector.matrix.android.api.session.room.model.message.MessageAudioConte import im.vector.matrix.android.api.session.room.model.message.MessageContent import im.vector.matrix.android.api.session.room.model.message.MessageEmoteContent import im.vector.matrix.android.api.session.room.model.message.MessageFileContent -import im.vector.matrix.android.api.session.room.model.message.MessageFormat import im.vector.matrix.android.api.session.room.model.message.MessageImageInfoContent import im.vector.matrix.android.api.session.room.model.message.MessageNoticeContent import im.vector.matrix.android.api.session.room.model.message.MessageOptionsContent @@ -351,7 +350,7 @@ class MessageItemFactory @Inject constructor( highlight: Boolean, callback: TimelineEventController.Callback?, attributes: AbsMessageItem.Attributes): VectorEpoxyModel<*>? { - val isFormatted = messageContent.formattedBody.takeIf { messageContent.format == MessageFormat.FORMAT_MATRIX_HTML }.isNullOrBlank().not() + val isFormatted = messageContent.matrixFormattedBody.isNullOrBlank().not() return if (isFormatted) { // First detect if the message contains some code block(s) or inline code val localFormattedBody = htmlRenderer.get().parse(messageContent.body) as Document From 330a33a0e846c3f82d27c1e07fbde60eecb5bb9e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 21 May 2020 01:47:17 +0200 Subject: [PATCH 7/7] Render formatted_body for m.notice and m.emote (Fixes #1196) --- CHANGES.md | 1 + .../MessageContentWithFormattedBody.kt | 4 +-- .../timeline/factory/MessageItemFactory.kt | 32 ++++++++++++------- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 2c7e734600..365ec0c8fc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,7 @@ Features ✨: Improvements 🙌: - Better connectivity lost indicator when airplane mode is on - Add a setting to hide redacted events (#951) + - Render formatted_body for m.notice and m.emote (#1196) Bugfix 🐛: - After jump to unread, newer messages are never loaded (#1008) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageContentWithFormattedBody.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageContentWithFormattedBody.kt index cebaf9b8c8..b51e3eb841 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageContentWithFormattedBody.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageContentWithFormattedBody.kt @@ -28,8 +28,8 @@ interface MessageContentWithFormattedBody : MessageContent { val formattedBody: String? /** - * Get the formattedBody, only if the format is equal to "org.matrix.custom.html" + * Get the formattedBody, only if not blank and if the format is equal to "org.matrix.custom.html" */ val matrixFormattedBody: String? - get() = formattedBody?.takeIf { format == MessageFormat.FORMAT_MATRIX_HTML } + get() = formattedBody?.takeIf { it.isNotBlank() && format == MessageFormat.FORMAT_MATRIX_HTML } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MessageItemFactory.kt index 9601327861..96abe1ff40 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MessageItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MessageItemFactory.kt @@ -29,6 +29,7 @@ import im.vector.matrix.android.api.session.events.model.RelationType import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.room.model.message.MessageAudioContent import im.vector.matrix.android.api.session.room.model.message.MessageContent +import im.vector.matrix.android.api.session.room.model.message.MessageContentWithFormattedBody import im.vector.matrix.android.api.session.room.model.message.MessageEmoteContent import im.vector.matrix.android.api.session.room.model.message.MessageFileContent import im.vector.matrix.android.api.session.room.model.message.MessageImageInfoContent @@ -462,14 +463,14 @@ class MessageItemFactory @Inject constructor( highlight: Boolean, callback: TimelineEventController.Callback?, attributes: AbsMessageItem.Attributes): MessageTextItem? { - val message = messageContent.body.let { - val formattedBody = span { - text = it - textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary) - textStyle = "italic" - } - formattedBody.linkify(callback) + val formattedBody = span { + text = messageContent.getHtmlBody() + textColor = colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary) + textStyle = "italic" } + + val message = formattedBody.linkify(callback) + return MessageTextItem_() .leftGuideline(avatarSizeProvider.leftGuideline) .attributes(attributes) @@ -483,10 +484,12 @@ class MessageItemFactory @Inject constructor( highlight: Boolean, callback: TimelineEventController.Callback?, attributes: AbsMessageItem.Attributes): MessageTextItem? { - val message = messageContent.body.let { - val formattedBody = "* ${informationData.memberName} $it" - formattedBody.linkify(callback) - } + val formattedBody = SpannableStringBuilder() + formattedBody.append("* ${informationData.memberName} ") + formattedBody.append(messageContent.getHtmlBody()) + + val message = formattedBody.linkify(callback) + return MessageTextItem_() .apply { if (informationData.hasBeenEdited) { @@ -502,6 +505,13 @@ class MessageItemFactory @Inject constructor( .movementMethod(createLinkMovementMethod(callback)) } + private fun MessageContentWithFormattedBody.getHtmlBody(): CharSequence { + return matrixFormattedBody + ?.let { htmlCompressor.compress(it) } + ?.let { htmlRenderer.get().render(it) } + ?: body + } + private fun buildRedactedItem(attributes: AbsMessageItem.Attributes, highlight: Boolean): RedactedMessageItem? { return RedactedMessageItem_()