Move share and download actions to the bottom sheet
This commit is contained in:
parent
194b1a8c56
commit
f8b2f24962
17 changed files with 127 additions and 178 deletions
|
|
@ -251,8 +251,6 @@ class MessagesFlowNode @AssistedInject constructor(
|
||||||
mediaSource = navTarget.mediaSource,
|
mediaSource = navTarget.mediaSource,
|
||||||
thumbnailSource = navTarget.thumbnailSource,
|
thumbnailSource = navTarget.thumbnailSource,
|
||||||
canShowInfo = true,
|
canShowInfo = true,
|
||||||
canDownload = true,
|
|
||||||
canShare = true,
|
|
||||||
)
|
)
|
||||||
val callback = object : MediaViewerEntryPoint.Callback {
|
val callback = object : MediaViewerEntryPoint.Callback {
|
||||||
override fun onDone() {
|
override fun onDone() {
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,5 @@ interface MediaViewerEntryPoint : FeatureEntryPoint {
|
||||||
val mediaSource: MediaSource,
|
val mediaSource: MediaSource,
|
||||||
val thumbnailSource: MediaSource?,
|
val thumbnailSource: MediaSource?,
|
||||||
val canShowInfo: Boolean,
|
val canShowInfo: Boolean,
|
||||||
val canDownload: Boolean,
|
|
||||||
val canShare: Boolean,
|
|
||||||
) : NodeInputs
|
) : NodeInputs
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,8 +59,6 @@ class DefaultMediaViewerEntryPoint @Inject constructor() : MediaViewerEntryPoint
|
||||||
mediaSource = MediaSource(url = avatarUrl),
|
mediaSource = MediaSource(url = avatarUrl),
|
||||||
thumbnailSource = null,
|
thumbnailSource = null,
|
||||||
canShowInfo = false,
|
canShowInfo = false,
|
||||||
canDownload = false,
|
|
||||||
canShare = false,
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,8 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
fun MediaDetailsBottomSheet(
|
fun MediaDetailsBottomSheet(
|
||||||
state: MediaBottomSheetState.MediaDetailsBottomSheetState,
|
state: MediaBottomSheetState.MediaDetailsBottomSheetState,
|
||||||
onViewInTimeline: (EventId) -> Unit,
|
onViewInTimeline: (EventId) -> Unit,
|
||||||
|
onShare: (EventId) -> Unit,
|
||||||
|
onDownload: (EventId) -> Unit,
|
||||||
onDelete: (EventId) -> Unit,
|
onDelete: (EventId) -> Unit,
|
||||||
onDismiss: () -> Unit,
|
onDismiss: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
|
@ -92,6 +94,22 @@ fun MediaDetailsBottomSheet(
|
||||||
onViewInTimeline(state.eventId)
|
onViewInTimeline(state.eventId)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
ListItem(
|
||||||
|
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.ShareAndroid())),
|
||||||
|
headlineContent = { Text(stringResource(CommonStrings.action_share)) },
|
||||||
|
style = ListItemStyle.Primary,
|
||||||
|
onClick = {
|
||||||
|
onShare(state.eventId)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
ListItem(
|
||||||
|
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Download())),
|
||||||
|
headlineContent = { Text(stringResource(CommonStrings.action_save)) },
|
||||||
|
style = ListItemStyle.Primary,
|
||||||
|
onClick = {
|
||||||
|
onDownload(state.eventId)
|
||||||
|
}
|
||||||
|
)
|
||||||
if (state.canDelete) {
|
if (state.canDelete) {
|
||||||
HorizontalDivider()
|
HorizontalDivider()
|
||||||
ListItem(
|
ListItem(
|
||||||
|
|
@ -196,6 +214,8 @@ internal fun MediaDetailsBottomSheetPreview() = ElementPreview {
|
||||||
MediaDetailsBottomSheet(
|
MediaDetailsBottomSheet(
|
||||||
state = aMediaDetailsBottomSheetState(),
|
state = aMediaDetailsBottomSheetState(),
|
||||||
onViewInTimeline = {},
|
onViewInTimeline = {},
|
||||||
|
onShare = {},
|
||||||
|
onDownload = {},
|
||||||
onDelete = {},
|
onDelete = {},
|
||||||
onDismiss = {},
|
onDismiss = {},
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ import io.element.android.libraries.mediaviewer.api.MediaInfo
|
||||||
sealed interface MediaGalleryEvents {
|
sealed interface MediaGalleryEvents {
|
||||||
data class ChangeMode(val mode: MediaGalleryMode) : MediaGalleryEvents
|
data class ChangeMode(val mode: MediaGalleryMode) : MediaGalleryEvents
|
||||||
data class LoadMore(val direction: Timeline.PaginationDirection) : MediaGalleryEvents
|
data class LoadMore(val direction: Timeline.PaginationDirection) : MediaGalleryEvents
|
||||||
data class Share(val mediaItem: MediaItem.Event) : MediaGalleryEvents
|
data class Share(val eventId: EventId?) : MediaGalleryEvents
|
||||||
data class SaveOnDisk(val mediaItem: MediaItem.Event) : MediaGalleryEvents
|
data class SaveOnDisk(val eventId: EventId?) : MediaGalleryEvents
|
||||||
data class OpenInfo(val mediaItem: MediaItem.Event) : MediaGalleryEvents
|
data class OpenInfo(val mediaItem: MediaItem.Event) : MediaGalleryEvents
|
||||||
data class ViewInTimeline(val eventId: EventId) : MediaGalleryEvents
|
data class ViewInTimeline(val eventId: EventId) : MediaGalleryEvents
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -117,8 +117,16 @@ class MediaGalleryPresenter @AssistedInject constructor(
|
||||||
timeline.dataOrNull()?.paginate(event.direction)
|
timeline.dataOrNull()?.paginate(event.direction)
|
||||||
}
|
}
|
||||||
is MediaGalleryEvents.Delete -> coroutineScope.delete(timeline, event.eventId)
|
is MediaGalleryEvents.Delete -> coroutineScope.delete(timeline, event.eventId)
|
||||||
is MediaGalleryEvents.SaveOnDisk -> coroutineScope.saveOnDisk(event.mediaItem)
|
is MediaGalleryEvents.SaveOnDisk -> coroutineScope.launch {
|
||||||
is MediaGalleryEvents.Share -> coroutineScope.share(event.mediaItem)
|
mediaItems.dataOrNull().find(event.eventId)?.let {
|
||||||
|
saveOnDisk(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is MediaGalleryEvents.Share -> coroutineScope.launch {
|
||||||
|
mediaItems.dataOrNull().find(event.eventId)?.let {
|
||||||
|
share(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
is MediaGalleryEvents.ViewInTimeline -> {
|
is MediaGalleryEvents.ViewInTimeline -> {
|
||||||
mediaBottomSheetState = MediaBottomSheetState.Hidden
|
mediaBottomSheetState = MediaBottomSheetState.Hidden
|
||||||
navigator.onViewInTimelineClick(event.eventId)
|
navigator.onViewInTimelineClick(event.eventId)
|
||||||
|
|
@ -221,7 +229,7 @@ class MediaGalleryPresenter @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun CoroutineScope.saveOnDisk(mediaItem: MediaItem.Event) = launch {
|
private suspend fun saveOnDisk(mediaItem: MediaItem.Event) {
|
||||||
downloadMedia(mediaItem)
|
downloadMedia(mediaItem)
|
||||||
.mapCatching { localMedia ->
|
.mapCatching { localMedia ->
|
||||||
localMediaActions.saveOnDisk(localMedia)
|
localMediaActions.saveOnDisk(localMedia)
|
||||||
|
|
@ -236,7 +244,7 @@ class MediaGalleryPresenter @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun CoroutineScope.share(mediaItem: MediaItem.Event) = launch {
|
private suspend fun share(mediaItem: MediaItem.Event) {
|
||||||
downloadMedia(mediaItem)
|
downloadMedia(mediaItem)
|
||||||
.mapCatching { localMedia ->
|
.mapCatching { localMedia ->
|
||||||
localMediaActions.share(localMedia)
|
localMediaActions.share(localMedia)
|
||||||
|
|
@ -255,3 +263,11 @@ class MediaGalleryPresenter @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun List<MediaItem>?.find(eventId: EventId?): MediaItem.Event? {
|
||||||
|
if (this == null || eventId == null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return filterIsInstance<MediaItem.Event>()
|
||||||
|
.firstOrNull { it.eventId() == eventId }
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,12 @@ fun MediaGalleryView(
|
||||||
onViewInTimeline = { eventId ->
|
onViewInTimeline = { eventId ->
|
||||||
state.eventSink(MediaGalleryEvents.ViewInTimeline(eventId))
|
state.eventSink(MediaGalleryEvents.ViewInTimeline(eventId))
|
||||||
},
|
},
|
||||||
|
onShare = { eventId ->
|
||||||
|
state.eventSink(MediaGalleryEvents.Share(eventId))
|
||||||
|
},
|
||||||
|
onDownload = { eventId ->
|
||||||
|
state.eventSink(MediaGalleryEvents.SaveOnDisk(eventId))
|
||||||
|
},
|
||||||
onDelete = { eventId ->
|
onDelete = { eventId ->
|
||||||
state.eventSink(
|
state.eventSink(
|
||||||
MediaGalleryEvents.ConfirmDelete(
|
MediaGalleryEvents.ConfirmDelete(
|
||||||
|
|
@ -276,11 +282,17 @@ private fun MediaGalleryFilesList(
|
||||||
modifier = Modifier.animateItem(),
|
modifier = Modifier.animateItem(),
|
||||||
file = item,
|
file = item,
|
||||||
onClick = { onItemClick(item) },
|
onClick = { onItemClick(item) },
|
||||||
|
onLongClick = {
|
||||||
|
eventSink(MediaGalleryEvents.OpenInfo(item))
|
||||||
|
},
|
||||||
)
|
)
|
||||||
is MediaItem.Audio -> AudioItemView(
|
is MediaItem.Audio -> AudioItemView(
|
||||||
modifier = Modifier.animateItem(),
|
modifier = Modifier.animateItem(),
|
||||||
audio = item,
|
audio = item,
|
||||||
onClick = { onItemClick(item) },
|
onClick = { onItemClick(item) },
|
||||||
|
onLongClick = {
|
||||||
|
eventSink(MediaGalleryEvents.OpenInfo(item))
|
||||||
|
},
|
||||||
)
|
)
|
||||||
is MediaItem.Voice -> {
|
is MediaItem.Voice -> {
|
||||||
val presenter: Presenter<VoiceMessageState> = presenterFactories.rememberPresenter(item)
|
val presenter: Presenter<VoiceMessageState> = presenterFactories.rememberPresenter(item)
|
||||||
|
|
@ -288,9 +300,9 @@ private fun MediaGalleryFilesList(
|
||||||
modifier = Modifier.animateItem(),
|
modifier = Modifier.animateItem(),
|
||||||
state = presenter.present(),
|
state = presenter.present(),
|
||||||
voice = item,
|
voice = item,
|
||||||
onShareClick = { eventSink(MediaGalleryEvents.Share(item)) },
|
onLongClick = {
|
||||||
onDownloadClick = { eventSink(MediaGalleryEvents.SaveOnDisk(item)) },
|
eventSink(MediaGalleryEvents.OpenInfo(item))
|
||||||
onInfoClick = { eventSink(MediaGalleryEvents.OpenInfo(item)) },
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is MediaItem.DateSeparator -> DateItemView(
|
is MediaItem.DateSeparator -> DateItemView(
|
||||||
|
|
|
||||||
|
|
@ -122,8 +122,6 @@ class MediaGalleryRootNode @AssistedInject constructor(
|
||||||
mediaSource = navTarget.mediaSource,
|
mediaSource = navTarget.mediaSource,
|
||||||
thumbnailSource = navTarget.thumbnailSource,
|
thumbnailSource = navTarget.thumbnailSource,
|
||||||
canShowInfo = true,
|
canShowInfo = true,
|
||||||
canDownload = true,
|
|
||||||
canShare = true,
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.callback(callback)
|
.callback(callback)
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,9 @@
|
||||||
|
|
||||||
package io.element.android.libraries.mediaviewer.impl.gallery.ui
|
package io.element.android.libraries.mediaviewer.impl.gallery.ui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.combinedClickable
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
|
@ -41,6 +42,7 @@ import io.element.android.libraries.mediaviewer.impl.gallery.MediaItem
|
||||||
fun AudioItemView(
|
fun AudioItemView(
|
||||||
audio: MediaItem.Audio,
|
audio: MediaItem.Audio,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
|
onLongClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
|
|
@ -52,6 +54,7 @@ fun AudioItemView(
|
||||||
FilenameRow(
|
FilenameRow(
|
||||||
audio = audio,
|
audio = audio,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
|
onLongClick = onLongClick,
|
||||||
)
|
)
|
||||||
val caption = audio.mediaInfo.caption
|
val caption = audio.mediaInfo.caption
|
||||||
if (caption != null) {
|
if (caption != null) {
|
||||||
|
|
@ -63,10 +66,12 @@ fun AudioItemView(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun FilenameRow(
|
private fun FilenameRow(
|
||||||
audio: MediaItem.Audio,
|
audio: MediaItem.Audio,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
|
onLongClick: () -> Unit,
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|
@ -75,7 +80,7 @@ private fun FilenameRow(
|
||||||
color = ElementTheme.colors.bgSubtleSecondary,
|
color = ElementTheme.colors.bgSubtleSecondary,
|
||||||
shape = RoundedCornerShape(12.dp),
|
shape = RoundedCornerShape(12.dp),
|
||||||
)
|
)
|
||||||
.clickable { onClick() }
|
.combinedClickable(onClick = onClick, onLongClick = onLongClick)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(start = 12.dp, end = 36.dp, top = 8.dp, bottom = 8.dp),
|
.padding(start = 12.dp, end = 36.dp, top = 8.dp, bottom = 8.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
|
@ -119,5 +124,6 @@ internal fun AudioItemViewPreview(
|
||||||
AudioItemView(
|
AudioItemView(
|
||||||
audio = audio,
|
audio = audio,
|
||||||
onClick = {},
|
onClick = {},
|
||||||
|
onLongClick = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,9 @@
|
||||||
|
|
||||||
package io.element.android.libraries.mediaviewer.impl.gallery.ui
|
package io.element.android.libraries.mediaviewer.impl.gallery.ui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.combinedClickable
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
|
@ -40,6 +41,7 @@ import io.element.android.libraries.mediaviewer.impl.gallery.MediaItem
|
||||||
fun FileItemView(
|
fun FileItemView(
|
||||||
file: MediaItem.File,
|
file: MediaItem.File,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
|
onLongClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
|
|
@ -51,6 +53,7 @@ fun FileItemView(
|
||||||
FilenameRow(
|
FilenameRow(
|
||||||
file = file,
|
file = file,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
|
onLongClick = onLongClick,
|
||||||
)
|
)
|
||||||
val caption = file.mediaInfo.caption
|
val caption = file.mediaInfo.caption
|
||||||
if (caption != null) {
|
if (caption != null) {
|
||||||
|
|
@ -62,10 +65,12 @@ fun FileItemView(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun FilenameRow(
|
private fun FilenameRow(
|
||||||
file: MediaItem.File,
|
file: MediaItem.File,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
|
onLongClick: () -> Unit,
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|
@ -74,7 +79,7 @@ private fun FilenameRow(
|
||||||
color = ElementTheme.colors.bgSubtleSecondary,
|
color = ElementTheme.colors.bgSubtleSecondary,
|
||||||
shape = RoundedCornerShape(12.dp),
|
shape = RoundedCornerShape(12.dp),
|
||||||
)
|
)
|
||||||
.clickable { onClick() }
|
.combinedClickable(onClick = onClick, onLongClick = onLongClick)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(start = 12.dp, end = 36.dp, top = 8.dp, bottom = 8.dp),
|
.padding(start = 12.dp, end = 36.dp, top = 8.dp, bottom = 8.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
|
@ -118,5 +123,6 @@ internal fun FileItemViewPreview(
|
||||||
FileItemView(
|
FileItemView(
|
||||||
file = file,
|
file = file,
|
||||||
onClick = {},
|
onClick = {},
|
||||||
|
onLongClick = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,10 @@
|
||||||
|
|
||||||
package io.element.android.libraries.mediaviewer.impl.gallery.ui
|
package io.element.android.libraries.mediaviewer.impl.gallery.ui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.combinedClickable
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
|
@ -58,9 +59,7 @@ import kotlinx.coroutines.delay
|
||||||
fun VoiceItemView(
|
fun VoiceItemView(
|
||||||
state: VoiceMessageState,
|
state: VoiceMessageState,
|
||||||
voice: MediaItem.Voice,
|
voice: MediaItem.Voice,
|
||||||
onShareClick: () -> Unit,
|
onLongClick: () -> Unit,
|
||||||
onDownloadClick: () -> Unit,
|
|
||||||
onInfoClick: () -> Unit,
|
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
|
|
@ -72,6 +71,7 @@ fun VoiceItemView(
|
||||||
VoiceInfoRow(
|
VoiceInfoRow(
|
||||||
state = state,
|
state = state,
|
||||||
voice = voice,
|
voice = voice,
|
||||||
|
onLongClick = onLongClick,
|
||||||
)
|
)
|
||||||
val caption = voice.mediaInfo.caption
|
val caption = voice.mediaInfo.caption
|
||||||
if (caption != null) {
|
if (caption != null) {
|
||||||
|
|
@ -79,19 +79,16 @@ fun VoiceItemView(
|
||||||
} else {
|
} else {
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
}
|
}
|
||||||
ActionIconsRow(
|
|
||||||
onShareClick = onShareClick,
|
|
||||||
onDownloadClick = onDownloadClick,
|
|
||||||
onInfoClick = onInfoClick,
|
|
||||||
)
|
|
||||||
HorizontalDivider()
|
HorizontalDivider()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun VoiceInfoRow(
|
private fun VoiceInfoRow(
|
||||||
state: VoiceMessageState,
|
state: VoiceMessageState,
|
||||||
voice: MediaItem.Voice,
|
voice: MediaItem.Voice,
|
||||||
|
onLongClick: () -> Unit,
|
||||||
) {
|
) {
|
||||||
fun playPause() {
|
fun playPause() {
|
||||||
state.eventSink(VoiceMessageEvents.PlayPause)
|
state.eventSink(VoiceMessageEvents.PlayPause)
|
||||||
|
|
@ -104,6 +101,7 @@ private fun VoiceInfoRow(
|
||||||
color = ElementTheme.colors.bgSubtleSecondary,
|
color = ElementTheme.colors.bgSubtleSecondary,
|
||||||
shape = RoundedCornerShape(12.dp),
|
shape = RoundedCornerShape(12.dp),
|
||||||
)
|
)
|
||||||
|
.combinedClickable(onClick = {}, onLongClick = onLongClick)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(start = 12.dp, end = 36.dp, top = 8.dp, bottom = 8.dp),
|
.padding(start = 12.dp, end = 36.dp, top = 8.dp, bottom = 8.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
|
@ -257,43 +255,6 @@ private fun CustomIconButton(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun ActionIconsRow(
|
|
||||||
onShareClick: () -> Unit,
|
|
||||||
onDownloadClick: () -> Unit,
|
|
||||||
onInfoClick: () -> Unit,
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
horizontalArrangement = Arrangement.End
|
|
||||||
) {
|
|
||||||
IconButton(
|
|
||||||
onClick = onShareClick,
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = CompoundIcons.ShareAndroid(),
|
|
||||||
contentDescription = null,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
IconButton(
|
|
||||||
onClick = onDownloadClick,
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = CompoundIcons.Download(),
|
|
||||||
contentDescription = null,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
IconButton(
|
|
||||||
onClick = onInfoClick,
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = CompoundIcons.Info(),
|
|
||||||
contentDescription = null,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@PreviewsDayNight
|
@PreviewsDayNight
|
||||||
@Composable
|
@Composable
|
||||||
internal fun VoiceItemViewPreview(
|
internal fun VoiceItemViewPreview(
|
||||||
|
|
@ -302,9 +263,7 @@ internal fun VoiceItemViewPreview(
|
||||||
VoiceItemView(
|
VoiceItemView(
|
||||||
state = aVoiceMessageState(),
|
state = aVoiceMessageState(),
|
||||||
voice = voice,
|
voice = voice,
|
||||||
onShareClick = {},
|
onLongClick = {},
|
||||||
onDownloadClick = {},
|
|
||||||
onInfoClick = {},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -316,8 +275,6 @@ internal fun VoiceItemViewPlayPreview(
|
||||||
VoiceItemView(
|
VoiceItemView(
|
||||||
state = state,
|
state = state,
|
||||||
voice = aMediaItemVoice(),
|
voice = aMediaItemVoice(),
|
||||||
onShareClick = {},
|
onLongClick = {},
|
||||||
onDownloadClick = {},
|
|
||||||
onInfoClick = {},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,9 +83,18 @@ class MediaViewerPresenter @AssistedInject constructor(
|
||||||
when (mediaViewerEvents) {
|
when (mediaViewerEvents) {
|
||||||
MediaViewerEvents.RetryLoading -> loadMediaTrigger++
|
MediaViewerEvents.RetryLoading -> loadMediaTrigger++
|
||||||
MediaViewerEvents.ClearLoadingError -> localMedia.value = AsyncData.Uninitialized
|
MediaViewerEvents.ClearLoadingError -> localMedia.value = AsyncData.Uninitialized
|
||||||
MediaViewerEvents.SaveOnDisk -> coroutineScope.saveOnDisk(localMedia.value)
|
MediaViewerEvents.SaveOnDisk -> {
|
||||||
MediaViewerEvents.Share -> coroutineScope.share(localMedia.value)
|
mediaBottomSheetState = MediaBottomSheetState.Hidden
|
||||||
MediaViewerEvents.OpenWith -> coroutineScope.open(localMedia.value)
|
coroutineScope.saveOnDisk(localMedia.value)
|
||||||
|
}
|
||||||
|
MediaViewerEvents.Share -> {
|
||||||
|
mediaBottomSheetState = MediaBottomSheetState.Hidden
|
||||||
|
coroutineScope.share(localMedia.value)
|
||||||
|
}
|
||||||
|
MediaViewerEvents.OpenWith -> {
|
||||||
|
mediaBottomSheetState = MediaBottomSheetState.Hidden
|
||||||
|
coroutineScope.open(localMedia.value)
|
||||||
|
}
|
||||||
is MediaViewerEvents.Delete -> {
|
is MediaViewerEvents.Delete -> {
|
||||||
mediaBottomSheetState = MediaBottomSheetState.Hidden
|
mediaBottomSheetState = MediaBottomSheetState.Hidden
|
||||||
coroutineScope.delete(mediaViewerEvents.eventId)
|
coroutineScope.delete(mediaViewerEvents.eventId)
|
||||||
|
|
@ -126,8 +135,6 @@ class MediaViewerPresenter @AssistedInject constructor(
|
||||||
downloadedMedia = localMedia.value,
|
downloadedMedia = localMedia.value,
|
||||||
snackbarMessage = snackbarMessage,
|
snackbarMessage = snackbarMessage,
|
||||||
canShowInfo = inputs.canShowInfo,
|
canShowInfo = inputs.canShowInfo,
|
||||||
canDownload = inputs.canDownload,
|
|
||||||
canShare = inputs.canShare,
|
|
||||||
mediaBottomSheetState = mediaBottomSheetState,
|
mediaBottomSheetState = mediaBottomSheetState,
|
||||||
eventSink = ::handleEvents
|
eventSink = ::handleEvents
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,6 @@ data class MediaViewerState(
|
||||||
val downloadedMedia: AsyncData<LocalMedia>,
|
val downloadedMedia: AsyncData<LocalMedia>,
|
||||||
val snackbarMessage: SnackbarMessage?,
|
val snackbarMessage: SnackbarMessage?,
|
||||||
val canShowInfo: Boolean,
|
val canShowInfo: Boolean,
|
||||||
val canDownload: Boolean,
|
|
||||||
val canShare: Boolean,
|
|
||||||
val mediaBottomSheetState: MediaBottomSheetState,
|
val mediaBottomSheetState: MediaBottomSheetState,
|
||||||
val eventSink: (MediaViewerEvents) -> Unit,
|
val eventSink: (MediaViewerEvents) -> Unit,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -91,8 +91,6 @@ open class MediaViewerStateProvider : PreviewParameterProvider<MediaViewerState>
|
||||||
),
|
),
|
||||||
mediaInfo = it,
|
mediaInfo = it,
|
||||||
canShowInfo = false,
|
canShowInfo = false,
|
||||||
canDownload = false,
|
|
||||||
canShare = false,
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
aMediaViewerState(
|
aMediaViewerState(
|
||||||
|
|
@ -118,8 +116,6 @@ fun aMediaViewerState(
|
||||||
downloadedMedia: AsyncData<LocalMedia> = AsyncData.Uninitialized,
|
downloadedMedia: AsyncData<LocalMedia> = AsyncData.Uninitialized,
|
||||||
mediaInfo: MediaInfo = anImageMediaInfo(),
|
mediaInfo: MediaInfo = anImageMediaInfo(),
|
||||||
canShowInfo: Boolean = true,
|
canShowInfo: Boolean = true,
|
||||||
canDownload: Boolean = true,
|
|
||||||
canShare: Boolean = true,
|
|
||||||
mediaBottomSheetState: MediaBottomSheetState = MediaBottomSheetState.Hidden,
|
mediaBottomSheetState: MediaBottomSheetState = MediaBottomSheetState.Hidden,
|
||||||
eventSink: (MediaViewerEvents) -> Unit = {},
|
eventSink: (MediaViewerEvents) -> Unit = {},
|
||||||
) = MediaViewerState(
|
) = MediaViewerState(
|
||||||
|
|
@ -129,8 +125,6 @@ fun aMediaViewerState(
|
||||||
downloadedMedia = downloadedMedia,
|
downloadedMedia = downloadedMedia,
|
||||||
snackbarMessage = null,
|
snackbarMessage = null,
|
||||||
canShowInfo = canShowInfo,
|
canShowInfo = canShowInfo,
|
||||||
canDownload = canDownload,
|
|
||||||
canShare = canShare,
|
|
||||||
mediaBottomSheetState = mediaBottomSheetState,
|
mediaBottomSheetState = mediaBottomSheetState,
|
||||||
eventSink = eventSink,
|
eventSink = eventSink,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -119,8 +119,6 @@ fun MediaViewerView(
|
||||||
) {
|
) {
|
||||||
MediaViewerTopBar(
|
MediaViewerTopBar(
|
||||||
actionsEnabled = state.downloadedMedia is AsyncData.Success,
|
actionsEnabled = state.downloadedMedia is AsyncData.Success,
|
||||||
canDownload = state.canDownload,
|
|
||||||
canShare = state.canShare,
|
|
||||||
mimeType = state.mediaInfo.mimeType,
|
mimeType = state.mediaInfo.mimeType,
|
||||||
senderName = state.mediaInfo.senderName,
|
senderName = state.mediaInfo.senderName,
|
||||||
dateSent = state.mediaInfo.dateSent,
|
dateSent = state.mediaInfo.dateSent,
|
||||||
|
|
@ -148,6 +146,12 @@ fun MediaViewerView(
|
||||||
onViewInTimeline = {
|
onViewInTimeline = {
|
||||||
state.eventSink(MediaViewerEvents.ViewInTimeline(it))
|
state.eventSink(MediaViewerEvents.ViewInTimeline(it))
|
||||||
},
|
},
|
||||||
|
onShare = {
|
||||||
|
state.eventSink(MediaViewerEvents.Share)
|
||||||
|
},
|
||||||
|
onDownload = {
|
||||||
|
state.eventSink(MediaViewerEvents.SaveOnDisk)
|
||||||
|
},
|
||||||
onDelete = { eventId ->
|
onDelete = { eventId ->
|
||||||
state.eventSink(MediaViewerEvents.ConfirmDelete(eventId))
|
state.eventSink(MediaViewerEvents.ConfirmDelete(eventId))
|
||||||
},
|
},
|
||||||
|
|
@ -313,8 +317,6 @@ private fun rememberShowProgress(downloadedMedia: AsyncData<LocalMedia>): Boolea
|
||||||
@Composable
|
@Composable
|
||||||
private fun MediaViewerTopBar(
|
private fun MediaViewerTopBar(
|
||||||
actionsEnabled: Boolean,
|
actionsEnabled: Boolean,
|
||||||
canDownload: Boolean,
|
|
||||||
canShare: Boolean,
|
|
||||||
mimeType: String,
|
mimeType: String,
|
||||||
senderName: String?,
|
senderName: String?,
|
||||||
dateSent: String?,
|
dateSent: String?,
|
||||||
|
|
@ -348,19 +350,6 @@ private fun MediaViewerTopBar(
|
||||||
),
|
),
|
||||||
navigationIcon = { BackButton(onClick = onBackClick) },
|
navigationIcon = { BackButton(onClick = onBackClick) },
|
||||||
actions = {
|
actions = {
|
||||||
if (canShare) {
|
|
||||||
IconButton(
|
|
||||||
enabled = actionsEnabled,
|
|
||||||
onClick = {
|
|
||||||
eventSink(MediaViewerEvents.Share)
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = CompoundIcons.ShareAndroid(),
|
|
||||||
contentDescription = stringResource(id = CommonStrings.action_share)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IconButton(
|
IconButton(
|
||||||
enabled = actionsEnabled,
|
enabled = actionsEnabled,
|
||||||
onClick = {
|
onClick = {
|
||||||
|
|
@ -378,19 +367,6 @@ private fun MediaViewerTopBar(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (canDownload) {
|
|
||||||
IconButton(
|
|
||||||
enabled = actionsEnabled,
|
|
||||||
onClick = {
|
|
||||||
eventSink(MediaViewerEvents.SaveOnDisk)
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = CompoundIcons.Download(),
|
|
||||||
contentDescription = stringResource(id = CommonStrings.action_save),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (canShowInfo) {
|
if (canShowInfo) {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = onInfoClick,
|
onClick = onInfoClick,
|
||||||
|
|
|
||||||
|
|
@ -66,8 +66,6 @@ class MediaViewerPresenterTest {
|
||||||
assertThat(initialState.downloadedMedia).isInstanceOf(AsyncData.Success::class.java)
|
assertThat(initialState.downloadedMedia).isInstanceOf(AsyncData.Success::class.java)
|
||||||
assertThat(initialState.snackbarMessage).isNull()
|
assertThat(initialState.snackbarMessage).isNull()
|
||||||
assertThat(initialState.canShowInfo).isTrue()
|
assertThat(initialState.canShowInfo).isTrue()
|
||||||
assertThat(initialState.canDownload).isTrue()
|
|
||||||
assertThat(initialState.canShare).isTrue()
|
|
||||||
assertThat(initialState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden)
|
assertThat(initialState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -86,48 +84,6 @@ class MediaViewerPresenterTest {
|
||||||
assertThat(initialState.downloadedMedia).isInstanceOf(AsyncData.Success::class.java)
|
assertThat(initialState.downloadedMedia).isInstanceOf(AsyncData.Success::class.java)
|
||||||
assertThat(initialState.snackbarMessage).isNull()
|
assertThat(initialState.snackbarMessage).isNull()
|
||||||
assertThat(initialState.canShowInfo).isFalse()
|
assertThat(initialState.canShowInfo).isFalse()
|
||||||
assertThat(initialState.canDownload).isTrue()
|
|
||||||
assertThat(initialState.canShare).isTrue()
|
|
||||||
assertThat(initialState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `present - initial state cannot share`() = runTest {
|
|
||||||
val presenter = createMediaViewerPresenter(
|
|
||||||
canShare = false,
|
|
||||||
room = FakeMatrixRoom(
|
|
||||||
canRedactOwnResult = { Result.success(true) },
|
|
||||||
)
|
|
||||||
)
|
|
||||||
presenter.test {
|
|
||||||
skipItems(2)
|
|
||||||
val initialState = awaitItem()
|
|
||||||
assertThat(initialState.downloadedMedia).isInstanceOf(AsyncData.Success::class.java)
|
|
||||||
assertThat(initialState.snackbarMessage).isNull()
|
|
||||||
assertThat(initialState.canShowInfo).isTrue()
|
|
||||||
assertThat(initialState.canDownload).isTrue()
|
|
||||||
assertThat(initialState.canShare).isFalse()
|
|
||||||
assertThat(initialState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `present - initial state cannot download`() = runTest {
|
|
||||||
val presenter = createMediaViewerPresenter(
|
|
||||||
canDownload = false,
|
|
||||||
room = FakeMatrixRoom(
|
|
||||||
canRedactOwnResult = { Result.success(true) },
|
|
||||||
)
|
|
||||||
)
|
|
||||||
presenter.test {
|
|
||||||
skipItems(2)
|
|
||||||
val initialState = awaitItem()
|
|
||||||
assertThat(initialState.downloadedMedia).isInstanceOf(AsyncData.Success::class.java)
|
|
||||||
assertThat(initialState.snackbarMessage).isNull()
|
|
||||||
assertThat(initialState.canShowInfo).isTrue()
|
|
||||||
assertThat(initialState.canDownload).isFalse()
|
|
||||||
assertThat(initialState.canShare).isTrue()
|
|
||||||
assertThat(initialState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden)
|
assertThat(initialState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -146,8 +102,6 @@ class MediaViewerPresenterTest {
|
||||||
assertThat(initialState.downloadedMedia).isInstanceOf(AsyncData.Success::class.java)
|
assertThat(initialState.downloadedMedia).isInstanceOf(AsyncData.Success::class.java)
|
||||||
assertThat(initialState.snackbarMessage).isNull()
|
assertThat(initialState.snackbarMessage).isNull()
|
||||||
assertThat(initialState.canShowInfo).isTrue()
|
assertThat(initialState.canShowInfo).isTrue()
|
||||||
assertThat(initialState.canDownload).isTrue()
|
|
||||||
assertThat(initialState.canShare).isTrue()
|
|
||||||
assertThat(initialState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden)
|
assertThat(initialState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -167,8 +121,6 @@ class MediaViewerPresenterTest {
|
||||||
assertThat(initialState.downloadedMedia).isInstanceOf(AsyncData.Success::class.java)
|
assertThat(initialState.downloadedMedia).isInstanceOf(AsyncData.Success::class.java)
|
||||||
assertThat(initialState.snackbarMessage).isNull()
|
assertThat(initialState.snackbarMessage).isNull()
|
||||||
assertThat(initialState.canShowInfo).isTrue()
|
assertThat(initialState.canShowInfo).isTrue()
|
||||||
assertThat(initialState.canDownload).isTrue()
|
|
||||||
assertThat(initialState.canShare).isTrue()
|
|
||||||
assertThat(initialState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden)
|
assertThat(initialState.mediaBottomSheetState).isEqualTo(MediaBottomSheetState.Hidden)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -350,8 +302,6 @@ class MediaViewerPresenterTest {
|
||||||
localMediaActions: FakeLocalMediaActions = FakeLocalMediaActions(),
|
localMediaActions: FakeLocalMediaActions = FakeLocalMediaActions(),
|
||||||
snackbarDispatcher: SnackbarDispatcher = SnackbarDispatcher(),
|
snackbarDispatcher: SnackbarDispatcher = SnackbarDispatcher(),
|
||||||
canShowInfo: Boolean = true,
|
canShowInfo: Boolean = true,
|
||||||
canShare: Boolean = true,
|
|
||||||
canDownload: Boolean = true,
|
|
||||||
mediaViewerNavigator: MediaViewerNavigator = FakeMediaViewerNavigator(),
|
mediaViewerNavigator: MediaViewerNavigator = FakeMediaViewerNavigator(),
|
||||||
room: MatrixRoom = FakeMatrixRoom(
|
room: MatrixRoom = FakeMatrixRoom(
|
||||||
liveTimeline = FakeTimeline(),
|
liveTimeline = FakeTimeline(),
|
||||||
|
|
@ -364,8 +314,6 @@ class MediaViewerPresenterTest {
|
||||||
mediaSource = aMediaSource(),
|
mediaSource = aMediaSource(),
|
||||||
thumbnailSource = null,
|
thumbnailSource = null,
|
||||||
canShowInfo = canShowInfo,
|
canShowInfo = canShowInfo,
|
||||||
canShare = canShare,
|
|
||||||
canDownload = canDownload,
|
|
||||||
),
|
),
|
||||||
localMediaFactory = localMediaFactory,
|
localMediaFactory = localMediaFactory,
|
||||||
mediaLoader = matrixMediaLoader,
|
mediaLoader = matrixMediaLoader,
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import io.element.android.libraries.architecture.AsyncData
|
import io.element.android.libraries.architecture.AsyncData
|
||||||
import io.element.android.libraries.mediaviewer.api.anImageMediaInfo
|
import io.element.android.libraries.mediaviewer.api.anImageMediaInfo
|
||||||
import io.element.android.libraries.mediaviewer.api.local.LocalMedia
|
import io.element.android.libraries.mediaviewer.api.local.LocalMedia
|
||||||
|
import io.element.android.libraries.mediaviewer.impl.details.aMediaDetailsBottomSheetState
|
||||||
import io.element.android.libraries.ui.strings.CommonStrings
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
import io.element.android.tests.testutils.EnsureNeverCalled
|
import io.element.android.tests.testutils.EnsureNeverCalled
|
||||||
import io.element.android.tests.testutils.EventsRecorder
|
import io.element.android.tests.testutils.EventsRecorder
|
||||||
|
|
@ -54,16 +55,6 @@ class MediaViewerViewTest {
|
||||||
testMenuAction(CommonStrings.action_open_with, MediaViewerEvents.OpenWith)
|
testMenuAction(CommonStrings.action_open_with, MediaViewerEvents.OpenWith)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `clicking on save emit expected Event`() {
|
|
||||||
testMenuAction(CommonStrings.action_save, MediaViewerEvents.SaveOnDisk)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `clicking on share emit expected Event`() {
|
|
||||||
testMenuAction(CommonStrings.action_share, MediaViewerEvents.Share)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun testMenuAction(contentDescriptionRes: Int, expectedEvent: MediaViewerEvents) {
|
private fun testMenuAction(contentDescriptionRes: Int, expectedEvent: MediaViewerEvents) {
|
||||||
val eventsRecorder = EventsRecorder<MediaViewerEvents>()
|
val eventsRecorder = EventsRecorder<MediaViewerEvents>()
|
||||||
rule.setMediaViewerView(
|
rule.setMediaViewerView(
|
||||||
|
|
@ -80,6 +71,32 @@ class MediaViewerViewTest {
|
||||||
eventsRecorder.assertSingle(expectedEvent)
|
eventsRecorder.assertSingle(expectedEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `clicking on save emit expected Event`() {
|
||||||
|
testBottomSheetAction(CommonStrings.action_save, MediaViewerEvents.SaveOnDisk)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `clicking on share emit expected Event`() {
|
||||||
|
testBottomSheetAction(CommonStrings.action_share, MediaViewerEvents.Share)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun testBottomSheetAction(contentDescriptionRes: Int, expectedEvent: MediaViewerEvents) {
|
||||||
|
val eventsRecorder = EventsRecorder<MediaViewerEvents>()
|
||||||
|
rule.setMediaViewerView(
|
||||||
|
aMediaViewerState(
|
||||||
|
downloadedMedia = AsyncData.Success(
|
||||||
|
LocalMedia(Uri.EMPTY, anImageMediaInfo())
|
||||||
|
),
|
||||||
|
mediaInfo = anImageMediaInfo(),
|
||||||
|
mediaBottomSheetState = aMediaDetailsBottomSheetState(),
|
||||||
|
eventSink = eventsRecorder
|
||||||
|
),
|
||||||
|
)
|
||||||
|
rule.clickOn(contentDescriptionRes)
|
||||||
|
eventsRecorder.assertSingle(expectedEvent)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `clicking on image hides the overlay`() {
|
fun `clicking on image hides the overlay`() {
|
||||||
val eventsRecorder = EventsRecorder<MediaViewerEvents>(expectEvents = false)
|
val eventsRecorder = EventsRecorder<MediaViewerEvents>(expectEvents = false)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue