Media: improve a bit the viewers

This commit is contained in:
ganfra 2023-05-24 22:19:18 +02:00
parent fc601acd28
commit 92e19c3dd9
11 changed files with 71 additions and 28 deletions

View file

@ -29,13 +29,12 @@ open class AttachmentsPreviewStateProvider : PreviewParameterProvider<Attachment
anAttachmentsPreviewState(),
anAttachmentsPreviewState(sendActionState = Async.Loading()),
anAttachmentsPreviewState(sendActionState = Async.Failure(RuntimeException())),
// Add other states here
)
}
fun anAttachmentsPreviewState(sendActionState: Async<Unit> = Async.Uninitialized) = AttachmentsPreviewState(
attachment = Attachment.Media(
localMedia = LocalMedia("".toUri(), mimeType = MimeTypes.OctetStream),
localMedia = LocalMedia("path".toUri(), MimeTypes.Jpeg, "an image", 1000L),
compressIfPossible = true
),
sendActionState = sendActionState,

View file

@ -79,13 +79,13 @@ fun AttachmentsPreviewView(
onSendClicked = ::postSendAttachment,
onDismiss = onDismiss
)
AttachmentSendStateView(
sendActionState = state.sendActionState,
onRetryClicked = ::postSendAttachment,
onRetryDismissed = ::postClearSendState
)
}
}
AttachmentSendStateView(
sendActionState = state.sendActionState,
onRetryClicked = ::postSendAttachment,
onRetryDismissed = ::postClearSendState
)
}
@Composable
@ -106,7 +106,6 @@ private fun AttachmentSendStateView(
onRetry = onRetryClicked
)
}
else -> Unit
}
}
@ -115,10 +114,11 @@ private fun AttachmentSendStateView(
private fun AttachmentPreviewContent(
attachment: Attachment,
onSendClicked: () -> Unit,
onDismiss: () -> Unit
onDismiss: () -> Unit,
modifier: Modifier = Modifier,
) {
Column(
modifier = Modifier
modifier = modifier
.fillMaxSize()
.padding(top = 24.dp)
) {

View file

@ -20,6 +20,8 @@ import android.content.Context
import android.net.Uri
import androidx.core.net.toUri
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.androidutils.file.getFileName
import io.element.android.libraries.androidutils.file.getFileSize
import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.ApplicationContext
@ -32,13 +34,19 @@ class AndroidLocalMediaFactory @Inject constructor(
) : LocalMediaFactory {
override fun createFromMediaFile(mediaFile: MediaFile, mimeType: String?): LocalMedia {
val resolvedMimeType = mimeType ?: MimeTypes.OctetStream
val uri = mediaFile.path().toUri()
return LocalMedia(uri, resolvedMimeType)
return createFromUri(uri, mimeType)
}
override fun createFromUri(uri: Uri, mimeType: String?): LocalMedia {
val resolvedMimeType = mimeType ?: context.contentResolver.getType(uri) ?: MimeTypes.OctetStream
return LocalMedia(uri, resolvedMimeType)
val fileName = context.getFileName(uri)
val fileSize = context.getFileSize(uri)
return LocalMedia(
uri = uri,
mimeType = resolvedMimeType,
name = fileName,
size = fileSize
)
}
}

View file

@ -25,6 +25,8 @@ import kotlinx.parcelize.Parcelize
data class LocalMedia(
val uri: Uri,
val mimeType: String,
val name: String?,
val size: Long,
) : Parcelable {
/**

View file

@ -19,6 +19,7 @@ package io.element.android.features.messages.impl.media.local
import android.annotation.SuppressLint
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.widget.FrameLayout
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@ -26,6 +27,8 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.Lifecycle
import androidx.media3.common.MediaItem
@ -34,6 +37,7 @@ import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.ui.AspectRatioFrameLayout
import androidx.media3.ui.PlayerView
import io.element.android.libraries.designsystem.R
import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
import me.saket.telephoto.zoomable.ZoomSpec
import me.saket.telephoto.zoomable.coil.ZoomableAsyncImage
@ -64,6 +68,13 @@ private fun MediaImageView(
localMedia: LocalMedia,
modifier: Modifier = Modifier,
) {
if (LocalInspectionMode.current) {
Image(
painter = painterResource(id = R.drawable.sample_background),
modifier = modifier.fillMaxSize(),
contentDescription = null,
)
}
val zoomableState = rememberZoomableState(
zoomSpec = ZoomSpec(maxZoomFactor = 3f)
)

View file

@ -40,7 +40,8 @@ object UriToFileMapper {
}
private fun isApplicable(data: Uri): Boolean {
return data.scheme.let { it == null || it == ContentResolver.SCHEME_FILE } &&
return !isAssetUri(data) &&
data.scheme.let { it == null || it == ContentResolver.SCHEME_FILE } &&
data.path.orEmpty().startsWith('/') && data.firstPathSegment != null
}

View file

@ -16,19 +16,30 @@
package io.element.android.features.messages.impl.media.viewer
import android.net.Uri
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.media3.common.MimeTypes
import io.element.android.features.messages.impl.media.local.LocalMedia
import io.element.android.libraries.architecture.Async
open class MediaViewerStateProvider : PreviewParameterProvider<MediaViewerState> {
override val values: Sequence<MediaViewerState>
get() = sequenceOf(
aMediaViewerState(),
// Add other states here
aMediaViewerState(Async.Loading()),
aMediaViewerState(Async.Failure(IllegalStateException())),
aMediaViewerState(
Async.Success(
LocalMedia(
Uri.EMPTY, MimeTypes.IMAGE_JPEG, "a file", 100L
)
),
)
)
}
fun aMediaViewerState() = MediaViewerState(
fun aMediaViewerState(downloadedMedia: Async<LocalMedia> = Async.Uninitialized) = MediaViewerState(
name = "A media",
downloadedMedia = Async.Uninitialized,
downloadedMedia = downloadedMedia,
eventSink = {}
)

View file

@ -63,9 +63,7 @@ fun MediaViewerView(
when (state.downloadedMedia) {
is Async.Success -> LocalMediaView(state.downloadedMedia.state)
is Async.Failure -> ErrorView(stringResource(id = StringR.string.error_unknown), ::onRetry)
else -> CircularProgressIndicator(
strokeWidth = 2.dp,
)
else -> CircularProgressIndicator()
}
}
}
@ -92,11 +90,6 @@ private fun ErrorView(
}
}
@Preview
@Composable
fun MediaViewerViewLightPreview(@PreviewParameter(MediaViewerStateProvider::class) state: MediaViewerState) =
ElementPreviewLight { ContentToPreview(state) }
@Preview
@Composable
fun MediaViewerViewDarkPreview(@PreviewParameter(MediaViewerStateProvider::class) state: MediaViewerState) =

View file

@ -84,7 +84,7 @@ class AttachmentsPreviewPresenterTest {
}
private fun anAttachmentsPreviewPresenter(
localMedia: LocalMedia = aLocalMedia(mimeType = MimeTypes.IMAGE_JPEG),
localMedia: LocalMedia = aLocalMedia(MimeTypes.IMAGE_JPEG),
room: MatrixRoom = FakeMatrixRoom()
): AttachmentsPreviewPresenter {
return AttachmentsPreviewPresenter(

View file

@ -22,11 +22,15 @@ import io.element.android.features.messages.impl.media.local.LocalMedia
import io.mockk.mockk
fun aLocalMedia(
mimeType: String,
uri: Uri = mockk("localMediaUri"),
mimeType: String
name: String = "a media",
size: Long = 1000,
) = LocalMedia(
uri = uri,
mimeType = mimeType
mimeType = mimeType,
name = name,
size = size,
)
fun aMediaAttachment(localMedia: LocalMedia, compressIfPossible: Boolean = true) = Attachment.Media(

View file

@ -27,6 +27,20 @@ fun Context.getFileName(uri: Uri): String? = when (uri.scheme) {
else -> uri.path?.let(::File)?.name
}
fun Context.getFileSize(uri: Uri): Long {
return when (uri.scheme) {
ContentResolver.SCHEME_CONTENT -> getContentFileSize(uri)
else -> uri.path?.let(::File)?.length()
} ?: 0
}
private fun Context.getContentFileSize(uri: Uri): Long? = runCatching {
contentResolver.query(uri, null, null, null, null)?.use { cursor ->
cursor.moveToFirst()
return@use cursor.getColumnIndexOrThrow(OpenableColumns.SIZE).let(cursor::getLong)
}
}.getOrNull()
private fun Context.getContentFileName(uri: Uri): String? = runCatching {
contentResolver.query(uri, null, null, null, null)?.use { cursor ->
cursor.moveToFirst()