From 9fb82a1e86a00932f027e33d2c8875e90e035b71 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 20:09:33 +0200 Subject: [PATCH] Update dependency org.matrix.rustcomponents:sdk-android to v0.2.41 (#3384) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Introduce value class UniqueId. * Allow reactions on non-sent Event, the SDK can now handle it. Also the SDK will manage local echo for reactions. * Update dependency org.matrix.rustcomponents:sdk-android to v0.2.41 * Fixes after SDK upgrade: - Use `ClientBuilderSlidingSync` to set `SlidingSyncVersionBuilder` in `RustMatrixClientFactory`. - `Room.toggleReaction(emoji: String, eventId: EventId)` is now `Room.toggleReaction(emoji: String, uniqueId: UniqueId)`, since reactions can now be applied to local echoes too in the SDK. * Rename exception case * Fix wrong error case being used in test --------- Co-authored-by: Benoit Marty Co-authored-by: Benoit Marty Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jorge MartΓ­n --- .../login/impl/error/ChangeServerError.kt | 2 +- .../login/impl/error/ErrorFormatterTest.kt | 2 +- .../features/messages/impl/MessagesEvents.kt | 4 +- .../messages/impl/MessagesPresenter.kt | 8 ++-- .../features/messages/impl/MessagesView.kt | 8 ++-- .../impl/actionlist/ActionListPresenter.kt | 1 - .../impl/timeline/TimelinePresenter.kt | 5 ++- .../impl/timeline/TimelineStateProvider.kt | 12 ++++-- .../TimelineItemGroupedEventsRow.kt | 2 +- .../CustomReactionBottomSheet.kt | 8 ++-- .../timeline/groups/TimelineItemGrouper.kt | 13 +++--- .../impl/timeline/model/TimelineItem.kt | 9 ++-- .../messages/impl/MessagesPresenterTest.kt | 25 +++++------ .../messages/impl/MessagesViewTest.kt | 4 +- .../actionlist/ActionListPresenterTest.kt | 2 +- .../impl/fixtures/MessageEventFixtures.kt | 3 +- .../PinnedMessagesBannerPresenterTest.kt | 8 ++-- .../impl/timeline/TimelineItemIndexerTest.kt | 3 +- .../impl/timeline/TimelinePresenterTest.kt | 40 +++++++++--------- .../impl/timeline/TimelineViewTest.kt | 3 +- .../groups/TimelineItemGrouperTest.kt | 23 +++++----- .../RedactedVoiceMessageManagerTest.kt | 3 +- .../features/poll/impl/PollFixtures.kt | 5 ++- gradle/libs.versions.toml | 2 +- .../api/auth/AuthenticationException.kt | 2 +- .../libraries/matrix/api/core/UniqueId.kt | 24 +++++++++++ .../libraries/matrix/api/room/MatrixRoom.kt | 3 +- .../matrix/api/timeline/MatrixTimelineItem.kt | 5 ++- .../libraries/matrix/api/timeline/Timeline.kt | 3 +- .../api/tracing/TracingFilterConfiguration.kt | 2 + .../matrix/impl/RustMatrixClientFactory.kt | 34 ++++++++------- .../impl/auth/AuthenticationException.kt | 2 +- .../auth/RustMatrixAuthenticationService.kt | 3 -- .../libraries/matrix/impl/mapper/Session.kt | 3 +- .../matrix/impl/room/RustMatrixRoom.kt | 5 ++- .../impl/timeline/MatrixTimelineItemMapper.kt | 3 +- .../matrix/impl/timeline/RustTimeline.kt | 5 ++- .../LastForwardIndicatorsPostProcessor.kt | 11 ++--- .../LoadingIndicatorsPostProcessor.kt | 5 ++- .../RoomBeginningPostProcessor.kt | 3 +- .../TimelineEncryptedHistoryPostProcessor.kt | 5 ++- .../AuthenticationExceptionMappingTest.kt | 4 +- .../RoomBeginningPostProcessorTest.kt | 42 ++++++++++++------- ...melineEncryptedHistoryPostProcessorTest.kt | 29 +++++++------ .../android/libraries/matrix/test/TestData.kt | 5 ++- .../matrix/test/room/FakeMatrixRoom.kt | 7 ++-- .../matrix/test/timeline/FakeTimeline.kt | 5 ++- 47 files changed, 237 insertions(+), 168 deletions(-) create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/UniqueId.kt diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/error/ChangeServerError.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/error/ChangeServerError.kt index f9289898b6..980f21641f 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/error/ChangeServerError.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/error/ChangeServerError.kt @@ -31,7 +31,7 @@ sealed class ChangeServerError : Throwable() { companion object { fun from(error: Throwable): ChangeServerError = when (error) { - is AuthenticationException.SlidingSyncNotAvailable -> SlidingSyncAlert + is AuthenticationException.SlidingSyncVersion -> SlidingSyncAlert else -> Error(R.string.screen_change_server_error_invalid_homeserver) } } diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/error/ErrorFormatterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/error/ErrorFormatterTest.kt index 1c3e9782cd..ad0207daac 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/error/ErrorFormatterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/error/ErrorFormatterTest.kt @@ -32,7 +32,7 @@ class ErrorFormatterTest { @Test fun `loginError - invalid auth error returns unknown error message`() { - val error = AuthenticationException.SlidingSyncNotAvailable("Some message. Also contains M_FORBIDDEN, but won't be parsed") + val error = AuthenticationException.SlidingSyncVersion("Some message. Also contains M_FORBIDDEN, but won't be parsed") assertThat(loginError(error)).isEqualTo(CommonStrings.error_unknown) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesEvents.kt index b901f7e130..0036dd8718 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesEvents.kt @@ -18,11 +18,11 @@ package io.element.android.features.messages.impl import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.timeline.model.TimelineItem -import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.UniqueId sealed interface MessagesEvents { data class HandleAction(val action: TimelineItemAction, val event: TimelineItem.Event) : MessagesEvents - data class ToggleReaction(val emoji: String, val eventId: EventId) : MessagesEvents + data class ToggleReaction(val emoji: String, val uniqueId: UniqueId) : MessagesEvents data class InviteDialogDismissed(val action: InviteDialogAction) : MessagesEvents data object Dismiss : MessagesEvents } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index c17ac1035b..a7f3dd682a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -69,7 +69,7 @@ import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.permalink.PermalinkParser import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomInfo @@ -192,7 +192,7 @@ class MessagesPresenter @AssistedInject constructor( ) } is MessagesEvents.ToggleReaction -> { - localCoroutineScope.toggleReaction(event.emoji, event.eventId) + localCoroutineScope.toggleReaction(event.emoji, event.uniqueId) } is MessagesEvents.InviteDialogDismissed -> { hasDismissedInviteDialog = true @@ -313,10 +313,10 @@ class MessagesPresenter @AssistedInject constructor( private fun CoroutineScope.toggleReaction( emoji: String, - eventId: EventId, + uniqueId: UniqueId, ) = launch(dispatchers.io) { timelineController.invokeOnCurrentTimeline { - toggleReaction(emoji, eventId) + toggleReaction(emoji, uniqueId) .onFailure { Timber.e(it) } } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index f1f8b844ef..a578995487 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt @@ -175,8 +175,7 @@ fun MessagesView( } fun onEmojiReactionClick(emoji: String, event: TimelineItem.Event) { - if (event.eventId == null) return - state.eventSink(MessagesEvents.ToggleReaction(emoji, event.eventId)) + state.eventSink(MessagesEvents.ToggleReaction(emoji, event.id)) } fun onEmojiReactionLongClick(emoji: String, event: TimelineItem.Event) { @@ -248,7 +247,6 @@ fun MessagesView( state = state.actionListState, onSelectAction = ::onActionSelected, onCustomReactionClick = { event -> - if (event.eventId == null) return@ActionListView state.customReactionState.eventSink(CustomReactionEvents.ShowCustomReactionSheet(event)) }, onEmojiReactionClick = ::onEmojiReactionClick, @@ -256,8 +254,8 @@ fun MessagesView( CustomReactionBottomSheet( state = state.customReactionState, - onSelectEmoji = { eventId, emoji -> - state.eventSink(MessagesEvents.ToggleReaction(emoji.unicode, eventId)) + onSelectEmoji = { uniqueId, emoji -> + state.eventSink(MessagesEvents.ToggleReaction(emoji.unicode, uniqueId)) } ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt index 124f4e911d..ee5c4c4ad3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt @@ -106,7 +106,6 @@ class ActionListPresenter @Inject constructor( isEventPinned = pinnedEventIds.contains(timelineItem.eventId), ) val displayEmojiReactions = usersEventPermissions.canSendReaction && - timelineItem.isRemote && timelineItem.content.canReact() if (actions.isNotEmpty() || displayEmojiReactions) { target.value = ActionListState.Target.Success( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt index c7e3dc6e98..6815da82f3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt @@ -40,6 +40,7 @@ import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.bool.orFalse import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.api.room.isDm @@ -95,7 +96,7 @@ class TimelinePresenter @AssistedInject constructor( val userHasPermissionToSendMessage by room.canSendMessageAsState(type = MessageEventType.ROOM_MESSAGE, updateKey = syncUpdateFlow.value) val userHasPermissionToSendReaction by room.canSendMessageAsState(type = MessageEventType.REACTION, updateKey = syncUpdateFlow.value) - val prevMostRecentItemId = rememberSaveable { mutableStateOf(null) } + val prevMostRecentItemId = rememberSaveable { mutableStateOf(null) } val newEventState = remember { mutableStateOf(NewEventState.None) } val messageShield: MutableState = remember { mutableStateOf(null) } @@ -242,7 +243,7 @@ class TimelinePresenter @AssistedInject constructor( */ private suspend fun computeNewItemState( timelineItems: ImmutableList, - prevMostRecentItemId: MutableState, + prevMostRecentItemId: MutableState, newEventState: MutableState ) = withContext(dispatchers.computation) { // FromMe is prioritized over FromOther, so skip if we already have a FromMe diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt index f1abc52725..82ce258abd 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt @@ -32,6 +32,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.TransactionId +import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState @@ -122,7 +123,10 @@ internal fun aTimelineItemList(content: TimelineItemEventContent): ImmutableList } fun aTimelineItemDaySeparator(): TimelineItem.Virtual { - return TimelineItem.Virtual(UUID.randomUUID().toString(), aTimelineItemDaySeparatorModel("Today")) + return TimelineItem.Virtual( + id = UniqueId(UUID.randomUUID().toString()), + model = aTimelineItemDaySeparatorModel("Today"), + ) } internal fun aTimelineItemEvent( @@ -144,7 +148,7 @@ internal fun aTimelineItemEvent( messageShield: MessageShield? = null, ): TimelineItem.Event { return TimelineItem.Event( - id = UUID.randomUUID().toString(), + id = UniqueId(UUID.randomUUID().toString()), eventId = eventId, transactionId = transactionId, senderId = UserId("@senderId:domain"), @@ -210,7 +214,7 @@ internal fun aTimelineItemReadReceipts( } internal fun aGroupedEvents( - id: Long = 0, + id: UniqueId = UniqueId("0"), withReadReceipts: Boolean = false, ): TimelineItem.GroupedEvents { val event1 = aTimelineItemEvent( @@ -231,7 +235,7 @@ internal fun aGroupedEvents( ) val events = listOf(event1, event2) return TimelineItem.GroupedEvents( - id = id.toString(), + id = id, events = events.toImmutableList(), aggregatedReadReceipts = events.flatMap { it.readReceiptState.receipts }.toImmutableList(), ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt index bb1cb2b2df..874d69013a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemGroupedEventsRow.kt @@ -58,7 +58,7 @@ fun TimelineItemGroupedEventsRow( eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit, modifier: Modifier = Modifier ) { - val isExpanded = rememberSaveable(key = timelineItem.identifier()) { mutableStateOf(false) } + val isExpanded = rememberSaveable(key = timelineItem.identifier().value) { mutableStateOf(false) } fun onExpandGroupClick() { isExpanded.value = !isExpanded.value diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionBottomSheet.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionBottomSheet.kt index face810bc7..dd05bd9365 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionBottomSheet.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionBottomSheet.kt @@ -25,13 +25,13 @@ import androidx.compose.ui.Modifier import io.element.android.emojibasebindings.Emoji import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet import io.element.android.libraries.designsystem.theme.components.hide -import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.UniqueId @OptIn(ExperimentalMaterial3Api::class) @Composable fun CustomReactionBottomSheet( state: CustomReactionState, - onSelectEmoji: (EventId, Emoji) -> Unit, + onSelectEmoji: (UniqueId, Emoji) -> Unit, modifier: Modifier = Modifier, ) { val sheetState = rememberModalBottomSheetState() @@ -43,10 +43,10 @@ fun CustomReactionBottomSheet( } fun onEmojiSelectedDismiss(emoji: Emoji) { - if (target?.event?.eventId == null) return + if (target?.event == null) return sheetState.hide(coroutineScope) { state.eventSink(CustomReactionEvents.DismissCustomReactionSheet) - onSelectEmoji(target.event.eventId, emoji) + onSelectEmoji(target.event.id, emoji) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouper.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouper.kt index b0d2f39338..b1a0ae2f6d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouper.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouper.kt @@ -20,6 +20,7 @@ import androidx.annotation.VisibleForTesting import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.libraries.di.RoomScope import io.element.android.libraries.di.SingleIn +import io.element.android.libraries.matrix.api.core.UniqueId import kotlinx.collections.immutable.toImmutableList import javax.inject.Inject @@ -71,7 +72,7 @@ private fun MutableList.addGroup( val groupId = groupIds.getOrPutGroupId(groupOfItems) add( TimelineItem.GroupedEvents( - id = groupId, + id = UniqueId(groupId), events = groupOfItems.toImmutableList(), aggregatedReadReceipts = groupOfItems.flatMap { it.readReceiptState.receipts }.toImmutableList() ) @@ -83,15 +84,15 @@ private fun MutableMap.getOrPutGroupId(timelineItems: List - this[timelineItem.identifier()] = groupId + return computeGroupIdWith(timelineItem).value.also { groupId -> + this[timelineItem.identifier().value] = groupId } } @VisibleForTesting -internal fun computeGroupIdWith(timelineItem: TimelineItem): String = "${timelineItem.identifier()}_group" +internal fun computeGroupIdWith(timelineItem: TimelineItem): UniqueId = UniqueId("${timelineItem.identifier()}_group") 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 2cb872e95f..5d471fb5ef 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 @@ -24,6 +24,7 @@ import io.element.android.features.messages.impl.timeline.model.virtual.Timeline import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.TransactionId +import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState @@ -36,7 +37,7 @@ import kotlinx.collections.immutable.ImmutableList @Immutable sealed interface TimelineItem { - fun identifier(): String = when (this) { + fun identifier(): UniqueId = when (this) { is Event -> id is Virtual -> id is GroupedEvents -> id @@ -58,13 +59,13 @@ sealed interface TimelineItem { @Immutable data class Virtual( - val id: String, + val id: UniqueId, val model: TimelineItemVirtualModel ) : TimelineItem @Immutable data class Event( - val id: String, + val id: UniqueId, // Note: eventId can be null when the event is a local echo val eventId: EventId? = null, val transactionId: TransactionId? = null, @@ -101,7 +102,7 @@ sealed interface TimelineItem { @Immutable data class GroupedEvents( - val id: String, + val id: UniqueId, val events: ImmutableList, val aggregatedReadReceipts: ImmutableList, ) : TimelineItem diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt index c9700a60bd..f20dcacc7c 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt @@ -69,6 +69,7 @@ import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.TransactionId +import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.permalink.PermalinkParser @@ -77,11 +78,11 @@ import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.api.room.RoomMembershipState import io.element.android.libraries.matrix.test.AN_AVATAR_URL -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_SESSION_ID import io.element.android.libraries.matrix.test.A_SESSION_ID_2 import io.element.android.libraries.matrix.test.A_THROWABLE +import io.element.android.libraries.matrix.test.A_UNIQUE_ID import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.permalink.FakePermalinkBuilder import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser @@ -197,8 +198,8 @@ class MessagesPresenterTest { @Test fun `present - handle toggling a reaction`() = runTest { val coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true) - val toggleReactionSuccess = lambdaRecorder { _: String, _: EventId -> Result.success(Unit) } - val toggleReactionFailure = lambdaRecorder { _: String, _: EventId -> Result.failure(IllegalStateException("Failed to send reaction")) } + val toggleReactionSuccess = lambdaRecorder { _: String, _: UniqueId -> Result.success(Unit) } + val toggleReactionFailure = lambdaRecorder { _: String, _: UniqueId -> Result.failure(IllegalStateException("Failed to send reaction")) } val timeline = FakeTimeline().apply { this.toggleReactionLambda = toggleReactionSuccess @@ -218,25 +219,25 @@ class MessagesPresenterTest { }.test { skipItems(1) val initialState = awaitItem() - initialState.eventSink.invoke(MessagesEvents.ToggleReaction("πŸ‘", AN_EVENT_ID)) + initialState.eventSink.invoke(MessagesEvents.ToggleReaction("πŸ‘", A_UNIQUE_ID)) // No crashes when sending a reaction failed timeline.apply { toggleReactionLambda = toggleReactionFailure } - initialState.eventSink.invoke(MessagesEvents.ToggleReaction("πŸ‘", AN_EVENT_ID)) + initialState.eventSink.invoke(MessagesEvents.ToggleReaction("πŸ‘", A_UNIQUE_ID)) assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None) assert(toggleReactionSuccess) .isCalledOnce() - .with(value("πŸ‘"), value(AN_EVENT_ID)) + .with(value("πŸ‘"), value(A_UNIQUE_ID)) assert(toggleReactionFailure) .isCalledOnce() - .with(value("πŸ‘"), value(AN_EVENT_ID)) + .with(value("πŸ‘"), value(A_UNIQUE_ID)) } } @Test fun `present - handle toggling a reaction twice`() = runTest { val coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true) - val toggleReactionSuccess = lambdaRecorder { _: String, _: EventId -> Result.success(Unit) } + val toggleReactionSuccess = lambdaRecorder { _: String, _: UniqueId -> Result.success(Unit) } val timeline = FakeTimeline().apply { this.toggleReactionLambda = toggleReactionSuccess @@ -255,13 +256,13 @@ class MessagesPresenterTest { presenter.present() }.test { val initialState = awaitFirstItem() - initialState.eventSink.invoke(MessagesEvents.ToggleReaction("πŸ‘", AN_EVENT_ID)) - initialState.eventSink.invoke(MessagesEvents.ToggleReaction("πŸ‘", AN_EVENT_ID)) + initialState.eventSink.invoke(MessagesEvents.ToggleReaction("πŸ‘", A_UNIQUE_ID)) + initialState.eventSink.invoke(MessagesEvents.ToggleReaction("πŸ‘", A_UNIQUE_ID)) assert(toggleReactionSuccess) .isCalledExactly(2) .withSequence( - listOf(value("πŸ‘"), value(AN_EVENT_ID)), - listOf(value("πŸ‘"), value(AN_EVENT_ID)), + listOf(value("πŸ‘"), value(A_UNIQUE_ID)), + listOf(value("πŸ‘"), value(A_UNIQUE_ID)), ) } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt index b304ad9178..e4248c2005 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt @@ -361,7 +361,7 @@ class MessagesViewTest { state = state, ) rule.onAllNodesWithText("πŸ‘οΈ").onFirst().performClick() - eventsRecorder.assertSingle(MessagesEvents.ToggleReaction("πŸ‘οΈ", timelineItem.eventId!!)) + eventsRecorder.assertSingle(MessagesEvents.ToggleReaction("πŸ‘οΈ", timelineItem.id)) } @Test @@ -463,7 +463,7 @@ class MessagesViewTest { // Give time for the close animation to complete rule.mainClock.advanceTimeBy(milliseconds = 1_000) customReactionStateEventsRecorder.assertSingle(CustomReactionEvents.DismissCustomReactionSheet) - eventsRecorder.assertSingle(MessagesEvents.ToggleReaction(aUnicode, timelineItem.eventId!!)) + eventsRecorder.assertSingle(MessagesEvents.ToggleReaction(aUnicode, timelineItem.id)) } @Test diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt index e8ea7cbbc2..5b34784c95 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt @@ -757,7 +757,7 @@ class ActionListPresenterTest { assertThat(successState.target).isEqualTo( ActionListState.Target.Success( event = messageEvent, - displayEmojiReactions = false, + displayEmojiReactions = true, actions = persistentListOf( TimelineItemAction.Edit, TimelineItemAction.Copy, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/MessageEventFixtures.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/MessageEventFixtures.kt index c712421f23..6338b6c437 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/MessageEventFixtures.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/fixtures/MessageEventFixtures.kt @@ -27,6 +27,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.TransactionId +import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield @@ -51,7 +52,7 @@ internal fun aMessageEvent( sendState: LocalEventSendState = LocalEventSendState.Sent(AN_EVENT_ID), messageShield: MessageShield? = null, ) = TimelineItem.Event( - id = eventId?.value.orEmpty(), + id = UniqueId(eventId?.value.orEmpty()), eventId = eventId, transactionId = transactionId, senderId = A_USER_ID, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt index 1ae4729a40..a94467e820 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt @@ -24,6 +24,8 @@ import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.AN_EVENT_ID_2 +import io.element.android.libraries.matrix.test.A_UNIQUE_ID +import io.element.android.libraries.matrix.test.A_UNIQUE_ID_2 import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.libraries.matrix.test.room.aRoomInfo import io.element.android.libraries.matrix.test.timeline.FakeTimeline @@ -80,7 +82,7 @@ class PinnedMessagesBannerPresenterTest { timelineItems = flowOf( listOf( MatrixTimelineItem.Event( - uniqueId = "FAKE_UNIQUE_ID", + uniqueId = A_UNIQUE_ID, event = anEventTimelineItem( eventId = AN_EVENT_ID, content = messageContent, @@ -112,14 +114,14 @@ class PinnedMessagesBannerPresenterTest { timelineItems = flowOf( listOf( MatrixTimelineItem.Event( - uniqueId = "FAKE_UNIQUE_ID", + uniqueId = A_UNIQUE_ID, event = anEventTimelineItem( eventId = AN_EVENT_ID, content = messageContent1, ), ), MatrixTimelineItem.Event( - uniqueId = "FAKE_UNIQUE_ID_2", + uniqueId = A_UNIQUE_ID_2, event = anEventTimelineItem( eventId = AN_EVENT_ID_2, content = messageContent2, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineItemIndexerTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineItemIndexerTest.kt index 642f07a3f9..dc6c7f9cd3 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineItemIndexerTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineItemIndexerTest.kt @@ -20,6 +20,7 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemReadMarkerModel import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.test.AN_EVENT_ID import org.junit.Test @@ -34,7 +35,7 @@ class TimelineItemIndexerTest { groupedEvents.events.forEach { eventIds.add(it.eventId!!) } }, TimelineItem.Virtual( - id = "dummy", + id = UniqueId("dummy"), model = TimelineItemReadMarkerModel ), ) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt index a155507817..188c69ced3 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt @@ -36,6 +36,7 @@ import io.element.android.features.poll.api.actions.SendPollResponseAction import io.element.android.features.poll.test.actions.FakeEndPollAction import io.element.android.features.poll.test.actions.FakeSendPollResponseAction import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.ReceiptType @@ -46,6 +47,8 @@ import io.element.android.libraries.matrix.api.timeline.item.event.Receipt import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.AN_EVENT_ID_2 +import io.element.android.libraries.matrix.test.A_UNIQUE_ID +import io.element.android.libraries.matrix.test.A_UNIQUE_ID_2 import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.libraries.matrix.test.room.aRoomMember @@ -79,9 +82,6 @@ import java.util.Date import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds -private const val FAKE_UNIQUE_ID = "FAKE_UNIQUE_ID" -private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" - @OptIn(ExperimentalCoroutinesApi::class) class TimelinePresenterTest { @get:Rule val warmUpRule = WarmUpRule() @@ -131,7 +131,7 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" val timeline = FakeTimeline( timelineItems = flowOf( listOf( - MatrixTimelineItem.Event(FAKE_UNIQUE_ID, anEventTimelineItem()) + MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem()) ) ) ) @@ -164,9 +164,9 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" val timeline = FakeTimeline( timelineItems = flowOf( listOf( - MatrixTimelineItem.Event(FAKE_UNIQUE_ID, anEventTimelineItem()), + MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem()), MatrixTimelineItem.Event( - uniqueId = FAKE_UNIQUE_ID_2, + uniqueId = A_UNIQUE_ID_2, event = anEventTimelineItem( eventId = AN_EVENT_ID_2, content = aMessageContent("Test message") @@ -201,9 +201,9 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" val timeline = FakeTimeline( timelineItems = flowOf( listOf( - MatrixTimelineItem.Event(FAKE_UNIQUE_ID, anEventTimelineItem()), + MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem()), MatrixTimelineItem.Event( - uniqueId = FAKE_UNIQUE_ID_2, + uniqueId = A_UNIQUE_ID_2, event = anEventTimelineItem( eventId = AN_EVENT_ID_2, content = aMessageContent("Test message") @@ -243,9 +243,9 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" val timeline = FakeTimeline( timelineItems = flowOf( listOf( - MatrixTimelineItem.Event(FAKE_UNIQUE_ID, anEventTimelineItem()), + MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem()), MatrixTimelineItem.Event( - uniqueId = FAKE_UNIQUE_ID_2, + uniqueId = A_UNIQUE_ID_2, event = anEventTimelineItem( eventId = AN_EVENT_ID_2, content = aMessageContent("Test message") @@ -279,8 +279,8 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" val timeline = FakeTimeline( timelineItems = flowOf( listOf( - MatrixTimelineItem.Virtual(FAKE_UNIQUE_ID, VirtualTimelineItem.ReadMarker), - MatrixTimelineItem.Virtual(FAKE_UNIQUE_ID, VirtualTimelineItem.ReadMarker) + MatrixTimelineItem.Virtual(A_UNIQUE_ID, VirtualTimelineItem.ReadMarker), + MatrixTimelineItem.Virtual(A_UNIQUE_ID, VirtualTimelineItem.ReadMarker) ) ) ).apply { @@ -310,13 +310,13 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" assertThat(initialState.newEventState).isEqualTo(NewEventState.None) assertThat(initialState.timelineItems.size).isEqualTo(0) timelineItems.emit( - listOf(MatrixTimelineItem.Event("0", anEventTimelineItem(content = aMessageContent()))) + listOf(MatrixTimelineItem.Event(UniqueId("0"), anEventTimelineItem(content = aMessageContent()))) ) consumeItemsUntilPredicate { it.timelineItems.size == 1 } // Mimics sending a message, and assert newEventState is FromMe timelineItems.getAndUpdate { items -> val event = anEventTimelineItem(content = aMessageContent(), isOwn = true) - items + listOf(MatrixTimelineItem.Event("1", event)) + items + listOf(MatrixTimelineItem.Event(UniqueId("1"), event)) } consumeItemsUntilPredicate { it.timelineItems.size == 2 } awaitLastSequentialItem().also { state -> @@ -325,7 +325,7 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" // Mimics receiving a message without clearing the previous FromMe timelineItems.getAndUpdate { items -> val event = anEventTimelineItem(content = aMessageContent()) - items + listOf(MatrixTimelineItem.Event("2", event)) + items + listOf(MatrixTimelineItem.Event(UniqueId("2"), event)) } consumeItemsUntilPredicate { it.timelineItems.size == 3 } @@ -337,7 +337,7 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" // Mimics receiving a message and assert newEventState is FromOther timelineItems.getAndUpdate { items -> val event = anEventTimelineItem(content = aMessageContent()) - items + listOf(MatrixTimelineItem.Event("3", event)) + items + listOf(MatrixTimelineItem.Event(UniqueId("3"), event)) } consumeItemsUntilPredicate { it.timelineItems.size == 4 } awaitLastSequentialItem().also { state -> @@ -381,7 +381,7 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" ), ) timelineItems.emit( - listOf(MatrixTimelineItem.Event(FAKE_UNIQUE_ID, anEventTimelineItem(reactions = oneReaction))) + listOf(MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem(reactions = oneReaction))) ) val item = awaitItem().timelineItems.first() assertThat(item).isInstanceOf(TimelineItem.Event::class.java) @@ -476,7 +476,7 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" timelineItems = flowOf( listOf( MatrixTimelineItem.Event( - uniqueId = FAKE_UNIQUE_ID, + uniqueId = A_UNIQUE_ID, event = anEventTimelineItem(), ) ) @@ -532,7 +532,7 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" timelineItems = flowOf( listOf( MatrixTimelineItem.Event( - uniqueId = FAKE_UNIQUE_ID, + uniqueId = A_UNIQUE_ID, event = anEventTimelineItem(eventId = AN_EVENT_ID), ) ) @@ -618,7 +618,7 @@ private const val FAKE_UNIQUE_ID_2 = "FAKE_UNIQUE_ID_2" timelineItems = flowOf( listOf( MatrixTimelineItem.Event( - FAKE_UNIQUE_ID, + A_UNIQUE_ID, anEventTimelineItem( sender = A_USER_ID, receipts = persistentListOf( diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewTest.kt index bb8ea58315..45f0189de1 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineViewTest.kt @@ -28,6 +28,7 @@ import io.element.android.features.messages.impl.timeline.model.event.aTimelineI import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemLoadingIndicatorModel import io.element.android.features.messages.impl.typing.TypingNotificationState import io.element.android.features.messages.impl.typing.aTypingNotificationState +import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield @@ -54,7 +55,7 @@ class TimelineViewTest { state = aTimelineState( timelineItems = persistentListOf( TimelineItem.Virtual( - id = "backward_pagination", + id = UniqueId("backward_pagination"), model = TimelineItemLoadingIndicatorModel(Timeline.PaginationDirection.BACKWARDS, 0) ), ), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouperTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouperTest.kt index fc98b34feb..7a8f99f792 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouperTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouperTest.kt @@ -26,6 +26,7 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItemRead import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateEventContent import io.element.android.features.messages.impl.timeline.model.virtual.aTimelineItemDaySeparatorModel import io.element.android.libraries.designsystem.components.avatar.anAvatarData +import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_USER_ID @@ -37,7 +38,7 @@ class TimelineItemGrouperTest { private val sut = TimelineItemGrouper() private val aGroupableItem = TimelineItem.Event( - id = "0", + id = UniqueId("0"), senderId = A_USER_ID, senderAvatar = anAvatarData(), senderProfile = aProfileTimelineDetailsReady(displayName = ""), @@ -54,7 +55,7 @@ class TimelineItemGrouperTest { messageShield = null, ) private val aNonGroupableItem = aMessageEvent() - private val aNonGroupableItemNoEvent = TimelineItem.Virtual("virtual", aTimelineItemDaySeparatorModel("Today")) + private val aNonGroupableItemNoEvent = TimelineItem.Virtual(UniqueId("virtual"), aTimelineItemDaySeparatorModel("Today")) @Test fun `test empty`() { @@ -82,8 +83,8 @@ class TimelineItemGrouperTest { fun `test groupables and ensure reordering`() { val result = sut.group( listOf( - aGroupableItem.copy(id = "1"), - aGroupableItem.copy(id = "0"), + aGroupableItem.copy(id = UniqueId("1")), + aGroupableItem.copy(id = UniqueId("0")), ), ) assertThat(result).isEqualTo( @@ -91,8 +92,8 @@ class TimelineItemGrouperTest { TimelineItem.GroupedEvents( id = computeGroupIdWith(aGroupableItem), events = listOf( - aGroupableItem.copy("0"), - aGroupableItem.copy(id = "1"), + aGroupableItem.copy(id = UniqueId("0")), + aGroupableItem.copy(id = UniqueId("1")), ).toImmutableList(), aggregatedReadReceipts = emptyList().toImmutableList(), ), @@ -161,13 +162,13 @@ class TimelineItemGrouperTest { fun `when calling multiple time the method group over a growing list of groupable items, then groupId is stable`() { // When val groupableItems = mutableListOf( - aGroupableItem.copy(id = "1"), - aGroupableItem.copy(id = "2") + aGroupableItem.copy(id = UniqueId("1")), + aGroupableItem.copy(id = UniqueId("2")) ) val expectedGroupId = sut.group(groupableItems).first().identifier() - groupableItems.add(0, aGroupableItem.copy("3")) - groupableItems.add(2, aGroupableItem.copy("4")) - groupableItems.add(aGroupableItem.copy("5")) + groupableItems.add(0, aGroupableItem.copy(UniqueId("3"))) + groupableItems.add(2, aGroupableItem.copy(UniqueId("4"))) + groupableItems.add(aGroupableItem.copy(UniqueId("5"))) val actualGroupId = sut.group(groupableItems).first().identifier() // Then assertThat(actualGroupId).isEqualTo(expectedGroupId) 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 93882d5f3e..5678a5c377 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 @@ -19,6 +19,7 @@ package io.element.android.features.messages.impl.voicemessages.timeline import com.google.common.truth.Truth.assertThat import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.matrix.api.core.EventId +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 @@ -80,7 +81,7 @@ fun TestScope.aDefaultRedactedVoiceMessageManager( fun aRedactedMatrixTimeline(eventId: EventId) = listOf( MatrixTimelineItem.Event( - uniqueId = "0", + uniqueId = UniqueId("0"), event = EventTimelineItem( eventId = eventId, transactionId = null, diff --git a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/PollFixtures.kt b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/PollFixtures.kt index c0a5b4f7f7..f39f89f78f 100644 --- a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/PollFixtures.kt +++ b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/PollFixtures.kt @@ -17,6 +17,7 @@ package io.element.android.features.poll.impl import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.poll.PollAnswer import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.item.event.PollContent @@ -32,8 +33,8 @@ fun aPollTimelineItems( return flowOf( polls.map { entry -> MatrixTimelineItem.Event( - entry.key.value, - anEventTimelineItem( + uniqueId = UniqueId(entry.key.value), + event = anEventTimelineItem( eventId = entry.key, content = entry.value, ) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8e216da35f..3d92db06b6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -162,7 +162,7 @@ jsoup = "org.jsoup:jsoup:1.18.1" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.0.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.40" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.41" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/AuthenticationException.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/AuthenticationException.kt index 559a548757..c3ae4cd57e 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/AuthenticationException.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/AuthenticationException.kt @@ -18,6 +18,6 @@ package io.element.android.libraries.matrix.api.auth sealed class AuthenticationException(message: String) : Exception(message) { class InvalidServerName(message: String) : AuthenticationException(message) - class SlidingSyncNotAvailable(message: String) : AuthenticationException(message) + class SlidingSyncVersion(message: String) : AuthenticationException(message) class Generic(message: String) : AuthenticationException(message) } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/UniqueId.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/UniqueId.kt new file mode 100644 index 0000000000..0d3df89660 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/UniqueId.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.api.core + +import java.io.Serializable + +@JvmInline +value class UniqueId(val value: String) : Serializable { + override fun toString(): String = value +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index b3feb25d5f..9b301b9288 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -22,6 +22,7 @@ import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.TransactionId +import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.media.AudioInfo import io.element.android.libraries.matrix.api.media.FileInfo @@ -155,7 +156,7 @@ interface MatrixRoom : Closeable { suspend fun sendFile(file: File, fileInfo: FileInfo, progressCallback: ProgressCallback?): Result - suspend fun toggleReaction(emoji: String, eventId: EventId): Result + suspend fun toggleReaction(emoji: String, uniqueId: UniqueId): Result suspend fun forwardEvent(eventId: EventId, roomIds: List): Result diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/MatrixTimelineItem.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/MatrixTimelineItem.kt index b677332e5f..84aa220620 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/MatrixTimelineItem.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/MatrixTimelineItem.kt @@ -18,15 +18,16 @@ package io.element.android.libraries.matrix.api.timeline import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.TransactionId +import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem sealed interface MatrixTimelineItem { - data class Event(val uniqueId: String, val event: EventTimelineItem) : MatrixTimelineItem { + data class Event(val uniqueId: UniqueId, val event: EventTimelineItem) : MatrixTimelineItem { val eventId: EventId? = event.eventId val transactionId: TransactionId? = event.transactionId } - data class Virtual(val uniqueId: String, val virtual: VirtualTimelineItem) : MatrixTimelineItem + data class Virtual(val uniqueId: UniqueId, val virtual: VirtualTimelineItem) : MatrixTimelineItem data object Other : MatrixTimelineItem } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt index 9585b2521b..1bfa8e8336 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt @@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.TransactionId +import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.media.AudioInfo import io.element.android.libraries.matrix.api.media.FileInfo import io.element.android.libraries.matrix.api.media.ImageInfo @@ -97,7 +98,7 @@ interface Timeline : AutoCloseable { suspend fun sendFile(file: File, fileInfo: FileInfo, progressCallback: ProgressCallback?): Result - suspend fun toggleReaction(emoji: String, eventId: EventId): Result + suspend fun toggleReaction(emoji: String, uniqueId: UniqueId): Result suspend fun forwardEvent(eventId: EventId, roomIds: List): Result diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TracingFilterConfiguration.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TracingFilterConfiguration.kt index 5ef123f35d..0ce3c3bdba 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TracingFilterConfiguration.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TracingFilterConfiguration.kt @@ -30,6 +30,7 @@ data class TracingFilterConfiguration( Target.MATRIX_SDK_SLIDING_SYNC to LogLevel.INFO, Target.MATRIX_SDK_BASE_SLIDING_SYNC to LogLevel.INFO, Target.MATRIX_SDK_UI_TIMELINE to LogLevel.INFO, + Target.MATRIX_SDK_BASE_CLIENT to LogLevel.TRACE, // To debug OIDC logouts Target.MATRIX_SDK_OIDC to LogLevel.TRACE, ) @@ -69,6 +70,7 @@ enum class Target(open val filter: String) { MATRIX_SDK_BASE_SLIDING_SYNC("matrix_sdk_base::sliding_sync"), MATRIX_SDK_UI_TIMELINE("matrix_sdk_ui::timeline"), MATRIX_SDK_BASE_READ_RECEIPTS("matrix_sdk_base::read_receipts"), + MATRIX_SDK_BASE_CLIENT("matrix_sdk_base"), } enum class LogLevel(open val filter: String) { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt index 2dfb215116..c62b4a0da5 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt @@ -16,6 +16,7 @@ package io.element.android.libraries.matrix.impl +import io.element.android.appconfig.AuthenticationConfig import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.di.CacheDirectory import io.element.android.libraries.matrix.impl.analytics.UtdTracker @@ -34,6 +35,8 @@ import kotlinx.coroutines.flow.first import kotlinx.coroutines.withContext import org.matrix.rustcomponents.sdk.ClientBuilder import org.matrix.rustcomponents.sdk.Session +import org.matrix.rustcomponents.sdk.SlidingSyncVersion +import org.matrix.rustcomponents.sdk.SlidingSyncVersionBuilder import org.matrix.rustcomponents.sdk.use import timber.log.Timber import java.io.File @@ -56,11 +59,11 @@ class RustMatrixClientFactory @Inject constructor( val client = getBaseClientBuilder( sessionPaths = sessionData.getSessionPaths(), passphrase = sessionData.passphrase, - slidingSync = if (appPreferencesStore.isSimplifiedSlidingSyncEnabledFlow().first()) { - ClientBuilderSlidingSync.Simplified - } else { - ClientBuilderSlidingSync.Restored - }, + slidingSync = when { + AuthenticationConfig.SLIDING_SYNC_PROXY_URL != null -> ClientBuilderSlidingSync.CustomProxy(AuthenticationConfig.SLIDING_SYNC_PROXY_URL!!) + appPreferencesStore.isSimplifiedSlidingSyncEnabledFlow().first() -> ClientBuilderSlidingSync.Simplified + else -> ClientBuilderSlidingSync.Restored + } ) .homeserverUrl(sessionData.homeserverUrl) .username(sessionData.userId) @@ -91,7 +94,6 @@ class RustMatrixClientFactory @Inject constructor( internal fun getBaseClientBuilder( sessionPaths: SessionPaths, passphrase: String?, - slidingSyncProxy: String? = null, slidingSync: ClientBuilderSlidingSync, ): ClientBuilder { return ClientBuilder() @@ -100,16 +102,17 @@ class RustMatrixClientFactory @Inject constructor( cachePath = sessionPaths.cacheDirectory.absolutePath, ) .passphrase(passphrase) - .slidingSyncProxy(slidingSyncProxy) .userAgent(userAgentProvider.provide()) .addRootCertificates(userCertificatesProvider.provides()) .autoEnableBackups(true) .autoEnableCrossSigning(true) .run { + // Apply sliding sync version settings when (slidingSync) { ClientBuilderSlidingSync.Restored -> this - ClientBuilderSlidingSync.Discovered -> requiresSlidingSync() - ClientBuilderSlidingSync.Simplified -> simplifiedSlidingSync(true) + is ClientBuilderSlidingSync.CustomProxy -> slidingSyncVersionBuilder(SlidingSyncVersionBuilder.Proxy(slidingSync.url)) + ClientBuilderSlidingSync.Discovered -> slidingSyncVersionBuilder(SlidingSyncVersionBuilder.DiscoverProxy) + ClientBuilderSlidingSync.Simplified -> slidingSyncVersionBuilder(SlidingSyncVersionBuilder.Native) } } .run { @@ -119,15 +122,18 @@ class RustMatrixClientFactory @Inject constructor( } } -enum class ClientBuilderSlidingSync { +sealed interface ClientBuilderSlidingSync { + // The proxy is set by the user. + data class CustomProxy(val url: String) : ClientBuilderSlidingSync + // The proxy will be supplied when restoring the Session. - Restored, + data object Restored : ClientBuilderSlidingSync // A proxy must be discovered whilst building the session. - Discovered, + data object Discovered : ClientBuilderSlidingSync // Use Simplified Sliding Sync (discovery isn't a thing yet). - Simplified, + data object Simplified : ClientBuilderSlidingSync } private fun SessionData.toSession() = Session( @@ -136,6 +142,6 @@ private fun SessionData.toSession() = Session( userId = userId, deviceId = deviceId, homeserverUrl = homeserverUrl, - slidingSyncProxy = slidingSyncProxy, + slidingSyncVersion = slidingSyncProxy?.let(SlidingSyncVersion::Proxy) ?: SlidingSyncVersion.Native, oidcData = oidcData, ) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt index 9e2f5b0b5b..90260037df 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt @@ -24,7 +24,7 @@ fun Throwable.mapAuthenticationException(): AuthenticationException { return when (this) { is RustAuthenticationException.Generic -> AuthenticationException.Generic(message) is RustAuthenticationException.InvalidServerName -> AuthenticationException.InvalidServerName(message) - is RustAuthenticationException.SlidingSyncNotAvailable -> AuthenticationException.SlidingSyncNotAvailable(message) + is RustAuthenticationException.SlidingSyncVersion -> AuthenticationException.SlidingSyncVersion(message) else -> AuthenticationException.Generic(message) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt index 5459afea6c..276cf4243c 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt @@ -17,7 +17,6 @@ package io.element.android.libraries.matrix.impl.auth import com.squareup.anvil.annotations.ContributesBinding -import io.element.android.appconfig.AuthenticationConfig import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.extensions.mapFailure import io.element.android.libraries.di.AppScope @@ -223,7 +222,6 @@ class RustMatrixAuthenticationService @Inject constructor( val client = rustMatrixClientFactory.getBaseClientBuilder( sessionPaths = emptySessionPaths, passphrase = pendingPassphrase, - slidingSyncProxy = AuthenticationConfig.SLIDING_SYNC_PROXY_URL, slidingSync = ClientBuilderSlidingSync.Discovered, ) .buildWithQrCode( @@ -267,7 +265,6 @@ class RustMatrixAuthenticationService @Inject constructor( .getBaseClientBuilder( sessionPaths = sessionPaths, passphrase = pendingPassphrase, - slidingSyncProxy = AuthenticationConfig.SLIDING_SYNC_PROXY_URL, slidingSync = ClientBuilderSlidingSync.Discovered, ) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/Session.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/Session.kt index 280d76691c..28d1f9ca59 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/Session.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/Session.kt @@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.impl.paths.SessionPaths import io.element.android.libraries.sessionstorage.api.LoginType import io.element.android.libraries.sessionstorage.api.SessionData import org.matrix.rustcomponents.sdk.Session +import org.matrix.rustcomponents.sdk.SlidingSyncVersion import java.util.Date internal fun Session.toSessionData( @@ -35,7 +36,7 @@ internal fun Session.toSessionData( refreshToken = refreshToken, homeserverUrl = homeserverUrl ?: this.homeserverUrl, oidcData = oidcData, - slidingSyncProxy = slidingSyncProxy, + slidingSyncProxy = (slidingSyncVersion as? SlidingSyncVersion.Proxy)?.url, loginTimestamp = Date(), isTokenValid = isTokenValid, loginType = loginType, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index 20dceeeb87..4d7888fbf9 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -25,6 +25,7 @@ import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.TransactionId +import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.media.AudioInfo import io.element.android.libraries.matrix.api.media.FileInfo @@ -459,8 +460,8 @@ class RustMatrixRoom( return liveTimeline.sendFile(file, fileInfo, progressCallback) } - override suspend fun toggleReaction(emoji: String, eventId: EventId): Result { - return liveTimeline.toggleReaction(emoji, eventId) + override suspend fun toggleReaction(emoji: String, uniqueId: UniqueId): Result { + return liveTimeline.toggleReaction(emoji, uniqueId) } override suspend fun forwardEvent(eventId: EventId, roomIds: List): Result { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineItemMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineItemMapper.kt index d38c86f0f9..cd6b5d0cfd 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineItemMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineItemMapper.kt @@ -17,6 +17,7 @@ package io.element.android.libraries.matrix.impl.timeline import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.impl.timeline.item.event.EventTimelineItemMapper import io.element.android.libraries.matrix.impl.timeline.item.virtual.VirtualTimelineItemMapper @@ -31,7 +32,7 @@ class MatrixTimelineItemMapper( private val eventTimelineItemMapper: EventTimelineItemMapper = EventTimelineItemMapper(), ) { fun map(timelineItem: TimelineItem): MatrixTimelineItem = timelineItem.use { - val uniqueId = timelineItem.uniqueId() + val uniqueId = UniqueId(timelineItem.uniqueId()) val asEvent = it.asEvent() if (asEvent != null) { val eventTimelineItem = eventTimelineItemMapper.map(asEvent) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt index 8c774d2d29..8d88713dc6 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt @@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.TransactionId +import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.media.AudioInfo import io.element.android.libraries.matrix.api.media.FileInfo import io.element.android.libraries.matrix.api.media.ImageInfo @@ -391,9 +392,9 @@ class RustTimeline( } } - override suspend fun toggleReaction(emoji: String, eventId: EventId): Result = withContext(dispatcher) { + override suspend fun toggleReaction(emoji: String, uniqueId: UniqueId): Result = withContext(dispatcher) { runCatching { - inner.toggleReaction(key = emoji, eventId = eventId.value) + inner.toggleReaction(key = emoji, uniqueId = uniqueId.value) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LastForwardIndicatorsPostProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LastForwardIndicatorsPostProcessor.kt index d717fac00d..d10dde519f 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LastForwardIndicatorsPostProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LastForwardIndicatorsPostProcessor.kt @@ -16,6 +16,7 @@ package io.element.android.libraries.matrix.impl.timeline.postprocessor +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.virtual.VirtualTimelineItem @@ -25,7 +26,7 @@ import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTime class LastForwardIndicatorsPostProcessor( private val isTimelineLive: Boolean, ) { - private val lastForwardIdentifiers = LinkedHashSet() + private val lastForwardIdentifiers = LinkedHashSet() fun process( items: List, @@ -56,17 +57,17 @@ class LastForwardIndicatorsPostProcessor( } } -private fun createLastForwardIndicator(identifier: String): MatrixTimelineItem { +private fun createLastForwardIndicator(identifier: UniqueId): MatrixTimelineItem { return MatrixTimelineItem.Virtual( - uniqueId = "last_forward_indicator_$identifier", + uniqueId = UniqueId("last_forward_indicator_$identifier"), virtual = VirtualTimelineItem.LastForwardIndicator ) } -private fun List.latestEventIdentifier(): String { +private fun List.latestEventIdentifier(): UniqueId { return findLast { it is MatrixTimelineItem.Event }?.let { (it as MatrixTimelineItem.Event).uniqueId - } ?: "fake_id" + } ?: UniqueId("fake_id") } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessor.kt index 7e24f89c1c..da38712ce4 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessor.kt @@ -16,6 +16,7 @@ package io.element.android.libraries.matrix.impl.timeline.postprocessor +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.Timeline import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem @@ -33,7 +34,7 @@ class LoadingIndicatorsPostProcessor(private val systemClock: SystemClock) { return buildList { if (shouldAddBackwardLoadingIndicator) { val backwardLoadingIndicator = MatrixTimelineItem.Virtual( - uniqueId = "BackwardLoadingIndicator", + uniqueId = UniqueId("BackwardLoadingIndicator"), virtual = VirtualTimelineItem.LoadingIndicator( direction = Timeline.PaginationDirection.BACKWARDS, timestamp = currentTimestamp @@ -44,7 +45,7 @@ class LoadingIndicatorsPostProcessor(private val systemClock: SystemClock) { addAll(items) if (shouldAddForwardLoadingIndicator) { val forwardLoadingIndicator = MatrixTimelineItem.Virtual( - uniqueId = "ForwardLoadingIndicator", + uniqueId = UniqueId("ForwardLoadingIndicator"), virtual = VirtualTimelineItem.LoadingIndicator( direction = Timeline.PaginationDirection.FORWARDS, timestamp = currentTimestamp diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessor.kt index e3fa9c8072..441982a4b7 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessor.kt @@ -17,6 +17,7 @@ package io.element.android.libraries.matrix.impl.timeline.postprocessor import androidx.annotation.VisibleForTesting +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.event.MembershipChange import io.element.android.libraries.matrix.api.timeline.item.event.OtherState @@ -77,7 +78,7 @@ class RoomBeginningPostProcessor { @VisibleForTesting fun createRoomBeginningItem(): MatrixTimelineItem.Virtual { return MatrixTimelineItem.Virtual( - uniqueId = VirtualTimelineItem.RoomBeginning.toString(), + uniqueId = UniqueId("RoomBeginning"), virtual = VirtualTimelineItem.RoomBeginning ) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessor.kt index e2b0530c53..22afcd53d9 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessor.kt @@ -16,6 +16,7 @@ package io.element.android.libraries.matrix.impl.timeline.postprocessor +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.virtual.VirtualTimelineItem import kotlinx.coroutines.CoroutineDispatcher @@ -23,6 +24,8 @@ import kotlinx.coroutines.withContext import timber.log.Timber import java.util.Date +internal val encryptedHistoryBannerId = UniqueId("EncryptedHistoryBannerId") + class TimelineEncryptedHistoryPostProcessor( private val dispatcher: CoroutineDispatcher, private val lastLoginTimestamp: Date?, @@ -44,7 +47,7 @@ class TimelineEncryptedHistoryPostProcessor( } return if (lastEncryptedHistoryBannerIndex >= 0) { val sublist = list.drop(lastEncryptedHistoryBannerIndex + 1).toMutableList() - sublist.add(0, MatrixTimelineItem.Virtual(VirtualTimelineItem.EncryptedHistoryBanner.toString(), VirtualTimelineItem.EncryptedHistoryBanner)) + sublist.add(0, MatrixTimelineItem.Virtual(encryptedHistoryBannerId, VirtualTimelineItem.EncryptedHistoryBanner)) sublist } else { list diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationExceptionMappingTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationExceptionMappingTest.kt index 3dff6320b2..6164758d60 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationExceptionMappingTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationExceptionMappingTest.kt @@ -48,8 +48,8 @@ class AuthenticationExceptionMappingTest { assertThat(ClientBuildException.Sdk("SDK issue").mapAuthenticationException()) .isException("SDK issue") - assertThat(ClientBuildException.SlidingSyncNotAvailable("Sliding sync not available").mapAuthenticationException()) - .isException("Sliding sync not available") + assertThat(ClientBuildException.SlidingSyncVersion("Sliding sync not available").mapAuthenticationException()) + .isException("Sliding sync not available") } private inline fun ThrowableSubject.isException(message: String) { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt index 63b0664bc7..d46655834d 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt @@ -17,6 +17,7 @@ package io.element.android.libraries.matrix.impl.timeline.postprocessor import com.google.common.truth.Truth.assertThat +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.event.MembershipChange import io.element.android.libraries.matrix.api.timeline.item.event.OtherState @@ -33,8 +34,8 @@ class RoomBeginningPostProcessorTest { @Test fun `processor removes room creation event and self-join event from DM timeline`() { val timelineItems = listOf( - MatrixTimelineItem.Event("m.room.create", anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))), - MatrixTimelineItem.Event("m.room.member", anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))), + MatrixTimelineItem.Event(UniqueId("m.room.create"), anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))), + MatrixTimelineItem.Event(UniqueId("m.room.member"), anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))), ) val processor = RoomBeginningPostProcessor() val processedItems = processor.process(timelineItems, isDm = true, hasMoreToLoadBackwards = false) @@ -44,14 +45,20 @@ class RoomBeginningPostProcessorTest { @Test fun `processor removes room creation event and self-join event from DM timeline even if they're not the first items`() { val timelineItems = listOf( - MatrixTimelineItem.Event("m.room.member_other", anEventTimelineItem(content = RoomMembershipContent(A_USER_ID_2, null, MembershipChange.JOINED))), - MatrixTimelineItem.Event("m.room.create", anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))), - MatrixTimelineItem.Event("m.room.message", anEventTimelineItem(content = aMessageContent("hi"))), - MatrixTimelineItem.Event("m.room.member", anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))), + MatrixTimelineItem.Event( + UniqueId("m.room.member_other"), + anEventTimelineItem(content = RoomMembershipContent(A_USER_ID_2, null, MembershipChange.JOINED)) + ), + MatrixTimelineItem.Event(UniqueId("m.room.create"), anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))), + MatrixTimelineItem.Event(UniqueId("m.room.message"), anEventTimelineItem(content = aMessageContent("hi"))), + MatrixTimelineItem.Event(UniqueId("m.room.member"), anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))), ) val expected = listOf( - MatrixTimelineItem.Event("m.room.member_other", anEventTimelineItem(content = RoomMembershipContent(A_USER_ID_2, null, MembershipChange.JOINED))), - MatrixTimelineItem.Event("m.room.message", anEventTimelineItem(content = aMessageContent("hi"))), + MatrixTimelineItem.Event( + UniqueId("m.room.member_other"), + anEventTimelineItem(content = RoomMembershipContent(A_USER_ID_2, null, MembershipChange.JOINED)) + ), + MatrixTimelineItem.Event(UniqueId("m.room.message"), anEventTimelineItem(content = aMessageContent("hi"))), ) val processor = RoomBeginningPostProcessor() val processedItems = processor.process(timelineItems, isDm = true, hasMoreToLoadBackwards = false) @@ -61,8 +68,8 @@ class RoomBeginningPostProcessorTest { @Test fun `processor will add beginning of room item if it's not a DM`() { val timelineItems = listOf( - MatrixTimelineItem.Event("m.room.create", anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))), - MatrixTimelineItem.Event("m.room.member", anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))), + MatrixTimelineItem.Event(UniqueId("m.room.create"), anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))), + MatrixTimelineItem.Event(UniqueId("m.room.member"), anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))), ) val processor = RoomBeginningPostProcessor() val processedItems = processor.process(timelineItems, isDm = false, hasMoreToLoadBackwards = false) @@ -74,7 +81,7 @@ class RoomBeginningPostProcessorTest { @Test fun `processor will not add beginning of room item if it's not a DM and EncryptedHistoryBanner item is found`() { val timelineItems = listOf( - MatrixTimelineItem.Virtual("EncryptedHistoryBanner", VirtualTimelineItem.EncryptedHistoryBanner), + MatrixTimelineItem.Virtual(UniqueId("EncryptedHistoryBanner"), VirtualTimelineItem.EncryptedHistoryBanner), ) val processor = RoomBeginningPostProcessor() val processedItems = processor.process(timelineItems, isDm = false, hasMoreToLoadBackwards = false) @@ -84,8 +91,8 @@ class RoomBeginningPostProcessorTest { @Test fun `processor won't remove items if it's not at the start of the timeline`() { val timelineItems = listOf( - MatrixTimelineItem.Event("m.room.create", anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))), - MatrixTimelineItem.Event("m.room.member", anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))), + MatrixTimelineItem.Event(UniqueId("m.room.create"), anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))), + MatrixTimelineItem.Event(UniqueId("m.room.member"), anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))), ) val processor = RoomBeginningPostProcessor() val processedItems = processor.process(timelineItems, isDm = true, hasMoreToLoadBackwards = true) @@ -95,7 +102,7 @@ class RoomBeginningPostProcessorTest { @Test fun `processor won't remove the first member join event if it can't find the room creation event`() { val timelineItems = listOf( - MatrixTimelineItem.Event("m.room.member", anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))), + MatrixTimelineItem.Event(UniqueId("m.room.member"), anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))), ) val processor = RoomBeginningPostProcessor() val processedItems = processor.process(timelineItems, isDm = true, hasMoreToLoadBackwards = true) @@ -105,8 +112,11 @@ class RoomBeginningPostProcessorTest { @Test fun `processor won't remove the first member join event if it's not from the room creator`() { val timelineItems = listOf( - MatrixTimelineItem.Event("m.room.create", anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))), - MatrixTimelineItem.Event("m.room.member", anEventTimelineItem(content = RoomMembershipContent(A_USER_ID_2, null, MembershipChange.JOINED))), + MatrixTimelineItem.Event(UniqueId("m.room.create"), anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))), + MatrixTimelineItem.Event( + UniqueId("m.room.member"), + anEventTimelineItem(content = RoomMembershipContent(A_USER_ID_2, null, MembershipChange.JOINED)) + ), ) val processor = RoomBeginningPostProcessor() val processedItems = processor.process(timelineItems, isDm = true, hasMoreToLoadBackwards = true) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessorTest.kt index 3343cbbdf4..cab7bed96b 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessorTest.kt @@ -19,6 +19,7 @@ package io.element.android.libraries.matrix.impl.timeline.postprocessor import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem +import io.element.android.libraries.matrix.test.A_UNIQUE_ID import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope @@ -26,8 +27,6 @@ import kotlinx.coroutines.test.runTest import org.junit.Test import java.util.Date -private const val FAKE_UNIQUE_ID = "FAKE_UNIQUE_ID" - class TimelineEncryptedHistoryPostProcessorTest { private val defaultLastLoginTimestamp = Date(1_689_061_264L) @@ -35,7 +34,7 @@ class TimelineEncryptedHistoryPostProcessorTest { fun `given an unencrypted room, nothing is done`() = runTest { val processor = createPostProcessor(isRoomEncrypted = false) val items = listOf( - MatrixTimelineItem.Event(FAKE_UNIQUE_ID, anEventTimelineItem()) + MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem()) ) assertThat(processor.process(items)).isSameInstanceAs(items) } @@ -44,7 +43,7 @@ class TimelineEncryptedHistoryPostProcessorTest { fun `given an encrypted room, and key backup enabled, nothing is done`() = runTest { val processor = createPostProcessor(isKeyBackupEnabled = true) val items = listOf( - MatrixTimelineItem.Event(FAKE_UNIQUE_ID, anEventTimelineItem()) + MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem()) ) assertThat(processor.process(items)).isSameInstanceAs(items) } @@ -53,7 +52,7 @@ class TimelineEncryptedHistoryPostProcessorTest { fun `given a null lastLoginTimestamp, nothing is done`() = runTest { val processor = createPostProcessor(lastLoginTimestamp = null) val items = listOf( - MatrixTimelineItem.Event(FAKE_UNIQUE_ID, anEventTimelineItem()) + MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem()) ) assertThat(processor.process(items)).isSameInstanceAs(items) } @@ -69,7 +68,7 @@ class TimelineEncryptedHistoryPostProcessorTest { fun `given a list with no items before lastLoginTimestamp, nothing is done`() = runTest { val processor = createPostProcessor() val items = listOf( - MatrixTimelineItem.Event(FAKE_UNIQUE_ID, anEventTimelineItem(timestamp = defaultLastLoginTimestamp.time + 1)) + MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem(timestamp = defaultLastLoginTimestamp.time + 1)) ) assertThat(processor.process(items)).isSameInstanceAs(items) } @@ -78,20 +77,20 @@ class TimelineEncryptedHistoryPostProcessorTest { fun `given a list with an item with equal timestamp as lastLoginTimestamp, it's replaced`() = runTest { val processor = createPostProcessor() val items = listOf( - MatrixTimelineItem.Event(FAKE_UNIQUE_ID, anEventTimelineItem(timestamp = defaultLastLoginTimestamp.time)) + MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem(timestamp = defaultLastLoginTimestamp.time)) ) assertThat(processor.process(items)) - .isEqualTo(listOf(MatrixTimelineItem.Virtual(VirtualTimelineItem.EncryptedHistoryBanner.toString(), VirtualTimelineItem.EncryptedHistoryBanner))) + .isEqualTo(listOf(MatrixTimelineItem.Virtual(encryptedHistoryBannerId, VirtualTimelineItem.EncryptedHistoryBanner))) } @Test fun `given a list with an item with a lower timestamp than lastLoginTimestamp, it's replaced`() = runTest { val processor = createPostProcessor() val items = listOf( - MatrixTimelineItem.Event(FAKE_UNIQUE_ID, anEventTimelineItem(timestamp = defaultLastLoginTimestamp.time - 1)) + MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem(timestamp = defaultLastLoginTimestamp.time - 1)) ) assertThat(processor.process(items)).isEqualTo( - listOf(MatrixTimelineItem.Virtual(VirtualTimelineItem.EncryptedHistoryBanner.toString(), VirtualTimelineItem.EncryptedHistoryBanner)) + listOf(MatrixTimelineItem.Virtual(encryptedHistoryBannerId, VirtualTimelineItem.EncryptedHistoryBanner)) ) } @@ -99,14 +98,14 @@ class TimelineEncryptedHistoryPostProcessorTest { fun `given a list with several with lower or equal timestamps than lastLoginTimestamp, then they're replaced`() = runTest { val processor = createPostProcessor() val items = listOf( - MatrixTimelineItem.Event(FAKE_UNIQUE_ID, anEventTimelineItem(timestamp = defaultLastLoginTimestamp.time - 1)), - MatrixTimelineItem.Event(FAKE_UNIQUE_ID, anEventTimelineItem(timestamp = defaultLastLoginTimestamp.time)), - MatrixTimelineItem.Event(FAKE_UNIQUE_ID, anEventTimelineItem(timestamp = defaultLastLoginTimestamp.time + 1)), + MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem(timestamp = defaultLastLoginTimestamp.time - 1)), + MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem(timestamp = defaultLastLoginTimestamp.time)), + MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem(timestamp = defaultLastLoginTimestamp.time + 1)), ) assertThat(processor.process(items)).isEqualTo( listOf( - MatrixTimelineItem.Virtual(VirtualTimelineItem.EncryptedHistoryBanner.toString(), VirtualTimelineItem.EncryptedHistoryBanner), - MatrixTimelineItem.Event(FAKE_UNIQUE_ID, anEventTimelineItem(timestamp = defaultLastLoginTimestamp.time + 1)) + MatrixTimelineItem.Virtual(encryptedHistoryBannerId, VirtualTimelineItem.EncryptedHistoryBanner), + MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem(timestamp = defaultLastLoginTimestamp.time + 1)) ) ) } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt index 3b39530978..3aa898a30d 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt @@ -24,6 +24,7 @@ import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.SpaceId import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.TransactionId +import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.RoomNotificationSettings @@ -55,7 +56,9 @@ val AN_EVENT_ID = EventId("\$anEventId") val AN_EVENT_ID_2 = EventId("\$anEventId2") val A_ROOM_ALIAS = RoomAlias("#alias1:domain") val A_TRANSACTION_ID = TransactionId("aTransactionId") -const val A_UNIQUE_ID = "aUniqueId" + +val A_UNIQUE_ID = UniqueId("aUniqueId") +val A_UNIQUE_ID_2 = UniqueId("aUniqueId2") const val A_ROOM_NAME = "A room name" const val A_ROOM_RAW_NAME = "A room raw name" diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index af1ad33bdc..49fddf5214 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -22,6 +22,7 @@ import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.TransactionId +import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.media.AudioInfo import io.element.android.libraries.matrix.api.media.FileInfo @@ -108,7 +109,7 @@ class FakeMatrixRoom( private val editMessageLambda: (EventId, String, String?, List) -> Result = { _, _, _, _ -> lambdaError() }, private val sendMessageResult: (String, String?, List) -> Result = { _, _, _ -> lambdaError() }, private val updateUserRoleResult: () -> Result = { lambdaError() }, - private val toggleReactionResult: (String, EventId) -> Result = { _, _ -> lambdaError() }, + private val toggleReactionResult: (String, UniqueId) -> Result = { _, _ -> lambdaError() }, private val retrySendMessageResult: (TransactionId) -> Result = { lambdaError() }, private val cancelSendResult: (TransactionId) -> Result = { lambdaError() }, private val forwardEventResult: (EventId, List) -> Result = { _, _ -> lambdaError() }, @@ -230,8 +231,8 @@ class FakeMatrixRoom( sendMessageResult(body, htmlBody, intentionalMentions) } - override suspend fun toggleReaction(emoji: String, eventId: EventId): Result { - return toggleReactionResult(emoji, eventId) + override suspend fun toggleReaction(emoji: String, uniqueId: UniqueId): Result { + return toggleReactionResult(emoji, uniqueId) } override suspend fun retrySendMessage(transactionId: TransactionId): Result { diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt index ea28693872..7f9a370fd8 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt @@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.TransactionId +import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.media.AudioInfo import io.element.android.libraries.matrix.api.media.FileInfo import io.element.android.libraries.matrix.api.media.ImageInfo @@ -219,8 +220,8 @@ class FakeTimeline( progressCallback ) - var toggleReactionLambda: (emoji: String, eventId: EventId) -> Result = { _, _ -> Result.success(Unit) } - override suspend fun toggleReaction(emoji: String, eventId: EventId): Result = toggleReactionLambda(emoji, eventId) + var toggleReactionLambda: (emoji: String, uniqueId: UniqueId) -> Result = { _, _ -> Result.success(Unit) } + override suspend fun toggleReaction(emoji: String, uniqueId: UniqueId): Result = toggleReactionLambda(emoji, uniqueId) var forwardEventLambda: (eventId: EventId, roomIds: List) -> Result = { _, _ -> Result.success(Unit) } override suspend fun forwardEvent(eventId: EventId, roomIds: List): Result = forwardEventLambda(eventId, roomIds)