From 19183022972a38c246766853ee230dd7bc058ac6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 10 Jul 2019 11:29:47 +0200 Subject: [PATCH] Reply with formatted content --- .../room/model/relation/RelationService.kt | 3 +- .../room/relation/DefaultRelationService.kt | 4 +- .../session/room/send/DefaultSendService.kt | 2 +- .../room/send/LocalEchoEventFactory.kt | 48 +++++++++++-------- .../home/room/detail/RoomDetailViewModel.kt | 4 +- 5 files changed, 35 insertions(+), 26 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/relation/RelationService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/relation/RelationService.kt index 2a3c5b6d84..7b547c48e0 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/relation/RelationService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/relation/RelationService.kt @@ -77,8 +77,9 @@ interface RelationService { * https://matrix.org/docs/spec/client_server/r0.4.0.html#id350 * @param eventReplied the event referenced by the reply * @param replyText the reply text + * @param autoMarkdown If true, the SDK will generate a formatted HTML message from the body text if markdown syntax is present */ - fun replyToMessage(eventReplied: Event, replyText: String): Cancelable? + fun replyToMessage(eventReplied: Event, replyText: String, autoMarkdown: Boolean = false): Cancelable? fun getEventSummaryLive(eventId: String): LiveData } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt index 27270c3e94..58151f18f7 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt @@ -127,8 +127,8 @@ internal class DefaultRelationService @Inject constructor(private val context: C } - override fun replyToMessage(eventReplied: Event, replyText: String): Cancelable? { - val event = eventFactory.createReplyTextEvent(roomId, eventReplied, replyText)?.also { + override fun replyToMessage(eventReplied: Event, replyText: String, autoMarkdown: Boolean): Cancelable? { + val event = eventFactory.createReplyTextEvent(roomId, eventReplied, replyText, autoMarkdown)?.also { saveLocalEcho(it) } ?: return null diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt index 71a2c4bbf2..9a94b05b1f 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt @@ -59,7 +59,7 @@ internal class DefaultSendService @Inject constructor(private val context: Conte } override fun sendFormattedTextMessage(text: String, formattedText: String): Cancelable { - val event = localEchoEventFactory.createFormattedTextEvent(roomId, text, formattedText).also { + val event = localEchoEventFactory.createFormattedTextEvent(roomId, TextContent(text, formattedText)).also { saveLocalEcho(it) } 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 1550dba833..9d7cf08909 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 @@ -52,30 +52,41 @@ import javax.inject.Inject internal class LocalEchoEventFactory @Inject constructor(private val credentials: Credentials, private val stringProvider: StringProvider, private val roomSummaryUpdater: RoomSummaryUpdater) { + // TODO Inject + private val parser = Parser.builder().build() + // TODO Inject + private val renderer = HtmlRenderer.builder().build() fun createTextEvent(roomId: String, msgType: String, text: String, autoMarkdown: Boolean): Event { - if (autoMarkdown && msgType == MessageType.MSGTYPE_TEXT) { - val parser = Parser.builder().build() - val document = parser.parse(text) - val renderer = HtmlRenderer.builder().build() - val htmlText = renderer.render(document) - if (isFormattedTextPertinent(text, htmlText)) { //FIXME - return createFormattedTextEvent(roomId, text, htmlText) - } + if (msgType == MessageType.MSGTYPE_TEXT) { + return createFormattedTextEvent(roomId, createTextContent(text, autoMarkdown)) } val content = MessageTextContent(type = msgType, body = text) return createEvent(roomId, content) } + private fun createTextContent(text: String, autoMarkdown: Boolean): TextContent { + if (autoMarkdown) { + val document = parser.parse(text) + val htmlText = renderer.render(document) + + if (isFormattedTextPertinent(text, htmlText)) { + return TextContent(text, htmlText) + } + } + + return TextContent(text) + } + private fun isFormattedTextPertinent(text: String, htmlText: String?) = text != htmlText && htmlText != "

${text.trim()}

\n" - fun createFormattedTextEvent(roomId: String, text: String, formattedText: String): Event { + fun createFormattedTextEvent(roomId: String, textContent: TextContent): Event { val content = MessageTextContent( type = MessageType.MSGTYPE_TEXT, - format = MessageType.FORMAT_MATRIX_HTML, - body = text, - formattedBody = formattedText + format = if (textContent.formattedText == null) MessageType.FORMAT_MATRIX_HTML else null, + body = textContent.text, + formattedBody = textContent.formattedText ) return createEvent(roomId, content) } @@ -87,7 +98,7 @@ internal class LocalEchoEventFactory @Inject constructor(private val credentials newBodyAutoMarkdown: Boolean, msgType: String, compatibilityText: String): Event { - + // TODO Format newBodyText var newContent = MessageTextContent( type = MessageType.MSGTYPE_TEXT, body = newBodyText @@ -202,7 +213,7 @@ internal class LocalEchoEventFactory @Inject constructor(private val credentials type = MessageType.MSGTYPE_AUDIO, body = attachment.name ?: "audio", audioInfo = AudioInfo( - mimeType = attachment.mimeType ?: "audio/mpeg", + mimeType = attachment.mimeType.takeIf { it.isNotBlank() } ?: "audio/mpeg", size = attachment.size ), url = attachment.path @@ -215,7 +226,7 @@ internal class LocalEchoEventFactory @Inject constructor(private val credentials type = MessageType.MSGTYPE_FILE, body = attachment.name ?: "file", info = FileInfo( - mimeType = attachment.mimeType ?: "application/octet-stream", + mimeType = attachment.mimeType.takeIf { it.isNotBlank() } ?: "application/octet-stream", size = attachment.size ), url = attachment.path @@ -244,7 +255,7 @@ internal class LocalEchoEventFactory @Inject constructor(private val credentials return "$LOCAL_ID_PREFIX${UUID.randomUUID()}" } - fun createReplyTextEvent(roomId: String, eventReplied: Event, replyText: String): Event? { + fun createReplyTextEvent(roomId: String, eventReplied: Event, replyText: String, autoMarkdown: Boolean): Event? { //Fallbacks and event representation //TODO Add error/warning logs when any of this is null val permalink = PermalinkFactory.createPermalink(eventReplied) ?: return null @@ -266,7 +277,7 @@ internal class LocalEchoEventFactory @Inject constructor(private val credentials userLink, userId, body.takeFormatted(), - replyText + createTextContent(replyText, autoMarkdown).takeFormatted() ) // // > <@alice:example.org> This is the original body @@ -294,8 +305,7 @@ internal class LocalEchoEventFactory @Inject constructor(private val credentials } /** - * Returns a pair of used for the fallback event representation - * in a reply message. + * Returns a TextContent used for the fallback event representation in a reply message. */ private fun bodyForReply(content: MessageContent?): TextContent { when (content?.type) { 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 9e0fda9146..9c96677b78 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 @@ -47,8 +47,6 @@ import im.vector.riotx.core.utils.LiveEvent import im.vector.riotx.features.command.CommandParser import im.vector.riotx.features.command.ParsedCommand import im.vector.riotx.features.home.room.detail.timeline.helper.TimelineDisplayableEvents -import io.reactivex.Observable -import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.rxkotlin.subscribeBy import org.commonmark.parser.Parser import org.commonmark.renderer.html.HtmlRenderer @@ -272,7 +270,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro } SendMode.REPLY -> { state.selectedEvent?.let { - room.replyToMessage(it.root, action.text) + room.replyToMessage(it.root, action.text, action.autoMarkdown) setState { copy( sendMode = SendMode.REGULAR,