From db512d63df090283aace053381e3393dfc33a94a Mon Sep 17 00:00:00 2001 From: Maxime NATUREL <46314705+mnaturel@users.noreply.github.com> Date: Mon, 20 Feb 2023 15:55:17 +0100 Subject: [PATCH 1/2] Adding changelog entry --- changelog.d/8150.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/8150.bugfix diff --git a/changelog.d/8150.bugfix b/changelog.d/8150.bugfix new file mode 100644 index 0000000000..9c67b2ba37 --- /dev/null +++ b/changelog.d/8150.bugfix @@ -0,0 +1 @@ +[Timeline]: Editing a reply from iOS breaks the "in reply to" rendering From ac0bdb7dfe630b516dad479ecde56b9bbaa5d727 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL <46314705+mnaturel@users.noreply.github.com> Date: Mon, 20 Feb 2023 15:55:49 +0100 Subject: [PATCH 2/2] Ensure edited text reply contains a formatted body --- .../session/room/timeline/TimelineEvent.kt | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEvent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEvent.kt index 3aa480094c..a49c20ccbb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEvent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEvent.kt @@ -28,6 +28,7 @@ import org.matrix.android.sdk.api.session.events.model.isLiveLocation import org.matrix.android.sdk.api.session.events.model.isPoll import org.matrix.android.sdk.api.session.events.model.isReply import org.matrix.android.sdk.api.session.events.model.isSticker +import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.model.EventAnnotationsSummary import org.matrix.android.sdk.api.session.room.model.ReadReceipt @@ -36,6 +37,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocati import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.model.message.MessageContentWithFormattedBody import org.matrix.android.sdk.api.session.room.model.message.MessageEndPollContent +import org.matrix.android.sdk.api.session.room.model.message.MessageFormat import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent import org.matrix.android.sdk.api.session.room.model.message.MessageStickerContent import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent @@ -157,7 +159,39 @@ fun TimelineEvent.getLastMessageContent(): MessageContent? { } fun TimelineEvent.getLastEditNewContent(): Content? { - return annotations?.editSummary?.latestEdit?.getClearContent()?.toModel()?.newContent + val lastContent = annotations?.editSummary?.latestEdit?.getClearContent()?.toModel()?.newContent + return if (isReply()) { + val previousFormattedBody = root.getClearContent().toModel()?.formattedBody + if (previousFormattedBody?.isNotEmpty() == true) { + val lastMessageContent = lastContent.toModel() + lastMessageContent?.let { ensureCorrectFormattedBodyInTextReply(it, previousFormattedBody) }?.toContent() ?: lastContent + } else { + lastContent + } + } else { + lastContent + } +} + +private const val MX_REPLY_END_TAG = "" + +/** + * Not every client sends a formatted body in the last edited event since this is not required in the + * [Matrix specification](https://spec.matrix.org/v1.4/client-server-api/#applying-mnew_content). + * We must ensure there is one so that it is still considered as a reply when rendering the message. + */ +private fun ensureCorrectFormattedBodyInTextReply(messageTextContent: MessageTextContent, previousFormattedBody: String): MessageTextContent { + return when { + messageTextContent.formattedBody.isNullOrEmpty() && previousFormattedBody.contains(MX_REPLY_END_TAG) -> { + // take previous formatted body with the new body content + val newFormattedBody = previousFormattedBody.replaceAfterLast(MX_REPLY_END_TAG, messageTextContent.body) + messageTextContent.copy( + formattedBody = newFormattedBody, + format = MessageFormat.FORMAT_MATRIX_HTML, + ) + } + else -> messageTextContent + } } private fun TimelineEvent.getLastPollEditNewContent(): Content? {