Remove dependencies to other presenters in MessagesPresenter.
This commit is contained in:
parent
62cbff0ffe
commit
6d87c8ad19
7 changed files with 238 additions and 257 deletions
|
|
@ -32,22 +32,21 @@ import io.element.android.features.messages.impl.actionlist.ActionListPresenter
|
||||||
import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
|
import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
|
||||||
import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionPostProcessor
|
import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionPostProcessor
|
||||||
import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents
|
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.messagecomposer.MessageComposerState
|
import io.element.android.features.messages.impl.messagecomposer.MessageComposerState
|
||||||
import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerState
|
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.TimelineController
|
||||||
import io.element.android.features.messages.impl.timeline.TimelineEvents
|
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.TimelinePresenter
|
||||||
import io.element.android.features.messages.impl.timeline.TimelineState
|
import io.element.android.features.messages.impl.timeline.TimelineState
|
||||||
import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionPresenter
|
import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionState
|
||||||
import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryPresenter
|
import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryState
|
||||||
import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetPresenter
|
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.TimelineItem
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent
|
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent
|
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent
|
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent
|
||||||
import io.element.android.features.messages.impl.timeline.protection.TimelineProtectionState
|
import io.element.android.features.messages.impl.timeline.protection.TimelineProtectionState
|
||||||
import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessageComposerPresenter
|
import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessageComposerState
|
||||||
import io.element.android.features.networkmonitor.api.NetworkMonitor
|
import io.element.android.features.networkmonitor.api.NetworkMonitor
|
||||||
import io.element.android.features.networkmonitor.api.NetworkStatus
|
import io.element.android.features.networkmonitor.api.NetworkStatus
|
||||||
import io.element.android.libraries.androidutils.clipboard.ClipboardHelper
|
import io.element.android.libraries.androidutils.clipboard.ClipboardHelper
|
||||||
|
|
@ -88,14 +87,14 @@ import timber.log.Timber
|
||||||
class MessagesPresenter @AssistedInject constructor(
|
class MessagesPresenter @AssistedInject constructor(
|
||||||
@Assisted private val navigator: MessagesNavigator,
|
@Assisted private val navigator: MessagesNavigator,
|
||||||
private val room: MatrixRoom,
|
private val room: MatrixRoom,
|
||||||
private val composerPresenter: MessageComposerPresenter,
|
private val composerPresenter: Presenter<MessageComposerState>,
|
||||||
private val voiceMessageComposerPresenter: VoiceMessageComposerPresenter,
|
private val voiceMessageComposerPresenter: Presenter<VoiceMessageComposerState>,
|
||||||
timelinePresenterFactory: TimelinePresenter.Factory,
|
timelinePresenterFactory: TimelinePresenter.Factory,
|
||||||
private val timelineProtectionPresenter: Presenter<TimelineProtectionState>,
|
private val timelineProtectionPresenter: Presenter<TimelineProtectionState>,
|
||||||
private val actionListPresenterFactory: ActionListPresenter.Factory,
|
private val actionListPresenterFactory: ActionListPresenter.Factory,
|
||||||
private val customReactionPresenter: CustomReactionPresenter,
|
private val customReactionPresenter: Presenter<CustomReactionState>,
|
||||||
private val reactionSummaryPresenter: ReactionSummaryPresenter,
|
private val reactionSummaryPresenter: Presenter<ReactionSummaryState>,
|
||||||
private val readReceiptBottomSheetPresenter: ReadReceiptBottomSheetPresenter,
|
private val readReceiptBottomSheetPresenter: Presenter<ReadReceiptBottomSheetState>,
|
||||||
private val pinnedMessagesBannerPresenter: Presenter<PinnedMessagesBannerState>,
|
private val pinnedMessagesBannerPresenter: Presenter<PinnedMessagesBannerState>,
|
||||||
private val networkMonitor: NetworkMonitor,
|
private val networkMonitor: NetworkMonitor,
|
||||||
private val snackbarDispatcher: SnackbarDispatcher,
|
private val snackbarDispatcher: SnackbarDispatcher,
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,22 @@ import dagger.Binds
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailurePresenter
|
import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailurePresenter
|
||||||
import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureState
|
import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureState
|
||||||
|
import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter
|
||||||
|
import io.element.android.features.messages.impl.messagecomposer.MessageComposerState
|
||||||
import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerPresenter
|
import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerPresenter
|
||||||
import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerState
|
import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerState
|
||||||
|
import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionPresenter
|
||||||
|
import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionState
|
||||||
|
import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryPresenter
|
||||||
|
import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryState
|
||||||
|
import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetPresenter
|
||||||
|
import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetState
|
||||||
import io.element.android.features.messages.impl.timeline.protection.TimelineProtectionPresenter
|
import io.element.android.features.messages.impl.timeline.protection.TimelineProtectionPresenter
|
||||||
import io.element.android.features.messages.impl.timeline.protection.TimelineProtectionState
|
import io.element.android.features.messages.impl.timeline.protection.TimelineProtectionState
|
||||||
import io.element.android.features.messages.impl.typing.TypingNotificationPresenter
|
import io.element.android.features.messages.impl.typing.TypingNotificationPresenter
|
||||||
import io.element.android.features.messages.impl.typing.TypingNotificationState
|
import io.element.android.features.messages.impl.typing.TypingNotificationState
|
||||||
|
import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessageComposerPresenter
|
||||||
|
import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessageComposerState
|
||||||
import io.element.android.libraries.architecture.Presenter
|
import io.element.android.libraries.architecture.Presenter
|
||||||
import io.element.android.libraries.di.RoomScope
|
import io.element.android.libraries.di.RoomScope
|
||||||
|
|
||||||
|
|
@ -35,4 +45,19 @@ interface MessagesModule {
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
fun bindTimelineProtectionPresenter(presenter: TimelineProtectionPresenter): Presenter<TimelineProtectionState>
|
fun bindTimelineProtectionPresenter(presenter: TimelineProtectionPresenter): Presenter<TimelineProtectionState>
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
fun bindMessageComposerPresenter(presenter: MessageComposerPresenter): Presenter<MessageComposerState>
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
fun bindVoiceMessageComposerPresenter(presenter: VoiceMessageComposerPresenter): Presenter<VoiceMessageComposerState>
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
fun bindCustomReactionPresenter(presenter: CustomReactionPresenter): Presenter<CustomReactionState>
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
fun bindReactionSummaryPresenter(presenter: ReactionSummaryPresenter): Presenter<ReactionSummaryState>
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
fun bindReadReceiptBottomSheetPresenter(presenter: ReadReceiptBottomSheetPresenter): Presenter<ReadReceiptBottomSheetState>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ fun aMessageComposerState(
|
||||||
canCreatePoll: Boolean = true,
|
canCreatePoll: Boolean = true,
|
||||||
attachmentsState: AttachmentsState = AttachmentsState.None,
|
attachmentsState: AttachmentsState = AttachmentsState.None,
|
||||||
suggestions: ImmutableList<ResolvedSuggestion> = persistentListOf(),
|
suggestions: ImmutableList<ResolvedSuggestion> = persistentListOf(),
|
||||||
|
eventSink: (MessageComposerEvents) -> Unit = {},
|
||||||
) = MessageComposerState(
|
) = MessageComposerState(
|
||||||
textEditorState = textEditorState,
|
textEditorState = textEditorState,
|
||||||
isFullScreen = isFullScreen,
|
isFullScreen = isFullScreen,
|
||||||
|
|
@ -44,5 +45,5 @@ fun aMessageComposerState(
|
||||||
attachmentsState = attachmentsState,
|
attachmentsState = attachmentsState,
|
||||||
suggestions = suggestions,
|
suggestions = suggestions,
|
||||||
resolveMentionDisplay = { _, _ -> TextDisplay.Plain },
|
resolveMentionDisplay = { _, _ -> TextDisplay.Plain },
|
||||||
eventSink = {},
|
eventSink = eventSink,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -7,33 +7,23 @@
|
||||||
|
|
||||||
package io.element.android.features.messages.impl
|
package io.element.android.features.messages.impl
|
||||||
|
|
||||||
import android.net.Uri
|
|
||||||
import app.cash.molecule.RecompositionMode
|
import app.cash.molecule.RecompositionMode
|
||||||
import app.cash.molecule.moleculeFlow
|
import app.cash.molecule.moleculeFlow
|
||||||
import app.cash.turbine.ReceiveTurbine
|
|
||||||
import app.cash.turbine.test
|
import app.cash.turbine.test
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import im.vector.app.features.analytics.plan.PinUnpinAction
|
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.ActionListState
|
import io.element.android.features.messages.impl.actionlist.ActionListState
|
||||||
import io.element.android.features.messages.impl.actionlist.FakeActionListPresenter
|
import io.element.android.features.messages.impl.actionlist.FakeActionListPresenter
|
||||||
import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
|
import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
|
||||||
import io.element.android.features.messages.impl.crypto.sendfailure.resolve.aResolveVerifiedUserSendFailureState
|
|
||||||
import io.element.android.features.messages.impl.draft.FakeComposerDraftService
|
|
||||||
import io.element.android.features.messages.impl.fixtures.aMessageEvent
|
import io.element.android.features.messages.impl.fixtures.aMessageEvent
|
||||||
import io.element.android.features.messages.impl.fixtures.aTimelineItemsFactoryCreator
|
import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents
|
||||||
import io.element.android.features.messages.impl.messagecomposer.DefaultMessageComposerContext
|
import io.element.android.features.messages.impl.messagecomposer.MessageComposerState
|
||||||
import io.element.android.features.messages.impl.messagecomposer.FakeRoomAliasSuggestionsDataSource
|
import io.element.android.features.messages.impl.messagecomposer.aMessageComposerState
|
||||||
import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter
|
|
||||||
import io.element.android.features.messages.impl.messagecomposer.TestRichTextEditorStateFactory
|
|
||||||
import io.element.android.features.messages.impl.messagecomposer.suggestions.SuggestionsProcessor
|
|
||||||
import io.element.android.features.messages.impl.pinned.banner.aLoadedPinnedMessagesBannerState
|
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.TimelineController
|
||||||
import io.element.android.features.messages.impl.timeline.TimelineItemIndexer
|
|
||||||
import io.element.android.features.messages.impl.timeline.TimelinePresenter
|
import io.element.android.features.messages.impl.timeline.TimelinePresenter
|
||||||
import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionPresenter
|
import io.element.android.features.messages.impl.timeline.createTimelinePresenter
|
||||||
import io.element.android.features.messages.impl.timeline.components.customreaction.FakeEmojibaseProvider
|
|
||||||
import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryPresenter
|
|
||||||
import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetPresenter
|
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent
|
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.TimelineItemImageContent
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent
|
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent
|
||||||
|
|
@ -41,25 +31,19 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent
|
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent
|
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent
|
||||||
import io.element.android.features.messages.impl.timeline.protection.aTimelineProtectionState
|
import io.element.android.features.messages.impl.timeline.protection.aTimelineProtectionState
|
||||||
import io.element.android.features.messages.impl.typing.aTypingNotificationState
|
import io.element.android.features.messages.impl.voicemessages.composer.aVoiceMessageComposerState
|
||||||
import io.element.android.features.messages.impl.utils.FakeTextPillificationHelper
|
|
||||||
import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessageComposerPlayer
|
|
||||||
import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessageComposerPresenter
|
|
||||||
import io.element.android.features.messages.impl.voicemessages.timeline.FakeRedactedVoiceMessageManager
|
|
||||||
import io.element.android.features.messages.test.FakeMessageComposerContext
|
|
||||||
import io.element.android.features.messages.test.timeline.FakeHtmlConverterProvider
|
import io.element.android.features.messages.test.timeline.FakeHtmlConverterProvider
|
||||||
import io.element.android.features.networkmonitor.test.FakeNetworkMonitor
|
import io.element.android.features.networkmonitor.test.FakeNetworkMonitor
|
||||||
import io.element.android.features.poll.api.actions.EndPollAction
|
import io.element.android.features.poll.api.actions.EndPollAction
|
||||||
import io.element.android.features.poll.test.actions.FakeEndPollAction
|
import io.element.android.features.poll.test.actions.FakeEndPollAction
|
||||||
import io.element.android.features.poll.test.actions.FakeSendPollResponseAction
|
|
||||||
import io.element.android.libraries.androidutils.clipboard.FakeClipboardHelper
|
import io.element.android.libraries.androidutils.clipboard.FakeClipboardHelper
|
||||||
import io.element.android.libraries.architecture.AsyncData
|
import io.element.android.libraries.architecture.AsyncData
|
||||||
|
import io.element.android.libraries.architecture.Presenter
|
||||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||||
import io.element.android.libraries.core.mimetype.MimeTypes
|
import io.element.android.libraries.core.mimetype.MimeTypes
|
||||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
|
||||||
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
||||||
import io.element.android.libraries.matrix.api.core.EventId
|
import io.element.android.libraries.matrix.api.core.EventId
|
||||||
import io.element.android.libraries.matrix.api.core.TransactionId
|
import io.element.android.libraries.matrix.api.core.TransactionId
|
||||||
|
|
@ -72,33 +56,24 @@ import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
|
||||||
import io.element.android.libraries.matrix.api.room.MessageEventType
|
import io.element.android.libraries.matrix.api.room.MessageEventType
|
||||||
import io.element.android.libraries.matrix.api.room.RoomMembershipState
|
import io.element.android.libraries.matrix.api.room.RoomMembershipState
|
||||||
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
|
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
|
||||||
|
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||||
import io.element.android.libraries.matrix.test.A_SESSION_ID_2
|
import io.element.android.libraries.matrix.test.A_SESSION_ID_2
|
||||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||||
import io.element.android.libraries.matrix.test.A_UNIQUE_ID
|
import io.element.android.libraries.matrix.test.A_UNIQUE_ID
|
||||||
import io.element.android.libraries.matrix.test.core.aBuildMeta
|
import io.element.android.libraries.matrix.test.core.aBuildMeta
|
||||||
import io.element.android.libraries.matrix.test.permalink.FakePermalinkBuilder
|
|
||||||
import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser
|
import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser
|
||||||
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
||||||
import io.element.android.libraries.matrix.test.room.aRoomInfo
|
import io.element.android.libraries.matrix.test.room.aRoomInfo
|
||||||
import io.element.android.libraries.matrix.test.room.aRoomMember
|
import io.element.android.libraries.matrix.test.room.aRoomMember
|
||||||
import io.element.android.libraries.matrix.test.timeline.FakeTimeline
|
import io.element.android.libraries.matrix.test.timeline.FakeTimeline
|
||||||
import io.element.android.libraries.matrix.ui.messages.RoomMemberProfilesCache
|
|
||||||
import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails
|
import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails
|
||||||
import io.element.android.libraries.mediapickers.test.FakePickerProvider
|
import io.element.android.libraries.textcomposer.model.MarkdownTextEditorState
|
||||||
import io.element.android.libraries.mediaplayer.test.FakeMediaPlayer
|
|
||||||
import io.element.android.libraries.mediaupload.api.MediaSender
|
|
||||||
import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor
|
|
||||||
import io.element.android.libraries.mediaviewer.test.FakeLocalMediaFactory
|
|
||||||
import io.element.android.libraries.permissions.api.PermissionsPresenter
|
|
||||||
import io.element.android.libraries.permissions.test.FakePermissionsPresenter
|
|
||||||
import io.element.android.libraries.permissions.test.FakePermissionsPresenterFactory
|
|
||||||
import io.element.android.libraries.preferences.test.InMemorySessionPreferencesStore
|
|
||||||
import io.element.android.libraries.textcomposer.mentions.MentionSpanProvider
|
|
||||||
import io.element.android.libraries.textcomposer.model.MessageComposerMode
|
import io.element.android.libraries.textcomposer.model.MessageComposerMode
|
||||||
import io.element.android.libraries.voicerecorder.test.FakeVoiceRecorder
|
import io.element.android.libraries.textcomposer.model.TextEditorState
|
||||||
import io.element.android.services.analytics.test.FakeAnalyticsService
|
import io.element.android.services.analytics.test.FakeAnalyticsService
|
||||||
|
import io.element.android.tests.testutils.EventsRecorder
|
||||||
import io.element.android.tests.testutils.WarmUpRule
|
import io.element.android.tests.testutils.WarmUpRule
|
||||||
import io.element.android.tests.testutils.consumeItemsUntilPredicate
|
import io.element.android.tests.testutils.consumeItemsUntilPredicate
|
||||||
import io.element.android.tests.testutils.consumeItemsUntilTimeout
|
import io.element.android.tests.testutils.consumeItemsUntilTimeout
|
||||||
|
|
@ -107,7 +82,6 @@ import io.element.android.tests.testutils.lambda.lambdaError
|
||||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||||
import io.element.android.tests.testutils.lambda.value
|
import io.element.android.tests.testutils.lambda.value
|
||||||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||||
import io.mockk.mockk
|
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
|
@ -123,8 +97,6 @@ class MessagesPresenterTest {
|
||||||
@get:Rule
|
@get:Rule
|
||||||
val warmUpRule = WarmUpRule()
|
val warmUpRule = WarmUpRule()
|
||||||
|
|
||||||
private val mockMediaUrl: Uri = mockk("localMediaUri")
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - initial state`() = runTest {
|
fun `present - initial state`() = runTest {
|
||||||
val presenter = createMessagesPresenter()
|
val presenter = createMessagesPresenter()
|
||||||
|
|
@ -212,15 +184,13 @@ class MessagesPresenterTest {
|
||||||
}.test {
|
}.test {
|
||||||
skipItems(1)
|
skipItems(1)
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
initialState.eventSink.invoke(MessagesEvents.ToggleReaction("👍", A_UNIQUE_ID))
|
initialState.eventSink(MessagesEvents.ToggleReaction("👍", A_UNIQUE_ID))
|
||||||
// No crashes when sending a reaction failed
|
|
||||||
timeline.apply { toggleReactionLambda = toggleReactionFailure }
|
|
||||||
initialState.eventSink.invoke(MessagesEvents.ToggleReaction("👍", A_UNIQUE_ID))
|
|
||||||
assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
|
|
||||||
|
|
||||||
assert(toggleReactionSuccess)
|
assert(toggleReactionSuccess)
|
||||||
.isCalledOnce()
|
.isCalledOnce()
|
||||||
.with(value("👍"), value(A_UNIQUE_ID))
|
.with(value("👍"), value(A_UNIQUE_ID))
|
||||||
|
// No crashes when sending a reaction failed
|
||||||
|
timeline.apply { toggleReactionLambda = toggleReactionFailure }
|
||||||
|
initialState.eventSink(MessagesEvents.ToggleReaction("👍", A_UNIQUE_ID))
|
||||||
assert(toggleReactionFailure)
|
assert(toggleReactionFailure)
|
||||||
.isCalledOnce()
|
.isCalledOnce()
|
||||||
.with(value("👍"), value(A_UNIQUE_ID))
|
.with(value("👍"), value(A_UNIQUE_ID))
|
||||||
|
|
@ -248,15 +218,16 @@ class MessagesPresenterTest {
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
val initialState = awaitFirstItem()
|
val initialState = awaitItem()
|
||||||
initialState.eventSink.invoke(MessagesEvents.ToggleReaction("👍", A_UNIQUE_ID))
|
initialState.eventSink(MessagesEvents.ToggleReaction("👍", A_UNIQUE_ID))
|
||||||
initialState.eventSink.invoke(MessagesEvents.ToggleReaction("👍", A_UNIQUE_ID))
|
initialState.eventSink(MessagesEvents.ToggleReaction("👍", A_UNIQUE_ID))
|
||||||
assert(toggleReactionSuccess)
|
assert(toggleReactionSuccess)
|
||||||
.isCalledExactly(2)
|
.isCalledExactly(2)
|
||||||
.withSequence(
|
.withSequence(
|
||||||
listOf(value("👍"), value(A_UNIQUE_ID)),
|
listOf(value("👍"), value(A_UNIQUE_ID)),
|
||||||
listOf(value("👍"), value(A_UNIQUE_ID)),
|
listOf(value("👍"), value(A_UNIQUE_ID)),
|
||||||
)
|
)
|
||||||
|
skipItems(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -267,9 +238,8 @@ class MessagesPresenterTest {
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
skipItems(1)
|
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Forward, aMessageEvent()))
|
initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Forward, aMessageEvent()))
|
||||||
assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
|
assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
|
||||||
assertThat(navigator.onForwardEventClickedCount).isEqualTo(1)
|
assertThat(navigator.onForwardEventClickedCount).isEqualTo(1)
|
||||||
}
|
}
|
||||||
|
|
@ -283,9 +253,9 @@ class MessagesPresenterTest {
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
val initialState = awaitFirstItem()
|
val initialState = awaitItem()
|
||||||
initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Copy, event))
|
initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Copy, event))
|
||||||
assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
|
skipItems(2)
|
||||||
assertThat(clipboardHelper.clipboardContents).isEqualTo((event.content as TimelineItemTextContent).body)
|
assertThat(clipboardHelper.clipboardContents).isEqualTo((event.content as TimelineItemTextContent).body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -310,24 +280,33 @@ class MessagesPresenterTest {
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
val initialState = awaitFirstItem()
|
val initialState = awaitItem()
|
||||||
initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.CopyLink, event))
|
initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.CopyLink, event))
|
||||||
assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
|
skipItems(2)
|
||||||
assertThat(clipboardHelper.clipboardContents).isEqualTo("a link")
|
assertThat(clipboardHelper.clipboardContents).isEqualTo("a link")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - handle action reply`() = runTest {
|
fun `present - handle action reply`() = runTest {
|
||||||
val presenter = createMessagesPresenter()
|
val composerRecorder = EventsRecorder<MessageComposerEvents>()
|
||||||
|
val presenter = createMessagesPresenter(
|
||||||
|
messageComposerPresenter = { aMessageComposerState(eventSink = composerRecorder) },
|
||||||
|
)
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
val initialState = awaitFirstItem()
|
val initialState = awaitItem()
|
||||||
initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Reply, aMessageEvent()))
|
initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Reply, aMessageEvent()))
|
||||||
val finalState = awaitItem()
|
awaitItem()
|
||||||
assertThat(finalState.composerState.mode).isInstanceOf(MessageComposerMode.Reply::class.java)
|
composerRecorder.assertSingle(
|
||||||
assertThat(finalState.actionListState.target).isEqualTo(ActionListState.Target.None)
|
MessageComposerEvents.SetMode(
|
||||||
|
composerMode = MessageComposerMode.Reply(
|
||||||
|
replyToDetails = InReplyToDetails.Loading(AN_EVENT_ID),
|
||||||
|
hideImage = false,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -337,21 +316,22 @@ class MessagesPresenterTest {
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
val initialState = awaitFirstItem()
|
val initialState = awaitItem()
|
||||||
initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Reply, aMessageEvent(eventId = null)))
|
initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Reply, aMessageEvent(eventId = null)))
|
||||||
assertThat(initialState.actionListState.target).isEqualTo(ActionListState.Target.None)
|
skipItems(1)
|
||||||
// Otherwise we would have some extra items here
|
|
||||||
ensureAllEventsConsumed()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - handle action reply to an image media message`() = runTest {
|
fun `present - handle action reply to an image media message`() = runTest {
|
||||||
val presenter = createMessagesPresenter()
|
val composerRecorder = EventsRecorder<MessageComposerEvents>()
|
||||||
|
val presenter = createMessagesPresenter(
|
||||||
|
messageComposerPresenter = { aMessageComposerState(eventSink = composerRecorder) },
|
||||||
|
)
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
val initialState = awaitFirstItem()
|
val initialState = awaitItem()
|
||||||
val mediaMessage = aMessageEvent(
|
val mediaMessage = aMessageEvent(
|
||||||
content = TimelineItemImageContent(
|
content = TimelineItemImageContent(
|
||||||
body = "image.jpg",
|
body = "image.jpg",
|
||||||
|
|
@ -368,22 +348,29 @@ class MessagesPresenterTest {
|
||||||
formattedFileSize = "4MB"
|
formattedFileSize = "4MB"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Reply, mediaMessage))
|
initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Reply, mediaMessage))
|
||||||
val finalState = awaitItem()
|
awaitItem()
|
||||||
assertThat(finalState.composerState.mode).isInstanceOf(MessageComposerMode.Reply::class.java)
|
composerRecorder.assertSingle(
|
||||||
val replyMode = finalState.composerState.mode as MessageComposerMode.Reply
|
MessageComposerEvents.SetMode(
|
||||||
assertThat(replyMode.replyToDetails).isInstanceOf(InReplyToDetails.Loading::class.java)
|
composerMode = MessageComposerMode.Reply(
|
||||||
assertThat(finalState.actionListState.target).isEqualTo(ActionListState.Target.None)
|
replyToDetails = InReplyToDetails.Loading(AN_EVENT_ID),
|
||||||
|
hideImage = false,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - handle action reply to a video media message`() = runTest {
|
fun `present - handle action reply to a video media message`() = runTest {
|
||||||
val presenter = createMessagesPresenter()
|
val composerRecorder = EventsRecorder<MessageComposerEvents>()
|
||||||
|
val presenter = createMessagesPresenter(
|
||||||
|
messageComposerPresenter = { aMessageComposerState(eventSink = composerRecorder) },
|
||||||
|
)
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
val initialState = awaitFirstItem()
|
val initialState = awaitItem()
|
||||||
val mediaMessage = aMessageEvent(
|
val mediaMessage = aMessageEvent(
|
||||||
content = TimelineItemVideoContent(
|
content = TimelineItemVideoContent(
|
||||||
body = "video.mp4",
|
body = "video.mp4",
|
||||||
|
|
@ -401,22 +388,29 @@ class MessagesPresenterTest {
|
||||||
formattedFileSize = "50MB"
|
formattedFileSize = "50MB"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Reply, mediaMessage))
|
initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Reply, mediaMessage))
|
||||||
val finalState = awaitItem()
|
awaitItem()
|
||||||
assertThat(finalState.composerState.mode).isInstanceOf(MessageComposerMode.Reply::class.java)
|
composerRecorder.assertSingle(
|
||||||
val replyMode = finalState.composerState.mode as MessageComposerMode.Reply
|
MessageComposerEvents.SetMode(
|
||||||
assertThat(replyMode.replyToDetails).isInstanceOf(InReplyToDetails.Loading::class.java)
|
composerMode = MessageComposerMode.Reply(
|
||||||
assertThat(finalState.actionListState.target).isEqualTo(ActionListState.Target.None)
|
replyToDetails = InReplyToDetails.Loading(AN_EVENT_ID),
|
||||||
|
hideImage = false,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - handle action reply to a file media message`() = runTest {
|
fun `present - handle action reply to a file media message`() = runTest {
|
||||||
val presenter = createMessagesPresenter()
|
val composerRecorder = EventsRecorder<MessageComposerEvents>()
|
||||||
|
val presenter = createMessagesPresenter(
|
||||||
|
messageComposerPresenter = { aMessageComposerState(eventSink = composerRecorder) },
|
||||||
|
)
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
val initialState = awaitFirstItem()
|
val initialState = awaitItem()
|
||||||
val mediaMessage = aMessageEvent(
|
val mediaMessage = aMessageEvent(
|
||||||
content = TimelineItemFileContent(
|
content = TimelineItemFileContent(
|
||||||
body = "file.pdf",
|
body = "file.pdf",
|
||||||
|
|
@ -427,26 +421,40 @@ class MessagesPresenterTest {
|
||||||
fileExtension = "pdf",
|
fileExtension = "pdf",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Reply, mediaMessage))
|
initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Reply, mediaMessage))
|
||||||
val finalState = awaitItem()
|
awaitItem()
|
||||||
assertThat(finalState.composerState.mode).isInstanceOf(MessageComposerMode.Reply::class.java)
|
composerRecorder.assertSingle(
|
||||||
val replyMode = finalState.composerState.mode as MessageComposerMode.Reply
|
MessageComposerEvents.SetMode(
|
||||||
assertThat(replyMode.replyToDetails).isInstanceOf(InReplyToDetails.Loading::class.java)
|
composerMode = MessageComposerMode.Reply(
|
||||||
assertThat(finalState.actionListState.target).isEqualTo(ActionListState.Target.None)
|
replyToDetails = InReplyToDetails.Loading(AN_EVENT_ID),
|
||||||
|
hideImage = false,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - handle action edit`() = runTest {
|
fun `present - handle action edit`() = runTest {
|
||||||
val presenter = createMessagesPresenter()
|
val composerRecorder = EventsRecorder<MessageComposerEvents>()
|
||||||
|
val presenter = createMessagesPresenter(
|
||||||
|
messageComposerPresenter = { aMessageComposerState(eventSink = composerRecorder) },
|
||||||
|
)
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
val initialState = awaitFirstItem()
|
val initialState = awaitItem()
|
||||||
initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Edit, aMessageEvent()))
|
initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Edit, aMessageEvent()))
|
||||||
val finalState = awaitItem()
|
awaitItem()
|
||||||
assertThat(finalState.composerState.mode).isInstanceOf(MessageComposerMode.Edit::class.java)
|
composerRecorder.assertSingle(
|
||||||
assertThat(finalState.actionListState.target).isEqualTo(ActionListState.Target.None)
|
MessageComposerEvents.SetMode(
|
||||||
|
composerMode = MessageComposerMode.Edit(
|
||||||
|
eventId = AN_EVENT_ID,
|
||||||
|
transactionId = null,
|
||||||
|
content = (aMessageEvent().content as TimelineItemTextContent).body
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -457,8 +465,9 @@ class MessagesPresenterTest {
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
val initialState = awaitFirstItem()
|
val initialState = awaitItem()
|
||||||
initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Edit, aMessageEvent(content = aTimelineItemPollContent())))
|
initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Edit, aMessageEvent(content = aTimelineItemPollContent())))
|
||||||
|
awaitItem()
|
||||||
assertThat(navigator.onEditPollClickedCount).isEqualTo(1)
|
assertThat(navigator.onEditPollClickedCount).isEqualTo(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -470,9 +479,9 @@ class MessagesPresenterTest {
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
val initialState = awaitFirstItem()
|
val initialState = awaitItem()
|
||||||
endPollAction.verifyExecutionCount(0)
|
endPollAction.verifyExecutionCount(0)
|
||||||
initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.EndPoll, aMessageEvent(content = aTimelineItemPollContent())))
|
initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.EndPoll, aMessageEvent(content = aTimelineItemPollContent())))
|
||||||
delay(1)
|
delay(1)
|
||||||
endPollAction.verifyExecutionCount(1)
|
endPollAction.verifyExecutionCount(1)
|
||||||
cancelAndIgnoreRemainingEvents()
|
cancelAndIgnoreRemainingEvents()
|
||||||
|
|
@ -496,16 +505,17 @@ class MessagesPresenterTest {
|
||||||
|
|
||||||
val redactEventLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String? -> Result.success(Unit) }
|
val redactEventLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String? -> Result.success(Unit) }
|
||||||
liveTimeline.redactEventLambda = redactEventLambda
|
liveTimeline.redactEventLambda = redactEventLambda
|
||||||
|
val presenter = createMessagesPresenter(
|
||||||
val presenter = createMessagesPresenter(matrixRoom = matrixRoom, coroutineDispatchers = coroutineDispatchers)
|
matrixRoom = matrixRoom,
|
||||||
|
coroutineDispatchers = coroutineDispatchers,
|
||||||
|
)
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
skipItems(1)
|
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
val messageEvent = aMessageEvent()
|
val messageEvent = aMessageEvent()
|
||||||
initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Redact, messageEvent))
|
initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Redact, messageEvent))
|
||||||
assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
|
awaitItem()
|
||||||
assert(redactEventLambda)
|
assert(redactEventLambda)
|
||||||
.isCalledOnce()
|
.isCalledOnce()
|
||||||
.with(value(messageEvent.eventId), value(messageEvent.transactionId), value(null))
|
.with(value(messageEvent.eventId), value(messageEvent.transactionId), value(null))
|
||||||
|
|
@ -519,9 +529,8 @@ class MessagesPresenterTest {
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
skipItems(1)
|
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.ReportContent, aMessageEvent()))
|
initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.ReportContent, aMessageEvent()))
|
||||||
assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
|
assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
|
||||||
assertThat(navigator.onReportContentClickedCount).isEqualTo(1)
|
assertThat(navigator.onReportContentClickedCount).isEqualTo(1)
|
||||||
}
|
}
|
||||||
|
|
@ -533,9 +542,8 @@ class MessagesPresenterTest {
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
skipItems(1)
|
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
initialState.eventSink.invoke(MessagesEvents.Dismiss)
|
initialState.eventSink(MessagesEvents.Dismiss)
|
||||||
assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
|
assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -547,9 +555,8 @@ class MessagesPresenterTest {
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
skipItems(1)
|
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.ViewSource, aMessageEvent()))
|
initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.ViewSource, aMessageEvent()))
|
||||||
assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
|
assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
|
||||||
assertThat(navigator.onShowEventDebugInfoClickedCount).isEqualTo(1)
|
assertThat(navigator.onShowEventDebugInfoClickedCount).isEqualTo(1)
|
||||||
}
|
}
|
||||||
|
|
@ -572,21 +579,18 @@ class MessagesPresenterTest {
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
skipItems(1)
|
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
// Initially the composer doesn't have focus, so we don't show the alert
|
// Initially the composer doesn't have focus, so we don't show the alert
|
||||||
assertThat(initialState.showReinvitePrompt).isFalse()
|
assertThat(initialState.showReinvitePrompt).isFalse()
|
||||||
// When the input field is focused we show the alert
|
// When the input field is focused we show the alert
|
||||||
initialState.composerState.textEditorState.requestFocus()
|
(initialState.composerState.textEditorState as TextEditorState.Markdown).state.hasFocus = true
|
||||||
val focusedState = consumeItemsUntilPredicate(timeout = 250.milliseconds) { state ->
|
skipItems(1)
|
||||||
state.showReinvitePrompt
|
val focusedState = awaitItem()
|
||||||
}.last()
|
|
||||||
assertThat(focusedState.showReinvitePrompt).isTrue()
|
assertThat(focusedState.showReinvitePrompt).isTrue()
|
||||||
// If it's dismissed then we stop showing the alert
|
// If it's dismissed then we stop showing the alert
|
||||||
initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Cancel))
|
initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Cancel))
|
||||||
val dismissedState = consumeItemsUntilPredicate(timeout = 250.milliseconds) { state ->
|
skipItems(1)
|
||||||
!state.showReinvitePrompt
|
val dismissedState = awaitItem()
|
||||||
}.last()
|
|
||||||
assertThat(dismissedState.showReinvitePrompt).isFalse()
|
assertThat(dismissedState.showReinvitePrompt).isFalse()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -608,9 +612,9 @@ class MessagesPresenterTest {
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
val initialState = awaitFirstItem()
|
val initialState = awaitItem()
|
||||||
assertThat(initialState.showReinvitePrompt).isFalse()
|
assertThat(initialState.showReinvitePrompt).isFalse()
|
||||||
initialState.composerState.textEditorState.requestFocus()
|
(initialState.composerState.textEditorState as TextEditorState.Markdown).state.hasFocus = true
|
||||||
val focusedState = awaitItem()
|
val focusedState = awaitItem()
|
||||||
assertThat(focusedState.showReinvitePrompt).isFalse()
|
assertThat(focusedState.showReinvitePrompt).isFalse()
|
||||||
}
|
}
|
||||||
|
|
@ -633,9 +637,9 @@ class MessagesPresenterTest {
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
val initialState = awaitFirstItem()
|
val initialState = awaitItem()
|
||||||
assertThat(initialState.showReinvitePrompt).isFalse()
|
assertThat(initialState.showReinvitePrompt).isFalse()
|
||||||
initialState.composerState.textEditorState.requestFocus()
|
(initialState.composerState.textEditorState as TextEditorState.Markdown).state.hasFocus = true
|
||||||
val focusedState = awaitItem()
|
val focusedState = awaitItem()
|
||||||
assertThat(focusedState.showReinvitePrompt).isFalse()
|
assertThat(focusedState.showReinvitePrompt).isFalse()
|
||||||
}
|
}
|
||||||
|
|
@ -799,7 +803,8 @@ class MessagesPresenterTest {
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
val state = awaitFirstItem()
|
skipItems(1)
|
||||||
|
val state = awaitItem()
|
||||||
assertThat(state.userEventPermissions.canSendMessage).isTrue()
|
assertThat(state.userEventPermissions.canSendMessage).isTrue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -826,9 +831,7 @@ class MessagesPresenterTest {
|
||||||
}.test {
|
}.test {
|
||||||
// Default value
|
// Default value
|
||||||
assertThat(awaitItem().userEventPermissions.canSendMessage).isTrue()
|
assertThat(awaitItem().userEventPermissions.canSendMessage).isTrue()
|
||||||
skipItems(1)
|
|
||||||
assertThat(awaitItem().userEventPermissions.canSendMessage).isFalse()
|
assertThat(awaitItem().userEventPermissions.canSendMessage).isFalse()
|
||||||
cancelAndIgnoreRemainingEvents()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -876,21 +879,27 @@ class MessagesPresenterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - handle action reply to a poll`() = runTest {
|
fun `present - handle action reply to a poll`() = runTest {
|
||||||
val presenter = createMessagesPresenter()
|
val composerRecorder = EventsRecorder<MessageComposerEvents>()
|
||||||
|
val presenter = createMessagesPresenter(
|
||||||
|
messageComposerPresenter = { aMessageComposerState(eventSink = composerRecorder) },
|
||||||
|
)
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
val initialState = awaitFirstItem()
|
val initialState = awaitItem()
|
||||||
val poll = aMessageEvent(
|
val poll = aMessageEvent(
|
||||||
content = aTimelineItemPollContent()
|
content = aTimelineItemPollContent()
|
||||||
)
|
)
|
||||||
initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Reply, poll))
|
initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Reply, poll))
|
||||||
val finalState = awaitItem()
|
val finalState = awaitItem()
|
||||||
assertThat(finalState.composerState.mode).isInstanceOf(MessageComposerMode.Reply::class.java)
|
composerRecorder.assertSingle(
|
||||||
val replyMode = finalState.composerState.mode as MessageComposerMode.Reply
|
MessageComposerEvents.SetMode(
|
||||||
|
composerMode = MessageComposerMode.Reply(
|
||||||
assertThat(replyMode.replyToDetails).isInstanceOf(InReplyToDetails.Loading::class.java)
|
replyToDetails = InReplyToDetails.Loading(AN_EVENT_ID),
|
||||||
assertThat(finalState.actionListState.target).isEqualTo(ActionListState.Target.None)
|
hideImage = false,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -916,15 +925,16 @@ class MessagesPresenterTest {
|
||||||
val messageEvent = aMessageEvent(
|
val messageEvent = aMessageEvent(
|
||||||
content = aTimelineItemTextContent()
|
content = aTimelineItemTextContent()
|
||||||
)
|
)
|
||||||
val initialState = awaitFirstItem()
|
val initialState = awaitItem()
|
||||||
|
|
||||||
timeline.pinEventLambda = successPinEventLambda
|
timeline.pinEventLambda = successPinEventLambda
|
||||||
initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Pin, messageEvent))
|
initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Pin, messageEvent))
|
||||||
assert(successPinEventLambda).isCalledOnce().with(value(messageEvent.eventId))
|
assert(successPinEventLambda).isCalledOnce().with(value(messageEvent.eventId))
|
||||||
|
|
||||||
timeline.pinEventLambda = failurePinEventLambda
|
timeline.pinEventLambda = failurePinEventLambda
|
||||||
initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Pin, messageEvent))
|
initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Pin, messageEvent))
|
||||||
assert(failurePinEventLambda).isCalledOnce().with(value(messageEvent.eventId))
|
assert(failurePinEventLambda).isCalledOnce().with(value(messageEvent.eventId))
|
||||||
|
skipItems(1)
|
||||||
assertThat(awaitItem().snackbarMessage).isNotNull()
|
assertThat(awaitItem().snackbarMessage).isNotNull()
|
||||||
assertThat(analyticsService.capturedEvents).containsExactly(
|
assertThat(analyticsService.capturedEvents).containsExactly(
|
||||||
PinUnpinAction(kind = PinUnpinAction.Kind.Pin, from = PinUnpinAction.From.Timeline),
|
PinUnpinAction(kind = PinUnpinAction.Kind.Pin, from = PinUnpinAction.From.Timeline),
|
||||||
|
|
@ -955,15 +965,16 @@ class MessagesPresenterTest {
|
||||||
val messageEvent = aMessageEvent(
|
val messageEvent = aMessageEvent(
|
||||||
content = aTimelineItemTextContent()
|
content = aTimelineItemTextContent()
|
||||||
)
|
)
|
||||||
val initialState = awaitFirstItem()
|
val initialState = awaitItem()
|
||||||
|
|
||||||
timeline.unpinEventLambda = successUnpinEventLambda
|
timeline.unpinEventLambda = successUnpinEventLambda
|
||||||
initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Unpin, messageEvent))
|
initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Unpin, messageEvent))
|
||||||
assert(successUnpinEventLambda).isCalledOnce().with(value(messageEvent.eventId))
|
assert(successUnpinEventLambda).isCalledOnce().with(value(messageEvent.eventId))
|
||||||
|
|
||||||
timeline.unpinEventLambda = failureUnpinEventLambda
|
timeline.unpinEventLambda = failureUnpinEventLambda
|
||||||
initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Unpin, messageEvent))
|
initialState.eventSink(MessagesEvents.HandleAction(TimelineItemAction.Unpin, messageEvent))
|
||||||
assert(failureUnpinEventLambda).isCalledOnce().with(value(messageEvent.eventId))
|
assert(failureUnpinEventLambda).isCalledOnce().with(value(messageEvent.eventId))
|
||||||
|
skipItems(1)
|
||||||
assertThat(awaitItem().snackbarMessage).isNotNull()
|
assertThat(awaitItem().snackbarMessage).isNotNull()
|
||||||
assertThat(analyticsService.capturedEvents).containsExactly(
|
assertThat(analyticsService.capturedEvents).containsExactly(
|
||||||
PinUnpinAction(kind = PinUnpinAction.Kind.Unpin, from = PinUnpinAction.From.Timeline),
|
PinUnpinAction(kind = PinUnpinAction.Kind.Unpin, from = PinUnpinAction.From.Timeline),
|
||||||
|
|
@ -972,12 +983,6 @@ class MessagesPresenterTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun <T> ReceiveTurbine<T>.awaitFirstItem(): T {
|
|
||||||
// Skip 2 item if Mentions feature is enabled, else 1
|
|
||||||
skipItems(if (FeatureFlags.Mentions.defaultValue(aBuildMeta())) 2 else 1)
|
|
||||||
return awaitItem()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun TestScope.createMessagesPresenter(
|
private fun TestScope.createMessagesPresenter(
|
||||||
coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers(),
|
coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers(),
|
||||||
matrixRoom: MatrixRoom = FakeMatrixRoom(
|
matrixRoom: MatrixRoom = FakeMatrixRoom(
|
||||||
|
|
@ -993,83 +998,34 @@ class MessagesPresenterTest {
|
||||||
navigator: FakeMessagesNavigator = FakeMessagesNavigator(),
|
navigator: FakeMessagesNavigator = FakeMessagesNavigator(),
|
||||||
clipboardHelper: FakeClipboardHelper = FakeClipboardHelper(),
|
clipboardHelper: FakeClipboardHelper = FakeClipboardHelper(),
|
||||||
analyticsService: FakeAnalyticsService = FakeAnalyticsService(),
|
analyticsService: FakeAnalyticsService = FakeAnalyticsService(),
|
||||||
permissionsPresenter: PermissionsPresenter = FakePermissionsPresenter(),
|
|
||||||
endPollAction: EndPollAction = FakeEndPollAction(),
|
endPollAction: EndPollAction = FakeEndPollAction(),
|
||||||
permalinkParser: PermalinkParser = FakePermalinkParser(),
|
permalinkParser: PermalinkParser = FakePermalinkParser(),
|
||||||
|
messageComposerPresenter: Presenter<MessageComposerState> = Presenter {
|
||||||
|
aMessageComposerState(
|
||||||
|
// Use TextEditorState.Markdown, so that we can request focus manually.
|
||||||
|
textEditorState = TextEditorState.Markdown(MarkdownTextEditorState(initialText = "", initialFocus = false))
|
||||||
|
)
|
||||||
|
},
|
||||||
|
actionListEventSink: (ActionListEvents) -> Unit = {},
|
||||||
): MessagesPresenter {
|
): MessagesPresenter {
|
||||||
val mediaSender = MediaSender(FakeMediaPreProcessor(), matrixRoom)
|
|
||||||
val permissionsPresenterFactory = FakePermissionsPresenterFactory(permissionsPresenter)
|
|
||||||
val sessionPreferencesStore = InMemorySessionPreferencesStore()
|
|
||||||
val mentionSpanProvider = MentionSpanProvider(FakePermalinkParser())
|
|
||||||
val messageComposerPresenter = MessageComposerPresenter(
|
|
||||||
appCoroutineScope = this,
|
|
||||||
room = matrixRoom,
|
|
||||||
mediaPickerProvider = FakePickerProvider(),
|
|
||||||
featureFlagService = FakeFeatureFlagService(mapOf(FeatureFlags.NotificationSettings.key to true)),
|
|
||||||
sessionPreferencesStore = InMemorySessionPreferencesStore(),
|
|
||||||
localMediaFactory = FakeLocalMediaFactory(mockMediaUrl),
|
|
||||||
mediaSender = mediaSender,
|
|
||||||
snackbarDispatcher = SnackbarDispatcher(),
|
|
||||||
analyticsService = analyticsService,
|
|
||||||
messageComposerContext = DefaultMessageComposerContext(),
|
|
||||||
richTextEditorStateFactory = TestRichTextEditorStateFactory(),
|
|
||||||
roomAliasSuggestionsDataSource = FakeRoomAliasSuggestionsDataSource(),
|
|
||||||
permissionsPresenterFactory = permissionsPresenterFactory,
|
|
||||||
permalinkParser = FakePermalinkParser(),
|
|
||||||
permalinkBuilder = FakePermalinkBuilder(),
|
|
||||||
timelineController = TimelineController(matrixRoom),
|
|
||||||
draftService = FakeComposerDraftService(),
|
|
||||||
mentionSpanProvider = mentionSpanProvider,
|
|
||||||
pillificationHelper = FakeTextPillificationHelper(),
|
|
||||||
roomMemberProfilesCache = RoomMemberProfilesCache(),
|
|
||||||
suggestionsProcessor = SuggestionsProcessor(),
|
|
||||||
).apply {
|
|
||||||
showTextFormatting = true
|
|
||||||
isTesting = true
|
|
||||||
}
|
|
||||||
val voiceMessageComposerPresenter = VoiceMessageComposerPresenter(
|
|
||||||
this,
|
|
||||||
FakeVoiceRecorder(),
|
|
||||||
analyticsService,
|
|
||||||
mediaSender,
|
|
||||||
player = VoiceMessageComposerPlayer(FakeMediaPlayer(), this),
|
|
||||||
messageComposerContext = FakeMessageComposerContext(),
|
|
||||||
permissionsPresenterFactory,
|
|
||||||
)
|
|
||||||
val timelinePresenter = TimelinePresenter(
|
|
||||||
timelineItemsFactoryCreator = aTimelineItemsFactoryCreator(),
|
|
||||||
room = matrixRoom,
|
|
||||||
dispatchers = coroutineDispatchers,
|
|
||||||
appScope = this,
|
|
||||||
navigator = navigator,
|
|
||||||
redactedVoiceMessageManager = FakeRedactedVoiceMessageManager(),
|
|
||||||
endPollAction = endPollAction,
|
|
||||||
sendPollResponseAction = FakeSendPollResponseAction(),
|
|
||||||
sessionPreferencesStore = sessionPreferencesStore,
|
|
||||||
timelineItemIndexer = TimelineItemIndexer(),
|
|
||||||
timelineController = TimelineController(matrixRoom),
|
|
||||||
resolveVerifiedUserSendFailurePresenter = { aResolveVerifiedUserSendFailureState() },
|
|
||||||
typingNotificationPresenter = { aTypingNotificationState() },
|
|
||||||
)
|
|
||||||
val timelinePresenterFactory = object : TimelinePresenter.Factory {
|
val timelinePresenterFactory = object : TimelinePresenter.Factory {
|
||||||
override fun create(navigator: MessagesNavigator): TimelinePresenter {
|
override fun create(navigator: MessagesNavigator): TimelinePresenter {
|
||||||
return timelinePresenter
|
return createTimelinePresenter(
|
||||||
|
endPollAction = endPollAction,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val featureFlagService = FakeFeatureFlagService()
|
val featureFlagService = FakeFeatureFlagService()
|
||||||
val readReceiptBottomSheetPresenter = ReadReceiptBottomSheetPresenter()
|
|
||||||
val customReactionPresenter = CustomReactionPresenter(emojibaseProvider = FakeEmojibaseProvider())
|
|
||||||
val reactionSummaryPresenter = ReactionSummaryPresenter(room = matrixRoom)
|
|
||||||
return MessagesPresenter(
|
return MessagesPresenter(
|
||||||
room = matrixRoom,
|
room = matrixRoom,
|
||||||
composerPresenter = messageComposerPresenter,
|
composerPresenter = messageComposerPresenter,
|
||||||
voiceMessageComposerPresenter = voiceMessageComposerPresenter,
|
voiceMessageComposerPresenter = { aVoiceMessageComposerState() },
|
||||||
timelinePresenterFactory = timelinePresenterFactory,
|
timelinePresenterFactory = timelinePresenterFactory,
|
||||||
timelineProtectionPresenter = { aTimelineProtectionState() },
|
timelineProtectionPresenter = { aTimelineProtectionState() },
|
||||||
actionListPresenterFactory = FakeActionListPresenter.Factory,
|
actionListPresenterFactory = FakeActionListPresenter.Factory(actionListEventSink),
|
||||||
customReactionPresenter = customReactionPresenter,
|
customReactionPresenter = { aCustomReactionState() },
|
||||||
reactionSummaryPresenter = reactionSummaryPresenter,
|
reactionSummaryPresenter = { aReactionSummaryState() },
|
||||||
readReceiptBottomSheetPresenter = readReceiptBottomSheetPresenter,
|
readReceiptBottomSheetPresenter = { aReadReceiptBottomSheetState() },
|
||||||
pinnedMessagesBannerPresenter = { aLoadedPinnedMessagesBannerState() },
|
pinnedMessagesBannerPresenter = { aLoadedPinnedMessagesBannerState() },
|
||||||
networkMonitor = FakeNetworkMonitor(),
|
networkMonitor = FakeNetworkMonitor(),
|
||||||
snackbarDispatcher = SnackbarDispatcher(),
|
snackbarDispatcher = SnackbarDispatcher(),
|
||||||
|
|
|
||||||
|
|
@ -10,15 +10,15 @@ package io.element.android.features.messages.impl.actionlist
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionPostProcessor
|
import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionPostProcessor
|
||||||
|
|
||||||
class FakeActionListPresenter : ActionListPresenter {
|
class FakeActionListPresenter(private val eventSink: (ActionListEvents) -> Unit = {}) : ActionListPresenter {
|
||||||
object Factory : ActionListPresenter.Factory {
|
class Factory(private val eventSink: (ActionListEvents) -> Unit = {}) : ActionListPresenter.Factory {
|
||||||
override fun create(postProcessor: TimelineItemActionPostProcessor): ActionListPresenter {
|
override fun create(postProcessor: TimelineItemActionPostProcessor): ActionListPresenter {
|
||||||
return FakeActionListPresenter()
|
return FakeActionListPresenter(eventSink)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun present(): ActionListState {
|
override fun present(): ActionListState {
|
||||||
return anActionListState()
|
return anActionListState(eventSink = eventSink)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -312,7 +312,7 @@ class PinnedMessagesListPresenterTest {
|
||||||
timelineProvider = timelineProvider,
|
timelineProvider = timelineProvider,
|
||||||
timelineProtectionPresenter = { aTimelineProtectionState() },
|
timelineProtectionPresenter = { aTimelineProtectionState() },
|
||||||
snackbarDispatcher = SnackbarDispatcher(),
|
snackbarDispatcher = SnackbarDispatcher(),
|
||||||
actionListPresenterFactory = FakeActionListPresenter.Factory,
|
actionListPresenterFactory = FakeActionListPresenter.Factory(),
|
||||||
analyticsService = analyticsService,
|
analyticsService = analyticsService,
|
||||||
appCoroutineScope = this,
|
appCoroutineScope = this,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -656,34 +656,34 @@ import kotlin.time.Duration.Companion.seconds
|
||||||
private suspend fun <T> ReceiveTurbine<T>.awaitFirstItem(): T {
|
private suspend fun <T> ReceiveTurbine<T>.awaitFirstItem(): T {
|
||||||
return awaitItem()
|
return awaitItem()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private fun TestScope.createTimelinePresenter(
|
|
||||||
timeline: Timeline = FakeTimeline(),
|
internal fun TestScope.createTimelinePresenter(
|
||||||
room: FakeMatrixRoom = FakeMatrixRoom(
|
timeline: Timeline = FakeTimeline(),
|
||||||
liveTimeline = timeline,
|
room: FakeMatrixRoom = FakeMatrixRoom(
|
||||||
canUserSendMessageResult = { _, _ -> Result.success(true) }
|
liveTimeline = timeline,
|
||||||
),
|
canUserSendMessageResult = { _, _ -> Result.success(true) }
|
||||||
redactedVoiceMessageManager: RedactedVoiceMessageManager = FakeRedactedVoiceMessageManager(),
|
),
|
||||||
messagesNavigator: FakeMessagesNavigator = FakeMessagesNavigator(),
|
redactedVoiceMessageManager: RedactedVoiceMessageManager = FakeRedactedVoiceMessageManager(),
|
||||||
endPollAction: EndPollAction = FakeEndPollAction(),
|
messagesNavigator: FakeMessagesNavigator = FakeMessagesNavigator(),
|
||||||
sendPollResponseAction: SendPollResponseAction = FakeSendPollResponseAction(),
|
endPollAction: EndPollAction = FakeEndPollAction(),
|
||||||
sessionPreferencesStore: InMemorySessionPreferencesStore = InMemorySessionPreferencesStore(),
|
sendPollResponseAction: SendPollResponseAction = FakeSendPollResponseAction(),
|
||||||
timelineItemIndexer: TimelineItemIndexer = TimelineItemIndexer(),
|
sessionPreferencesStore: InMemorySessionPreferencesStore = InMemorySessionPreferencesStore(),
|
||||||
): TimelinePresenter {
|
timelineItemIndexer: TimelineItemIndexer = TimelineItemIndexer(),
|
||||||
return TimelinePresenter(
|
): TimelinePresenter {
|
||||||
timelineItemsFactoryCreator = aTimelineItemsFactoryCreator(),
|
return TimelinePresenter(
|
||||||
room = room,
|
timelineItemsFactoryCreator = aTimelineItemsFactoryCreator(),
|
||||||
dispatchers = testCoroutineDispatchers(),
|
room = room,
|
||||||
appScope = this,
|
dispatchers = testCoroutineDispatchers(),
|
||||||
navigator = messagesNavigator,
|
appScope = this,
|
||||||
redactedVoiceMessageManager = redactedVoiceMessageManager,
|
navigator = messagesNavigator,
|
||||||
endPollAction = endPollAction,
|
redactedVoiceMessageManager = redactedVoiceMessageManager,
|
||||||
sendPollResponseAction = sendPollResponseAction,
|
endPollAction = endPollAction,
|
||||||
sessionPreferencesStore = sessionPreferencesStore,
|
sendPollResponseAction = sendPollResponseAction,
|
||||||
timelineItemIndexer = timelineItemIndexer,
|
sessionPreferencesStore = sessionPreferencesStore,
|
||||||
timelineController = TimelineController(room),
|
timelineItemIndexer = timelineItemIndexer,
|
||||||
resolveVerifiedUserSendFailurePresenter = { aResolveVerifiedUserSendFailureState() },
|
timelineController = TimelineController(room),
|
||||||
typingNotificationPresenter = { aTypingNotificationState() },
|
resolveVerifiedUserSendFailurePresenter = { aResolveVerifiedUserSendFailureState() },
|
||||||
)
|
typingNotificationPresenter = { aTypingNotificationState() },
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue