diff --git a/CHANGES.md b/CHANGES.md index 4523eeaf5d..10e0b0dc01 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ Improvements 🙌: - Search reaction by name or keyword in emoji picker - Handle code tags (#567) - Support spoiler messages + - Support m.sticker and m.room.join_rules events in timeline Other changes: - Markdown set to off by default (#412) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomJoinRules.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomJoinRules.kt new file mode 100644 index 0000000000..d7cf8678c3 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomJoinRules.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2019 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 + +import com.squareup.moshi.Json + +/** + * Enum for [RoomJoinRulesContent] : https://matrix.org/docs/spec/client_server/r0.4.0#m-room-join-rules + */ +enum class RoomJoinRules(val value: String) { + + @Json(name = "public") + PUBLIC("public"), + + @Json(name = "invite") + INVITE("invite"), + + @Json(name = "knock") + KNOCK("knock"), + + @Json(name = "private") + PRIVATE("private") +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomJoinRulesContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomJoinRulesContent.kt new file mode 100644 index 0000000000..cf6b182e2d --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomJoinRulesContent.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2019 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 + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * Class representing the EventType.STATE_ROOM_JOIN_RULES state event content + */ +@JsonClass(generateAdapter = true) +data class RoomJoinRulesContent( + @Json(name = "join_rule") val joinRules: RoomJoinRules? = null +) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageImageContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageImageContent.kt index 107a8b276d..fbac261802 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageImageContent.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageImageContent.kt @@ -38,7 +38,7 @@ data class MessageImageContent( /** * Metadata about the image referred to in url. */ - @Json(name = "info") val info: ImageInfo? = null, + @Json(name = "info") override val info: ImageInfo? = null, /** * Required. Required if the file is unencrypted. The URL (typically MXC URI) to the image. @@ -52,4 +52,4 @@ data class MessageImageContent( * Required if the file is encrypted. Information on the encrypted file, as specified in End-to-end encryption. */ @Json(name = "file") override val encryptedFileInfo: EncryptedFileInfo? = null -) : MessageEncryptedContent +) : MessageImageInfoContent diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageImageInfoContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageImageInfoContent.kt new file mode 100644 index 0000000000..9087a45b4c --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageImageInfoContent.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2019 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 + +/** + * A content with image information + */ +interface MessageImageInfoContent : MessageEncryptedContent { + val info: ImageInfo? +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageStickerContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageStickerContent.kt new file mode 100644 index 0000000000..d1b4a5c3cb --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/message/MessageStickerContent.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2019 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 + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass +import im.vector.matrix.android.api.session.events.model.Content +import im.vector.matrix.android.api.session.room.model.relation.RelationDefaultContent +import im.vector.matrix.android.internal.crypto.model.rest.EncryptedFileInfo + +@JsonClass(generateAdapter = true) +data class MessageStickerContent( + /** + * Set in local, not from server + */ + override val type: String = MessageType.MSGTYPE_STICKER_LOCAL, + + /** + * Required. A textual representation of the image. This could be the alt text of the image, the filename of the image, + * or some kind of content description for accessibility e.g. 'image attachment'. + */ + @Json(name = "body") override val body: String, + + /** + * Metadata about the image referred to in url. + */ + @Json(name = "info") override val info: ImageInfo? = null, + + /** + * Required. Required if the file is unencrypted. The URL (typically MXC URI) to the image. + */ + @Json(name = "url") override val url: String? = null, + + @Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null, + @Json(name = "m.new_content") override val newContent: Content? = null, + + /** + * Required if the file is encrypted. Information on the encrypted file, as specified in End-to-end encryption. + */ + @Json(name = "file") override val encryptedFileInfo: EncryptedFileInfo? = null +) : MessageImageInfoContent 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 c05383de4e..ad747efee9 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 @@ -23,6 +23,7 @@ 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.util.ContentUtils.extractUsefulTextFromReply import im.vector.matrix.android.internal.crypto.model.event.EncryptedEventContent @@ -99,8 +100,14 @@ fun TimelineEvent.getEditedEventId(): String? { /** * Get last MessageContent, after a possible edition */ -fun TimelineEvent.getLastMessageContent(): MessageContent? = annotations?.editSummary?.aggregatedContent?.toModel() +fun TimelineEvent.getLastMessageContent(): MessageContent? { + return if (root.getClearType() == EventType.STICKER) { + root.getClearContent().toModel() + } else { + annotations?.editSummary?.aggregatedContent?.toModel() ?: root.getClearContent().toModel() + } +} /** * Get last Message body, after a possible edition @@ -110,7 +117,7 @@ fun TimelineEvent.getLastMessageBody(): String? { if (lastMessageContent != null) { return lastMessageContent.newContent?.toModel()?.body - ?: lastMessageContent.body + ?: lastMessageContent.body } return null diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt index 4643c30f4a..6fdbf94590 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt @@ -877,7 +877,7 @@ class RoomDetailFragment @Inject constructor( vectorBaseActivity.notImplemented("encrypted message click") } - override fun onImageMessageClicked(messageImageContent: MessageImageContent, mediaData: ImageContentRenderer.Data, view: View) { + override fun onImageMessageClicked(messageImageContent: MessageImageInfoContent, mediaData: ImageContentRenderer.Data, view: View) { // TODO Use navigator val intent = ImageMediaViewerActivity.newIntent(vectorBaseActivity, mediaData, ViewCompat.getTransitionName(view)) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/TimelineEventController.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/TimelineEventController.kt index 8b1296482f..be2f1dd7e4 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/TimelineEventController.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/TimelineEventController.kt @@ -62,7 +62,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec fun onEventVisible(event: TimelineEvent) fun onRoomCreateLinkClicked(url: String) fun onEncryptedMessageClicked(informationData: MessageInformationData, view: View) - fun onImageMessageClicked(messageImageContent: MessageImageContent, mediaData: ImageContentRenderer.Data, view: View) + fun onImageMessageClicked(messageImageContent: MessageImageInfoContent, mediaData: ImageContentRenderer.Data, view: View) fun onVideoMessageClicked(messageVideoContent: MessageVideoContent, mediaData: VideoContentRenderer.Data, view: View) fun onFileMessageClicked(eventId: String, messageFileContent: MessageFileContent) fun onAudioMessageClicked(messageAudioContent: MessageAudioContent) 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 eacd702b7d..ac6c563099 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 @@ -89,7 +89,7 @@ class MessageItemFactory @Inject constructor( return defaultItemFactory.create(malformedText, informationData, highlight, callback) } if (messageContent.relatesTo?.type == RelationType.REPLACE - || event.isEncrypted() && event.root.content.toModel()?.relatesTo?.type == RelationType.REPLACE + || event.isEncrypted() && event.root.content.toModel()?.relatesTo?.type == RelationType.REPLACE ) { // This is an edit event, we should it when debugging as a notice event return noticeItemFactory.create(event, highlight, readMarkerVisible, callback) @@ -99,14 +99,14 @@ class MessageItemFactory @Inject constructor( // val all = event.root.toContent() // val ev = all.toModel() return when (messageContent) { - is MessageEmoteContent -> buildEmoteMessageItem(messageContent, informationData, highlight, callback, attributes) - is MessageTextContent -> buildItemForTextContent(messageContent, informationData, highlight, callback, attributes) - is MessageImageContent -> buildImageMessageItem(messageContent, informationData, highlight, callback, attributes) - is MessageNoticeContent -> buildNoticeMessageItem(messageContent, informationData, highlight, callback, attributes) - is MessageVideoContent -> buildVideoMessageItem(messageContent, informationData, highlight, callback, attributes) - is MessageFileContent -> buildFileMessageItem(messageContent, informationData, highlight, callback, attributes) - is MessageAudioContent -> buildAudioMessageItem(messageContent, informationData, highlight, callback, attributes) - else -> buildNotHandledMessageItem(messageContent, informationData, highlight, callback) + is MessageEmoteContent -> buildEmoteMessageItem(messageContent, informationData, highlight, callback, attributes) + is MessageTextContent -> buildItemForTextContent(messageContent, informationData, highlight, callback, attributes) + is MessageImageInfoContent -> buildImageMessageItem(messageContent, informationData, highlight, callback, attributes) + is MessageNoticeContent -> buildNoticeMessageItem(messageContent, informationData, highlight, callback, attributes) + is MessageVideoContent -> buildVideoMessageItem(messageContent, informationData, highlight, callback, attributes) + is MessageFileContent -> buildFileMessageItem(messageContent, informationData, highlight, callback, attributes) + is MessageAudioContent -> buildAudioMessageItem(messageContent, informationData, highlight, callback, attributes) + else -> buildNotHandledMessageItem(messageContent, informationData, highlight, callback) } } @@ -157,7 +157,7 @@ class MessageItemFactory @Inject constructor( return defaultItemFactory.create(text, informationData, highlight, callback) } - private fun buildImageMessageItem(messageContent: MessageImageContent, + private fun buildImageMessageItem(messageContent: MessageImageInfoContent, @Suppress("UNUSED_PARAMETER") informationData: MessageInformationData, highlight: Boolean, @@ -196,7 +196,7 @@ class MessageItemFactory @Inject constructor( val thumbnailData = ImageContentRenderer.Data( filename = messageContent.body, url = messageContent.videoInfo?.thumbnailFile?.url - ?: messageContent.videoInfo?.thumbnailUrl, + ?: messageContent.videoInfo?.thumbnailUrl, elementToDecrypt = messageContent.videoInfo?.thumbnailFile?.toElementToDecrypt(), height = messageContent.videoInfo?.height, maxHeight = maxHeight, @@ -326,9 +326,9 @@ class MessageItemFactory @Inject constructor( // nop } }, - editStart, - editEnd, - Spanned.SPAN_INCLUSIVE_EXCLUSIVE) + editStart, + editEnd, + Spanned.SPAN_INCLUSIVE_EXCLUSIVE) return spannable } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt index b396eb1f0e..618ca121c2 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt @@ -39,23 +39,25 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me val computedModel = try { when (event.root.getClearType()) { - EventType.MESSAGE -> messageItemFactory.create(event, nextEvent, highlight, readMarkerVisible, callback) + EventType.STICKER, + EventType.MESSAGE -> messageItemFactory.create(event, nextEvent, highlight, readMarkerVisible, callback) // State and call EventType.STATE_ROOM_TOMBSTONE, EventType.STATE_ROOM_NAME, EventType.STATE_ROOM_TOPIC, EventType.STATE_ROOM_MEMBER, + EventType.STATE_ROOM_JOIN_RULES, EventType.STATE_HISTORY_VISIBILITY, EventType.CALL_INVITE, EventType.CALL_HANGUP, EventType.CALL_ANSWER, EventType.REACTION, EventType.REDACTION, - EventType.ENCRYPTION -> noticeItemFactory.create(event, highlight, readMarkerVisible, callback) + EventType.ENCRYPTION -> noticeItemFactory.create(event, highlight, readMarkerVisible, callback) // State room create - EventType.STATE_ROOM_CREATE -> roomCreateItemFactory.create(event, callback) + EventType.STATE_ROOM_CREATE -> roomCreateItemFactory.create(event, callback) // Crypto - EventType.ENCRYPTED -> { + EventType.ENCRYPTED -> { if (event.root.isRedacted()) { // Redacted event, let the MessageItemFactory handle it messageItemFactory.create(event, nextEvent, highlight, readMarkerVisible, callback) @@ -65,9 +67,8 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me } // Unhandled event types (yet) - EventType.STATE_ROOM_THIRD_PARTY_INVITE, - EventType.STICKER -> defaultItemFactory.create(event, highlight, readMarkerVisible, callback) - else -> { + EventType.STATE_ROOM_THIRD_PARTY_INVITE -> defaultItemFactory.create(event, highlight, readMarkerVisible, callback) + else -> { Timber.v("Type ${event.root.getClearType()} not handled") null } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/format/NoticeEventFormatter.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/format/NoticeEventFormatter.kt index 9a86420277..a3910664a2 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/format/NoticeEventFormatter.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/format/NoticeEventFormatter.kt @@ -22,6 +22,8 @@ import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.room.model.Membership import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibility import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibilityContent +import im.vector.matrix.android.api.session.room.model.RoomJoinRules +import im.vector.matrix.android.api.session.room.model.RoomJoinRulesContent import im.vector.matrix.android.api.session.room.model.RoomMember import im.vector.matrix.android.api.session.room.model.RoomNameContent import im.vector.matrix.android.api.session.room.model.RoomTopicContent @@ -38,6 +40,7 @@ class NoticeEventFormatter @Inject constructor(private val sessionHolder: Active fun format(timelineEvent: TimelineEvent): CharSequence? { return when (val type = timelineEvent.root.getClearType()) { + EventType.STATE_ROOM_JOIN_RULES -> formatJoinRulesEvent(timelineEvent.root, timelineEvent.getDisambiguatedDisplayName()) EventType.STATE_ROOM_NAME -> formatRoomNameEvent(timelineEvent.root, timelineEvent.getDisambiguatedDisplayName()) EventType.STATE_ROOM_TOPIC -> formatRoomTopicEvent(timelineEvent.root, timelineEvent.getDisambiguatedDisplayName()) EventType.STATE_ROOM_MEMBER -> formatRoomMemberEvent(timelineEvent.root, timelineEvent.getDisambiguatedDisplayName()) @@ -58,6 +61,7 @@ class NoticeEventFormatter @Inject constructor(private val sessionHolder: Active fun format(event: Event, senderName: String?): CharSequence? { return when (val type = event.getClearType()) { + EventType.STATE_ROOM_JOIN_RULES -> formatJoinRulesEvent(event, senderName) EventType.STATE_ROOM_NAME -> formatRoomNameEvent(event, senderName) EventType.STATE_ROOM_TOPIC -> formatRoomTopicEvent(event, senderName) EventType.STATE_ROOM_MEMBER -> formatRoomMemberEvent(event, senderName) @@ -220,4 +224,13 @@ class NoticeEventFormatter @Inject constructor(private val sessionHolder: Active else -> null } } + + private fun formatJoinRulesEvent(event: Event, senderName: String?): CharSequence? { + val content = event.getClearContent().toModel() ?: return null + return when (content.joinRules) { + RoomJoinRules.INVITE -> stringProvider.getString(R.string.room_join_rules_invite, senderName) + RoomJoinRules.PUBLIC -> stringProvider.getString(R.string.room_join_rules_public, senderName) + else -> null + } + } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/TimelineDisplayableEvents.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/TimelineDisplayableEvents.kt index f40b8e6f6d..1cd851f8c8 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/TimelineDisplayableEvents.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/TimelineDisplayableEvents.kt @@ -36,7 +36,8 @@ object TimelineDisplayableEvents { EventType.STATE_ROOM_THIRD_PARTY_INVITE, EventType.STICKER, EventType.STATE_ROOM_CREATE, - EventType.STATE_ROOM_TOMBSTONE + EventType.STATE_ROOM_TOMBSTONE, + EventType.STATE_ROOM_JOIN_RULES ) val DEBUG_DISPLAYABLE_TYPES = DISPLAYABLE_TYPES + listOf( diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryItemFactory.kt index f977fe80fd..85652c4139 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryItemFactory.kt @@ -18,10 +18,9 @@ package im.vector.riotx.features.home.room.list import android.view.View 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.Membership import im.vector.matrix.android.api.session.room.model.RoomSummary -import im.vector.matrix.android.api.session.room.model.message.MessageContent +import im.vector.matrix.android.api.session.room.timeline.getLastMessageContent import im.vector.riotx.R import im.vector.riotx.core.date.VectorDateFormatter import im.vector.riotx.core.epoxy.VectorEpoxyModel @@ -97,9 +96,9 @@ class RoomSummaryItemFactory @Inject constructor(private val noticeEventFormatte latestFormattedEvent = if (latestEvent.root.isEncrypted() && latestEvent.root.mxDecryptionResult == null) { stringProvider.getString(R.string.encrypted_message) - } else if (latestEvent.root.getClearType() == EventType.MESSAGE) { + } else if (latestEvent.root.getClearType() == EventType.MESSAGE || latestEvent.root.getClearType() == EventType.STICKER) { val senderName = latestEvent.getDisambiguatedDisplayName() - val content = latestEvent.root.getClearContent()?.toModel() + val content = latestEvent.getLastMessageContent() val message = content?.body ?: "" if (roomSummary.isDirect.not()) { span { diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml index 6e5b5da92e..8d8be693e1 100644 --- a/vector/src/main/res/values/strings_riotX.xml +++ b/vector/src/main/res/values/strings_riotX.xml @@ -19,4 +19,9 @@ Long click on a room to see more options + + %1$s made the room public to whoever knows the link. + %1$s made the room invite only. + +