diff --git a/dependencies.gradle b/dependencies.gradle index 72419adcb0..1dceeac424 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -149,6 +149,7 @@ ext.libs = [ 'glideImageLoader' : "com.github.piasy:GlideImageLoader:$bigImageViewer", 'progressPieIndicator' : "com.github.piasy:ProgressPieIndicator:$bigImageViewer", 'glideImageViewFactory' : "com.github.piasy:GlideImageViewFactory:$bigImageViewer", + 'glideWebpDecoder' : "com.github.zjupure:webpdecoder:2.3.$glide", 'flowBinding' : "io.github.reactivecircus.flowbinding:flowbinding-android:$flowBinding", 'flowBindingAppcompat' : "io.github.reactivecircus.flowbinding:flowbinding-appcompat:$flowBinding", 'flowBindingMaterial' : "io.github.reactivecircus.flowbinding:flowbinding-material:$flowBinding" diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle index 14347c45d4..083730635b 100644 --- a/dependencies_groups.gradle +++ b/dependencies_groups.gradle @@ -82,6 +82,7 @@ ext.groups = [ 'com.github.piasy', 'com.github.shyiko.klob', 'com.github.rubensousa', + 'com.github.zjupure', 'com.google', 'com.google.android', 'com.google.api.grpc', diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MimeTypes.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MimeTypes.kt index 5ec0dedadf..af8ab71a87 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MimeTypes.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MimeTypes.kt @@ -30,6 +30,7 @@ object MimeTypes { const val BadJpg = "image/jpg" const val Jpeg = "image/jpeg" const val Gif = "image/gif" + const val Webp = "image/webp" const val Ogg = "audio/ogg" diff --git a/vector/build.gradle b/vector/build.gradle index cd12857b26..4a88db3bf4 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -218,6 +218,7 @@ dependencies { implementation libs.github.bigImageViewer implementation libs.github.glideImageLoader implementation libs.github.glideImageViewFactory + implementation libs.github.glideWebpDecoder // implementation 'com.github.MikeOrtiz:TouchImageView:3.0.2' implementation 'com.github.chrisbanes:PhotoView:2.3.0' diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt index 3d372788e7..36b6f82eae 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt @@ -538,10 +538,13 @@ class MessageItemFactory @Inject constructor( allowNonMxcUrls = informationData.sendState.isSending() ) - val playable = messageContent.mimeType == MimeTypes.Gif + // The webp library doesn't allow us to not animate images. + // Furthermore, its corner transformations are wrong when not using the animated case for rendering. + val forcePlay = messageContent.mimeType == MimeTypes.Webp + val playable = messageContent.mimeType == MimeTypes.Gif || forcePlay return MessageImageVideoItem_() - .attributes(attributes) + .attributes(attributes.takeUnless { forcePlay && !it.autoplayAnimatedImages } ?: attributes.copy(autoplayAnimatedImages = true)) .leftGuideline(avatarSizeProvider.leftGuideline) .imageContentRenderer(imageContentRenderer) .contentUploadStateTrackerBinder(contentUploadStateTrackerBinder) @@ -552,14 +555,16 @@ class MessageItemFactory @Inject constructor( .inReplyToClickCallback(callback) .mediaData(data) .apply { - if (messageContent.msgType == MessageType.MSGTYPE_STICKER_LOCAL) { + val inMemory = if (messageContent.msgType == MessageType.MSGTYPE_STICKER_LOCAL) { mode(ImageContentRenderer.Mode.STICKER) - clickListener { view -> - callback?.onImageMessageClicked(messageContent, data, view, listOf(data)) - } + listOf(data) } else { + emptyList() + } + // Big image viewer doesn't support webp + if (messageContent.mimeType != MimeTypes.Webp) { clickListener { view -> - callback?.onImageMessageClicked(messageContent, data, view, emptyList()) + callback?.onImageMessageClicked(messageContent, data, view, inMemory) } } }.apply { diff --git a/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt b/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt index c1fb65c79a..891dfa652a 100644 --- a/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt +++ b/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt @@ -24,6 +24,8 @@ import android.widget.ImageView import androidx.core.view.isGone import androidx.core.view.isVisible import androidx.core.view.updateLayoutParams +import com.bumptech.glide.integration.webp.decoder.WebpDrawable +import com.bumptech.glide.integration.webp.decoder.WebpDrawableTransformation import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.Transformation import com.bumptech.glide.load.engine.DiskCacheStrategy @@ -180,7 +182,9 @@ class ImageContentRenderer @Inject constructor( }) request = if (animate && mode == Mode.ANIMATED_THUMBNAIL) { // Glide seems to already do some dp to px calculation for animated gifs? - request.transform(RoundedCorners(cornerRoundnessDp)) + val animatedCornerTransformation = RoundedCorners(cornerRoundnessDp) + request.transform(animatedCornerTransformation) + .transform(WebpDrawable::class.java, WebpDrawableTransformation(animatedCornerTransformation)) //request.apply(RequestOptions.bitmapTransform(RoundedCorners(3))) } else { request.dontAnimate()