Skip to content

Commit 5c41de6

Browse files
committed
Move share and download actions to the bottom sheet
1 parent 33634b2 commit 5c41de6

File tree

17 files changed

+122
-173
lines changed

17 files changed

+122
-173
lines changed

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,6 @@ class MessagesFlowNode @AssistedInject constructor(
251251
mediaSource = navTarget.mediaSource,
252252
thumbnailSource = navTarget.thumbnailSource,
253253
canShowInfo = true,
254-
canDownload = true,
255-
canShare = true,
256254
)
257255
val callback = object : MediaViewerEntryPoint.Callback {
258256
override fun onDone() {

libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaViewerEntryPoint.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,5 @@ interface MediaViewerEntryPoint : FeatureEntryPoint {
3636
val mediaSource: MediaSource,
3737
val thumbnailSource: MediaSource?,
3838
val canShowInfo: Boolean,
39-
val canDownload: Boolean,
40-
val canShare: Boolean,
4139
) : NodeInputs
4240
}

libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPoint.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,6 @@ class DefaultMediaViewerEntryPoint @Inject constructor() : MediaViewerEntryPoint
5959
mediaSource = MediaSource(url = avatarUrl),
6060
thumbnailSource = null,
6161
canShowInfo = false,
62-
canDownload = false,
63-
canShare = false,
6462
)
6563
)
6664
}

libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/details/MediaDetailsBottomSheet.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ import io.element.android.libraries.ui.strings.CommonStrings
4848
fun MediaDetailsBottomSheet(
4949
state: MediaBottomSheetState.MediaDetailsBottomSheetState,
5050
onViewInTimeline: (EventId) -> Unit,
51+
onShare: (EventId) -> Unit,
52+
onDownload: (EventId) -> Unit,
5153
onDelete: (EventId) -> Unit,
5254
onDismiss: () -> Unit,
5355
modifier: Modifier = Modifier,
@@ -92,6 +94,22 @@ fun MediaDetailsBottomSheet(
9294
onViewInTimeline(state.eventId)
9395
}
9496
)
97+
ListItem(
98+
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.ShareAndroid())),
99+
headlineContent = { Text(stringResource(CommonStrings.action_share)) },
100+
style = ListItemStyle.Primary,
101+
onClick = {
102+
onShare(state.eventId)
103+
}
104+
)
105+
ListItem(
106+
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Download())),
107+
headlineContent = { Text(stringResource(CommonStrings.action_save)) },
108+
style = ListItemStyle.Primary,
109+
onClick = {
110+
onDownload(state.eventId)
111+
}
112+
)
95113
if (state.canDelete) {
96114
HorizontalDivider()
97115
ListItem(
@@ -196,6 +214,8 @@ internal fun MediaDetailsBottomSheetPreview() = ElementPreview {
196214
MediaDetailsBottomSheet(
197215
state = aMediaDetailsBottomSheetState(),
198216
onViewInTimeline = {},
217+
onShare = {},
218+
onDownload = {},
199219
onDelete = {},
200220
onDismiss = {},
201221
)

libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryEvents.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import io.element.android.libraries.mediaviewer.api.MediaInfo
1515
sealed interface MediaGalleryEvents {
1616
data class ChangeMode(val mode: MediaGalleryMode) : MediaGalleryEvents
1717
data class LoadMore(val direction: Timeline.PaginationDirection) : MediaGalleryEvents
18-
data class Share(val mediaItem: MediaItem.Event) : MediaGalleryEvents
19-
data class SaveOnDisk(val mediaItem: MediaItem.Event) : MediaGalleryEvents
18+
data class Share(val eventId: EventId?) : MediaGalleryEvents
19+
data class SaveOnDisk(val eventId: EventId?) : MediaGalleryEvents
2020
data class OpenInfo(val mediaItem: MediaItem.Event) : MediaGalleryEvents
2121
data class ViewInTimeline(val eventId: EventId) : MediaGalleryEvents
2222

libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryPresenter.kt

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,16 @@ class MediaGalleryPresenter @AssistedInject constructor(
117117
timeline.dataOrNull()?.paginate(event.direction)
118118
}
119119
is MediaGalleryEvents.Delete -> coroutineScope.delete(timeline, event.eventId)
120-
is MediaGalleryEvents.SaveOnDisk -> coroutineScope.saveOnDisk(event.mediaItem)
121-
is MediaGalleryEvents.Share -> coroutineScope.share(event.mediaItem)
120+
is MediaGalleryEvents.SaveOnDisk -> coroutineScope.launch {
121+
mediaItems.dataOrNull().find(event.eventId)?.let {
122+
saveOnDisk(it)
123+
}
124+
}
125+
is MediaGalleryEvents.Share -> coroutineScope.launch {
126+
mediaItems.dataOrNull().find(event.eventId)?.let {
127+
share(it)
128+
}
129+
}
122130
is MediaGalleryEvents.ViewInTimeline -> {
123131
mediaBottomSheetState = MediaBottomSheetState.Hidden
124132
navigator.onViewInTimelineClick(event.eventId)
@@ -221,7 +229,7 @@ class MediaGalleryPresenter @AssistedInject constructor(
221229
}
222230
}
223231

224-
private fun CoroutineScope.saveOnDisk(mediaItem: MediaItem.Event) = launch {
232+
private suspend fun saveOnDisk(mediaItem: MediaItem.Event) {
225233
downloadMedia(mediaItem)
226234
.mapCatching { localMedia ->
227235
localMediaActions.saveOnDisk(localMedia)
@@ -236,7 +244,7 @@ class MediaGalleryPresenter @AssistedInject constructor(
236244
}
237245
}
238246

239-
private fun CoroutineScope.share(mediaItem: MediaItem.Event) = launch {
247+
private suspend fun share(mediaItem: MediaItem.Event) {
240248
downloadMedia(mediaItem)
241249
.mapCatching { localMedia ->
242250
localMediaActions.share(localMedia)
@@ -255,3 +263,11 @@ class MediaGalleryPresenter @AssistedInject constructor(
255263
}
256264
}
257265
}
266+
267+
private fun List<MediaItem>?.find(eventId: EventId?): MediaItem.Event? {
268+
if (this == null || eventId == null) {
269+
return null
270+
}
271+
return filterIsInstance<MediaItem.Event>()
272+
.firstOrNull { it.eventId() == eventId }
273+
}

libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryView.kt

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,12 @@ fun MediaGalleryView(
153153
onViewInTimeline = { eventId ->
154154
state.eventSink(MediaGalleryEvents.ViewInTimeline(eventId))
155155
},
156+
onShare = { eventId ->
157+
state.eventSink(MediaGalleryEvents.Share(eventId))
158+
},
159+
onDownload = { eventId ->
160+
state.eventSink(MediaGalleryEvents.SaveOnDisk(eventId))
161+
},
156162
onDelete = { eventId ->
157163
state.eventSink(
158164
MediaGalleryEvents.ConfirmDelete(
@@ -276,21 +282,27 @@ private fun MediaGalleryFilesList(
276282
modifier = Modifier.animateItem(),
277283
file = item,
278284
onClick = { onItemClick(item) },
285+
onLongClick = {
286+
eventSink(MediaGalleryEvents.OpenInfo(item))
287+
},
279288
)
280289
is MediaItem.Audio -> AudioItemView(
281290
modifier = Modifier.animateItem(),
282291
audio = item,
283292
onClick = { onItemClick(item) },
293+
onLongClick = {
294+
eventSink(MediaGalleryEvents.OpenInfo(item))
295+
},
284296
)
285297
is MediaItem.Voice -> {
286298
val presenter: Presenter<VoiceMessageState> = presenterFactories.rememberPresenter(item)
287299
VoiceItemView(
288300
modifier = Modifier.animateItem(),
289301
state = presenter.present(),
290302
voice = item,
291-
onShareClick = { eventSink(MediaGalleryEvents.Share(item)) },
292-
onDownloadClick = { eventSink(MediaGalleryEvents.SaveOnDisk(item)) },
293-
onInfoClick = { eventSink(MediaGalleryEvents.OpenInfo(item)) },
303+
onLongClick = {
304+
eventSink(MediaGalleryEvents.OpenInfo(item))
305+
},
294306
)
295307
}
296308
is MediaItem.DateSeparator -> DateItemView(

libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/root/MediaGalleryRootNode.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,6 @@ class MediaGalleryRootNode @AssistedInject constructor(
122122
mediaSource = navTarget.mediaSource,
123123
thumbnailSource = navTarget.thumbnailSource,
124124
canShowInfo = true,
125-
canDownload = true,
126-
canShare = true,
127125
)
128126
)
129127
.callback(callback)

libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/AudioItemView.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77

88
package io.element.android.libraries.mediaviewer.impl.gallery.ui
99

10+
import androidx.compose.foundation.ExperimentalFoundationApi
1011
import androidx.compose.foundation.background
11-
import androidx.compose.foundation.clickable
12+
import androidx.compose.foundation.combinedClickable
1213
import androidx.compose.foundation.layout.Column
1314
import androidx.compose.foundation.layout.Row
1415
import androidx.compose.foundation.layout.Spacer
@@ -41,6 +42,7 @@ import io.element.android.libraries.mediaviewer.impl.gallery.MediaItem
4142
fun AudioItemView(
4243
audio: MediaItem.Audio,
4344
onClick: () -> Unit,
45+
onLongClick: () -> Unit,
4446
modifier: Modifier = Modifier,
4547
) {
4648
Column(
@@ -52,6 +54,7 @@ fun AudioItemView(
5254
FilenameRow(
5355
audio = audio,
5456
onClick = onClick,
57+
onLongClick = onLongClick,
5558
)
5659
val caption = audio.mediaInfo.caption
5760
if (caption != null) {
@@ -63,10 +66,12 @@ fun AudioItemView(
6366
}
6467
}
6568

69+
@OptIn(ExperimentalFoundationApi::class)
6670
@Composable
6771
private fun FilenameRow(
6872
audio: MediaItem.Audio,
6973
onClick: () -> Unit,
74+
onLongClick: () -> Unit,
7075
) {
7176
Row(
7277
modifier = Modifier
@@ -75,7 +80,7 @@ private fun FilenameRow(
7580
color = ElementTheme.colors.bgSubtleSecondary,
7681
shape = RoundedCornerShape(12.dp),
7782
)
78-
.clickable { onClick() }
83+
.combinedClickable(onClick = onClick, onLongClick = onLongClick)
7984
.fillMaxWidth()
8085
.padding(start = 12.dp, end = 36.dp, top = 8.dp, bottom = 8.dp),
8186
verticalAlignment = Alignment.CenterVertically,
@@ -119,5 +124,6 @@ internal fun AudioItemViewPreview(
119124
AudioItemView(
120125
audio = audio,
121126
onClick = {},
127+
onLongClick = {},
122128
)
123129
}

libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/FileItemView.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77

88
package io.element.android.libraries.mediaviewer.impl.gallery.ui
99

10+
import androidx.compose.foundation.ExperimentalFoundationApi
1011
import androidx.compose.foundation.background
11-
import androidx.compose.foundation.clickable
12+
import androidx.compose.foundation.combinedClickable
1213
import androidx.compose.foundation.layout.Column
1314
import androidx.compose.foundation.layout.Row
1415
import androidx.compose.foundation.layout.Spacer
@@ -40,6 +41,7 @@ import io.element.android.libraries.mediaviewer.impl.gallery.MediaItem
4041
fun FileItemView(
4142
file: MediaItem.File,
4243
onClick: () -> Unit,
44+
onLongClick: () -> Unit,
4345
modifier: Modifier = Modifier,
4446
) {
4547
Column(
@@ -51,6 +53,7 @@ fun FileItemView(
5153
FilenameRow(
5254
file = file,
5355
onClick = onClick,
56+
onLongClick = onLongClick,
5457
)
5558
val caption = file.mediaInfo.caption
5659
if (caption != null) {
@@ -62,10 +65,12 @@ fun FileItemView(
6265
}
6366
}
6467

68+
@OptIn(ExperimentalFoundationApi::class)
6569
@Composable
6670
private fun FilenameRow(
6771
file: MediaItem.File,
6872
onClick: () -> Unit,
73+
onLongClick: () -> Unit,
6974
) {
7075
Row(
7176
modifier = Modifier
@@ -74,7 +79,7 @@ private fun FilenameRow(
7479
color = ElementTheme.colors.bgSubtleSecondary,
7580
shape = RoundedCornerShape(12.dp),
7681
)
77-
.clickable { onClick() }
82+
.combinedClickable(onClick = onClick, onLongClick = onLongClick)
7883
.fillMaxWidth()
7984
.padding(start = 12.dp, end = 36.dp, top = 8.dp, bottom = 8.dp),
8085
verticalAlignment = Alignment.CenterVertically,
@@ -118,5 +123,6 @@ internal fun FileItemViewPreview(
118123
FileItemView(
119124
file = file,
120125
onClick = {},
126+
onLongClick = {},
121127
)
122128
}

0 commit comments

Comments
 (0)