diff --git a/changelog.d/1082.bugfix b/changelog.d/1082.bugfix new file mode 100644 index 0000000000..bd979c8c86 --- /dev/null +++ b/changelog.d/1082.bugfix @@ -0,0 +1 @@ +Correction du crash lorsque l'image de l'avatar d'un membre est trop grande. \ No newline at end of file diff --git a/library/ui-strings/src/main/res/values-fr/strings.xml b/library/ui-strings/src/main/res/values-fr/strings.xml index 7c88b18119..f361a2ed95 100644 --- a/library/ui-strings/src/main/res/values-fr/strings.xml +++ b/library/ui-strings/src/main/res/values-fr/strings.xml @@ -2013,7 +2013,7 @@ Assurez-vous que les bonnes personnes ont accès à %s. Avec qui travaillez-vous \? Pour rejoindre un espace existant, il vous faut une invitation. - Le fichier est trop volumineux pour être envoyé. + Le fichier est trop volumineux ou l’image est trop grande pour être envoyée. Compression de la vidéo %d %% Compression de l’image… Utiliser par défaut et ne plus demander diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/FileUploader.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/FileUploader.kt index eee55735e0..f14d4914ee 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/FileUploader.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/FileUploader.kt @@ -17,6 +17,8 @@ package org.matrix.android.sdk.internal.session.content import android.content.Context +import android.graphics.Bitmap +import android.graphics.BitmapFactory import android.net.Uri import com.squareup.moshi.Moshi import kotlinx.coroutines.Dispatchers @@ -37,12 +39,14 @@ import org.matrix.android.sdk.api.failure.MatrixError import org.matrix.android.sdk.api.session.content.ContentUrlResolver import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService +import org.matrix.android.sdk.api.util.MimeTypes.isMimeTypeImage import org.matrix.android.sdk.internal.di.Authenticated import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.ProgressRequestBody import org.matrix.android.sdk.internal.network.awaitResponse import org.matrix.android.sdk.internal.network.toFailure import org.matrix.android.sdk.internal.util.TemporaryFileCreator +import timber.log.Timber import java.io.File import java.io.FileNotFoundException import java.io.IOException @@ -70,6 +74,7 @@ internal class FileUploader @Inject constructor( ): ContentUploadResponse { // Check size limit val maxUploadFileSize = homeServerCapabilitiesService.getHomeServerCapabilities().maxUploadFileSize + val maxImageSize = 32_000_000 if (maxUploadFileSize != HomeServerCapabilities.MAX_UPLOAD_FILE_SIZE_UNKNOWN && file.length() > maxUploadFileSize) { @@ -83,6 +88,24 @@ internal class FileUploader @Inject constructor( ) } + // TCHAP Check image size limit + if (mimeType.isMimeTypeImage()) { + BitmapFactory.Options().run { + inJustDecodeBounds = true + decodeBitmap(file, this) + if (outHeight * outWidth > maxImageSize) { + // Known limitation and image size too big for the server, save the pain to upload it + throw Failure.ServerError( + error = MatrixError( + code = MatrixError.M_TOO_LARGE, + message = "Cannot upload images larger than ${maxImageSize / 1_000_000} Megapixels" + ), + httpCode = 413 + ) + } + } + } + val uploadBody = object : RequestBody() { override fun contentLength() = file.length() @@ -135,6 +158,17 @@ internal class FileUploader @Inject constructor( } } + private fun decodeBitmap(file: File, options: BitmapFactory.Options = BitmapFactory.Options()): Bitmap? { + return try { + file.inputStream().use { inputStream -> + BitmapFactory.decodeStream(inputStream, null, options) + } + } catch (e: Exception) { + Timber.e(e, "Cannot decode Bitmap") + null + } + } + private suspend fun upload( uploadBody: RequestBody, filename: String?, diff --git a/vector/src/main/java/im/vector/app/features/home/AvatarRenderer.kt b/vector/src/main/java/im/vector/app/features/home/AvatarRenderer.kt index 7f142cf117..ffd5a4849c 100644 --- a/vector/src/main/java/im/vector/app/features/home/AvatarRenderer.kt +++ b/vector/src/main/java/im/vector/app/features/home/AvatarRenderer.kt @@ -162,7 +162,8 @@ class AvatarRenderer @Inject constructor( fun render( glideRequests: GlideRequests, matrixItem: MatrixItem, - target: Target + target: Target, + maxPxSize: Int = 0 ) { val placeholder = getPlaceholderDrawable(matrixItem) glideRequests.loadResolvedUrl(matrixItem.avatarUrl) @@ -172,7 +173,8 @@ class AvatarRenderer @Inject constructor( it.transform(MultiTransformation(CenterCrop(), RoundedCorners(dimensionConverter.dpToPx(8)))) } else -> { - it.apply(RequestOptions.circleCropTransform()) + // TCHAP Fix avatar sizing + it.apply(RequestOptions.circleCropTransform().override(maxPxSize, maxPxSize)) } } } @@ -264,10 +266,10 @@ class AvatarRenderer @Inject constructor( } @AnyThread - fun getCachedDrawable(glideRequests: GlideRequests, matrixItem: MatrixItem): Drawable { + fun getCachedDrawable(glideRequests: GlideRequests, matrixItem: MatrixItem, maxPxSize: Int = 0): Drawable { return glideRequests.loadResolvedUrl(matrixItem.avatarUrl) .onlyRetrieveFromCache(true) - .apply(RequestOptions.circleCropTransform()) + .apply(RequestOptions.circleCropTransform().override(maxPxSize, maxPxSize)) // TCHAP Fix avatar sizing .submit() .get() } diff --git a/vector/src/main/java/im/vector/app/features/html/PillImageSpan.kt b/vector/src/main/java/im/vector/app/features/html/PillImageSpan.kt index 95592e564f..390804ba81 100644 --- a/vector/src/main/java/im/vector/app/features/html/PillImageSpan.kt +++ b/vector/src/main/java/im/vector/app/features/html/PillImageSpan.kt @@ -57,6 +57,7 @@ class PillImageSpan( override val matrixItem: MatrixItem ) : ReplacementSpan(), MatrixItemSpan { + private val maxPxSize = context.resources.getDimensionPixelSize(im.vector.lib.ui.styles.R.dimen.pill_avatar_size) private val pillDrawable = createChipDrawable() private val target = PillImageSpanTarget(this) private var tv: WeakReference? = null @@ -64,7 +65,7 @@ class PillImageSpan( @UiThread fun bind(textView: TextView) { tv = WeakReference(textView) - avatarRenderer.render(glideRequests, matrixItem, target) + avatarRenderer.render(glideRequests, matrixItem, target, maxPxSize) // TCHAP Fix avatar sizing } // ReplacementSpan ***************************************************************************** @@ -144,7 +145,7 @@ class PillImageSpan( } else -> { try { - avatarRenderer.getCachedDrawable(glideRequests, matrixItem) + avatarRenderer.getCachedDrawable(glideRequests, matrixItem, maxPxSize) // TCHAP Fix avatar sizing } catch (exception: Exception) { avatarRenderer.getPlaceholderDrawable(matrixItem) }