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 7d0d6cb2d0..1798584853 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 @@ -32,6 +32,7 @@ import io.element.android.features.messages.impl.attachments.Attachment import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter import io.element.android.features.messages.impl.timeline.TimelineEvents +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 import io.element.android.features.messages.impl.timeline.model.TimelineItem @@ -62,6 +63,7 @@ class MessagesNode @AssistedInject constructor( private val room: MatrixRoom, private val analyticsService: AnalyticsService, messageComposerPresenterFactory: MessageComposerPresenter.Factory, + timelinePresenterFactory: TimelinePresenter.Factory, presenterFactory: MessagesPresenter.Factory, private val timelineItemPresenterFactories: TimelineItemPresenterFactories, private val mediaPlayer: MediaPlayer, @@ -70,6 +72,7 @@ class MessagesNode @AssistedInject constructor( private val presenter = presenterFactory.create( navigator = this, composerPresenter = messageComposerPresenterFactory.create(this), + timelinePresenter = timelinePresenterFactory.create(this), ) private val callbacks = plugins() 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 8f11c491e2..e39056ec9b 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,6 @@ 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.TimelineController import io.element.android.features.messages.impl.timeline.TimelineEvents -import io.element.android.features.messages.impl.timeline.TimelinePresenter 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 @@ -91,7 +90,7 @@ class MessagesPresenter @AssistedInject constructor( private val room: MatrixRoom, @Assisted private val composerPresenter: Presenter, private val voiceMessageComposerPresenter: Presenter, - timelinePresenterFactory: TimelinePresenter.Factory, + @Assisted private val timelinePresenter: Presenter, private val timelineProtectionPresenter: Presenter, private val identityChangeStatePresenter: Presenter, actionListPresenterFactory: ActionListPresenter.Factory, @@ -111,7 +110,6 @@ class MessagesPresenter @AssistedInject constructor( private val permalinkParser: PermalinkParser, private val analyticsService: AnalyticsService, ) : Presenter { - private val timelinePresenter = timelinePresenterFactory.create(navigator = navigator) private val actionListPresenter = actionListPresenterFactory.create(TimelineItemActionPostProcessor.Default) @AssistedFactory @@ -119,6 +117,7 @@ class MessagesPresenter @AssistedInject constructor( fun create( navigator: MessagesNavigator, composerPresenter: Presenter, + timelinePresenter: Presenter, ): MessagesPresenter } 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 4f4de58bf5..61606a51de 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 @@ -23,8 +23,8 @@ import io.element.android.features.messages.impl.messagecomposer.MessageComposer import io.element.android.features.messages.impl.messagecomposer.aMessageComposerState import io.element.android.features.messages.impl.pinned.banner.aLoadedPinnedMessagesBannerState import io.element.android.features.messages.impl.timeline.TimelineController -import io.element.android.features.messages.impl.timeline.TimelinePresenter -import io.element.android.features.messages.impl.timeline.createTimelinePresenter +import io.element.android.features.messages.impl.timeline.TimelineEvents +import io.element.android.features.messages.impl.timeline.aTimelineState import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent @@ -36,8 +36,6 @@ import io.element.android.features.messages.impl.timeline.protection.aTimelinePr import io.element.android.features.messages.impl.voicemessages.composer.aVoiceMessageComposerState import io.element.android.features.messages.test.timeline.FakeHtmlConverterProvider import io.element.android.features.networkmonitor.test.FakeNetworkMonitor -import io.element.android.features.poll.api.actions.EndPollAction -import io.element.android.features.poll.test.actions.FakeEndPollAction import io.element.android.features.roomcall.api.aStandByCallState import io.element.android.libraries.androidutils.clipboard.FakeClipboardHelper import io.element.android.libraries.architecture.AsyncData @@ -220,7 +218,7 @@ class MessagesPresenterTest { @Test fun `present - handle action forward`() = runTest { - val onForwardEventClickLambda = lambdaRecorder { } + val onForwardEventClickLambda = lambdaRecorder { } val navigator = FakeMessagesNavigator( onForwardEventClickLambda = onForwardEventClickLambda, ) @@ -458,7 +456,7 @@ class MessagesPresenterTest { @Test fun `present - handle action edit poll`() = runTest { - val onEditPollClickLambda = lambdaRecorder { } + val onEditPollClickLambda = lambdaRecorder { } val navigator = FakeMessagesNavigator( onEditPollClickLambda = onEditPollClickLambda ) @@ -475,16 +473,15 @@ class MessagesPresenterTest { @Test fun `present - handle action end poll`() = runTest { - val endPollAction = FakeEndPollAction() - val presenter = createMessagesPresenter(endPollAction = endPollAction) + val timelineEventSink = EventsRecorder() + val presenter = createMessagesPresenter(timelineEventSink = timelineEventSink) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitItem() - endPollAction.verifyExecutionCount(0) initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.EndPoll, aMessageEvent(content = aTimelineItemPollContent()))) delay(1) - endPollAction.verifyExecutionCount(1) + timelineEventSink.assertSingle(TimelineEvents.EndPoll(AN_EVENT_ID)) cancelAndIgnoreRemainingEvents() } } @@ -525,7 +522,7 @@ class MessagesPresenterTest { @Test fun `present - handle action report content`() = runTest { - val onReportContentClickLambda = lambdaRecorder { _: EventId, _: UserId -> } + val onReportContentClickLambda = lambdaRecorder { _: EventId, _: UserId -> } val navigator = FakeMessagesNavigator( onReportContentClickLambda = onReportContentClickLambda ) @@ -554,7 +551,7 @@ class MessagesPresenterTest { @Test fun `present - handle action show developer info`() = runTest { - val onShowEventDebugInfoClickLambda = lambdaRecorder { _: EventId?, _: TimelineItemDebugInfo -> } + val onShowEventDebugInfoClickLambda = lambdaRecorder { _: EventId?, _: TimelineItemDebugInfo -> } val navigator = FakeMessagesNavigator( onShowEventDebugInfoClickLambda = onShowEventDebugInfoClickLambda ) @@ -1102,7 +1099,7 @@ class MessagesPresenterTest { navigator: FakeMessagesNavigator = FakeMessagesNavigator(), clipboardHelper: FakeClipboardHelper = FakeClipboardHelper(), analyticsService: FakeAnalyticsService = FakeAnalyticsService(), - endPollAction: EndPollAction = FakeEndPollAction(), + timelineEventSink: (TimelineEvents) -> Unit = {}, permalinkParser: PermalinkParser = FakePermalinkParser(), messageComposerPresenter: Presenter = Presenter { aMessageComposerState( @@ -1112,19 +1109,12 @@ class MessagesPresenterTest { }, actionListEventSink: (ActionListEvents) -> Unit = {}, ): MessagesPresenter { - val timelinePresenterFactory = object : TimelinePresenter.Factory { - override fun create(navigator: MessagesNavigator): TimelinePresenter { - return createTimelinePresenter( - endPollAction = endPollAction, - ) - } - } val featureFlagService = FakeFeatureFlagService() return MessagesPresenter( room = matrixRoom, composerPresenter = messageComposerPresenter, voiceMessageComposerPresenter = { aVoiceMessageComposerState() }, - timelinePresenterFactory = timelinePresenterFactory, + timelinePresenter = { aTimelineState(eventSink = timelineEventSink) }, timelineProtectionPresenter = { aTimelineProtectionState() }, actionListPresenterFactory = FakeActionListPresenter.Factory(actionListEventSink), customReactionPresenter = { aCustomReactionState() }, 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 4326ec5545..a21dcb2834 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 @@ -660,35 +660,35 @@ import kotlin.time.Duration.Companion.seconds private suspend fun ReceiveTurbine.awaitFirstItem(): T { return awaitItem() } -} -internal fun TestScope.createTimelinePresenter( - timeline: Timeline = FakeTimeline(), - room: FakeMatrixRoom = FakeMatrixRoom( - liveTimeline = timeline, - canUserSendMessageResult = { _, _ -> Result.success(true) } - ), - redactedVoiceMessageManager: RedactedVoiceMessageManager = FakeRedactedVoiceMessageManager(), - messagesNavigator: FakeMessagesNavigator = FakeMessagesNavigator(), - endPollAction: EndPollAction = FakeEndPollAction(), - sendPollResponseAction: SendPollResponseAction = FakeSendPollResponseAction(), - sessionPreferencesStore: InMemorySessionPreferencesStore = InMemorySessionPreferencesStore(), - timelineItemIndexer: TimelineItemIndexer = TimelineItemIndexer(), -): TimelinePresenter { - return TimelinePresenter( - timelineItemsFactoryCreator = aTimelineItemsFactoryCreator(), - room = room, - dispatchers = testCoroutineDispatchers(), - appScope = this, - navigator = messagesNavigator, - redactedVoiceMessageManager = redactedVoiceMessageManager, - endPollAction = endPollAction, - sendPollResponseAction = sendPollResponseAction, - sessionPreferencesStore = sessionPreferencesStore, - timelineItemIndexer = timelineItemIndexer, - timelineController = TimelineController(room), - resolveVerifiedUserSendFailurePresenter = { aResolveVerifiedUserSendFailureState() }, - typingNotificationPresenter = { aTypingNotificationState() }, - roomCallStatePresenter = { aStandByCallState() }, - ) + private fun TestScope.createTimelinePresenter( + timeline: Timeline = FakeTimeline(), + room: FakeMatrixRoom = FakeMatrixRoom( + liveTimeline = timeline, + canUserSendMessageResult = { _, _ -> Result.success(true) } + ), + redactedVoiceMessageManager: RedactedVoiceMessageManager = FakeRedactedVoiceMessageManager(), + messagesNavigator: FakeMessagesNavigator = FakeMessagesNavigator(), + endPollAction: EndPollAction = FakeEndPollAction(), + sendPollResponseAction: SendPollResponseAction = FakeSendPollResponseAction(), + sessionPreferencesStore: InMemorySessionPreferencesStore = InMemorySessionPreferencesStore(), + timelineItemIndexer: TimelineItemIndexer = TimelineItemIndexer(), + ): TimelinePresenter { + return TimelinePresenter( + timelineItemsFactoryCreator = aTimelineItemsFactoryCreator(), + room = room, + dispatchers = testCoroutineDispatchers(), + appScope = this, + navigator = messagesNavigator, + redactedVoiceMessageManager = redactedVoiceMessageManager, + endPollAction = endPollAction, + sendPollResponseAction = sendPollResponseAction, + sessionPreferencesStore = sessionPreferencesStore, + timelineItemIndexer = timelineItemIndexer, + timelineController = TimelineController(room), + resolveVerifiedUserSendFailurePresenter = { aResolveVerifiedUserSendFailureState() }, + typingNotificationPresenter = { aTypingNotificationState() }, + roomCallStatePresenter = { aStandByCallState() }, + ) + } }