From bac69c4a35267083a2cd5ceddaca71bc5c3681f2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 22 Jan 2025 15:04:34 +0100 Subject: [PATCH] Add timestamp to trigger back pagination. --- .../impl/viewer/MediaViewerDataSource.kt | 14 +++++++++-- .../impl/viewer/MediaViewerNode.kt | 5 +++- .../impl/viewer/MediaViewerState.kt | 1 + .../impl/viewer/MediaViewerStateProvider.kt | 12 +++++++++- .../impl/viewer/MediaViewerView.kt | 2 +- .../impl/viewer/MediaViewerDataSourceTest.kt | 24 +++++++++++++------ .../impl/viewer/MediaViewerPresenterTest.kt | 2 ++ 7 files changed, 48 insertions(+), 12 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerDataSource.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerDataSource.kt index 97d5f626b0..9138334e90 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerDataSource.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerDataSource.kt @@ -27,6 +27,7 @@ import io.element.android.libraries.mediaviewer.impl.gallery.eventId import io.element.android.libraries.mediaviewer.impl.gallery.mediaInfo import io.element.android.libraries.mediaviewer.impl.gallery.mediaSource import io.element.android.libraries.mediaviewer.impl.gallery.thumbnailSource +import io.element.android.services.toolbox.api.systemclock.SystemClock import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toPersistentList @@ -42,6 +43,7 @@ class MediaViewerDataSource( private val galleryDataSource: MediaGalleryDataSource, private val mediaLoader: MatrixMediaLoader, private val localMediaFactory: LocalMediaFactory, + private val systemClock: SystemClock, ) { // List of media files that are currently being loaded private val mediaFiles: MutableList = mutableListOf() @@ -108,12 +110,20 @@ class MediaViewerDataSource( ) } is MediaItem.LoadingIndicator -> add( - MediaViewerPageData.Loading(mediaItem.direction) + MediaViewerPageData.Loading( + direction = mediaItem.direction, + timestamp = systemClock.epochMillis(), + ) ) } } if (isEmpty()) { - add(MediaViewerPageData.Loading(Timeline.PaginationDirection.BACKWARDS)) + add( + MediaViewerPageData.Loading( + direction = Timeline.PaginationDirection.BACKWARDS, + timestamp = systemClock.epochMillis(), + ) + ) } }.toPersistentList() diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerNode.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerNode.kt index 05a5fb759c..e06b691520 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerNode.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerNode.kt @@ -27,6 +27,7 @@ import io.element.android.libraries.mediaviewer.api.local.LocalMediaFactory import io.element.android.libraries.mediaviewer.impl.gallery.MediaGalleryMode import io.element.android.libraries.mediaviewer.impl.gallery.SingleMediaGalleryDataSource import io.element.android.libraries.mediaviewer.impl.gallery.TimelineMediaGalleryDataSource +import io.element.android.services.toolbox.api.systemclock.SystemClock @ContributesNode(RoomScope::class) class MediaViewerNode @AssistedInject constructor( @@ -37,6 +38,7 @@ class MediaViewerNode @AssistedInject constructor( mediaLoader: MatrixMediaLoader, localMediaFactory: LocalMediaFactory, coroutineDispatchers: CoroutineDispatchers, + systemClock: SystemClock, ) : Node(buildContext, plugins = plugins), MediaViewerNavigator { private val inputs = inputs() @@ -77,7 +79,8 @@ class MediaViewerNode @AssistedInject constructor( galleryMode = galleryMode, galleryDataSource = mediaGallerySource, mediaLoader = mediaLoader, - localMediaFactory = localMediaFactory + localMediaFactory = localMediaFactory, + systemClock = systemClock, ) ) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerState.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerState.kt index 60c4889f60..cf363a70f1 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerState.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerState.kt @@ -34,6 +34,7 @@ sealed interface MediaViewerPageData { data class Loading( val direction: Timeline.PaginationDirection, + val timestamp: Long, ) : MediaViewerPageData data class MediaViewerData( diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt index 88931c90fc..2c54751fed 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt @@ -151,7 +151,7 @@ open class MediaViewerStateProvider : PreviewParameterProvider }, aMediaViewerState( listOf( - MediaViewerPageData.Loading(Timeline.PaginationDirection.BACKWARDS) + aMediaViewerPageDataLoading() ), ), aMediaViewerState( @@ -162,6 +162,16 @@ open class MediaViewerStateProvider : PreviewParameterProvider ) } +fun aMediaViewerPageDataLoading( + direction: Timeline.PaginationDirection = Timeline.PaginationDirection.BACKWARDS, + timestamp: Long = 0L, +): MediaViewerPageData { + return MediaViewerPageData.Loading( + direction = direction, + timestamp = timestamp, + ) +} + fun aMediaViewerPageData( downloadedMedia: AsyncData = AsyncData.Uninitialized, mediaInfo: MediaInfo = anImageMediaInfo(), diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index c04bddb3d8..3246faa255 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -128,7 +128,7 @@ fun MediaViewerView( ) } is MediaViewerPageData.Loading -> { - LaunchedEffect(Unit) { + LaunchedEffect(dataForPage.timestamp) { state.eventSink(MediaViewerEvents.LoadMore(dataForPage.direction)) } MediaViewerLoadingPage( diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerDataSourceTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerDataSourceTest.kt index e7a684a44d..4af8fe0066 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerDataSourceTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerDataSourceTest.kt @@ -27,6 +27,8 @@ import io.element.android.libraries.mediaviewer.impl.gallery.ui.aMediaItemFile import io.element.android.libraries.mediaviewer.impl.gallery.ui.aMediaItemImage import io.element.android.libraries.mediaviewer.impl.gallery.ui.aMediaItemLoadingIndicator import io.element.android.libraries.mediaviewer.test.FakeLocalMediaFactory +import io.element.android.services.toolbox.test.systemclock.A_FAKE_TIMESTAMP +import io.element.android.services.toolbox.test.systemclock.FakeSystemClock import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value import io.element.android.tests.testutils.testCoroutineDispatchers @@ -90,7 +92,12 @@ class MediaViewerDataSourceTest { ) val result = awaitItem() assertThat(result).hasSize(1) - assertThat(result.first()).isEqualTo(MediaViewerPageData.Loading(Timeline.PaginationDirection.BACKWARDS)) + assertThat(result.first()).isEqualTo( + MediaViewerPageData.Loading( + direction = Timeline.PaginationDirection.BACKWARDS, + timestamp = A_FAKE_TIMESTAMP, + ) + ) } } @@ -118,8 +125,14 @@ class MediaViewerDataSourceTest { ) val result = awaitItem() assertThat(result).containsExactly( - MediaViewerPageData.Loading(Timeline.PaginationDirection.BACKWARDS), - MediaViewerPageData.Loading(Timeline.PaginationDirection.FORWARDS), + MediaViewerPageData.Loading( + direction = Timeline.PaginationDirection.BACKWARDS, + timestamp = A_FAKE_TIMESTAMP, + ), + MediaViewerPageData.Loading( + direction = Timeline.PaginationDirection.FORWARDS, + timestamp = A_FAKE_TIMESTAMP, + ), ) } } @@ -255,10 +268,6 @@ class MediaViewerDataSourceTest { } } - @Test - fun clearLoadingError() { - } - private fun TestScope.createMediaViewerDataSource( galleryMode: MediaGalleryMode = MediaGalleryMode.Images, galleryDataSource: MediaGalleryDataSource = FakeMediaGalleryDataSource(), @@ -270,5 +279,6 @@ class MediaViewerDataSourceTest { galleryDataSource = galleryDataSource, mediaLoader = mediaLoader, localMediaFactory = localMediaFactory, + systemClock = FakeSystemClock(), ) } diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt index 3b408cbab5..ac0acfe719 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt @@ -37,6 +37,7 @@ import io.element.android.libraries.mediaviewer.impl.gallery.MediaGalleryMode 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.FakeLocalMediaFactory +import io.element.android.services.toolbox.test.systemclock.FakeSystemClock import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value @@ -593,6 +594,7 @@ class MediaViewerPresenterTest { galleryDataSource = mediaGalleryDataSource, mediaLoader = matrixMediaLoader, localMediaFactory = localMediaFactory, + systemClock = FakeSystemClock(), ), room = room, localMediaActions = localMediaActions,