From 53ce85872bf5a9284713694139c26b0272278988 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 27 Jan 2026 09:13:07 +0100 Subject: [PATCH 01/18] Remove unused `MessagesEvents.Dismiss` --- .../android/features/messages/impl/MessagesEvents.kt | 1 - .../features/messages/impl/MessagesPresenter.kt | 2 -- .../features/messages/impl/MessagesPresenterTest.kt | 10 ---------- 3 files changed, 13 deletions(-) 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 2419d76038..ecd9a5117d 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,7 +18,6 @@ sealed interface MessagesEvents { data class ToggleReaction(val emoji: String, val eventOrTransactionId: EventOrTransactionId) : MessagesEvents data class InviteDialogDismissed(val action: InviteDialogAction) : MessagesEvents data class OnUserClicked(val user: MatrixUser) : MessagesEvents - data object Dismiss : MessagesEvents data object MarkAsFullyReadAndExit : 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 8a5f3cf423..075c51e1c0 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 @@ -27,7 +27,6 @@ import dev.zacsweers.metro.AssistedInject import im.vector.app.features.analytics.plan.PinUnpinAction import io.element.android.appconfig.MessageComposerConfig import io.element.android.features.messages.api.timeline.HtmlConverterProvider -import io.element.android.features.messages.impl.actionlist.ActionListEvents import io.element.android.features.messages.impl.actionlist.ActionListState import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.crypto.historyvisible.HistoryVisibleState @@ -243,7 +242,6 @@ class MessagesPresenter( localCoroutineScope.reinviteOtherUser(inviteProgress) } } - is MessagesEvents.Dismiss -> actionListState.eventSink(ActionListEvents.Clear) is MessagesEvents.OnUserClicked -> { roomMemberModerationState.eventSink(RoomMemberModerationEvents.ShowActionsForUser(event.user)) } 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 bdf84e9eec..5576e40023 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 @@ -539,16 +539,6 @@ class MessagesPresenterTest { } } - @Test - fun `present - handle dismiss action`() = runTest { - val presenter = createMessagesPresenter() - presenter.testWithLifecycleOwner { - val initialState = awaitItem() - initialState.eventSink(MessagesEvents.Dismiss) - assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None) - } - } - @Test fun `present - handle action show developer info`() = runTest { val onShowEventDebugInfoClickLambda = lambdaRecorder { _: EventId?, _: TimelineItemDebugInfo -> } From 847766eb33bd659a52110b9a262c84041c99739f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 27 Jan 2026 09:25:12 +0100 Subject: [PATCH 02/18] Add confirmation dialog when ending poll from the bottom sheet. --- .../features/messages/impl/MessagesView.kt | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) 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 ea50cf0fe2..165dbf3fa5 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 @@ -31,6 +31,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment @@ -341,9 +342,30 @@ fun MessagesView( maxBottomSheetContentHeight = maxComposerHeightPx.toDp(), ) + var endPollConfirmingEvent: TimelineItem.Event? by remember { mutableStateOf(null) } + + if (endPollConfirmingEvent != null) { + ConfirmationDialog( + content = stringResource(id = CommonStrings.common_poll_end_confirmation), + onSubmitClick = { + endPollConfirmingEvent?.let { event -> + onActionSelected(TimelineItemAction.EndPoll, event) + } + endPollConfirmingEvent = null + }, + onDismiss = { endPollConfirmingEvent = null }, + ) + } + ActionListView( state = state.actionListState, - onSelectAction = ::onActionSelected, + onSelectAction = { action: TimelineItemAction, event: TimelineItem.Event -> + if (action == TimelineItemAction.EndPoll) { + endPollConfirmingEvent = event + } else { + onActionSelected(action, event) + } + }, onCustomReactionClick = { event -> state.customReactionState.eventSink(CustomReactionEvents.ShowCustomReactionSheet(event)) }, From f7c7fdca9eb67745a3dac8c3c9f960f71fd2f256 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 27 Jan 2026 09:34:18 +0100 Subject: [PATCH 03/18] ActionListEvents -> ActionListEvent --- .../features/messages/impl/MessagesView.kt | 4 +- ...ActionListEvents.kt => ActionListEvent.kt} | 6 +- .../impl/actionlist/ActionListPresenter.kt | 6 +- .../impl/actionlist/ActionListState.kt | 2 +- .../actionlist/ActionListStateProvider.kt | 2 +- .../impl/actionlist/ActionListView.kt | 10 +- .../pinned/list/PinnedMessagesListView.kt | 6 +- .../messages/impl/MessagesPresenterTest.kt | 4 +- .../messages/impl/MessagesViewTest.kt | 6 +- .../actionlist/ActionListPresenterTest.kt | 102 +++++++++--------- .../pinned/list/PinnedMessagesListViewTest.kt | 6 +- 11 files changed, 77 insertions(+), 77 deletions(-) rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/{ActionListEvents.kt => ActionListEvent.kt} (85%) 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 165dbf3fa5..f8a5e22341 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 @@ -52,7 +52,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.features.messages.api.timeline.voicemessages.composer.VoiceMessageComposerEvent -import io.element.android.features.messages.impl.actionlist.ActionListEvents +import io.element.android.features.messages.impl.actionlist.ActionListEvent import io.element.android.features.messages.impl.actionlist.ActionListView import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.crypto.historyvisible.HistoryVisibleStateView @@ -169,7 +169,7 @@ fun MessagesView( Timber.v("OnMessageLongClicked= ${event.id}") hidingKeyboard { state.actionListState.eventSink( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = event, userEventPermissions = state.userEventPermissions, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListEvent.kt similarity index 85% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListEvents.kt rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListEvent.kt index 415a80a48b..df6b1486b8 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListEvent.kt @@ -11,10 +11,10 @@ package io.element.android.features.messages.impl.actionlist import io.element.android.features.messages.impl.UserEventPermissions import io.element.android.features.messages.impl.timeline.model.TimelineItem -sealed interface ActionListEvents { - data object Clear : ActionListEvents +sealed interface ActionListEvent { + data object Clear : ActionListEvent data class ComputeForMessage( val event: TimelineItem.Event, val userEventPermissions: UserEventPermissions, - ) : ActionListEvents + ) : ActionListEvent } 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 36166409b9..f9d97f6d9d 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 @@ -107,10 +107,10 @@ class DefaultActionListPresenter( val isThreadsEnabled = featureFlagService.isFeatureEnabledFlow(FeatureFlags.Threads).collectAsState(false) - fun handleEvent(event: ActionListEvents) { + fun handleEvent(event: ActionListEvent) { when (event) { - ActionListEvents.Clear -> target.value = ActionListState.Target.None - is ActionListEvents.ComputeForMessage -> localCoroutineScope.computeForMessage( + ActionListEvent.Clear -> target.value = ActionListState.Target.None + is ActionListEvent.ComputeForMessage -> localCoroutineScope.computeForMessage( timelineItem = event.event, usersEventPermissions = event.userEventPermissions, isDeveloperModeEnabled = isDeveloperModeEnabled, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListState.kt index c0554aaf0c..179c5e4fa0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListState.kt @@ -16,7 +16,7 @@ import kotlinx.collections.immutable.ImmutableList data class ActionListState( val target: Target, - val eventSink: (ActionListEvents) -> Unit, + val eventSink: (ActionListEvent) -> Unit, ) { @Immutable sealed interface Target { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt index e57e5bdc1e..a69c6d7612 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt @@ -192,7 +192,7 @@ open class ActionListStateProvider : PreviewParameterProvider { fun anActionListState( target: ActionListState.Target = ActionListState.Target.None, - eventSink: (ActionListEvents) -> Unit = {}, + eventSink: (ActionListEvent) -> Unit = {}, ) = ActionListState( target = target, eventSink = eventSink diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt index 704f79a4f5..53f15066b6 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt @@ -118,7 +118,7 @@ fun ActionListView( ) { if (targetItem == null) return sheetState.hide(coroutineScope) { - state.eventSink(ActionListEvents.Clear) + state.eventSink(ActionListEvent.Clear) onSelectAction(itemAction, targetItem) } } @@ -126,7 +126,7 @@ fun ActionListView( fun onEmojiReactionClick(emoji: String) { if (targetItem == null) return sheetState.hide(coroutineScope) { - state.eventSink(ActionListEvents.Clear) + state.eventSink(ActionListEvent.Clear) onEmojiReactionClick(emoji, targetItem) } } @@ -134,19 +134,19 @@ fun ActionListView( fun onCustomReactionClick() { if (targetItem == null) return sheetState.hide(coroutineScope) { - state.eventSink(ActionListEvents.Clear) + state.eventSink(ActionListEvent.Clear) onCustomReactionClick(targetItem) } } fun onDismiss() { - state.eventSink(ActionListEvents.Clear) + state.eventSink(ActionListEvent.Clear) } fun onVerifiedUserSendFailureClick() { if (targetItem == null) return sheetState.hide(coroutineScope) { - state.eventSink(ActionListEvents.Clear) + state.eventSink(ActionListEvent.Clear) onVerifiedUserSendFailureClick(targetItem) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt index 18175f12c9..cdca126753 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt @@ -25,7 +25,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import im.vector.app.features.analytics.plan.Interaction import io.element.android.compound.tokens.generated.CompoundIcons -import io.element.android.features.messages.impl.actionlist.ActionListEvents +import io.element.android.features.messages.impl.actionlist.ActionListEvent import io.element.android.features.messages.impl.actionlist.ActionListView import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.link.LinkEvents @@ -175,7 +175,7 @@ private fun PinnedMessagesListLoaded( ) { fun onActionSelected(timelineItemAction: TimelineItemAction, event: TimelineItem.Event) { state.actionListState.eventSink( - ActionListEvents.Clear + ActionListEvent.Clear ) state.eventSink( PinnedMessagesListEvents.HandleAction( @@ -187,7 +187,7 @@ private fun PinnedMessagesListLoaded( fun onMessageLongClick(event: TimelineItem.Event) { state.actionListState.eventSink( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = event, userEventPermissions = state.userEventPermissions, ) 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 5576e40023..6d9d2ff906 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 @@ -13,7 +13,7 @@ package io.element.android.features.messages.impl import androidx.lifecycle.Lifecycle import com.google.common.truth.Truth.assertThat import im.vector.app.features.analytics.plan.PinUnpinAction -import io.element.android.features.messages.impl.actionlist.ActionListEvents +import io.element.android.features.messages.impl.actionlist.ActionListEvent import io.element.android.features.messages.impl.actionlist.ActionListState import io.element.android.features.messages.impl.actionlist.anActionListState import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction @@ -1276,7 +1276,7 @@ class MessagesPresenterTest { }, encryptionService: FakeEncryptionService = FakeEncryptionService(), featureFlagService: FakeFeatureFlagService = FakeFeatureFlagService(), - actionListEventSink: (ActionListEvents) -> Unit = {}, + actionListEventSink: (ActionListEvent) -> Unit = {}, addRecentEmoji: AddRecentEmoji = AddRecentEmoji { _ -> lambdaError() }, markAsFullyRead: MarkAsFullyRead = FakeMarkAsFullyRead(), ): MessagesPresenter { 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 23665a043c..71d6176bc8 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 @@ -30,7 +30,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.emojibasebindings.Emoji import io.element.android.emojibasebindings.EmojibaseCategory import io.element.android.emojibasebindings.EmojibaseStore -import io.element.android.features.messages.impl.actionlist.ActionListEvents +import io.element.android.features.messages.impl.actionlist.ActionListEvent import io.element.android.features.messages.impl.actionlist.ActionListState import io.element.android.features.messages.impl.actionlist.anActionListState import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction @@ -183,7 +183,7 @@ class MessagesViewTest { userHasPermissionToSendReaction: Boolean = false, userCanPinEvent: Boolean = false, ) { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val state = aMessagesState( actionListState = anActionListState( eventSink = eventsRecorder @@ -206,7 +206,7 @@ class MessagesViewTest { // Cannot perform click on "Text", it's not detected. Use tag instead rule.onAllNodesWithTag(TestTags.messageBubble.value).onFirst().performTouchInput { longClick() } eventsRecorder.assertSingle( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = timelineItem, userEventPermissions = state.userEventPermissions, ) 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 7c61d2b8b2..a07c09998f 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 @@ -79,7 +79,7 @@ class ActionListPresenterTest { val initialState = awaitItem() val messageEvent = aMessageEvent(isMine = true, isEditable = false, content = TimelineItemRedactedContent) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = false, @@ -103,7 +103,7 @@ class ActionListPresenterTest { recentEmojis = suggestedEmojis, ) ) - initialState.eventSink.invoke(ActionListEvents.Clear) + initialState.eventSink.invoke(ActionListEvent.Clear) assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) } } @@ -121,7 +121,7 @@ class ActionListPresenterTest { content = TimelineItemRedactedContent ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = false, @@ -145,7 +145,7 @@ class ActionListPresenterTest { recentEmojis = suggestedEmojis, ) ) - initialState.eventSink.invoke(ActionListEvents.Clear) + initialState.eventSink.invoke(ActionListEvent.Clear) assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) } } @@ -163,7 +163,7 @@ class ActionListPresenterTest { content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false, formattedBody = A_MESSAGE) ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = false, @@ -193,7 +193,7 @@ class ActionListPresenterTest { recentEmojis = suggestedEmojis, ) ) - initialState.eventSink.invoke(ActionListEvents.Clear) + initialState.eventSink.invoke(ActionListEvent.Clear) assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) } } @@ -210,7 +210,7 @@ class ActionListPresenterTest { content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false, formattedBody = A_MESSAGE) ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = false, @@ -240,7 +240,7 @@ class ActionListPresenterTest { recentEmojis = suggestedEmojis, ) ) - initialState.eventSink.invoke(ActionListEvents.Clear) + initialState.eventSink.invoke(ActionListEvent.Clear) assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) } } @@ -258,7 +258,7 @@ class ActionListPresenterTest { content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false, formattedBody = A_MESSAGE) ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = true, @@ -287,7 +287,7 @@ class ActionListPresenterTest { recentEmojis = suggestedEmojis, ) ) - initialState.eventSink.invoke(ActionListEvents.Clear) + initialState.eventSink.invoke(ActionListEvent.Clear) assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) } } @@ -305,7 +305,7 @@ class ActionListPresenterTest { content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false, formattedBody = A_MESSAGE) ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = false, @@ -336,7 +336,7 @@ class ActionListPresenterTest { recentEmojis = suggestedEmojis, ) ) - initialState.eventSink.invoke(ActionListEvents.Clear) + initialState.eventSink.invoke(ActionListEvent.Clear) assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) } } @@ -354,7 +354,7 @@ class ActionListPresenterTest { content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false, formattedBody = A_MESSAGE) ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = false, @@ -385,7 +385,7 @@ class ActionListPresenterTest { recentEmojis = suggestedEmojis, ) ) - initialState.eventSink.invoke(ActionListEvents.Clear) + initialState.eventSink.invoke(ActionListEvent.Clear) assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) } } @@ -402,7 +402,7 @@ class ActionListPresenterTest { content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false, formattedBody = A_MESSAGE) ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = true, @@ -433,7 +433,7 @@ class ActionListPresenterTest { recentEmojis = suggestedEmojis, ) ) - initialState.eventSink.invoke(ActionListEvents.Clear) + initialState.eventSink.invoke(ActionListEvent.Clear) assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) } } @@ -449,7 +449,7 @@ class ActionListPresenterTest { content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false, formattedBody = A_MESSAGE) ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = true, @@ -480,7 +480,7 @@ class ActionListPresenterTest { recentEmojis = suggestedEmojis, ) ) - initialState.eventSink.invoke(ActionListEvents.Clear) + initialState.eventSink.invoke(ActionListEvent.Clear) assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) } } @@ -497,7 +497,7 @@ class ActionListPresenterTest { content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false, formattedBody = A_MESSAGE) ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = false, @@ -527,7 +527,7 @@ class ActionListPresenterTest { recentEmojis = suggestedEmojis, ) ) - initialState.eventSink.invoke(ActionListEvents.Clear) + initialState.eventSink.invoke(ActionListEvent.Clear) assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) } } @@ -544,7 +544,7 @@ class ActionListPresenterTest { content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false, formattedBody = A_MESSAGE) ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = false, @@ -571,7 +571,7 @@ class ActionListPresenterTest { recentEmojis = suggestedEmojis, ) ) - initialState.eventSink.invoke(ActionListEvents.Clear) + initialState.eventSink.invoke(ActionListEvent.Clear) assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) } } @@ -589,7 +589,7 @@ class ActionListPresenterTest { content = aTimelineItemImageContent(), ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = true, @@ -619,7 +619,7 @@ class ActionListPresenterTest { recentEmojis = suggestedEmojis, ) ) - initialState.eventSink.invoke(ActionListEvents.Clear) + initialState.eventSink.invoke(ActionListEvent.Clear) assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) } } @@ -639,7 +639,7 @@ class ActionListPresenterTest { ), ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = true, @@ -671,7 +671,7 @@ class ActionListPresenterTest { recentEmojis = suggestedEmojis, ) ) - initialState.eventSink.invoke(ActionListEvents.Clear) + initialState.eventSink.invoke(ActionListEvent.Clear) assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) } } @@ -691,7 +691,7 @@ class ActionListPresenterTest { ), ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = true, @@ -721,7 +721,7 @@ class ActionListPresenterTest { recentEmojis = suggestedEmojis, ) ) - initialState.eventSink.invoke(ActionListEvents.Clear) + initialState.eventSink.invoke(ActionListEvent.Clear) assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) } } @@ -738,7 +738,7 @@ class ActionListPresenterTest { content = aTimelineItemStateEventContent(), ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = stateEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = false, @@ -762,7 +762,7 @@ class ActionListPresenterTest { recentEmojis = suggestedEmojis, ) ) - initialState.eventSink.invoke(ActionListEvents.Clear) + initialState.eventSink.invoke(ActionListEvent.Clear) assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) } } @@ -779,7 +779,7 @@ class ActionListPresenterTest { content = aTimelineItemStateEventContent(), ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = stateEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = false, @@ -806,7 +806,7 @@ class ActionListPresenterTest { content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false, formattedBody = A_MESSAGE) ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = true, @@ -836,7 +836,7 @@ class ActionListPresenterTest { recentEmojis = suggestedEmojis, ) ) - initialState.eventSink.invoke(ActionListEvents.Clear) + initialState.eventSink.invoke(ActionListEvent.Clear) assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) } } @@ -853,7 +853,7 @@ class ActionListPresenterTest { content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false, formattedBody = A_MESSAGE) ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = true, @@ -883,7 +883,7 @@ class ActionListPresenterTest { recentEmojis = suggestedEmojis, ) ) - initialState.eventSink.invoke(ActionListEvents.Clear) + initialState.eventSink.invoke(ActionListEvent.Clear) assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) } } @@ -906,7 +906,7 @@ class ActionListPresenterTest { content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false, formattedBody = A_MESSAGE) ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = true, @@ -937,7 +937,7 @@ class ActionListPresenterTest { recentEmojis = suggestedEmojis, ) ) - initialState.eventSink.invoke(ActionListEvents.Clear) + initialState.eventSink.invoke(ActionListEvent.Clear) assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) } } @@ -959,7 +959,7 @@ class ActionListPresenterTest { ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = false, @@ -973,7 +973,7 @@ class ActionListPresenterTest { assertThat(awaitItem().target).isInstanceOf(ActionListState.Target.Success::class.java) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = redactedEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = false, @@ -1005,7 +1005,7 @@ class ActionListPresenterTest { ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = true, @@ -1047,7 +1047,7 @@ class ActionListPresenterTest { content = aTimelineItemPollContent(answerItems = aPollAnswerItemList(hasVotes = false)), ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = true, @@ -1092,7 +1092,7 @@ class ActionListPresenterTest { content = aTimelineItemPollContent(answerItems = aPollAnswerItemList(hasVotes = true)), ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = true, @@ -1136,7 +1136,7 @@ class ActionListPresenterTest { content = aTimelineItemPollContent(isEnded = true), ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = true, @@ -1181,7 +1181,7 @@ class ActionListPresenterTest { ), ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = true, @@ -1224,7 +1224,7 @@ class ActionListPresenterTest { content = TimelineItemRtcNotificationContent(), ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = true, @@ -1264,7 +1264,7 @@ class ActionListPresenterTest { sendState = LocalEventSendState.Failed.VerifiedUserChangedIdentity(users = listOf(A_USER_ID)), ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions(), ) @@ -1296,7 +1296,7 @@ class ActionListPresenterTest { threadInfo = TimelineItemThreadInfo.ThreadResponse(threadRootId = A_THREAD_ID) ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = true, @@ -1350,7 +1350,7 @@ class ActionListPresenterTest { assertThat(messageEvent.isRemote).isTrue() initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = true, @@ -1405,7 +1405,7 @@ class ActionListPresenterTest { assertThat(messageEvent.isRemote).isTrue() initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = true, @@ -1460,7 +1460,7 @@ class ActionListPresenterTest { assertThat(messageEvent.isRemote).isFalse() initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = true, @@ -1513,7 +1513,7 @@ class ActionListPresenterTest { ) initialState.eventSink.invoke( - ActionListEvents.ComputeForMessage( + ActionListEvent.ComputeForMessage( event = messageEvent, userEventPermissions = aUserEventPermissions( canRedactOwn = true, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListViewTest.kt index 3f96f1dfca..2f49c9f91f 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListViewTest.kt @@ -17,7 +17,7 @@ import androidx.compose.ui.test.onFirst import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTouchInput import androidx.test.ext.junit.runners.AndroidJUnit4 -import io.element.android.features.messages.impl.actionlist.ActionListEvents +import io.element.android.features.messages.impl.actionlist.ActionListEvent import io.element.android.features.messages.impl.actionlist.anActionListState import io.element.android.features.messages.impl.timeline.aTimelineItemList import io.element.android.features.messages.impl.timeline.model.TimelineItem @@ -77,7 +77,7 @@ class PinnedMessagesListViewTest { @Test fun `long click on an event emits the expected event`() { - val eventsRecorder = EventsRecorder(expectEvents = true) + val eventsRecorder = EventsRecorder(expectEvents = true) val content = aTimelineItemFileContent() val state = aLoadedPinnedMessagesListState( timelineItems = aTimelineItemList(content), @@ -92,7 +92,7 @@ class PinnedMessagesListViewTest { longClick() } val event = state.timelineItems.first() as TimelineItem.Event - eventsRecorder.assertSingle(ActionListEvents.ComputeForMessage(event, state.userEventPermissions)) + eventsRecorder.assertSingle(ActionListEvent.ComputeForMessage(event, state.userEventPermissions)) } } From f184562d8fefe6ff95845f9775ace62c9c22215c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 27 Jan 2026 09:35:51 +0100 Subject: [PATCH 04/18] Use presenter test extension. --- .../actionlist/ActionListPresenterTest.kt | 127 +++++------------- 1 file changed, 31 insertions(+), 96 deletions(-) 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 a07c09998f..7a99ad39aa 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 @@ -8,9 +8,6 @@ package io.element.android.features.messages.impl.actionlist -import app.cash.molecule.RecompositionMode -import app.cash.molecule.moleculeFlow -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.impl.aUserEventPermissions import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction @@ -62,9 +59,7 @@ class ActionListPresenterTest { @Test fun `present - initial state`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = true) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.target).isEqualTo(ActionListState.Target.None) } @@ -73,9 +68,7 @@ class ActionListPresenterTest { @Test fun `present - compute for message from me redacted`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = true) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent(isMine = true, isEditable = false, content = TimelineItemRedactedContent) initialState.eventSink.invoke( @@ -111,9 +104,7 @@ class ActionListPresenterTest { @Test fun `present - compute for message from others redacted`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = true) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = false, @@ -153,9 +144,7 @@ class ActionListPresenterTest { @Test fun `present - compute for others message`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = true) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = false, @@ -248,9 +237,7 @@ class ActionListPresenterTest { @Test fun `present - compute for others message cannot sent message`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = true) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = false, @@ -295,9 +282,7 @@ class ActionListPresenterTest { @Test fun `present - compute for others message and can redact`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = true) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = false, @@ -344,9 +329,7 @@ class ActionListPresenterTest { @Test fun `present - compute for others message and cannot send reaction`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = true) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = false, @@ -393,9 +376,7 @@ class ActionListPresenterTest { @Test fun `present - compute for my message`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = true) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = true, @@ -488,9 +469,7 @@ class ActionListPresenterTest { @Test fun `present - compute for my message cannot redact`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = true) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = true, @@ -535,9 +514,7 @@ class ActionListPresenterTest { @Test fun `present - compute for my message no permission`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = true) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = true, @@ -579,9 +556,7 @@ class ActionListPresenterTest { @Test fun `present - compute for a media item`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = true) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = true, @@ -627,9 +602,7 @@ class ActionListPresenterTest { @Test fun `present - compute for a media with caption item`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = true) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = true, @@ -679,9 +652,7 @@ class ActionListPresenterTest { @Test fun `present - compute for a media with caption item - other user event`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = true) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = false, @@ -729,9 +700,7 @@ class ActionListPresenterTest { @Test fun `present - compute for a state item in debug build`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = true) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val stateEvent = aTimelineItemEvent( isMine = true, @@ -770,9 +739,7 @@ class ActionListPresenterTest { @Test fun `present - compute for a state item in non-debuggable build`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = false) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val stateEvent = aTimelineItemEvent( isMine = true, @@ -797,9 +764,7 @@ class ActionListPresenterTest { @Test fun `present - compute message in non-debuggable build`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = false) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = true, @@ -844,9 +809,7 @@ class ActionListPresenterTest { @Test fun `present - compute message when user can't pin`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = true) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = true, @@ -897,9 +860,7 @@ class ActionListPresenterTest { isDeveloperModeEnabled = true, room = room ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = true, @@ -945,9 +906,7 @@ class ActionListPresenterTest { @Test fun `present - compute message with no actions`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = false) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = true, @@ -992,9 +951,7 @@ class ActionListPresenterTest { @Test fun `present - compute not sent message`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = false) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( // No event id, so it's not sent yet @@ -1037,9 +994,7 @@ class ActionListPresenterTest { @Test fun `present - compute for editable poll message`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = false) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = true, @@ -1082,9 +1037,7 @@ class ActionListPresenterTest { @Test fun `present - compute for non-editable poll message`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = false) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = true, @@ -1126,9 +1079,7 @@ class ActionListPresenterTest { @Test fun `present - compute for ended poll message`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = false) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = true, @@ -1169,9 +1120,7 @@ class ActionListPresenterTest { @Test fun `present - compute for voice message`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = false) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = true, @@ -1215,9 +1164,7 @@ class ActionListPresenterTest { @Test fun `present - compute for call notify`() = runTest { val presenter = createActionListPresenter(isDeveloperModeEnabled = true) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = true, @@ -1256,9 +1203,7 @@ class ActionListPresenterTest { userDisplayNameResult = { Result.success("Alice") } ) val presenter = createActionListPresenter(isDeveloperModeEnabled = false, room = room) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( sendState = LocalEventSendState.Failed.VerifiedUserChangedIdentity(users = listOf(A_USER_ID)), @@ -1283,9 +1228,7 @@ class ActionListPresenterTest { timelineMode = Timeline.Mode.Thread(A_THREAD_ID), featureFlagService = FakeFeatureFlagService(initialState = mapOf(FeatureFlags.Threads.key to true)), ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = true, @@ -1334,9 +1277,7 @@ class ActionListPresenterTest { isDeveloperModeEnabled = false, featureFlagService = FakeFeatureFlagService(initialState = mapOf(FeatureFlags.Threads.key to true)), ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( eventId = AN_EVENT_ID, @@ -1388,9 +1329,7 @@ class ActionListPresenterTest { isDeveloperModeEnabled = false, featureFlagService = FakeFeatureFlagService(initialState = mapOf(FeatureFlags.Threads.key to true)), ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( eventId = AN_EVENT_ID, @@ -1443,9 +1382,7 @@ class ActionListPresenterTest { isDeveloperModeEnabled = false, featureFlagService = FakeFeatureFlagService(initialState = mapOf(FeatureFlags.Threads.key to true)), ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( eventId = null, @@ -1498,9 +1435,7 @@ class ActionListPresenterTest { isDeveloperModeEnabled = false, recentEmojis = GetRecentEmojis { Result.success((listOf("👍️", ":)", "❤️") + otherEmojis).toImmutableList()) }, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val messageEvent = aMessageEvent( eventId = null, From a1e5afcdd5318cfd4c29769dcd15fb8854223552 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 27 Jan 2026 09:38:45 +0100 Subject: [PATCH 05/18] MessagesEvents -> MessagesEvent --- .../{MessagesEvents.kt => MessagesEvent.kt} | 12 +-- .../features/messages/impl/MessagesNode.kt | 4 +- .../messages/impl/MessagesPresenter.kt | 12 +-- .../features/messages/impl/MessagesState.kt | 2 +- .../messages/impl/MessagesStateProvider.kt | 2 +- .../features/messages/impl/MessagesView.kt | 14 ++-- .../messages/impl/MessagesPresenterTest.kt | 74 +++++++++---------- .../messages/impl/MessagesViewTest.kt | 38 +++++----- 8 files changed, 79 insertions(+), 79 deletions(-) rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/{MessagesEvents.kt => MessagesEvent.kt} (81%) 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/MessagesEvent.kt similarity index 81% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesEvents.kt rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesEvent.kt index ecd9a5117d..bef8ca84d6 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/MessagesEvent.kt @@ -13,12 +13,12 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId import io.element.android.libraries.matrix.api.user.MatrixUser -sealed interface MessagesEvents { - data class HandleAction(val action: TimelineItemAction, val event: TimelineItem.Event) : MessagesEvents - data class ToggleReaction(val emoji: String, val eventOrTransactionId: EventOrTransactionId) : MessagesEvents - data class InviteDialogDismissed(val action: InviteDialogAction) : MessagesEvents - data class OnUserClicked(val user: MatrixUser) : MessagesEvents - data object MarkAsFullyReadAndExit : MessagesEvents +sealed interface MessagesEvent { + data class HandleAction(val action: TimelineItemAction, val event: TimelineItem.Event) : MessagesEvent + data class ToggleReaction(val emoji: String, val eventOrTransactionId: EventOrTransactionId) : MessagesEvent + data class InviteDialogDismissed(val action: InviteDialogAction) : MessagesEvent + data class OnUserClicked(val user: MatrixUser) : MessagesEvent + data object MarkAsFullyReadAndExit : MessagesEvent } enum class InviteDialogAction { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt index 0692a98745..b2507e6870 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt @@ -242,7 +242,7 @@ class MessagesNode( val state = presenter.present() BackHandler { - state.eventSink(MessagesEvents.MarkAsFullyReadAndExit) + state.eventSink(MessagesEvent.MarkAsFullyReadAndExit) } OnLifecycleEvent { _, event -> @@ -253,7 +253,7 @@ class MessagesNode( } MessagesView( state = state, - onBackClick = { state.eventSink(MessagesEvents.MarkAsFullyReadAndExit) }, + onBackClick = { state.eventSink(MessagesEvent.MarkAsFullyReadAndExit) }, onRoomDetailsClick = callback::navigateToRoomDetails, onEventContentClick = { isLive, event -> if (isLive) { 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 075c51e1c0..5f2413c9a1 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 @@ -220,9 +220,9 @@ class MessagesPresenter( onPauseOrDispose {} } - fun handleEvent(event: MessagesEvents) { + fun handleEvent(event: MessagesEvent) { when (event) { - is MessagesEvents.HandleAction -> { + is MessagesEvent.HandleAction -> { localCoroutineScope.handleTimelineAction( action = event.action, targetEvent = event.event, @@ -232,20 +232,20 @@ class MessagesPresenter( timelineProtectionState = timelineProtectionState, ) } - is MessagesEvents.ToggleReaction -> { + is MessagesEvent.ToggleReaction -> { localCoroutineScope.toggleReaction(event.emoji, event.eventOrTransactionId) } - is MessagesEvents.InviteDialogDismissed -> { + is MessagesEvent.InviteDialogDismissed -> { hasDismissedInviteDialog = true if (event.action == InviteDialogAction.Invite) { localCoroutineScope.reinviteOtherUser(inviteProgress) } } - is MessagesEvents.OnUserClicked -> { + is MessagesEvent.OnUserClicked -> { roomMemberModerationState.eventSink(RoomMemberModerationEvents.ShowActionsForUser(event.user)) } - is MessagesEvents.MarkAsFullyReadAndExit -> coroutineScope.launch { + is MessagesEvent.MarkAsFullyReadAndExit -> coroutineScope.launch { if (!markingAsReadAndExiting.getAndSet(true)) { val latestEventId = room.liveTimeline.getLatestEventId().getOrElse { Timber.w(it, "Failed to get latest event id to mark as fully read") diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt index b9d86a6597..f7868806c1 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt @@ -57,7 +57,7 @@ data class MessagesState( val dmUserVerificationState: IdentityState?, val roomMemberModerationState: RoomMemberModerationState, val successorRoom: SuccessorRoom?, - val eventSink: (MessagesEvents) -> Unit + val eventSink: (MessagesEvent) -> Unit ) { val isTombstoned = successorRoom != null } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt index cec9f68b45..b6d8dcd71c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt @@ -133,7 +133,7 @@ fun aMessagesState( dmUserVerificationState: IdentityState? = null, roomMemberModerationState: RoomMemberModerationState = aRoomMemberModerationState(), successorRoom: SuccessorRoom? = null, - eventSink: (MessagesEvents) -> Unit = {}, + eventSink: (MessagesEvent) -> Unit = {}, ) = MessagesState( roomId = RoomId("!id:domain"), roomName = roomName, 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 f8a5e22341..4dfbe74fda 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 @@ -178,11 +178,11 @@ fun MessagesView( } fun onActionSelected(action: TimelineItemAction, event: TimelineItem.Event) { - state.eventSink(MessagesEvents.HandleAction(action, event)) + state.eventSink(MessagesEvent.HandleAction(action, event)) } fun onEmojiReactionClick(emoji: String, event: TimelineItem.Event) { - state.eventSink(MessagesEvents.ToggleReaction(emoji, event.eventOrTransactionId)) + state.eventSink(MessagesEvent.ToggleReaction(emoji, event.eventOrTransactionId)) } fun onEmojiReactionLongClick(emoji: String, event: TimelineItem.Event) { @@ -244,7 +244,7 @@ fun MessagesView( onMessageLongClick = ::onMessageLongClick, onUserDataClick = { hidingKeyboard { - state.eventSink(MessagesEvents.OnUserClicked(it)) + state.eventSink(MessagesEvent.OnUserClicked(it)) } }, onLinkClick = { link, customTab -> @@ -264,7 +264,7 @@ fun MessagesView( onSendLocationClick = onSendLocationClick, onCreatePollClick = onCreatePollClick, onSwipeToReply = { targetEvent -> - state.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Reply, targetEvent)) + state.eventSink(MessagesEvent.HandleAction(TimelineItemAction.Reply, targetEvent)) }, forceJumpToBottomVisibility = forceJumpToBottomVisibility, onJoinCallClick = onJoinCallClick, @@ -378,7 +378,7 @@ fun MessagesView( CustomReactionBottomSheet( state = state.customReactionState, onSelectEmoji = { uniqueId, emoji -> - state.eventSink(MessagesEvents.ToggleReaction(emoji.unicode, uniqueId)) + state.eventSink(MessagesEvent.ToggleReaction(emoji.unicode, uniqueId)) } ) @@ -404,8 +404,8 @@ private fun ReinviteDialog(state: MessagesState) { content = stringResource(id = R.string.screen_room_invite_again_alert_message), cancelText = stringResource(id = CommonStrings.action_cancel), submitText = stringResource(id = CommonStrings.action_invite), - onSubmitClick = { state.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Invite)) }, - onDismiss = { state.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Cancel)) } + onSubmitClick = { state.eventSink(MessagesEvent.InviteDialogDismissed(InviteDialogAction.Invite)) }, + onDismiss = { state.eventSink(MessagesEvent.InviteDialogDismissed(InviteDialogAction.Cancel)) } ) } } 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 6d9d2ff906..3afe719798 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 @@ -185,14 +185,14 @@ class MessagesPresenterTest { presenter.testWithLifecycleOwner { skipItems(1) val initialState = awaitItem() - initialState.eventSink(MessagesEvents.ToggleReaction("👍", AN_EVENT_ID.toEventOrTransactionId())) + initialState.eventSink(MessagesEvent.ToggleReaction("👍", AN_EVENT_ID.toEventOrTransactionId())) advanceUntilIdle() assert(toggleReactionSuccess) .isCalledOnce() .with(value("👍"), value(AN_EVENT_ID.toEventOrTransactionId())) // No crashes when sending a reaction failed timeline.toggleReactionLambda = toggleReactionFailure - initialState.eventSink(MessagesEvents.ToggleReaction("👍", AN_EVENT_ID.toEventOrTransactionId())) + initialState.eventSink(MessagesEvent.ToggleReaction("👍", AN_EVENT_ID.toEventOrTransactionId())) advanceUntilIdle() assert(toggleReactionFailure) .isCalledOnce() @@ -230,8 +230,8 @@ class MessagesPresenterTest { ) presenter.testWithLifecycleOwner { val initialState = awaitItem() - initialState.eventSink(MessagesEvents.ToggleReaction("👍", AN_EVENT_ID.toEventOrTransactionId())) - initialState.eventSink(MessagesEvents.ToggleReaction("👍", AN_EVENT_ID.toEventOrTransactionId())) + initialState.eventSink(MessagesEvent.ToggleReaction("👍", AN_EVENT_ID.toEventOrTransactionId())) + initialState.eventSink(MessagesEvent.ToggleReaction("👍", AN_EVENT_ID.toEventOrTransactionId())) advanceUntilIdle() assert(toggleReactionSuccess) .isCalledExactly(2) @@ -253,7 +253,7 @@ class MessagesPresenterTest { val presenter = createMessagesPresenter(navigator = navigator) presenter.testWithLifecycleOwner { val initialState = awaitItem() - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Forward, aMessageEvent())) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.Forward, aMessageEvent())) assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None) onForwardEventClickLambda.assertions().isCalledOnce().with(value(AN_EVENT_ID)) } @@ -266,7 +266,7 @@ class MessagesPresenterTest { val presenter = createMessagesPresenter(clipboardHelper = clipboardHelper) presenter.testWithLifecycleOwner { val initialState = awaitItem() - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.CopyText, event)) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.CopyText, event)) skipItems(2) assertThat(clipboardHelper.clipboardContents).isEqualTo((event.content as TimelineItemTextContent).body) } @@ -289,7 +289,7 @@ class MessagesPresenterTest { ) presenter.testWithLifecycleOwner { val initialState = awaitItem() - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.CopyLink, event)) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.CopyLink, event)) skipItems(2) assertThat(clipboardHelper.clipboardContents).isEqualTo("a link") } @@ -303,7 +303,7 @@ class MessagesPresenterTest { ) presenter.testWithLifecycleOwner { val initialState = awaitItem() - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Reply, aMessageEvent())) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.Reply, aMessageEvent())) awaitItem() composerRecorder.assertSingle( MessageComposerEvent.SetMode( @@ -321,7 +321,7 @@ class MessagesPresenterTest { val presenter = createMessagesPresenter() presenter.testWithLifecycleOwner { val initialState = awaitItem() - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Reply, aMessageEvent(eventId = null))) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.Reply, aMessageEvent(eventId = null))) skipItems(1) } } @@ -354,7 +354,7 @@ class MessagesPresenterTest { formattedFileSize = "4MB" ) ) - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Reply, mediaMessage)) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.Reply, mediaMessage)) awaitItem() composerRecorder.assertSingle( MessageComposerEvent.SetMode( @@ -396,7 +396,7 @@ class MessagesPresenterTest { formattedFileSize = "50MB" ) ) - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Reply, mediaMessage)) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.Reply, mediaMessage)) awaitItem() composerRecorder.assertSingle( MessageComposerEvent.SetMode( @@ -431,7 +431,7 @@ class MessagesPresenterTest { fileExtension = "pdf", ) ) - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Reply, mediaMessage)) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.Reply, mediaMessage)) awaitItem() composerRecorder.assertSingle( MessageComposerEvent.SetMode( @@ -452,7 +452,7 @@ class MessagesPresenterTest { ) presenter.testWithLifecycleOwner { val initialState = awaitItem() - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Edit, aMessageEvent())) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.Edit, aMessageEvent())) awaitItem() composerRecorder.assertSingle( MessageComposerEvent.SetMode( @@ -474,7 +474,7 @@ class MessagesPresenterTest { val presenter = createMessagesPresenter(navigator = navigator) presenter.testWithLifecycleOwner { val initialState = awaitItem() - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.EditPoll, aMessageEvent(content = aTimelineItemPollContent()))) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.EditPoll, aMessageEvent(content = aTimelineItemPollContent()))) awaitItem() onEditPollClickLambda.assertions().isCalledOnce().with(value(AN_EVENT_ID)) } @@ -486,7 +486,7 @@ class MessagesPresenterTest { val presenter = createMessagesPresenter(timelineEventSink = timelineEventSink) presenter.testWithLifecycleOwner { val initialState = awaitItem() - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.EndPoll, aMessageEvent(content = aTimelineItemPollContent()))) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.EndPoll, aMessageEvent(content = aTimelineItemPollContent()))) delay(1) timelineEventSink.assertSingle(TimelineEvents.EndPoll(AN_EVENT_ID)) cancelAndIgnoreRemainingEvents() @@ -516,7 +516,7 @@ class MessagesPresenterTest { presenter.testWithLifecycleOwner { val initialState = awaitItem() val messageEvent = aMessageEvent() - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Redact, messageEvent)) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.Redact, messageEvent)) awaitItem() assert(redactEventLambda) .isCalledOnce() @@ -533,7 +533,7 @@ class MessagesPresenterTest { val presenter = createMessagesPresenter(navigator = navigator) presenter.testWithLifecycleOwner { val initialState = awaitItem() - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.ReportContent, aMessageEvent())) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.ReportContent, aMessageEvent())) assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None) onReportContentClickLambda.assertions().isCalledOnce().with(value(AN_EVENT_ID), value(A_USER_ID)) } @@ -548,7 +548,7 @@ class MessagesPresenterTest { val presenter = createMessagesPresenter(navigator = navigator) presenter.testWithLifecycleOwner { val initialState = awaitItem() - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.ViewSource, aMessageEvent())) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.ViewSource, aMessageEvent())) assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None) onShowEventDebugInfoClickLambda.assertions().isCalledOnce().with(value(AN_EVENT_ID), value(aTimelineItemDebugInfo())) } @@ -576,7 +576,7 @@ class MessagesPresenterTest { val focusedState = awaitItem() assertThat(focusedState.showReinvitePrompt).isTrue() // If it's dismissed then we stop showing the alert - initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Cancel)) + initialState.eventSink(MessagesEvent.InviteDialogDismissed(InviteDialogAction.Cancel)) skipItems(1) val dismissedState = awaitItem() assertThat(dismissedState.showReinvitePrompt).isFalse() @@ -648,7 +648,7 @@ class MessagesPresenterTest { val presenter = createMessagesPresenter(joinedRoom = room) presenter.testWithLifecycleOwner { val initialState = consumeItemsUntilTimeout().last() - initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Invite)) + initialState.eventSink(MessagesEvent.InviteDialogDismissed(InviteDialogAction.Invite)) skipItems(1) val loadingState = awaitItem() assertThat(loadingState.inviteProgress.isLoading()).isTrue() @@ -680,7 +680,7 @@ class MessagesPresenterTest { val presenter = createMessagesPresenter(joinedRoom = room) presenter.testWithLifecycleOwner { val initialState = consumeItemsUntilTimeout().last() - initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Invite)) + initialState.eventSink(MessagesEvent.InviteDialogDismissed(InviteDialogAction.Invite)) skipItems(1) val loadingState = consumeItemsUntilPredicate { state -> state.inviteProgress.isLoading() @@ -704,7 +704,7 @@ class MessagesPresenterTest { val presenter = createMessagesPresenter(joinedRoom = room) presenter.testWithLifecycleOwner { val initialState = consumeItemsUntilTimeout().last() - initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Invite)) + initialState.eventSink(MessagesEvent.InviteDialogDismissed(InviteDialogAction.Invite)) skipItems(1) val loadingState = awaitItem() assertThat(loadingState.inviteProgress.isLoading()).isTrue() @@ -733,7 +733,7 @@ class MessagesPresenterTest { val presenter = createMessagesPresenter(joinedRoom = room) presenter.testWithLifecycleOwner { val initialState = consumeItemsUntilTimeout().last() - initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Invite)) + initialState.eventSink(MessagesEvent.InviteDialogDismissed(InviteDialogAction.Invite)) val loadingState = consumeItemsUntilPredicate { state -> state.inviteProgress.isLoading() @@ -830,7 +830,7 @@ class MessagesPresenterTest { val poll = aMessageEvent( content = aTimelineItemPollContent() ) - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Reply, poll)) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.Reply, poll)) skipItems(1) composerRecorder.assertSingle( MessageComposerEvent.SetMode( @@ -868,11 +868,11 @@ class MessagesPresenterTest { val initialState = awaitItem() timeline.pinEventLambda = successPinEventLambda - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Pin, messageEvent)) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.Pin, messageEvent)) assert(successPinEventLambda).isCalledOnce().with(value(messageEvent.eventId)) timeline.pinEventLambda = failurePinEventLambda - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Pin, messageEvent)) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.Pin, messageEvent)) assert(failurePinEventLambda).isCalledOnce().with(value(messageEvent.eventId)) skipItems(1) assertThat(awaitItem().snackbarMessage).isNotNull() @@ -908,11 +908,11 @@ class MessagesPresenterTest { val initialState = awaitItem() timeline.unpinEventLambda = successUnpinEventLambda - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Unpin, messageEvent)) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.Unpin, messageEvent)) assert(successUnpinEventLambda).isCalledOnce().with(value(messageEvent.eventId)) timeline.unpinEventLambda = failureUnpinEventLambda - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Unpin, messageEvent)) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.Unpin, messageEvent)) assert(failureUnpinEventLambda).isCalledOnce().with(value(messageEvent.eventId)) skipItems(1) assertThat(awaitItem().snackbarMessage).isNotNull() @@ -936,7 +936,7 @@ class MessagesPresenterTest { ) presenter.testWithLifecycleOwner { val initialState = awaitItem() - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.EditCaption, messageEvent)) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.EditCaption, messageEvent)) awaitItem() composerRecorder.assertSingle( MessageComposerEvent.SetMode( @@ -962,7 +962,7 @@ class MessagesPresenterTest { ) presenter.testWithLifecycleOwner { val initialState = awaitItem() - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.AddCaption, messageEvent)) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.AddCaption, messageEvent)) awaitItem() composerRecorder.assertSingle( MessageComposerEvent.SetMode( @@ -1000,7 +1000,7 @@ class MessagesPresenterTest { presenter.testWithLifecycleOwner { skipItems(1) val initialState = awaitItem() - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.RemoveCaption, messageEvent)) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.RemoveCaption, messageEvent)) editCaptionLambda.assertions().isCalledOnce().with(value(AN_EVENT_ID.toEventOrTransactionId()), value(null), value(null)) } } @@ -1014,7 +1014,7 @@ class MessagesPresenterTest { presenter.testWithLifecycleOwner { skipItems(1) val initialState = awaitItem() - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.ViewInTimeline, messageEvent)) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.ViewInTimeline, messageEvent)) // No op! } } @@ -1108,7 +1108,7 @@ class MessagesPresenterTest { presenter.testWithLifecycleOwner { val initialState = awaitItem() initialState.eventSink( - MessagesEvents.HandleAction( + MessagesEvent.HandleAction( action = TimelineItemAction.ReplyInThread, event = aMessageEvent(threadInfo = TimelineItemThreadInfo.ThreadResponse(A_THREAD_ID)) ) @@ -1130,7 +1130,7 @@ class MessagesPresenterTest { presenter.testWithLifecycleOwner { val initialState = awaitItem() initialState.eventSink( - MessagesEvents.HandleAction( + MessagesEvent.HandleAction( action = TimelineItemAction.ReplyInThread, event = aMessageEvent( // The event id will be used as the thread id instead @@ -1155,7 +1155,7 @@ class MessagesPresenterTest { ) presenter.testWithLifecycleOwner { val initialState = awaitItem() - initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.ReplyInThread, aMessageEvent())) + initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.ReplyInThread, aMessageEvent())) awaitItem() composerRecorder.assertSingle( MessageComposerEvent.SetMode( @@ -1182,7 +1182,7 @@ class MessagesPresenterTest { ) presenter.testWithLifecycleOwner { val initialState = awaitItem() - initialState.eventSink(MessagesEvents.MarkAsFullyReadAndExit) + initialState.eventSink(MessagesEvent.MarkAsFullyReadAndExit) runCurrent() @@ -1206,7 +1206,7 @@ class MessagesPresenterTest { ) presenter.testWithLifecycleOwner { val initialState = awaitItem() - initialState.eventSink(MessagesEvents.MarkAsFullyReadAndExit) + initialState.eventSink(MessagesEvent.MarkAsFullyReadAndExit) runCurrent() 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 71d6176bc8..336a3e67c7 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 @@ -88,7 +88,7 @@ class MessagesViewTest { @Test fun `clicking on back invoke expected callback`() { - val eventsRecorder = EventsRecorder(expectEvents = false) + val eventsRecorder = EventsRecorder(expectEvents = false) val state = aMessagesState( eventSink = eventsRecorder ) @@ -103,7 +103,7 @@ class MessagesViewTest { @Test fun `clicking on room name invoke expected callback`() { - val eventsRecorder = EventsRecorder(expectEvents = false) + val eventsRecorder = EventsRecorder(expectEvents = false) val state = aMessagesState( eventSink = eventsRecorder ) @@ -118,7 +118,7 @@ class MessagesViewTest { @Test fun `clicking on join call invoke expected callback`() { - val eventsRecorder = EventsRecorder(expectEvents = false) + val eventsRecorder = EventsRecorder(expectEvents = false) val state = aMessagesState( eventSink = eventsRecorder ) @@ -134,7 +134,7 @@ class MessagesViewTest { @Test fun `clicking on an Event invoke expected callback`() { - val eventsRecorder = EventsRecorder(expectEvents = false) + val eventsRecorder = EventsRecorder(expectEvents = false) val state = aMessagesState( timelineState = aTimelineState( timelineItems = aTimelineItemList(aTimelineItemTextContent()), @@ -253,7 +253,7 @@ class MessagesViewTest { } private fun swipeTest(userHasPermissionToSendMessage: Boolean) { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val canBeRepliedEvent = aTimelineItemEvent(canBeRepliedTo = true) val cannotBeRepliedEvent = aTimelineItemEvent(canBeRepliedTo = false) val state = aMessagesState( @@ -273,7 +273,7 @@ class MessagesViewTest { onLast().performTouchInput { swipeRight(endX = 200f) } } if (userHasPermissionToSendMessage) { - eventsRecorder.assertSingle(MessagesEvents.HandleAction(TimelineItemAction.Reply, canBeRepliedEvent)) + eventsRecorder.assertSingle(MessagesEvent.HandleAction(TimelineItemAction.Reply, canBeRepliedEvent)) } else { eventsRecorder.assertEmpty() } @@ -281,7 +281,7 @@ class MessagesViewTest { @Test fun `clicking on send location invoke expected callback`() { - val eventsRecorder = EventsRecorder(expectEvents = false) + val eventsRecorder = EventsRecorder(expectEvents = false) val state = aMessagesState( composerState = aMessageComposerState( showAttachmentSourcePicker = true @@ -299,7 +299,7 @@ class MessagesViewTest { @Test fun `clicking on create poll invoke expected callback`() { - val eventsRecorder = EventsRecorder(expectEvents = false) + val eventsRecorder = EventsRecorder(expectEvents = false) val state = aMessagesState( composerState = aMessageComposerState( showAttachmentSourcePicker = true @@ -319,7 +319,7 @@ class MessagesViewTest { @Test @Config(qualifiers = "h1024dp") fun `clicking on the avatar of the sender of an Event emits the expected event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val state = aMessagesState( eventSink = eventsRecorder ) @@ -327,7 +327,7 @@ class MessagesViewTest { rule.setMessagesView(state = state) rule.onNodeWithTag(TestTags.timelineItemSenderAvatar.value, useUnmergedTree = true).performClick() eventsRecorder.assertSingle( - MessagesEvents.OnUserClicked( + MessagesEvent.OnUserClicked( MatrixUser( userId = timelineEvent.senderId, displayName = timelineEvent.senderProfile.getDisplayName(), @@ -340,13 +340,13 @@ class MessagesViewTest { @Test @Config(qualifiers = "h1024dp") fun `clicking on the display name of the sender of an Event emits expected event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val state = aMessagesState(eventSink = eventsRecorder) val timelineEvent = state.timelineState.timelineItems.filterIsInstance().first() rule.setMessagesView(state = state) rule.onNodeWithTag(TestTags.timelineItemSenderAvatar.value, useUnmergedTree = true).performClick() eventsRecorder.assertSingle( - MessagesEvents.OnUserClicked( + MessagesEvent.OnUserClicked( MatrixUser( userId = timelineEvent.senderId, displayName = timelineEvent.senderProfile.getDisplayName(), @@ -358,7 +358,7 @@ class MessagesViewTest { @Test fun `selecting a action on a message emits the expected Event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val state = aMessagesState( eventSink = eventsRecorder ) @@ -381,12 +381,12 @@ class MessagesViewTest { rule.clickOn(CommonStrings.action_edit) // Give time for the close animation to complete rule.mainClock.advanceTimeBy(milliseconds = 1_000) - eventsRecorder.assertSingle(MessagesEvents.HandleAction(TimelineItemAction.Edit, timelineItem)) + eventsRecorder.assertSingle(MessagesEvent.HandleAction(TimelineItemAction.Edit, timelineItem)) } @Test fun `clicking on a reaction emits the expected Event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val state = aMessagesState( timelineState = aTimelineState( timelineItems = aTimelineItemList(aTimelineItemTextContent()), @@ -401,7 +401,7 @@ class MessagesViewTest { text = "👍️", useUnmergedTree = true, ).onFirst().performClick() - eventsRecorder.assertSingle(MessagesEvents.ToggleReaction("👍️", timelineItem.eventOrTransactionId)) + eventsRecorder.assertSingle(MessagesEvent.ToggleReaction("👍️", timelineItem.eventOrTransactionId)) } @Test @@ -513,7 +513,7 @@ class MessagesViewTest { fun `clicking on a custom emoji emits the expected Events`() { val aUnicode = "🙈" val customReactionStateEventsRecorder = EventsRecorder() - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val state = aMessagesState( eventSink = eventsRecorder, ) @@ -547,7 +547,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.eventOrTransactionId)) + eventsRecorder.assertSingle(MessagesEvent.ToggleReaction(aUnicode, timelineItem.eventOrTransactionId)) } @Test @@ -589,7 +589,7 @@ class MessagesViewTest { @Test fun `no banner shown when there is no successor room`() { - val eventsRecorder = EventsRecorder(expectEvents = false) + val eventsRecorder = EventsRecorder(expectEvents = false) val state = aMessagesState( successorRoom = null, eventSink = eventsRecorder From 6bb979a83313f7a42df1c9ba0bcd6ee0a5a3c2ec Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 27 Jan 2026 09:45:10 +0100 Subject: [PATCH 06/18] TimelineEvents -> TimelineEvent --- .../features/messages/impl/MessagesNode.kt | 10 ++-- .../messages/impl/MessagesPresenter.kt | 4 +- .../features/messages/impl/MessagesView.kt | 8 +-- .../impl/threads/ThreadedMessagesNode.kt | 10 ++-- .../{TimelineEvents.kt => TimelineEvent.kt} | 24 ++++----- .../impl/timeline/TimelinePresenter.kt | 30 +++++------ .../messages/impl/timeline/TimelineState.kt | 2 +- .../impl/timeline/TimelineStateProvider.kt | 2 +- .../messages/impl/timeline/TimelineView.kt | 14 ++--- .../components/TimelineEventTimestampView.kt | 9 ++-- .../components/TimelineItemEventRow.kt | 12 ++--- .../TimelineItemGroupedEventsRow.kt | 6 +-- .../timeline/components/TimelineItemRow.kt | 4 +- .../components/TimelineItemStateEventRow.kt | 4 +- .../components/TimelineItemVirtualRow.kt | 8 +-- .../event/TimelineItemEventContentView.kt | 4 +- .../components/event/TimelineItemPollView.kt | 10 ++-- .../messages/impl/MessagesPresenterTest.kt | 8 +-- .../messages/impl/MessagesViewTest.kt | 14 ++--- .../impl/timeline/TimelinePresenterTest.kt | 51 +++++++++---------- .../impl/timeline/TimelineViewTest.kt | 28 +++++----- .../event/TimelineItemPollViewTest.kt | 14 ++--- 22 files changed, 137 insertions(+), 139 deletions(-) rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/{TimelineEvents.kt => TimelineEvent.kt} (77%) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt index b2507e6870..e892f80c7d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt @@ -36,7 +36,7 @@ import io.element.android.features.messages.impl.attachments.Attachment import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvent import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter import io.element.android.features.messages.impl.timeline.TimelineController -import io.element.android.features.messages.impl.timeline.TimelineEvents +import io.element.android.features.messages.impl.timeline.TimelineEvent import io.element.android.features.messages.impl.timeline.TimelinePresenter import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPresenterFactories import io.element.android.features.messages.impl.timeline.di.TimelineItemPresenterFactories @@ -151,7 +151,7 @@ class MessagesNode( activity: Activity, darkTheme: Boolean, url: String, - eventSink: (TimelineEvents) -> Unit, + eventSink: (TimelineEvent) -> Unit, customTab: Boolean ) { when (val permalink = permalinkParser.parse(url)) { @@ -178,12 +178,12 @@ class MessagesNode( private fun handleRoomLinkClick( roomLink: PermalinkData.RoomLink, - eventSink: (TimelineEvents) -> Unit, + eventSink: (TimelineEvent) -> Unit, ) { if (room.matches(roomLink.roomIdOrAlias)) { val eventId = roomLink.eventId if (eventId != null) { - eventSink(TimelineEvents.FocusOnEvent(eventId)) + eventSink(TimelineEvent.FocusOnEvent(eventId)) } else { // Click on the same room, ignore displaySameRoomToast() @@ -305,7 +305,7 @@ class MessagesNode( } LaunchedEffect(focusedEventId) { if (focusedEventId != null) { - state.timelineState.eventSink(TimelineEvents.FocusOnEvent(focusedEventId!!)) + state.timelineState.eventSink(TimelineEvent.FocusOnEvent(focusedEventId!!)) focusedEventId = null } } 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 5f2413c9a1..c1f8effd64 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 @@ -37,7 +37,7 @@ import io.element.android.features.messages.impl.messagecomposer.MessageComposer import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerState import io.element.android.features.messages.impl.timeline.MarkAsFullyRead import io.element.android.features.messages.impl.timeline.TimelineController -import io.element.android.features.messages.impl.timeline.TimelineEvents +import io.element.android.features.messages.impl.timeline.TimelineEvent import io.element.android.features.messages.impl.timeline.TimelineState import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionState import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryState @@ -527,7 +527,7 @@ class MessagesPresenter( event: TimelineItem.Event, timelineState: TimelineState, ) { - event.eventId?.let { timelineState.eventSink(TimelineEvents.EndPoll(it)) } + event.eventId?.let { timelineState.eventSink(TimelineEvent.EndPoll(it)) } } private suspend fun handleCopyLink(event: TimelineItem.Event) { 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 4dfbe74fda..2d9319c262 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 @@ -68,7 +68,7 @@ import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBan import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerView import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerViewDefaults import io.element.android.features.messages.impl.timeline.FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS -import io.element.android.features.messages.impl.timeline.TimelineEvents +import io.element.android.features.messages.impl.timeline.TimelineEvent import io.element.android.features.messages.impl.timeline.TimelineView import io.element.android.features.messages.impl.timeline.aGroupedEvents import io.element.android.features.messages.impl.timeline.aTimelineItemDaySeparator @@ -301,7 +301,7 @@ fun MessagesView( state = state, onLinkClick = { url, customTab -> onLinkClick(url, customTab) }, onRoomSuccessorClick = { roomId -> - state.timelineState.eventSink(TimelineEvents.NavigateToPredecessorOrSuccessorRoom(roomId = roomId)) + state.timelineState.eventSink(TimelineEvent.NavigateToPredecessorOrSuccessorRoom(roomId = roomId)) }, ) }, @@ -371,7 +371,7 @@ fun MessagesView( }, onEmojiReactionClick = ::onEmojiReactionClick, onVerifiedUserSendFailureClick = { event -> - state.timelineState.eventSink(TimelineEvents.ComputeVerifiedUserSendFailure(event)) + state.timelineState.eventSink(TimelineEvent.ComputeVerifiedUserSendFailure(event)) }, ) @@ -489,7 +489,7 @@ private fun MessagesViewContent( ) { fun focusOnPinnedEvent(eventId: EventId) { state.timelineState.eventSink( - TimelineEvents.FocusOnEvent(eventId = eventId, debounce = FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS.milliseconds) + TimelineEvent.FocusOnEvent(eventId = eventId, debounce = FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS.milliseconds) ) } PinnedMessagesBannerView( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt index 10922ca5e7..03953e0e29 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt @@ -36,7 +36,7 @@ import io.element.android.features.messages.impl.attachments.Attachment import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvent import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter import io.element.android.features.messages.impl.timeline.TimelineController -import io.element.android.features.messages.impl.timeline.TimelineEvents +import io.element.android.features.messages.impl.timeline.TimelineEvent import io.element.android.features.messages.impl.timeline.TimelinePresenter import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPresenterFactories import io.element.android.features.messages.impl.timeline.di.TimelineItemPresenterFactories @@ -148,7 +148,7 @@ class ThreadedMessagesNode( activity: Activity, darkTheme: Boolean, url: String, - eventSink: (TimelineEvents) -> Unit, + eventSink: (TimelineEvent) -> Unit, customTab: Boolean ) { when (val permalink = permalinkParser.parse(url)) { @@ -175,12 +175,12 @@ class ThreadedMessagesNode( private fun handleRoomLinkClick( roomLink: PermalinkData.RoomLink, - eventSink: (TimelineEvents) -> Unit, + eventSink: (TimelineEvent) -> Unit, ) { if (room.matches(roomLink.roomIdOrAlias)) { val eventId = roomLink.eventId if (eventId != null) { - eventSink(TimelineEvents.FocusOnEvent(eventId)) + eventSink(TimelineEvent.FocusOnEvent(eventId)) } else { // Click on the same room, navigate up // Note that it can not be enough to go back to the room if the thread has been opened @@ -277,7 +277,7 @@ class ThreadedMessagesNode( } LaunchedEffect(Unit) { focusedEventId?.also { eventId -> - state.timelineState.eventSink(TimelineEvents.FocusOnEvent(eventId)) + state.timelineState.eventSink(TimelineEvent.FocusOnEvent(eventId)) } // Reset the focused event id to null to avoid refocusing when restoring node. focusedEventId = null diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvent.kt similarity index 77% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvents.kt rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvent.kt index c7fe37b531..b3fc841ba9 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvent.kt @@ -16,19 +16,19 @@ import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.timeline.Timeline import kotlin.time.Duration -sealed interface TimelineEvents { - data class OnScrollFinished(val firstIndex: Int) : TimelineEvents - data class FocusOnEvent(val eventId: EventId, val debounce: Duration = Duration.ZERO) : TimelineEvents - data object ClearFocusRequestState : TimelineEvents - data object OnFocusEventRender : TimelineEvents - data object JumpToLive : TimelineEvents +sealed interface TimelineEvent { + data class OnScrollFinished(val firstIndex: Int) : TimelineEvent + data class FocusOnEvent(val eventId: EventId, val debounce: Duration = Duration.ZERO) : TimelineEvent + data object ClearFocusRequestState : TimelineEvent + data object OnFocusEventRender : TimelineEvent + data object JumpToLive : TimelineEvent - data object HideShieldDialog : TimelineEvents + data object HideShieldDialog : TimelineEvent /** * Events coming from a timeline item. */ - sealed interface EventFromTimelineItem : TimelineEvents + sealed interface EventFromTimelineItem : TimelineEvent data class ComputeVerifiedUserSendFailure(val event: TimelineItem.Event) : EventFromTimelineItem data class ShowShieldDialog(val messageShieldData: MessageShieldData) : EventFromTimelineItem @@ -43,18 +43,18 @@ sealed interface TimelineEvents { /** * Events coming from a poll item. */ - sealed interface TimelineItemPollEvents : EventFromTimelineItem + sealed interface TimelineItemPollEvent : EventFromTimelineItem data class SelectPollAnswer( val pollStartId: EventId, val answerId: String - ) : TimelineItemPollEvents + ) : TimelineItemPollEvent data class EndPoll( val pollStartId: EventId, - ) : TimelineItemPollEvents + ) : TimelineItemPollEvent data class EditPoll( val pollStartId: EventId, - ) : TimelineItemPollEvents + ) : TimelineItemPollEvent } 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 8d1612ff1e..df704287a3 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 @@ -150,9 +150,9 @@ class TimelinePresenter( value = featureFlagService.isFeatureEnabled(FeatureFlags.Threads) } - fun handleEvent(event: TimelineEvents) { + fun handleEvent(event: TimelineEvent) { when (event) { - is TimelineEvents.LoadMore -> { + is TimelineEvent.LoadMore -> { if (event.direction == Timeline.PaginationDirection.FORWARDS && timelineMode is Timeline.Mode.Thread) { // Do not paginate forwards in thread mode, as it's not supported return @@ -161,7 +161,7 @@ class TimelinePresenter( timelineController.paginate(direction = event.direction) } } - is TimelineEvents.OnScrollFinished -> { + is TimelineEvent.OnScrollFinished -> { if (isLive) { if (event.firstIndex == 0) { newEventState.value = NewEventState.None @@ -177,7 +177,7 @@ class TimelinePresenter( newEventState.value = NewEventState.None } } - is TimelineEvents.SelectPollAnswer -> sessionCoroutineScope.launch { + is TimelineEvent.SelectPollAnswer -> sessionCoroutineScope.launch { timelineController.invokeOnCurrentTimeline { sendPollResponseAction.execute( timeline = this, @@ -186,7 +186,7 @@ class TimelinePresenter( ) } } - is TimelineEvents.EndPoll -> sessionCoroutineScope.launch { + is TimelineEvent.EndPoll -> sessionCoroutineScope.launch { timelineController.invokeOnCurrentTimeline { endPollAction.execute( timeline = this, @@ -194,38 +194,38 @@ class TimelinePresenter( ) } } - is TimelineEvents.EditPoll -> { + is TimelineEvent.EditPoll -> { navigator.navigateToEditPoll(event.pollStartId) } - is TimelineEvents.FocusOnEvent -> sessionCoroutineScope.launch { + is TimelineEvent.FocusOnEvent -> sessionCoroutineScope.launch { focusRequestState.value = FocusRequestState.Requested(event.eventId, event.debounce) delay(event.debounce) Timber.tag(tag).d("Started focus on ${event.eventId}") focusOnEvent(event.eventId, focusRequestState) }.start() - is TimelineEvents.OnFocusEventRender -> { + is TimelineEvent.OnFocusEventRender -> { // If there was a pending 'notification tap opens timeline' transaction, finish it now we're focused in the required event analyticsService.finishLongRunningTransaction(NotificationToMessage) focusRequestState.value = focusRequestState.value.onFocusEventRender() } - is TimelineEvents.ClearFocusRequestState -> { + is TimelineEvent.ClearFocusRequestState -> { focusRequestState.value = FocusRequestState.None } - is TimelineEvents.JumpToLive -> { + is TimelineEvent.JumpToLive -> { timelineController.focusOnLive() } - TimelineEvents.HideShieldDialog -> messageShieldDialogData.value = null - is TimelineEvents.ShowShieldDialog -> messageShieldDialogData.value = event.messageShieldData - is TimelineEvents.ComputeVerifiedUserSendFailure -> { + TimelineEvent.HideShieldDialog -> messageShieldDialogData.value = null + is TimelineEvent.ShowShieldDialog -> messageShieldDialogData.value = event.messageShieldData + is TimelineEvent.ComputeVerifiedUserSendFailure -> { resolveVerifiedUserSendFailureState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(event.event)) } - is TimelineEvents.NavigateToPredecessorOrSuccessorRoom -> { + is TimelineEvent.NavigateToPredecessorOrSuccessorRoom -> { // Navigate to the predecessor or successor room val serverNames = calculateServerNamesForRoom(room) navigator.navigateToRoom(event.roomId, null, serverNames) } - is TimelineEvents.OpenThread -> { + is TimelineEvent.OpenThread -> { navigator.navigateToThread( threadRootId = event.threadRootEventId, focusedEventId = event.focusedEvent, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt index a53960f63b..03f0083856 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt @@ -34,7 +34,7 @@ data class TimelineState( val messageShieldDialogData: MessageShieldData?, val resolveVerifiedUserSendFailureState: ResolveVerifiedUserSendFailureState, val displayThreadSummaries: Boolean, - val eventSink: (TimelineEvents) -> Unit, + val eventSink: (TimelineEvent) -> Unit, ) { private val lastTimelineEvent = timelineItems.firstOrNull { it is TimelineItem.Event } as? TimelineItem.Event val hasAnyEvent = lastTimelineEvent != null 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 e2ed3d4307..adfaa93cce 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 @@ -56,7 +56,7 @@ fun aTimelineState( messageShield: MessageShield? = null, resolveVerifiedUserSendFailureState: ResolveVerifiedUserSendFailureState = aResolveVerifiedUserSendFailureState(), displayThreadSummaries: Boolean = false, - eventSink: (TimelineEvents) -> Unit = {}, + eventSink: (TimelineEvent) -> Unit = {}, ): TimelineState { val focusedEventId = timelineItems.filterIsInstance().getOrNull(focusedEventIndex)?.eventId val focusRequestState = if (focusedEventId != null) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index f8d488c0ba..e44a6e170c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -107,19 +107,19 @@ fun TimelineView( nestedScrollConnection: NestedScrollConnection = rememberNestedScrollInteropConnection(), ) { fun clearFocusRequestState() { - state.eventSink(TimelineEvents.ClearFocusRequestState) + state.eventSink(TimelineEvent.ClearFocusRequestState) } fun onScrollFinishAt(firstVisibleIndex: Int) { - state.eventSink(TimelineEvents.OnScrollFinished(firstVisibleIndex)) + state.eventSink(TimelineEvent.OnScrollFinished(firstVisibleIndex)) } fun onFocusEventRender() { - state.eventSink(TimelineEvents.OnFocusEventRender) + state.eventSink(TimelineEvent.OnFocusEventRender) } fun onJumpToLive() { - state.eventSink(TimelineEvents.JumpToLive) + state.eventSink(TimelineEvent.JumpToLive) } val context = LocalContext.current @@ -129,7 +129,7 @@ fun TimelineView( val useReverseLayout = !isTalkbackActive() fun inReplyToClick(eventId: EventId) { - state.eventSink(TimelineEvents.FocusOnEvent(eventId)) + state.eventSink(TimelineEvent.FocusOnEvent(eventId)) } fun onLinkLongClick(link: Link) { @@ -143,7 +143,7 @@ fun TimelineView( } fun prefetchMoreItems() { - state.eventSink(TimelineEvents.LoadMore(Timeline.PaginationDirection.BACKWARDS)) + state.eventSink(TimelineEvent.LoadMore(Timeline.PaginationDirection.BACKWARDS)) } // Animate alpha when timeline is first displayed, to avoid flashes or glitching when viewing rooms @@ -223,7 +223,7 @@ private fun MessageShieldDialog(state: TimelineState) { val messageShield = state.messageShieldDialogData ?: return AlertDialog( content = messageShield.toText(), - onDismiss = { state.eventSink.invoke(TimelineEvents.HideShieldDialog) }, + onDismiss = { state.eventSink.invoke(TimelineEvent.HideShieldDialog) }, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt index 40369595ea..a6ace1cadd 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt @@ -23,7 +23,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons -import io.element.android.features.messages.impl.timeline.TimelineEvents +import io.element.android.features.messages.impl.timeline.TimelineEvent import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.isEdited import io.element.android.features.messages.impl.timeline.model.event.isRedacted @@ -33,13 +33,12 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState -import io.element.android.libraries.matrix.api.timeline.item.event.isCritical import io.element.android.libraries.ui.strings.CommonStrings @Composable fun TimelineEventTimestampView( event: TimelineItem.Event, - eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, modifier: Modifier = Modifier, ) { val formattedTime = event.sentTime @@ -80,7 +79,7 @@ fun TimelineEventTimestampView( enabled = isVerifiedUserSendFailure, onClickLabel = stringResource(CommonStrings.action_open_context_menu), ) { - eventSink(TimelineEvents.ComputeVerifiedUserSendFailure(event)) + eventSink(TimelineEvent.ComputeVerifiedUserSendFailure(event)) } ) } @@ -96,7 +95,7 @@ fun TimelineEventTimestampView( .clickable( onClickLabel = stringResource(CommonStrings.a11y_view_details), ) { - eventSink(TimelineEvents.ShowShieldDialog(shield)) + eventSink(TimelineEvent.ShowShieldDialog(shield)) }, tint = shield.toIconColor(), ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index 1f40e94a9b..811ba83759 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -57,7 +57,7 @@ import androidx.constraintlayout.compose.ConstrainScope import androidx.constraintlayout.compose.ConstraintLayout import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons -import io.element.android.features.messages.impl.timeline.TimelineEvents +import io.element.android.features.messages.impl.timeline.TimelineEvent import io.element.android.features.messages.impl.timeline.TimelineRoomInfo import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.components.event.TimelineItemEventContentView @@ -153,7 +153,7 @@ fun TimelineItemEventRow( onMoreReactionsClick: (eventId: TimelineItem.Event) -> Unit, onReadReceiptClick: (event: TimelineItem.Event) -> Unit, onSwipeToReply: () -> Unit, - eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, modifier: Modifier = Modifier, eventContentView: @Composable (Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit = { contentModifier, onContentLayoutChange -> // Only pass down a custom clickable lambda if the content can be clicked separately @@ -278,7 +278,7 @@ fun TimelineItemEventRow( isOutgoing = event.isMine, onClick = { event.eventId?.let { - eventSink(TimelineEvents.OpenThread(it.toThreadId(), null)) + eventSink(TimelineEvent.OpenThread(it.toThreadId(), null)) } } ) @@ -410,7 +410,7 @@ private fun TimelineItemEventRowContent( onReactionClick: (emoji: String) -> Unit, onReactionLongClick: (emoji: String) -> Unit, onMoreReactionsClick: (event: TimelineItem.Event) -> Unit, - eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, modifier: Modifier = Modifier, eventContentView: @Composable (Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit, ) { @@ -585,7 +585,7 @@ private fun MessageEventBubbleContent( timelineProtectionState: TimelineProtectionState, onMessageLongClick: () -> Unit, inReplyToClick: () -> Unit, - eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, @SuppressLint("ModifierParameter") // need to rename this modifier to prevent linter false positives @Suppress("ModifierNaming") @@ -623,7 +623,7 @@ private fun MessageEventBubbleContent( @Composable fun WithTimestampLayout( timestampPosition: TimestampPosition, - eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, modifier: Modifier = Modifier, canShrinkContent: Boolean = false, content: @Composable (onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit) -> Unit, 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 66f2459491..9f5842afd4 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 @@ -16,7 +16,7 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.res.pluralStringResource import io.element.android.features.messages.impl.R -import io.element.android.features.messages.impl.timeline.TimelineEvents +import io.element.android.features.messages.impl.timeline.TimelineEvent import io.element.android.features.messages.impl.timeline.TimelineRoomInfo import io.element.android.features.messages.impl.timeline.aGroupedEvents import io.element.android.features.messages.impl.timeline.aTimelineRoomInfo @@ -57,7 +57,7 @@ fun TimelineItemGroupedEventsRow( onReactionLongClick: (key: String, TimelineItem.Event) -> Unit, onMoreReactionsClick: (TimelineItem.Event) -> Unit, onReadReceiptClick: (TimelineItem.Event) -> Unit, - eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, modifier: Modifier = Modifier, eventContentView: @Composable (TimelineItem.Event, Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit = { event, contentModifier, onContentLayoutChange -> @@ -130,7 +130,7 @@ private fun TimelineItemGroupedEventsRowContent( onReactionLongClick: (key: String, TimelineItem.Event) -> Unit, onMoreReactionsClick: (TimelineItem.Event) -> Unit, onReadReceiptClick: (TimelineItem.Event) -> Unit, - eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, modifier: Modifier = Modifier, eventContentView: @Composable (TimelineItem.Event, Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit = { event, contentModifier, onContentLayoutChange -> diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt index 4a0a6f70b8..93882e8436 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt @@ -26,7 +26,7 @@ import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme -import io.element.android.features.messages.impl.timeline.TimelineEvents +import io.element.android.features.messages.impl.timeline.TimelineEvent import io.element.android.features.messages.impl.timeline.TimelineRoomInfo import io.element.android.features.messages.impl.timeline.components.event.TimelineItemEventContentView import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayoutData @@ -73,7 +73,7 @@ internal fun TimelineItemRow( onReadReceiptClick: (TimelineItem.Event) -> Unit, onSwipeToReply: (TimelineItem.Event) -> Unit, onJoinCallClick: () -> Unit, - eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, modifier: Modifier = Modifier, eventContentView: @Composable (TimelineItem.Event, Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit = { event, contentModifier, onContentLayoutChange -> diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemStateEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemStateEventRow.kt index e796e93311..4c6f627af0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemStateEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemStateEventRow.kt @@ -21,7 +21,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex -import io.element.android.features.messages.impl.timeline.TimelineEvents +import io.element.android.features.messages.impl.timeline.TimelineEvent import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.components.event.TimelineItemEventContentView import io.element.android.features.messages.impl.timeline.components.receipt.ReadReceiptViewState @@ -44,7 +44,7 @@ fun TimelineItemStateEventRow( onClick: () -> Unit, onLongClick: () -> Unit, onReadReceiptsClick: (event: TimelineItem.Event) -> Unit, - eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, modifier: Modifier = Modifier ) { val interactionSource = remember { MutableInteractionSource() } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemVirtualRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemVirtualRow.kt index be94512c2c..a7685314f9 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemVirtualRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemVirtualRow.kt @@ -15,7 +15,7 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Modifier -import io.element.android.features.messages.impl.timeline.TimelineEvents +import io.element.android.features.messages.impl.timeline.TimelineEvent import io.element.android.features.messages.impl.timeline.TimelineRoomInfo import io.element.android.features.messages.impl.timeline.components.virtual.TimelineItemDaySeparatorView import io.element.android.features.messages.impl.timeline.components.virtual.TimelineItemReadMarkerView @@ -35,7 +35,7 @@ import timber.log.Timber fun TimelineItemVirtualRow( virtual: TimelineItem.Virtual, timelineRoomInfo: TimelineRoomInfo, - eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, modifier: Modifier = Modifier ) { Box(modifier = modifier) { @@ -48,7 +48,7 @@ fun TimelineItemVirtualRow( roomName = timelineRoomInfo.name, isDm = timelineRoomInfo.isDm, onPredecessorRoomClick = { roomId -> - eventSink(TimelineEvents.NavigateToPredecessorOrSuccessorRoom(roomId)) + eventSink(TimelineEvent.NavigateToPredecessorOrSuccessorRoom(roomId)) }, ) } @@ -57,7 +57,7 @@ fun TimelineItemVirtualRow( val latestEventSink by rememberUpdatedState(eventSink) LaunchedEffect(virtual.model.timestamp) { Timber.d("Pagination triggered by load more indicator") - latestEventSink(TimelineEvents.LoadMore(virtual.model.direction)) + latestEventSink(TimelineEvent.LoadMore(virtual.model.direction)) } } // Empty model trick to avoid timeline jumping during forward pagination. diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt index 73cd1ad8b8..dcd53e3fa2 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt @@ -10,7 +10,7 @@ package io.element.android.features.messages.impl.timeline.components.event import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import io.element.android.features.messages.impl.timeline.TimelineEvents +import io.element.android.features.messages.impl.timeline.TimelineEvent import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayoutData import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPresenterFactories import io.element.android.features.messages.impl.timeline.di.rememberPresenter @@ -43,7 +43,7 @@ fun TimelineItemEventContentView( onShowContentClick: () -> Unit, onLinkClick: (Link) -> Unit, onLinkLongClick: (Link) -> Unit, - eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, modifier: Modifier = Modifier, onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit = {}, ) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemPollView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemPollView.kt index ba72c067f0..e956a99b45 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemPollView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemPollView.kt @@ -11,7 +11,7 @@ package io.element.android.features.messages.impl.timeline.components.event import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.PreviewParameter -import io.element.android.features.messages.impl.timeline.TimelineEvents +import io.element.android.features.messages.impl.timeline.TimelineEvent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContentProvider import io.element.android.features.poll.api.pollcontent.PollContentView @@ -23,19 +23,19 @@ import kotlinx.collections.immutable.toImmutableList @Composable fun TimelineItemPollView( content: TimelineItemPollContent, - eventSink: (TimelineEvents.TimelineItemPollEvents) -> Unit, + eventSink: (TimelineEvent.TimelineItemPollEvent) -> Unit, modifier: Modifier = Modifier, ) { fun onSelectAnswer(pollStartId: EventId, answerId: String) { - eventSink(TimelineEvents.SelectPollAnswer(pollStartId, answerId)) + eventSink(TimelineEvent.SelectPollAnswer(pollStartId, answerId)) } fun onEndPoll(pollStartId: EventId) { - eventSink(TimelineEvents.EndPoll(pollStartId)) + eventSink(TimelineEvent.EndPoll(pollStartId)) } fun onEditPoll(pollStartId: EventId) { - eventSink(TimelineEvents.EditPoll(pollStartId)) + eventSink(TimelineEvent.EditPoll(pollStartId)) } PollContentView( 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 3afe719798..15331f2ba5 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 @@ -28,7 +28,7 @@ import io.element.android.features.messages.impl.pinned.banner.aLoadedPinnedMess import io.element.android.features.messages.impl.timeline.FakeMarkAsFullyRead import io.element.android.features.messages.impl.timeline.MarkAsFullyRead import io.element.android.features.messages.impl.timeline.TimelineController -import io.element.android.features.messages.impl.timeline.TimelineEvents +import io.element.android.features.messages.impl.timeline.TimelineEvent import io.element.android.features.messages.impl.timeline.aTimelineState import io.element.android.features.messages.impl.timeline.model.TimelineItemThreadInfo import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent @@ -482,13 +482,13 @@ class MessagesPresenterTest { @Test fun `present - handle action end poll`() = runTest { - val timelineEventSink = EventsRecorder() + val timelineEventSink = EventsRecorder() val presenter = createMessagesPresenter(timelineEventSink = timelineEventSink) presenter.testWithLifecycleOwner { val initialState = awaitItem() initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.EndPoll, aMessageEvent(content = aTimelineItemPollContent()))) delay(1) - timelineEventSink.assertSingle(TimelineEvents.EndPoll(AN_EVENT_ID)) + timelineEventSink.assertSingle(TimelineEvent.EndPoll(AN_EVENT_ID)) cancelAndIgnoreRemainingEvents() } } @@ -1263,7 +1263,7 @@ class MessagesPresenterTest { navigator: FakeMessagesNavigator = FakeMessagesNavigator(), clipboardHelper: FakeClipboardHelper = FakeClipboardHelper(), analyticsService: FakeAnalyticsService = FakeAnalyticsService(), - timelineEventSink: (TimelineEvents) -> Unit = {}, + timelineEventSink: (TimelineEvent) -> Unit = {}, permalinkParser: PermalinkParser = FakePermalinkParser(), messageComposerPresenter: Presenter = Presenter { aMessageComposerState( 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 336a3e67c7..ee272ac6f3 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 @@ -40,7 +40,7 @@ import io.element.android.features.messages.impl.messagecomposer.aMessageCompose import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerItem import io.element.android.features.messages.impl.pinned.banner.aLoadedPinnedMessagesBannerState import io.element.android.features.messages.impl.timeline.FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS -import io.element.android.features.messages.impl.timeline.TimelineEvents +import io.element.android.features.messages.impl.timeline.TimelineEvent import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.aTimelineItemList import io.element.android.features.messages.impl.timeline.aTimelineItemReadReceipts @@ -483,7 +483,7 @@ class MessagesViewTest { @Test fun `clicking on verified user send failure from action list emits the expected Event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val state = aMessagesState() val timelineItem = state.timelineState.timelineItems.first() as TimelineItem.Event val stateWithActionListState = state.copy( @@ -506,7 +506,7 @@ class MessagesViewTest { rule.onNodeWithText(verifiedUserSendFailure).performClick() // Give time for the close animation to complete rule.mainClock.advanceTimeBy(milliseconds = 1_000) - eventsRecorder.assertSingle(TimelineEvents.ComputeVerifiedUserSendFailure(timelineItem)) + eventsRecorder.assertSingle(TimelineEvent.ComputeVerifiedUserSendFailure(timelineItem)) } @Test @@ -552,7 +552,7 @@ class MessagesViewTest { @Test fun `clicking on pinned messages banner emits the expected Event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val state = aMessagesState( timelineState = aTimelineState(eventSink = eventsRecorder), pinnedMessagesBannerState = aLoadedPinnedMessagesBannerState( @@ -566,12 +566,12 @@ class MessagesViewTest { ) rule.setMessagesView(state = state) rule.onNodeWithText("This is a pinned message").performClick() - eventsRecorder.assertSingle(TimelineEvents.FocusOnEvent(AN_EVENT_ID, debounce = FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS.milliseconds)) + eventsRecorder.assertSingle(TimelineEvent.FocusOnEvent(AN_EVENT_ID, debounce = FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS.milliseconds)) } @Test fun `clicking on successor room button emits expected event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val successorRoomId = RoomId("!successor:server.org") val state = aMessagesState( successorRoom = SuccessorRoom( @@ -584,7 +584,7 @@ class MessagesViewTest { val text = rule.activity.getString(R.string.screen_room_timeline_tombstoned_room_action) // The bottomsheet subcompose seems to make the node to appear twice rule.onAllNodesWithText(text).onFirst().performClick() - eventsRecorder.assertSingle(TimelineEvents.NavigateToPredecessorOrSuccessorRoom(successorRoomId)) + eventsRecorder.assertSingle(TimelineEvent.NavigateToPredecessorOrSuccessorRoom(successorRoomId)) } @Test 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 529e7fcdbe..194694714b 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 @@ -9,7 +9,6 @@ package io.element.android.features.messages.impl.timeline import app.cash.turbine.ReceiveTurbine -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.impl.FakeMessagesNavigator import io.element.android.features.messages.impl.crypto.sendfailure.resolve.aResolveVerifiedUserSendFailureState @@ -120,8 +119,8 @@ class TimelinePresenterTest { val presenter = createTimelinePresenter(timeline = timeline) presenter.test { val initialState = awaitItem() - initialState.eventSink.invoke(TimelineEvents.LoadMore(Timeline.PaginationDirection.BACKWARDS)) - initialState.eventSink.invoke(TimelineEvents.LoadMore(Timeline.PaginationDirection.FORWARDS)) + initialState.eventSink.invoke(TimelineEvent.LoadMore(Timeline.PaginationDirection.BACKWARDS)) + initialState.eventSink.invoke(TimelineEvent.LoadMore(Timeline.PaginationDirection.FORWARDS)) assert(paginateLambda) .isCalledExactly(2) .withSequence( @@ -173,7 +172,7 @@ class TimelinePresenterTest { ) presenter.test { val initialState = awaitFirstItem() - initialState.eventSink.invoke(TimelineEvents.OnScrollFinished(0)) + initialState.eventSink.invoke(TimelineEvent.OnScrollFinished(0)) runCurrent() assert(markAsReadResult) .isCalledOnce() @@ -207,7 +206,7 @@ class TimelinePresenterTest { presenter.test { skipItems(1) awaitItem().run { - eventSink.invoke(TimelineEvents.OnScrollFinished(1)) + eventSink.invoke(TimelineEvent.OnScrollFinished(1)) } advanceUntilIdle() assert(sendReadReceiptsLambda) @@ -246,8 +245,8 @@ class TimelinePresenterTest { presenter.test { skipItems(1) awaitItem().run { - eventSink.invoke(TimelineEvents.OnScrollFinished(0)) - eventSink.invoke(TimelineEvents.OnScrollFinished(1)) + eventSink.invoke(TimelineEvent.OnScrollFinished(0)) + eventSink.invoke(TimelineEvent.OnScrollFinished(1)) } advanceUntilIdle() assert(sendReadReceiptsLambda) @@ -282,8 +281,8 @@ class TimelinePresenterTest { presenter.test { skipItems(1) awaitItem().run { - eventSink.invoke(TimelineEvents.OnScrollFinished(1)) - eventSink.invoke(TimelineEvents.OnScrollFinished(1)) + eventSink.invoke(TimelineEvent.OnScrollFinished(1)) + eventSink.invoke(TimelineEvent.OnScrollFinished(1)) } advanceUntilIdle() cancelAndIgnoreRemainingEvents() @@ -310,7 +309,7 @@ class TimelinePresenterTest { presenter.test { skipItems(1) val initialState = awaitFirstItem() - initialState.eventSink.invoke(TimelineEvents.OnScrollFinished(1)) + initialState.eventSink.invoke(TimelineEvent.OnScrollFinished(1)) cancelAndIgnoreRemainingEvents() assert(sendReadReceiptsLambda).isNeverCalled() } @@ -349,7 +348,7 @@ class TimelinePresenterTest { consumeItemsUntilPredicate { it.timelineItems.size == 3 } // Scroll to bottom to clear previous FromMe - initialState.eventSink.invoke(TimelineEvents.OnScrollFinished(0)) + initialState.eventSink.invoke(TimelineEvent.OnScrollFinished(0)) awaitLastSequentialItem().also { state -> assertThat(state.newEventState).isEqualTo(NewEventState.None) } @@ -429,7 +428,7 @@ class TimelinePresenterTest { ) presenter.test { val initialState = awaitFirstItem() - initialState.eventSink.invoke(TimelineEvents.SelectPollAnswer(AN_EVENT_ID, "anAnswerId")) + initialState.eventSink.invoke(TimelineEvent.SelectPollAnswer(AN_EVENT_ID, "anAnswerId")) } delay(1) sendPollResponseAction.verifyExecutionCount(1) @@ -443,7 +442,7 @@ class TimelinePresenterTest { ) presenter.test { val initialState = awaitFirstItem() - initialState.eventSink.invoke(TimelineEvents.EndPoll(AN_EVENT_ID)) + initialState.eventSink.invoke(TimelineEvent.EndPoll(AN_EVENT_ID)) } delay(1) endPollAction.verifyExecutionCount(1) @@ -459,7 +458,7 @@ class TimelinePresenterTest { messagesNavigator = navigator, ) presenter.test { - awaitFirstItem().eventSink(TimelineEvents.EditPoll(AN_EVENT_ID)) + awaitFirstItem().eventSink(TimelineEvent.EditPoll(AN_EVENT_ID)) onEditPollClickLambda.assertions().isCalledOnce().with(value(AN_EVENT_ID)) } } @@ -510,7 +509,7 @@ class TimelinePresenterTest { ) presenter.test { val initialState = awaitFirstItem() - initialState.eventSink.invoke(TimelineEvents.FocusOnEvent(AN_EVENT_ID)) + initialState.eventSink.invoke(TimelineEvent.FocusOnEvent(AN_EVENT_ID)) awaitItem().also { state -> assertThat(state.focusedEventId).isEqualTo(AN_EVENT_ID) assertThat(state.focusRequestState).isEqualTo(FocusRequestState.Requested(AN_EVENT_ID, Duration.ZERO)) @@ -524,7 +523,7 @@ class TimelinePresenterTest { assertThat(state.focusRequestState).isEqualTo(FocusRequestState.Success(AN_EVENT_ID)) assertThat(state.timelineItems).isNotEmpty() } - initialState.eventSink.invoke(TimelineEvents.JumpToLive) + initialState.eventSink.invoke(TimelineEvent.JumpToLive) skipItems(2) awaitItem().also { state -> // Event stays focused @@ -564,7 +563,7 @@ class TimelinePresenterTest { // Pre-populate the indexer after the first items have been retrieved timelineItemIndexer.process(listOf(aMessageEvent(eventId = AN_EVENT_ID))) - initialState.eventSink.invoke(TimelineEvents.FocusOnEvent(AN_EVENT_ID)) + initialState.eventSink.invoke(TimelineEvent.FocusOnEvent(AN_EVENT_ID)) advanceUntilIdle() @@ -595,7 +594,7 @@ class TimelinePresenterTest { ) presenter.test { val initialState = awaitFirstItem() - initialState.eventSink(TimelineEvents.FocusOnEvent(AN_EVENT_ID)) + initialState.eventSink(TimelineEvent.FocusOnEvent(AN_EVENT_ID)) awaitItem().also { state -> assertThat(state.focusedEventId).isEqualTo(AN_EVENT_ID) assertThat(state.focusRequestState).isEqualTo(FocusRequestState.Requested(AN_EVENT_ID, Duration.ZERO)) @@ -606,7 +605,7 @@ class TimelinePresenterTest { } awaitItem().also { state -> assertThat(state.focusRequestState).isInstanceOf(FocusRequestState.Failure::class.java) - state.eventSink(TimelineEvents.ClearFocusRequestState) + state.eventSink(TimelineEvent.ClearFocusRequestState) } awaitItem().also { state -> assertThat(state.focusRequestState).isEqualTo(FocusRequestState.None) @@ -648,7 +647,7 @@ class TimelinePresenterTest { ) presenter.test { val initialState = awaitFirstItem() - initialState.eventSink.invoke(TimelineEvents.FocusOnEvent(AN_EVENT_ID)) + initialState.eventSink.invoke(TimelineEvent.FocusOnEvent(AN_EVENT_ID)) awaitItem().also { state -> assertThat(state.focusedEventId).isEqualTo(AN_EVENT_ID) @@ -707,7 +706,7 @@ class TimelinePresenterTest { ) presenter.test { val initialState = awaitFirstItem() - initialState.eventSink.invoke(TimelineEvents.FocusOnEvent(AN_EVENT_ID)) + initialState.eventSink.invoke(TimelineEvent.FocusOnEvent(AN_EVENT_ID)) awaitItem().also { state -> assertThat(state.focusedEventId).isEqualTo(AN_EVENT_ID) @@ -762,7 +761,7 @@ class TimelinePresenterTest { ) presenter.test { val initialState = awaitFirstItem() - initialState.eventSink.invoke(TimelineEvents.FocusOnEvent(AN_EVENT_ID)) + initialState.eventSink.invoke(TimelineEvent.FocusOnEvent(AN_EVENT_ID)) awaitItem().also { state -> assertThat(state.focusedEventId).isEqualTo(AN_EVENT_ID) @@ -821,7 +820,7 @@ class TimelinePresenterTest { ) presenter.test { val initialState = awaitFirstItem() - initialState.eventSink.invoke(TimelineEvents.FocusOnEvent(AN_EVENT_ID)) + initialState.eventSink.invoke(TimelineEvent.FocusOnEvent(AN_EVENT_ID)) awaitItem().also { state -> assertThat(state.focusedEventId).isEqualTo(AN_EVENT_ID) @@ -854,10 +853,10 @@ class TimelinePresenterTest { val initialState = awaitFirstItem() assertThat(initialState.messageShieldDialogData).isNull() val shieldData = MessageShieldData(shield, null, null) - initialState.eventSink(TimelineEvents.ShowShieldDialog(shieldData)) + initialState.eventSink(TimelineEvent.ShowShieldDialog(shieldData)) awaitItem().also { state -> assertThat(state.messageShieldDialogData).isEqualTo(shieldData) - state.eventSink(TimelineEvents.HideShieldDialog) + state.eventSink(TimelineEvent.HideShieldDialog) } awaitItem().also { state -> assertThat(state.messageShieldDialogData).isNull() @@ -963,7 +962,7 @@ class TimelinePresenterTest { val presenter = createTimelinePresenter(room = room, messagesNavigator = navigator) presenter.test { val initialState = awaitFirstItem() - initialState.eventSink(TimelineEvents.NavigateToPredecessorOrSuccessorRoom(A_ROOM_ID)) + initialState.eventSink(TimelineEvent.NavigateToPredecessorOrSuccessorRoom(A_ROOM_ID)) assert(onNavigateToRoomLambda) .isCalledOnce() .with( 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 587b8f0839..c56641a048 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 @@ -50,7 +50,7 @@ class TimelineViewTest { @Test fun `reaching the end of the timeline with more events to load emits a LoadMore event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() rule.setTimelineView( state = aTimelineState( timelineItems = persistentListOf( @@ -62,12 +62,12 @@ class TimelineViewTest { eventSink = eventsRecorder, ), ) - eventsRecorder.assertSingle(TimelineEvents.LoadMore(Timeline.PaginationDirection.BACKWARDS)) + eventsRecorder.assertSingle(TimelineEvent.LoadMore(Timeline.PaginationDirection.BACKWARDS)) } @Test fun `reaching the end of the timeline does not send a LoadMore event`() { - val eventsRecorder = EventsRecorder(expectEvents = false) + val eventsRecorder = EventsRecorder(expectEvents = false) rule.setTimelineView( state = aTimelineState( eventSink = eventsRecorder, @@ -77,7 +77,7 @@ class TimelineViewTest { @Test fun `scroll to bottom on live timeline does not emit the Event`() { - val eventsRecorder = EventsRecorder(expectEvents = false) + val eventsRecorder = EventsRecorder(expectEvents = false) rule.setTimelineView( state = aTimelineState( isLive = true, @@ -91,7 +91,7 @@ class TimelineViewTest { @Test fun `scroll to bottom on detached timeline emits the expected Event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() rule.setTimelineView( state = aTimelineState( isLive = false, @@ -100,12 +100,12 @@ class TimelineViewTest { ) val contentDescription = rule.activity.getString(CommonStrings.a11y_jump_to_bottom) rule.onNodeWithContentDescription(contentDescription).performClick() - eventsRecorder.assertSingle(TimelineEvents.JumpToLive) + eventsRecorder.assertSingle(TimelineEvent.JumpToLive) } @Test fun `show shield dialog`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() rule.setTimelineView( state = aTimelineState( timelineItems = persistentListOf( @@ -122,15 +122,15 @@ class TimelineViewTest { rule.onNodeWithContentDescription(contentDescription).performClick() eventsRecorder.assertList( listOf( - TimelineEvents.OnScrollFinished(0), - TimelineEvents.ShowShieldDialog(MessageShieldData(MessageShield.UnverifiedIdentity(true))), + TimelineEvent.OnScrollFinished(0), + TimelineEvent.ShowShieldDialog(MessageShieldData(MessageShield.UnverifiedIdentity(true))), ) ) } @Test fun `hide shield dialog`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() rule.setTimelineView( state = aTimelineState( isLive = false, @@ -139,12 +139,12 @@ class TimelineViewTest { ), ) rule.clickOn(CommonStrings.action_ok) - eventsRecorder.assertSingle(TimelineEvents.HideShieldDialog) + eventsRecorder.assertSingle(TimelineEvent.HideShieldDialog) } @Test fun `scrolling near to the start of the loaded items triggers a pre-fetch`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val items = List(200) { aTimelineItemEvent( eventId = EventId("\$event_$it"), @@ -167,8 +167,8 @@ class TimelineViewTest { eventsRecorder.assertList( listOf( - TimelineEvents.OnScrollFinished(firstIndex = 0), - TimelineEvents.LoadMore(Timeline.PaginationDirection.BACKWARDS), + TimelineEvent.OnScrollFinished(firstIndex = 0), + TimelineEvent.LoadMore(Timeline.PaginationDirection.BACKWARDS), ) ) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemPollViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemPollViewTest.kt index f8b416a302..64b5216d2e 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemPollViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemPollViewTest.kt @@ -13,7 +13,7 @@ import androidx.compose.ui.test.hasText import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.performClick import androidx.test.ext.junit.runners.AndroidJUnit4 -import io.element.android.features.messages.impl.timeline.TimelineEvents +import io.element.android.features.messages.impl.timeline.TimelineEvent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.ui.strings.CommonStrings @@ -39,7 +39,7 @@ class TimelineItemPollViewTest { } private fun testAnswer(answerIndex: Int) { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val content = aTimelineItemPollContent() rule.setContent { TimelineItemPollView( @@ -52,12 +52,12 @@ class TimelineItemPollViewTest { matcher = hasText(answer.text), useUnmergedTree = true, ).performClick() - eventsRecorder.assertSingle(TimelineEvents.SelectPollAnswer(content.eventId!!, answer.id)) + eventsRecorder.assertSingle(TimelineEvent.SelectPollAnswer(content.eventId!!, answer.id)) } @Test fun `editing a poll should emit a PollEditClicked event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val content = aTimelineItemPollContent( isMine = true, isEditable = true, @@ -69,12 +69,12 @@ class TimelineItemPollViewTest { ) } rule.clickOn(CommonStrings.action_edit_poll) - eventsRecorder.assertSingle(TimelineEvents.EditPoll(content.eventId!!)) + eventsRecorder.assertSingle(TimelineEvent.EditPoll(content.eventId!!)) } @Test fun `closing a poll should emit a PollEndClicked event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val content = aTimelineItemPollContent( isMine = true, ) @@ -88,6 +88,6 @@ class TimelineItemPollViewTest { // A confirmation dialog should be shown eventsRecorder.assertEmpty() rule.pressTag(TestTags.dialogPositive.value) - eventsRecorder.assertSingle(TimelineEvents.EndPoll(content.eventId!!)) + eventsRecorder.assertSingle(TimelineEvent.EndPoll(content.eventId!!)) } } From 92a77fab1840a4ad71c1562742dc3c4d4845d0c6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 27 Jan 2026 09:47:49 +0100 Subject: [PATCH 07/18] EventFromTimelineItem -> TimelineItemEvent --- .../messages/impl/timeline/TimelineEvent.kt | 14 +++++++------- .../components/TimelineEventTimestampView.kt | 2 +- .../timeline/components/TimelineItemEventRow.kt | 8 ++++---- .../components/TimelineItemGroupedEventsRow.kt | 4 ++-- .../impl/timeline/components/TimelineItemRow.kt | 2 +- .../components/TimelineItemStateEventRow.kt | 2 +- .../timeline/components/TimelineItemVirtualRow.kt | 2 +- .../event/TimelineItemEventContentView.kt | 2 +- 8 files changed, 18 insertions(+), 18 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvent.kt index b3fc841ba9..1591cbf6cc 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvent.kt @@ -28,22 +28,22 @@ sealed interface TimelineEvent { /** * Events coming from a timeline item. */ - sealed interface EventFromTimelineItem : TimelineEvent + sealed interface TimelineItemEvent : TimelineEvent - data class ComputeVerifiedUserSendFailure(val event: TimelineItem.Event) : EventFromTimelineItem - data class ShowShieldDialog(val messageShieldData: MessageShieldData) : EventFromTimelineItem - data class LoadMore(val direction: Timeline.PaginationDirection) : EventFromTimelineItem - data class OpenThread(val threadRootEventId: ThreadId, val focusedEvent: EventId?) : EventFromTimelineItem + data class ComputeVerifiedUserSendFailure(val event: TimelineItem.Event) : TimelineItemEvent + data class ShowShieldDialog(val messageShieldData: MessageShieldData) : TimelineItemEvent + data class LoadMore(val direction: Timeline.PaginationDirection) : TimelineItemEvent + data class OpenThread(val threadRootEventId: ThreadId, val focusedEvent: EventId?) : TimelineItemEvent /** * Navigate to the predecessor or successor room of the current room. */ - data class NavigateToPredecessorOrSuccessorRoom(val roomId: RoomId) : EventFromTimelineItem + data class NavigateToPredecessorOrSuccessorRoom(val roomId: RoomId) : TimelineItemEvent /** * Events coming from a poll item. */ - sealed interface TimelineItemPollEvent : EventFromTimelineItem + sealed interface TimelineItemPollEvent : TimelineItemEvent data class SelectPollAnswer( val pollStartId: EventId, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt index a6ace1cadd..21ef7c5b09 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt @@ -38,7 +38,7 @@ import io.element.android.libraries.ui.strings.CommonStrings @Composable fun TimelineEventTimestampView( event: TimelineItem.Event, - eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.TimelineItemEvent) -> Unit, modifier: Modifier = Modifier, ) { val formattedTime = event.sentTime diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index 811ba83759..b253f45937 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -153,7 +153,7 @@ fun TimelineItemEventRow( onMoreReactionsClick: (eventId: TimelineItem.Event) -> Unit, onReadReceiptClick: (event: TimelineItem.Event) -> Unit, onSwipeToReply: () -> Unit, - eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.TimelineItemEvent) -> Unit, modifier: Modifier = Modifier, eventContentView: @Composable (Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit = { contentModifier, onContentLayoutChange -> // Only pass down a custom clickable lambda if the content can be clicked separately @@ -410,7 +410,7 @@ private fun TimelineItemEventRowContent( onReactionClick: (emoji: String) -> Unit, onReactionLongClick: (emoji: String) -> Unit, onMoreReactionsClick: (event: TimelineItem.Event) -> Unit, - eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.TimelineItemEvent) -> Unit, modifier: Modifier = Modifier, eventContentView: @Composable (Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit, ) { @@ -585,7 +585,7 @@ private fun MessageEventBubbleContent( timelineProtectionState: TimelineProtectionState, onMessageLongClick: () -> Unit, inReplyToClick: () -> Unit, - eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.TimelineItemEvent) -> Unit, @SuppressLint("ModifierParameter") // need to rename this modifier to prevent linter false positives @Suppress("ModifierNaming") @@ -623,7 +623,7 @@ private fun MessageEventBubbleContent( @Composable fun WithTimestampLayout( timestampPosition: TimestampPosition, - eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.TimelineItemEvent) -> Unit, modifier: Modifier = Modifier, canShrinkContent: Boolean = false, content: @Composable (onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit) -> Unit, 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 9f5842afd4..505d76b24b 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 @@ -57,7 +57,7 @@ fun TimelineItemGroupedEventsRow( onReactionLongClick: (key: String, TimelineItem.Event) -> Unit, onMoreReactionsClick: (TimelineItem.Event) -> Unit, onReadReceiptClick: (TimelineItem.Event) -> Unit, - eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.TimelineItemEvent) -> Unit, modifier: Modifier = Modifier, eventContentView: @Composable (TimelineItem.Event, Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit = { event, contentModifier, onContentLayoutChange -> @@ -130,7 +130,7 @@ private fun TimelineItemGroupedEventsRowContent( onReactionLongClick: (key: String, TimelineItem.Event) -> Unit, onMoreReactionsClick: (TimelineItem.Event) -> Unit, onReadReceiptClick: (TimelineItem.Event) -> Unit, - eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.TimelineItemEvent) -> Unit, modifier: Modifier = Modifier, eventContentView: @Composable (TimelineItem.Event, Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit = { event, contentModifier, onContentLayoutChange -> diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt index 93882e8436..15e47e5269 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt @@ -73,7 +73,7 @@ internal fun TimelineItemRow( onReadReceiptClick: (TimelineItem.Event) -> Unit, onSwipeToReply: (TimelineItem.Event) -> Unit, onJoinCallClick: () -> Unit, - eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.TimelineItemEvent) -> Unit, modifier: Modifier = Modifier, eventContentView: @Composable (TimelineItem.Event, Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit = { event, contentModifier, onContentLayoutChange -> diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemStateEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemStateEventRow.kt index 4c6f627af0..6e409f2b8d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemStateEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemStateEventRow.kt @@ -44,7 +44,7 @@ fun TimelineItemStateEventRow( onClick: () -> Unit, onLongClick: () -> Unit, onReadReceiptsClick: (event: TimelineItem.Event) -> Unit, - eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.TimelineItemEvent) -> Unit, modifier: Modifier = Modifier ) { val interactionSource = remember { MutableInteractionSource() } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemVirtualRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemVirtualRow.kt index a7685314f9..3e8e3c919e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemVirtualRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemVirtualRow.kt @@ -35,7 +35,7 @@ import timber.log.Timber fun TimelineItemVirtualRow( virtual: TimelineItem.Virtual, timelineRoomInfo: TimelineRoomInfo, - eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.TimelineItemEvent) -> Unit, modifier: Modifier = Modifier ) { Box(modifier = modifier) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt index dcd53e3fa2..4fc243864c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt @@ -43,7 +43,7 @@ fun TimelineItemEventContentView( onShowContentClick: () -> Unit, onLinkClick: (Link) -> Unit, onLinkLongClick: (Link) -> Unit, - eventSink: (TimelineEvent.EventFromTimelineItem) -> Unit, + eventSink: (TimelineEvent.TimelineItemEvent) -> Unit, modifier: Modifier = Modifier, onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit = {}, ) { From c96f6036a33730c3876957d7f33ee62412e543bb Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 27 Jan 2026 09:55:20 +0100 Subject: [PATCH 08/18] LinkEvents -> LinkEvent --- .../android/features/messages/impl/MessagesView.kt | 4 ++-- .../impl/link/{LinkEvents.kt => LinkEvent.kt} | 8 ++++---- .../features/messages/impl/link/LinkPresenter.kt | 8 ++++---- .../android/features/messages/impl/link/LinkState.kt | 2 +- .../features/messages/impl/link/LinkStateProvider.kt | 2 +- .../android/features/messages/impl/link/LinkView.kt | 6 +++--- .../impl/pinned/list/PinnedMessagesListView.kt | 6 +++--- .../features/messages/impl/link/LinkPresenterTest.kt | 10 +++++----- .../features/messages/impl/link/LinkViewTest.kt | 12 ++++++------ 9 files changed, 29 insertions(+), 29 deletions(-) rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/{LinkEvents.kt => LinkEvent.kt} (68%) 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 2d9319c262..8094ab938b 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 @@ -57,7 +57,7 @@ import io.element.android.features.messages.impl.actionlist.ActionListView import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.crypto.historyvisible.HistoryVisibleStateView import io.element.android.features.messages.impl.crypto.identity.IdentityChangeStateView -import io.element.android.features.messages.impl.link.LinkEvents +import io.element.android.features.messages.impl.link.LinkEvent import io.element.android.features.messages.impl.link.LinkView import io.element.android.features.messages.impl.messagecomposer.AttachmentsBottomSheet import io.element.android.features.messages.impl.messagecomposer.DisabledComposerView @@ -252,7 +252,7 @@ fun MessagesView( onLinkClick(link.url, true) // Do not check those links, they are internal link only } else { - state.linkState.eventSink(LinkEvents.OnLinkClick(link)) + state.linkState.eventSink(LinkEvent.OnLinkClick(link)) } }, onReactionClick = ::onEmojiReactionClick, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkEvent.kt similarity index 68% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkEvents.kt rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkEvent.kt index ce817bf642..fb94eaf420 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkEvent.kt @@ -10,8 +10,8 @@ package io.element.android.features.messages.impl.link import io.element.android.wysiwyg.link.Link -sealed interface LinkEvents { - data class OnLinkClick(val link: Link) : LinkEvents - data object Confirm : LinkEvents - data object Cancel : LinkEvents +sealed interface LinkEvent { + data class OnLinkClick(val link: Link) : LinkEvent + data object Confirm : LinkEvent + data object Cancel : LinkEvent } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkPresenter.kt index b6886652d5..572209f463 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkPresenter.kt @@ -25,9 +25,9 @@ class LinkPresenter( override fun present(): LinkState { val linkClick: MutableState> = remember { mutableStateOf(AsyncAction.Uninitialized) } - fun handleEvent(event: LinkEvents) { + fun handleEvent(event: LinkEvent) { when (event) { - is LinkEvents.OnLinkClick -> { + is LinkEvent.OnLinkClick -> { linkClick.value = AsyncAction.Loading val result = linkChecker.isSafe(event.link) if (result) { @@ -37,12 +37,12 @@ class LinkPresenter( linkClick.value = ConfirmingLinkClick(event.link) } } - LinkEvents.Confirm -> { + LinkEvent.Confirm -> { linkClick.value = (linkClick.value as? ConfirmingLinkClick) ?.let { AsyncAction.Success(it.link) } ?: AsyncAction.Uninitialized } - LinkEvents.Cancel -> { + LinkEvent.Cancel -> { linkClick.value = AsyncAction.Uninitialized } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkState.kt index c06d23ef9a..20b5cc7fe3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkState.kt @@ -13,5 +13,5 @@ import io.element.android.wysiwyg.link.Link data class LinkState( val linkClick: AsyncAction, - val eventSink: (LinkEvents) -> Unit, + val eventSink: (LinkEvent) -> Unit, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkStateProvider.kt index 8388cbea52..2e021ec276 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkStateProvider.kt @@ -29,7 +29,7 @@ open class LinkStateProvider : PreviewParameterProvider { fun aLinkState( linkClick: AsyncAction = AsyncAction.Uninitialized, - eventSink: (LinkEvents) -> Unit = {}, + eventSink: (LinkEvent) -> Unit = {}, ) = LinkState( linkClick = linkClick, eventSink = eventSink, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkView.kt index 1a7558de05..69e6ee8673 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/link/LinkView.kt @@ -46,10 +46,10 @@ fun LinkView( ), submitText = stringResource(CommonStrings.action_continue), onSubmitClick = { - state.eventSink(LinkEvents.Confirm) + state.eventSink(LinkEvent.Confirm) }, onDismiss = { - state.eventSink(LinkEvents.Cancel) + state.eventSink(LinkEvent.Cancel) }, ) } @@ -58,7 +58,7 @@ fun LinkView( val latestOnLinkValid by rememberUpdatedState(onLinkValid) LaunchedEffect(state.linkClick.data) { latestOnLinkValid(state.linkClick.data) - state.eventSink(LinkEvents.Cancel) + state.eventSink(LinkEvent.Cancel) } } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt index cdca126753..85f709d212 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt @@ -28,7 +28,7 @@ import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.messages.impl.actionlist.ActionListEvent import io.element.android.features.messages.impl.actionlist.ActionListView import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction -import io.element.android.features.messages.impl.link.LinkEvents +import io.element.android.features.messages.impl.link.LinkEvent import io.element.android.features.messages.impl.link.LinkView import io.element.android.features.messages.impl.timeline.components.TimelineItemRow import io.element.android.features.messages.impl.timeline.components.event.TimelineItemEventContentView @@ -222,7 +222,7 @@ private fun PinnedMessagesListLoaded( focusedEventId = null, onUserDataClick = onUserDataClick, onLinkClick = { link -> - state.linkState.eventSink(LinkEvents.OnLinkClick(link)) + state.linkState.eventSink(LinkEvent.OnLinkClick(link)) }, onLinkLongClick = onLinkLongClick, onContentClick = onEventClick, @@ -243,7 +243,7 @@ private fun PinnedMessagesListLoaded( onContentClick = { onEventClick(event) }, onLongClick = { onMessageLongClick(event) }, onLinkClick = { link -> - state.linkState.eventSink(LinkEvents.OnLinkClick(link)) + state.linkState.eventSink(LinkEvent.OnLinkClick(link)) }, onLinkLongClick = onLinkLongClick, modifier = contentModifier, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/link/LinkPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/link/LinkPresenterTest.kt index 02292cf0ce..30548022e7 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/link/LinkPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/link/LinkPresenterTest.kt @@ -45,7 +45,7 @@ class LinkPresenterTest { presenter.test { val initialState = awaitItem() assertThat(initialState.linkClick).isEqualTo(AsyncAction.Uninitialized) - initialState.eventSink(LinkEvents.OnLinkClick(aLink)) + initialState.eventSink(LinkEvent.OnLinkClick(aLink)) assertThat(awaitItem().linkClick).isEqualTo(AsyncAction.Loading) val state = awaitItem() assertThat(state.linkClick).isEqualTo(AsyncAction.Success(aLink)) @@ -61,11 +61,11 @@ class LinkPresenterTest { presenter.test { val initialState = awaitItem() assertThat(initialState.linkClick).isEqualTo(AsyncAction.Uninitialized) - initialState.eventSink(LinkEvents.OnLinkClick(aLink)) + initialState.eventSink(LinkEvent.OnLinkClick(aLink)) assertThat(awaitItem().linkClick).isEqualTo(AsyncAction.Loading) val state = awaitItem() assertThat(state.linkClick).isEqualTo(ConfirmingLinkClick(aLink)) - state.eventSink(LinkEvents.Cancel) + state.eventSink(LinkEvent.Cancel) val finalState = awaitItem() assertThat(finalState.linkClick).isEqualTo(AsyncAction.Uninitialized) } @@ -79,11 +79,11 @@ class LinkPresenterTest { presenter.test { val initialState = awaitItem() assertThat(initialState.linkClick).isEqualTo(AsyncAction.Uninitialized) - initialState.eventSink(LinkEvents.OnLinkClick(aLink)) + initialState.eventSink(LinkEvent.OnLinkClick(aLink)) assertThat(awaitItem().linkClick).isEqualTo(AsyncAction.Loading) val state = awaitItem() assertThat(state.linkClick).isEqualTo(ConfirmingLinkClick(aLink)) - state.eventSink(LinkEvents.Confirm) + state.eventSink(LinkEvent.Confirm) val finalState = awaitItem() assertThat(finalState.linkClick).isEqualTo(AsyncAction.Success(aLink)) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/link/LinkViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/link/LinkViewTest.kt index 54c95d83c7..e198ea9043 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/link/LinkViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/link/LinkViewTest.kt @@ -31,7 +31,7 @@ class LinkViewTest { @Test fun `clicking on cancel emits the expected event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() rule.setLinkView( aLinkState( linkClick = ConfirmingLinkClick(aLink), @@ -40,13 +40,13 @@ class LinkViewTest { ) rule.clickOn(CommonStrings.action_cancel) eventsRecorder.assertSingle( - LinkEvents.Cancel + LinkEvent.Cancel ) } @Test fun `clicking on continue emits the expected event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() rule.setLinkView( aLinkState( linkClick = ConfirmingLinkClick(aLink), @@ -55,13 +55,13 @@ class LinkViewTest { ) rule.clickOn(CommonStrings.action_continue) eventsRecorder.assertSingle( - LinkEvents.Confirm + LinkEvent.Confirm ) } @Test fun `success state invokes the callback and emits the expected event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() ensureCalledOnceWithParam(aLink) { callback -> rule.setLinkView( aLinkState( @@ -72,7 +72,7 @@ class LinkViewTest { ) } eventsRecorder.assertSingle( - LinkEvents.Cancel + LinkEvent.Cancel ) } } From 56668377d415743ffff6eca04326d695214cc9b5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 27 Jan 2026 09:57:36 +0100 Subject: [PATCH 09/18] AttachmentsPreviewEvents -> AttachmentsPreviewEvent --- ...ewEvents.kt => AttachmentsPreviewEvent.kt} | 8 +++--- .../preview/AttachmentsPreviewPresenter.kt | 8 +++--- .../preview/AttachmentsPreviewState.kt | 2 +- .../preview/AttachmentsPreviewView.kt | 8 +++--- .../AttachmentsPreviewPresenterTest.kt | 28 +++++++++---------- 5 files changed, 27 insertions(+), 27 deletions(-) rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/{AttachmentsPreviewEvents.kt => AttachmentsPreviewEvent.kt} (69%) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewEvent.kt similarity index 69% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewEvents.kt rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewEvent.kt index d8e29de92e..d473d4c3f4 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewEvent.kt @@ -8,8 +8,8 @@ package io.element.android.features.messages.impl.attachments.preview -sealed interface AttachmentsPreviewEvents { - data object SendAttachment : AttachmentsPreviewEvents - data object CancelAndDismiss : AttachmentsPreviewEvents - data object CancelAndClearSendState : AttachmentsPreviewEvents +sealed interface AttachmentsPreviewEvent { + data object SendAttachment : AttachmentsPreviewEvent + data object CancelAndDismiss : AttachmentsPreviewEvent + data object CancelAndClearSendState : AttachmentsPreviewEvent } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt index 6db903cb1b..8e92e53f6a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewPresenter.kt @@ -140,9 +140,9 @@ class AttachmentsPreviewPresenter( } } - fun handleEvent(event: AttachmentsPreviewEvents) { + fun handleEvent(event: AttachmentsPreviewEvent) { when (event) { - is AttachmentsPreviewEvents.SendAttachment -> { + is AttachmentsPreviewEvent.SendAttachment -> { ongoingSendAttachmentJob.value = coroutineScope.launch { // If the media optimization selector is displayed, we need to wait for the user to select the options // before we can pre-process the media. @@ -191,7 +191,7 @@ class AttachmentsPreviewPresenter( } } } - AttachmentsPreviewEvents.CancelAndDismiss -> { + AttachmentsPreviewEvent.CancelAndDismiss -> { displayFileTooLargeError = false // Cancel media preprocessing and sending @@ -206,7 +206,7 @@ class AttachmentsPreviewPresenter( sendActionState, ) } - AttachmentsPreviewEvents.CancelAndClearSendState -> { + AttachmentsPreviewEvent.CancelAndClearSendState -> { // Cancel media sending ongoingSendAttachmentJob.value?.let { it.cancel() diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewState.kt index 42d01a4f21..97ca230d77 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewState.kt @@ -20,7 +20,7 @@ data class AttachmentsPreviewState( val textEditorState: TextEditorState, val mediaOptimizationSelectorState: MediaOptimizationSelectorState, val displayFileTooLargeError: Boolean, - val eventSink: (AttachmentsPreviewEvents) -> Unit + val eventSink: (AttachmentsPreviewEvent) -> Unit, ) @Immutable diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt index 8f55957e32..bb3a07c2ff 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt @@ -82,15 +82,15 @@ fun AttachmentsPreviewView( modifier: Modifier = Modifier, ) { fun postSendAttachment() { - state.eventSink(AttachmentsPreviewEvents.SendAttachment) + state.eventSink(AttachmentsPreviewEvent.SendAttachment) } fun postCancel() { - state.eventSink(AttachmentsPreviewEvents.CancelAndDismiss) + state.eventSink(AttachmentsPreviewEvent.CancelAndDismiss) } fun postClearSendState() { - state.eventSink(AttachmentsPreviewEvents.CancelAndClearSendState) + state.eventSink(AttachmentsPreviewEvent.CancelAndClearSendState) } BackHandler(enabled = state.sendActionState !is SendActionState.Sending.Uploading && state.sendActionState !is SendActionState.Done) { @@ -199,7 +199,7 @@ private fun AttachmentPreviewContent( AlertDialog( title = stringResource(CommonStrings.dialog_file_too_large_to_upload_title), content = content, - onDismiss = { state.eventSink(AttachmentsPreviewEvents.CancelAndDismiss) }, + onDismiss = { state.eventSink(AttachmentsPreviewEvent.CancelAndDismiss) }, ) } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt index fe462fc988..1e4bea0b4a 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt @@ -15,7 +15,7 @@ import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat -import io.element.android.features.messages.impl.attachments.preview.AttachmentsPreviewEvents +import io.element.android.features.messages.impl.attachments.preview.AttachmentsPreviewEvent import io.element.android.features.messages.impl.attachments.preview.AttachmentsPreviewPresenter import io.element.android.features.messages.impl.attachments.preview.OnDoneListener import io.element.android.features.messages.impl.attachments.preview.SendActionState @@ -117,7 +117,7 @@ class AttachmentsPreviewPresenterTest { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) - initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) + initialState.eventSink(AttachmentsPreviewEvent.SendAttachment) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = true)) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.ReadyToUpload(mediaUploadInfo)) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Uploading(mediaUploadInfo)) @@ -156,7 +156,7 @@ class AttachmentsPreviewPresenterTest { processLatch.complete(Unit) advanceUntilIdle() assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) - initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) + initialState.eventSink(AttachmentsPreviewEvent.SendAttachment) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.ReadyToUpload(mediaUploadInfo)) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Uploading(mediaUploadInfo)) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Done) @@ -191,7 +191,7 @@ class AttachmentsPreviewPresenterTest { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) - initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) + initialState.eventSink(AttachmentsPreviewEvent.SendAttachment) // Pre-processing finishes processLatch.complete(Unit) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = true)) @@ -221,7 +221,7 @@ class AttachmentsPreviewPresenterTest { }.test { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) - initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) + initialState.eventSink(AttachmentsPreviewEvent.SendAttachment) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) // Pre-processing finishes processLatch.complete(Unit) @@ -249,7 +249,7 @@ class AttachmentsPreviewPresenterTest { // Pre-processing finishes processLatch.complete(Unit) advanceUntilIdle() - initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) + initialState.eventSink(AttachmentsPreviewEvent.SendAttachment) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) assertThat(awaitItem().sendActionState).isInstanceOf(SendActionState.Failure::class.java) } @@ -270,7 +270,7 @@ class AttachmentsPreviewPresenterTest { }.test { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) - initialState.eventSink(AttachmentsPreviewEvents.CancelAndDismiss) + initialState.eventSink(AttachmentsPreviewEvent.CancelAndDismiss) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Done) deleteCallback.assertions().isCalledOnce() onDoneListener.assertions().isCalledOnce() @@ -304,7 +304,7 @@ class AttachmentsPreviewPresenterTest { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) initialState.textEditorState.setMarkdown(A_CAPTION) - initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) + initialState.eventSink(AttachmentsPreviewEvent.SendAttachment) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) assertThat(awaitItem().sendActionState).isInstanceOf(SendActionState.Sending.ReadyToUpload::class.java) assertThat(awaitItem().sendActionState).isInstanceOf(SendActionState.Sending.Uploading::class.java) @@ -347,7 +347,7 @@ class AttachmentsPreviewPresenterTest { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) initialState.textEditorState.setMarkdown(A_CAPTION) - initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) + initialState.eventSink(AttachmentsPreviewEvent.SendAttachment) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) assertThat(awaitItem().sendActionState).isInstanceOf(SendActionState.Sending.ReadyToUpload::class.java) assertThat(awaitItem().sendActionState).isInstanceOf(SendActionState.Sending.Uploading::class.java) @@ -388,7 +388,7 @@ class AttachmentsPreviewPresenterTest { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) initialState.textEditorState.setMarkdown(A_CAPTION) - initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) + initialState.eventSink(AttachmentsPreviewEvent.SendAttachment) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) assertThat(awaitItem().sendActionState).isInstanceOf(SendActionState.Sending.ReadyToUpload::class.java) assertThat(awaitItem().sendActionState).isInstanceOf(SendActionState.Sending.Uploading::class.java) @@ -423,7 +423,7 @@ class AttachmentsPreviewPresenterTest { }.test { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) - initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) + initialState.eventSink(AttachmentsPreviewEvent.SendAttachment) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.ReadyToUpload(mediaUploadInfo)) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Uploading(mediaUploadInfo)) @@ -434,7 +434,7 @@ class AttachmentsPreviewPresenterTest { val failureState = awaitItem() assertThat(failureState.sendActionState).isEqualTo(SendActionState.Failure(failure, mediaUploadInfo)) sendFileResult.assertions().isCalledOnce() - failureState.eventSink(AttachmentsPreviewEvents.CancelAndClearSendState) + failureState.eventSink(AttachmentsPreviewEvent.CancelAndClearSendState) val clearedState = awaitLastSequentialItem() assertThat(clearedState.sendActionState).isEqualTo(SendActionState.Sending.ReadyToUpload(mediaUploadInfo)) } @@ -458,11 +458,11 @@ class AttachmentsPreviewPresenterTest { }.test { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) - initialState.eventSink(AttachmentsPreviewEvents.SendAttachment) + initialState.eventSink(AttachmentsPreviewEvent.SendAttachment) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.ReadyToUpload(mediaUploadInfo)) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Uploading(mediaUploadInfo)) - initialState.eventSink(AttachmentsPreviewEvents.CancelAndClearSendState) + initialState.eventSink(AttachmentsPreviewEvent.CancelAndClearSendState) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.ReadyToUpload(mediaUploadInfo)) // The sending is cancelled and the state is kept at ReadyToUpload ensureAllEventsConsumed() From 4d04808875920ce14eff7029f201e82c4e28b609 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 27 Jan 2026 09:58:44 +0100 Subject: [PATCH 10/18] ResolveVerifiedUserSendFailureEvent -> ResolveVerifiedUserSendFailureEven --- ...=> ResolveVerifiedUserSendFailureEvent.kt} | 10 ++--- ...ResolveVerifiedUserSendFailurePresenter.kt | 10 ++--- .../ResolveVerifiedUserSendFailureState.kt | 2 +- ...lveVerifiedUserSendFailureStateProvider.kt | 2 +- .../ResolveVerifiedUserSendFailureView.kt | 6 +-- .../impl/timeline/TimelinePresenter.kt | 4 +- ...lveVerifiedUserSendFailurePresenterTest.kt | 38 +++++++++---------- .../ResolveVerifiedUserSendFailureViewTest.kt | 8 ++-- 8 files changed, 40 insertions(+), 40 deletions(-) rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/{ResolveVerifiedUserSendFailureEvents.kt => ResolveVerifiedUserSendFailureEvent.kt} (70%) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureEvent.kt similarity index 70% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureEvents.kt rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureEvent.kt index 242dc58453..607d7b423b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureEvent.kt @@ -10,12 +10,12 @@ package io.element.android.features.messages.impl.crypto.sendfailure.resolve import io.element.android.features.messages.impl.timeline.model.TimelineItem -sealed interface ResolveVerifiedUserSendFailureEvents { +sealed interface ResolveVerifiedUserSendFailureEvent { data class ComputeForMessage( val messageEvent: TimelineItem.Event, - ) : ResolveVerifiedUserSendFailureEvents + ) : ResolveVerifiedUserSendFailureEvent - data object ResolveAndResend : ResolveVerifiedUserSendFailureEvents - data object Retry : ResolveVerifiedUserSendFailureEvents - data object Dismiss : ResolveVerifiedUserSendFailureEvents + data object ResolveAndResend : ResolveVerifiedUserSendFailureEvent + data object Retry : ResolveVerifiedUserSendFailureEvent + data object Dismiss : ResolveVerifiedUserSendFailureEvent } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenter.kt index 720e6762f7..e66bb34275 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenter.kt @@ -48,9 +48,9 @@ class ResolveVerifiedUserSendFailurePresenter( } val coroutineScope = rememberCoroutineScope() - fun handleEvent(event: ResolveVerifiedUserSendFailureEvents) { + fun handleEvent(event: ResolveVerifiedUserSendFailureEvent) { when (event) { - is ResolveVerifiedUserSendFailureEvents.ComputeForMessage -> { + is ResolveVerifiedUserSendFailureEvent.ComputeForMessage -> { val sendState = event.messageEvent.localSendState as? LocalEventSendState.Failed.VerifiedUser val transactionId = event.messageEvent.transactionId val sendHandle = event.messageEvent.sendhandle @@ -65,10 +65,10 @@ class ResolveVerifiedUserSendFailurePresenter( null } } - ResolveVerifiedUserSendFailureEvents.Dismiss -> { + ResolveVerifiedUserSendFailureEvent.Dismiss -> { resolver = null } - ResolveVerifiedUserSendFailureEvents.Retry -> { + ResolveVerifiedUserSendFailureEvent.Retry -> { coroutineScope.launch { resolver?.run { runUpdatingState(retryAction) { @@ -77,7 +77,7 @@ class ResolveVerifiedUserSendFailurePresenter( } } } - ResolveVerifiedUserSendFailureEvents.ResolveAndResend -> { + ResolveVerifiedUserSendFailureEvent.ResolveAndResend -> { coroutineScope.launch { resolver?.run { runUpdatingState(resolveAction) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureState.kt index dfe9ac36de..7a42a06a5b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureState.kt @@ -15,5 +15,5 @@ data class ResolveVerifiedUserSendFailureState( val verifiedUserSendFailure: VerifiedUserSendFailure, val resolveAction: AsyncAction, val retryAction: AsyncAction, - val eventSink: (ResolveVerifiedUserSendFailureEvents) -> Unit + val eventSink: (ResolveVerifiedUserSendFailureEvent) -> Unit ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureStateProvider.kt index 251f0e6564..e167ac3221 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureStateProvider.kt @@ -29,7 +29,7 @@ fun aResolveVerifiedUserSendFailureState( verifiedUserSendFailure: VerifiedUserSendFailure = VerifiedUserSendFailure.None, resolveAction: AsyncAction = AsyncAction.Uninitialized, retryAction: AsyncAction = AsyncAction.Uninitialized, - eventSink: (ResolveVerifiedUserSendFailureEvents) -> Unit = {} + eventSink: (ResolveVerifiedUserSendFailureEvent) -> Unit = {} ) = ResolveVerifiedUserSendFailureState( verifiedUserSendFailure = verifiedUserSendFailure, resolveAction = resolveAction, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt index 3f881e7bb9..98e2bba3be 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt @@ -47,15 +47,15 @@ fun ResolveVerifiedUserSendFailureView( var showSheet by remember { mutableStateOf(false) } fun dismiss() { - state.eventSink(ResolveVerifiedUserSendFailureEvents.Dismiss) + state.eventSink(ResolveVerifiedUserSendFailureEvent.Dismiss) } fun onRetryClick() { - state.eventSink(ResolveVerifiedUserSendFailureEvents.Retry) + state.eventSink(ResolveVerifiedUserSendFailureEvent.Retry) } fun onResolveAndResendClick() { - state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) + state.eventSink(ResolveVerifiedUserSendFailureEvent.ResolveAndResend) } LaunchedEffect(state.verifiedUserSendFailure) { 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 df704287a3..12e4e0b1d1 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 @@ -25,7 +25,7 @@ import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject import io.element.android.features.messages.impl.MessagesNavigator import io.element.android.features.messages.impl.UserEventPermissions -import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureEvents +import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureEvent import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.timeline.components.MessageShieldData import io.element.android.features.messages.impl.timeline.factories.TimelineItemsFactory @@ -218,7 +218,7 @@ class TimelinePresenter( TimelineEvent.HideShieldDialog -> messageShieldDialogData.value = null is TimelineEvent.ShowShieldDialog -> messageShieldDialogData.value = event.messageShieldData is TimelineEvent.ComputeVerifiedUserSendFailure -> { - resolveVerifiedUserSendFailureState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(event.event)) + resolveVerifiedUserSendFailureState.eventSink(ResolveVerifiedUserSendFailureEvent.ComputeForMessage(event.event)) } is TimelineEvent.NavigateToPredecessorOrSuccessorRoom -> { // Navigate to the predecessor or successor room diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenterTest.kt index 7f22de9159..963ae16e76 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenterTest.kt @@ -47,7 +47,7 @@ class ResolveVerifiedUserSendFailurePresenterTest { val sentMessage = aMessageEvent() val initialState = awaitItem() assertThat(initialState.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) - initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(sentMessage)) + initialState.eventSink(ResolveVerifiedUserSendFailureEvent.ComputeForMessage(sentMessage)) ensureAllEventsConsumed() } } @@ -61,7 +61,7 @@ class ResolveVerifiedUserSendFailurePresenterTest { ) val initialState = awaitItem() assertThat(initialState.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) - initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(sentMessage)) + initialState.eventSink(ResolveVerifiedUserSendFailureEvent.ComputeForMessage(sentMessage)) ensureAllEventsConsumed() } } @@ -75,7 +75,7 @@ class ResolveVerifiedUserSendFailurePresenterTest { ) val initialState = awaitItem() assertThat(initialState.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) - initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(failedMessage)) + initialState.eventSink(ResolveVerifiedUserSendFailureEvent.ComputeForMessage(failedMessage)) ensureAllEventsConsumed() } } @@ -94,11 +94,11 @@ class ResolveVerifiedUserSendFailurePresenterTest { val failedMessage = aVerifiedUserHasUnsignedDeviceFailedMessage() val initialState = awaitItem() assertThat(initialState.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) - initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(failedMessage)) + initialState.eventSink(ResolveVerifiedUserSendFailureEvent.ComputeForMessage(failedMessage)) skipItems(1) awaitItem().also { state -> assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromYou) - state.eventSink(ResolveVerifiedUserSendFailureEvents.Dismiss) + state.eventSink(ResolveVerifiedUserSendFailureEvent.Dismiss) } skipItems(1) awaitItem().also { state -> @@ -122,12 +122,12 @@ class ResolveVerifiedUserSendFailurePresenterTest { val failedMessage = aVerifiedUserHasUnsignedDeviceFailedMessage() val initialState = awaitItem() assertThat(initialState.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) - initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(failedMessage)) + initialState.eventSink(ResolveVerifiedUserSendFailureEvent.ComputeForMessage(failedMessage)) skipItems(1) awaitItem().also { state -> assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromYou) - state.eventSink(ResolveVerifiedUserSendFailureEvents.Retry) + state.eventSink(ResolveVerifiedUserSendFailureEvent.Retry) } awaitItem().also { state -> assertThat(state.retryAction).isEqualTo(AsyncAction.Loading) @@ -158,12 +158,12 @@ class ResolveVerifiedUserSendFailurePresenterTest { val failedMessage = aVerifiedUserHasUnsignedDeviceFailedMessage() val initialState = awaitItem() assertThat(initialState.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) - initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(failedMessage)) + initialState.eventSink(ResolveVerifiedUserSendFailureEvent.ComputeForMessage(failedMessage)) skipItems(1) awaitItem().also { state -> assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromYou) - state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) + state.eventSink(ResolveVerifiedUserSendFailureEvent.ResolveAndResend) } awaitItem().also { state -> assertThat(state.resolveAction).isEqualTo(AsyncAction.Loading) @@ -173,7 +173,7 @@ class ResolveVerifiedUserSendFailurePresenterTest { awaitItem().also { state -> assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromOther(A_USER_ID_2.value)) assertThat(state.resolveAction).isEqualTo(AsyncAction.Success(Unit)) - state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) + state.eventSink(ResolveVerifiedUserSendFailureEvent.ResolveAndResend) } skipItems(3) @@ -201,12 +201,12 @@ class ResolveVerifiedUserSendFailurePresenterTest { val failedMessage = aVerifiedUserHasUnsignedDeviceFailedMessage() val initialState = awaitItem() assertThat(initialState.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) - initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(failedMessage)) + initialState.eventSink(ResolveVerifiedUserSendFailureEvent.ComputeForMessage(failedMessage)) skipItems(1) awaitItem().also { state -> assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromYou) - state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) + state.eventSink(ResolveVerifiedUserSendFailureEvent.ResolveAndResend) } awaitItem().also { state -> assertThat(state.resolveAction).isEqualTo(AsyncAction.Loading) @@ -233,12 +233,12 @@ class ResolveVerifiedUserSendFailurePresenterTest { val failedMessage = aVerifiedUserChangedIdentityMessage() val initialState = awaitItem() assertThat(initialState.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) - initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(failedMessage)) + initialState.eventSink(ResolveVerifiedUserSendFailureEvent.ComputeForMessage(failedMessage)) skipItems(1) awaitItem().also { state -> assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.ChangedIdentity(A_USER_ID.value)) - state.eventSink(ResolveVerifiedUserSendFailureEvents.Retry) + state.eventSink(ResolveVerifiedUserSendFailureEvent.Retry) } awaitItem().also { state -> assertThat(state.retryAction).isEqualTo(AsyncAction.Loading) @@ -269,12 +269,12 @@ class ResolveVerifiedUserSendFailurePresenterTest { val failedMessage = aVerifiedUserChangedIdentityMessage() val initialState = awaitItem() assertThat(initialState.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) - initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(failedMessage)) + initialState.eventSink(ResolveVerifiedUserSendFailureEvent.ComputeForMessage(failedMessage)) skipItems(1) awaitItem().also { state -> assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.ChangedIdentity(A_USER_ID.value)) - state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) + state.eventSink(ResolveVerifiedUserSendFailureEvent.ResolveAndResend) } awaitItem().also { state -> assertThat(state.resolveAction).isEqualTo(AsyncAction.Loading) @@ -284,7 +284,7 @@ class ResolveVerifiedUserSendFailurePresenterTest { awaitItem().also { state -> assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.ChangedIdentity(A_USER_ID_2.value)) assertThat(state.resolveAction).isEqualTo(AsyncAction.Success(Unit)) - state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) + state.eventSink(ResolveVerifiedUserSendFailureEvent.ResolveAndResend) } skipItems(3) @@ -312,12 +312,12 @@ class ResolveVerifiedUserSendFailurePresenterTest { val failedMessage = aVerifiedUserChangedIdentityMessage() val initialState = awaitItem() assertThat(initialState.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) - initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(failedMessage)) + initialState.eventSink(ResolveVerifiedUserSendFailureEvent.ComputeForMessage(failedMessage)) skipItems(1) awaitItem().also { state -> assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.ChangedIdentity(A_USER_ID.value)) - state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) + state.eventSink(ResolveVerifiedUserSendFailureEvent.ResolveAndResend) } awaitItem().also { state -> assertThat(state.resolveAction).isEqualTo(AsyncAction.Loading) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureViewTest.kt index df1311b6d4..02767fbeb9 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureViewTest.kt @@ -27,7 +27,7 @@ class ResolveVerifiedUserSendFailureViewTest { @Test fun `clicking on resolve and resend emit the expected event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() rule.setResolveVerifiedUserSendFailureView( state = aResolveVerifiedUserSendFailureState( verifiedUserSendFailure = aChangedIdentitySendFailure(), @@ -36,12 +36,12 @@ class ResolveVerifiedUserSendFailureViewTest { ) rule.clickOn(res = CommonStrings.screen_resolve_send_failure_changed_identity_primary_button_title) - eventsRecorder.assertSingle(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) + eventsRecorder.assertSingle(ResolveVerifiedUserSendFailureEvent.ResolveAndResend) } @Test fun `clicking on retry emit the expected event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() rule.setResolveVerifiedUserSendFailureView( state = aResolveVerifiedUserSendFailureState( verifiedUserSendFailure = aChangedIdentitySendFailure(), @@ -50,7 +50,7 @@ class ResolveVerifiedUserSendFailureViewTest { ) rule.clickOn(res = CommonStrings.action_retry) - eventsRecorder.assertSingle(ResolveVerifiedUserSendFailureEvents.Retry) + eventsRecorder.assertSingle(ResolveVerifiedUserSendFailureEvent.Retry) } private fun AndroidComposeTestRule.setResolveVerifiedUserSendFailureView( From f237b31db9e3586d7ca5a0cbe2f942d56dbf5d9c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 27 Jan 2026 09:59:18 +0100 Subject: [PATCH 11/18] PinnedMessagesBannerEvents -> PinnedMessagesBannerEvent --- ...MessagesBannerEvents.kt => PinnedMessagesBannerEvent.kt} | 4 ++-- .../impl/pinned/banner/PinnedMessagesBannerPresenter.kt | 6 +++--- .../impl/pinned/banner/PinnedMessagesBannerState.kt | 2 +- .../impl/pinned/banner/PinnedMessagesBannerStateProvider.kt | 2 +- .../messages/impl/pinned/banner/PinnedMessagesBannerView.kt | 2 +- .../impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt | 4 ++-- .../impl/pinned/banner/PinnedMessagesBannerViewTest.kt | 6 +++--- 7 files changed, 13 insertions(+), 13 deletions(-) rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/{PinnedMessagesBannerEvents.kt => PinnedMessagesBannerEvent.kt} (74%) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerEvent.kt similarity index 74% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerEvents.kt rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerEvent.kt index d4926404fe..42363c952d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerEvent.kt @@ -8,6 +8,6 @@ package io.element.android.features.messages.impl.pinned.banner -sealed interface PinnedMessagesBannerEvents { - data object MoveToNextPinned : PinnedMessagesBannerEvents +sealed interface PinnedMessagesBannerEvent { + data object MoveToNextPinned : PinnedMessagesBannerEvent } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt index eada4b06d7..088959ea18 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt @@ -58,9 +58,9 @@ class PinnedMessagesBannerPresenter( }, ) - fun handleEvent(event: PinnedMessagesBannerEvents) { + fun handleEvent(event: PinnedMessagesBannerEvent) { when (event) { - is PinnedMessagesBannerEvents.MoveToNextPinned -> { + is PinnedMessagesBannerEvent.MoveToNextPinned -> { val loadedCount = pinnedItems.value.dataOrNull().orEmpty().size currentPinnedMessageIndex = (currentPinnedMessageIndex - 1).mod(loadedCount) } @@ -80,7 +80,7 @@ class PinnedMessagesBannerPresenter( expectedPinnedMessagesCount: Int, pinnedItems: AsyncData>, currentPinnedMessageIndex: Int, - eventSink: (PinnedMessagesBannerEvents) -> Unit + eventSink: (PinnedMessagesBannerEvent) -> Unit ): PinnedMessagesBannerState { return when (pinnedItems) { is AsyncData.Failure, is AsyncData.Uninitialized -> PinnedMessagesBannerState.Hidden diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt index 0ed43376ff..b6deb2edb4 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt @@ -41,6 +41,6 @@ sealed interface PinnedMessagesBannerState { val currentPinnedMessage: PinnedMessagesBannerItem, val currentPinnedMessageIndex: Int, val loadedPinnedMessagesCount: Int, - val eventSink: (PinnedMessagesBannerEvents) -> Unit + val eventSink: (PinnedMessagesBannerEvent) -> Unit ) : Visible } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt index ad7713e6f3..2a2c30bf6b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerStateProvider.kt @@ -50,7 +50,7 @@ internal fun aLoadedPinnedMessagesBannerState( eventId = EventId("\$" + Random.nextInt().toString()), formatted = AnnotatedString(message) ), - eventSink: (PinnedMessagesBannerEvents) -> Unit = {} + eventSink: (PinnedMessagesBannerEvent) -> Unit = {} ) = PinnedMessagesBannerState.Loaded( currentPinnedMessage = currentPinnedMessage, currentPinnedMessageIndex = currentPinnedMessageIndex, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt index ee44f7b95d..21b89da5d1 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt @@ -96,7 +96,7 @@ private fun PinnedMessagesBannerRow( if (state is PinnedMessagesBannerState.Loaded) { analyticsService.captureInteraction(Interaction.Name.PinnedMessageBannerClick) onClick(state.currentPinnedMessage.eventId) - state.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) + state.eventSink(PinnedMessagesBannerEvent.MoveToNextPinned) } }, verticalAlignment = Alignment.CenterVertically, 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 d8269f85d8..1f95baccc9 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 @@ -127,7 +127,7 @@ class PinnedMessagesBannerPresenterTest { assertThat(loadedState.currentPinnedMessageIndex).isEqualTo(1) assertThat(loadedState.loadedPinnedMessagesCount).isEqualTo(2) assertThat(loadedState.currentPinnedMessage.formatted.text).isEqualTo(messageContent2.toString()) - loadedState.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) + loadedState.eventSink(PinnedMessagesBannerEvent.MoveToNextPinned) } awaitItem().also { loadedState -> @@ -135,7 +135,7 @@ class PinnedMessagesBannerPresenterTest { assertThat(loadedState.currentPinnedMessageIndex).isEqualTo(0) assertThat(loadedState.loadedPinnedMessagesCount).isEqualTo(2) assertThat(loadedState.currentPinnedMessage.formatted.text).isEqualTo(messageContent1.toString()) - loadedState.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned) + loadedState.eventSink(PinnedMessagesBannerEvent.MoveToNextPinned) } awaitItem().also { loadedState -> diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerViewTest.kt index a7bbdf999a..2c33e348c0 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerViewTest.kt @@ -33,7 +33,7 @@ class PinnedMessagesBannerViewTest { @Test fun `clicking on the banner invoke expected callback`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val state = aLoadedPinnedMessagesBannerState( eventSink = eventsRecorder ) @@ -44,13 +44,13 @@ class PinnedMessagesBannerViewTest { onClick = callback ) rule.onRoot().performClick() - eventsRecorder.assertSingle(PinnedMessagesBannerEvents.MoveToNextPinned) + eventsRecorder.assertSingle(PinnedMessagesBannerEvent.MoveToNextPinned) } } @Test fun `clicking on view all emit the expected event`() { - val eventsRecorder = EventsRecorder(expectEvents = true) + val eventsRecorder = EventsRecorder(expectEvents = true) val state = aLoadedPinnedMessagesBannerState( eventSink = eventsRecorder ) From e2f281b24827e45d879763f6f45df5691d6a3c8a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 27 Jan 2026 10:00:02 +0100 Subject: [PATCH 12/18] PinnedMessagesListEvents -> PinnedMessagesListEvent --- ...essagesListEvents.kt => PinnedMessagesListEvent.kt} | 4 ++-- .../impl/pinned/list/PinnedMessagesListPresenter.kt | 6 +++--- .../impl/pinned/list/PinnedMessagesListState.kt | 2 +- .../pinned/list/PinnedMessagesListStateProvider.kt | 2 +- .../impl/pinned/list/PinnedMessagesListView.kt | 2 +- .../pinned/list/PinnedMessagesListPresenterTest.kt | 10 +++++----- .../impl/pinned/list/PinnedMessagesListViewTest.kt | 4 ++-- 7 files changed, 15 insertions(+), 15 deletions(-) rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/{PinnedMessagesListEvents.kt => PinnedMessagesListEvent.kt} (84%) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListEvent.kt similarity index 84% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListEvents.kt rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListEvent.kt index 4a3dcf6146..6ad4fbefe6 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListEvent.kt @@ -11,6 +11,6 @@ package io.element.android.features.messages.impl.pinned.list import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.timeline.model.TimelineItem -sealed interface PinnedMessagesListEvents { - data class HandleAction(val action: TimelineItemAction, val event: TimelineItem.Event) : PinnedMessagesListEvents +sealed interface PinnedMessagesListEvent { + data class HandleAction(val action: TimelineItemAction, val event: TimelineItem.Event) : PinnedMessagesListEvent } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt index b2d2caa7f9..f884cdac84 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt @@ -134,9 +134,9 @@ class PinnedMessagesListPresenter( } ) - fun handleEvent(event: PinnedMessagesListEvents) { + fun handleEvent(event: PinnedMessagesListEvent) { when (event) { - is PinnedMessagesListEvents.HandleAction -> sessionCoroutineScope.handleTimelineAction(event.action, event.event) + is PinnedMessagesListEvent.HandleAction -> sessionCoroutineScope.handleTimelineAction(event.action, event.event) } } @@ -232,7 +232,7 @@ class PinnedMessagesListPresenter( linkState: LinkState, userEventPermissions: UserEventPermissions, timelineItems: AsyncData>, - eventSink: (PinnedMessagesListEvents) -> Unit + eventSink: (PinnedMessagesListEvent) -> Unit ): PinnedMessagesListState { return when (timelineItems) { AsyncData.Uninitialized, is AsyncData.Loading -> PinnedMessagesListState.Loading diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListState.kt index c62d293ce8..bf37029eff 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListState.kt @@ -35,7 +35,7 @@ sealed interface PinnedMessagesListState { val actionListState: ActionListState, val linkState: LinkState, val displayThreadSummaries: Boolean, - val eventSink: (PinnedMessagesListEvents) -> Unit, + val eventSink: (PinnedMessagesListEvent) -> Unit, ) : PinnedMessagesListState { val loadedPinnedMessagesCount = timelineItems.count { timelineItem -> timelineItem is TimelineItem.Event } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListStateProvider.kt index a3ed06c53f..bfa9820a44 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListStateProvider.kt @@ -94,7 +94,7 @@ fun aLoadedPinnedMessagesListState( actionListState: ActionListState = anActionListState(), aUserEventPermissions: UserEventPermissions = UserEventPermissions.DEFAULT, displayThreadSummaries: Boolean = false, - eventSink: (PinnedMessagesListEvents) -> Unit = {} + eventSink: (PinnedMessagesListEvent) -> Unit = {} ) = PinnedMessagesListState.Filled( timelineRoomInfo = timelineRoomInfo, timelineProtectionState = timelineProtectionState, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt index 85f709d212..b125bdcf6f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListView.kt @@ -178,7 +178,7 @@ private fun PinnedMessagesListLoaded( ActionListEvent.Clear ) state.eventSink( - PinnedMessagesListEvents.HandleAction( + PinnedMessagesListEvent.HandleAction( action = timelineItemAction, event = event, ) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenterTest.kt index 351f841fcf..8b2da2cefd 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenterTest.kt @@ -152,11 +152,11 @@ class PinnedMessagesListPresenterTest { val eventItem = filledState.timelineItems.first() as TimelineItem.Event pinnedEventsTimeline.unpinEventLambda = successUnpinEventLambda - filledState.eventSink(PinnedMessagesListEvents.HandleAction(TimelineItemAction.Unpin, eventItem)) + filledState.eventSink(PinnedMessagesListEvent.HandleAction(TimelineItemAction.Unpin, eventItem)) advanceUntilIdle() pinnedEventsTimeline.unpinEventLambda = failureUnpinEventLambda - filledState.eventSink(PinnedMessagesListEvents.HandleAction(TimelineItemAction.Unpin, eventItem)) + filledState.eventSink(PinnedMessagesListEvent.HandleAction(TimelineItemAction.Unpin, eventItem)) advanceUntilIdle() cancelAndIgnoreRemainingEvents() @@ -196,7 +196,7 @@ class PinnedMessagesListPresenterTest { skipItems(3) val filledState = awaitItem() as PinnedMessagesListState.Filled val eventItem = filledState.timelineItems.first() as TimelineItem.Event - filledState.eventSink(PinnedMessagesListEvents.HandleAction(TimelineItemAction.ViewInTimeline, eventItem)) + filledState.eventSink(PinnedMessagesListEvent.HandleAction(TimelineItemAction.ViewInTimeline, eventItem)) advanceUntilIdle() cancelAndIgnoreRemainingEvents() assert(onViewInTimelineClickLambda) @@ -225,7 +225,7 @@ class PinnedMessagesListPresenterTest { skipItems(3) val filledState = awaitItem() as PinnedMessagesListState.Filled val eventItem = filledState.timelineItems.first() as TimelineItem.Event - filledState.eventSink(PinnedMessagesListEvents.HandleAction(TimelineItemAction.ViewSource, eventItem)) + filledState.eventSink(PinnedMessagesListEvent.HandleAction(TimelineItemAction.ViewSource, eventItem)) advanceUntilIdle() cancelAndIgnoreRemainingEvents() assert(onShowEventDebugInfoClickLambda) @@ -254,7 +254,7 @@ class PinnedMessagesListPresenterTest { skipItems(3) val filledState = awaitItem() as PinnedMessagesListState.Filled val eventItem = filledState.timelineItems.first() as TimelineItem.Event - filledState.eventSink(PinnedMessagesListEvents.HandleAction(TimelineItemAction.Forward, eventItem)) + filledState.eventSink(PinnedMessagesListEvent.HandleAction(TimelineItemAction.Forward, eventItem)) advanceUntilIdle() cancelAndIgnoreRemainingEvents() assert(onForwardEventClickLambda) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListViewTest.kt index 2f49c9f91f..41671b71c1 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListViewTest.kt @@ -43,7 +43,7 @@ class PinnedMessagesListViewTest { @Test fun `clicking on back calls the expected callback`() { - val eventsRecorder = EventsRecorder(expectEvents = false) + val eventsRecorder = EventsRecorder(expectEvents = false) val state = aLoadedPinnedMessagesListState( eventSink = eventsRecorder ) @@ -58,7 +58,7 @@ class PinnedMessagesListViewTest { @Test fun `click on an event calls the expected callback`() { - val eventsRecorder = EventsRecorder(expectEvents = false) + val eventsRecorder = EventsRecorder(expectEvents = false) val content = aTimelineItemFileContent() val state = aLoadedPinnedMessagesListState( timelineItems = aTimelineItemList(content), From 60b261cd6155646f89c15c63428db46825e499cb Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 27 Jan 2026 10:00:44 +0100 Subject: [PATCH 13/18] ReportMessageEvents -> ReportMessageEvent --- ...ortMessageEvents.kt => ReportMessageEvent.kt} | 10 +++++----- .../impl/report/ReportMessagePresenter.kt | 10 +++++----- .../messages/impl/report/ReportMessageState.kt | 2 +- .../messages/impl/report/ReportMessageView.kt | 8 ++++---- .../impl/report/ReportMessagePresenterTest.kt | 16 ++++++++-------- 5 files changed, 23 insertions(+), 23 deletions(-) rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/{ReportMessageEvents.kt => ReportMessageEvent.kt} (65%) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessageEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessageEvent.kt similarity index 65% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessageEvents.kt rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessageEvent.kt index 966b83d61b..d60029aed6 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessageEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessageEvent.kt @@ -8,9 +8,9 @@ package io.element.android.features.messages.impl.report -sealed interface ReportMessageEvents { - data class UpdateReason(val reason: String) : ReportMessageEvents - data object ToggleBlockUser : ReportMessageEvents - data object Report : ReportMessageEvents - data object ClearError : ReportMessageEvents +sealed interface ReportMessageEvent { + data class UpdateReason(val reason: String) : ReportMessageEvent + data object ToggleBlockUser : ReportMessageEvent + data object Report : ReportMessageEvent + data object ClearError : ReportMessageEvent } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessagePresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessagePresenter.kt index 5dee4f5b79..25a167f2eb 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessagePresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessagePresenter.kt @@ -54,12 +54,12 @@ class ReportMessagePresenter( var blockUser by rememberSaveable { mutableStateOf(false) } var result: MutableState> = remember { mutableStateOf(AsyncAction.Uninitialized) } - fun handleEvent(event: ReportMessageEvents) { + fun handleEvent(event: ReportMessageEvent) { when (event) { - is ReportMessageEvents.UpdateReason -> reason = event.reason - ReportMessageEvents.ToggleBlockUser -> blockUser = !blockUser - ReportMessageEvents.Report -> coroutineScope.report(inputs.eventId, inputs.senderId, reason, blockUser, result) - ReportMessageEvents.ClearError -> result.value = AsyncAction.Uninitialized + is ReportMessageEvent.UpdateReason -> reason = event.reason + ReportMessageEvent.ToggleBlockUser -> blockUser = !blockUser + ReportMessageEvent.Report -> coroutineScope.report(inputs.eventId, inputs.senderId, reason, blockUser, result) + ReportMessageEvent.ClearError -> result.value = AsyncAction.Uninitialized } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessageState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessageState.kt index 38eee9d746..efec4ef998 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessageState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessageState.kt @@ -14,5 +14,5 @@ data class ReportMessageState( val reason: String, val blockUser: Boolean, val result: AsyncAction, - val eventSink: (ReportMessageEvents) -> Unit + val eventSink: (ReportMessageEvent) -> Unit ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessageView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessageView.kt index a2c398776f..dde3f13558 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessageView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessageView.kt @@ -57,7 +57,7 @@ fun ReportMessageView( progressDialog = {}, onSuccess = { onBackClick() }, errorMessage = { stringResource(CommonStrings.error_unknown) }, - onErrorDismiss = { state.eventSink(ReportMessageEvents.ClearError) } + onErrorDismiss = { state.eventSink(ReportMessageEvent.ClearError) } ) Scaffold( @@ -84,7 +84,7 @@ fun ReportMessageView( TextField( value = state.reason, - onValueChange = { state.eventSink(ReportMessageEvents.UpdateReason(it)) }, + onValueChange = { state.eventSink(ReportMessageEvent.UpdateReason(it)) }, placeholder = stringResource(R.string.screen_report_content_hint), minLines = 3, enabled = !isSending, @@ -113,7 +113,7 @@ fun ReportMessageView( Switch( enabled = !isSending, checked = state.blockUser, - onCheckedChange = { state.eventSink(ReportMessageEvents.ToggleBlockUser) }, + onCheckedChange = { state.eventSink(ReportMessageEvent.ToggleBlockUser) }, ) } @@ -125,7 +125,7 @@ fun ReportMessageView( showProgress = isSending, onClick = { focusManager.clearFocus(force = true) - state.eventSink(ReportMessageEvents.Report) + state.eventSink(ReportMessageEvent.Report) }, modifier = Modifier .fillMaxWidth() diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/report/ReportMessagePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/report/ReportMessagePresenterTest.kt index fd8d33d1b6..0bc9cd6585 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/report/ReportMessagePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/report/ReportMessagePresenterTest.kt @@ -51,7 +51,7 @@ class ReportMessagePresenterTest { }.test { val initialState = awaitItem() val reason = "This user is making the chat very toxic." - initialState.eventSink(ReportMessageEvents.UpdateReason(reason)) + initialState.eventSink(ReportMessageEvent.UpdateReason(reason)) assertThat(awaitItem().reason).isEqualTo(reason) } @@ -64,11 +64,11 @@ class ReportMessagePresenterTest { presenter.present() }.test { val initialState = awaitItem() - initialState.eventSink(ReportMessageEvents.ToggleBlockUser) + initialState.eventSink(ReportMessageEvent.ToggleBlockUser) assertThat(awaitItem().blockUser).isTrue() - initialState.eventSink(ReportMessageEvents.ToggleBlockUser) + initialState.eventSink(ReportMessageEvent.ToggleBlockUser) assertThat(awaitItem().blockUser).isFalse() } @@ -87,9 +87,9 @@ class ReportMessagePresenterTest { presenter.present() }.test { val initialState = awaitItem() - initialState.eventSink(ReportMessageEvents.ToggleBlockUser) + initialState.eventSink(ReportMessageEvent.ToggleBlockUser) skipItems(1) - initialState.eventSink(ReportMessageEvents.Report) + initialState.eventSink(ReportMessageEvent.Report) assertThat(awaitItem().result).isInstanceOf(AsyncAction.Loading::class.java) assertThat(awaitItem().result).isInstanceOf(AsyncAction.Success::class.java) reportContentResult.assertions().isCalledOnce() @@ -109,7 +109,7 @@ class ReportMessagePresenterTest { presenter.present() }.test { val initialState = awaitItem() - initialState.eventSink(ReportMessageEvents.Report) + initialState.eventSink(ReportMessageEvent.Report) assertThat(awaitItem().result).isInstanceOf(AsyncAction.Loading::class.java) assertThat(awaitItem().result).isInstanceOf(AsyncAction.Success::class.java) reportContentResult.assertions().isCalledOnce() @@ -129,13 +129,13 @@ class ReportMessagePresenterTest { presenter.present() }.test { val initialState = awaitItem() - initialState.eventSink(ReportMessageEvents.Report) + initialState.eventSink(ReportMessageEvent.Report) assertThat(awaitItem().result).isInstanceOf(AsyncAction.Loading::class.java) val resultState = awaitItem() assertThat(resultState.result).isInstanceOf(AsyncAction.Failure::class.java) reportContentResult.assertions().isCalledOnce() - resultState.eventSink(ReportMessageEvents.ClearError) + resultState.eventSink(ReportMessageEvent.ClearError) assertThat(awaitItem().result).isInstanceOf(AsyncAction.Uninitialized::class.java) } } From cca2fa5ccc6ff27f1d38e745fe7767ed59a6860f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 27 Jan 2026 10:01:38 +0100 Subject: [PATCH 14/18] CustomReactionEvents -> CustomReactionEvent --- .../messages/impl/MessagesStateProvider.kt | 4 ++-- .../android/features/messages/impl/MessagesView.kt | 6 +++--- .../customreaction/CustomReactionBottomSheet.kt | 4 ++-- ...tomReactionEvents.kt => CustomReactionEvent.kt} | 6 +++--- .../customreaction/CustomReactionPresenter.kt | 6 +++--- .../customreaction/CustomReactionState.kt | 2 +- .../features/messages/impl/MessagesViewTest.kt | 14 +++++++------- .../customreaction/CustomReactionPresenterTest.kt | 6 +++--- 8 files changed, 24 insertions(+), 24 deletions(-) rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/{CustomReactionEvents.kt => CustomReactionEvent.kt} (88%) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt index b6d8dcd71c..03d12049cc 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt @@ -28,7 +28,7 @@ import io.element.android.features.messages.impl.pinned.banner.aLoadedPinnedMess import io.element.android.features.messages.impl.timeline.TimelineState import io.element.android.features.messages.impl.timeline.aTimelineItemList import io.element.android.features.messages.impl.timeline.aTimelineState -import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionEvents +import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionEvent import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionState import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryEvents import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryState @@ -196,7 +196,7 @@ fun aReactionSummaryState( fun aCustomReactionState( target: CustomReactionState.Target = CustomReactionState.Target.None, recentEmojis: ImmutableList = persistentListOf(), - eventSink: (CustomReactionEvents) -> Unit = {}, + eventSink: (CustomReactionEvent) -> Unit = {}, ) = CustomReactionState( target = target, recentEmojis = recentEmojis, 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 8094ab938b..32fe8cddf5 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 @@ -75,7 +75,7 @@ import io.element.android.features.messages.impl.timeline.aTimelineItemDaySepara import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.aTimelineState import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionBottomSheet -import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionEvents +import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionEvent import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryEvents import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryView import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheet @@ -191,7 +191,7 @@ fun MessagesView( } fun onMoreReactionsClick(event: TimelineItem.Event) { - state.customReactionState.eventSink(CustomReactionEvents.ShowCustomReactionSheet(event)) + state.customReactionState.eventSink(CustomReactionEvent.ShowCustomReactionSheet(event)) } val expandableState = rememberExpandableBottomSheetLayoutState() @@ -367,7 +367,7 @@ fun MessagesView( } }, onCustomReactionClick = { event -> - state.customReactionState.eventSink(CustomReactionEvents.ShowCustomReactionSheet(event)) + state.customReactionState.eventSink(CustomReactionEvent.ShowCustomReactionSheet(event)) }, onEmojiReactionClick = ::onEmojiReactionClick, onVerifiedUserSendFailureClick = { event -> 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 0226eea7b9..f42a26cf65 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 @@ -35,13 +35,13 @@ fun CustomReactionBottomSheet( val target = state.target as? CustomReactionState.Target.Success fun onDismiss() { - state.eventSink(CustomReactionEvents.DismissCustomReactionSheet) + state.eventSink(CustomReactionEvent.DismissCustomReactionSheet) } fun onEmojiSelectedDismiss(emoji: Emoji) { if (target?.event == null) return sheetState.hide(coroutineScope) { - state.eventSink(CustomReactionEvents.DismissCustomReactionSheet) + state.eventSink(CustomReactionEvent.DismissCustomReactionSheet) onSelectEmoji(target.event.eventOrTransactionId, emoji) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionEvent.kt similarity index 88% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionEvents.kt rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionEvent.kt index b73d1295c4..deaf27739e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionEvent.kt @@ -10,7 +10,7 @@ package io.element.android.features.messages.impl.timeline.components.customreac import io.element.android.features.messages.impl.timeline.model.TimelineItem -sealed interface CustomReactionEvents { - data class ShowCustomReactionSheet(val event: TimelineItem.Event) : CustomReactionEvents - data object DismissCustomReactionSheet : CustomReactionEvents +sealed interface CustomReactionEvent { + data class ShowCustomReactionSheet(val event: TimelineItem.Event) : CustomReactionEvent + data object DismissCustomReactionSheet : CustomReactionEvent } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt index 4ccfc3f883..a1ebb66ea7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt @@ -54,10 +54,10 @@ class CustomReactionPresenter( target.value = CustomReactionState.Target.None } - fun handleEvent(event: CustomReactionEvents) { + fun handleEvent(event: CustomReactionEvent) { when (event) { - is CustomReactionEvents.ShowCustomReactionSheet -> handleShowCustomReactionSheet(event.event) - is CustomReactionEvents.DismissCustomReactionSheet -> handleDismissCustomReactionSheet() + is CustomReactionEvent.ShowCustomReactionSheet -> handleShowCustomReactionSheet(event.event) + is CustomReactionEvent.DismissCustomReactionSheet -> handleDismissCustomReactionSheet() } } val event = (target.value as? CustomReactionState.Target.Success)?.event diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionState.kt index 1d3e3e820e..1897d4e5a7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionState.kt @@ -17,7 +17,7 @@ data class CustomReactionState( val target: Target, val selectedEmoji: ImmutableSet, val recentEmojis: ImmutableList, - val eventSink: (CustomReactionEvents) -> Unit, + val eventSink: (CustomReactionEvent) -> Unit, ) { sealed interface Target { data object None : Target 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 ee272ac6f3..7be3365067 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 @@ -46,7 +46,7 @@ import io.element.android.features.messages.impl.timeline.aTimelineItemList import io.element.android.features.messages.impl.timeline.aTimelineItemReadReceipts import io.element.android.features.messages.impl.timeline.aTimelineRoomInfo import io.element.android.features.messages.impl.timeline.aTimelineState -import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionEvents +import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionEvent import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionState import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryEvents import io.element.android.features.messages.impl.timeline.components.receipt.aReadReceiptData @@ -429,7 +429,7 @@ class MessagesViewTest { @Test fun `clicking on more reaction emits the expected Event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val state = aMessagesState( timelineState = aTimelineState( timelineItems = aTimelineItemList(aTimelineItemTextContent()), @@ -444,12 +444,12 @@ class MessagesViewTest { ) val moreReactionContentDescription = rule.activity.getString(R.string.screen_room_timeline_add_reaction) rule.onAllNodesWithContentDescription(moreReactionContentDescription).onFirst().performClick() - eventsRecorder.assertSingle(CustomReactionEvents.ShowCustomReactionSheet(timelineItem)) + eventsRecorder.assertSingle(CustomReactionEvent.ShowCustomReactionSheet(timelineItem)) } @Test fun `clicking on more reaction from action list emits the expected Event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val state = aMessagesState( timelineState = aTimelineState( timelineItems = aTimelineItemList(aTimelineItemTextContent()), @@ -478,7 +478,7 @@ class MessagesViewTest { rule.onNodeWithContentDescription(moreReactionContentDescription).performClick() // Give time for the close animation to complete rule.mainClock.advanceTimeBy(milliseconds = 1_000) - eventsRecorder.assertSingle(CustomReactionEvents.ShowCustomReactionSheet(timelineItem)) + eventsRecorder.assertSingle(CustomReactionEvent.ShowCustomReactionSheet(timelineItem)) } @Test @@ -512,7 +512,7 @@ class MessagesViewTest { @Test fun `clicking on a custom emoji emits the expected Events`() { val aUnicode = "🙈" - val customReactionStateEventsRecorder = EventsRecorder() + val customReactionStateEventsRecorder = EventsRecorder() val eventsRecorder = EventsRecorder() val state = aMessagesState( eventSink = eventsRecorder, @@ -546,7 +546,7 @@ class MessagesViewTest { rule.onNodeWithText(aUnicode, useUnmergedTree = true).performClick() // Give time for the close animation to complete rule.mainClock.advanceTimeBy(milliseconds = 1_000) - customReactionStateEventsRecorder.assertSingle(CustomReactionEvents.DismissCustomReactionSheet) + customReactionStateEventsRecorder.assertSingle(CustomReactionEvent.DismissCustomReactionSheet) eventsRecorder.assertSingle(MessagesEvent.ToggleReaction(aUnicode, timelineItem.eventOrTransactionId)) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt index a43b4121bb..f5d854b463 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt @@ -40,14 +40,14 @@ class CustomReactionPresenterTest { val initialState = awaitItem() assertThat(initialState.target).isEqualTo(CustomReactionState.Target.None) - initialState.eventSink(CustomReactionEvents.ShowCustomReactionSheet(event)) + initialState.eventSink(CustomReactionEvent.ShowCustomReactionSheet(event)) assertThat(awaitItem().target).isEqualTo(CustomReactionState.Target.Loading(event)) val eventId = (awaitItem().target as? CustomReactionState.Target.Success)?.event?.eventId assertThat(eventId).isEqualTo(AN_EVENT_ID) - initialState.eventSink(CustomReactionEvents.DismissCustomReactionSheet) + initialState.eventSink(CustomReactionEvent.DismissCustomReactionSheet) assertThat(awaitItem().target).isEqualTo(CustomReactionState.Target.None) } } @@ -63,7 +63,7 @@ class CustomReactionPresenterTest { assertThat(initialState.target).isEqualTo(CustomReactionState.Target.None) val key = reactions.reactions.first().key - initialState.eventSink(CustomReactionEvents.ShowCustomReactionSheet(event)) + initialState.eventSink(CustomReactionEvent.ShowCustomReactionSheet(event)) assertThat(awaitItem().target).isEqualTo(CustomReactionState.Target.Loading(event)) From f327461358d6f74af02e035091eb2fe0e8e554e4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 27 Jan 2026 10:02:08 +0100 Subject: [PATCH 15/18] EmojiPickerEvents -> EmojiPickerEvent --- .../timeline/components/customreaction/picker/EmojiPicker.kt | 2 +- .../picker/{EmojiPickerEvents.kt => EmojiPickerEvent.kt} | 4 ++-- .../components/customreaction/picker/EmojiPickerPresenter.kt | 4 ++-- .../components/customreaction/picker/EmojiPickerState.kt | 2 +- .../customreaction/picker/EmojiPickerStateProvider.kt | 2 +- .../customreaction/picker/EmojiPickerPresenterTest.kt | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/{EmojiPickerEvents.kt => EmojiPickerEvent.kt} (88%) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPicker.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPicker.kt index e3bffd2137..0575341d3d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPicker.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPicker.kt @@ -60,7 +60,7 @@ fun EmojiPicker( queryState = state.searchQuery, resultState = state.searchResults, active = state.isSearchActive, - onActiveChange = { state.eventSink(EmojiPickerEvents.ToggleSearchActive(it)) }, + onActiveChange = { state.eventSink(EmojiPickerEvent.ToggleSearchActive(it)) }, windowInsets = WindowInsets(0, 0, 0, 0), placeHolderTitle = stringResource(CommonStrings.emoji_picker_search_placeholder), ) { emojis -> diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerEvent.kt similarity index 88% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerEvents.kt rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerEvent.kt index c353085eac..6ea5eea0f6 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerEvent.kt @@ -8,6 +8,6 @@ package io.element.android.features.messages.impl.timeline.components.customreaction.picker -sealed interface EmojiPickerEvents { - data class ToggleSearchActive(val isActive: Boolean) : EmojiPickerEvents +sealed interface EmojiPickerEvent { + data class ToggleSearchActive(val isActive: Boolean) : EmojiPickerEvent } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerPresenter.kt index 060e890457..3a4cf6c9ce 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerPresenter.kt @@ -93,10 +93,10 @@ class EmojiPickerPresenter( } val isInPreview = LocalInspectionMode.current - fun handleEvent(event: EmojiPickerEvents) { + fun handleEvent(event: EmojiPickerEvent) { when (event) { // For some reason, in preview mode the SearchBar emits this event with an `isActive = true` value automatically - is EmojiPickerEvents.ToggleSearchActive -> if (!isInPreview) { + is EmojiPickerEvent.ToggleSearchActive -> if (!isInPreview) { isSearchActive = event.isActive } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerState.kt index a2ea66a9fb..c1d306dece 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerState.kt @@ -24,7 +24,7 @@ data class EmojiPickerState( val searchQuery: TextFieldState, val isSearchActive: Boolean, val searchResults: SearchBarResultState>, - val eventSink: (EmojiPickerEvents) -> Unit, + val eventSink: (EmojiPickerEvent) -> Unit, ) /** diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerStateProvider.kt index b9de6166a6..958b3849f5 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerStateProvider.kt @@ -73,7 +73,7 @@ internal fun anEmojiPickerState( searchQuery: String = "", isSearchActive: Boolean = false, searchResults: SearchBarResultState> = SearchBarResultState.Initial(), - eventSink: (EmojiPickerEvents) -> Unit = {}, + eventSink: (EmojiPickerEvent) -> Unit = {}, ) = EmojiPickerState( categories = categories, allEmojis = allEmojis, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerPresenterTest.kt index 473abedcfc..541b16b546 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerPresenterTest.kt @@ -66,10 +66,10 @@ class EmojiPickerPresenterTest { val initialState = awaitItem() assertThat(initialState.isSearchActive).isFalse() - initialState.eventSink(EmojiPickerEvents.ToggleSearchActive(true)) + initialState.eventSink(EmojiPickerEvent.ToggleSearchActive(true)) assertThat(awaitItem().isSearchActive).isTrue() - initialState.eventSink(EmojiPickerEvents.ToggleSearchActive(false)) + initialState.eventSink(EmojiPickerEvent.ToggleSearchActive(false)) assertThat(awaitItem().isSearchActive).isFalse() } } From dd7c9dee7878de357357e8f851664e45c20b5516 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 27 Jan 2026 10:02:44 +0100 Subject: [PATCH 16/18] ReactionSummaryEvents -> ReactionSummaryEvent --- .../android/features/messages/impl/MessagesStateProvider.kt | 4 ++-- .../element/android/features/messages/impl/MessagesView.kt | 4 ++-- .../{ReactionSummaryEvents.kt => ReactionSummaryEvent.kt} | 6 +++--- .../components/reactionsummary/ReactionSummaryPresenter.kt | 6 +++--- .../components/reactionsummary/ReactionSummaryState.kt | 2 +- .../components/reactionsummary/ReactionSummaryView.kt | 2 +- .../android/features/messages/impl/MessagesViewTest.kt | 6 +++--- .../reactionsummary/ReactionSummaryPresenterTest.kt | 4 ++-- 8 files changed, 17 insertions(+), 17 deletions(-) rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/{ReactionSummaryEvents.kt => ReactionSummaryEvent.kt} (85%) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt index 03d12049cc..cf46e896b9 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt @@ -30,7 +30,7 @@ import io.element.android.features.messages.impl.timeline.aTimelineItemList import io.element.android.features.messages.impl.timeline.aTimelineState import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionEvent import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionState -import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryEvents +import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryEvent import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryState import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetEvents import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetState @@ -187,7 +187,7 @@ fun aUserEventPermissions( fun aReactionSummaryState( target: ReactionSummaryState.Summary? = null, - eventSink: (ReactionSummaryEvents) -> Unit = {} + eventSink: (ReactionSummaryEvent) -> Unit = {} ) = ReactionSummaryState( target = target, eventSink = eventSink, 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 32fe8cddf5..87efc50528 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 @@ -76,7 +76,7 @@ import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.aTimelineState import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionBottomSheet import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionEvent -import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryEvents +import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryEvent import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryView import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheet import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetEvents @@ -187,7 +187,7 @@ fun MessagesView( fun onEmojiReactionLongClick(emoji: String, event: TimelineItem.Event) { if (event.eventId == null) return - state.reactionSummaryState.eventSink(ReactionSummaryEvents.ShowReactionSummary(event.eventId, event.reactionsState.reactions, emoji)) + state.reactionSummaryState.eventSink(ReactionSummaryEvent.ShowReactionSummary(event.eventId, event.reactionsState.reactions, emoji)) } fun onMoreReactionsClick(event: TimelineItem.Event) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryEvent.kt similarity index 85% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryEvents.kt rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryEvent.kt index 987b61e505..0203eb71b0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryEvent.kt @@ -11,7 +11,7 @@ package io.element.android.features.messages.impl.timeline.components.reactionsu import io.element.android.features.messages.impl.timeline.model.AggregatedReaction import io.element.android.libraries.matrix.api.core.EventId -sealed interface ReactionSummaryEvents { - data object Clear : ReactionSummaryEvents - data class ShowReactionSummary(val eventId: EventId, val reactions: List, val selectedKey: String) : ReactionSummaryEvents +sealed interface ReactionSummaryEvent { + data object Clear : ReactionSummaryEvent + data class ShowReactionSummary(val eventId: EventId, val reactions: List, val selectedKey: String) : ReactionSummaryEvent } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenter.kt index a95fe57bc7..d212aa6ff3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenter.kt @@ -37,14 +37,14 @@ class ReactionSummaryPresenter( } val targetWithAvatars = populateSenderAvatars(members = membersState.roomMembers().orEmpty().toImmutableList(), summary = target.value) - fun handleEvent(event: ReactionSummaryEvents) { + fun handleEvent(event: ReactionSummaryEvent) { when (event) { - is ReactionSummaryEvents.ShowReactionSummary -> target.value = ReactionSummaryState.Summary( + is ReactionSummaryEvent.ShowReactionSummary -> target.value = ReactionSummaryState.Summary( reactions = event.reactions.toImmutableList(), selectedKey = event.selectedKey, selectedEventId = event.eventId ) - ReactionSummaryEvents.Clear -> target.value = null + ReactionSummaryEvent.Clear -> target.value = null } } return ReactionSummaryState( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryState.kt index cf5342f853..36ba50a237 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryState.kt @@ -14,7 +14,7 @@ import kotlinx.collections.immutable.ImmutableList data class ReactionSummaryState( val target: Summary?, - val eventSink: (ReactionSummaryEvents) -> Unit + val eventSink: (ReactionSummaryEvent) -> Unit ) { data class Summary( val reactions: ImmutableList, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryView.kt index 944fd9a195..c138378a3a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryView.kt @@ -84,7 +84,7 @@ fun ReactionSummaryView( modifier: Modifier = Modifier, ) { fun onDismiss() { - state.eventSink(ReactionSummaryEvents.Clear) + state.eventSink(ReactionSummaryEvent.Clear) } if (state.target != null) { 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 7be3365067..abac682a10 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 @@ -48,7 +48,7 @@ import io.element.android.features.messages.impl.timeline.aTimelineRoomInfo import io.element.android.features.messages.impl.timeline.aTimelineState import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionEvent import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionState -import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryEvents +import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryEvent import io.element.android.features.messages.impl.timeline.components.receipt.aReadReceiptData import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetEvents import io.element.android.features.messages.impl.timeline.model.TimelineItem @@ -406,7 +406,7 @@ class MessagesViewTest { @Test fun `long clicking on a reaction emits the expected Event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val state = aMessagesState( timelineState = aTimelineState( timelineItems = aTimelineItemList(aTimelineItemTextContent()), @@ -424,7 +424,7 @@ class MessagesViewTest { text = "👍️", useUnmergedTree = true, ).onFirst().performTouchInput { longClick() } - eventsRecorder.assertSingle(ReactionSummaryEvents.ShowReactionSummary(timelineItem.eventId!!, timelineItem.reactionsState.reactions, "👍️")) + eventsRecorder.assertSingle(ReactionSummaryEvent.ShowReactionSummary(timelineItem.eventId!!, timelineItem.reactionsState.reactions, "👍️")) } @Test diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenterTest.kt index a05b7da5f5..4621a87e75 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenterTest.kt @@ -32,7 +32,7 @@ class ReactionSummaryPresenterTest { private val aggregatedReaction = anAggregatedReaction(userId = A_USER_ID, key = "👍", isHighlighted = true) private val roomMember = aRoomMember(userId = A_USER_ID, avatarUrl = AN_AVATAR_URL, displayName = A_USER_NAME) - private val summaryEvent = ReactionSummaryEvents.ShowReactionSummary(AN_EVENT_ID, listOf(aggregatedReaction), aggregatedReaction.key) + private val summaryEvent = ReactionSummaryEvent.ShowReactionSummary(AN_EVENT_ID, listOf(aggregatedReaction), aggregatedReaction.key) private val room = FakeBaseRoom().apply { givenRoomMembersState(RoomMembersState.Ready(persistentListOf(roomMember))) } @@ -49,7 +49,7 @@ class ReactionSummaryPresenterTest { initialState.eventSink(summaryEvent) assertThat(awaitItem().target).isNotNull() - initialState.eventSink(ReactionSummaryEvents.Clear) + initialState.eventSink(ReactionSummaryEvent.Clear) assertThat(awaitItem().target).isNull() } } From c74169d8931cee597d8b0fb852f60f48c75507ff Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 27 Jan 2026 10:03:28 +0100 Subject: [PATCH 17/18] ReadReceiptBottomSheetEvents -> ReadReceiptBottomSheetEvent --- .../android/features/messages/impl/MessagesStateProvider.kt | 4 ++-- .../element/android/features/messages/impl/MessagesView.kt | 4 ++-- .../receipt/bottomsheet/ReadReceiptBottomSheet.kt | 4 ++-- ...tBottomSheetEvents.kt => ReadReceiptBottomSheetEvent.kt} | 6 +++--- .../receipt/bottomsheet/ReadReceiptBottomSheetPresenter.kt | 6 +++--- .../receipt/bottomsheet/ReadReceiptBottomSheetState.kt | 2 +- .../android/features/messages/impl/MessagesViewTest.kt | 6 +++--- .../bottomsheet/ReadReceiptBottomSheetPresenterTest.kt | 6 +++--- 8 files changed, 19 insertions(+), 19 deletions(-) rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/{ReadReceiptBottomSheetEvents.kt => ReadReceiptBottomSheetEvent.kt} (78%) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt index cf46e896b9..edf61d90cd 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt @@ -32,7 +32,7 @@ import io.element.android.features.messages.impl.timeline.components.customreact import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionState import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryEvent import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryState -import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetEvents +import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetEvent import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetState import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent @@ -206,7 +206,7 @@ fun aCustomReactionState( fun aReadReceiptBottomSheetState( selectedEvent: TimelineItem.Event? = null, - eventSink: (ReadReceiptBottomSheetEvents) -> Unit = {}, + eventSink: (ReadReceiptBottomSheetEvent) -> Unit = {}, ) = ReadReceiptBottomSheetState( selectedEvent = selectedEvent, eventSink = eventSink, 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 87efc50528..437e652cff 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 @@ -79,7 +79,7 @@ import io.element.android.features.messages.impl.timeline.components.customreact import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryEvent import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryView import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheet -import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetEvents +import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetEvent import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemStateEventContent @@ -259,7 +259,7 @@ fun MessagesView( onReactionLongClick = ::onEmojiReactionLongClick, onMoreReactionsClick = ::onMoreReactionsClick, onReadReceiptClick = { event -> - state.readReceiptBottomSheetState.eventSink(ReadReceiptBottomSheetEvents.EventSelected(event)) + state.readReceiptBottomSheetState.eventSink(ReadReceiptBottomSheetEvent.EventSelected(event)) }, onSendLocationClick = onSendLocationClick, onCreatePollClick = onCreatePollClick, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheet.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheet.kt index 57c46a6326..b65e326045 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheet.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheet.kt @@ -55,7 +55,7 @@ internal fun ReadReceiptBottomSheet( onDismissRequest = { coroutineScope.launch { sheetState.hide() - state.eventSink(ReadReceiptBottomSheetEvents.Dismiss) + state.eventSink(ReadReceiptBottomSheetEvent.Dismiss) } } ) { @@ -64,7 +64,7 @@ internal fun ReadReceiptBottomSheet( onUserDataClick = { coroutineScope.launch { sheetState.hide() - state.eventSink(ReadReceiptBottomSheetEvents.Dismiss) + state.eventSink(ReadReceiptBottomSheetEvent.Dismiss) onUserDataClick.invoke(it) } }, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetEvent.kt similarity index 78% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetEvents.kt rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetEvent.kt index 04723d0214..9c605c42df 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetEvent.kt @@ -10,7 +10,7 @@ package io.element.android.features.messages.impl.timeline.components.receipt.bo import io.element.android.features.messages.impl.timeline.model.TimelineItem -sealed interface ReadReceiptBottomSheetEvents { - data class EventSelected(val event: TimelineItem.Event) : ReadReceiptBottomSheetEvents - data object Dismiss : ReadReceiptBottomSheetEvents +sealed interface ReadReceiptBottomSheetEvent { + data class EventSelected(val event: TimelineItem.Event) : ReadReceiptBottomSheetEvent + data object Dismiss : ReadReceiptBottomSheetEvent } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetPresenter.kt index e1264b77e7..b5b4168a28 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetPresenter.kt @@ -23,13 +23,13 @@ class ReadReceiptBottomSheetPresenter : Presenter { override fun present(): ReadReceiptBottomSheetState { var selectedEvent: TimelineItem.Event? by remember { mutableStateOf(null) } - fun handleEvent(event: ReadReceiptBottomSheetEvents) { + fun handleEvent(event: ReadReceiptBottomSheetEvent) { @Suppress("LiftReturnOrAssignment") when (event) { - is ReadReceiptBottomSheetEvents.EventSelected -> { + is ReadReceiptBottomSheetEvent.EventSelected -> { selectedEvent = event.event } - ReadReceiptBottomSheetEvents.Dismiss -> { + ReadReceiptBottomSheetEvent.Dismiss -> { selectedEvent = null } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetState.kt index 7ec4107f8f..d708399f86 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetState.kt @@ -12,5 +12,5 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItem data class ReadReceiptBottomSheetState( val selectedEvent: TimelineItem.Event?, - val eventSink: (ReadReceiptBottomSheetEvents) -> Unit, + val eventSink: (ReadReceiptBottomSheetEvent) -> Unit, ) 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 abac682a10..c6d974bae7 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 @@ -50,7 +50,7 @@ import io.element.android.features.messages.impl.timeline.components.customreact import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionState import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryEvent import io.element.android.features.messages.impl.timeline.components.receipt.aReadReceiptData -import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetEvents +import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetEvent import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent import io.element.android.libraries.matrix.api.core.RoomId @@ -216,7 +216,7 @@ class MessagesViewTest { @Test @Config(qualifiers = "h1024dp") fun `clicking on a read receipt list emits the expected Event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val state = aMessagesState( timelineState = aTimelineState( renderReadReceipts = true, @@ -239,7 +239,7 @@ class MessagesViewTest { state = state, ) rule.onNodeWithTag(TestTags.messageReadReceipts.value, useUnmergedTree = true).performClick() - eventsRecorder.assertSingle(ReadReceiptBottomSheetEvents.EventSelected(timelineItem)) + eventsRecorder.assertSingle(ReadReceiptBottomSheetEvent.EventSelected(timelineItem)) } @Test diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetPresenterTest.kt index d39500fec2..0a10188f48 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetPresenterTest.kt @@ -30,7 +30,7 @@ class ReadReceiptBottomSheetPresenterTest { }.test { val initialState = awaitItem() val selectedEvent = aTimelineItemEvent() - initialState.eventSink(ReadReceiptBottomSheetEvents.EventSelected(selectedEvent)) + initialState.eventSink(ReadReceiptBottomSheetEvent.EventSelected(selectedEvent)) assertThat(awaitItem().selectedEvent).isSameInstanceAs(selectedEvent) } } @@ -43,9 +43,9 @@ class ReadReceiptBottomSheetPresenterTest { }.test { val initialState = awaitItem() val selectedEvent = aTimelineItemEvent() - initialState.eventSink(ReadReceiptBottomSheetEvents.EventSelected(selectedEvent)) + initialState.eventSink(ReadReceiptBottomSheetEvent.EventSelected(selectedEvent)) skipItems(1) - initialState.eventSink(ReadReceiptBottomSheetEvents.Dismiss) + initialState.eventSink(ReadReceiptBottomSheetEvent.Dismiss) assertThat(awaitItem().selectedEvent).isNull() } } From 847e62a5ac9d90f8915ea9d0a64065e2843e2d9e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 27 Jan 2026 10:08:25 +0100 Subject: [PATCH 18/18] Use presenter test extension. --- .../AttachmentsPreviewPresenterTest.kt | 51 ++----- ...tMediaOptimizationSelectorPresenterTest.kt | 40 ++---- .../MessageComposerPresenterTest.kt | 132 +++++------------- .../impl/report/ReportMessagePresenterTest.kt | 28 +--- .../CustomReactionPresenterTest.kt | 12 +- .../ReactionSummaryPresenterTest.kt | 12 +- .../ReadReceiptBottomSheetPresenterTest.kt | 12 +- .../typing/TypingNotificationPresenterTest.kt | 28 +--- 8 files changed, 78 insertions(+), 237 deletions(-) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt index 1e4bea0b4a..384b78471d 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/AttachmentsPreviewPresenterTest.kt @@ -11,9 +11,6 @@ package io.element.android.features.messages.impl.attachments import android.net.Uri -import app.cash.molecule.RecompositionMode -import app.cash.molecule.moleculeFlow -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.impl.attachments.preview.AttachmentsPreviewEvent import io.element.android.features.messages.impl.attachments.preview.AttachmentsPreviewPresenter @@ -111,9 +108,7 @@ class AttachmentsPreviewPresenterTest { mediaPreProcessor = mediaPreProcessor, onDoneListener = { onDoneListener() }, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) @@ -147,9 +142,7 @@ class AttachmentsPreviewPresenterTest { mediaPreProcessor = mediaPreProcessor, onDoneListener = { onDoneListener() }, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) // Pre-processing finishes @@ -185,9 +178,7 @@ class AttachmentsPreviewPresenterTest { mediaPreProcessor = mediaPreProcessor, onDoneListener = { onDoneListener() }, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) assertThat(awaitItem().sendActionState).isEqualTo(SendActionState.Sending.Processing(displayProgress = false)) @@ -216,9 +207,7 @@ class AttachmentsPreviewPresenterTest { }, onDoneListener = { onDoneListener() }, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) initialState.eventSink(AttachmentsPreviewEvent.SendAttachment) @@ -241,9 +230,7 @@ class AttachmentsPreviewPresenterTest { }, onDoneListener = { onDoneListener() }, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) // Pre-processing finishes @@ -265,9 +252,7 @@ class AttachmentsPreviewPresenterTest { temporaryUriDeleter = FakeTemporaryUriDeleter(deleteCallback), onDoneListener = { onDoneListener() }, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) initialState.eventSink(AttachmentsPreviewEvent.CancelAndDismiss) @@ -298,9 +283,7 @@ class AttachmentsPreviewPresenterTest { mediaPreProcessor = mediaPreProcessor, onDoneListener = { onDoneListener() }, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) initialState.textEditorState.setMarkdown(A_CAPTION) @@ -341,9 +324,7 @@ class AttachmentsPreviewPresenterTest { mediaPreProcessor = mediaPreProcessor, onDoneListener = { onDoneListener() }, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) initialState.textEditorState.setMarkdown(A_CAPTION) @@ -418,9 +399,7 @@ class AttachmentsPreviewPresenterTest { }, ) val presenter = createAttachmentsPreviewPresenter(room = room, onDoneListener = onDoneListenerResult) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) initialState.eventSink(AttachmentsPreviewEvent.SendAttachment) @@ -453,9 +432,7 @@ class AttachmentsPreviewPresenterTest { ), onDoneListener = onDoneListenerResult, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.sendActionState).isEqualTo(SendActionState.Idle) initialState.eventSink(AttachmentsPreviewEvent.SendAttachment) @@ -503,9 +480,7 @@ class AttachmentsPreviewPresenterTest { } ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { assertThat(localMedia.info.fileSize).isGreaterThan(maxUploadSize) consumeItemsUntilPredicate { it.mediaOptimizationSelectorState.maxUploadSize.isSuccess() } @@ -563,9 +538,7 @@ class AttachmentsPreviewPresenterTest { } ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { consumeItemsUntilPredicate { it.mediaOptimizationSelectorState.maxUploadSize.isSuccess() && it.mediaOptimizationSelectorState.videoSizeEstimations.dataOrNull()?.isNotEmpty() == true diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/video/DefaultMediaOptimizationSelectorPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/video/DefaultMediaOptimizationSelectorPresenterTest.kt index 96cc93ea3d..106fff7375 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/video/DefaultMediaOptimizationSelectorPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/video/DefaultMediaOptimizationSelectorPresenterTest.kt @@ -11,9 +11,6 @@ package io.element.android.features.messages.impl.attachments.video import android.net.Uri import android.util.Size import androidx.test.ext.junit.runners.AndroidJUnit4 -import app.cash.molecule.RecompositionMode -import app.cash.molecule.moleculeFlow -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.test.attachments.video.FakeVideoMetadataExtractor import io.element.android.features.messages.test.attachments.video.FakeVideoMetadataExtractorFactory @@ -29,6 +26,7 @@ import io.element.android.libraries.mediaviewer.api.local.LocalMedia import io.element.android.libraries.mediaviewer.test.viewer.aLocalMedia import io.element.android.libraries.preferences.api.store.VideoCompressionPreset import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.test import io.mockk.mockk import kotlinx.coroutines.test.runTest import org.junit.Rule @@ -46,9 +44,7 @@ class DefaultMediaOptimizationSelectorPresenterTest { @Test fun `present - initial state`() = runTest { val presenter = createDefaultMediaOptimizationSelectorPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { awaitItem().run { // Loading assertThat(videoSizeEstimations).isInstanceOf(AsyncData.Loading::class.java) @@ -77,9 +73,7 @@ class DefaultMediaOptimizationSelectorPresenterTest { val presenter = createDefaultMediaOptimizationSelectorPresenter( localMedia = aLocalMedia(mockMediaUrl, anImageMediaInfo()) ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { // Skip loading state skipItems(1) @@ -94,9 +88,7 @@ class DefaultMediaOptimizationSelectorPresenterTest { @Test fun `present - OpenVideoPresetSelectorDialog displays it, DismissVideoPresetSelectorDialog hides it`() = runTest { val presenter = createDefaultMediaOptimizationSelectorPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { // Skip loading state val eventSink = awaitItem().eventSink @@ -115,9 +107,7 @@ class DefaultMediaOptimizationSelectorPresenterTest { @Test fun `present - SelectVideoPreset sets it and dismisses the dialog`() = runTest { val presenter = createDefaultMediaOptimizationSelectorPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { // Skip loading state val eventSink = awaitItem().eventSink @@ -139,9 +129,7 @@ class DefaultMediaOptimizationSelectorPresenterTest { val presenter = createDefaultMediaOptimizationSelectorPresenter( mediaExtractorFactory = FakeVideoMetadataExtractorFactory(FakeVideoMetadataExtractor(sizeResult = Result.failure(AN_EXCEPTION))), ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { // Skip loading state val eventSink = awaitItem().eventSink @@ -163,9 +151,7 @@ class DefaultMediaOptimizationSelectorPresenterTest { ) ), ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { // Skip loading and loaded states val eventSink = awaitItem().eventSink skipItems(1) @@ -188,9 +174,7 @@ class DefaultMediaOptimizationSelectorPresenterTest { val presenter = createDefaultMediaOptimizationSelectorPresenter( localMedia = aLocalMedia(mockMediaUrl, anImageMediaInfo()), ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { // Skip loading state val eventSink = awaitItem().eventSink @@ -207,9 +191,7 @@ class DefaultMediaOptimizationSelectorPresenterTest { val presenter = createDefaultMediaOptimizationSelectorPresenter( maxUploadSizeProvider = MaxUploadSizeProvider { Result.failure(AN_EXCEPTION) } ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { // Skip loading and loaded state skipItems(1) assertThat(awaitItem().maxUploadSize.dataOrNull()).isEqualTo(1024 * 1024 * 100) @@ -221,9 +203,7 @@ class DefaultMediaOptimizationSelectorPresenterTest { val presenter = createDefaultMediaOptimizationSelectorPresenter( featureFlagService = FakeFeatureFlagService(mapOf(FeatureFlags.SelectableMediaQuality.key to false)), ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { // Skip loading and loaded state skipItems(1) assertThat(awaitItem().displayMediaSelectorViews).isFalse() diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt index 2feafbc9e5..e16236f109 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt @@ -137,9 +137,7 @@ class MessageComposerPresenterTest { @Test fun `present - initial state`() = runTest { val presenter = createPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() assertThat(initialState.isFullScreen).isFalse() assertThat(initialState.textEditorState.messageHtml()).isEqualTo("") @@ -152,9 +150,7 @@ class MessageComposerPresenterTest { @Test fun `present - toggle fullscreen`() = runTest { val presenter = createPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink.invoke(MessageComposerEvent.ToggleFullScreenState) val fullscreenState = awaitItem() @@ -168,9 +164,7 @@ class MessageComposerPresenterTest { @Test fun `present - change message`() = runTest { val presenter = createPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.textEditorState.setHtml(A_MESSAGE) assertThat(initialState.textEditorState.messageHtml()).isEqualTo(A_MESSAGE) @@ -347,9 +341,7 @@ class MessageComposerPresenterTest { @Test fun `present - change mode to reply`() = runTest { val presenter = createPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { var state = awaitFirstItem() val mode = aReplyMode() state.eventSink.invoke(MessageComposerEvent.SetMode(mode)) @@ -363,9 +355,7 @@ class MessageComposerPresenterTest { @Test fun `present - cancel reply`() = runTest { val presenter = createPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { var state = awaitFirstItem() val mode = aReplyMode() state.eventSink.invoke(MessageComposerEvent.SetMode(mode)) @@ -625,9 +615,7 @@ class MessageComposerPresenterTest { val presenter = createPresenter( joinedRoom, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() assertThat(initialState.textEditorState.messageHtml()).isEqualTo("") val mode = aReplyMode() @@ -661,9 +649,7 @@ class MessageComposerPresenterTest { @Test fun `present - Open attachments menu`() = runTest { val presenter = createPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() assertThat(initialState.showAttachmentSourcePicker).isFalse() initialState.eventSink(MessageComposerEvent.AddAttachment) @@ -674,9 +660,7 @@ class MessageComposerPresenterTest { @Test fun `present - Dismiss attachments menu`() = runTest { val presenter = createPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink(MessageComposerEvent.AddAttachment) skipItems(1) @@ -717,9 +701,7 @@ class MessageComposerPresenterTest { ) ) ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink(MessageComposerEvent.PickAttachmentSource.FromGallery) onPreviewAttachmentLambda.assertions().isCalledOnce() @@ -758,9 +740,7 @@ class MessageComposerPresenterTest { ) ) ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink(MessageComposerEvent.PickAttachmentSource.FromGallery) onPreviewAttachmentLambda.assertions().isCalledOnce() @@ -774,9 +754,7 @@ class MessageComposerPresenterTest { givenResult(null) // Simulate a user canceling the flow givenMimeType(MimeTypes.Images) } - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink(MessageComposerEvent.PickAttachmentSource.FromGallery) // No crashes here, otherwise it fails @@ -796,9 +774,7 @@ class MessageComposerPresenterTest { room = room, navigator = navigator, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink(MessageComposerEvent.PickAttachmentSource.FromFiles) onPreviewAttachmentLambda.assertions().isCalledOnce() @@ -811,9 +787,7 @@ class MessageComposerPresenterTest { typingNoticeResult = { Result.success(Unit) } ) val presenter = createPresenter(room = room) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink(MessageComposerEvent.AddAttachment) val attachmentOpenState = awaitItem() @@ -830,9 +804,7 @@ class MessageComposerPresenterTest { typingNoticeResult = { Result.success(Unit) } ) val presenter = createPresenter(room = room) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink(MessageComposerEvent.AddAttachment) val attachmentOpenState = awaitItem() @@ -858,9 +830,7 @@ class MessageComposerPresenterTest { permissionPresenter = permissionPresenter, navigator = navigator, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink(MessageComposerEvent.PickAttachmentSource.PhotoFromCamera) onPreviewAttachmentLambda.assertions().isCalledOnce() @@ -882,9 +852,7 @@ class MessageComposerPresenterTest { permissionPresenter = permissionPresenter, navigator = navigator, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink(MessageComposerEvent.PickAttachmentSource.PhotoFromCamera) permissionPresenter.setPermissionGranted() @@ -908,9 +876,7 @@ class MessageComposerPresenterTest { permissionPresenter = permissionPresenter, navigator = navigator, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink(MessageComposerEvent.PickAttachmentSource.VideoFromCamera) onPreviewAttachmentLambda.assertions().isCalledOnce() @@ -932,9 +898,7 @@ class MessageComposerPresenterTest { permissionPresenter = permissionPresenter, navigator = navigator, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink(MessageComposerEvent.PickAttachmentSource.VideoFromCamera) val permissionState = awaitItem() @@ -949,9 +913,7 @@ class MessageComposerPresenterTest { fun `present - errors are tracked`() = runTest { val testException = Exception("Test error") val presenter = createPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink(MessageComposerEvent.Error(testException)) assertThat(analyticsService.trackedErrors).containsExactly(testException) @@ -961,9 +923,7 @@ class MessageComposerPresenterTest { @Test fun `present - ToggleTextFormatting toggles text formatting`() = runTest { val presenter = createPresenter(isRichTextEditorEnabled = false) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() assertThat(initialState.showTextFormatting).isFalse() initialState.eventSink(MessageComposerEvent.AddAttachment) @@ -1008,9 +968,7 @@ class MessageComposerPresenterTest { givenRoomInfo(aRoomInfo(isDirect = false)) } val presenter = createPresenter(room) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() // A null suggestion (no suggestion was received) returns nothing @@ -1062,9 +1020,7 @@ class MessageComposerPresenterTest { givenRoomInfo(aRoomInfo(isDirect = false)) } val presenter = createPresenter(room) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() // An empty suggestion returns the joined members that are not the current user, but not the room initialState.eventSink(MessageComposerEvent.SuggestionReceived(Suggestion(0, 0, SuggestionType.Mention, ""))) @@ -1099,9 +1055,7 @@ class MessageComposerPresenterTest { ) } val presenter = createPresenter(room) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() // An empty suggestion returns the joined members that are not the current user, but not the room initialState.eventSink(MessageComposerEvent.SuggestionReceived(Suggestion(0, 0, SuggestionType.Mention, ""))) @@ -1119,9 +1073,7 @@ class MessageComposerPresenterTest { } ) ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.textEditorState.setHtml("Hey @bo") initialState.eventSink(MessageComposerEvent.InsertSuggestion(ResolvedSuggestion.Member(aRoomMember(userId = A_USER_ID_2)))) @@ -1153,9 +1105,7 @@ class MessageComposerPresenterTest { typingNoticeResult = { Result.success(Unit) } ) val presenter = createPresenter(room = room) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() // Check intentional mentions on message sent @@ -1242,9 +1192,7 @@ class MessageComposerPresenterTest { typingNoticeResult = typingNoticeResult, ) val presenter = createPresenter(room = room) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() typingNoticeResult.assertions().isNeverCalled() initialState.eventSink.invoke(MessageComposerEvent.TypingNotice(true)) @@ -1268,9 +1216,7 @@ class MessageComposerPresenterTest { isSendTypingNotificationsEnabled = false ) val presenter = createPresenter(room = room, sessionPreferencesStore = store) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() typingNoticeResult.assertions().isNeverCalled() initialState.eventSink.invoke(MessageComposerEvent.TypingNotice(true)) @@ -1286,9 +1232,7 @@ class MessageComposerPresenterTest { this.loadDraftLambda = loadDraftLambda } val presenter = createPresenter(draftService = composerDraftService) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { awaitFirstItem() assert(loadDraftLambda) .isCalledOnce() @@ -1311,9 +1255,7 @@ class MessageComposerPresenterTest { draftService = composerDraftService, permalinkBuilder = permalinkBuilder, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(2) awaitItem().also { state -> assertThat(state.textEditorState.messageMarkdown(permalinkBuilder)).isEqualTo(A_MESSAGE) @@ -1344,9 +1286,7 @@ class MessageComposerPresenterTest { draftService = composerDraftService, permalinkBuilder = permalinkBuilder, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) awaitItem().also { state -> assertThat(state.showTextFormatting).isTrue() @@ -1377,9 +1317,7 @@ class MessageComposerPresenterTest { draftService = composerDraftService, permalinkBuilder = permalinkBuilder, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(2) awaitItem().also { state -> assertThat(state.showTextFormatting).isFalse() @@ -1423,9 +1361,7 @@ class MessageComposerPresenterTest { draftService = composerDraftService, permalinkBuilder = permalinkBuilder, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(2) awaitItem().also { state -> assertThat(state.showTextFormatting).isFalse() @@ -1452,9 +1388,7 @@ class MessageComposerPresenterTest { this.saveDraftLambda = saveDraftLambda } val presenter = createPresenter(draftService = composerDraftService) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitFirstItem() initialState.eventSink.invoke(MessageComposerEvent.SaveDraft) advanceUntilIdle() diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/report/ReportMessagePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/report/ReportMessagePresenterTest.kt index 0bc9cd6585..69cf3b04cd 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/report/ReportMessagePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/report/ReportMessagePresenterTest.kt @@ -8,9 +8,6 @@ package io.element.android.features.messages.impl.report -import app.cash.molecule.RecompositionMode -import app.cash.molecule.moleculeFlow -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher @@ -22,6 +19,7 @@ import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.test import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -33,9 +31,7 @@ class ReportMessagePresenterTest { @Test fun `presenter - initial state`() = runTest { val presenter = createReportMessagePresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.reason).isEmpty() assertThat(initialState.blockUser).isFalse() @@ -46,9 +42,7 @@ class ReportMessagePresenterTest { @Test fun `presenter - update reason`() = runTest { val presenter = createReportMessagePresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val reason = "This user is making the chat very toxic." initialState.eventSink(ReportMessageEvent.UpdateReason(reason)) @@ -60,9 +54,7 @@ class ReportMessagePresenterTest { @Test fun `presenter - toggle block user`() = runTest { val presenter = createReportMessagePresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() initialState.eventSink(ReportMessageEvent.ToggleBlockUser) @@ -83,9 +75,7 @@ class ReportMessagePresenterTest { reportContentResult = reportContentResult ) val presenter = createReportMessagePresenter(joinedRoom = room) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() initialState.eventSink(ReportMessageEvent.ToggleBlockUser) skipItems(1) @@ -105,9 +95,7 @@ class ReportMessagePresenterTest { reportContentResult = reportContentResult ) val presenter = createReportMessagePresenter(joinedRoom = room) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() initialState.eventSink(ReportMessageEvent.Report) assertThat(awaitItem().result).isInstanceOf(AsyncAction.Loading::class.java) @@ -125,9 +113,7 @@ class ReportMessagePresenterTest { reportContentResult = reportContentResult ) val presenter = createReportMessagePresenter(joinedRoom = room) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() initialState.eventSink(ReportMessageEvent.Report) assertThat(awaitItem().result).isInstanceOf(AsyncAction.Loading::class.java) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt index f5d854b463..e3317b3d42 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt @@ -8,15 +8,13 @@ package io.element.android.features.messages.impl.timeline.components.customreaction -import app.cash.molecule.RecompositionMode -import app.cash.molecule.moleculeFlow -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.aTimelineItemReactions import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.recentemojis.test.FakeEmojibaseProvider import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.test import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.test.runTest import org.junit.Rule @@ -33,9 +31,7 @@ class CustomReactionPresenterTest { @Test fun `present - handle selecting and de-selecting an event`() = runTest { - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val event = aTimelineItemEvent(eventId = AN_EVENT_ID) val initialState = awaitItem() assertThat(initialState.target).isEqualTo(CustomReactionState.Target.None) @@ -54,9 +50,7 @@ class CustomReactionPresenterTest { @Test fun `present - handle selected emojis`() = runTest { - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val reactions = aTimelineItemReactions(count = 1, isHighlighted = true) val event = aTimelineItemEvent(eventId = AN_EVENT_ID, timelineItemReactions = reactions) val initialState = awaitItem() diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenterTest.kt index 4621a87e75..f42f47adc3 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenterTest.kt @@ -8,9 +8,6 @@ package io.element.android.features.messages.impl.timeline.components.reactionsummary -import app.cash.molecule.RecompositionMode -import app.cash.molecule.moleculeFlow -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.impl.timeline.model.anAggregatedReaction import io.element.android.libraries.matrix.api.room.RoomMembersState @@ -21,6 +18,7 @@ import io.element.android.libraries.matrix.test.A_USER_NAME import io.element.android.libraries.matrix.test.room.FakeBaseRoom import io.element.android.libraries.matrix.test.room.aRoomMember import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.test import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.test.runTest import org.junit.Rule @@ -40,9 +38,7 @@ class ReactionSummaryPresenterTest { @Test fun `present - handle showing and hiding the reaction summary`() = runTest { - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.target).isNull() @@ -56,9 +52,7 @@ class ReactionSummaryPresenterTest { @Test fun `present - handle reaction summary content and avatars populated`() = runTest { - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.target).isNull() diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetPresenterTest.kt index 0a10188f48..91c89ec89e 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheetPresenterTest.kt @@ -8,12 +8,10 @@ package io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet -import app.cash.molecule.RecompositionMode -import app.cash.molecule.moleculeFlow -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.test import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -25,9 +23,7 @@ class ReadReceiptBottomSheetPresenterTest { @Test fun `present - handle event selected`() = runTest { val presenter = createPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val selectedEvent = aTimelineItemEvent() initialState.eventSink(ReadReceiptBottomSheetEvent.EventSelected(selectedEvent)) @@ -38,9 +34,7 @@ class ReadReceiptBottomSheetPresenterTest { @Test fun `present - handle dismiss`() = runTest { val presenter = createPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val selectedEvent = aTimelineItemEvent() initialState.eventSink(ReadReceiptBottomSheetEvent.EventSelected(selectedEvent)) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/typing/TypingNotificationPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/typing/TypingNotificationPresenterTest.kt index 896c529ed1..62e596bc21 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/typing/TypingNotificationPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/typing/TypingNotificationPresenterTest.kt @@ -8,10 +8,7 @@ package io.element.android.features.messages.impl.typing -import app.cash.molecule.RecompositionMode -import app.cash.molecule.moleculeFlow import app.cash.turbine.Event -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.JoinedRoom @@ -26,6 +23,7 @@ import io.element.android.libraries.matrix.test.room.aRoomMember import io.element.android.libraries.preferences.api.store.SessionPreferencesStore import io.element.android.libraries.preferences.test.InMemorySessionPreferencesStore import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.test import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.runTest @@ -40,9 +38,7 @@ class TypingNotificationPresenterTest { @Test fun `present - initial state`() = runTest { val presenter = createPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.renderTypingNotifications).isTrue() assertThat(initialState.typingMembers).isEmpty() @@ -61,9 +57,7 @@ class TypingNotificationPresenterTest { joinedRoom = room, sessionPreferencesStore = sessionPreferencesStore, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) val initialState = awaitItem() assertThat(initialState.renderTypingNotifications).isFalse() @@ -95,9 +89,7 @@ class TypingNotificationPresenterTest { val typingMembersFlow = MutableStateFlow>(emptyList()) val room = FakeJoinedRoom(roomTypingMembersFlow = typingMembersFlow) val presenter = createPresenter(joinedRoom = room) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.typingMembers).isEmpty() typingMembersFlow.emit(listOf(A_USER_ID_2)) @@ -133,9 +125,7 @@ class TypingNotificationPresenterTest { ) } val presenter = createPresenter(joinedRoom = room) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.typingMembers).isEmpty() typingMembersFlow.emit(listOf(A_USER_ID_2)) @@ -160,9 +150,7 @@ class TypingNotificationPresenterTest { val typingMembersFlow = MutableStateFlow>(emptyList()) val room = FakeJoinedRoom(roomTypingMembersFlow = typingMembersFlow) val presenter = createPresenter(joinedRoom = room) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.typingMembers).isEmpty() typingMembersFlow.emit(listOf(A_USER_ID_2)) @@ -194,9 +182,7 @@ class TypingNotificationPresenterTest { val typingMembersFlow = MutableStateFlow>(emptyList()) val room = FakeJoinedRoom(roomTypingMembersFlow = typingMembersFlow) val presenter = createPresenter(joinedRoom = room) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.typingMembers).isEmpty() typingMembersFlow.emit(listOf(A_USER_ID_2))