diff --git a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/InvitePeopleView.kt b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/InvitePeopleView.kt index 5363ca43f1c..bc45a3740ef 100644 --- a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/InvitePeopleView.kt +++ b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/InvitePeopleView.kt @@ -65,7 +65,7 @@ private fun InvitePeopleViewError( contentAlignment = Alignment.Center, ) { AsyncFailure( - throwable = error, + message = error.localizedMessage, onRetry = null, modifier = Modifier.padding(horizontal = 16.dp), ) diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/leave/LeaveSpaceView.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/leave/LeaveSpaceView.kt index 9c8f13405a0..4a1490c5a01 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/leave/LeaveSpaceView.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/leave/LeaveSpaceView.kt @@ -110,7 +110,7 @@ fun LeaveSpaceView( } is AsyncData.Failure -> item { AsyncFailure( - throwable = state.selectableSpaceRooms.error, + message = state.selectableSpaceRooms.error.localizedMessage, onRetry = { state.eventSink(LeaveSpaceEvents.Retry) }, diff --git a/features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/file/ViewFileView.kt b/features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/file/ViewFileView.kt index 4f3b84734fa..0c086cffffc 100644 --- a/features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/file/ViewFileView.kt +++ b/features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/file/ViewFileView.kt @@ -82,7 +82,7 @@ fun ViewFileView( lines = state.lines.data.toImmutableList(), colorationMode = state.colorationMode, ) - is AsyncData.Failure -> AsyncFailure(throwable = state.lines.error, onRetry = null) + is AsyncData.Failure -> AsyncFailure(message = state.lines.error.localizedMessage, onRetry = null) } } } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncFailure.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncFailure.kt index b2050a6d7e8..ac86a2ce473 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncFailure.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncFailure.kt @@ -25,7 +25,7 @@ import io.element.android.libraries.ui.strings.CommonStrings @Composable fun AsyncFailure( - throwable: Throwable, + message: String?, onRetry: (() -> Unit)?, modifier: Modifier = Modifier, ) { @@ -35,7 +35,7 @@ fun AsyncFailure( .padding(vertical = 32.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { - Text(text = throwable.message ?: stringResource(id = CommonStrings.error_unknown)) + Text(text = message ?: stringResource(id = CommonStrings.error_unknown)) if (onRetry != null) { Spacer(modifier = Modifier.height(24.dp)) Button( @@ -50,7 +50,7 @@ fun AsyncFailure( @Composable internal fun AsyncFailurePreview() = ElementPreview { AsyncFailure( - throwable = IllegalStateException("An error occurred"), + message = "An error occurred", onRetry = {} ) } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/MediaGalleryDataSource.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/MediaGalleryDataSource.kt index f40bb08a862..b2610be208f 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/MediaGalleryDataSource.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/MediaGalleryDataSource.kt @@ -27,6 +27,7 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onCompletion import kotlinx.coroutines.flow.onEach +import timber.log.Timber import java.util.concurrent.atomic.AtomicBoolean interface MediaGalleryDataSource { @@ -76,6 +77,9 @@ class TimelineMediaGalleryDataSource( emit(it) }, { + // We couldn't load the timeline, so we reset the started state to allow retrying + Timber.e(it, "Failed to get timeline for media gallery") + isStarted.set(false) groupedMediaItemsFlow.emit(AsyncData.Failure(it)) }, ) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryEvents.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryEvents.kt index df7d82c7b29..d75406a1c28 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryEvents.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryEvents.kt @@ -29,4 +29,6 @@ sealed interface MediaGalleryEvents { data object CloseBottomSheet : MediaGalleryEvents data class Delete(val eventId: EventId) : MediaGalleryEvents + + data object ReloadTimeline : MediaGalleryEvents } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt index ba3d4d5e1f8..99dc24abf35 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt @@ -87,6 +87,9 @@ class MediaGalleryPresenter( is MediaGalleryEvents.ChangeMode -> { mode = event.mode } + is MediaGalleryEvents.ReloadTimeline -> { + mediaGalleryDataSource.start() + } is MediaGalleryEvents.LoadMore -> coroutineScope.launch { mediaGalleryDataSource.loadMore(event.direction) } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryView.kt index a48ff93d714..72a0d720e4c 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryView.kt @@ -231,7 +231,7 @@ private fun MediaGalleryPage( } is AsyncData.Failure -> { ErrorContent( - error = groupedMediaItems.error, + onRetry = { state.eventSink(MediaGalleryEvents.ReloadTimeline) }, ) } else -> Unit @@ -454,10 +454,10 @@ private fun LoadingMoreIndicator( } @Composable -private fun ErrorContent(error: Throwable) { +private fun ErrorContent(onRetry: () -> Unit) { AsyncFailure( - throwable = error, - onRetry = null, + message = null, + onRetry = onRetry, modifier = Modifier.fillMaxSize(), ) } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerEvents.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerEvents.kt index 708c423d363..d6d0053926d 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerEvents.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerEvents.kt @@ -16,6 +16,7 @@ sealed interface MediaViewerEvents { data class Share(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvents data class OpenWith(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvents data class ClearLoadingError(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvents + data object ReloadTimeline : MediaViewerEvents data class ViewInTimeline(val eventId: EventId) : MediaViewerEvents data class OpenInfo(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvents data class ConfirmDelete( diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt index 6f59bc3ff7f..dccdef32ea5 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt @@ -97,6 +97,9 @@ class MediaViewerPresenter( is MediaViewerEvents.ClearLoadingError -> { dataSource.clearLoadingError(event.data) } + is MediaViewerEvents.ReloadTimeline -> { + dataSource.setup() + } is MediaViewerEvents.SaveOnDisk -> { mediaBottomSheetState = MediaBottomSheetState.Hidden coroutineScope.saveOnDisk(event.data.downloadedMedia.value) 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 110054eb20b..285d59eef31 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 @@ -127,8 +127,8 @@ fun MediaViewerView( when (val dataForPage = state.listData[page]) { is MediaViewerPageData.Failure -> { MediaViewerErrorPage( - throwable = dataForPage.throwable, onDismiss = onBackClick, + onRetry = { state.eventSink(MediaViewerEvents.ReloadTimeline) }, ) } is MediaViewerPageData.Loading -> { @@ -394,8 +394,8 @@ private fun MediaViewerLoadingPage( @Composable private fun MediaViewerErrorPage( - throwable: Throwable, onDismiss: () -> Unit, + onRetry: () -> Unit, modifier: Modifier = Modifier, ) { MediaViewerFlickToDismiss( @@ -409,8 +409,8 @@ private fun MediaViewerErrorPage( contentAlignment = Alignment.Center ) { AsyncFailure( - throwable = throwable, - onRetry = null + message = null, + onRetry = onRetry, ) } } diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en.png index 4cd81a7d433..648be418774 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d73197d295f9181e6f297ecd5da016775a7fd669016528527af5d37f52f1a2e1 -size 14572 +oid sha256:8eb73d17c106db2a650335dc70928603bf810637417a52edb7bd01e9199880b5 +size 17973 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en.png index f7b9912cd19..c2e33c68b04 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a1645075b7bed6fe2fd712996da3860b8db43915f848a53abb8fec2545ecf158 -size 14576 +oid sha256:e538dd4c7235fd79fe9627aa008067126787ed391dbe6f2361372307ad6d708f +size 17983 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en.png index 7953623173f..dc47ba9bcaf 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:624d1a64dff25fddae712e14ec2f7c9a1cdbc89fbbf9e9938e4eeaee30d588d7 -size 14048 +oid sha256:a2c166860f7d443455adf73ab342693983a2310421b2611a5c748fc8a5357711 +size 17355 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en.png index 5caea13b501..514cd629a1c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:176f723c4a2dd25faf869d3a13cd68ab1bf017367b4a74ab100651693c7fac64 -size 14140 +oid sha256:763add4e3c82f9fc81aea7e32da36ccd15951278e9e94f385b2f549579ce4696 +size 17439 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_15_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_15_en.png index ef898feace2..8d88179db94 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_15_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58634665793af557117c70203ed96690f6e9291ee1b34b5b803efa707a961080 -size 5085 +oid sha256:50a66633bc960604490a9e9bfcd4f041b319a6f27169ddf489d8e93c7bfc5487 +size 11005