Change cover placeholder (#6756)

(cherry picked from commit 869424cd16)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceComfortableGridHolder.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceCompactGridHolder.kt
#	app/src/main/java/eu/kanade/tachiyomi/widget/StateImageViewTarget.kt
This commit is contained in:
Ivan Iskandar
2022-03-10 05:26:55 +07:00
committed by Jobobby04
parent 01b8256daf
commit 4a627ea359
11 changed files with 54 additions and 222 deletions
@@ -3,15 +3,11 @@ package eu.kanade.tachiyomi.ui.browse.latest
import android.view.View
import androidx.core.view.isVisible
import coil.dispose
import coil.imageLoader
import coil.request.CachePolicy
import coil.request.ImageRequest
import coil.transition.CrossfadeTransition
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.databinding.GlobalSearchControllerCardItemBinding
import eu.kanade.tachiyomi.widget.StateImageViewTarget
import eu.kanade.tachiyomi.util.view.loadAutoPause
class LatestCardHolder(view: View, adapter: LatestCardAdapter) :
FlexibleViewHolder(view, adapter) {
@@ -55,17 +51,8 @@ class LatestCardHolder(view: View, adapter: LatestCardAdapter) :
fun setImage(manga: Manga) {
binding.cover.dispose()
if (!manga.thumbnail_url.isNullOrEmpty()) {
val crossfadeDuration = itemView.context.imageLoader.defaults.transitionFactory.let {
if (it is CrossfadeTransition.Factory) it.durationMillis else 0
}
val request = ImageRequest.Builder(itemView.context)
.data(manga)
.setParameter(MangaCoverFetcher.USE_CUSTOM_COVER, false)
.diskCachePolicy(CachePolicy.DISABLED)
.target(StateImageViewTarget(binding.cover, binding.progress, crossfadeDuration))
.build()
itemView.context.imageLoader.enqueue(request)
binding.cover.loadAutoPause(manga) {
setParameter(MangaCoverFetcher.USE_CUSTOM_COVER, false)
}
}
}
@@ -2,15 +2,12 @@ package eu.kanade.tachiyomi.ui.browse.source.browse
import androidx.core.view.isVisible
import coil.dispose
import coil.imageLoader
import coil.request.ImageRequest
import coil.transition.CrossfadeTransition
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.databinding.SourceComfortableGridItemBinding
import eu.kanade.tachiyomi.widget.StateImageViewTarget
import eu.kanade.tachiyomi.util.view.loadAutoPause
import exh.metadata.metadata.MangaDexSearchMetadata
import exh.metadata.metadata.base.RaisedSearchMetadata
@@ -67,16 +64,8 @@ class SourceComfortableGridHolder(
override fun setImage(manga: Manga) {
binding.thumbnail.dispose()
if (!manga.thumbnail_url.isNullOrEmpty()) {
val crossfadeDuration = binding.root.context.imageLoader.defaults.transitionFactory.let {
if (it is CrossfadeTransition.Factory) it.durationMillis else 0
}
val request = ImageRequest.Builder(binding.root.context)
.data(manga)
.setParameter(MangaCoverFetcher.USE_CUSTOM_COVER, false)
.target(StateImageViewTarget(binding.thumbnail, binding.progress, crossfadeDuration))
.build()
itemView.context.imageLoader.enqueue(request)
binding.thumbnail.loadAutoPause(manga) {
setParameter(MangaCoverFetcher.USE_CUSTOM_COVER, false)
}
}
}
@@ -2,15 +2,12 @@ package eu.kanade.tachiyomi.ui.browse.source.browse
import androidx.core.view.isVisible
import coil.dispose
import coil.imageLoader
import coil.request.ImageRequest
import coil.transition.CrossfadeTransition
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.databinding.SourceCompactGridItemBinding
import eu.kanade.tachiyomi.widget.StateImageViewTarget
import eu.kanade.tachiyomi.util.view.loadAutoPause
import exh.metadata.metadata.MangaDexSearchMetadata
import exh.metadata.metadata.base.RaisedSearchMetadata
@@ -67,16 +64,8 @@ class SourceCompactGridHolder(
override fun setImage(manga: Manga) {
binding.thumbnail.dispose()
if (!manga.thumbnail_url.isNullOrEmpty()) {
val crossfadeDuration = binding.root.context.imageLoader.defaults.transitionFactory.let {
if (it is CrossfadeTransition.Factory) it.durationMillis else 0
}
val request = ImageRequest.Builder(binding.root.context)
.data(manga)
.setParameter(MangaCoverFetcher.USE_CUSTOM_COVER, false)
.target(StateImageViewTarget(binding.thumbnail, binding.progress, crossfadeDuration))
.build()
itemView.context.imageLoader.enqueue(request)
binding.thumbnail.loadAutoPause(manga) {
setParameter(MangaCoverFetcher.USE_CUSTOM_COVER, false)
}
}
}
@@ -3,17 +3,13 @@ package eu.kanade.tachiyomi.ui.browse.source.browse
import android.view.View
import androidx.core.view.isVisible
import coil.dispose
import coil.imageLoader
import coil.request.CachePolicy
import coil.request.ImageRequest
import coil.transition.CrossfadeTransition
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.databinding.SourceEnhancedEhentaiListItemBinding
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.widget.StateImageViewTarget
import eu.kanade.tachiyomi.util.view.loadAutoPause
import exh.metadata.MetadataUtil
import exh.metadata.metadata.EHentaiSearchMetadata
import exh.metadata.metadata.base.RaisedSearchMetadata
@@ -50,10 +46,11 @@ class SourceEnhancedEHentaiListHolder(view: View, adapter: FlexibleAdapter<*>) :
binding.thumbnail.alpha = if (manga.favorite) 0.3f else 1.0f
// For rounded corners
binding.badges.clipToOutline = true
binding.badges.leftBadges.clipToOutline = true
binding.badges.rightBadges.clipToOutline = true
// Set favorite badge
binding.favoriteText.isVisible = manga.favorite
binding.badges.favoriteText.isVisible = manga.favorite
setImage(manga)
}
@@ -103,21 +100,9 @@ class SourceEnhancedEHentaiListHolder(view: View, adapter: FlexibleAdapter<*>) :
}
override fun setImage(manga: Manga) {
// For rounded corners
binding.card.clipToOutline = true
binding.thumbnail.dispose()
if (!manga.thumbnail_url.isNullOrEmpty()) {
val crossfadeDuration = itemView.context.imageLoader.defaults.transitionFactory.let {
if (it is CrossfadeTransition.Factory) it.durationMillis else 0
}
val request = ImageRequest.Builder(itemView.context)
.data(manga)
.setParameter(MangaCoverFetcher.USE_CUSTOM_COVER, false)
.diskCachePolicy(CachePolicy.DISABLED)
.target(StateImageViewTarget(binding.thumbnail, binding.progress, crossfadeDuration))
.build()
itemView.context.imageLoader.enqueue(request)
binding.thumbnail.loadAutoPause(manga) {
setParameter(MangaCoverFetcher.USE_CUSTOM_COVER, false)
}
}
}
@@ -3,14 +3,11 @@ package eu.kanade.tachiyomi.ui.browse.source.globalsearch
import android.view.View
import androidx.core.view.isVisible
import coil.dispose
import coil.imageLoader
import coil.request.ImageRequest
import coil.transition.CrossfadeTransition
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.databinding.GlobalSearchControllerCardItemBinding
import eu.kanade.tachiyomi.widget.StateImageViewTarget
import eu.kanade.tachiyomi.util.view.loadAutoPause
class GlobalSearchCardHolder(view: View, adapter: GlobalSearchCardAdapter) :
FlexibleViewHolder(view, adapter) {
@@ -54,16 +51,8 @@ class GlobalSearchCardHolder(view: View, adapter: GlobalSearchCardAdapter) :
fun setImage(manga: Manga) {
binding.cover.dispose()
if (!manga.thumbnail_url.isNullOrEmpty()) {
val crossfadeDuration = itemView.context.imageLoader.defaults.transitionFactory.let {
if (it is CrossfadeTransition.Factory) it.durationMillis else 0
}
val request = ImageRequest.Builder(itemView.context)
.data(manga)
.setParameter(MangaCoverFetcher.USE_CUSTOM_COVER, false)
.target(StateImageViewTarget(binding.cover, binding.progress, crossfadeDuration))
.build()
itemView.context.imageLoader.enqueue(request)
binding.cover.loadAutoPause(manga) {
setParameter(MangaCoverFetcher.USE_CUSTOM_COVER, false)
}
}
}
@@ -3,15 +3,11 @@ package eu.kanade.tachiyomi.ui.browse.source.index
import android.view.View
import androidx.core.view.isVisible
import coil.dispose
import coil.imageLoader
import coil.request.CachePolicy
import coil.request.ImageRequest
import coil.transition.CrossfadeTransition
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.databinding.GlobalSearchControllerCardItemBinding
import eu.kanade.tachiyomi.widget.StateImageViewTarget
import eu.kanade.tachiyomi.util.view.loadAutoPause
class IndexCardHolder(view: View, adapter: IndexCardAdapter) :
FlexibleViewHolder(view, adapter) {
@@ -55,17 +51,8 @@ class IndexCardHolder(view: View, adapter: IndexCardAdapter) :
fun setImage(manga: Manga) {
binding.cover.dispose()
if (!manga.thumbnail_url.isNullOrEmpty()) {
val crossfadeDuration = itemView.context.imageLoader.defaults.transitionFactory.let {
if (it is CrossfadeTransition.Factory) it.durationMillis else 0
}
val request = ImageRequest.Builder(itemView.context)
.data(manga)
.setParameter(MangaCoverFetcher.USE_CUSTOM_COVER, false)
.diskCachePolicy(CachePolicy.DISABLED)
.target(StateImageViewTarget(binding.cover, binding.progress, crossfadeDuration))
.build()
itemView.context.imageLoader.enqueue(request)
binding.cover.loadAutoPause(manga) {
setParameter(MangaCoverFetcher.USE_CUSTOM_COVER, false)
}
}
}
@@ -1,11 +1,14 @@
package eu.kanade.tachiyomi.util.view
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.Animatable
import android.graphics.drawable.ColorDrawable
import android.widget.ImageView
import androidx.annotation.AttrRes
import androidx.annotation.DrawableRes
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.graphics.ColorUtils
import coil.ImageLoader
import coil.imageLoader
import coil.load
@@ -38,20 +41,22 @@ fun ImageView.loadAutoPause(
loader: ImageLoader = context.imageLoader,
builder: ImageRequest.Builder.() -> Unit = {}
) {
// Build the original request so we can add on our success listener
load(data, loader) {
val placeholderColor = ColorUtils.setAlphaComponent(Color.GRAY, 0x1F) // 12% gray
placeholder(ColorDrawable(placeholderColor))
// Build the original request so we can add on our success listener
val originalBuild = apply(builder).build()
val originalListener = apply(builder).build().listener
listener(
onSuccess = { request, metadata ->
(request.target as? ImageViewTarget)?.drawable.let {
if (it is Animatable && context.animatorDurationScale == 0f) it.stop()
}
originalBuild.listener?.onSuccess(request, metadata)
originalListener?.onSuccess(request, metadata)
},
onStart = { request -> originalBuild.listener?.onStart(request) },
onCancel = { request -> originalBuild.listener?.onCancel(request) },
onError = { request, throwable -> originalBuild.listener?.onError(request, throwable) }
onStart = { request -> originalListener?.onStart(request) },
onCancel = { request -> originalListener?.onCancel(request) },
onError = { request, throwable -> originalListener?.onError(request, throwable) }
)
}
}
@@ -1,43 +0,0 @@
package eu.kanade.tachiyomi.widget
import android.graphics.drawable.Drawable
import android.view.View
import android.widget.ImageView
import androidx.core.view.isVisible
import coil.drawable.CrossfadeDrawable
import coil.target.ImageViewTarget
/**
* A Coil target to display an image with an optional view to show while loading.
*
* @param target the view where the image will be loaded
* @param progress the view to show when the image is loading.
* @param crossfadeDuration duration in millisecond to crossfade the result drawable
*/
class StateImageViewTarget(
private val target: ImageView,
private val progress: View,
private val crossfadeDuration: Int = 0
) : ImageViewTarget(target) {
override fun onStart(placeholder: Drawable?) {
progress.isVisible = true
}
override fun onSuccess(result: Drawable) {
progress.isVisible = false
if (crossfadeDuration > 0) {
val crossfadeResult = CrossfadeDrawable(target.drawable, result, durationMillis = crossfadeDuration)
target.setImageDrawable(crossfadeResult)
crossfadeResult.start()
} else {
target.setImageDrawable(result)
}
}
override fun onError(error: Drawable?) {
progress.isVisible = false
if (error != null) {
target.setImageDrawable(error)
}
}
}