mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-03 23:58:55 +01:00 
			
		
		
		
	Change cover placeholder (#6756)
This commit is contained in:
		@@ -2,14 +2,11 @@ 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.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
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class used to hold the displayed data of a manga in the catalogue, like the cover or the title.
 | 
			
		||||
@@ -49,16 +46,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,14 +2,11 @@ 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.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
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class used to hold the displayed data of a manga in the catalogue, like the cover or the title.
 | 
			
		||||
@@ -49,16 +46,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,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)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -9,19 +9,6 @@
 | 
			
		||||
    android:foreground="@drawable/library_item_selector_overlay"
 | 
			
		||||
    android:padding="4dp">
 | 
			
		||||
 | 
			
		||||
    <com.google.android.material.progressindicator.CircularProgressIndicator
 | 
			
		||||
        android:id="@+id/progress"
 | 
			
		||||
        style="@style/Widget.Tachiyomi.CircularProgressIndicator.Small"
 | 
			
		||||
        android:layout_width="wrap_content"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:indeterminate="true"
 | 
			
		||||
        android:visibility="gone"
 | 
			
		||||
        app:layout_constraintBottom_toBottomOf="@+id/thumbnail"
 | 
			
		||||
        app:layout_constraintEnd_toEndOf="@+id/thumbnail"
 | 
			
		||||
        app:layout_constraintStart_toStartOf="@+id/thumbnail"
 | 
			
		||||
        app:layout_constraintTop_toTopOf="parent"
 | 
			
		||||
        tools:visibility="visible" />
 | 
			
		||||
 | 
			
		||||
    <com.google.android.material.imageview.ShapeableImageView
 | 
			
		||||
        android:id="@+id/thumbnail"
 | 
			
		||||
        android:layout_width="0dp"
 | 
			
		||||
 
 | 
			
		||||
@@ -55,18 +55,4 @@
 | 
			
		||||
        app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
        tools:text="Sample name" />
 | 
			
		||||
 | 
			
		||||
    <com.google.android.material.progressindicator.CircularProgressIndicator
 | 
			
		||||
        android:id="@+id/progress"
 | 
			
		||||
        style="@style/Widget.Tachiyomi.CircularProgressIndicator.Small"
 | 
			
		||||
        android:layout_width="wrap_content"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:layout_gravity="center"
 | 
			
		||||
        android:indeterminate="true"
 | 
			
		||||
        android:visibility="gone"
 | 
			
		||||
        app:layout_constraintBottom_toBottomOf="parent"
 | 
			
		||||
        app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
        app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
        app:layout_constraintTop_toTopOf="parent"
 | 
			
		||||
        tools:visibility="visible" />
 | 
			
		||||
 | 
			
		||||
</androidx.constraintlayout.widget.ConstraintLayout>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user