From 3b5b443cbbababbf416eec80972d057d59bbc05e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 29 Nov 2024 13:50:19 +0100 Subject: [PATCH 01/13] MediaViewer: iterate on design --- .../messages/impl/MessagesFlowNode.kt | 20 ++- .../libraries/mediaviewer/api/MediaInfo.kt | 43 ++++- .../impl/DefaultMediaViewerEntryPoint.kt | 4 +- .../impl/local/AndroidLocalMediaFactory.kt | 12 +- .../impl/local/DefaultLocalMediaRenderer.kt | 1 + .../mediaviewer/impl/local/LocalMediaView.kt | 2 + .../impl/local/video/MediaVideoView.kt | 9 +- .../impl/viewer/MediaViewerStateProvider.kt | 96 ++++++----- .../impl/viewer/MediaViewerView.kt | 151 ++++++++++++++---- .../local/AndroidLocalMediaFactoryTest.kt | 8 +- .../mediaviewer/test/FakeLocalMediaFactory.kt | 4 +- 11 files changed, 264 insertions(+), 86 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt index 9d5ed6ff8c..e80f99a67c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt @@ -337,7 +337,9 @@ class MessagesFlowNode @AssistedInject constructor( caption = event.content.caption, mimeType = event.content.mimeType, formattedFileSize = event.content.formattedFileSize, - fileExtension = event.content.fileExtension + fileExtension = event.content.fileExtension, + senderName = event.safeSenderName, + dateSent = event.sentTime, ), mediaSource = event.content.mediaSource, thumbnailSource = event.content.thumbnailSource, @@ -355,7 +357,9 @@ class MessagesFlowNode @AssistedInject constructor( caption = event.content.caption, mimeType = event.content.mimeType, formattedFileSize = event.content.formattedFileSize, - fileExtension = event.content.fileExtension + fileExtension = event.content.fileExtension, + senderName = event.safeSenderName, + dateSent = event.sentTime, ), mediaSource = event.content.preferredMediaSource, thumbnailSource = event.content.thumbnailSource, @@ -373,7 +377,9 @@ class MessagesFlowNode @AssistedInject constructor( caption = event.content.caption, mimeType = event.content.mimeType, formattedFileSize = event.content.formattedFileSize, - fileExtension = event.content.fileExtension + fileExtension = event.content.fileExtension, + senderName = event.safeSenderName, + dateSent = event.sentTime, ), mediaSource = event.content.videoSource, thumbnailSource = event.content.thumbnailSource, @@ -388,7 +394,9 @@ class MessagesFlowNode @AssistedInject constructor( caption = event.content.caption, mimeType = event.content.mimeType, formattedFileSize = event.content.formattedFileSize, - fileExtension = event.content.fileExtension + fileExtension = event.content.fileExtension, + senderName = event.safeSenderName, + dateSent = event.sentTime, ), mediaSource = event.content.fileSource, thumbnailSource = event.content.thumbnailSource, @@ -403,7 +411,9 @@ class MessagesFlowNode @AssistedInject constructor( caption = event.content.caption, mimeType = event.content.mimeType, formattedFileSize = event.content.formattedFileSize, - fileExtension = event.content.fileExtension + fileExtension = event.content.fileExtension, + senderName = event.safeSenderName, + dateSent = event.sentTime, ), mediaSource = event.content.mediaSource, thumbnailSource = null, diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaInfo.kt b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaInfo.kt index 93cd2f9378..5c317b1d6a 100644 --- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaInfo.kt +++ b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaInfo.kt @@ -18,44 +18,73 @@ data class MediaInfo( val mimeType: String, val formattedFileSize: String, val fileExtension: String, + val senderName: String?, + val dateSent: String?, ) : Parcelable -fun anImageMediaInfo(): MediaInfo = MediaInfo( +fun anImageMediaInfo( + caption: String? = null, + senderName: String? = null, + dateSent: String? = null, +): MediaInfo = MediaInfo( filename = "an image file.jpg", - caption = null, + caption = caption, mimeType = MimeTypes.Jpeg, formattedFileSize = "4MB", fileExtension = "jpg", + senderName = senderName, + dateSent = dateSent, ) -fun aVideoMediaInfo(): MediaInfo = MediaInfo( +fun aVideoMediaInfo( + caption: String? = null, + senderName: String? = null, + dateSent: String? = null, +): MediaInfo = MediaInfo( filename = "a video file.mp4", - caption = null, + caption = caption, mimeType = MimeTypes.Mp4, formattedFileSize = "14MB", fileExtension = "mp4", + senderName = senderName, + dateSent = dateSent, ) -fun aPdfMediaInfo(): MediaInfo = MediaInfo( +fun aPdfMediaInfo( + senderName: String? = null, + dateSent: String? = null, +): MediaInfo = MediaInfo( filename = "a pdf file.pdf", caption = null, mimeType = MimeTypes.Pdf, formattedFileSize = "23MB", fileExtension = "pdf", + senderName = senderName, + dateSent = dateSent, ) -fun anApkMediaInfo(): MediaInfo = MediaInfo( +fun anApkMediaInfo( + senderName: String? = null, + dateSent: String? = null, +): MediaInfo = MediaInfo( filename = "an apk file.apk", caption = null, mimeType = MimeTypes.Apk, formattedFileSize = "50MB", fileExtension = "apk", + senderName = senderName, + dateSent = dateSent, ) -fun anAudioMediaInfo(): MediaInfo = MediaInfo( +fun anAudioMediaInfo( + senderName: String? = null, + dateSent: String? = null, +): MediaInfo = MediaInfo( filename = "an audio file.mp3", caption = null, mimeType = MimeTypes.Mp3, formattedFileSize = "7MB", fileExtension = "mp3", + senderName = senderName, + dateSent = dateSent, ) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPoint.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPoint.kt index 5bd16c840b..86d7bca722 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPoint.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPoint.kt @@ -46,7 +46,9 @@ class DefaultMediaViewerEntryPoint @Inject constructor() : MediaViewerEntryPoint caption = null, mimeType = mimeType, formattedFileSize = "", - fileExtension = "" + fileExtension = "", + senderName = null, + dateSent = null, ), mediaSource = MediaSource(url = avatarUrl), thumbnailSource = null, diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt index 461563f465..8b5163cf6c 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt @@ -41,6 +41,8 @@ class AndroidLocalMediaFactory @Inject constructor( name = mediaInfo.filename, caption = mediaInfo.caption, formattedFileSize = mediaInfo.formattedFileSize, + senderName = mediaInfo.senderName, + dateSent = mediaInfo.dateSent, ) override fun createFromUri( @@ -54,6 +56,8 @@ class AndroidLocalMediaFactory @Inject constructor( name = name, caption = null, formattedFileSize = formattedFileSize, + senderName = null, + dateSent = null, ) private fun createFromUri( @@ -61,7 +65,9 @@ class AndroidLocalMediaFactory @Inject constructor( mimeType: String?, name: String?, caption: String?, - formattedFileSize: String? + formattedFileSize: String?, + senderName: String?, + dateSent: String?, ): LocalMedia { val resolvedMimeType = mimeType ?: context.getMimeType(uri) ?: MimeTypes.OctetStream val fileName = name ?: context.getFileName(uri) ?: "" @@ -74,7 +80,9 @@ class AndroidLocalMediaFactory @Inject constructor( filename = fileName, caption = caption, formattedFileSize = fileSize, - fileExtension = fileExtension + fileExtension = fileExtension, + senderName = senderName, + dateSent = dateSent, ) ) } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/DefaultLocalMediaRenderer.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/DefaultLocalMediaRenderer.kt index 6b1005dccf..b801ebe00f 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/DefaultLocalMediaRenderer.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/DefaultLocalMediaRenderer.kt @@ -29,6 +29,7 @@ class DefaultLocalMediaRenderer @Inject constructor() : LocalMediaRenderer { ) LocalMediaView( modifier = Modifier.fillMaxSize(), + bottomPaddingInPixels = 0, localMedia = localMedia, localMediaViewState = localMediaViewState, onClick = {} diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/LocalMediaView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/LocalMediaView.kt index 44392e27b9..5d0a2993df 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/LocalMediaView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/LocalMediaView.kt @@ -22,6 +22,7 @@ import io.element.android.libraries.mediaviewer.impl.local.video.MediaVideoView @Composable fun LocalMediaView( localMedia: LocalMedia?, + bottomPaddingInPixels: Int, onClick: () -> Unit, modifier: Modifier = Modifier, localMediaViewState: LocalMediaViewState = rememberLocalMediaViewState(), @@ -37,6 +38,7 @@ fun LocalMediaView( ) mimeType.isMimeTypeVideo() -> MediaVideoView( localMediaViewState = localMediaViewState, + bottomPaddingInPixels = bottomPaddingInPixels, localMedia = localMedia, modifier = modifier, ) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt index d978549192..6d172823e7 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaVideoView.kt @@ -14,6 +14,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf @@ -37,6 +38,7 @@ import androidx.media3.ui.PlayerView import io.element.android.compound.theme.ElementTheme import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.text.toDp import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.utils.KeepScreenOn import io.element.android.libraries.designsystem.utils.OnLifecycleEvent @@ -51,6 +53,7 @@ import kotlin.time.Duration.Companion.seconds @Composable fun MediaVideoView( localMediaViewState: LocalMediaViewState, + bottomPaddingInPixels: Int, localMedia: LocalMedia?, modifier: Modifier = Modifier, ) { @@ -66,6 +69,7 @@ fun MediaVideoView( } ExoPlayerMediaVideoView( localMediaViewState = localMediaViewState, + bottomPaddingInPixels = bottomPaddingInPixels, exoPlayer = exoPlayer, localMedia = localMedia, modifier = modifier, @@ -76,6 +80,7 @@ fun MediaVideoView( @Composable private fun ExoPlayerMediaVideoView( localMediaViewState: LocalMediaViewState, + bottomPaddingInPixels: Int, exoPlayer: ExoPlayer, localMedia: LocalMedia?, modifier: Modifier = Modifier, @@ -232,7 +237,8 @@ private fun ExoPlayerMediaVideoView( }, modifier = Modifier .fillMaxWidth() - .align(Alignment.BottomCenter), + .align(Alignment.BottomCenter) + .padding(bottom = bottomPaddingInPixels.toDp()), ) } @@ -254,6 +260,7 @@ private fun ExoPlayerMediaVideoView( internal fun MediaVideoViewPreview() = ElementPreview { MediaVideoView( modifier = Modifier.fillMaxSize(), + bottomPaddingInPixels = 0, localMediaViewState = rememberLocalMediaViewState(), localMedia = null, ) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt index 4ffcb75b07..6c7a9fb704 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt @@ -24,52 +24,72 @@ open class MediaViewerStateProvider : PreviewParameterProvider aMediaViewerState(), aMediaViewerState(AsyncData.Loading()), aMediaViewerState(AsyncData.Failure(IllegalStateException("error"))), - aMediaViewerState( - AsyncData.Success( - LocalMedia(Uri.EMPTY, anImageMediaInfo()) - ), - anImageMediaInfo(), - ), - aMediaViewerState( - AsyncData.Success( - LocalMedia(Uri.EMPTY, aVideoMediaInfo()) - ), - aVideoMediaInfo(), - ), - aMediaViewerState( - AsyncData.Success( - LocalMedia(Uri.EMPTY, aPdfMediaInfo()) - ), - aPdfMediaInfo(), - ), + anImageMediaInfo( + senderName = "Sally Sanderson", + dateSent = "21 NOV, 2024", + caption = "A caption", + ).let { + aMediaViewerState( + AsyncData.Success( + LocalMedia(Uri.EMPTY, it) + ), + it, + ) + }, + aVideoMediaInfo( + senderName = "Sally Sanderson", + dateSent = "21 NOV, 2024", + caption = "A caption", + ).let { + aMediaViewerState( + AsyncData.Success( + LocalMedia(Uri.EMPTY, it) + ), + it, + ) + }, + aPdfMediaInfo().let { + aMediaViewerState( + AsyncData.Success( + LocalMedia(Uri.EMPTY, it) + ), + it, + ) + }, aMediaViewerState( AsyncData.Loading(), anApkMediaInfo(), ), - aMediaViewerState( - AsyncData.Success( - LocalMedia(Uri.EMPTY, anApkMediaInfo()) - ), - anApkMediaInfo(), - ), + anApkMediaInfo().let { + aMediaViewerState( + AsyncData.Success( + LocalMedia(Uri.EMPTY, it) + ), + it, + ) + }, aMediaViewerState( AsyncData.Loading(), anAudioMediaInfo(), ), - aMediaViewerState( - AsyncData.Success( - LocalMedia(Uri.EMPTY, anAudioMediaInfo()) - ), - anAudioMediaInfo(), - ), - aMediaViewerState( - AsyncData.Success( - LocalMedia(Uri.EMPTY, anImageMediaInfo()) - ), - anImageMediaInfo(), - canDownload = false, - canShare = false, - ), + anAudioMediaInfo().let { + aMediaViewerState( + AsyncData.Success( + LocalMedia(Uri.EMPTY, it) + ), + it, + ) + }, + anImageMediaInfo().let { + aMediaViewerState( + AsyncData.Success( + LocalMedia(Uri.EMPTY, it) + ), + it, + canDownload = false, + canShare = false, + ) + }, ) } 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 ae5e9401cb..1e3c264d14 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 @@ -16,10 +16,14 @@ import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.OpenInNew import androidx.compose.material3.ExperimentalMaterial3Api @@ -28,6 +32,7 @@ import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberUpdatedState @@ -36,12 +41,15 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import coil.compose.AsyncImage +import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.core.mimetype.MimeTypes @@ -51,6 +59,7 @@ import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.IconButton import io.element.android.libraries.designsystem.theme.components.Scaffold +import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState @@ -80,6 +89,7 @@ fun MediaViewerView( val snackbarHostState = rememberSnackbarHostState(snackbarMessage = state.snackbarMessage) var showOverlay by remember { mutableStateOf(true) } + var bottomPaddingInPixels by remember { mutableIntStateOf(0) } BackHandler { onBackClick() } Scaffold( modifier, @@ -88,6 +98,7 @@ fun MediaViewerView( ) { MediaViewerPage( showOverlay = showOverlay, + bottomPaddingInPixels = bottomPaddingInPixels, state = state, onDismiss = { onBackClick() @@ -97,14 +108,29 @@ fun MediaViewerView( } ) AnimatedVisibility(visible = showOverlay, enter = fadeIn(), exit = fadeOut()) { - MediaViewerTopBar( - actionsEnabled = state.downloadedMedia is AsyncData.Success, - mimeType = state.mediaInfo.mimeType, - onBackClick = onBackClick, - canDownload = state.canDownload, - canShare = state.canShare, - eventSink = state.eventSink - ) + Box( + modifier = Modifier + .fillMaxSize() + .navigationBarsPadding() + ) { + MediaViewerTopBar( + actionsEnabled = state.downloadedMedia is AsyncData.Success, + senderName = state.mediaInfo.senderName, + dateSent = state.mediaInfo.dateSent, + onBackClick = onBackClick, + eventSink = state.eventSink + ) + MediaViewerBottomBar( + modifier = Modifier.align(Alignment.BottomCenter), + actionsEnabled = state.downloadedMedia is AsyncData.Success, + canDownload = state.canDownload, + canShare = state.canShare, + mimeType = state.mediaInfo.mimeType, + caption = state.mediaInfo.caption, + onHeightChanged = { bottomPaddingInPixels = it }, + eventSink = state.eventSink + ) + } } } } @@ -112,6 +138,7 @@ fun MediaViewerView( @Composable private fun MediaViewerPage( showOverlay: Boolean, + bottomPaddingInPixels: Int, state: MediaViewerState, onDismiss: () -> Unit, onShowOverlayChange: (Boolean) -> Unit, @@ -148,8 +175,8 @@ private fun MediaViewerPage( Box( modifier = Modifier - .fillMaxSize() - .navigationBarsPadding() + .fillMaxSize() + .navigationBarsPadding() ) { Box(contentAlignment = Alignment.Center) { val zoomableState = rememberZoomableState( @@ -168,6 +195,7 @@ private fun MediaViewerPage( LocalMediaView( modifier = Modifier.fillMaxSize(), + bottomPaddingInPixels = bottomPaddingInPixels, localMediaViewState = localMediaViewState, localMedia = state.downloadedMedia.dataOrNull(), mediaInfo = state.mediaInfo, @@ -193,8 +221,8 @@ private fun MediaViewerPage( if (showProgress) { LinearProgressIndicator( modifier = Modifier - .fillMaxWidth() - .height(2.dp) + .fillMaxWidth() + .height(2.dp) ) } } @@ -246,23 +274,99 @@ private fun rememberShowProgress(downloadedMedia: AsyncData): Boolea return showProgress } +@Suppress("UNUSED_PARAMETER") @OptIn(ExperimentalMaterial3Api::class) @Composable private fun MediaViewerTopBar( actionsEnabled: Boolean, - canDownload: Boolean, - canShare: Boolean, - mimeType: String, + senderName: String?, + dateSent: String?, onBackClick: () -> Unit, eventSink: (MediaViewerEvents) -> Unit, ) { TopAppBar( - title = {}, + title = { + if (senderName != null && dateSent != null) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(end = 48.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Text( + text = senderName, + style = ElementTheme.typography.fontBodyMdMedium, + color = ElementTheme.colors.textPrimary, + ) + Text( + text = dateSent, + style = ElementTheme.typography.fontBodySmRegular, + color = ElementTheme.colors.textPrimary, + ) + } + } + }, colors = TopAppBarDefaults.topAppBarColors( containerColor = Color.Transparent.copy(0.6f), ), navigationIcon = { BackButton(onClick = onBackClick) }, actions = { + // TODO Add action to open infos. + } + ) +} + +@Composable +private fun MediaViewerBottomBar( + actionsEnabled: Boolean, + canDownload: Boolean, + canShare: Boolean, + mimeType: String, + caption: String?, + onHeightChanged: (Int) -> Unit, + eventSink: (MediaViewerEvents) -> Unit, + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier + .fillMaxWidth() + .background(Color(0x99101317)) + .onSizeChanged { + onHeightChanged(it.height) + }, + ) { + if (caption != null) { + Text( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + text = caption, + maxLines = 5, + overflow = TextOverflow.Ellipsis, + style = ElementTheme.typography.fontBodyLgRegular, + ) + } + Row( + modifier = modifier + .fillMaxWidth() + .padding(start = 8.dp, end = 8.dp, bottom = 8.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + if (canShare) { + IconButton( + enabled = actionsEnabled, + onClick = { + eventSink(MediaViewerEvents.Share) + }, + modifier = Modifier.align(Alignment.CenterVertically) + ) { + Icon( + imageVector = CompoundIcons.ShareAndroid(), + contentDescription = stringResource(id = CommonStrings.action_share) + ) + } + } + Spacer(modifier = Modifier.weight(1f)) IconButton( enabled = actionsEnabled, onClick = { @@ -293,21 +397,8 @@ private fun MediaViewerTopBar( ) } } - if (canShare) { - IconButton( - enabled = actionsEnabled, - onClick = { - eventSink(MediaViewerEvents.Share) - }, - ) { - Icon( - imageVector = CompoundIcons.ShareAndroid(), - contentDescription = stringResource(id = CommonStrings.action_share) - ) - } - } } - ) + } } @Composable diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactoryTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactoryTest.kt index 5729c5310d..c341f6e751 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactoryTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactoryTest.kt @@ -11,6 +11,7 @@ import com.google.common.truth.Truth.assertThat import io.element.android.libraries.androidutils.filesize.FakeFileSizeFormatter import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.matrix.api.media.MediaFile +import io.element.android.libraries.matrix.test.A_USER_NAME import io.element.android.libraries.matrix.test.media.FakeMediaFile import io.element.android.libraries.mediaviewer.api.MediaInfo import io.element.android.libraries.mediaviewer.api.anImageMediaInfo @@ -25,7 +26,10 @@ class AndroidLocalMediaFactoryTest { @Test fun `test AndroidLocalMediaFactory`() { val sut = createAndroidLocalMediaFactory() - val result = sut.createFromMediaFile(aMediaFile(), anImageMediaInfo()) + val result = sut.createFromMediaFile(aMediaFile(), anImageMediaInfo( + senderName = A_USER_NAME, + dateSent = "12:34", + )) assertThat(result.uri.toString()).endsWith("aPath") assertThat(result.info).isEqualTo( MediaInfo( @@ -34,6 +38,8 @@ class AndroidLocalMediaFactoryTest { mimeType = MimeTypes.Jpeg, formattedFileSize = "4MB", fileExtension = "jpg", + senderName = A_USER_NAME, + dateSent = "12:34" ) ) } diff --git a/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaFactory.kt b/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaFactory.kt index df85f2d53d..a0f36c6f0f 100644 --- a/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaFactory.kt +++ b/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaFactory.kt @@ -36,7 +36,9 @@ class FakeLocalMediaFactory( caption = null, mimeType = mimeType ?: fallbackMimeType, formattedFileSize = formattedFileSize ?: fallbackFileSize, - fileExtension = fileExtensionExtractor.extractFromName(safeName) + fileExtension = fileExtensionExtractor.extractFromName(safeName), + senderName = null, + dateSent = null ) return aLocalMedia(uri, mediaInfo) } From 1f61be8f86ddad71bd99755b8304f1f0a46e37c2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 2 Dec 2024 17:12:18 +0100 Subject: [PATCH 02/13] Improve preview. --- .../libraries/mediaviewer/impl/viewer/MediaViewerView.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 1e3c264d14..0099ffe700 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 @@ -89,7 +89,8 @@ fun MediaViewerView( val snackbarHostState = rememberSnackbarHostState(snackbarMessage = state.snackbarMessage) var showOverlay by remember { mutableStateOf(true) } - var bottomPaddingInPixels by remember { mutableIntStateOf(0) } + val defaultBottomPaddingInPixels = if (LocalInspectionMode.current) 303 else 0 + var bottomPaddingInPixels by remember { mutableIntStateOf(defaultBottomPaddingInPixels) } BackHandler { onBackClick() } Scaffold( modifier, From 3f9621e4af0e2912cd587c0f74b208cd3f9c8a1e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 2 Dec 2024 15:47:54 +0100 Subject: [PATCH 03/13] Video player: Iterate on Play/Pause button --- .../local/video/MediaPlayerControllerView.kt | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaPlayerControllerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaPlayerControllerView.kt index 9cee07728f..f0c6040412 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaPlayerControllerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaPlayerControllerView.kt @@ -11,10 +11,13 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.widthIn +import androidx.compose.foundation.shape.CircleShape import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableFloatStateOf @@ -63,8 +66,21 @@ fun MediaPlayerControllerView( .widthIn(max = 480.dp), verticalAlignment = Alignment.CenterVertically, ) { - IconButton( - onClick = onTogglePlay, + val bgColor = if (state.isPlaying) { + ElementTheme.colors.bgCanvasDefault + } else { + ElementTheme.colors.textPrimary + } + Box( + modifier = Modifier + .clickable { onTogglePlay() } + .size(36.dp) + .background( + color = bgColor, + shape = CircleShape, + ) + .padding(8.dp), + contentAlignment = Alignment.Center, ) { if (state.isPlaying) { Icon( @@ -75,7 +91,7 @@ fun MediaPlayerControllerView( } else { Icon( imageVector = CompoundIcons.PlaySolid(), - tint = ElementTheme.colors.iconPrimary, + tint = ElementTheme.colors.iconOnSolidPrimary, contentDescription = stringResource(CommonStrings.a11y_play) ) } From 3c5454f0b7ad99bd543055eef8e818f282a3ca2b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 2 Dec 2024 17:18:10 +0100 Subject: [PATCH 04/13] Add Divider --- .../libraries/mediaviewer/impl/viewer/MediaViewerView.kt | 2 ++ 1 file changed, 2 insertions(+) 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 0099ffe700..a9b43843f5 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 @@ -56,6 +56,7 @@ import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.dialogs.RetryDialog import io.element.android.libraries.designsystem.preview.ElementPreviewDark +import io.element.android.libraries.designsystem.theme.components.HorizontalDivider import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.IconButton import io.element.android.libraries.designsystem.theme.components.Scaffold @@ -336,6 +337,7 @@ private fun MediaViewerBottomBar( onHeightChanged(it.height) }, ) { + HorizontalDivider() if (caption != null) { Text( modifier = Modifier From 89aee0446af28b0d4b6474cabe46af0e1d993634 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 2 Dec 2024 17:38:47 +0100 Subject: [PATCH 05/13] Fix player controls not showing on attachment preview. --- .../attachments/preview/AttachmentsPreviewView.kt | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt index d0a980658d..a91baaad8c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/attachments/preview/AttachmentsPreviewView.kt @@ -11,12 +11,14 @@ import androidx.activity.compose.BackHandler import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.padding import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -81,8 +83,9 @@ fun AttachmentsPreviewView( title = {}, ) } - ) { + ) { paddingValues -> AttachmentPreviewContent( + modifier = Modifier.padding(paddingValues), state = state, localMediaRenderer = localMediaRenderer, onSendClick = ::postSendAttachment, @@ -134,14 +137,16 @@ private fun AttachmentPreviewContent( state: AttachmentsPreviewState, localMediaRenderer: LocalMediaRenderer, onSendClick: () -> Unit, + modifier: Modifier = Modifier, ) { - Box( - modifier = Modifier + Column( + modifier = modifier .fillMaxSize() .navigationBarsPadding(), ) { Box( - modifier = Modifier.fillMaxSize(), + modifier = Modifier + .weight(1f), contentAlignment = Alignment.Center ) { when (val attachment = state.attachment) { @@ -157,7 +162,6 @@ private fun AttachmentPreviewContent( .fillMaxWidth() .background(ElementTheme.colors.bgCanvasDefault) .height(IntrinsicSize.Min) - .align(Alignment.BottomCenter) .imePadding(), ) } From dc34a861b41455a3116ae41178a0877349b07325 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Mon, 2 Dec 2024 16:51:17 +0000 Subject: [PATCH 06/13] Update screenshots --- ...messages.impl.attachments.preview_AttachmentsView_0_en.png | 4 ++-- ...messages.impl.attachments.preview_AttachmentsView_1_en.png | 4 ++-- ...messages.impl.attachments.preview_AttachmentsView_2_en.png | 4 ++-- ...messages.impl.attachments.preview_AttachmentsView_3_en.png | 4 ++-- ...messages.impl.attachments.preview_AttachmentsView_4_en.png | 4 ++-- ...messages.impl.attachments.preview_AttachmentsView_5_en.png | 4 ++-- ...er.impl.local.video_MediaPlayerControllerView_Day_0_en.png | 4 ++-- ...er.impl.local.video_MediaPlayerControllerView_Day_1_en.png | 4 ++-- ....impl.local.video_MediaPlayerControllerView_Night_0_en.png | 4 ++-- ....impl.local.video_MediaPlayerControllerView_Night_1_en.png | 4 ++-- ...s.mediaviewer.impl.local.video_MediaVideoView_Day_0_en.png | 4 ++-- ...mediaviewer.impl.local.video_MediaVideoView_Night_0_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_0_en.png | 4 ++-- ...ibraries.mediaviewer.impl.viewer_MediaViewerView_10_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_1_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_2_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_3_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_5_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png | 4 ++-- ...libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png | 4 ++-- 23 files changed, 46 insertions(+), 46 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_0_en.png index d56a5de7d3..71d0679471 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7839db8763b29e38ad67380e09101e48fd3a650080967fb5e51a8bf6411d0427 -size 397423 +oid sha256:17aa655ef22beec5cef50f5d44cb2ecd8ad3a1979bc072a33079a49a8c4495c5 +size 397284 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_1_en.png index fb0ca03ea3..9df61f791e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2c40163401ccd77a79d314bd373bb09d9b9bd0bd8d0afe281792c19d6fd593d3 -size 51465 +oid sha256:8a0e722772be6b9d38c5f0ef3198502ca6e6ebb2599e3a4ebb4cc95cde907095 +size 52012 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_2_en.png index 8c6edbaa98..40926d90b9 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1cba25287c6d2beee594937c3139b3800630379e1b5a552c5cca886f8646bbfe -size 51429 +oid sha256:aa4cae0da657162117538b6839032ebf467542a043f18e308eeaf5ae28ca14e8 +size 51984 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_3_en.png index 350eb73178..63c6848197 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b4f33aa3545c29c25b3c40e6de90772e4e1f0685095429bdbcc4216e9020161c -size 89038 +oid sha256:df6fc9bcb3636549fdfeacb4c9e19cc3c699b7519558bd14f409e7b0c6a84d80 +size 89846 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_4_en.png index 6920a089ef..a31bc036b5 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:507c7dffae1aabfa687174f1f964e2c40b004183b6bc3a70b56d764e0d308b47 -size 392923 +oid sha256:aedd5d3a01457b8ed06b16cd63d08f24ae34568e2b912b82fb892b154c94e6df +size 392780 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_5_en.png index d56a5de7d3..71d0679471 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_AttachmentsView_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7839db8763b29e38ad67380e09101e48fd3a650080967fb5e51a8bf6411d0427 -size 397423 +oid sha256:17aa655ef22beec5cef50f5d44cb2ecd8ad3a1979bc072a33079a49a8c4495c5 +size 397284 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Day_0_en.png index 5a9251549c..93d2782dbb 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e7a7ea1da7e7602cc53cc162c4a685516a7a46ca148eafca6e19a5748630bda5 -size 7036 +oid sha256:333a21a41a7d5f8d47946648a7381dadeccf213a1176696b3512c08ae929d4d6 +size 7819 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Day_1_en.png index 3a2eb1a103..a40e83dc48 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bc35254c6962b5b113a2c25c4c9dd0c94449521152ffd73f41a0c36429fabbb0 -size 7258 +oid sha256:cba8f49caf65856569266a561206437840a43da2d41ed5f08321ecda99204329 +size 8236 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Night_0_en.png index 0877436913..d6bb46d5c2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9f69e358ddd7e00f7301598f5dd235a2f5b9077f8926c2bfa3a4bca1168900f0 -size 7173 +oid sha256:773785bb234c0719c0f27ee91a970c63d7f971518dc0c83298a4b6adb9acc4cf +size 8066 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Night_1_en.png index bc5633f7b6..64ec4ae5d4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaPlayerControllerView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b096093e04eb187fce0a85496c8a5b251afe0d0bccd977abcfb4d1e3dbe32a20 -size 7436 +oid sha256:5424e7ce4a5259aab297a7911741352f0fba01e5fdac972768441db9edf41171 +size 7675 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en.png index ec685d363a..6ab81fd4de 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3b7160dc01dd4704bb07a8c91858bef0d4e99c0f55ca1d7dbdc3e22546a25125 -size 12210 +oid sha256:267d4be8b727a0ecb5af1e5f1e69adfd68f50f32f1de78f4f9fde60f635244b5 +size 13045 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en.png index df1ea796c1..48a87ab6ae 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2591b742c64d3d058d4638e5014080f8b3eb13eba3a73951d71dfdc60e7676d9 -size 12455 +oid sha256:412476e819f688b5314651fd3d59439fc0e4f53ee777e3a070b82fd19d51700e +size 13272 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_0_en.png index c6d641ba08..ae44f16e97 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a6fe771fa6492768239d0caf7a9c10613efb95ff9c2c1b786ee0a6974392af9f -size 389635 +oid sha256:9df1a0ff2b3aaab2d1a346cb134b560d65c462286575ffc6124099529562eac1 +size 389594 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_10_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_10_en.png index 6a81f3f129..347f2dd6c2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_10_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b286342ff4d46637beac1f980294f77b3e2eb6824d56448cdbdce7b41c911ab -size 388612 +oid sha256:4fde3cef34d23c894ae480a1b4c961065f244d845584f8607c4bb21e0a7e5f10 +size 388615 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_1_en.png index 909f84c081..a9ae9d7999 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b023a77242de9cab647e87b18edcd86a48a7843aa8fa51c84b443e3e8b41bcb -size 389669 +oid sha256:cf07ed00618c0552205b1e726050382369041bb7f2d9742b754a5652eca48265 +size 389631 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_2_en.png index fb24aa81f3..173f440a84 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:75ff0cd0cfe594a217d2b58b48c2bb4aedad692a270c2cee8aa3d4bdf6758e1e -size 94797 +oid sha256:143285221dd5a1e714a9897293f13c45ca567635e60350738033b315f44f742a +size 94735 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_3_en.png index 3b71589b75..a63c5a2230 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0dc5fdbd7d0b3980ad19bf74640067e8bb294def913e3d13d7bc4ad9c822382d -size 389921 +oid sha256:a4e1b6a7a3dcc1627aec1767ac8edac95bec483ebdc98d71d65342084e08a4dc +size 396792 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png index d5d6d31f12..585ab58d5e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:05794effa4c47e3d2b68892e613f18a55c96789a4e65a182dd0bf2ca0c812d44 -size 14474 +oid sha256:6c3c2b7b1d64387ec1109ab21304df50de5bd4fac0317c27a2799e7405da3843 +size 22219 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_5_en.png index b56bd6454a..94ba7bede2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e6113747e1677c2f28c2a109bc2c7075a753917068c1bbc3a46d5bdef4db4e23 -size 5756 +oid sha256:364fce9e921a21dcaae9ef1d7c98efe47c4c9118d23958550ee9eafaf202e2fa +size 5751 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png index 4cf13a8381..72bdd87b18 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f5a6ec7984ceab5acf44431a9bff89c29c9ac27c95804d29b800124addd6e910 -size 14800 +oid sha256:769a00d9e84cb2da43d790158f35e66bc5ed6538fdcb7f5e316f5de13d9bd9ad +size 14768 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png index 27b6fb0c1b..7658ec5375 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d03b94e2b502b9857b9b4c2527df86d1aa0a194abed794cbe601ec4172422dcc -size 14987 +oid sha256:bf1804b21f3d383c94e28714746ac61987643c8ec0480d2850b19eb01991aa4e +size 15043 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png index f4d2b37db6..f927629007 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:56b9d11058f06732364668a5833f52fa4e62541fa8ee48f13996ae0a11e11100 -size 13609 +oid sha256:ec58fa08f3c160e1b7d462b580f79b1c05a5644b9f807a79cfeebbeea417ed10 +size 13502 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png index b0693b38c5..4394560d46 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:25c1e3cb51b13bb65b281180862ac8fb6faa1e8bd0ce26d8d0e07321c03c116c -size 13742 +oid sha256:689081427ece8bc009266a50b9d2a80def581f51f00bf65b35d295b0ea7dcab3 +size 13736 From 70faf229cb9fa97bfb3679f730619e931dbe9629 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 2 Dec 2024 18:09:29 +0100 Subject: [PATCH 07/13] Fix modifier issue. --- .../libraries/mediaviewer/impl/viewer/MediaViewerView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 a9b43843f5..96d513458d 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 @@ -350,7 +350,7 @@ private fun MediaViewerBottomBar( ) } Row( - modifier = modifier + modifier = Modifier .fillMaxWidth() .padding(start = 8.dp, end = 8.dp, bottom = 8.dp), verticalAlignment = Alignment.CenterVertically, From 92975e83b650f52b921d2731301ab28f29a8d9d0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 3 Dec 2024 09:26:03 +0100 Subject: [PATCH 08/13] Fix detekt issues. --- .../impl/local/video/MediaPlayerControllerView.kt | 4 +++- .../libraries/mediaviewer/impl/viewer/MediaViewerView.kt | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaPlayerControllerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaPlayerControllerView.kt index f0c6040412..2a5757aa94 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaPlayerControllerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/video/MediaPlayerControllerView.kt @@ -25,6 +25,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign @@ -73,12 +74,13 @@ fun MediaPlayerControllerView( } Box( modifier = Modifier - .clickable { onTogglePlay() } .size(36.dp) .background( color = bgColor, shape = CircleShape, ) + .clip(CircleShape) + .clickable { onTogglePlay() } .padding(8.dp), contentAlignment = Alignment.Center, ) { 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 96d513458d..cdcc6f9fb2 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 @@ -129,7 +129,7 @@ fun MediaViewerView( canShare = state.canShare, mimeType = state.mediaInfo.mimeType, caption = state.mediaInfo.caption, - onHeightChanged = { bottomPaddingInPixels = it }, + onHeightChange = { bottomPaddingInPixels = it }, eventSink = state.eventSink ) } @@ -325,7 +325,7 @@ private fun MediaViewerBottomBar( canShare: Boolean, mimeType: String, caption: String?, - onHeightChanged: (Int) -> Unit, + onHeightChange: (Int) -> Unit, eventSink: (MediaViewerEvents) -> Unit, modifier: Modifier = Modifier, ) { @@ -334,7 +334,7 @@ private fun MediaViewerBottomBar( .fillMaxWidth() .background(Color(0x99101317)) .onSizeChanged { - onHeightChanged(it.height) + onHeightChange(it.height) }, ) { HorizontalDivider() From a21bd16af605fcef8118db7994dbb1b7f6108837 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 3 Dec 2024 09:42:13 +0100 Subject: [PATCH 09/13] Move more fields to TimelineItemEventContentWithAttachment --- .../features/messages/impl/MessagesFlowNode.kt | 4 ++-- .../event/TimelineItemContentMessageFactory.kt | 6 ++++-- .../model/event/TimelineItemAudioContent.kt | 8 ++++---- .../model/event/TimelineItemEventContent.kt | 5 +++++ .../model/event/TimelineItemFileContent.kt | 8 ++++---- .../event/TimelineItemFileContentProvider.kt | 2 +- .../model/event/TimelineItemImageContent.kt | 8 ++++---- .../model/event/TimelineItemStickerContent.kt | 8 ++++---- .../model/event/TimelineItemVideoContent.kt | 8 ++++---- .../event/TimelineItemVideoContentProvider.kt | 2 +- .../model/event/TimelineItemVoiceContent.kt | 6 ++++-- .../event/TimelineItemVoiceContentProvider.kt | 2 ++ .../messages/impl/MessagesPresenterTest.kt | 4 ++-- .../TimelineItemContentMessageFactoryTest.kt | 16 ++++++++++------ 14 files changed, 51 insertions(+), 36 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt index e80f99a67c..53500cfd35 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt @@ -381,7 +381,7 @@ class MessagesFlowNode @AssistedInject constructor( senderName = event.safeSenderName, dateSent = event.sentTime, ), - mediaSource = event.content.videoSource, + mediaSource = event.content.mediaSource, thumbnailSource = event.content.thumbnailSource, ) overlay.show(navTarget) @@ -398,7 +398,7 @@ class MessagesFlowNode @AssistedInject constructor( senderName = event.safeSenderName, dateSent = event.sentTime, ), - mediaSource = event.content.fileSource, + mediaSource = event.content.mediaSource, thumbnailSource = event.content.thumbnailSource, ) overlay.show(navTarget) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt index 867cb694db..c2515560f5 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt @@ -147,7 +147,7 @@ class TimelineItemContentMessageFactory @Inject constructor( formattedCaption = parseHtml(messageType.formattedCaption) ?: messageType.caption?.withLinks(), isEdited = content.isEdited, thumbnailSource = messageType.info?.thumbnailSource, - videoSource = messageType.source, + mediaSource = messageType.source, mimeType = messageType.info?.mimetype ?: MimeTypes.OctetStream, width = messageType.info?.width?.toInt(), height = messageType.info?.height?.toInt(), @@ -186,6 +186,8 @@ class TimelineItemContentMessageFactory @Inject constructor( duration = messageType.info?.duration ?: Duration.ZERO, mimeType = messageType.info?.mimetype ?: MimeTypes.OctetStream, waveform = messageType.details?.waveform?.toImmutableList() ?: persistentListOf(), + formattedFileSize = fileSizeFormatter.format(messageType.info?.size ?: 0), + fileExtension = fileExtensionExtractor.extractFromName(messageType.filename) ) } false -> { @@ -211,7 +213,7 @@ class TimelineItemContentMessageFactory @Inject constructor( formattedCaption = parseHtml(messageType.formattedCaption) ?: messageType.caption?.withLinks(), isEdited = content.isEdited, thumbnailSource = messageType.info?.thumbnailSource, - fileSource = messageType.source, + mediaSource = messageType.source, mimeType = messageType.info?.mimetype ?: MimeTypes.fromFileExtension(fileExtension), formattedFileSize = fileSizeFormatter.format(messageType.info?.size ?: 0), fileExtension = fileExtension diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemAudioContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemAudioContent.kt index 46176cc474..a3b2061b92 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemAudioContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemAudioContent.kt @@ -17,10 +17,10 @@ data class TimelineItemAudioContent( override val formattedCaption: CharSequence?, override val isEdited: Boolean, val duration: Duration, - val mediaSource: MediaSource, - val mimeType: String, - val formattedFileSize: String, - val fileExtension: String, + override val mediaSource: MediaSource, + override val mimeType: String, + override val formattedFileSize: String, + override val fileExtension: String, ) : TimelineItemEventContentWithAttachment { val fileExtensionAndSize = formatFileExtensionAndSize( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt index 62c55c22ef..6c823462bf 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt @@ -8,6 +8,7 @@ package io.element.android.features.messages.impl.timeline.model.event import androidx.compose.runtime.Immutable +import io.element.android.libraries.matrix.api.media.MediaSource @Immutable sealed interface TimelineItemEventContent { @@ -26,6 +27,10 @@ sealed interface TimelineItemEventContentWithAttachment : val filename: String val caption: String? val formattedCaption: CharSequence? + val mediaSource: MediaSource + val mimeType: String + val formattedFileSize: String + val fileExtension: String val bestDescription: String get() = caption ?: filename diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemFileContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemFileContent.kt index 3f1d8fe041..286411c511 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemFileContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemFileContent.kt @@ -15,11 +15,11 @@ data class TimelineItemFileContent( override val caption: String?, override val formattedCaption: CharSequence?, override val isEdited: Boolean, - val fileSource: MediaSource, + override val mediaSource: MediaSource, val thumbnailSource: MediaSource?, - val formattedFileSize: String, - val fileExtension: String, - val mimeType: String, + override val formattedFileSize: String, + override val fileExtension: String, + override val mimeType: String, ) : TimelineItemEventContentWithAttachment { override val type: String = "TimelineItemFileContent" diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemFileContentProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemFileContentProvider.kt index 409e26079e..b8f28c741a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemFileContentProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemFileContentProvider.kt @@ -31,7 +31,7 @@ fun aTimelineItemFileContent( formattedCaption = null, isEdited = false, thumbnailSource = null, - fileSource = MediaSource(url = ""), + mediaSource = MediaSource(url = ""), mimeType = MimeTypes.Pdf, formattedFileSize = "100kB", fileExtension = "pdf" diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemImageContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemImageContent.kt index 78323166b4..80b055a5a6 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemImageContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemImageContent.kt @@ -18,11 +18,11 @@ data class TimelineItemImageContent( override val caption: String?, override val formattedCaption: CharSequence?, override val isEdited: Boolean, - val mediaSource: MediaSource, + override val mediaSource: MediaSource, val thumbnailSource: MediaSource?, - val formattedFileSize: String, - val fileExtension: String, - val mimeType: String, + override val formattedFileSize: String, + override val fileExtension: String, + override val mimeType: String, val blurhash: String?, val width: Int?, val height: Int?, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemStickerContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemStickerContent.kt index ebaeb53b4b..ebf25d7e95 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemStickerContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemStickerContent.kt @@ -14,11 +14,11 @@ data class TimelineItemStickerContent( override val caption: String?, override val formattedCaption: CharSequence?, override val isEdited: Boolean, - val mediaSource: MediaSource, + override val mediaSource: MediaSource, val thumbnailSource: MediaSource?, - val formattedFileSize: String, - val fileExtension: String, - val mimeType: String, + override val formattedFileSize: String, + override val fileExtension: String, + override val mimeType: String, val blurhash: String?, val width: Int?, val height: Int?, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemVideoContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemVideoContent.kt index caee06ef64..74406aaf37 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemVideoContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemVideoContent.kt @@ -16,7 +16,7 @@ data class TimelineItemVideoContent( override val formattedCaption: CharSequence?, override val isEdited: Boolean, val duration: Duration, - val videoSource: MediaSource, + override val mediaSource: MediaSource, val thumbnailSource: MediaSource?, val aspectRatio: Float?, val blurHash: String?, @@ -24,9 +24,9 @@ data class TimelineItemVideoContent( val width: Int?, val thumbnailWidth: Int?, val thumbnailHeight: Int?, - val mimeType: String, - val formattedFileSize: String, - val fileExtension: String, + override val mimeType: String, + override val formattedFileSize: String, + override val fileExtension: String, ) : TimelineItemEventContentWithAttachment { override val type: String = "TimelineItemImageContent" diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemVideoContentProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemVideoContentProvider.kt index 1ed05fa606..477c00d808 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemVideoContentProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemVideoContentProvider.kt @@ -35,7 +35,7 @@ fun aTimelineItemVideoContent( blurHash = blurhash, aspectRatio = aspectRatio, duration = 100.milliseconds, - videoSource = MediaSource(""), + mediaSource = MediaSource(""), width = 150, height = 300, thumbnailWidth = 150, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemVoiceContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemVoiceContent.kt index 21b6696ffe..ad3908166a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemVoiceContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemVoiceContent.kt @@ -19,8 +19,10 @@ data class TimelineItemVoiceContent( override val formattedCaption: CharSequence?, override val isEdited: Boolean, val duration: Duration, - val mediaSource: MediaSource, - val mimeType: String, + override val mediaSource: MediaSource, + override val formattedFileSize: String, + override val fileExtension: String, + override val mimeType: String, val waveform: ImmutableList, ) : TimelineItemEventContentWithAttachment { override val type: String = "TimelineItemAudioContent" diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemVoiceContentProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemVoiceContentProvider.kt index bd7308d970..0c3fd246ca 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemVoiceContentProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemVoiceContentProvider.kt @@ -53,4 +53,6 @@ fun aTimelineItemVoiceContent( mediaSource = mediaSource, mimeType = mimeType, waveform = waveform.toPersistentList(), + formattedFileSize = "1.0 MB", + fileExtension = "ogg", ) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt index 541034bc57..8cb7464a9a 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt @@ -371,7 +371,7 @@ class MessagesPresenterTest { formattedCaption = null, isEdited = false, duration = 10.milliseconds, - videoSource = MediaSource(AN_AVATAR_URL), + mediaSource = MediaSource(AN_AVATAR_URL), thumbnailSource = MediaSource(AN_AVATAR_URL), mimeType = MimeTypes.Mp4, blurHash = null, @@ -413,7 +413,7 @@ class MessagesPresenterTest { caption = null, isEdited = false, formattedCaption = null, - fileSource = MediaSource(AN_AVATAR_URL), + mediaSource = MediaSource(AN_AVATAR_URL), thumbnailSource = MediaSource(AN_AVATAR_URL), formattedFileSize = "10 MB", mimeType = MimeTypes.Pdf, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt index b771141ce3..751186554c 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt @@ -239,7 +239,7 @@ class TimelineItemContentMessageFactoryTest { formattedCaption = null, isEdited = false, duration = Duration.ZERO, - videoSource = MediaSource(url = "url", json = null), + mediaSource = MediaSource(url = "url", json = null), thumbnailSource = null, aspectRatio = null, blurHash = null, @@ -291,7 +291,7 @@ class TimelineItemContentMessageFactoryTest { formattedCaption = SpannedString("formatted"), isEdited = true, duration = 1.minutes, - videoSource = MediaSource(url = "url", json = null), + mediaSource = MediaSource(url = "url", json = null), thumbnailSource = MediaSource("url_thumbnail"), aspectRatio = 3f, blurHash = A_BLUR_HASH, @@ -380,7 +380,9 @@ class TimelineItemContentMessageFactoryTest { duration = Duration.ZERO, mediaSource = MediaSource(url = "url", json = null), mimeType = MimeTypes.OctetStream, - waveform = emptyList().toImmutableList() + waveform = emptyList().toImmutableList(), + fileExtension = "", + formattedFileSize = "", ) assertThat(result).isEqualTo(expected) } @@ -419,7 +421,9 @@ class TimelineItemContentMessageFactoryTest { duration = 1.minutes, mediaSource = MediaSource(url = "url", json = null), mimeType = MimeTypes.Ogg, - waveform = persistentListOf(1f, 2f) + waveform = persistentListOf(1f, 2f), + fileExtension = "", + formattedFileSize = "", ) assertThat(result).isEqualTo(expected) } @@ -571,7 +575,7 @@ class TimelineItemContentMessageFactoryTest { caption = null, formattedCaption = null, isEdited = false, - fileSource = MediaSource(url = "url", json = null), + mediaSource = MediaSource(url = "url", json = null), thumbnailSource = null, formattedFileSize = "0 Bytes", fileExtension = "", @@ -612,7 +616,7 @@ class TimelineItemContentMessageFactoryTest { caption = null, formattedCaption = null, isEdited = true, - fileSource = MediaSource(url = "url", json = null), + mediaSource = MediaSource(url = "url", json = null), thumbnailSource = MediaSource("url_thumbnail"), formattedFileSize = "123 Bytes", fileExtension = "pdf", From dbb062f230db3499c8f70e6a90b45559e2de1815 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 3 Dec 2024 09:59:18 +0100 Subject: [PATCH 10/13] Create method buildMediaViewerNavTarget --- .../messages/impl/MessagesFlowNode.kt | 87 ++++++++----------- 1 file changed, 37 insertions(+), 50 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt index 53500cfd35..f6400f579b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt @@ -40,6 +40,7 @@ import io.element.android.features.messages.impl.timeline.TimelineController import io.element.android.features.messages.impl.timeline.debug.EventDebugInfoNode import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContent +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContentWithAttachment import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent @@ -331,16 +332,9 @@ class MessagesFlowNode @AssistedInject constructor( private fun processEventClick(event: TimelineItem.Event): Boolean { return when (event.content) { is TimelineItemImageContent -> { - val navTarget = NavTarget.MediaViewer( - mediaInfo = MediaInfo( - filename = event.content.filename, - caption = event.content.caption, - mimeType = event.content.mimeType, - formattedFileSize = event.content.formattedFileSize, - fileExtension = event.content.fileExtension, - senderName = event.safeSenderName, - dateSent = event.sentTime, - ), + val navTarget = buildMediaViewerNavTarget( + event = event, + content = event.content, mediaSource = event.content.mediaSource, thumbnailSource = event.content.thumbnailSource, ) @@ -351,16 +345,9 @@ class MessagesFlowNode @AssistedInject constructor( /* Sticker may have an empty url and no thumbnail if encrypted on certain bridges */ if (event.content.preferredMediaSource != null) { - val navTarget = NavTarget.MediaViewer( - mediaInfo = MediaInfo( - filename = event.content.filename, - caption = event.content.caption, - mimeType = event.content.mimeType, - formattedFileSize = event.content.formattedFileSize, - fileExtension = event.content.fileExtension, - senderName = event.safeSenderName, - dateSent = event.sentTime, - ), + val navTarget = buildMediaViewerNavTarget( + event = event, + content = event.content, mediaSource = event.content.preferredMediaSource, thumbnailSource = event.content.thumbnailSource, ) @@ -371,16 +358,9 @@ class MessagesFlowNode @AssistedInject constructor( } } is TimelineItemVideoContent -> { - val navTarget = NavTarget.MediaViewer( - mediaInfo = MediaInfo( - filename = event.content.filename, - caption = event.content.caption, - mimeType = event.content.mimeType, - formattedFileSize = event.content.formattedFileSize, - fileExtension = event.content.fileExtension, - senderName = event.safeSenderName, - dateSent = event.sentTime, - ), + val navTarget = buildMediaViewerNavTarget( + event = event, + content = event.content, mediaSource = event.content.mediaSource, thumbnailSource = event.content.thumbnailSource, ) @@ -388,16 +368,9 @@ class MessagesFlowNode @AssistedInject constructor( true } is TimelineItemFileContent -> { - val navTarget = NavTarget.MediaViewer( - mediaInfo = MediaInfo( - filename = event.content.filename, - caption = event.content.caption, - mimeType = event.content.mimeType, - formattedFileSize = event.content.formattedFileSize, - fileExtension = event.content.fileExtension, - senderName = event.safeSenderName, - dateSent = event.sentTime, - ), + val navTarget = buildMediaViewerNavTarget( + event = event, + content = event.content, mediaSource = event.content.mediaSource, thumbnailSource = event.content.thumbnailSource, ) @@ -405,16 +378,9 @@ class MessagesFlowNode @AssistedInject constructor( true } is TimelineItemAudioContent -> { - val navTarget = NavTarget.MediaViewer( - mediaInfo = MediaInfo( - filename = event.content.filename, - caption = event.content.caption, - mimeType = event.content.mimeType, - formattedFileSize = event.content.formattedFileSize, - fileExtension = event.content.fileExtension, - senderName = event.safeSenderName, - dateSent = event.sentTime, - ), + val navTarget = buildMediaViewerNavTarget( + event = event, + content = event.content, mediaSource = event.content.mediaSource, thumbnailSource = null, ) @@ -433,6 +399,27 @@ class MessagesFlowNode @AssistedInject constructor( } } + private fun buildMediaViewerNavTarget( + event: TimelineItem.Event, + content: TimelineItemEventContentWithAttachment, + mediaSource: MediaSource, + thumbnailSource: MediaSource?, + ): NavTarget { + return NavTarget.MediaViewer( + mediaInfo = MediaInfo( + filename = content.filename, + caption = content.caption, + mimeType = content.mimeType, + formattedFileSize = content.formattedFileSize, + fileExtension = content.fileExtension, + senderName = event.safeSenderName, + dateSent = event.sentTime, + ), + mediaSource = mediaSource, + thumbnailSource = thumbnailSource, + ) + } + @Composable override fun View(modifier: Modifier) { mentionSpanTheme.updateStyles(currentUserId = room.sessionId) From 04edf84783c0399c1f91ff1be80a0cd154a8192c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 3 Dec 2024 10:17:28 +0100 Subject: [PATCH 11/13] Fix navigation issue. LocationViewer should not use the Appyx overlay. --- .../element/android/features/messages/impl/MessagesFlowNode.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt index f6400f579b..3d014fd024 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt @@ -392,7 +392,7 @@ class MessagesFlowNode @AssistedInject constructor( location = event.content.location, description = event.content.description, ) - overlay.show(navTarget) + backstack.push(navTarget) true } else -> false From 0574c14421a58314eb227ce0bb01455678c7f72f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 3 Dec 2024 10:21:06 +0100 Subject: [PATCH 12/13] Simplify code. --- .../messages/impl/MessagesFlowNode.kt | 39 +++++++++---------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt index 3d014fd024..8cbb7b6d74 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt @@ -330,68 +330,65 @@ class MessagesFlowNode @AssistedInject constructor( } private fun processEventClick(event: TimelineItem.Event): Boolean { - return when (event.content) { + val navTarget = when (event.content) { is TimelineItemImageContent -> { - val navTarget = buildMediaViewerNavTarget( + buildMediaViewerNavTarget( event = event, content = event.content, mediaSource = event.content.mediaSource, thumbnailSource = event.content.thumbnailSource, ) - overlay.show(navTarget) - true } is TimelineItemStickerContent -> { /* Sticker may have an empty url and no thumbnail if encrypted on certain bridges */ - if (event.content.preferredMediaSource != null) { - val navTarget = buildMediaViewerNavTarget( + event.content.preferredMediaSource?.let { preferredMediaSource -> + buildMediaViewerNavTarget( event = event, content = event.content, - mediaSource = event.content.preferredMediaSource, + mediaSource = preferredMediaSource, thumbnailSource = event.content.thumbnailSource, ) - overlay.show(navTarget) - true - } else { - false } } is TimelineItemVideoContent -> { - val navTarget = buildMediaViewerNavTarget( + buildMediaViewerNavTarget( event = event, content = event.content, mediaSource = event.content.mediaSource, thumbnailSource = event.content.thumbnailSource, ) - overlay.show(navTarget) - true } is TimelineItemFileContent -> { - val navTarget = buildMediaViewerNavTarget( + buildMediaViewerNavTarget( event = event, content = event.content, mediaSource = event.content.mediaSource, thumbnailSource = event.content.thumbnailSource, ) - overlay.show(navTarget) - true } is TimelineItemAudioContent -> { - val navTarget = buildMediaViewerNavTarget( + buildMediaViewerNavTarget( event = event, content = event.content, mediaSource = event.content.mediaSource, thumbnailSource = null, ) - overlay.show(navTarget) - true } is TimelineItemLocationContent -> { - val navTarget = NavTarget.LocationViewer( + NavTarget.LocationViewer( location = event.content.location, description = event.content.description, ) + } + else -> null + } + return when (navTarget) { + is NavTarget.MediaViewer -> { + overlay.show(navTarget) + true + } + is NavTarget.LocationViewer -> { backstack.push(navTarget) true } From 5e927398b143ba519482735070f77491909ba1f2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 3 Dec 2024 11:37:19 +0100 Subject: [PATCH 13/13] Fix tests. --- .../event/TimelineItemContentMessageFactoryTest.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt index 751186554c..fb853f4472 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt @@ -382,7 +382,7 @@ class TimelineItemContentMessageFactoryTest { mimeType = MimeTypes.OctetStream, waveform = emptyList().toImmutableList(), fileExtension = "", - formattedFileSize = "", + formattedFileSize = "0 Bytes", ) assertThat(result).isEqualTo(expected) } @@ -422,8 +422,8 @@ class TimelineItemContentMessageFactoryTest { mediaSource = MediaSource(url = "url", json = null), mimeType = MimeTypes.Ogg, waveform = persistentListOf(1f, 2f), - fileExtension = "", - formattedFileSize = "", + fileExtension = "ogg", + formattedFileSize = "123 Bytes", ) assertThat(result).isEqualTo(expected) }