diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt index a9a1745b85..c43f7dcdd2 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt @@ -277,7 +277,7 @@ private fun MessagePreviewAndIndicatorRow( val messagePreview = if (room.isTombstoned) { stringResource(R.string.screen_roomlist_tombstoned_room_description) } else { - room.lastMessage.orEmpty() + room.latestEvent.orEmpty() } val annotatedMessagePreview = messagePreview as? AnnotatedString ?: AnnotatedString(text = messagePreview.toString()) Text( diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactory.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactory.kt index 62b34ba8de..935410e572 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactory.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactory.kt @@ -15,7 +15,7 @@ import io.element.android.libraries.core.extensions.orEmpty import io.element.android.libraries.dateformatter.api.DateFormatter import io.element.android.libraries.dateformatter.api.DateFormatterMode import io.element.android.libraries.designsystem.components.avatar.AvatarSize -import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter +import io.element.android.libraries.eventformatter.api.RoomLatestEventFormatter import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.roomlist.RoomSummary @@ -26,7 +26,7 @@ import kotlinx.collections.immutable.toImmutableList @Inject class RoomListRoomSummaryFactory( private val dateFormatter: DateFormatter, - private val roomLastMessageFormatter: RoomLastMessageFormatter, + private val roomLatestEventFormatter: RoomLatestEventFormatter, ) { fun create(roomSummary: RoomSummary): RoomListRoomSummary { val roomInfo = roomSummary.info @@ -40,13 +40,11 @@ class RoomListRoomSummaryFactory( numberOfUnreadNotifications = roomInfo.numUnreadNotifications, isMarkedUnread = roomInfo.isMarkedUnread, timestamp = dateFormatter.format( - timestamp = roomSummary.lastMessageTimestamp, + timestamp = roomSummary.latestEventTimestamp, mode = DateFormatterMode.TimeOrDate, useRelative = true, ), - lastMessage = roomSummary.lastMessage?.let { message -> - roomLastMessageFormatter.format(message.event, roomInfo.isDm) - }.orEmpty(), + latestEvent = roomLatestEventFormatter.format(roomSummary.latestEvent, roomInfo.isDm).orEmpty(), avatarData = avatarData, userDefinedNotificationMode = roomInfo.userDefinedNotificationMode, hasRoomCall = roomInfo.hasRoomCall, diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummary.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummary.kt index 215ded2081..aa983baf56 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummary.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummary.kt @@ -29,7 +29,7 @@ data class RoomListRoomSummary( val numberOfUnreadNotifications: Long, val isMarkedUnread: Boolean, val timestamp: String?, - val lastMessage: CharSequence?, + val latestEvent: CharSequence?, val avatarData: AvatarData, val userDefinedNotificationMode: RoomNotificationMode?, val hasRoomCall: Boolean, diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummaryProvider.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummaryProvider.kt index e00d7564ba..e88d6d0972 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummaryProvider.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummaryProvider.kt @@ -171,7 +171,7 @@ internal fun aRoomListRoomSummary( numberOfUnreadNotifications = numberOfUnreadNotifications, isMarkedUnread = isMarkedUnread, timestamp = timestamp, - lastMessage = lastMessage, + latestEvent = lastMessage, avatarData = avatarData, userDefinedNotificationMode = notificationMode, hasRoomCall = hasRoomCall, diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactoryTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactoryTest.kt index fd51c3b53e..941f889f69 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactoryTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactoryTest.kt @@ -10,12 +10,12 @@ package io.element.android.features.home.impl.datasource import io.element.android.libraries.dateformatter.api.DateFormatter import io.element.android.libraries.dateformatter.test.FakeDateFormatter -import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter +import io.element.android.libraries.eventformatter.api.RoomLatestEventFormatter fun aRoomListRoomSummaryFactory( dateFormatter: DateFormatter = FakeDateFormatter { _, _, _ -> "Today" }, - roomLastMessageFormatter: RoomLastMessageFormatter = RoomLastMessageFormatter { _, _ -> "Hey" } + roomLatestEventFormatter: RoomLatestEventFormatter = RoomLatestEventFormatter { _, _ -> "Hey" } ) = RoomListRoomSummaryFactory( dateFormatter = dateFormatter, - roomLastMessageFormatter = roomLastMessageFormatter + roomLatestEventFormatter = roomLatestEventFormatter ) diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/model/RoomListBaseRoomSummaryTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/model/RoomListBaseRoomSummaryTest.kt index 72465e15fd..cbf6c145ad 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/model/RoomListBaseRoomSummaryTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/model/RoomListBaseRoomSummaryTest.kt @@ -96,7 +96,7 @@ internal fun createRoomListRoomSummary( numberOfUnreadNotifications = numberOfUnreadNotifications, isMarkedUnread = isMarkedUnread, timestamp = timestamp, - lastMessage = "", + latestEvent = "", avatarData = AvatarData(id = A_ROOM_ID.value, name = A_ROOM_NAME, size = AvatarSize.RoomListItem), displayType = displayType, userDefinedNotificationMode = userDefinedNotificationMode, diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenterTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenterTest.kt index cf535e187d..cf636e26ca 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenterTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenterTest.kt @@ -35,8 +35,8 @@ import io.element.android.features.rageshake.test.logs.FakeAnnouncementService import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.dateformatter.api.DateFormatter import io.element.android.libraries.dateformatter.test.FakeDateFormatter -import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter -import io.element.android.libraries.eventformatter.test.FakeRoomLastMessageFormatter +import io.element.android.libraries.eventformatter.api.RoomLatestEventFormatter +import io.element.android.libraries.eventformatter.test.FakeRoomLatestEventFormatter import io.element.android.libraries.fullscreenintent.api.aFullScreenIntentPermissionsState import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId @@ -638,7 +638,7 @@ class RoomListPresenterTest { client: MatrixClient = FakeMatrixClient(), leaveRoomState: LeaveRoomState = aLeaveRoomState(), dateFormatter: DateFormatter = FakeDateFormatter(), - roomLastMessageFormatter: RoomLastMessageFormatter = FakeRoomLastMessageFormatter(), + roomLatestEventFormatter: RoomLatestEventFormatter = FakeRoomLatestEventFormatter(), sessionPreferencesStore: SessionPreferencesStore = InMemorySessionPreferencesStore(), analyticsService: AnalyticsService = FakeAnalyticsService(), filtersPresenter: Presenter = Presenter { aRoomListFiltersState() }, @@ -655,7 +655,7 @@ class RoomListPresenterTest { roomListService = client.roomListService, roomListRoomSummaryFactory = aRoomListRoomSummaryFactory( dateFormatter = dateFormatter, - roomLastMessageFormatter = roomLastMessageFormatter, + roomLatestEventFormatter = roomLatestEventFormatter, ), coroutineDispatchers = testCoroutineDispatchers(), notificationSettingsService = client.notificationSettingsService, diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListViewTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListViewTest.kt index 5c3bef26c4..7855180926 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListViewTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListViewTest.kt @@ -170,7 +170,7 @@ class RoomListViewTest { // Remove automatic initial events eventsRecorder.clear() - rule.onNodeWithText(room0.lastMessage!!.toString()).performClick() + rule.onNodeWithText(room0.latestEvent!!.toString()).performClick() } eventsRecorder.assertEmpty() @@ -192,7 +192,7 @@ class RoomListViewTest { ) // Remove automatic initial events eventsRecorder.clear() - rule.onNodeWithText(room0.lastMessage!!.toString()) + rule.onNodeWithText(room0.latestEvent!!.toString()) .performClick() .performClick() } @@ -214,7 +214,7 @@ class RoomListViewTest { // Remove automatic initial events eventsRecorder.clear() - rule.onNodeWithText(room0.lastMessage!!.toString()).performTouchInput { longClick() } + rule.onNodeWithText(room0.latestEvent!!.toString()).performTouchInput { longClick() } eventsRecorder.assertSingle(RoomListEvents.ShowContextMenu(room0)) } diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/search/RoomListSearchPresenterTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/search/RoomListSearchPresenterTest.kt index d21f3a09a8..dee0601915 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/search/RoomListSearchPresenterTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/search/RoomListSearchPresenterTest.kt @@ -14,7 +14,7 @@ import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.features.home.impl.datasource.aRoomListRoomSummaryFactory import io.element.android.libraries.dateformatter.test.FakeDateFormatter -import io.element.android.libraries.eventformatter.test.FakeRoomLastMessageFormatter +import io.element.android.libraries.eventformatter.test.FakeRoomLatestEventFormatter import io.element.android.libraries.matrix.api.roomlist.RoomListFilter import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.test.room.aRoomSummary @@ -126,7 +126,7 @@ fun TestScope.createRoomListSearchPresenter( roomListService = roomListService, roomSummaryFactory = aRoomListRoomSummaryFactory( dateFormatter = FakeDateFormatter(), - roomLastMessageFormatter = FakeRoomLastMessageFormatter(), + roomLatestEventFormatter = FakeRoomLatestEventFormatter(), ), coroutineDispatchers = testCoroutineDispatchers(), ), diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index 2e2ea2b3e8..1f40e94a9b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -103,7 +103,7 @@ import io.element.android.libraries.matrix.api.timeline.item.EmbeddedEventInfo import io.element.android.libraries.matrix.api.timeline.item.ThreadSummary import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent -import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageType import io.element.android.libraries.matrix.api.timeline.item.event.getAvatarUrl import io.element.android.libraries.matrix.api.timeline.item.event.getDisambiguatedDisplayName @@ -542,7 +542,7 @@ private fun TimelineItemEventRowContent( @Composable private fun MessageSenderInformation( senderId: UserId, - senderProfile: ProfileTimelineDetails, + senderProfile: ProfileDetails, senderAvatar: AvatarData, onClick: () -> Unit, modifier: Modifier = Modifier @@ -844,7 +844,7 @@ internal fun TimelineItemEventRowWithThreadSummaryPreview() = ElementPreview { type = TextMessageType("This is the latest message in the thread", null) ), senderId = UserId("@user:id"), - senderProfile = ProfileTimelineDetails.Ready( + senderProfile = ProfileDetails.Ready( displayName = "Alice", avatarUrl = null, displayNameAmbiguous = false, @@ -877,7 +877,7 @@ internal fun ThreadSummaryViewPreview() { type = TextMessageType(body, null) ), senderId = UserId("@user:id"), - senderProfile = ProfileTimelineDetails.Ready( + senderProfile = ProfileDetails.Ready( displayName = "Alice", avatarUrl = null, displayNameAmbiguous = true, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt index ef69c0d6a1..31cf689ef8 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt @@ -25,7 +25,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.LegacyCallInv import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent import io.element.android.libraries.matrix.api.timeline.item.event.PollContent import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent -import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails import io.element.android.libraries.matrix.api.timeline.item.event.RedactedContent import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent import io.element.android.libraries.matrix.api.timeline.item.event.StateContent @@ -63,7 +63,7 @@ class TimelineItemContentFactory( eventId: EventId?, isEditable: Boolean, sender: UserId, - senderProfile: ProfileTimelineDetails, + senderProfile: ProfileDetails, ): TimelineItemEventContent { val isOutgoing = sessionId == sender return when (itemContent) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt index 590090b6ed..1f01b16012 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt @@ -28,7 +28,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransa import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import io.element.android.libraries.matrix.api.timeline.item.event.MessageShieldProvider -import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails import io.element.android.libraries.matrix.api.timeline.item.event.SendHandleProvider import io.element.android.libraries.matrix.api.timeline.item.event.TimelineItemDebugInfoProvider import io.element.android.libraries.matrix.api.timeline.item.event.TimelineItemEventOrigin @@ -69,7 +69,7 @@ sealed interface TimelineItem { val eventId: EventId? = null, val transactionId: TransactionId? = null, val senderId: UserId, - val senderProfile: ProfileTimelineDetails, + val senderProfile: ProfileDetails, val senderAvatar: AvatarData, val content: TimelineItemEventContent, val sentTimeMillis: Long = 0L, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/RedactedVoiceMessageManagerTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/RedactedVoiceMessageManagerTest.kt index e69e83ad04..8bced93023 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/RedactedVoiceMessageManagerTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/RedactedVoiceMessageManagerTest.kt @@ -15,7 +15,7 @@ import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem -import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails import io.element.android.libraries.matrix.api.timeline.item.event.RedactedContent import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.AN_EVENT_ID_2 @@ -86,7 +86,7 @@ fun aRedactedMatrixTimeline(eventId: EventId) = listOf( reactions = persistentListOf(), receipts = persistentListOf(), sender = A_USER_ID, - senderProfile = ProfileTimelineDetails.Unavailable, + senderProfile = ProfileDetails.Unavailable, timestamp = 9442, content = RedactedContent, origin = null, diff --git a/libraries/eventformatter/api/src/main/kotlin/io/element/android/libraries/eventformatter/api/RoomLastMessageFormatter.kt b/libraries/eventformatter/api/src/main/kotlin/io/element/android/libraries/eventformatter/api/RoomLatestEventFormatter.kt similarity index 59% rename from libraries/eventformatter/api/src/main/kotlin/io/element/android/libraries/eventformatter/api/RoomLastMessageFormatter.kt rename to libraries/eventformatter/api/src/main/kotlin/io/element/android/libraries/eventformatter/api/RoomLatestEventFormatter.kt index dfdf15cc24..5eb7713b54 100644 --- a/libraries/eventformatter/api/src/main/kotlin/io/element/android/libraries/eventformatter/api/RoomLastMessageFormatter.kt +++ b/libraries/eventformatter/api/src/main/kotlin/io/element/android/libraries/eventformatter/api/RoomLatestEventFormatter.kt @@ -8,8 +8,8 @@ package io.element.android.libraries.eventformatter.api -import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem +import io.element.android.libraries.matrix.api.roomlist.LatestEventValue -fun interface RoomLastMessageFormatter { - fun format(event: EventTimelineItem, isDmRoom: Boolean): CharSequence? +fun interface RoomLatestEventFormatter { + fun format(latestEvent: LatestEventValue, isDmRoom: Boolean): CharSequence? } diff --git a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatter.kt similarity index 82% rename from libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt rename to libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatter.kt index 4373977ec8..48b8c83bc6 100644 --- a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt +++ b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatter.kt @@ -10,13 +10,15 @@ package io.element.android.libraries.eventformatter.impl import dev.zacsweers.metro.ContributesBinding import io.element.android.libraries.di.SessionScope -import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter +import io.element.android.libraries.eventformatter.api.RoomLatestEventFormatter import io.element.android.libraries.eventformatter.impl.mode.RenderingMode +import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.permalink.PermalinkParser +import io.element.android.libraries.matrix.api.roomlist.LatestEventValue import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType import io.element.android.libraries.matrix.api.timeline.item.event.CallNotifyContent import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageType -import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem +import io.element.android.libraries.matrix.api.timeline.item.event.EventContent import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseMessageLikeContent import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseStateContent import io.element.android.libraries.matrix.api.timeline.item.event.FileMessageType @@ -45,22 +47,46 @@ import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.services.toolbox.api.strings.StringProvider @ContributesBinding(SessionScope::class) -class DefaultRoomLastMessageFormatter( +class DefaultRoomLatestEventFormatter( private val sp: StringProvider, private val roomMembershipContentFormatter: RoomMembershipContentFormatter, private val profileChangeContentFormatter: ProfileChangeContentFormatter, private val stateContentFormatter: StateContentFormatter, - private val permalinkParser: PermalinkParser -) : RoomLastMessageFormatter { + private val permalinkParser: PermalinkParser, +) : RoomLatestEventFormatter { companion object { // Max characters to display in the last message. This works around https://github.com/element-hq/element-x-android/issues/2105 private const val MAX_SAFE_LENGTH = 500 } - override fun format(event: EventTimelineItem, isDmRoom: Boolean): CharSequence? { - val isOutgoing = event.isOwn - val senderDisambiguatedDisplayName = event.senderProfile.getDisambiguatedDisplayName(event.sender) - return when (val content = event.content) { + override fun format(latestEvent: LatestEventValue, isDmRoom: Boolean): CharSequence? { + return when (latestEvent) { + LatestEventValue.None -> null + is LatestEventValue.Local -> formatContent( + content = latestEvent.content, + isDmRoom = isDmRoom, + isOutgoing = true, + senderId = latestEvent.senderId, + senderDisambiguatedDisplayName = latestEvent.senderProfile.getDisambiguatedDisplayName(latestEvent.senderId) + ) + is LatestEventValue.Remote -> formatContent( + content = latestEvent.content, + isDmRoom = isDmRoom, + isOutgoing = latestEvent.isOwn, + senderId = latestEvent.senderId, + senderDisambiguatedDisplayName = latestEvent.senderProfile.getDisambiguatedDisplayName(latestEvent.senderId) + ) + } + } + + private fun formatContent( + content: EventContent, + isDmRoom: Boolean, + isOutgoing: Boolean, + senderId: UserId, + senderDisambiguatedDisplayName: String + ): CharSequence? { + return when (content) { is MessageContent -> content.process(senderDisambiguatedDisplayName, isDmRoom, isOutgoing) RedactedContent -> { val message = sp.getString(CommonStrings.common_message_removed) @@ -78,7 +104,7 @@ class DefaultRoomLastMessageFormatter( roomMembershipContentFormatter.format(content, senderDisambiguatedDisplayName, isOutgoing) } is ProfileChangeContent -> { - profileChangeContentFormatter.format(content, event.sender, senderDisambiguatedDisplayName, isOutgoing) + profileChangeContentFormatter.format(content, senderId, senderDisambiguatedDisplayName, isOutgoing) } is StateContent -> { stateContentFormatter.format(content, senderDisambiguatedDisplayName, isOutgoing, RenderingMode.RoomList) diff --git a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatterTest.kt b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatterTest.kt index c067113b2d..10c09ad41d 100644 --- a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatterTest.kt +++ b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatterTest.kt @@ -44,7 +44,7 @@ import io.element.android.libraries.matrix.test.media.aMediaSource import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser import io.element.android.libraries.matrix.test.timeline.aPollContent import io.element.android.libraries.matrix.test.timeline.aProfileChangeMessageContent -import io.element.android.libraries.matrix.test.timeline.aProfileTimelineDetails +import io.element.android.libraries.matrix.test.timeline.aProfileDetails import io.element.android.libraries.matrix.test.timeline.aStickerContent import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem import io.element.android.libraries.matrix.test.timeline.item.event.aRoomMembershipContent @@ -778,7 +778,7 @@ class DefaultPinnedMessagesBannerFormatterTest { content: EventContent, ): EventTimelineItem { val sender = if (sentByYou) A_USER_ID else someoneElseId - val profile = aProfileTimelineDetails(senderDisplayName) + val profile = aProfileDetails(senderDisplayName) return anEventTimelineItem( content = content, senderProfile = profile, diff --git a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultBaseRoomLastMessageFormatterTest.kt b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt similarity index 79% rename from libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultBaseRoomLastMessageFormatterTest.kt rename to libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt index 5b8c2c86df..96d341f447 100644 --- a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultBaseRoomLastMessageFormatterTest.kt +++ b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt @@ -15,10 +15,10 @@ import com.google.common.truth.Truth.assertWithMessage import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.media.ImageInfo import io.element.android.libraries.matrix.api.media.MediaSource +import io.element.android.libraries.matrix.api.roomlist.LatestEventValue import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageType import io.element.android.libraries.matrix.api.timeline.item.event.EventContent -import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseMessageLikeContent import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseStateContent import io.element.android.libraries.matrix.api.timeline.item.event.FileMessageType @@ -43,11 +43,11 @@ import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.media.aMediaSource import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser +import io.element.android.libraries.matrix.test.room.aRemoteLatestEvent import io.element.android.libraries.matrix.test.timeline.aPollContent import io.element.android.libraries.matrix.test.timeline.aProfileChangeMessageContent -import io.element.android.libraries.matrix.test.timeline.aProfileTimelineDetails +import io.element.android.libraries.matrix.test.timeline.aProfileDetails import io.element.android.libraries.matrix.test.timeline.aStickerContent -import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem import io.element.android.libraries.matrix.test.timeline.item.event.aRoomMembershipContent import io.element.android.services.toolbox.impl.strings.AndroidStringProvider import org.junit.Before @@ -59,17 +59,17 @@ import org.robolectric.annotation.Config @Suppress("LargeClass") @RunWith(RobolectricTestRunner::class) -class DefaultBaseRoomLastMessageFormatterTest { +class DefaultRoomLatestEventFormatterTest { private lateinit var context: Context private lateinit var fakeMatrixClient: FakeMatrixClient - private lateinit var formatter: DefaultRoomLastMessageFormatter + private lateinit var formatter: DefaultRoomLatestEventFormatter @Before fun setup() { context = RuntimeEnvironment.getApplication() as Context fakeMatrixClient = FakeMatrixClient() val stringProvider = AndroidStringProvider(context.resources) - formatter = DefaultRoomLastMessageFormatter( + formatter = DefaultRoomLatestEventFormatter( sp = AndroidStringProvider(context.resources), roomMembershipContentFormatter = RoomMembershipContentFormatter(fakeMatrixClient, stringProvider), profileChangeContentFormatter = ProfileChangeContentFormatter(stringProvider), @@ -84,7 +84,7 @@ class DefaultBaseRoomLastMessageFormatterTest { val expected = "Message removed" val senderName = "Someone" sequenceOf(false, true).forEach { isDm -> - val message = createRoomEvent(false, senderName, RedactedContent) + val message = createLatestEvent(false, senderName, RedactedContent) val result = formatter.format(message, isDm) if (isDm) { assertThat(result).isEqualTo(expected) @@ -100,7 +100,7 @@ class DefaultBaseRoomLastMessageFormatterTest { fun `Sticker content`() { val body = "a sticker body" val info = ImageInfo(null, null, null, null, null, null, null) - val message = createRoomEvent(false, null, aStickerContent(body, info, aMediaSource(url = "url"))) + val message = createLatestEvent(false, null, aStickerContent(body, info, aMediaSource(url = "url"))) val result = formatter.format(message, false) val expectedBody = someoneElseId.value + ": Sticker (a sticker body)" assertThat(result.toString()).isEqualTo(expectedBody) @@ -112,7 +112,7 @@ class DefaultBaseRoomLastMessageFormatterTest { val expected = "Waiting for this message" val senderName = "Someone" sequenceOf(false, true).forEach { isDm -> - val message = createRoomEvent(false, senderName, UnableToDecryptContent(UnableToDecryptContent.Data.Unknown)) + val message = createLatestEvent(false, senderName, UnableToDecryptContent(UnableToDecryptContent.Data.Unknown)) val result = formatter.format(message, isDm) if (isDm) { assertThat(result).isEqualTo(expected) @@ -134,7 +134,7 @@ class DefaultBaseRoomLastMessageFormatterTest { FailedToParseStateContent("", "", ""), UnknownContent, ).forEach { type -> - val message = createRoomEvent(false, senderName, type) + val message = createLatestEvent(false, senderName, type) val result = formatter.format(message, isDm) if (isDm) { assertWithMessage("$type was not properly handled").that(result).isEqualTo(expected) @@ -198,7 +198,7 @@ class DefaultBaseRoomLastMessageFormatterTest { sequenceOf(false, true).forEach { isDm -> sharedContentMessagesTypes.forEach { type -> val content = createMessageContent(type) - val message = createRoomEvent(sentByYou = sentByYou, senderDisplayName = senderName, content = content) + val message = createLatestEvent(sentByYou = sentByYou, senderDisplayName = senderName, content = content) val result = formatter.format(message, isDmRoom = isDm) if (isDm) { resultsInDm.add(type to result) @@ -294,11 +294,11 @@ class DefaultBaseRoomLastMessageFormatterTest { val youContent = aRoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED) val someoneContent = aRoomMembershipContent(UserId("@someone_else:domain"), otherName, MembershipChange.JOINED) - val youJoinedRoomEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youJoinedRoomEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = youContent) val youJoinedRoom = formatter.format(youJoinedRoomEvent, false) assertThat(youJoinedRoom).isEqualTo("You joined the room") - val someoneJoinedRoomEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneJoinedRoomEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) val someoneJoinedRoom = formatter.format(someoneJoinedRoomEvent, false) assertThat(someoneJoinedRoom).isEqualTo("$otherName joined the room") } @@ -310,11 +310,11 @@ class DefaultBaseRoomLastMessageFormatterTest { val youContent = aRoomMembershipContent(A_USER_ID, null, MembershipChange.LEFT) val someoneContent = aRoomMembershipContent(UserId("@someone_else:domain"), otherName, MembershipChange.LEFT) - val youLeftRoomEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youLeftRoomEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = youContent) val youLeftRoom = formatter.format(youLeftRoomEvent, false) assertThat(youLeftRoom).isEqualTo("You left the room") - val someoneLeftRoomEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneLeftRoomEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) val someoneLeftRoom = formatter.format(someoneLeftRoomEvent, false) assertThat(someoneLeftRoom).isEqualTo("$otherName left the room") } @@ -329,19 +329,19 @@ class DefaultBaseRoomLastMessageFormatterTest { val someoneContent = aRoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.BANNED) val someoneKickedContent = aRoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.KICKED_AND_BANNED) - val youBannedEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youBannedEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = youContent) val youBanned = formatter.format(youBannedEvent, false) assertThat(youBanned).isEqualTo("You banned $third") - val youKickBannedEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youKickedContent) + val youKickBannedEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = youKickedContent) val youKickedBanned = formatter.format(youKickBannedEvent, false) assertThat(youKickedBanned).isEqualTo("You banned $third") - val someoneBannedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneBannedEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) val someoneBanned = formatter.format(someoneBannedEvent, false) assertThat(someoneBanned).isEqualTo("$otherName banned $third") - val someoneKickBannedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneKickedContent) + val someoneKickBannedEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = someoneKickedContent) val someoneKickBanned = formatter.format(someoneKickBannedEvent, false) assertThat(someoneKickBanned).isEqualTo("$otherName banned $third") } @@ -356,19 +356,19 @@ class DefaultBaseRoomLastMessageFormatterTest { val someoneContent = aRoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.BANNED, A_REASON) val someoneKickedContent = aRoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.KICKED_AND_BANNED, A_REASON) - val youBannedEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youBannedEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = youContent) val youBanned = formatter.format(youBannedEvent, false) assertThat(youBanned).isEqualTo("You banned $third: $A_REASON") - val youKickBannedEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youKickedContent) + val youKickBannedEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = youKickedContent) val youKickedBanned = formatter.format(youKickBannedEvent, false) assertThat(youKickedBanned).isEqualTo("You banned $third: $A_REASON") - val someoneBannedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneBannedEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) val someoneBanned = formatter.format(someoneBannedEvent, false) assertThat(someoneBanned).isEqualTo("$otherName banned $third: $A_REASON") - val someoneKickBannedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneKickedContent) + val someoneKickBannedEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = someoneKickedContent) val someoneKickBanned = formatter.format(someoneKickBannedEvent, false) assertThat(someoneKickBanned).isEqualTo("$otherName banned $third: $A_REASON") } @@ -381,11 +381,11 @@ class DefaultBaseRoomLastMessageFormatterTest { val youContent = aRoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.UNBANNED) val someoneContent = aRoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.UNBANNED) - val youUnbannedEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youUnbannedEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = youContent) val youUnbanned = formatter.format(youUnbannedEvent, false) assertThat(youUnbanned).isEqualTo("You unbanned $third") - val someoneUnbannedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneUnbannedEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) val someoneUnbanned = formatter.format(someoneUnbannedEvent, false) assertThat(someoneUnbanned).isEqualTo("$otherName unbanned $third") } @@ -398,11 +398,11 @@ class DefaultBaseRoomLastMessageFormatterTest { val youContent = aRoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.KICKED) val someoneContent = aRoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.KICKED) - val youKickedEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youKickedEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = youContent) val youKicked = formatter.format(youKickedEvent, false) assertThat(youKicked).isEqualTo("You removed $third") - val someoneKickedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneKickedEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) val someoneKicked = formatter.format(someoneKickedEvent, false) assertThat(someoneKicked).isEqualTo("$otherName removed $third") } @@ -415,11 +415,11 @@ class DefaultBaseRoomLastMessageFormatterTest { val youContent = aRoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.KICKED, A_REASON) val someoneContent = aRoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.KICKED, A_REASON) - val youKickedEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youKickedEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = youContent) val youKicked = formatter.format(youKickedEvent, false) assertThat(youKicked).isEqualTo("You removed $third: $A_REASON") - val someoneKickedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneKickedEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) val someoneKicked = formatter.format(someoneKickedEvent, false) assertThat(someoneKicked).isEqualTo("$otherName removed $third: $A_REASON") } @@ -432,15 +432,15 @@ class DefaultBaseRoomLastMessageFormatterTest { val youContent = aRoomMembershipContent(A_USER_ID, null, MembershipChange.INVITED) val someoneContent = aRoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.INVITED) - val youWereInvitedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = youContent) + val youWereInvitedEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = youContent) val youWereInvited = formatter.format(youWereInvitedEvent, false) assertThat(youWereInvited).isEqualTo("$otherName invited you") - val youInvitedEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = someoneContent) + val youInvitedEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = someoneContent) val youInvited = formatter.format(youInvitedEvent, false) assertThat(youInvited).isEqualTo("You invited $third") - val someoneInvitedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneInvitedEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) val someoneInvited = formatter.format(someoneInvitedEvent, false) assertThat(someoneInvited).isEqualTo("$otherName invited $third") } @@ -452,11 +452,11 @@ class DefaultBaseRoomLastMessageFormatterTest { val youContent = aRoomMembershipContent(A_USER_ID, null, MembershipChange.INVITATION_ACCEPTED) val someoneContent = aRoomMembershipContent(UserId("@someone_else:domain"), otherName, MembershipChange.INVITATION_ACCEPTED) - val youAcceptedInviteEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youAcceptedInviteEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = youContent) val youAcceptedInvite = formatter.format(youAcceptedInviteEvent, false) assertThat(youAcceptedInvite).isEqualTo("You accepted the invite") - val someoneAcceptedInviteEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneAcceptedInviteEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) val someoneAcceptedInvite = formatter.format(someoneAcceptedInviteEvent, false) assertThat(someoneAcceptedInvite).isEqualTo("$otherName accepted the invite") } @@ -468,11 +468,11 @@ class DefaultBaseRoomLastMessageFormatterTest { val youContent = aRoomMembershipContent(A_USER_ID, null, MembershipChange.INVITATION_REJECTED) val someoneContent = aRoomMembershipContent(UserId("@someone_else:domain"), otherName, MembershipChange.INVITATION_REJECTED) - val youRejectedInviteEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youRejectedInviteEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = youContent) val youRejectedInvite = formatter.format(youRejectedInviteEvent, false) assertThat(youRejectedInvite).isEqualTo("You rejected the invitation") - val someoneRejectedInviteEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneRejectedInviteEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) val someoneRejectedInvite = formatter.format(someoneRejectedInviteEvent, false) assertThat(someoneRejectedInvite).isEqualTo("$otherName rejected the invitation") } @@ -484,11 +484,11 @@ class DefaultBaseRoomLastMessageFormatterTest { val third = "Someone" val someoneContent = aRoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.INVITATION_REVOKED) - val youRevokedInviteEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = someoneContent) + val youRevokedInviteEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = someoneContent) val youRevokedInvite = formatter.format(youRevokedInviteEvent, false) assertThat(youRevokedInvite).isEqualTo("You revoked the invitation for $third to join the room") - val someoneRevokedInviteEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneRevokedInviteEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) val someoneRevokedInvite = formatter.format(someoneRevokedInviteEvent, false) assertThat(someoneRevokedInvite).isEqualTo("$otherName revoked the invitation for $third to join the room") } @@ -500,11 +500,11 @@ class DefaultBaseRoomLastMessageFormatterTest { val youContent = aRoomMembershipContent(A_USER_ID, null, MembershipChange.KNOCKED) val someoneContent = aRoomMembershipContent(UserId("@someone_else:domain"), otherName, MembershipChange.KNOCKED) - val youKnockedEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youKnockedEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = youContent) val youKnocked = formatter.format(youKnockedEvent, false) assertThat(youKnocked).isEqualTo("You requested to join") - val someoneKnockedEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneKnockedEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) val someoneKnocked = formatter.format(someoneKnockedEvent, false) assertThat(someoneKnocked).isEqualTo("$otherName is requesting to join") } @@ -516,11 +516,11 @@ class DefaultBaseRoomLastMessageFormatterTest { val third = "Someone" val someoneContent = aRoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.KNOCK_ACCEPTED) - val youAcceptedKnockEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = someoneContent) + val youAcceptedKnockEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = someoneContent) val youAcceptedKnock = formatter.format(youAcceptedKnockEvent, false) assertThat(youAcceptedKnock).isEqualTo("You allowed $third to join") - val someoneAcceptedKnockEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneAcceptedKnockEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) val someoneAcceptedKnock = formatter.format(someoneAcceptedKnockEvent, false) assertThat(someoneAcceptedKnock).isEqualTo("$otherName granted access to $third") } @@ -532,11 +532,11 @@ class DefaultBaseRoomLastMessageFormatterTest { val youContent = aRoomMembershipContent(A_USER_ID, null, MembershipChange.KNOCK_RETRACTED) val someoneContent = aRoomMembershipContent(UserId("@someone_else:domain"), null, MembershipChange.KNOCK_RETRACTED) - val youRetractedKnockEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youRetractedKnockEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = youContent) val youRetractedKnock = formatter.format(youRetractedKnockEvent, false) assertThat(youRetractedKnock).isEqualTo("You cancelled your request to join") - val someoneRetractedKnockEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneRetractedKnockEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) val someoneRetractedKnock = formatter.format(someoneRetractedKnockEvent, false) assertThat(someoneRetractedKnock).isEqualTo("$otherName is no longer interested in joining") } @@ -549,15 +549,15 @@ class DefaultBaseRoomLastMessageFormatterTest { val youContent = aRoomMembershipContent(A_USER_ID, third, MembershipChange.KNOCK_DENIED) val someoneContent = aRoomMembershipContent(UserId("@someone_else:domain"), third, MembershipChange.KNOCK_DENIED) - val youDeniedKnockEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = someoneContent) + val youDeniedKnockEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = someoneContent) val youDeniedKnock = formatter.format(youDeniedKnockEvent, false) assertThat(youDeniedKnock).isEqualTo("You rejected $third's request to join") - val someoneDeniedKnockEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneDeniedKnockEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) val someoneDeniedKnock = formatter.format(someoneDeniedKnockEvent, false) assertThat(someoneDeniedKnock).isEqualTo("$otherName rejected $third's request to join") - val someoneDeniedYourKnockEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = youContent) + val someoneDeniedYourKnockEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = youContent) val someoneDeniedYourKnock = formatter.format(someoneDeniedYourKnockEvent, false) assertThat(someoneDeniedYourKnock).isEqualTo("$otherName rejected your request to join") } @@ -569,11 +569,11 @@ class DefaultBaseRoomLastMessageFormatterTest { val youContent = aRoomMembershipContent(A_USER_ID, null, MembershipChange.NONE) val someoneContent = aRoomMembershipContent(UserId("@someone_else:domain"), otherName, MembershipChange.NONE) - val youNoneRoomEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = youContent) + val youNoneRoomEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = youContent) val youNoneRoom = formatter.format(youNoneRoomEvent, false) assertThat(youNoneRoom).isEqualTo("You made no changes") - val someoneNoneRoomEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) + val someoneNoneRoomEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = someoneContent) val someoneNoneRoom = formatter.format(someoneNoneRoomEvent, false) assertThat(someoneNoneRoom).isEqualTo("$otherName made no changes") } @@ -585,7 +585,7 @@ class DefaultBaseRoomLastMessageFormatterTest { val results = otherChanges.map { change -> val content = aRoomMembershipContent(A_USER_ID, null, change) - val event = createRoomEvent(sentByYou = false, senderDisplayName = "Someone", content = content) + val event = createLatestEvent(sentByYou = false, senderDisplayName = "Someone", content = content) val result = formatter.format(event, false) change to result } @@ -604,19 +604,19 @@ class DefaultBaseRoomLastMessageFormatterTest { val changedContent = StateContent("", OtherState.RoomAvatar("new_avatar")) val removedContent = StateContent("", OtherState.RoomAvatar(null)) - val youChangedRoomAvatarEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = changedContent) + val youChangedRoomAvatarEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = changedContent) val youChangedRoomAvatar = formatter.format(youChangedRoomAvatarEvent, false) assertThat(youChangedRoomAvatar).isEqualTo("You changed the room avatar") - val someoneChangedRoomAvatarEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent) + val someoneChangedRoomAvatarEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent) val someoneChangedRoomAvatar = formatter.format(someoneChangedRoomAvatarEvent, false) assertThat(someoneChangedRoomAvatar).isEqualTo("$otherName changed the room avatar") - val youRemovedRoomAvatarEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = removedContent) + val youRemovedRoomAvatarEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = removedContent) val youRemovedRoomAvatar = formatter.format(youRemovedRoomAvatarEvent, false) assertThat(youRemovedRoomAvatar).isEqualTo("You removed the room avatar") - val someoneRemovedRoomAvatarEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent) + val someoneRemovedRoomAvatarEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent) val someoneRemovedRoomAvatar = formatter.format(someoneRemovedRoomAvatarEvent, false) assertThat(someoneRemovedRoomAvatar).isEqualTo("$otherName removed the room avatar") } @@ -627,11 +627,11 @@ class DefaultBaseRoomLastMessageFormatterTest { val otherName = "Other" val content = StateContent("", OtherState.RoomCreate) - val youCreatedRoomMessage = createRoomEvent(sentByYou = true, senderDisplayName = null, content = content) + val youCreatedRoomMessage = createLatestEvent(sentByYou = true, senderDisplayName = null, content = content) val youCreatedRoom = formatter.format(youCreatedRoomMessage, false) assertThat(youCreatedRoom).isEqualTo("You created the room") - val someoneCreatedRoomEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = content) + val someoneCreatedRoomEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = content) val someoneCreatedRoom = formatter.format(someoneCreatedRoomEvent, false) assertThat(someoneCreatedRoom).isEqualTo("$otherName created the room") } @@ -642,11 +642,11 @@ class DefaultBaseRoomLastMessageFormatterTest { val otherName = "Other" val content = StateContent("", OtherState.RoomEncryption) - val youCreatedRoomMessage = createRoomEvent(sentByYou = true, senderDisplayName = null, content = content) + val youCreatedRoomMessage = createLatestEvent(sentByYou = true, senderDisplayName = null, content = content) val youCreatedRoom = formatter.format(youCreatedRoomMessage, false) assertThat(youCreatedRoom).isEqualTo("Encryption enabled") - val someoneCreatedRoomEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = content) + val someoneCreatedRoomEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = content) val someoneCreatedRoom = formatter.format(someoneCreatedRoomEvent, false) assertThat(someoneCreatedRoom).isEqualTo("Encryption enabled") } @@ -659,19 +659,19 @@ class DefaultBaseRoomLastMessageFormatterTest { val changedContent = StateContent("", OtherState.RoomName(newName)) val removedContent = StateContent("", OtherState.RoomName(null)) - val youChangedRoomNameEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = changedContent) + val youChangedRoomNameEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = changedContent) val youChangedRoomName = formatter.format(youChangedRoomNameEvent, false) assertThat(youChangedRoomName).isEqualTo("You changed the room name to: $newName") - val someoneChangedRoomNameEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent) + val someoneChangedRoomNameEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent) val someoneChangedRoomName = formatter.format(someoneChangedRoomNameEvent, false) assertThat(someoneChangedRoomName).isEqualTo("$otherName changed the room name to: $newName") - val youRemovedRoomNameEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = removedContent) + val youRemovedRoomNameEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = removedContent) val youRemovedRoomName = formatter.format(youRemovedRoomNameEvent, false) assertThat(youRemovedRoomName).isEqualTo("You removed the room name") - val someoneRemovedRoomNameEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent) + val someoneRemovedRoomNameEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent) val someoneRemovedRoomName = formatter.format(someoneRemovedRoomNameEvent, false) assertThat(someoneRemovedRoomName).isEqualTo("$otherName removed the room name") } @@ -684,19 +684,19 @@ class DefaultBaseRoomLastMessageFormatterTest { val changedContent = StateContent("", OtherState.RoomThirdPartyInvite(inviteeName)) val removedContent = StateContent("", OtherState.RoomThirdPartyInvite(null)) - val youInvitedSomeoneEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = changedContent) + val youInvitedSomeoneEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = changedContent) val youInvitedSomeone = formatter.format(youInvitedSomeoneEvent, false) assertThat(youInvitedSomeone).isEqualTo("You sent an invitation to $inviteeName to join the room") - val someoneInvitedSomeoneEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent) + val someoneInvitedSomeoneEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent) val someoneInvitedSomeone = formatter.format(someoneInvitedSomeoneEvent, false) assertThat(someoneInvitedSomeone).isEqualTo("$otherName sent an invitation to $inviteeName to join the room") - val youInvitedNoOneEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = removedContent) + val youInvitedNoOneEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = removedContent) val youInvitedNoOne = formatter.format(youInvitedNoOneEvent, false) assertThat(youInvitedNoOne).isNull() - val someoneInvitedNoOneEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent) + val someoneInvitedNoOneEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent) val someoneInvitedNoOne = formatter.format(someoneInvitedNoOneEvent, false) assertThat(someoneInvitedNoOne).isNull() } @@ -710,27 +710,27 @@ class DefaultBaseRoomLastMessageFormatterTest { val removedContent = StateContent("", OtherState.RoomTopic(null)) val blankContent = StateContent("", OtherState.RoomTopic("")) - val youChangedRoomTopicEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = changedContent) + val youChangedRoomTopicEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = changedContent) val youChangedRoomTopic = formatter.format(youChangedRoomTopicEvent, false) assertThat(youChangedRoomTopic).isEqualTo("You changed the topic to: $roomTopic") - val someoneChangedRoomTopicEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent) + val someoneChangedRoomTopicEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent) val someoneChangedRoomTopic = formatter.format(someoneChangedRoomTopicEvent, false) assertThat(someoneChangedRoomTopic).isEqualTo("$otherName changed the topic to: $roomTopic") - val youRemovedRoomTopicEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = removedContent) + val youRemovedRoomTopicEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = removedContent) val youRemovedRoomTopic = formatter.format(youRemovedRoomTopicEvent, false) assertThat(youRemovedRoomTopic).isEqualTo("You removed the room topic") - val someoneRemovedRoomTopicEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent) + val someoneRemovedRoomTopicEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent) val someoneRemovedRoomTopic = formatter.format(someoneRemovedRoomTopicEvent, false) assertThat(someoneRemovedRoomTopic).isEqualTo("$otherName removed the room topic") - val youSetBlankRoomTopicEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = blankContent) + val youSetBlankRoomTopicEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = blankContent) val youSetBlankRoomTopic = formatter.format(youSetBlankRoomTopicEvent, false) assertThat(youSetBlankRoomTopic).isEqualTo("You removed the room topic") - val someoneSetBlankRoomTopicEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = blankContent) + val someoneSetBlankRoomTopicEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = blankContent) val someoneSetBlankRoomTopic = formatter.format(someoneSetBlankRoomTopicEvent, false) assertThat(someoneSetBlankRoomTopic).isEqualTo("$otherName removed the room topic") } @@ -758,7 +758,7 @@ class DefaultBaseRoomLastMessageFormatterTest { val results = otherStates.map { state -> val content = StateContent("", state) - val event = createRoomEvent(sentByYou = false, senderDisplayName = "Someone", content = content) + val event = createLatestEvent(sentByYou = false, senderDisplayName = "Someone", content = content) val result = formatter.format(event, false) state to result } @@ -780,35 +780,35 @@ class DefaultBaseRoomLastMessageFormatterTest { val invalidContent = aProfileChangeMessageContent(avatarUrl = null, prevAvatarUrl = null) val sameContent = aProfileChangeMessageContent(avatarUrl = "same_avatar_url", prevAvatarUrl = "same_avatar_url") - val youChangedAvatarEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = changedContent) + val youChangedAvatarEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = changedContent) val youChangedAvatar = formatter.format(youChangedAvatarEvent, false) assertThat(youChangedAvatar).isEqualTo("You changed your avatar") - val someoneChangeAvatarEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent) + val someoneChangeAvatarEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent) val someoneChangeAvatar = formatter.format(someoneChangeAvatarEvent, false) assertThat(someoneChangeAvatar).isEqualTo("$otherName changed their avatar") - val youSetAvatarEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = setContent) + val youSetAvatarEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = setContent) val youSetAvatar = formatter.format(youSetAvatarEvent, false) assertThat(youSetAvatar).isEqualTo("You changed your avatar") - val someoneSetAvatarEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = setContent) + val someoneSetAvatarEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = setContent) val someoneSetAvatar = formatter.format(someoneSetAvatarEvent, false) assertThat(someoneSetAvatar).isEqualTo("$otherName changed their avatar") - val youRemovedAvatarEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = removedContent) + val youRemovedAvatarEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = removedContent) val youRemovedAvatar = formatter.format(youRemovedAvatarEvent, false) assertThat(youRemovedAvatar).isEqualTo("You changed your avatar") - val someoneRemovedAvatarEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent) + val someoneRemovedAvatarEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent) val someoneRemovedAvatar = formatter.format(someoneRemovedAvatarEvent, false) assertThat(someoneRemovedAvatar).isEqualTo("$otherName changed their avatar") - val unchangedEvent = createRoomEvent(sentByYou = true, senderDisplayName = otherName, content = sameContent) + val unchangedEvent = createLatestEvent(sentByYou = true, senderDisplayName = otherName, content = sameContent) val unchangedResult = formatter.format(unchangedEvent, false) assertThat(unchangedResult).isNull() - val invalidEvent = createRoomEvent(sentByYou = true, senderDisplayName = otherName, content = invalidContent) + val invalidEvent = createLatestEvent(sentByYou = true, senderDisplayName = otherName, content = invalidContent) val invalidResult = formatter.format(invalidEvent, false) assertThat(invalidResult).isNull() } @@ -825,35 +825,35 @@ class DefaultBaseRoomLastMessageFormatterTest { val sameContent = aProfileChangeMessageContent(displayName = newDisplayName, prevDisplayName = newDisplayName) val invalidContent = aProfileChangeMessageContent(displayName = null, prevDisplayName = null) - val youChangedDisplayNameEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = changedContent) + val youChangedDisplayNameEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = changedContent) val youChangedDisplayName = formatter.format(youChangedDisplayNameEvent, false) assertThat(youChangedDisplayName).isEqualTo("You changed your display name from $oldDisplayName to $newDisplayName") - val someoneChangedDisplayNameEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent) + val someoneChangedDisplayNameEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = changedContent) val someoneChangedDisplayName = formatter.format(someoneChangedDisplayNameEvent, false) assertThat(someoneChangedDisplayName).isEqualTo("$someoneElseId changed their display name from $oldDisplayName to $newDisplayName") - val youSetDisplayNameEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = setContent) + val youSetDisplayNameEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = setContent) val youSetDisplayName = formatter.format(youSetDisplayNameEvent, false) assertThat(youSetDisplayName).isEqualTo("You set your display name to $newDisplayName") - val someoneSetDisplayNameEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = setContent) + val someoneSetDisplayNameEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = setContent) val someoneSetDisplayName = formatter.format(someoneSetDisplayNameEvent, false) assertThat(someoneSetDisplayName).isEqualTo("$someoneElseId set their display name to $newDisplayName") - val youRemovedDisplayNameEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = removedContent) + val youRemovedDisplayNameEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = removedContent) val youRemovedDisplayName = formatter.format(youRemovedDisplayNameEvent, false) assertThat(youRemovedDisplayName).isEqualTo("You removed your display name (it was $oldDisplayName)") - val someoneRemovedDisplayNameEvent = createRoomEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent) + val someoneRemovedDisplayNameEvent = createLatestEvent(sentByYou = false, senderDisplayName = otherName, content = removedContent) val someoneRemovedDisplayName = formatter.format(someoneRemovedDisplayNameEvent, false) assertThat(someoneRemovedDisplayName).isEqualTo("$someoneElseId removed their display name (it was $oldDisplayName)") - val unchangedEvent = createRoomEvent(sentByYou = true, senderDisplayName = otherName, content = sameContent) + val unchangedEvent = createLatestEvent(sentByYou = true, senderDisplayName = otherName, content = sameContent) val unchangedResult = formatter.format(unchangedEvent, false) assertThat(unchangedResult).isNull() - val invalidEvent = createRoomEvent(sentByYou = true, senderDisplayName = otherName, content = invalidContent) + val invalidEvent = createLatestEvent(sentByYou = true, senderDisplayName = otherName, content = invalidContent) val invalidResult = formatter.format(invalidEvent, false) assertThat(invalidResult).isNull() } @@ -882,15 +882,15 @@ class DefaultBaseRoomLastMessageFormatterTest { prevAvatarUrl = "same_avatar_url", ) - val youChangedBothEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = changedContent) + val youChangedBothEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = changedContent) val youChangedBoth = formatter.format(youChangedBothEvent, false) assertThat(youChangedBoth).isEqualTo("You changed your display name from $oldDisplayName to $newDisplayName\n(avatar was changed too)") - val invalidContentEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = invalidContent) + val invalidContentEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = invalidContent) val invalidMessage = formatter.format(invalidContentEvent, false) assertThat(invalidMessage).isNull() - val sameContentEvent = createRoomEvent(sentByYou = true, senderDisplayName = null, content = sameContent) + val sameContentEvent = createLatestEvent(sentByYou = true, senderDisplayName = null, content = sameContent) val sameMessage = formatter.format(sameContentEvent, false) assertThat(sameMessage).isNull() } @@ -904,10 +904,10 @@ class DefaultBaseRoomLastMessageFormatterTest { fun `Computes last message for poll in DM`() { val pollContent = aPollContent() - val mineContentEvent = createRoomEvent(sentByYou = true, senderDisplayName = "Alice", content = pollContent) + val mineContentEvent = createLatestEvent(sentByYou = true, senderDisplayName = "Alice", content = pollContent) assertThat(formatter.format(mineContentEvent, true)).isEqualTo("Poll: Do you like polls?") - val contentEvent = createRoomEvent(sentByYou = false, senderDisplayName = "Bob", content = pollContent) + val contentEvent = createLatestEvent(sentByYou = false, senderDisplayName = "Bob", content = pollContent) assertThat(formatter.format(contentEvent, true)).isEqualTo("Poll: Do you like polls?") } @@ -916,26 +916,26 @@ class DefaultBaseRoomLastMessageFormatterTest { fun `Computes last message for poll in room`() { val pollContent = aPollContent() - val mineContentEvent = createRoomEvent(sentByYou = true, senderDisplayName = "Alice", content = pollContent) + val mineContentEvent = createLatestEvent(sentByYou = true, senderDisplayName = "Alice", content = pollContent) assertThat(formatter.format(mineContentEvent, false).toString()).isEqualTo("You: Poll: Do you like polls?") - val contentEvent = createRoomEvent(sentByYou = false, senderDisplayName = "Bob", content = pollContent) + val contentEvent = createLatestEvent(sentByYou = false, senderDisplayName = "Bob", content = pollContent) assertThat(formatter.format(contentEvent, false).toString()).isEqualTo("Bob: Poll: Do you like polls?") } // endregion - private fun createRoomEvent( + private fun createLatestEvent( sentByYou: Boolean, senderDisplayName: String?, content: EventContent, - ): EventTimelineItem { + ): LatestEventValue { val sender = if (sentByYou) A_USER_ID else someoneElseId - val profile = aProfileTimelineDetails(senderDisplayName) - return anEventTimelineItem( - content = content, + val profile = aProfileDetails(senderDisplayName) + return aRemoteLatestEvent( + senderId = sender, senderProfile = profile, - sender = sender, + content = content, isOwn = sentByYou, ) } diff --git a/libraries/eventformatter/test/src/main/kotlin/io/element/android/libraries/eventformatter/test/FakeRoomLastMessageFormatter.kt b/libraries/eventformatter/test/src/main/kotlin/io/element/android/libraries/eventformatter/test/FakeRoomLatestEventFormatter.kt similarity index 59% rename from libraries/eventformatter/test/src/main/kotlin/io/element/android/libraries/eventformatter/test/FakeRoomLastMessageFormatter.kt rename to libraries/eventformatter/test/src/main/kotlin/io/element/android/libraries/eventformatter/test/FakeRoomLatestEventFormatter.kt index b5c069cff1..d82128b2d3 100644 --- a/libraries/eventformatter/test/src/main/kotlin/io/element/android/libraries/eventformatter/test/FakeRoomLastMessageFormatter.kt +++ b/libraries/eventformatter/test/src/main/kotlin/io/element/android/libraries/eventformatter/test/FakeRoomLatestEventFormatter.kt @@ -8,13 +8,13 @@ package io.element.android.libraries.eventformatter.test -import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter -import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem +import io.element.android.libraries.eventformatter.api.RoomLatestEventFormatter +import io.element.android.libraries.matrix.api.roomlist.LatestEventValue -class FakeRoomLastMessageFormatter : RoomLastMessageFormatter { +class FakeRoomLatestEventFormatter : RoomLatestEventFormatter { private var result: CharSequence? = null - override fun format(event: EventTimelineItem, isDmRoom: Boolean): CharSequence? { + override fun format(latestEvent: LatestEventValue, isDmRoom: Boolean): CharSequence? { return result } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/message/RoomMessage.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/message/RoomMessage.kt deleted file mode 100644 index 02aafb2e98..0000000000 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/message/RoomMessage.kt +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2023-2025 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.libraries.matrix.api.room.message - -import io.element.android.libraries.matrix.api.core.EventId -import io.element.android.libraries.matrix.api.core.UserId -import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem - -data class RoomMessage( - val eventId: EventId, - val event: EventTimelineItem, - val sender: UserId, - val originServerTs: Long, -) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/LatestEventValue.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/LatestEventValue.kt new file mode 100644 index 0000000000..5482a67875 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/LatestEventValue.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.api.roomlist + +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.timeline.item.event.EventContent +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails + +sealed interface LatestEventValue { + data object None : LatestEventValue + data class Remote( + val timestamp: Long, + val content: EventContent, + val senderId: UserId, + val senderProfile: ProfileDetails, + val isOwn: Boolean, + ) : LatestEventValue + + data class Local( + val timestamp: Long, + val content: EventContent, + val senderId: UserId, + val senderProfile: ProfileDetails, + val isSending: Boolean, + ) : LatestEventValue +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt index 50af91a36c..89a4acfec1 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt @@ -9,13 +9,16 @@ package io.element.android.libraries.matrix.api.roomlist import io.element.android.libraries.matrix.api.room.RoomInfo -import io.element.android.libraries.matrix.api.room.message.RoomMessage data class RoomSummary( val info: RoomInfo, - val lastMessage: RoomMessage?, + val latestEvent: LatestEventValue, ) { val roomId = info.id - val lastMessageTimestamp = lastMessage?.originServerTs + val latestEventTimestamp = when (latestEvent) { + is LatestEventValue.None -> null + is LatestEventValue.Local -> latestEvent.timestamp + is LatestEventValue.Remote -> latestEvent.timestamp + } val isOneToOne get() = info.activeMembersCount == 2L } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/ThreadSummary.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/ThreadSummary.kt index 8b2b0d101e..97923995a0 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/ThreadSummary.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/ThreadSummary.kt @@ -13,7 +13,7 @@ import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.timeline.item.event.EventContent import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId -import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails sealed interface EventThreadInfo { data class ThreadRoot(val summary: ThreadSummary) : EventThreadInfo @@ -29,6 +29,6 @@ data class EmbeddedEventInfo( val eventOrTransactionId: EventOrTransactionId, val content: EventContent, val senderId: UserId, - val senderProfile: ProfileTimelineDetails, + val senderProfile: ProfileDetails, val timestamp: Long, ) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventTimelineItem.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventTimelineItem.kt index ba63a11c4c..8294b78c24 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventTimelineItem.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventTimelineItem.kt @@ -27,7 +27,7 @@ data class EventTimelineItem( val reactions: ImmutableList, val receipts: ImmutableList, val sender: UserId, - val senderProfile: ProfileTimelineDetails, + val senderProfile: ProfileDetails, val timestamp: Long, val content: EventContent, val origin: TimelineItemEventOrigin?, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/InReplyTo.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/InReplyTo.kt index e9a12d82a3..43a54602ca 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/InReplyTo.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/InReplyTo.kt @@ -25,7 +25,7 @@ sealed interface InReplyTo { val eventId: EventId, val content: EventContent, val senderId: UserId, - val senderProfile: ProfileTimelineDetails, + val senderProfile: ProfileDetails, ) : InReplyTo /** diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/ProfileTimelineDetails.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/ProfileDetails.kt similarity index 68% rename from libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/ProfileTimelineDetails.kt rename to libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/ProfileDetails.kt index dee7290c98..6393a27bb2 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/ProfileTimelineDetails.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/ProfileDetails.kt @@ -12,20 +12,20 @@ import androidx.compose.runtime.Immutable import io.element.android.libraries.matrix.api.core.UserId @Immutable -sealed interface ProfileTimelineDetails { - data object Unavailable : ProfileTimelineDetails +sealed interface ProfileDetails { + data object Unavailable : ProfileDetails - data object Pending : ProfileTimelineDetails + data object Pending : ProfileDetails data class Ready( val displayName: String?, val displayNameAmbiguous: Boolean, val avatarUrl: String? - ) : ProfileTimelineDetails + ) : ProfileDetails data class Error( val message: String - ) : ProfileTimelineDetails + ) : ProfileDetails } /** @@ -34,9 +34,9 @@ sealed interface ProfileTimelineDetails { * If the display name is ambiguous, the user ID is appended in parentheses. * Otherwise, the display name is returned. */ -fun ProfileTimelineDetails.getDisambiguatedDisplayName(userId: UserId): String { +fun ProfileDetails.getDisambiguatedDisplayName(userId: UserId): String { return when (this) { - is ProfileTimelineDetails.Ready -> when { + is ProfileDetails.Ready -> when { displayName == null -> userId.value displayNameAmbiguous -> "$displayName ($userId)" else -> displayName @@ -45,16 +45,16 @@ fun ProfileTimelineDetails.getDisambiguatedDisplayName(userId: UserId): String { } } -fun ProfileTimelineDetails.getDisplayName(): String? { +fun ProfileDetails.getDisplayName(): String? { return when (this) { - is ProfileTimelineDetails.Ready -> displayName + is ProfileDetails.Ready -> displayName else -> null } } -fun ProfileTimelineDetails.getAvatarUrl(): String? { +fun ProfileDetails.getAvatarUrl(): String? { return when (this) { - is ProfileTimelineDetails.Ready -> avatarUrl + is ProfileDetails.Ready -> avatarUrl else -> null } } diff --git a/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/ProfileTimelineDetailsTest.kt b/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/ProfileTimelineDetailsTest.kt index 4fa764adce..ffb59ba7d1 100644 --- a/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/ProfileTimelineDetailsTest.kt +++ b/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/ProfileTimelineDetailsTest.kt @@ -18,23 +18,23 @@ private val aUserId = UserId(A_USER_ID) class ProfileTimelineDetailsTest { @Test fun `getDisambiguatedDisplayName of Unavailable should be equal to userId`() { - assertThat(ProfileTimelineDetails.Unavailable.getDisambiguatedDisplayName(aUserId)).isEqualTo(A_USER_ID) + assertThat(ProfileDetails.Unavailable.getDisambiguatedDisplayName(aUserId)).isEqualTo(A_USER_ID) } @Test fun `getDisambiguatedDisplayName of Error should be equal to userId`() { - assertThat(ProfileTimelineDetails.Error("An error").getDisambiguatedDisplayName(aUserId)).isEqualTo(A_USER_ID) + assertThat(ProfileDetails.Error("An error").getDisambiguatedDisplayName(aUserId)).isEqualTo(A_USER_ID) } @Test fun `getDisambiguatedDisplayName of Pending should be equal to userId`() { - assertThat(ProfileTimelineDetails.Pending.getDisambiguatedDisplayName(aUserId)).isEqualTo(A_USER_ID) + assertThat(ProfileDetails.Pending.getDisambiguatedDisplayName(aUserId)).isEqualTo(A_USER_ID) } @Test fun `getDisambiguatedDisplayName of Ready without display name should be equal to userId`() { assertThat( - ProfileTimelineDetails.Ready( + ProfileDetails.Ready( displayName = null, displayNameAmbiguous = false, avatarUrl = null, @@ -45,7 +45,7 @@ class ProfileTimelineDetailsTest { @Test fun `getDisambiguatedDisplayName of Ready with display name should be equal to display name`() { assertThat( - ProfileTimelineDetails.Ready( + ProfileDetails.Ready( displayName = "Alice", displayNameAmbiguous = false, avatarUrl = null, @@ -56,7 +56,7 @@ class ProfileTimelineDetailsTest { @Test fun `getDisambiguatedDisplayName of Ready with display name and ambiguous should be equal to display name with user id`() { assertThat( - ProfileTimelineDetails.Ready( + ProfileDetails.Ready( displayName = "Alice", displayNameAmbiguous = true, avatarUrl = null, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/message/RoomMessageFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/message/RoomMessageFactory.kt deleted file mode 100644 index d03cf013a4..0000000000 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/message/RoomMessageFactory.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2023-2025 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.libraries.matrix.impl.room.message - -import io.element.android.libraries.matrix.api.room.message.RoomMessage -import io.element.android.libraries.matrix.impl.timeline.item.event.EventTimelineItemMapper -import org.matrix.rustcomponents.sdk.EventTimelineItem as RustEventTimelineItem - -class RoomMessageFactory( - private val eventTimelineItemMapper: EventTimelineItemMapper = EventTimelineItemMapper(), -) { - fun create(eventTimelineItem: RustEventTimelineItem?): RoomMessage? { - eventTimelineItem ?: return null - val mappedTimelineItem = eventTimelineItemMapper.map(eventTimelineItem) - return RoomMessage( - eventId = mappedTimelineItem.eventId ?: return null, - event = mappedTimelineItem, - sender = mappedTimelineItem.sender, - originServerTs = mappedTimelineItem.timestamp, - ) - } -} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactory.kt index b0d545e2a1..4e342f3a48 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactory.kt @@ -40,7 +40,7 @@ internal class RoomListFactory( private val sessionCoroutineScope: CoroutineScope, private val analyticsService: AnalyticsService, ) { - private val roomSummaryDetailsFactory: RoomSummaryFactory = RoomSummaryFactory() + private val roomSummaryFactory: RoomSummaryFactory = RoomSummaryFactory() /** * Creates a room list that can be used to load more rooms and filter them dynamically. @@ -55,7 +55,7 @@ internal class RoomListFactory( val loadingStateFlow: MutableStateFlow = MutableStateFlow(RoomList.LoadingState.NotLoaded) val filteredSummariesFlow = MutableSharedFlow>(replay = 1, extraBufferCapacity = 1) val summariesFlow = MutableSharedFlow>(replay = 1, extraBufferCapacity = 1) - val processor = RoomSummaryListProcessor(summariesFlow, innerRoomListService, coroutineContext, roomSummaryDetailsFactory) + val processor = RoomSummaryListProcessor(summariesFlow, innerRoomListService, coroutineContext, roomSummaryFactory) // Makes sure we don't miss any events val dynamicEvents = MutableSharedFlow(replay = 100) val currentFilter = MutableStateFlow(initialFilter) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryFactory.kt index de4f09ada6..3d5efedd54 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryFactory.kt @@ -8,24 +8,44 @@ package io.element.android.libraries.matrix.impl.roomlist +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.roomlist.LatestEventValue import io.element.android.libraries.matrix.api.roomlist.RoomSummary import io.element.android.libraries.matrix.impl.room.RoomInfoMapper -import io.element.android.libraries.matrix.impl.room.message.RoomMessageFactory +import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper +import io.element.android.libraries.matrix.impl.timeline.item.event.map import org.matrix.rustcomponents.sdk.Room import org.matrix.rustcomponents.sdk.use +import org.matrix.rustcomponents.sdk.LatestEventValue as RustLatestEventValue class RoomSummaryFactory( - private val roomMessageFactory: RoomMessageFactory = RoomMessageFactory(), + private val contentMapper: TimelineEventContentMapper = TimelineEventContentMapper(), private val roomInfoMapper: RoomInfoMapper = RoomInfoMapper(), ) { suspend fun create(room: Room): RoomSummary { val roomInfo = room.roomInfo().let(roomInfoMapper::map) - val latestRoomMessage = room.latestEvent().use { event -> - roomMessageFactory.create(event) + val latestEvent = room.newLatestEvent().use { event -> + when (event) { + is RustLatestEventValue.None -> LatestEventValue.None + is RustLatestEventValue.Local -> LatestEventValue.Local( + timestamp = event.timestamp.toLong(), + content = contentMapper.map(event.content), + isSending = event.isSending, + senderId = UserId(event.sender), + senderProfile = event.profile.map(), + ) + is RustLatestEventValue.Remote -> LatestEventValue.Remote( + timestamp = event.timestamp.toLong(), + content = contentMapper.map(event.content), + senderId = UserId(event.sender), + senderProfile = event.profile.map(), + isOwn = event.isOwn, + ) + } } return RoomSummary( info = roomInfo, - lastMessage = latestRoomMessage, + latestEvent = latestEvent, ) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt index c99e2b5448..3f5a919139 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt @@ -24,7 +24,7 @@ class RoomSummaryListProcessor( private val roomSummaries: MutableSharedFlow>, private val roomListService: RoomListServiceInterface, private val coroutineContext: CoroutineContext, - private val roomSummaryDetailsFactory: RoomSummaryFactory = RoomSummaryFactory(), + private val roomSummaryFactory: RoomSummaryFactory, ) { private val mutex = Mutex() @@ -103,7 +103,7 @@ class RoomSummaryListProcessor( } private suspend fun buildSummaryForRoomListEntry(entry: Room): RoomSummary { - return entry.use { roomSummaryDetailsFactory.create(room = it) } + return entry.use { roomSummaryFactory.create(room = it) } } private suspend fun buildRoomSummaryForIdentifier(identifier: String): RoomSummary? { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt index 68b8c7a8bb..6715169899 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt @@ -17,7 +17,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.EventReaction import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield -import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails import io.element.android.libraries.matrix.api.timeline.item.event.ReactionSender import io.element.android.libraries.matrix.api.timeline.item.event.Receipt import io.element.android.libraries.matrix.api.timeline.item.event.TimelineItemEventOrigin @@ -64,12 +64,12 @@ class EventTimelineItemMapper( } } -fun RustProfileDetails.map(): ProfileTimelineDetails { +fun RustProfileDetails.map(): ProfileDetails { return when (this) { - RustProfileDetails.Pending -> ProfileTimelineDetails.Pending - RustProfileDetails.Unavailable -> ProfileTimelineDetails.Unavailable - is RustProfileDetails.Error -> ProfileTimelineDetails.Error(message) - is RustProfileDetails.Ready -> ProfileTimelineDetails.Ready( + RustProfileDetails.Pending -> ProfileDetails.Pending + RustProfileDetails.Unavailable -> ProfileDetails.Unavailable + is RustProfileDetails.Error -> ProfileDetails.Error(message) + is RustProfileDetails.Ready -> ProfileDetails.Ready( displayName = displayName, displayNameAmbiguous = displayNameAmbiguous, avatarUrl = avatarUrl diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt index 9c84ccc559..eaa62abb65 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt @@ -192,6 +192,6 @@ class RoomSummaryListProcessorTest { summaries, FakeFfiRoomListService(), coroutineContext = StandardTestDispatcher(testScheduler), - roomSummaryDetailsFactory = RoomSummaryFactory(), + roomSummaryFactory = RoomSummaryFactory(), ) } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/LatestEventValueFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/LatestEventValueFixture.kt new file mode 100644 index 0000000000..32d6cc927c --- /dev/null +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/LatestEventValueFixture.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.test.room + +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.roomlist.LatestEventValue +import io.element.android.libraries.matrix.api.timeline.item.event.EventContent +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.matrix.test.timeline.aMessageContent +import io.element.android.libraries.matrix.test.timeline.aProfileDetails + +fun aRemoteLatestEvent( + content: EventContent = aMessageContent(), + timestamp: Long = 0L, + isOwn: Boolean = false, + senderId: UserId = A_USER_ID, + senderProfile: ProfileDetails = aProfileDetails(), +): LatestEventValue.Remote { + return LatestEventValue.Remote( + timestamp = timestamp, + content = content, + senderId = senderId, + senderProfile = senderProfile, + isOwn = isOwn, + ) +} + +fun aLocalLatestEvent( + content: EventContent = aMessageContent(), + timestamp: Long = 0L, + isSending: Boolean = false, + senderId: UserId = A_USER_ID, + senderProfile: ProfileDetails = aProfileDetails(), +): LatestEventValue.Local { + return LatestEventValue.Local( + timestamp = timestamp, + content = content, + senderId = senderId, + senderProfile = senderProfile, + isSending = isSending, + ) +} diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt index 45715cbd27..8568e3c916 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt @@ -18,28 +18,24 @@ import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility import io.element.android.libraries.matrix.api.room.join.JoinRule -import io.element.android.libraries.matrix.api.room.message.RoomMessage import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevels import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom +import io.element.android.libraries.matrix.api.roomlist.LatestEventValue import io.element.android.libraries.matrix.api.roomlist.RoomSummary -import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem import io.element.android.libraries.matrix.api.user.MatrixUser -import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_NAME import io.element.android.libraries.matrix.test.A_ROOM_RAW_NAME import io.element.android.libraries.matrix.test.A_ROOM_TOPIC -import io.element.android.libraries.matrix.test.A_USER_ID -import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem import kotlinx.collections.immutable.persistentMapOf import kotlinx.collections.immutable.toImmutableList fun aRoomSummary( info: RoomInfo = aRoomInfo(), - lastMessage: RoomMessage? = aRoomMessage(), + latestEventValue: LatestEventValue = aRemoteLatestEvent(), ) = RoomSummary( info = info, - lastMessage = lastMessage, + latestEvent = latestEventValue, ) fun aRoomSummary( @@ -79,7 +75,7 @@ fun aRoomSummary( numUnreadNotifications: Long = 0, numUnreadMentions: Long = 0, historyVisibility: RoomHistoryVisibility = RoomHistoryVisibility.Joined, - lastMessage: RoomMessage? = aRoomMessage(), + latestEvent: LatestEventValue = aRemoteLatestEvent(), roomVersion: String? = "11", privilegedCreatorRole: Boolean = false, ) = RoomSummary( @@ -120,17 +116,5 @@ fun aRoomSummary( roomVersion = roomVersion, privilegedCreatorRole = privilegedCreatorRole, ), - lastMessage = lastMessage, -) - -fun aRoomMessage( - eventId: EventId = AN_EVENT_ID, - event: EventTimelineItem = anEventTimelineItem(), - userId: UserId = A_USER_ID, - timestamp: Long = 0L, -) = RoomMessage( - eventId = eventId, - event = event, - sender = userId, - originServerTs = timestamp, + latestEvent = latestEvent, ) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/TimelineFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/TimelineFixture.kt index e2e6192363..c8d8ff6015 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/TimelineFixture.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/TimelineFixture.kt @@ -27,7 +27,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import io.element.android.libraries.matrix.api.timeline.item.event.MessageType import io.element.android.libraries.matrix.api.timeline.item.event.PollContent import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent -import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails import io.element.android.libraries.matrix.api.timeline.item.event.Receipt import io.element.android.libraries.matrix.api.timeline.item.event.SendHandleProvider import io.element.android.libraries.matrix.api.timeline.item.event.StickerContent @@ -53,7 +53,7 @@ fun anEventTimelineItem( reactions: ImmutableList = persistentListOf(), receipts: ImmutableList = persistentListOf(), sender: UserId = A_USER_ID, - senderProfile: ProfileTimelineDetails = aProfileTimelineDetails(), + senderProfile: ProfileDetails = aProfileDetails(), timestamp: Long = 0L, content: EventContent = aProfileChangeMessageContent(), debugInfoProvider: TimelineItemDebugInfoProvider = TimelineItemDebugInfoProvider { aTimelineItemDebugInfo() }, @@ -79,11 +79,11 @@ fun anEventTimelineItem( sendHandleProvider = sendHandleProvider, ) -fun aProfileTimelineDetails( +fun aProfileDetails( displayName: String? = A_USER_NAME, displayNameAmbiguous: Boolean = false, avatarUrl: String? = null -): ProfileTimelineDetails = ProfileTimelineDetails.Ready( +): ProfileDetails = ProfileDetails.Ready( displayName = displayName, displayNameAmbiguous = displayNameAmbiguous, avatarUrl = avatarUrl, diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetails.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetails.kt index 0d12866e8c..3179c748ea 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetails.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetails.kt @@ -15,7 +15,7 @@ import io.element.android.libraries.matrix.api.permalink.PermalinkParser import io.element.android.libraries.matrix.api.timeline.item.event.EventContent import io.element.android.libraries.matrix.api.timeline.item.event.InReplyTo import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent -import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails import io.element.android.libraries.matrix.api.timeline.item.event.StickerContent import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageType import io.element.android.libraries.matrix.ui.messages.toPlainText @@ -25,7 +25,7 @@ sealed interface InReplyToDetails { data class Ready( val eventId: EventId, val senderId: UserId, - val senderProfile: ProfileTimelineDetails, + val senderProfile: ProfileDetails, val eventContent: EventContent?, val textContent: String?, ) : InReplyToDetails diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailsProvider.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailsProvider.kt index 20fb717d7d..ac545ed8ea 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailsProvider.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailsProvider.kt @@ -24,7 +24,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.MessageConten import io.element.android.libraries.matrix.api.timeline.item.event.MessageType import io.element.android.libraries.matrix.api.timeline.item.event.NoticeMessageType import io.element.android.libraries.matrix.api.timeline.item.event.PollContent -import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails import io.element.android.libraries.matrix.api.timeline.item.event.RedactedContent import io.element.android.libraries.matrix.api.timeline.item.event.StickerMessageType import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageType @@ -161,7 +161,7 @@ fun aProfileTimelineDetailsReady( displayName: String? = "Sender", displayNameAmbiguous: Boolean = false, avatarUrl: String? = null, -) = ProfileTimelineDetails.Ready( +) = ProfileDetails.Ready( displayName = displayName, displayNameAmbiguous = displayNameAmbiguous, avatarUrl = avatarUrl, diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToView.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToView.kt index 6746c8ffdb..fc5d6577c7 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToView.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToView.kt @@ -42,7 +42,7 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.matrix.api.core.UserId -import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails import io.element.android.libraries.matrix.api.timeline.item.event.getDisambiguatedDisplayName import io.element.android.libraries.matrix.ui.components.AttachmentThumbnail import io.element.android.libraries.matrix.ui.messages.sender.SenderName @@ -74,7 +74,7 @@ fun InReplyToView( @Composable private fun ReplyToReadyContent( senderId: UserId, - senderProfile: ProfileTimelineDetails, + senderProfile: ProfileDetails, metadata: InReplyToMetadata?, modifier: Modifier = Modifier, ) { diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/sender/SenderName.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/sender/SenderName.kt index 582223fee6..cdca0937c1 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/sender/SenderName.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/sender/SenderName.kt @@ -23,13 +23,13 @@ import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.matrix.api.core.UserId -import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails // https://www.figma.com/file/Ni6Ii8YKtmXCKYNE90cC67/Timeline-(new)?type=design&node-id=917-80169&mode=design&t=A0CJCBbMqR8NOwUQ-0 @Composable fun SenderName( senderId: UserId, - senderProfile: ProfileTimelineDetails, + senderProfile: ProfileDetails, senderNameMode: SenderNameMode, modifier: Modifier = Modifier, ) { @@ -39,12 +39,12 @@ fun SenderName( verticalAlignment = Alignment.CenterVertically, ) { when (senderProfile) { - is ProfileTimelineDetails.Error, - ProfileTimelineDetails.Pending, - ProfileTimelineDetails.Unavailable -> { + is ProfileDetails.Error, + ProfileDetails.Pending, + ProfileDetails.Unavailable -> { MainText(text = senderId.value, mode = senderNameMode) } - is ProfileTimelineDetails.Ready -> { + is ProfileDetails.Ready -> { val displayName = senderProfile.displayName if (displayName.isNullOrEmpty()) { MainText(text = senderId.value, mode = senderNameMode) @@ -121,7 +121,7 @@ internal fun SenderNamePreview( ) = ElementPreview { SenderName( senderId = senderNameData.userId, - senderProfile = senderNameData.profileTimelineDetails, + senderProfile = senderNameData.profileDetails, senderNameMode = senderNameData.senderNameMode, ) } diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/sender/SenderNameDataProvider.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/sender/SenderNameDataProvider.kt index af9366c474..96ad91b869 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/sender/SenderNameDataProvider.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/sender/SenderNameDataProvider.kt @@ -11,11 +11,11 @@ package io.element.android.libraries.matrix.ui.messages.sender import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.matrix.api.core.UserId -import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails data class SenderNameData( val userId: UserId, - val profileTimelineDetails: ProfileTimelineDetails, + val profileDetails: ProfileDetails, val senderNameMode: SenderNameMode, ) @@ -38,7 +38,7 @@ open class SenderNameDataProvider : PreviewParameterProvider { SenderNameData( senderNameMode = senderNameMode, userId = UserId("@alice:${senderNameMode.javaClass.simpleName.lowercase()}"), - profileTimelineDetails = ProfileTimelineDetails.Unavailable, + profileDetails = ProfileDetails.Unavailable, ), ) } @@ -49,7 +49,7 @@ private fun aSenderNameData( displayNameAmbiguous: Boolean = false, ) = SenderNameData( userId = UserId("@alice:${senderNameMode.javaClass.simpleName.lowercase()}"), - profileTimelineDetails = ProfileTimelineDetails.Ready( + profileDetails = ProfileDetails.Ready( displayName = "Alice ${senderNameMode.javaClass.simpleName}", displayNameAmbiguous = displayNameAmbiguous, avatarUrl = null diff --git a/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailTest.kt b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailTest.kt index 6bbcf9127c..9507a30763 100644 --- a/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailTest.kt +++ b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetailTest.kt @@ -18,7 +18,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageTy import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser -import io.element.android.libraries.matrix.test.timeline.aProfileTimelineDetails +import io.element.android.libraries.matrix.test.timeline.aProfileDetails import io.element.android.libraries.matrix.test.timeline.item.event.aRoomMembershipContent import org.junit.Test @@ -47,7 +47,7 @@ class InReplyToDetailTest { val inReplyTo = InReplyTo.Ready( eventId = AN_EVENT_ID, senderId = A_USER_ID, - senderProfile = aProfileTimelineDetails(), + senderProfile = aProfileDetails(), content = aRoomMembershipContent( userId = A_USER_ID, change = MembershipChange.INVITED, @@ -65,7 +65,7 @@ class InReplyToDetailTest { val inReplyTo = InReplyTo.Ready( eventId = AN_EVENT_ID, senderId = A_USER_ID, - senderProfile = aProfileTimelineDetails(), + senderProfile = aProfileDetails(), content = MessageContent( body = "**Hello!**", inReplyTo = null, @@ -90,7 +90,7 @@ class InReplyToDetailTest { val inReplyTo = InReplyTo.Ready( eventId = AN_EVENT_ID, senderId = A_USER_ID, - senderProfile = aProfileTimelineDetails(), + senderProfile = aProfileDetails(), content = MessageContent( body = "**Hello!**", inReplyTo = null, diff --git a/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToMetadataKtTest.kt b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToMetadataKtTest.kt index 67c3596af3..e7cae1151b 100644 --- a/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToMetadataKtTest.kt +++ b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToMetadataKtTest.kt @@ -29,7 +29,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.ImageMessageT import io.element.android.libraries.matrix.api.timeline.item.event.LocationMessageType import io.element.android.libraries.matrix.api.timeline.item.event.OtherState import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent -import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails import io.element.android.libraries.matrix.api.timeline.item.event.RedactedContent import io.element.android.libraries.matrix.api.timeline.item.event.StateContent import io.element.android.libraries.matrix.api.timeline.item.event.StickerContent @@ -42,7 +42,7 @@ import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.media.aMediaSource import io.element.android.libraries.matrix.test.timeline.aMessageContent import io.element.android.libraries.matrix.test.timeline.aPollContent -import io.element.android.libraries.matrix.test.timeline.aProfileTimelineDetails +import io.element.android.libraries.matrix.test.timeline.aProfileDetails import io.element.android.libraries.matrix.test.timeline.item.event.aRoomMembershipContent import io.element.android.libraries.matrix.ui.components.A_BLUR_HASH import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo @@ -549,7 +549,7 @@ class InReplyToMetadataKtTest { private fun anInReplyToDetailsReady( eventId: EventId = AN_EVENT_ID, senderId: UserId = A_USER_ID, - senderProfile: ProfileTimelineDetails = aProfileTimelineDetails(), + senderProfile: ProfileDetails = aProfileDetails(), eventContent: EventContent? = aMessageContent(), textContent: String? = "textContent", ) = InReplyToDetails.Ready(