MediaGalleryEvents -> MediaGalleryEvent

This commit is contained in:
Benoit Marty 2026-04-22 11:01:36 +02:00
parent 83b4bfad96
commit 1e39736797
5 changed files with 67 additions and 67 deletions

View file

@ -14,22 +14,22 @@ import io.element.android.libraries.matrix.api.timeline.Timeline
import io.element.android.libraries.mediaviewer.api.MediaInfo
import io.element.android.libraries.mediaviewer.impl.model.MediaItem
sealed interface MediaGalleryEvents {
data class ChangeMode(val mode: MediaGalleryMode) : MediaGalleryEvents
data class LoadMore(val direction: Timeline.PaginationDirection) : MediaGalleryEvents
data class Share(val eventId: EventId) : MediaGalleryEvents
data class Forward(val eventId: EventId) : MediaGalleryEvents
data class SaveOnDisk(val eventId: EventId) : MediaGalleryEvents
data class OpenWith(val eventId: EventId) : MediaGalleryEvents
data class OpenInfo(val mediaItem: MediaItem.Event) : MediaGalleryEvents
data class ViewInTimeline(val eventId: EventId) : MediaGalleryEvents
sealed interface MediaGalleryEvent {
data class ChangeMode(val mode: MediaGalleryMode) : MediaGalleryEvent
data class LoadMore(val direction: Timeline.PaginationDirection) : MediaGalleryEvent
data class Share(val eventId: EventId) : MediaGalleryEvent
data class Forward(val eventId: EventId) : MediaGalleryEvent
data class SaveOnDisk(val eventId: EventId) : MediaGalleryEvent
data class OpenWith(val eventId: EventId) : MediaGalleryEvent
data class OpenInfo(val mediaItem: MediaItem.Event) : MediaGalleryEvent
data class ViewInTimeline(val eventId: EventId) : MediaGalleryEvent
data class ConfirmDelete(
val eventId: EventId,
val mediaInfo: MediaInfo,
val thumbnailSource: MediaSource?,
) : MediaGalleryEvents
) : MediaGalleryEvent
data object CloseBottomSheet : MediaGalleryEvents
data class Delete(val eventId: EventId) : MediaGalleryEvents
data object CloseBottomSheet : MediaGalleryEvent
data class Delete(val eventId: EventId) : MediaGalleryEvent
}

View file

@ -88,44 +88,44 @@ class MediaGalleryPresenter(
val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState()
localMediaActions.Configure()
fun handleEvent(event: MediaGalleryEvents) {
fun handleEvent(event: MediaGalleryEvent) {
when (event) {
is MediaGalleryEvents.ChangeMode -> {
is MediaGalleryEvent.ChangeMode -> {
mode = event.mode
}
is MediaGalleryEvents.LoadMore -> coroutineScope.launch {
is MediaGalleryEvent.LoadMore -> coroutineScope.launch {
mediaGalleryDataSource.loadMore(event.direction)
}
is MediaGalleryEvents.Delete -> coroutineScope.launch {
is MediaGalleryEvent.Delete -> coroutineScope.launch {
mediaGalleryDataSource.deleteItem(event.eventId)
}
is MediaGalleryEvents.SaveOnDisk -> coroutineScope.launch {
is MediaGalleryEvent.SaveOnDisk -> coroutineScope.launch {
mediaBottomSheetState = MediaBottomSheetState.Hidden
groupedMediaItems.dataOrNull().find(event.eventId)?.let {
saveOnDisk(it)
}
}
is MediaGalleryEvents.OpenWith -> coroutineScope.launch {
is MediaGalleryEvent.OpenWith -> coroutineScope.launch {
mediaBottomSheetState = MediaBottomSheetState.Hidden
groupedMediaItems.dataOrNull().find(event.eventId)?.let {
openWith(it)
}
}
is MediaGalleryEvents.Share -> coroutineScope.launch {
is MediaGalleryEvent.Share -> coroutineScope.launch {
mediaBottomSheetState = MediaBottomSheetState.Hidden
groupedMediaItems.dataOrNull().find(event.eventId)?.let {
share(it)
}
}
is MediaGalleryEvents.Forward -> {
is MediaGalleryEvent.Forward -> {
mediaBottomSheetState = MediaBottomSheetState.Hidden
navigator.onForwardClick(event.eventId)
}
is MediaGalleryEvents.ViewInTimeline -> {
is MediaGalleryEvent.ViewInTimeline -> {
mediaBottomSheetState = MediaBottomSheetState.Hidden
navigator.onViewInTimelineClick(event.eventId)
}
is MediaGalleryEvents.OpenInfo -> coroutineScope.launch {
is MediaGalleryEvent.OpenInfo -> coroutineScope.launch {
mediaBottomSheetState = MediaBottomSheetState.MediaDetailsBottomSheetState(
eventId = event.mediaItem.eventId(),
canDelete = when (event.mediaItem.mediaInfo().senderId) {
@ -143,14 +143,14 @@ class MediaGalleryPresenter(
},
)
}
is MediaGalleryEvents.ConfirmDelete -> {
is MediaGalleryEvent.ConfirmDelete -> {
mediaBottomSheetState = MediaBottomSheetState.MediaDeleteConfirmationState(
eventId = event.eventId,
mediaInfo = event.mediaInfo,
thumbnailSource = event.thumbnailSource,
)
}
MediaGalleryEvents.CloseBottomSheet -> {
MediaGalleryEvent.CloseBottomSheet -> {
mediaBottomSheetState = MediaBottomSheetState.Hidden
}
}

View file

@ -20,7 +20,7 @@ data class MediaGalleryState(
val groupedMediaItems: AsyncData<GroupedMediaItems>,
val mediaBottomSheetState: MediaBottomSheetState,
val snackbarMessage: SnackbarMessage?,
val eventSink: (MediaGalleryEvents) -> Unit,
val eventSink: (MediaGalleryEvent) -> Unit,
)
enum class MediaGalleryMode(val stringResource: Int) {

View file

@ -132,7 +132,7 @@ fun MediaGalleryView(
index = mode.ordinal,
count = MediaGalleryMode.entries.size,
selected = state.mode == mode,
onClick = { state.eventSink(MediaGalleryEvents.ChangeMode(mode)) },
onClick = { state.eventSink(MediaGalleryEvent.ChangeMode(mode)) },
text = stringResource(mode.stringResource),
)
}
@ -162,23 +162,23 @@ fun MediaGalleryView(
MediaDetailsBottomSheet(
state = bottomSheetState,
onViewInTimeline = { eventId ->
state.eventSink(MediaGalleryEvents.ViewInTimeline(eventId))
state.eventSink(MediaGalleryEvent.ViewInTimeline(eventId))
},
onShare = { eventId ->
state.eventSink(MediaGalleryEvents.Share(eventId))
state.eventSink(MediaGalleryEvent.Share(eventId))
},
onForward = { eventId ->
state.eventSink(MediaGalleryEvents.Forward(eventId))
state.eventSink(MediaGalleryEvent.Forward(eventId))
},
onDownload = { eventId ->
state.eventSink(MediaGalleryEvents.SaveOnDisk(eventId))
state.eventSink(MediaGalleryEvent.SaveOnDisk(eventId))
},
onOpenWith = { eventId ->
state.eventSink(MediaGalleryEvents.OpenWith(eventId))
state.eventSink(MediaGalleryEvent.OpenWith(eventId))
},
onDelete = { eventId ->
state.eventSink(
MediaGalleryEvents.ConfirmDelete(
MediaGalleryEvent.ConfirmDelete(
eventId = eventId,
mediaInfo = bottomSheetState.mediaInfo,
thumbnailSource = bottomSheetState.thumbnailSource,
@ -186,7 +186,7 @@ fun MediaGalleryView(
)
},
onDismiss = {
state.eventSink(MediaGalleryEvents.CloseBottomSheet)
state.eventSink(MediaGalleryEvent.CloseBottomSheet)
},
)
}
@ -194,10 +194,10 @@ fun MediaGalleryView(
MediaDeleteConfirmationBottomSheet(
state = bottomSheetState,
onDelete = {
state.eventSink(MediaGalleryEvents.Delete(it))
state.eventSink(MediaGalleryEvent.Delete(it))
},
onDismiss = {
state.eventSink(MediaGalleryEvents.CloseBottomSheet)
state.eventSink(MediaGalleryEvent.CloseBottomSheet)
},
)
}
@ -216,7 +216,7 @@ private fun MediaGalleryPage(
val loadingItem = groupedMediaItems.dataOrNull()?.getItems(mode)?.singleOrNull() as? MediaItem.LoadingIndicator
if (loadingItem != null) {
LaunchedEffect(loadingItem.timestamp) {
state.eventSink(MediaGalleryEvents.LoadMore(loadingItem.direction))
state.eventSink(MediaGalleryEvent.LoadMore(loadingItem.direction))
}
}
LoadingContent(mode)
@ -261,7 +261,7 @@ private fun AsyncData<GroupedMediaItems>.isLoadingItems(mode: MediaGalleryMode):
@Composable
private fun MediaGalleryImages(
imagesAndVideos: ImmutableList<MediaItem>,
eventSink: (MediaGalleryEvents) -> Unit,
eventSink: (MediaGalleryEvent) -> Unit,
onItemClick: (MediaItem.Event) -> Unit,
) {
if (imagesAndVideos.isEmpty()) {
@ -282,7 +282,7 @@ private fun MediaGalleryImages(
@Composable
private fun MediaGalleryFiles(
files: ImmutableList<MediaItem>,
eventSink: (MediaGalleryEvents) -> Unit,
eventSink: (MediaGalleryEvent) -> Unit,
onItemClick: (MediaItem.Event) -> Unit,
) {
if (files.isEmpty()) {
@ -303,7 +303,7 @@ private fun MediaGalleryFiles(
@Composable
private fun MediaGalleryFilesList(
files: ImmutableList<MediaItem>,
eventSink: (MediaGalleryEvents) -> Unit,
eventSink: (MediaGalleryEvent) -> Unit,
onItemClick: (MediaItem.Event) -> Unit,
) {
val presenterFactories = LocalMediaItemPresenterFactories.current
@ -321,7 +321,7 @@ private fun MediaGalleryFilesList(
file = item,
onClick = { onItemClick(item) },
onLongClick = {
eventSink(MediaGalleryEvents.OpenInfo(item))
eventSink(MediaGalleryEvent.OpenInfo(item))
},
)
is MediaItem.Audio -> AudioItemView(
@ -329,7 +329,7 @@ private fun MediaGalleryFilesList(
audio = item,
onClick = { onItemClick(item) },
onLongClick = {
eventSink(MediaGalleryEvents.OpenInfo(item))
eventSink(MediaGalleryEvent.OpenInfo(item))
},
)
is MediaItem.Voice -> {
@ -339,7 +339,7 @@ private fun MediaGalleryFilesList(
state = presenter.present(),
voice = item,
onLongClick = {
eventSink(MediaGalleryEvents.OpenInfo(item))
eventSink(MediaGalleryEvent.OpenInfo(item))
},
)
}
@ -364,7 +364,7 @@ private fun MediaGalleryFilesList(
@Composable
private fun MediaGalleryImageGrid(
imagesAndVideos: ImmutableList<MediaItem>,
eventSink: (MediaGalleryEvents) -> Unit,
eventSink: (MediaGalleryEvent) -> Unit,
onItemClick: (MediaItem.Event) -> Unit,
) {
LazyVerticalGrid(
@ -406,7 +406,7 @@ private fun MediaGalleryImageGrid(
image = item,
onClick = { onItemClick(item) },
onLongClick = {
eventSink(MediaGalleryEvents.OpenInfo(item))
eventSink(MediaGalleryEvent.OpenInfo(item))
},
)
is MediaItem.Video -> VideoItemView(
@ -414,7 +414,7 @@ private fun MediaGalleryImageGrid(
video = item,
onClick = { onItemClick(item) },
onLongClick = {
eventSink(MediaGalleryEvents.OpenInfo(item))
eventSink(MediaGalleryEvent.OpenInfo(item))
},
)
is MediaItem.LoadingIndicator -> LoadingMoreIndicator(
@ -430,7 +430,7 @@ private fun MediaGalleryImageGrid(
@Composable
private fun LoadingMoreIndicator(
item: MediaItem.LoadingIndicator,
eventSink: (MediaGalleryEvents) -> Unit,
eventSink: (MediaGalleryEvent) -> Unit,
modifier: Modifier = Modifier
) {
Box(
@ -455,7 +455,7 @@ private fun LoadingMoreIndicator(
}
val latestEventSink by rememberUpdatedState(eventSink)
LaunchedEffect(item.timestamp) {
latestEventSink(MediaGalleryEvents.LoadMore(item.direction))
latestEventSink(MediaGalleryEvent.LoadMore(item.direction))
}
}
}

View file

@ -84,10 +84,10 @@ class MediaGalleryPresenterTest {
presenter.test {
val initialState = awaitFirstItem()
assertThat(initialState.mode).isEqualTo(MediaGalleryMode.Images)
initialState.eventSink(MediaGalleryEvents.ChangeMode(MediaGalleryMode.Files))
initialState.eventSink(MediaGalleryEvent.ChangeMode(MediaGalleryMode.Files))
val state = awaitItem()
assertThat(state.mode).isEqualTo(MediaGalleryMode.Files)
state.eventSink(MediaGalleryEvents.ChangeMode(MediaGalleryMode.Images))
state.eventSink(MediaGalleryEvent.ChangeMode(MediaGalleryMode.Images))
val imageModeState = awaitItem()
assertThat(imageModeState.mode).isEqualTo(MediaGalleryMode.Images)
}
@ -123,7 +123,7 @@ class MediaGalleryPresenterTest {
eventId = AN_EVENT_ID,
senderId = A_USER_ID,
)
initialState.eventSink(MediaGalleryEvents.OpenInfo(item))
initialState.eventSink(MediaGalleryEvent.OpenInfo(item))
val state = awaitItem()
assertThat(state.mediaBottomSheetState).isEqualTo(
MediaBottomSheetState.MediaDetailsBottomSheetState(
@ -134,7 +134,7 @@ class MediaGalleryPresenterTest {
)
)
// Close the bottom sheet
state.eventSink(MediaGalleryEvents.CloseBottomSheet)
state.eventSink(MediaGalleryEvent.CloseBottomSheet)
val closedState = awaitItem()
assertThat(closedState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden)
}
@ -170,7 +170,7 @@ class MediaGalleryPresenterTest {
eventId = AN_EVENT_ID,
senderId = A_USER_ID_2,
)
initialState.eventSink(MediaGalleryEvents.OpenInfo(item))
initialState.eventSink(MediaGalleryEvent.OpenInfo(item))
val state = awaitItem()
assertThat(state.mediaBottomSheetState).isEqualTo(
MediaBottomSheetState.MediaDetailsBottomSheetState(
@ -181,7 +181,7 @@ class MediaGalleryPresenterTest {
)
)
// Close the bottom sheet
state.eventSink(MediaGalleryEvents.CloseBottomSheet)
state.eventSink(MediaGalleryEvent.CloseBottomSheet)
val closedState = awaitItem()
assertThat(closedState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden)
}
@ -199,7 +199,7 @@ class MediaGalleryPresenterTest {
val initialState = awaitFirstItem()
// Delete bottom sheet
val item = aMediaItemImage()
initialState.eventSink(MediaGalleryEvents.ConfirmDelete(AN_EVENT_ID, item.mediaInfo, item.thumbnailSource))
initialState.eventSink(MediaGalleryEvent.ConfirmDelete(AN_EVENT_ID, item.mediaInfo, item.thumbnailSource))
val deleteState = awaitItem()
assertThat(deleteState.mediaBottomSheetState).isEqualTo(
MediaBottomSheetState.MediaDeleteConfirmationState(
@ -209,7 +209,7 @@ class MediaGalleryPresenterTest {
)
)
// Close the bottom sheet
deleteState.eventSink(MediaGalleryEvents.CloseBottomSheet)
deleteState.eventSink(MediaGalleryEvent.CloseBottomSheet)
val deleteClosedState = awaitItem()
assertThat(deleteClosedState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden)
}
@ -226,7 +226,7 @@ class MediaGalleryPresenterTest {
)
presenter.test {
val initialState = awaitFirstItem()
initialState.eventSink(MediaGalleryEvents.Delete(AN_EVENT_ID))
initialState.eventSink(MediaGalleryEvent.Delete(AN_EVENT_ID))
deleteItemLambda.assertions().isCalledOnce().with(value(AN_EVENT_ID))
}
}
@ -236,7 +236,7 @@ class MediaGalleryPresenterTest {
val presenter = createMediaGalleryPresenter()
presenter.test {
val initialState = awaitFirstItem()
initialState.eventSink(MediaGalleryEvents.Share(AN_EVENT_ID))
initialState.eventSink(MediaGalleryEvent.Share(AN_EVENT_ID))
}
}
@ -258,7 +258,7 @@ class MediaGalleryPresenterTest {
)
presenter.test {
val initialState = awaitFirstItem()
initialState.eventSink(MediaGalleryEvents.Share(AN_EVENT_ID))
initialState.eventSink(MediaGalleryEvent.Share(AN_EVENT_ID))
val finalState = awaitItem()
assertThat(finalState.snackbarMessage).isNull()
}
@ -283,7 +283,7 @@ class MediaGalleryPresenterTest {
)
presenter.test {
val initialState = awaitFirstItem()
initialState.eventSink(MediaGalleryEvents.Share(AN_EVENT_ID))
initialState.eventSink(MediaGalleryEvent.Share(AN_EVENT_ID))
skipItems(1)
val finalState = awaitItem()
assertThat(finalState.snackbarMessage).isInstanceOf(SnackbarMessage::class.java)
@ -295,7 +295,7 @@ class MediaGalleryPresenterTest {
val presenter = createMediaGalleryPresenter()
presenter.test {
val initialState = awaitFirstItem()
initialState.eventSink(MediaGalleryEvents.SaveOnDisk(AN_EVENT_ID))
initialState.eventSink(MediaGalleryEvent.SaveOnDisk(AN_EVENT_ID))
}
}
@ -317,7 +317,7 @@ class MediaGalleryPresenterTest {
)
presenter.test {
val initialState = awaitFirstItem()
initialState.eventSink(MediaGalleryEvents.SaveOnDisk(AN_EVENT_ID))
initialState.eventSink(MediaGalleryEvent.SaveOnDisk(AN_EVENT_ID))
skipItems(1)
val finalState = awaitItem()
assertThat(finalState.snackbarMessage?.messageResId).isEqualTo(CommonStrings.common_file_saved_on_disk_android)
@ -343,7 +343,7 @@ class MediaGalleryPresenterTest {
)
presenter.test {
val initialState = awaitFirstItem()
initialState.eventSink(MediaGalleryEvents.SaveOnDisk(AN_EVENT_ID))
initialState.eventSink(MediaGalleryEvent.SaveOnDisk(AN_EVENT_ID))
skipItems(1)
val finalState = awaitItem()
assertThat(finalState.snackbarMessage).isInstanceOf(SnackbarMessage::class.java)
@ -373,10 +373,10 @@ class MediaGalleryPresenterTest {
eventId = AN_EVENT_ID,
senderId = A_USER_ID,
)
initialState.eventSink(MediaGalleryEvents.OpenInfo(item))
initialState.eventSink(MediaGalleryEvent.OpenInfo(item))
val withBottomSheetState = awaitItem()
assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.MediaDetailsBottomSheetState::class.java)
withBottomSheetState.eventSink(MediaGalleryEvents.ViewInTimeline(AN_EVENT_ID))
withBottomSheetState.eventSink(MediaGalleryEvent.ViewInTimeline(AN_EVENT_ID))
val finalState = awaitItem()
assertThat(finalState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden)
onViewInTimelineClickLambda.assertions().isCalledOnce().with(value(AN_EVENT_ID))
@ -406,10 +406,10 @@ class MediaGalleryPresenterTest {
eventId = AN_EVENT_ID,
senderId = A_USER_ID,
)
initialState.eventSink(MediaGalleryEvents.OpenInfo(item))
initialState.eventSink(MediaGalleryEvent.OpenInfo(item))
val withBottomSheetState = awaitItem()
assertThat(withBottomSheetState.mediaBottomSheetState).isInstanceOf(MediaBottomSheetState.MediaDetailsBottomSheetState::class.java)
withBottomSheetState.eventSink(MediaGalleryEvents.Forward(AN_EVENT_ID))
withBottomSheetState.eventSink(MediaGalleryEvent.Forward(AN_EVENT_ID))
val finalState = awaitItem()
assertThat(finalState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden)
onForwardClickLambda.assertions().isCalledOnce().with(value(AN_EVENT_ID))
@ -427,7 +427,7 @@ class MediaGalleryPresenterTest {
)
presenter.test {
val initialState = awaitFirstItem()
initialState.eventSink(MediaGalleryEvents.LoadMore(Timeline.PaginationDirection.BACKWARDS))
initialState.eventSink(MediaGalleryEvent.LoadMore(Timeline.PaginationDirection.BACKWARDS))
loadMoreLambda.assertions().isCalledOnce().with(value(Timeline.PaginationDirection.BACKWARDS))
}
}