From e3ad4ee06fa8cc6f3877e59121c8b3f5140d228c Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 16 May 2023 11:24:14 +0200 Subject: [PATCH] Media : extract an extension method to mediaupload --- .../textcomposer/MessageComposerPresenter.kt | 48 ++++++------------- .../mediaupload/api/MediaPreProcessor.kt | 3 ++ .../libraries/mediaupload/api/RoomExt.kt | 39 +++++++++++++++ .../mediaupload/MediaPreProcessorImpl.kt | 10 ++-- 4 files changed, 62 insertions(+), 38 deletions(-) create mode 100644 libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/RoomExt.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenter.kt index 9b8dcabdd2..54019b5e8a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/textcomposer/MessageComposerPresenter.kt @@ -43,7 +43,7 @@ import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.mediapickers.api.PickerProvider import io.element.android.libraries.mediaupload.api.MediaPreProcessor import io.element.android.libraries.mediaupload.api.MediaType -import io.element.android.libraries.mediaupload.api.MediaUploadInfo +import io.element.android.libraries.mediaupload.api.sendMedia import io.element.android.libraries.textcomposer.MessageComposerMode import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.CoroutineScope @@ -191,39 +191,21 @@ class MessageComposerPresenter @Inject constructor( mediaType: MediaType, deleteOriginal: Boolean = false ) = launch { - runCatching { - val info = handleMediaPreProcessing(uri, mediaType, deleteOriginal).getOrNull() ?: return@runCatching - when (info) { - is MediaUploadInfo.Image -> { - room.sendImage(info.file, info.thumbnailInfo.file, info.info) + mediaPreProcessor.process(uri, mediaType, deleteOriginal) + .map { info -> + room.sendMedia(info) + } + .onSuccess { + Timber.d("onSuccess sending media") + }.onFailure { failure -> + Timber.e(failure, "onfailure sending media: $failure") + val snackbarMessage = if (failure is MediaPreProcessor.Failure) { + StringR.string.screen_media_upload_preview_error_failed_processing + } else { + StringR.string.screen_media_upload_preview_error_failed_sending } + snackbarDispatcher.post(SnackbarMessage(snackbarMessage)) + } - is MediaUploadInfo.Video -> { - room.sendVideo(info.file, info.thumbnailInfo.file, info.info) - } - - is MediaUploadInfo.AnyFile -> { - room.sendFile(info.file, info.info) - } - else -> error("Unexpected MediaUploadInfo format: $info") - }.getOrThrow() - }.onFailure { - snackbarDispatcher.post(SnackbarMessage(StringR.string.screen_media_upload_preview_error_failed_sending)) - Timber.e(it, "Couldn't upload media") - }.onSuccess { - Timber.d("Media uploaded") - } - } - - private suspend fun handleMediaPreProcessing( - uri: Uri, - mediaType: MediaType, - deleteOriginal: Boolean, - ): Result { - val result = mediaPreProcessor.process(uri, mediaType, deleteOriginal = deleteOriginal) - Timber.d("Pre-processed media result: $result") - return result.onFailure { - snackbarDispatcher.post(SnackbarMessage(StringR.string.screen_media_upload_preview_error_failed_processing)) - } } } diff --git a/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaPreProcessor.kt b/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaPreProcessor.kt index 6e2168ca4b..cd45482871 100644 --- a/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaPreProcessor.kt +++ b/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/MediaPreProcessor.kt @@ -29,4 +29,7 @@ interface MediaPreProcessor { mediaType: MediaType, deleteOriginal: Boolean = false ): Result + + data class Failure(override val cause: Throwable?) : RuntimeException(cause) } + diff --git a/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/RoomExt.kt b/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/RoomExt.kt new file mode 100644 index 0000000000..ca5ec40ae8 --- /dev/null +++ b/libraries/mediaupload/api/src/main/kotlin/io/element/android/libraries/mediaupload/api/RoomExt.kt @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.mediaupload.api + +import io.element.android.libraries.matrix.api.room.MatrixRoom + +suspend fun MatrixRoom.sendMedia( + info: MediaUploadInfo, +): Result { + return when (info) { + is MediaUploadInfo.Image -> { + sendImage(info.file, info.thumbnailInfo.file, info.info) + } + + is MediaUploadInfo.Video -> { + sendVideo(info.file, info.thumbnailInfo.file, info.info) + } + + is MediaUploadInfo.AnyFile -> { + sendFile(info.file, info.info) + } + else -> error("Unexpected MediaUploadInfo format: $info") + } +} + diff --git a/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/MediaPreProcessorImpl.kt b/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/MediaPreProcessorImpl.kt index 76cc7fae1e..6831cad565 100644 --- a/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/MediaPreProcessorImpl.kt +++ b/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/MediaPreProcessorImpl.kt @@ -25,6 +25,7 @@ import com.squareup.anvil.annotations.ContributesBinding import io.element.android.libraries.androidutils.file.createTmpFile import io.element.android.libraries.androidutils.media.runAndRelease import io.element.android.libraries.core.data.tryOrNull +import io.element.android.libraries.core.extensions.mapFailure import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeImage import io.element.android.libraries.di.AppScope @@ -71,6 +72,7 @@ class MediaPreProcessorImpl @Inject constructor( * See [the Matrix spec](https://spec.matrix.org/latest/client-server-api/?ref=blog.gitter.im#thumbnails). */ private const val THUMB_MAX_WIDTH = 800 + /** * Max height of thumbnail images. * See [the Matrix spec](https://spec.matrix.org/latest/client-server-api/?ref=blog.gitter.im#thumbnails). @@ -93,7 +95,7 @@ class MediaPreProcessorImpl @Inject constructor( // Camera returns an 'octet-stream' mimetype, so it needs to be overridden val mimeType = contentResolver.getType(uri) val mimeTypeOrDefault = if (mimeType == MimeTypes.OctetStream) { - when(mediaType) { + when (mediaType) { MediaType.Image -> MimeTypes.Jpeg MediaType.Video -> MimeTypes.Mp4 MediaType.Audio -> MimeTypes.Ogg @@ -104,7 +106,7 @@ class MediaPreProcessorImpl @Inject constructor( } val compressBeforeSending = mediaType in sequenceOf(MediaType.Image, MediaType.Video) val result = if (compressBeforeSending && mimeType != MimeTypes.Gif) { - when(mediaType) { + when (mediaType) { MediaType.Image -> processImage(uri) MediaType.Video -> processVideo(uri, mimeTypeOrDefault) MediaType.Audio -> processAudio(uri, mimeTypeOrDefault) @@ -124,13 +126,11 @@ class MediaPreProcessorImpl @Inject constructor( ) MediaUploadInfo.AnyFile(file, info) } - if (deleteOriginal) { contentResolver.delete(uri, null, null) } - result - } + }.mapFailure { MediaPreProcessor.Failure(it) } private suspend fun processImage(uri: Uri): MediaUploadInfo { val compressedFileResult = contentResolver.openInputStream(uri).use { input ->