From e8fc16d166e778b4d2ebc5a3b7215929a2e03e64 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Wed, 21 Aug 2024 06:01:21 +0700 Subject: [PATCH] refactor(coil): Move ImageView.loadManga() to its own directory --- .../data/coil/LibraryMangaImageTarget.kt | 32 ++------- .../tachiyomi/ui/library/LibraryGridHolder.kt | 5 +- .../tachiyomi/ui/library/LibraryListHolder.kt | 5 +- .../tachiyomi/ui/manga/EditMangaDialog.kt | 5 +- .../tachiyomi/ui/manga/MangaHeaderHolder.kt | 65 +++++++++---------- .../tachiyomi/ui/migration/MangaHolder.kt | 5 +- .../tachiyomi/ui/recents/RecentMangaHolder.kt | 9 ++- .../core/util/coil/ImageViewExtensions.kt | 42 ++++++++++++ 8 files changed, 88 insertions(+), 80 deletions(-) create mode 100644 app/src/main/java/yokai/presentation/core/util/coil/ImageViewExtensions.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/coil/LibraryMangaImageTarget.kt b/app/src/main/java/eu/kanade/tachiyomi/data/coil/LibraryMangaImageTarget.kt index d963feead1..cc4957a1dd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/coil/LibraryMangaImageTarget.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/coil/LibraryMangaImageTarget.kt @@ -4,38 +4,32 @@ import android.graphics.BitmapFactory import android.widget.ImageView import androidx.palette.graphics.Palette import coil3.Image -import coil3.ImageLoader -import coil3.imageLoader -import coil3.request.Disposable -import coil3.request.ImageRequest -import coil3.size.Precision -import coil3.size.SizeResolver import coil3.target.ImageViewTarget import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.database.models.updateCoverLastModified +import eu.kanade.tachiyomi.domain.manga.models.Manga import eu.kanade.tachiyomi.util.system.launchIO import uy.kohesive.injekt.injectLazy -import yokai.domain.manga.models.MangaCover class LibraryMangaImageTarget( override val view: ImageView, - val cover: MangaCover, + val libraryManga: Manga, ) : ImageViewTarget(view) { private val coverCache: CoverCache by injectLazy() override fun onError(error: Image?) { super.onError(error) - if (cover.inLibrary) { + if (libraryManga.favorite) { launchIO { - val file = coverCache.getCoverFile(cover.url, false) + val file = coverCache.getCoverFile(libraryManga.thumbnail_url, false) // if the file exists and the there was still an error then the file is corrupted if (file != null && file.exists()) { val options = BitmapFactory.Options() options.inJustDecodeBounds = true BitmapFactory.decodeFile(file.path, options) if (options.outWidth == -1 || options.outHeight == -1) { - cover.updateCoverLastModified() + libraryManga.updateCoverLastModified() file.delete() } } @@ -44,22 +38,6 @@ class LibraryMangaImageTarget( } } -@JvmSynthetic -inline fun ImageView.loadManga( - cover: MangaCover, - imageLoader: ImageLoader = context.imageLoader, - builder: ImageRequest.Builder.() -> Unit = {}, -): Disposable { - val request = ImageRequest.Builder(context) - .data(cover) - .target(LibraryMangaImageTarget(this, cover)) - .size(SizeResolver.ORIGINAL) - .precision(Precision.INEXACT) - .apply(builder) - .build() - return imageLoader.enqueue(request) -} - fun Palette.getBestColor(defaultColor: Int) = getBestColor() ?: defaultColor fun Palette.getBestColor(): Int? { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGridHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGridHolder.kt index 1c9a72858b..091642038b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGridHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGridHolder.kt @@ -13,7 +13,6 @@ import androidx.core.view.updateLayoutParams import coil3.dispose import coil3.size.Scale import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.coil.loadManga import eu.kanade.tachiyomi.data.database.models.dominantCoverColors import eu.kanade.tachiyomi.databinding.MangaGridItemBinding import eu.kanade.tachiyomi.domain.manga.models.Manga @@ -24,7 +23,7 @@ import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.view.backgroundColor import eu.kanade.tachiyomi.util.view.setCards import eu.kanade.tachiyomi.widget.AutofitRecyclerView -import yokai.domain.manga.models.cover +import yokai.presentation.core.util.coil.loadManga /** * Class used to hold the displayed data of a manga in the library, like the cover or the title. @@ -125,7 +124,7 @@ class LibraryGridHolder( private fun setCover(manga: Manga) { if ((adapter.recyclerView.context as? Activity)?.isDestroyed == true) return - binding.coverThumbnail.loadManga(manga.cover()) { + binding.coverThumbnail.loadManga(manga) { val hasRatio = binding.coverThumbnail.layoutParams.height != ViewGroup.LayoutParams.WRAP_CONTENT if (!fixedSize && !hasRatio) { scale(Scale.FIT) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryListHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryListHolder.kt index a7b11d2faf..568068a324 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryListHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryListHolder.kt @@ -5,13 +5,12 @@ import android.view.ViewGroup import androidx.core.view.isVisible import androidx.core.view.updateLayoutParams import coil3.dispose -import eu.kanade.tachiyomi.data.coil.loadManga import eu.kanade.tachiyomi.databinding.MangaListItemBinding import eu.kanade.tachiyomi.util.lang.highlightText import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.view.setCards -import yokai.domain.manga.models.cover import yokai.i18n.MR +import yokai.presentation.core.util.coil.loadManga import yokai.util.lang.getString /** @@ -96,7 +95,7 @@ class LibraryListHolder( // Update the cover. binding.coverThumbnail.dispose() - binding.coverThumbnail.loadManga(item.manga.cover()) + binding.coverThumbnail.loadManga(item.manga) } override fun onActionStateChanged(position: Int, actionState: Int) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/EditMangaDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/EditMangaDialog.kt index 551727ec5e..0034bfdc93 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/EditMangaDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/EditMangaDialog.kt @@ -18,7 +18,6 @@ import com.google.android.material.chip.Chip import com.google.android.material.chip.ChipGroup import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher -import eu.kanade.tachiyomi.data.coil.loadManga import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.seriesType import eu.kanade.tachiyomi.databinding.EditMangaDialogBinding @@ -41,8 +40,8 @@ import eu.kanade.tachiyomi.widget.TachiyomiTextInputEditText import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy -import yokai.domain.manga.models.cover import yokai.i18n.MR +import yokai.presentation.core.util.coil.loadManga import yokai.util.lang.getString import android.R as AR @@ -99,7 +98,7 @@ class EditMangaDialog : DialogController { fun onViewCreated() { val context = binding.root.context - binding.mangaCover.loadManga(manga.cover()) + binding.mangaCover.loadManga(manga) val isLocal = manga.isLocal() binding.mangaLang.isVisible = isLocal diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaHeaderHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaHeaderHolder.kt index 9f70defca5..cc043bee07 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaHeaderHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaHeaderHolder.kt @@ -32,7 +32,6 @@ import coil3.request.placeholder import com.google.android.material.button.MaterialButton import com.google.android.material.chip.Chip import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.coil.loadManga import eu.kanade.tachiyomi.data.database.models.seriesType import eu.kanade.tachiyomi.databinding.ChapterHeaderItemBinding import eu.kanade.tachiyomi.databinding.MangaHeaderItemBinding @@ -47,8 +46,8 @@ import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.system.isInNightMode import eu.kanade.tachiyomi.util.system.isLTR import eu.kanade.tachiyomi.util.view.resetStrokeColor -import yokai.domain.manga.models.cover import yokai.i18n.MR +import yokai.presentation.core.util.coil.loadManga import yokai.util.lang.getString import android.R as AR @@ -671,41 +670,35 @@ class MangaHeaderHolder( binding ?: return if (!manga.initialized) return val drawable = adapter.controller.binding.mangaCoverFull.drawable - binding.mangaCover.loadManga( - manga.cover(), - builder = { - placeholder(drawable) - error(drawable) - if (manga.favorite) networkCachePolicy(CachePolicy.READ_ONLY) - diskCachePolicy(CachePolicy.READ_ONLY) - }, - ) - binding.backdrop.loadManga( - manga.cover(), - builder = { - placeholder(drawable) - error(drawable) - if (manga.favorite) networkCachePolicy(CachePolicy.READ_ONLY) - diskCachePolicy(CachePolicy.READ_ONLY) - target( - onSuccess = { - val result = it.asDrawable(itemView.resources) - val bitmap = (result as? BitmapDrawable)?.bitmap - if (bitmap == null) { - binding.backdrop.setImageDrawable(result) - return@target - } - val yOffset = (bitmap.height / 2 * 0.33).toInt() + binding.mangaCover.loadManga(manga) { + placeholder(drawable) + error(drawable) + if (manga.favorite) networkCachePolicy(CachePolicy.READ_ONLY) + diskCachePolicy(CachePolicy.READ_ONLY) + } + binding.backdrop.loadManga(manga) { + placeholder(drawable) + error(drawable) + if (manga.favorite) networkCachePolicy(CachePolicy.READ_ONLY) + diskCachePolicy(CachePolicy.READ_ONLY) + target( + onSuccess = { + val result = it.asDrawable(itemView.resources) + val bitmap = (result as? BitmapDrawable)?.bitmap + if (bitmap == null) { + binding.backdrop.setImageDrawable(result) + return@target + } + val yOffset = (bitmap.height / 2 * 0.33).toInt() - binding.backdrop.setImageDrawable( - Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height - yOffset) - .toDrawable(itemView.resources), - ) - applyBlur() - }, - ) - }, - ) + binding.backdrop.setImageDrawable( + Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height - yOffset) + .toDrawable(itemView.resources), + ) + applyBlur() + }, + ) + } } fun expand() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/MangaHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/MangaHolder.kt index 2cf126d4eb..6732e191a5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/MangaHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/MangaHolder.kt @@ -5,11 +5,10 @@ import androidx.recyclerview.widget.RecyclerView import coil3.dispose import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.items.IFlexible -import eu.kanade.tachiyomi.data.coil.loadManga import eu.kanade.tachiyomi.databinding.MangaListItemBinding import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder import eu.kanade.tachiyomi.util.view.setCards -import yokai.domain.manga.models.cover +import yokai.presentation.core.util.coil.loadManga class MangaHolder( view: View, @@ -30,6 +29,6 @@ class MangaHolder( // Update the cover. binding.coverThumbnail.dispose() - binding.coverThumbnail.loadManga(item.manga.cover()) + binding.coverThumbnail.loadManga(item.manga) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentMangaHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentMangaHolder.kt index 8df1d0e4ff..6d76a2c584 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentMangaHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentMangaHolder.kt @@ -16,7 +16,6 @@ import androidx.core.view.updatePaddingRelative import androidx.transition.TransitionManager import androidx.transition.TransitionSet import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.coil.loadManga import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.ChapterHistory import eu.kanade.tachiyomi.data.download.model.Download @@ -32,10 +31,10 @@ import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.system.timeSpanFromNow import eu.kanade.tachiyomi.util.view.setAnimVectorCompat import eu.kanade.tachiyomi.util.view.setCards -import java.util.* -import java.util.concurrent.* -import yokai.domain.manga.models.cover +import java.util.Date +import java.util.concurrent.TimeUnit import yokai.i18n.MR +import yokai.presentation.core.util.coil.loadManga import yokai.util.lang.getString import android.R as AR @@ -213,7 +212,7 @@ class RecentMangaHolder( else -> context.timeSpanFromNow(MR.strings.read_, item.mch.history.last_read) } if ((context as? Activity)?.isDestroyed != true) { - binding.coverThumbnail.loadManga(item.mch.manga.cover()) + binding.coverThumbnail.loadManga(item.mch.manga) } if (!item.mch.manga.isLocal()) { notifyStatus( diff --git a/app/src/main/java/yokai/presentation/core/util/coil/ImageViewExtensions.kt b/app/src/main/java/yokai/presentation/core/util/coil/ImageViewExtensions.kt new file mode 100644 index 0000000000..3e219fce97 --- /dev/null +++ b/app/src/main/java/yokai/presentation/core/util/coil/ImageViewExtensions.kt @@ -0,0 +1,42 @@ +package yokai.presentation.core.util.coil + +import android.widget.ImageView +import coil3.ImageLoader +import coil3.imageLoader +import coil3.request.Disposable +import coil3.request.ImageRequest +import coil3.size.Precision +import coil3.size.SizeResolver +import eu.kanade.tachiyomi.data.coil.LibraryMangaImageTarget +import eu.kanade.tachiyomi.domain.manga.models.Manga +import yokai.domain.manga.models.MangaCover +import yokai.domain.manga.models.cover + +fun ImageView.loadManga( + manga: Manga, + imageLoader: ImageLoader = context.imageLoader, + builder: ImageRequest.Builder.() -> Unit = {}, +): Disposable { + val request = ImageRequest.Builder(context) + .data(manga.cover()) + .target(LibraryMangaImageTarget(this, manga)) + .size(SizeResolver.ORIGINAL) + .precision(Precision.INEXACT) + .apply(builder) + .build() + return imageLoader.enqueue(request) +} + +fun ImageView.loadManga( + cover: MangaCover, + imageLoader: ImageLoader = context.imageLoader, + builder: ImageRequest.Builder.() -> Unit = {}, +): Disposable { + val request = ImageRequest.Builder(context) + .data(cover) + .size(SizeResolver.ORIGINAL) + .precision(Precision.INEXACT) + .apply(builder) + .build() + return imageLoader.enqueue(request) +}