From da06695ab76cc82e9aab39c4d12583d9592b0239 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 24 Jul 2020 15:05:54 +0200 Subject: [PATCH] Relation content should be checked in encrypted content and not the decrypted one --- .../android/api/session/events/model/Event.kt | 16 +++++++++++- .../room/model/message/MessageContent.kt | 4 --- .../session/room/timeline/TimelineEvent.kt | 25 ++++++++++++++----- .../room/send/LocalEchoEventFactory.kt | 13 +++++----- .../edithistory/ViewEditHistoryViewModel.kt | 6 ++--- .../format/DisplayableEventFormatter.kt | 8 +++--- 6 files changed, 46 insertions(+), 26 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/Event.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/Event.kt index 975e72e088..2fbd5f4d4d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/Event.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/Event.kt @@ -21,9 +21,11 @@ import com.squareup.moshi.JsonClass import im.vector.matrix.android.api.session.crypto.MXCryptoError import im.vector.matrix.android.api.session.room.model.message.MessageContent import im.vector.matrix.android.api.session.room.model.message.MessageType +import im.vector.matrix.android.api.session.room.model.relation.RelationDefaultContent import im.vector.matrix.android.api.session.room.send.SendState import im.vector.matrix.android.api.util.JsonDict import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult +import im.vector.matrix.android.internal.crypto.model.event.EncryptedEventContent import im.vector.matrix.android.internal.di.MoshiProvider import org.json.JSONObject import timber.log.Timber @@ -240,6 +242,18 @@ fun Event.isFileMessage(): Boolean { return getClearType() == EventType.MESSAGE && when (getClearContent()?.toModel()?.msgType) { MessageType.MSGTYPE_FILE -> true - else -> false + else -> false } } + +fun Event.getRelationContent(): RelationDefaultContent? { + return if (isEncrypted()) { + content.toModel()?.relatesTo + } else { + content.toModel()?.relatesTo + } +} + +fun Event.isReply(): Boolean { + return getRelationContent()?.inReplyTo?.eventId != null +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageContent.kt index bc5228e5e8..32c446cb54 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageContent.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageContent.kt @@ -25,7 +25,3 @@ interface MessageContent { val relatesTo: RelationDefaultContent? val newContent: Content? } - -fun MessageContent?.isReply(): Boolean { - return this?.relatesTo?.inReplyTo?.eventId != null -} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/timeline/TimelineEvent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/timeline/TimelineEvent.kt index 273ea2366a..5f0db3e206 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/timeline/TimelineEvent.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/timeline/TimelineEvent.kt @@ -20,15 +20,16 @@ import im.vector.matrix.android.BuildConfig import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.events.model.RelationType +import im.vector.matrix.android.api.session.events.model.getRelationContent +import im.vector.matrix.android.api.session.events.model.isReply import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary import im.vector.matrix.android.api.session.room.model.ReadReceipt import im.vector.matrix.android.api.session.room.model.message.MessageContent import im.vector.matrix.android.api.session.room.model.message.MessageStickerContent -import im.vector.matrix.android.api.session.room.model.message.isReply +import im.vector.matrix.android.api.session.room.model.relation.RelationDefaultContent import im.vector.matrix.android.api.session.room.sender.SenderInfo import im.vector.matrix.android.api.util.ContentUtils.extractUsefulTextFromReply -import im.vector.matrix.android.internal.crypto.model.event.EncryptedEventContent /** * This data class is a wrapper around an Event. It allows to get useful data in the context of a timeline. @@ -88,11 +89,18 @@ data class TimelineEvent( */ fun TimelineEvent.hasBeenEdited() = annotations?.editSummary != null +/** + * Get the relation content if any + */ +fun TimelineEvent.getRelationContent(): RelationDefaultContent? { + return root.getRelationContent() +} + /** * Get the eventId which was edited by this event if any */ fun TimelineEvent.getEditedEventId(): String? { - return root.getClearContent().toModel()?.relatesTo?.takeIf { it.type == RelationType.REPLACE }?.eventId + return getRelationContent()?.takeIf { it.type == RelationType.REPLACE }?.eventId } /** @@ -121,11 +129,16 @@ fun TimelineEvent.getLastMessageBody(): String? { return null } +/** + * Returns true if it's a reply + */ +fun TimelineEvent.isReply(): Boolean { + return root.isReply() +} + fun TimelineEvent.getTextEditableContent(): String? { - val originalContent = root.getClearContent().toModel() ?: return null - val isReply = originalContent.isReply() || root.content.toModel()?.relatesTo?.inReplyTo?.eventId != null val lastContent = getLastMessageContent() - return if (isReply) { + return if (isReply()) { return extractUsefulTextFromReply(lastContent?.body ?: "") } else { lastContent?.body ?: "" 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 4e3c2481cd..ee52cf966f 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 @@ -30,7 +30,6 @@ import im.vector.matrix.android.api.session.events.model.LocalEcho import im.vector.matrix.android.api.session.events.model.RelationType import im.vector.matrix.android.api.session.events.model.UnsignedData import im.vector.matrix.android.api.session.events.model.toContent -import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.room.model.message.AudioInfo import im.vector.matrix.android.api.session.room.model.message.FileInfo import im.vector.matrix.android.api.session.room.model.message.ImageInfo @@ -50,13 +49,13 @@ import im.vector.matrix.android.api.session.room.model.message.OPTION_TYPE_POLL import im.vector.matrix.android.api.session.room.model.message.OptionItem import im.vector.matrix.android.api.session.room.model.message.ThumbnailInfo import im.vector.matrix.android.api.session.room.model.message.VideoInfo -import im.vector.matrix.android.api.session.room.model.message.isReply import im.vector.matrix.android.api.session.room.model.relation.ReactionContent import im.vector.matrix.android.api.session.room.model.relation.ReactionInfo import im.vector.matrix.android.api.session.room.model.relation.RelationDefaultContent 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.api.session.room.timeline.isReply import im.vector.matrix.android.internal.di.UserId import im.vector.matrix.android.internal.session.content.ThumbnailExtractor import im.vector.matrix.android.internal.session.room.send.pills.TextPillsUtils @@ -173,7 +172,7 @@ internal class LocalEchoEventFactory @Inject constructor( val userLink = originalEvent.root.senderId?.let { PermalinkFactory.createPermalink(it) } ?: "" - val body = bodyForReply(originalEvent.getLastMessageContent(), originalEvent.root.getClearContent().toModel()) + val body = bodyForReply(originalEvent.getLastMessageContent(), originalEvent.isReply()) val replyFormatted = REPLY_PATTERN.format( permalink, userLink, @@ -368,7 +367,7 @@ internal class LocalEchoEventFactory @Inject constructor( val userId = eventReplied.root.senderId ?: return null val userLink = PermalinkFactory.createPermalink(userId) ?: return null - val body = bodyForReply(eventReplied.getLastMessageContent(), eventReplied.root.getClearContent().toModel()) + val body = bodyForReply(eventReplied.getLastMessageContent(), eventReplied.isReply()) val replyFormatted = REPLY_PATTERN.format( permalink, userLink, @@ -414,10 +413,10 @@ internal class LocalEchoEventFactory @Inject constructor( /** * Returns a TextContent used for the fallback event representation in a reply message. - * We also pass the original content, because in case of an edit of a reply the last content is not + * In case of an edit of a reply the last content is not * himself a reply, but it will contain the fallbacks, so we have to trim them. */ - private fun bodyForReply(content: MessageContent?, originalContent: MessageContent?): TextContent { + private fun bodyForReply(content: MessageContent?, isReply: Boolean): TextContent { when (content?.msgType) { MessageType.MSGTYPE_EMOTE, MessageType.MSGTYPE_TEXT, @@ -426,7 +425,6 @@ internal class LocalEchoEventFactory @Inject constructor( if (content is MessageContentWithFormattedBody) { formattedText = content.matrixFormattedBody } - val isReply = content.isReply() || originalContent.isReply() return if (isReply) { TextContent(content.body, formattedText).removeInReplyFallbacks() } else { @@ -487,6 +485,7 @@ internal class LocalEchoEventFactory @Inject constructor( // // No whitespace because currently breaks temporary formatted text to Span const val REPLY_PATTERN = """
In reply to %s
%s
%s""" + // This is used to replace inner mx-reply tags val MX_REPLY_REGEX = ".*".toRegex() } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/edithistory/ViewEditHistoryViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/edithistory/ViewEditHistoryViewModel.kt index f03a1c8704..2180e18684 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/edithistory/ViewEditHistoryViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/edithistory/ViewEditHistoryViewModel.kt @@ -30,9 +30,7 @@ import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.crypto.MXCryptoError 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.MessageContent -import im.vector.matrix.android.api.session.room.model.message.isReply +import im.vector.matrix.android.api.session.events.model.isReply import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult import im.vector.riotx.core.date.VectorDateFormatter import im.vector.riotx.core.platform.EmptyAction @@ -113,7 +111,7 @@ class ViewEditHistoryViewModel @AssistedInject constructor(@Assisted } if (event.eventId == it.eventId) { - originalIsReply = it.getClearContent().toModel().isReply() + originalIsReply = it.isReply() } } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt index 0043cc10c5..42a8dd2604 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt @@ -19,11 +19,11 @@ package im.vector.riotx.features.home.room.detail.timeline.format import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.room.model.message.MessageType -import im.vector.matrix.android.api.session.room.model.message.isReply import im.vector.matrix.android.api.session.room.model.relation.ReactionContent 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.api.session.room.timeline.getTextEditableContent +import im.vector.matrix.android.api.session.room.timeline.isReply import im.vector.riotx.EmojiCompatWrapper import im.vector.riotx.R import im.vector.riotx.core.resources.ColorProvider @@ -79,13 +79,13 @@ class DisplayableEventFormatter @Inject constructor( return simpleFormat(senderName, stringProvider.getString(R.string.sent_a_file), appendAuthor) } MessageType.MSGTYPE_TEXT -> { - if (messageContent.isReply()) { + return if (timelineEvent.isReply()) { // Skip reply prefix, and show important // TODO add a reply image span ? - return simpleFormat(senderName, timelineEvent.getTextEditableContent() + simpleFormat(senderName, timelineEvent.getTextEditableContent() ?: messageContent.body, appendAuthor) } else { - return simpleFormat(senderName, messageContent.body, appendAuthor) + simpleFormat(senderName, messageContent.body, appendAuthor) } } else -> {