Add Forward action to MediaDetailsBottomSheet. Closes #5454

Improve API of Callback when forwarding Event.
This commit is contained in:
Benoit Marty 2025-10-28 16:02:37 +01:00 committed by Benoit Marty
parent e9cfce915a
commit 21bae4aee2
35 changed files with 190 additions and 36 deletions

View file

@ -49,6 +49,7 @@ fun MediaDetailsBottomSheet(
state: MediaBottomSheetState.MediaDetailsBottomSheetState,
onViewInTimeline: (EventId) -> Unit,
onShare: (EventId) -> Unit,
onForward: (EventId) -> Unit,
onDownload: (EventId) -> Unit,
onDelete: (EventId) -> Unit,
onDismiss: () -> Unit,
@ -102,6 +103,14 @@ fun MediaDetailsBottomSheet(
onShare(state.eventId)
}
)
ListItem(
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Forward())),
headlineContent = { Text(stringResource(CommonStrings.action_forward)) },
style = ListItemStyle.Primary,
onClick = {
onForward(state.eventId)
}
)
ListItem(
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Download())),
headlineContent = { Text(stringResource(CommonStrings.action_save)) },
@ -216,6 +225,7 @@ internal fun MediaDetailsBottomSheetPreview() = ElementPreview {
state = aMediaDetailsBottomSheetState(),
onViewInTimeline = {},
onShare = {},
onForward = {},
onDownload = {},
onDelete = {},
onDismiss = {},

View file

@ -17,6 +17,7 @@ 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 OpenInfo(val mediaItem: MediaItem.Event) : MediaGalleryEvents
data class ViewInTimeline(val eventId: EventId) : MediaGalleryEvents

View file

@ -11,4 +11,5 @@ import io.element.android.libraries.matrix.api.core.EventId
interface MediaGalleryNavigator {
fun onViewInTimelineClick(eventId: EventId)
fun onForwardClick(eventId: EventId)
}

View file

@ -40,6 +40,7 @@ class MediaGalleryNode(
fun onBackClick()
fun onItemClick(item: MediaItem.Event)
fun onViewInTimeline(eventId: EventId)
fun onForward(eventId: EventId)
}
private fun onBackClick() {
@ -54,6 +55,12 @@ class MediaGalleryNode(
}
}
override fun onForwardClick(eventId: EventId) {
plugins<Callback>().forEach {
it.onForward(eventId)
}
}
private fun onItemClick(item: MediaItem.Event) {
plugins<Callback>().forEach {
it.onItemClick(item)

View file

@ -105,6 +105,10 @@ class MediaGalleryPresenter(
share(it)
}
}
is MediaGalleryEvents.Forward -> {
mediaBottomSheetState = MediaBottomSheetState.Hidden
navigator.onForwardClick(event.eventId)
}
is MediaGalleryEvents.ViewInTimeline -> {
mediaBottomSheetState = MediaBottomSheetState.Hidden
navigator.onViewInTimelineClick(event.eventId)

View file

@ -166,6 +166,9 @@ fun MediaGalleryView(
onShare = { eventId ->
state.eventSink(MediaGalleryEvents.Share(eventId))
},
onForward = { eventId ->
state.eventSink(MediaGalleryEvents.Forward(eventId))
},
onDownload = { eventId ->
state.eventSink(MediaGalleryEvents.SaveOnDisk(eventId))
},

View file

@ -44,7 +44,7 @@ import kotlinx.parcelize.Parcelize
class MediaGalleryFlowNode(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
private val mediaViewerEntryPoint: MediaViewerEntryPoint
private val mediaViewerEntryPoint: MediaViewerEntryPoint,
) : BaseFlowNode<MediaGalleryFlowNode.NavTarget>(
backstack = BackStack(
initialElement = NavTarget.Root,
@ -82,6 +82,12 @@ class MediaGalleryFlowNode(
}
}
private fun forwardEvent(eventId: EventId) {
plugins<MediaGalleryEntryPoint.Callback>().forEach {
it.forwardEvent(eventId)
}
}
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
return when (navTarget) {
NavTarget.Root -> {
@ -94,6 +100,10 @@ class MediaGalleryFlowNode(
this@MediaGalleryFlowNode.onViewInTimeline(eventId)
}
override fun onForward(eventId: EventId) {
forwardEvent(eventId)
}
override fun onItemClick(item: MediaItem.Event) {
val mode = when (item) {
is MediaItem.Audio,
@ -124,6 +134,11 @@ class MediaGalleryFlowNode(
override fun onViewInTimeline(eventId: EventId) {
this@MediaGalleryFlowNode.onViewInTimeline(eventId)
}
override fun onForwardEvent(eventId: EventId) {
// Need to go to the parent because of the overlay
forwardEvent(eventId)
}
}
mediaViewerEntryPoint.nodeBuilder(this, buildContext)
.params(

View file

@ -17,6 +17,7 @@ sealed interface MediaViewerEvents {
data class OpenWith(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvents
data class ClearLoadingError(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvents
data class ViewInTimeline(val eventId: EventId) : MediaViewerEvents
data class Forward(val eventId: EventId) : MediaViewerEvents
data class OpenInfo(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvents
data class ConfirmDelete(
val eventId: EventId,

View file

@ -11,5 +11,6 @@ import io.element.android.libraries.matrix.api.core.EventId
interface MediaViewerNavigator {
fun onViewInTimelineClick(eventId: EventId)
fun onForwardClick(eventId: EventId)
fun onItemDeleted()
}

View file

@ -71,6 +71,12 @@ class MediaViewerNode(
}
}
override fun onForwardClick(eventId: EventId) {
plugins<MediaViewerEntryPoint.Callback>().forEach {
it.onForwardEvent(eventId)
}
}
override fun onItemDeleted() {
onDone()
}

View file

@ -117,6 +117,10 @@ class MediaViewerPresenter(
mediaBottomSheetState = MediaBottomSheetState.Hidden
navigator.onViewInTimelineClick(event.eventId)
}
is MediaViewerEvents.Forward -> {
mediaBottomSheetState = MediaBottomSheetState.Hidden
navigator.onForwardClick(event.eventId)
}
is MediaViewerEvents.OpenInfo -> coroutineScope.launch {
mediaBottomSheetState = MediaBottomSheetState.MediaDetailsBottomSheetState(
eventId = event.data.eventId,

View file

@ -247,6 +247,9 @@ fun MediaViewerView(
state.eventSink(MediaViewerEvents.Share(currentData))
}
},
onForward = {
state.eventSink(MediaViewerEvents.Forward(it))
},
onDownload = {
(currentData as? MediaViewerPageData.MediaViewerData)?.let {
state.eventSink(MediaViewerEvents.SaveOnDisk(currentData))