diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/latest/LatestCardHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/latest/LatestCardHolder.kt index 844f41ea5..ad4de5acb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/latest/LatestCardHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/latest/LatestCardHolder.kt @@ -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) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceComfortableGridHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceComfortableGridHolder.kt index bd156eecd..798cc1c3a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceComfortableGridHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceComfortableGridHolder.kt @@ -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) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceCompactGridHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceCompactGridHolder.kt index 49142f806..65fb3c777 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceCompactGridHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceCompactGridHolder.kt @@ -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) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceEnhancedEHentaiListHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceEnhancedEHentaiListHolder.kt index 4336722d1..8447951af 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceEnhancedEHentaiListHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceEnhancedEHentaiListHolder.kt @@ -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) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchCardHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchCardHolder.kt index fd31f1005..58888764c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchCardHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchCardHolder.kt @@ -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) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/index/IndexCardHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/index/IndexCardHolder.kt index fc4650b9c..6ef2626d3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/index/IndexCardHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/index/IndexCardHolder.kt @@ -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) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/view/ImageViewExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/view/ImageViewExtensions.kt index a8fddfd39..c64f04575 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/view/ImageViewExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/view/ImageViewExtensions.kt @@ -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) } ) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/StateImageViewTarget.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/StateImageViewTarget.kt deleted file mode 100755 index 0600e5d61..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/StateImageViewTarget.kt +++ /dev/null @@ -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) - } - } -} diff --git a/app/src/main/res/layout/source_comfortable_grid_item.xml b/app/src/main/res/layout/source_comfortable_grid_item.xml index ce8578e58..b86ddc316 100644 --- a/app/src/main/res/layout/source_comfortable_grid_item.xml +++ b/app/src/main/res/layout/source_comfortable_grid_item.xml @@ -9,19 +9,6 @@ android:foreground="@drawable/library_item_selector_overlay" android:padding="4dp"> - - - - diff --git a/app/src/main/res/layout/source_enhanced_ehentai_list_item.xml b/app/src/main/res/layout/source_enhanced_ehentai_list_item.xml index 012e41b31..5f3e7e5ba 100644 --- a/app/src/main/res/layout/source_enhanced_ehentai_list_item.xml +++ b/app/src/main/res/layout/source_enhanced_ehentai_list_item.xml @@ -8,58 +8,29 @@ android:foreground="@drawable/library_item_selector_overlay" android:padding="4dp"> - - - - - - - - - - - + app:layout_constraintTop_toTopOf="parent" + app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.Cover" + tools:ignore="ContentDescription" + tools:src="@mipmap/ic_launcher" /> + @@ -83,7 +54,7 @@ android:ellipsize="end" android:maxLines="1" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toEndOf="@+id/card" + app:layout_constraintStart_toEndOf="@+id/thumbnail" app:layout_constraintTop_toBottomOf="@+id/title" tools:text="Manga title for the life of me I cant think yes totally" /> @@ -95,7 +66,7 @@ android:layout_marginBottom="8dp" android:background="@drawable/rounded_rectangle" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintStart_toEndOf="@+id/card"> + app:layout_constraintStart_toEndOf="@+id/thumbnail"> + app:layout_constraintStart_toEndOf="@+id/thumbnail" />