Let the Presenter use real classes.

This commit is contained in:
Benoit Marty 2024-12-10 15:56:54 +01:00
parent 7a3bd38c96
commit 57fc19d545
11 changed files with 45 additions and 145 deletions

View file

@ -51,6 +51,7 @@ dependencies {
implementation(projects.libraries.di) implementation(projects.libraries.di)
implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrix.api)
testImplementation(projects.libraries.dateformatter.test)
testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.featureflag.test)
testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.matrix.test)
testImplementation(projects.libraries.mediaviewer.test) testImplementation(projects.libraries.mediaviewer.test)

View file

@ -7,10 +7,8 @@
package io.element.android.libraries.mediaviewer.impl.gallery package io.element.android.libraries.mediaviewer.impl.gallery
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.androidutils.filesize.FileSizeFormatter import io.element.android.libraries.androidutils.filesize.FileSizeFormatter
import io.element.android.libraries.dateformatter.api.toHumanReadableDuration import io.element.android.libraries.dateformatter.api.toHumanReadableDuration
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.CallNotifyContent import io.element.android.libraries.matrix.api.timeline.item.event.CallNotifyContent
@ -45,18 +43,13 @@ import java.text.DateFormat
import java.util.Date import java.util.Date
import javax.inject.Inject import javax.inject.Inject
interface EventItemFactory { class EventItemFactory @Inject constructor(
fun create(currentTimelineItem: MatrixTimelineItem.Event): MediaItem.Event?
}
@ContributesBinding(RoomScope::class)
class DefaultEventItemFactory @Inject constructor(
private val fileSizeFormatter: FileSizeFormatter, private val fileSizeFormatter: FileSizeFormatter,
private val fileExtensionExtractor: FileExtensionExtractor, private val fileExtensionExtractor: FileExtensionExtractor,
) : EventItemFactory { ) {
private val timeFormatter = DateFormat.getDateInstance() private val timeFormatter = DateFormat.getDateInstance()
override fun create( fun create(
currentTimelineItem: MatrixTimelineItem.Event, currentTimelineItem: MatrixTimelineItem.Event,
): MediaItem.Event? { ): MediaItem.Event? {
val event = currentTimelineItem.event val event = currentTimelineItem.event

View file

@ -7,23 +7,14 @@
package io.element.android.libraries.mediaviewer.impl.gallery package io.element.android.libraries.mediaviewer.impl.gallery
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.di.RoomScope
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import javax.inject.Inject import javax.inject.Inject
interface MediaItemsPostProcessor { class MediaItemsPostProcessor @Inject constructor() {
fun process( fun process(
mediaItems: AsyncData<ImmutableList<MediaItem>>, mediaItems: AsyncData<ImmutableList<MediaItem>>,
): AsyncData<GroupedMediaItems>
}
@ContributesBinding(RoomScope::class)
class DefaultMediaItemsPostProcessor @Inject constructor() : MediaItemsPostProcessor {
override fun process(
mediaItems: AsyncData<ImmutableList<MediaItem>>,
): AsyncData<GroupedMediaItems> { ): AsyncData<GroupedMediaItems> {
return when (mediaItems) { return when (mediaItems) {
is AsyncData.Uninitialized -> AsyncData.Uninitialized is AsyncData.Uninitialized -> AsyncData.Uninitialized

View file

@ -7,12 +7,10 @@
package io.element.android.libraries.mediaviewer.impl.gallery package io.element.android.libraries.mediaviewer.impl.gallery
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.androidutils.diff.DefaultDiffCacheInvalidator import io.element.android.libraries.androidutils.diff.DefaultDiffCacheInvalidator
import io.element.android.libraries.androidutils.diff.DiffCacheUpdater import io.element.android.libraries.androidutils.diff.DiffCacheUpdater
import io.element.android.libraries.androidutils.diff.MutableListDiffCache import io.element.android.libraries.androidutils.diff.MutableListDiffCache
import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toPersistentList
@ -24,17 +22,11 @@ import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import javax.inject.Inject import javax.inject.Inject
interface TimelineMediaItemsFactory { class TimelineMediaItemsFactory @Inject constructor(
val timelineItems: Flow<ImmutableList<MediaItem>>
suspend fun replaceWith(timelineItems: List<MatrixTimelineItem>)
}
@ContributesBinding(RoomScope::class)
class DefaultTimelineMediaItemsFactory @Inject constructor(
private val dispatchers: CoroutineDispatchers, private val dispatchers: CoroutineDispatchers,
private val virtualItemFactory: VirtualItemFactory, private val virtualItemFactory: VirtualItemFactory,
private val eventItemFactory: EventItemFactory, private val eventItemFactory: EventItemFactory,
) : TimelineMediaItemsFactory { ) {
private val _timelineItems = MutableSharedFlow<ImmutableList<MediaItem>>(replay = 1) private val _timelineItems = MutableSharedFlow<ImmutableList<MediaItem>>(replay = 1)
private val lock = Mutex() private val lock = Mutex()
private val diffCache = MutableListDiffCache<MediaItem>() private val diffCache = MutableListDiffCache<MediaItem>()
@ -50,9 +42,9 @@ class DefaultTimelineMediaItemsFactory @Inject constructor(
} }
} }
override val timelineItems: Flow<ImmutableList<MediaItem>> = _timelineItems.distinctUntilChanged() val timelineItems: Flow<ImmutableList<MediaItem>> = _timelineItems.distinctUntilChanged()
override suspend fun replaceWith( suspend fun replaceWith(
timelineItems: List<MatrixTimelineItem>, timelineItems: List<MatrixTimelineItem>,
) = withContext(dispatchers.computation) { ) = withContext(dispatchers.computation) {
lock.withLock { lock.withLock {

View file

@ -7,22 +7,15 @@
package io.element.android.libraries.mediaviewer.impl.gallery package io.element.android.libraries.mediaviewer.impl.gallery
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.dateformatter.api.DaySeparatorFormatter import io.element.android.libraries.dateformatter.api.DaySeparatorFormatter
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem
import javax.inject.Inject import javax.inject.Inject
interface VirtualItemFactory { class VirtualItemFactory @Inject constructor(
fun create(timelineItem: MatrixTimelineItem.Virtual): MediaItem?
}
@ContributesBinding(RoomScope::class)
class DefaultVirtualItemFactory @Inject constructor(
private val daySeparatorFormatter: DaySeparatorFormatter, private val daySeparatorFormatter: DaySeparatorFormatter,
) : VirtualItemFactory { ) {
override fun create(timelineItem: MatrixTimelineItem.Virtual): MediaItem? { fun create(timelineItem: MatrixTimelineItem.Virtual): MediaItem? {
return when (val virtual = timelineItem.virtual) { return when (val virtual = timelineItem.virtual) {
is VirtualTimelineItem.DayDivider -> MediaItem.DateSeparator( is VirtualTimelineItem.DayDivider -> MediaItem.DateSeparator(
id = timelineItem.uniqueId, id = timelineItem.uniqueId,

View file

@ -55,7 +55,7 @@ import kotlin.time.Duration.Companion.seconds
class DefaultEventItemFactoryTest { class DefaultEventItemFactoryTest {
@Test @Test
fun `create check all null cases`() { fun `create check all null cases`() {
val factory = createDefaultEventItemFactory() val factory = createEventItemFactory()
val contents = listOf( val contents = listOf(
CallNotifyContent, CallNotifyContent,
FailedToParseMessageLikeContent("", ""), FailedToParseMessageLikeContent("", ""),
@ -100,7 +100,7 @@ class DefaultEventItemFactoryTest {
@Test @Test
fun `create MessageContent check all null cases`() { fun `create MessageContent check all null cases`() {
val factory = createDefaultEventItemFactory() val factory = createEventItemFactory()
val messageTypes = listOf( val messageTypes = listOf(
EmoteMessageType("", null), EmoteMessageType("", null),
NoticeMessageType("", null), NoticeMessageType("", null),
@ -125,7 +125,7 @@ class DefaultEventItemFactoryTest {
@Test @Test
fun `create for FileMessageType`() { fun `create for FileMessageType`() {
val factory = createDefaultEventItemFactory() val factory = createEventItemFactory()
val result = factory.create( val result = factory.create(
MatrixTimelineItem.Event( MatrixTimelineItem.Event(
uniqueId = A_UNIQUE_ID, uniqueId = A_UNIQUE_ID,
@ -169,7 +169,7 @@ class DefaultEventItemFactoryTest {
@Test @Test
fun `create for ImageMessageType`() { fun `create for ImageMessageType`() {
val factory = createDefaultEventItemFactory() val factory = createEventItemFactory()
val result = factory.create( val result = factory.create(
MatrixTimelineItem.Event( MatrixTimelineItem.Event(
uniqueId = A_UNIQUE_ID, uniqueId = A_UNIQUE_ID,
@ -217,7 +217,7 @@ class DefaultEventItemFactoryTest {
@Test @Test
fun `create for AudioMessageType`() { fun `create for AudioMessageType`() {
val factory = createDefaultEventItemFactory() val factory = createEventItemFactory()
val result = factory.create( val result = factory.create(
MatrixTimelineItem.Event( MatrixTimelineItem.Event(
uniqueId = A_UNIQUE_ID, uniqueId = A_UNIQUE_ID,
@ -260,7 +260,7 @@ class DefaultEventItemFactoryTest {
@Test @Test
fun `create for VideoMessageType`() { fun `create for VideoMessageType`() {
val factory = createDefaultEventItemFactory() val factory = createEventItemFactory()
val result = factory.create( val result = factory.create(
MatrixTimelineItem.Event( MatrixTimelineItem.Event(
uniqueId = A_UNIQUE_ID, uniqueId = A_UNIQUE_ID,
@ -310,7 +310,7 @@ class DefaultEventItemFactoryTest {
@Test @Test
fun `create for VoiceMessageType`() { fun `create for VoiceMessageType`() {
val factory = createDefaultEventItemFactory() val factory = createEventItemFactory()
val result = factory.create( val result = factory.create(
MatrixTimelineItem.Event( MatrixTimelineItem.Event(
uniqueId = A_UNIQUE_ID, uniqueId = A_UNIQUE_ID,
@ -357,7 +357,7 @@ class DefaultEventItemFactoryTest {
@Test @Test
fun `create for StickerMessageType`() { fun `create for StickerMessageType`() {
val factory = createDefaultEventItemFactory() val factory = createEventItemFactory()
val result = factory.create( val result = factory.create(
MatrixTimelineItem.Event( MatrixTimelineItem.Event(
uniqueId = A_UNIQUE_ID, uniqueId = A_UNIQUE_ID,
@ -404,7 +404,7 @@ class DefaultEventItemFactoryTest {
} }
} }
private fun createDefaultEventItemFactory() = DefaultEventItemFactory( private fun createEventItemFactory() = EventItemFactory(
fileSizeFormatter = FakeFileSizeFormatter(), fileSizeFormatter = FakeFileSizeFormatter(),
fileExtensionExtractor = FileExtensionExtractorWithoutValidation(), fileExtensionExtractor = FileExtensionExtractorWithoutValidation(),
) )

View file

@ -1,16 +0,0 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.mediaviewer.impl.gallery
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
class FakeEventItemFactory : EventItemFactory {
override fun create(currentTimelineItem: MatrixTimelineItem.Event): MediaItem.Event? {
return null
}
}

View file

@ -1,23 +0,0 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.mediaviewer.impl.gallery
import io.element.android.libraries.architecture.AsyncData
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
class FakeMediaItemsPostProcessor : MediaItemsPostProcessor {
override fun process(mediaItems: AsyncData<ImmutableList<MediaItem>>): AsyncData<GroupedMediaItems> {
return AsyncData.Success(
GroupedMediaItems(
imageAndVideoItems = persistentListOf(),
fileItems = persistentListOf()
)
)
}
}

View file

@ -1,26 +0,0 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.mediaviewer.impl.gallery
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.tests.testutils.lambda.lambdaError
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
class FakeTimelineMediaItemsFactory(
private val replaceWithLambda: (List<MatrixTimelineItem>) -> Unit = { lambdaError() },
) : TimelineMediaItemsFactory {
override val timelineItems: Flow<ImmutableList<MediaItem>>
get() = flowOf(emptyList<MediaItem>().toImmutableList())
override suspend fun replaceWith(timelineItems: List<MatrixTimelineItem>) {
replaceWithLambda(timelineItems)
}
}

View file

@ -1,16 +0,0 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.mediaviewer.impl.gallery
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
class FakeVirtualItemFactory : VirtualItemFactory {
override fun create(timelineItem: MatrixTimelineItem.Virtual): MediaItem? {
return null
}
}

View file

@ -9,10 +9,11 @@ package io.element.android.libraries.mediaviewer.impl.gallery
import android.net.Uri import android.net.Uri
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.androidutils.filesize.FakeFileSizeFormatter
import io.element.android.libraries.dateformatter.test.FakeDaySeparatorFormatter
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
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.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_ROOM_NAME import io.element.android.libraries.matrix.test.A_ROOM_NAME
import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.A_USER_ID
@ -24,12 +25,15 @@ import io.element.android.libraries.mediaviewer.impl.details.MediaBottomSheetSta
import io.element.android.libraries.mediaviewer.impl.gallery.ui.aMediaItemImage import io.element.android.libraries.mediaviewer.impl.gallery.ui.aMediaItemImage
import io.element.android.libraries.mediaviewer.test.FakeLocalMediaActions import io.element.android.libraries.mediaviewer.test.FakeLocalMediaActions
import io.element.android.libraries.mediaviewer.test.FakeLocalMediaFactory import io.element.android.libraries.mediaviewer.test.FakeLocalMediaFactory
import io.element.android.libraries.mediaviewer.test.util.FileExtensionExtractorWithoutValidation
import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.WarmUpRule
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.test import io.element.android.tests.testutils.test
import io.element.android.tests.testutils.testCoroutineDispatchers
import io.mockk.mockk import io.mockk.mockk
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
@ -55,7 +59,7 @@ class MediaGalleryPresenterTest {
) )
) )
presenter.test { presenter.test {
skipItems(1) skipItems(2)
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState.mode).isEqualTo(MediaGalleryMode.Images) assertThat(initialState.mode).isEqualTo(MediaGalleryMode.Images)
assertThat(initialState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) assertThat(initialState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden)
@ -84,7 +88,7 @@ class MediaGalleryPresenterTest {
) )
) )
presenter.test { presenter.test {
skipItems(1) skipItems(2)
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState.mode).isEqualTo(MediaGalleryMode.Images) assertThat(initialState.mode).isEqualTo(MediaGalleryMode.Images)
initialState.eventSink(MediaGalleryEvents.ChangeMode(MediaGalleryMode.Files)) initialState.eventSink(MediaGalleryEvents.ChangeMode(MediaGalleryMode.Files))
@ -106,7 +110,7 @@ class MediaGalleryPresenterTest {
`present - bottom sheet state - own message`(canDeleteOwn = false) `present - bottom sheet state - own message`(canDeleteOwn = false)
} }
private suspend fun `present - bottom sheet state - own message`(canDeleteOwn: Boolean) { private suspend fun TestScope.`present - bottom sheet state - own message`(canDeleteOwn: Boolean) {
val presenter = createMediaGalleryPresenter( val presenter = createMediaGalleryPresenter(
room = FakeMatrixRoom( room = FakeMatrixRoom(
sessionId = A_USER_ID, sessionId = A_USER_ID,
@ -116,7 +120,7 @@ class MediaGalleryPresenterTest {
) )
) )
presenter.test { presenter.test {
skipItems(1) skipItems(2)
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) assertThat(initialState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden)
val item = aMediaItemImage( val item = aMediaItemImage(
@ -150,7 +154,7 @@ class MediaGalleryPresenterTest {
`present - bottom sheet state - other message`(canDeleteOther = false) `present - bottom sheet state - other message`(canDeleteOther = false)
} }
private suspend fun `present - bottom sheet state - other message`(canDeleteOther: Boolean) { private suspend fun TestScope.`present - bottom sheet state - other message`(canDeleteOther: Boolean) {
val presenter = createMediaGalleryPresenter( val presenter = createMediaGalleryPresenter(
room = FakeMatrixRoom( room = FakeMatrixRoom(
sessionId = A_USER_ID, sessionId = A_USER_ID,
@ -160,7 +164,7 @@ class MediaGalleryPresenterTest {
) )
) )
presenter.test { presenter.test {
skipItems(1) skipItems(2)
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden) assertThat(initialState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden)
val item = aMediaItemImage( val item = aMediaItemImage(
@ -193,7 +197,7 @@ class MediaGalleryPresenterTest {
) )
) )
presenter.test { presenter.test {
skipItems(1) skipItems(2)
val initialState = awaitItem() val initialState = awaitItem()
// Delete bottom sheet // Delete bottom sheet
val item = aMediaItemImage() val item = aMediaItemImage()
@ -226,14 +230,14 @@ class MediaGalleryPresenterTest {
navigator = navigator, navigator = navigator,
) )
presenter.test { presenter.test {
skipItems(1) skipItems(2)
val initialState = awaitItem() val initialState = awaitItem()
initialState.eventSink(MediaGalleryEvents.ViewInTimeline(AN_EVENT_ID)) initialState.eventSink(MediaGalleryEvents.ViewInTimeline(AN_EVENT_ID))
onViewInTimelineClickLambda.assertions().isCalledOnce().with(value(AN_EVENT_ID)) onViewInTimelineClickLambda.assertions().isCalledOnce().with(value(AN_EVENT_ID))
} }
} }
private fun createMediaGalleryPresenter( private fun TestScope.createMediaGalleryPresenter(
matrixMediaLoader: FakeMatrixMediaLoader = FakeMatrixMediaLoader(), matrixMediaLoader: FakeMatrixMediaLoader = FakeMatrixMediaLoader(),
localMediaActions: FakeLocalMediaActions = FakeLocalMediaActions(), localMediaActions: FakeLocalMediaActions = FakeLocalMediaActions(),
snackbarDispatcher: SnackbarDispatcher = SnackbarDispatcher(), snackbarDispatcher: SnackbarDispatcher = SnackbarDispatcher(),
@ -245,14 +249,21 @@ class MediaGalleryPresenterTest {
return MediaGalleryPresenter( return MediaGalleryPresenter(
navigator = navigator, navigator = navigator,
room = room, room = room,
timelineMediaItemsFactory = FakeTimelineMediaItemsFactory( timelineMediaItemsFactory = TimelineMediaItemsFactory(
replaceWithLambda = lambdaRecorder<List<MatrixTimelineItem>, Unit> { _ -> }, dispatchers = testCoroutineDispatchers(),
virtualItemFactory = VirtualItemFactory(
daySeparatorFormatter = FakeDaySeparatorFormatter(),
),
eventItemFactory = EventItemFactory(
fileSizeFormatter = FakeFileSizeFormatter(),
fileExtensionExtractor = FileExtensionExtractorWithoutValidation(),
),
), ),
localMediaFactory = localMediaFactory, localMediaFactory = localMediaFactory,
mediaLoader = matrixMediaLoader, mediaLoader = matrixMediaLoader,
localMediaActions = localMediaActions, localMediaActions = localMediaActions,
snackbarDispatcher = snackbarDispatcher, snackbarDispatcher = snackbarDispatcher,
mediaItemsPostProcessor = FakeMediaItemsPostProcessor(), mediaItemsPostProcessor = MediaItemsPostProcessor(),
) )
} }
} }