8000 MBL-1420: Webp format now supported for animated gifs by Arkariang · Pull Request #2039 · kickstarter/android-oss · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

MBL-1420: Webp format now supported for animated gifs #2039

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
8000
merged 15 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ dependencies {

// GLIDE
final glide_version = "4.16.0"
// webpdecoder
implementation "com.github.zjupure:webpdecoder:2.6.$glide_version"
implementation "com.github.bumptech.glide:glide:$glide_version"
annotationProcessor "com.github.bumptech.glide:compiler:$glide_version"
kapt "com.github.bumptech.glide:compiler:$glide_version"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,15 @@ fun String?.parseToDouble(): Double {
}

/**
* Returns a boolean that reflects if the string is an email address
* Returns a boolean that reflects if the string contains the .webp extension
*/
fun String.isWebp(): Boolean {
val gifPattern = "(?:\\/\\/.*\\.(?:webp))"
return gifPattern.toRegex().find(this) != null
}

/**
* Returns a boolean that reflects if the string contains the .gif extension
*/
fun String.isGif(): Boolean {
val gifPattern = "(?:\\/\\/.*\\.(?:gif))"
Expand Down
36 changes: 27 additions & 9 deletions app/src/main/java/com/kickstarter/ui/extensions/ImageViewExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,17 @@ import android.graphics.drawable.Drawable
import android.widget.ImageView
import androidx.appcompat.widget.AppCompatImageView
import com.bumptech.glide.Glide
import com.bumptech.glide.integration.webp.decoder.WebpDrawable
import com.bumptech.glide.integration.webp.decoder.WebpDrawableTransformation
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.Target
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.kickstarter.R
import com.kickstarter.libs.utils.extensions.isKSApplication
import javax.sql.DataSource

fun ImageView.loadCircleImage(url: String?) {
url?.let {
Expand Down Expand Up @@ -80,7 +82,7 @@ fun ImageView.loadImageWithResize(
}
}
}
fun ImageView.loadImage(url: String?, context: Context, imageViewPlaceholder: AppCompatImageView? = null) {
fun ImageView.loadImage(url: String?, context: Context, imageZoomablePlaceholder: AppCompatImageView? = null) {
url?.let {
val targetView = this
if (context.applicationContext.isKSApplication()) {
Expand All @@ -95,7 +97,8 @@ fun ImageView.loadImage(url: String?, context: Context, imageViewPlaceholder: Ap
dataSource: com.bumptech.glide.load.DataSource,
isFirstResource: Boolean
): Boolean {
imageViewPlaceholder?.setImageDrawable(resource)
targetView.setImageDrawable(resource)
imageZoomablePlaceholder?.setImageDrawable(resource)
return isFirstResource
}

Expand All @@ -106,12 +109,11 @@ fun ImageView.loadImage(url: String?, context: Context, imageViewPlaceholder: Ap
isFirstResource: Boolean
): Boolean {
targetView.setImageDrawable(null)
imageViewPlaceholder?.setImageDrawable(null)
imageZoomablePlaceholder?.setImageDrawable(null)
return isFirstResource
}
})
.placeholder(ColorDrawable(Color.TRANSPARENT))
.diskCacheStrategy(DiskCacheStrategy.ALL)
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
Copy link
Contributor Author
@Arkariang Arkariang May 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DiskCacheStrategy.AUTOMATIC intelligently chooses a cache strategy based on the resource & placeholder removed

.load(url)
.into(this)
} catch (e: Exception) {
Expand All @@ -125,15 +127,31 @@ fun ImageView.loadImage(url: String?, context: Context, imageViewPlaceholder: Ap
}
}

fun ImageView.loadWebp(url: String?, context: Context) {
url?.let {
try {
val roundedCorners = RoundedCorners(1)
Glide.with(this)
.load(it)
.optionalTransform(roundedCorners)
.optionalTransform(WebpDrawable::class.java, WebpDrawableTransformation(roundedCorners))
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
.into(this)
} catch (e: Exception) {
this.setImageResource(R.drawable.image_placeholder)
FirebaseCrashlytics.getInstance().setCustomKey("ImageView.loadImageWithResize", " with url: $url ${e.message ?: ""}")
FirebaseCrashlytics.getInstance().recordException(e)
}
}
}
fun ImageView.loadGifImage(url: String?, context: Context) {
url?.let {
if (context.applicationContext.isKSApplication()) {
try {
Glide.with(context)
.asGif()
.placeholder(ColorDrawable(Color.TRANSPARENT))
.diskCacheStrategy(DiskCacheStrategy.ALL)
.load(url)
.load(it)
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
.into(this)
} catch (e: Exception) {
this.setImageResource(R.drawable.image_placeholder)
Expand Down
20 changes: 14 additions & 6 deletions app/src/main/java/com/kickstarter/ui/views/ImageWithCaptionView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ import com.aghajari.zoomhelper.ZoomHelper
import com.kickstarter.R
import com.kickstarter.databinding.ViewImageWithCaptionBinding
import com.kickstarter.libs.utils.extensions.isGif
import com.kickstarter.libs.utils.extensions.isWebp
import com.kickstarter.ui.extensions.loadGifImage
import com.kickstarter.ui.extensions.loadImage
import com.kickstarter.ui.extensions.loadWebp
import com.kickstarter.ui.extensions.makeLinks

@SuppressLint("ClickableViewAccessibility")
Expand All @@ -35,12 +37,18 @@ class ImageWithCaptionView @JvmOverloads constructor(
binding.imageView.setImageDrawable(null)
binding.imageViewPlaceholder.setImageDrawable(null)
} else {
if (src.isGif()) {
binding.imageView.loadGifImage(src, context)
} else {
binding.imageView.loadImage(src, context, binding.imageViewPlaceholder)
ZoomHelper.addZoomableView(binding.imageView)
ZoomHelper.removeZoomableView(binding.imageViewPlaceholder)
when {
src.isWebp() -> {
binding.imageView.loadWebp(src, context)
}
src.isGif() -> {
binding.imageView.loadGifImage(src, context)
}
else -> {
binding.imageView.loadImage(src, context, binding.imageViewPlaceholder)
ZoomHelper.addZoomableView(binding.imageView)
ZoomHelper.removeZoomableView(binding.imageViewPlaceholder)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.kickstarter.libs.htmlparser

import com.kickstarter.libs.utils.extensions.isGif
import com.kickstarter.libs.utils.extensions.isWebp
import junit.framework.TestCase
import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.assertTrue
import org.junit.Test
import java.net.URI

Expand Down Expand Up @@ -344,4 +347,27 @@ class HTMLParserTest {
assert(h6.components[0].styles[0] == TextComponent.TextStyleType.HEADER6)
assert(h6.components[0].text == "This is heading 6")
}

@Test
fun given_HTML_withGifAndWebpExtensions_HtmlParser_returns_ImageViewElement_with_URL() {
val htmlGif = "<div class=\"template asset\" contenteditable=\"false\" data-alt-text=\"\" data-caption=\"\" data-id=\"44904170\">\n" +
" <figure class=\"image\">\n" +
" <img alt=\"\" class=\"fit js-lazy-image\" data-src=\"https://i.kickstarter.com/assets/044/904/170/8f34ecce9f82c23fde692cc4142c4630_original.gif?fit=scale-down&amp;amp;origin=ugc&amp;amp;q=92&amp;amp;width=700&amp;amp;sig=ZqRtxdLrF0UP7iJ0za7PZozt0HPUbVshM%2Bnphli8oTA%3D\" src=\"https://i.kickstarter.com/assets/044/904/170/8f34ecce9f82c23fde692cc4142c4630_original.gif?anim=false&amp;amp;fit=scale-down&amp;amp;origin=ugc&amp;amp;q=92&amp;amp;width=700&amp;amp;sig=%2FNSNA716ADltGnCen9XnFGjlOi6nSy36sef7hdFe9eQ%3D\" > \n" +
" </figure>\n" +
"</div>\n"
val htmlWebMP =
"<div class=\"template asset\" contenteditable=\"false\" data-alt-text=\"\" data-caption=\"\" data-id=\"44690634\">\n" +
" <figure class=\"image\">\n" +
" <img alt=\"\" class=\"fit\" src=\"https://i.kickstarter.com/assets/044/690/634/1a2c5e757fa2a5b0db60876b56e11295_original.webp?fit=scale-down&amp;amp;origin=ugc&amp;amp;q=92&amp;amp;width=700&amp;amp;sig=4V3Wnp7WocWKYQWv9ErXnbB4%2FPeGiCv59bBv3e04Kqs%3D\">\n" +
" </figure>\n" +
"</div>"

val listOfElements = HTMLParser().parse(htmlGif + htmlWebMP)
assert(listOfElements.size == 2)
val imageViewGif: ImageViewElement = listOfElements.first() as ImageViewElement
val imageViewWebp: ImageViewElement = listOfElements.last() as ImageViewElement

assertTrue(imageViewGif.src.isGif())
assertTrue(imageViewWebp.src.isWebp())
}
}
0