Skip to content

Commit 24e1740

Browse files
authored
Merge pull request #8151 from vector-im/fix/mna/edited-reply-parsing
[Timeline]: Editing a reply from iOS breaks the "in reply to" rendering (PSG-1168)
2 parents 7938eac + ac0bdb7 commit 24e1740

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

changelog.d/8150.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[Timeline]: Editing a reply from iOS breaks the "in reply to" rendering

matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEvent.kt

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import org.matrix.android.sdk.api.session.events.model.isLiveLocation
2828
import org.matrix.android.sdk.api.session.events.model.isPoll
2929
import org.matrix.android.sdk.api.session.events.model.isReply
3030
import org.matrix.android.sdk.api.session.events.model.isSticker
31+
import org.matrix.android.sdk.api.session.events.model.toContent
3132
import org.matrix.android.sdk.api.session.events.model.toModel
3233
import org.matrix.android.sdk.api.session.room.model.EventAnnotationsSummary
3334
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
3637
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
3738
import org.matrix.android.sdk.api.session.room.model.message.MessageContentWithFormattedBody
3839
import org.matrix.android.sdk.api.session.room.model.message.MessageEndPollContent
40+
import org.matrix.android.sdk.api.session.room.model.message.MessageFormat
3941
import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent
4042
import org.matrix.android.sdk.api.session.room.model.message.MessageStickerContent
4143
import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent
@@ -157,7 +159,39 @@ fun TimelineEvent.getLastMessageContent(): MessageContent? {
157159
}
158160

159161
fun TimelineEvent.getLastEditNewContent(): Content? {
160-
return annotations?.editSummary?.latestEdit?.getClearContent()?.toModel<MessageContent>()?.newContent
162+
val lastContent = annotations?.editSummary?.latestEdit?.getClearContent()?.toModel<MessageContent>()?.newContent
163+
return if (isReply()) {
164+
val previousFormattedBody = root.getClearContent().toModel<MessageTextContent>()?.formattedBody
165+
if (previousFormattedBody?.isNotEmpty() == true) {
166+
val lastMessageContent = lastContent.toModel<MessageTextContent>()
167+
lastMessageContent?.let { ensureCorrectFormattedBodyInTextReply(it, previousFormattedBody) }?.toContent() ?: lastContent
168+
} else {
169+
lastContent
170+
}
171+
} else {
172+
lastContent
173+
}
174+
}
175+
176+
private const val MX_REPLY_END_TAG = "</mx-reply>"
177+
178+
/**
179+
* Not every client sends a formatted body in the last edited event since this is not required in the
180+
* [Matrix specification](https://spec.matrix.org/v1.4/client-server-api/#applying-mnew_content).
181+
* We must ensure there is one so that it is still considered as a reply when rendering the message.
182+
*/
183+
private fun ensureCorrectFormattedBodyInTextReply(messageTextContent: MessageTextContent, previousFormattedBody: String): MessageTextContent {
184+
return when {
185+
messageTextContent.formattedBody.isNullOrEmpty() && previousFormattedBody.contains(MX_REPLY_END_TAG) -> {
186+
// take previous formatted body with the new body content
187+
val newFormattedBody = previousFormattedBody.replaceAfterLast(MX_REPLY_END_TAG, messageTextContent.body)
188+
messageTextContent.copy(
189+
formattedBody = newFormattedBody,
190+
format = MessageFormat.FORMAT_MATRIX_HTML,
191+
)
192+
}
193+
else -> messageTextContent
194+
}
161195
}
162196

163197
private fun TimelineEvent.getLastPollEditNewContent(): Content? {

0 commit comments

Comments
 (0)