From 1f8072f18b27c0578ebb99a03058e5dcbc079838 Mon Sep 17 00:00:00 2001 From: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com> Date: Sat, 5 Mar 2022 04:04:32 +0700 Subject: [PATCH] Coil 2.x upgrade (#6725) * Migrate to Coil 2 * Adapt to use coil disk cache * Update to alpha 7 * Update to alpha 8 * Update to rc01 (cherry picked from commit 10eef282fa2fc0d8ae919d8b86bff1b529b4330d) # Conflicts: # app/src/main/java/eu/kanade/tachiyomi/App.kt # app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt # app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryComfortableGridHolder.kt # app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCompactGridHolder.kt # app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt --- app/src/main/java/eu/kanade/tachiyomi/App.kt | 41 ++- .../kanade/tachiyomi/data/cache/CoverCache.kt | 2 +- .../tachiyomi/data/coil/ByteBufferFetcher.kt | 25 -- .../tachiyomi/data/coil/MangaCoverFetcher.kt | 237 +++++++++++------- .../tachiyomi/data/coil/MangaCoverKeyer.kt | 11 + .../data/coil/TachiyomiImageDecoder.kt | 56 +++-- .../kanade/tachiyomi/network/NetworkHelper.kt | 3 - .../ui/browse/extension/ExtensionHolder.kt | 4 +- .../ui/browse/latest/LatestCardHolder.kt | 8 +- .../process/MigrationProcessHolder.kt | 8 +- .../migration/manga/MigrationMangaHolder.kt | 8 +- .../browse/SourceComfortableGridHolder.kt | 8 +- .../source/browse/SourceCompactGridHolder.kt | 8 +- .../browse/SourceEnhancedEHentaiListHolder.kt | 8 +- .../browse/source/browse/SourceListHolder.kt | 8 +- .../globalsearch/GlobalSearchCardHolder.kt | 8 +- .../ui/browse/source/index/IndexCardHolder.kt | 8 +- .../library/LibraryComfortableGridHolder.kt | 12 +- .../ui/library/LibraryCompactGridHolder.kt | 10 +- .../tachiyomi/ui/library/LibraryListHolder.kt | 8 +- .../tachiyomi/ui/manga/EditMangaDialog.kt | 6 +- .../tachiyomi/ui/manga/MangaPresenter.kt | 2 +- .../ui/manga/info/MangaInfoHeaderAdapter.kt | 6 +- .../ui/manga/merged/EditMergedMangaHolder.kt | 4 +- .../ui/manga/track/TrackSearchHolder.kt | 8 +- .../ui/reader/viewer/ReaderPageImageView.kt | 4 +- .../ui/recent/history/HistoryHolder.kt | 8 +- .../ui/recent/updates/UpdatesHolder.kt | 8 +- .../util/view/ImageViewExtensions.kt | 7 +- gradle/libs.versions.toml | 2 +- 30 files changed, 310 insertions(+), 226 deletions(-) delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/coil/ByteBufferFetcher.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/coil/MangaCoverKeyer.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/App.kt b/app/src/main/java/eu/kanade/tachiyomi/App.kt index 8af0b3c91..2a383f55e 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/App.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/App.kt @@ -22,6 +22,7 @@ import coil.ImageLoader import coil.ImageLoaderFactory import coil.decode.GifDecoder import coil.decode.ImageDecoderDecoder +import coil.disk.DiskCache import coil.util.DebugLogger import com.elvishew.xlog.LogConfiguration import com.elvishew.xlog.LogLevel @@ -35,8 +36,8 @@ import com.google.firebase.analytics.ktx.analytics import com.google.firebase.ktx.Firebase import com.ms_square.debugoverlay.DebugOverlay import com.ms_square.debugoverlay.modules.FpsModule -import eu.kanade.tachiyomi.data.coil.ByteBufferFetcher import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher +import eu.kanade.tachiyomi.data.coil.MangaCoverKeyer import eu.kanade.tachiyomi.data.coil.TachiyomiImageDecoder import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.preference.PreferenceValues @@ -150,17 +151,20 @@ open class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory { override fun newImageLoader(): ImageLoader { return ImageLoader.Builder(this).apply { - componentRegistry { + val callFactoryInit = { Injekt.get().client } + val diskCacheInit = { CoilDiskCache.get(this@App) } + components { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - add(ImageDecoderDecoder(this@App)) + add(ImageDecoderDecoder.Factory()) } else { - add(GifDecoder()) + add(GifDecoder.Factory()) } - add(TachiyomiImageDecoder(this@App.resources)) - add(ByteBufferFetcher()) - add(MangaCoverFetcher()) + add(TachiyomiImageDecoder.Factory()) + add(MangaCoverFetcher.Factory(lazy(callFactoryInit), lazy(diskCacheInit))) + add(MangaCoverKeyer()) } - okHttpClient(Injekt.get().coilClient) + callFactory(callFactoryInit) + diskCache(diskCacheInit) crossfade((300 * this@App.animatorDurationScale).toInt()) allowRgb565(getSystemService()!!.isLowRamDevice) if (preferences.verboseLogging()) logger(DebugLogger()) @@ -296,3 +300,24 @@ open class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory { } private const val ACTION_DISABLE_INCOGNITO_MODE = "tachi.action.DISABLE_INCOGNITO_MODE" + +/** + * Direct copy of Coil's internal SingletonDiskCache so that [MangaCoverFetcher] can access it. + */ +internal object CoilDiskCache { + + private const val FOLDER_NAME = "image_cache" + private var instance: DiskCache? = null + + @Synchronized + fun get(context: Context): DiskCache { + return instance ?: run { + val safeCacheDir = context.cacheDir.apply { mkdirs() } + // Create the singleton disk cache instance. + DiskCache.Builder() + .directory(safeCacheDir.resolve(FOLDER_NAME)) + .build() + .also { instance = it } + } + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.kt b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.kt index fbdfc52bd..123d697a7 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.kt @@ -104,7 +104,7 @@ class CoverCache(private val context: Context) { * Clear coil's memory cache. */ fun clearMemoryCache() { - context.imageLoader.memoryCache.clear() + context.imageLoader.memoryCache?.clear() } private fun getCacheDir(dir: String): File { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/coil/ByteBufferFetcher.kt b/app/src/main/java/eu/kanade/tachiyomi/data/coil/ByteBufferFetcher.kt deleted file mode 100644 index 78d9c7ecd..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/coil/ByteBufferFetcher.kt +++ /dev/null @@ -1,25 +0,0 @@ -package eu.kanade.tachiyomi.data.coil - -import coil.bitmap.BitmapPool -import coil.decode.DataSource -import coil.decode.Options -import coil.fetch.FetchResult -import coil.fetch.Fetcher -import coil.fetch.SourceResult -import coil.size.Size -import okio.buffer -import okio.source -import java.io.ByteArrayInputStream -import java.nio.ByteBuffer - -class ByteBufferFetcher : Fetcher { - override suspend fun fetch(pool: BitmapPool, data: ByteBuffer, size: Size, options: Options): FetchResult { - return SourceResult( - source = ByteArrayInputStream(data.array()).source().buffer(), - mimeType = null, - dataSource = DataSource.MEMORY - ) - } - - override fun key(data: ByteBuffer): String? = null -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/coil/MangaCoverFetcher.kt b/app/src/main/java/eu/kanade/tachiyomi/data/coil/MangaCoverFetcher.kt index 7dab6c7da..49be61061 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/coil/MangaCoverFetcher.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/coil/MangaCoverFetcher.kt @@ -1,18 +1,18 @@ package eu.kanade.tachiyomi.data.coil -import coil.bitmap.BitmapPool +import coil.ImageLoader import coil.decode.DataSource -import coil.decode.Options +import coil.decode.ImageSource +import coil.disk.DiskCache import coil.fetch.FetchResult import coil.fetch.Fetcher import coil.fetch.SourceResult import coil.network.HttpException -import coil.request.get -import coil.size.Size +import coil.request.Options +import coil.request.Parameters import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher.Companion.USE_CUSTOM_COVER import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.online.HttpSource @@ -20,130 +20,181 @@ import okhttp3.CacheControl import okhttp3.Call import okhttp3.Request import okhttp3.Response -import okhttp3.ResponseBody -import okio.buffer -import okio.sink -import okio.source -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get +import okhttp3.internal.closeQuietly +import okio.Path.Companion.toOkioPath import uy.kohesive.injekt.injectLazy import java.io.File +import java.net.HttpURLConnection /** - * Coil component that fetches [Manga] cover while using the cached file in disk when available. + * A [Fetcher] that fetches cover image for [Manga] object. + * + * It uses [Manga.thumbnail_url] if custom cover is not set by the user. + * Disk caching for library items is handled by [CoverCache], otherwise + * handled by Coil's [DiskCache]. * * Available request parameter: * - [USE_CUSTOM_COVER]: Use custom cover if set by user, default is true */ -class MangaCoverFetcher : Fetcher { - private val coverCache: CoverCache by injectLazy() - private val sourceManager: SourceManager by injectLazy() - private val defaultClient = Injekt.get().coilClient +class MangaCoverFetcher( + private val manga: Manga, + private val sourceLazy: Lazy, + private val options: Options, + private val coverCache: CoverCache, + private val callFactoryLazy: Lazy, + private val diskCacheLazy: Lazy +) : Fetcher { - override fun key(data: Manga): String? { - if (data.thumbnail_url.isNullOrBlank()) return null - return data.thumbnail_url!! - } + // For non-custom cover + private val diskCacheKey: String? by lazy { MangaCoverKeyer().key(manga, options) } + private lateinit var url: String - override suspend fun fetch(pool: BitmapPool, data: Manga, size: Size, options: Options): FetchResult { + override suspend fun fetch(): FetchResult { // Use custom cover if exists - val useCustomCover = options.parameters[USE_CUSTOM_COVER] as? Boolean ?: true - val customCoverFile = coverCache.getCustomCoverFile(data) + val useCustomCover = options.parameters.value(USE_CUSTOM_COVER) ?: true + val customCoverFile = coverCache.getCustomCoverFile(manga) if (useCustomCover && customCoverFile.exists()) { return fileLoader(customCoverFile) } - val cover = data.thumbnail_url - return when (getResourceType(cover)) { - Type.URL -> httpLoader(data, options) - Type.File -> fileLoader(data) + // diskCacheKey is thumbnail_url + url = diskCacheKey ?: error("No cover specified") + return when (getResourceType(url)) { + Type.URL -> httpLoader() + Type.File -> fileLoader(File(url.substringAfter("file://"))) null -> error("Invalid image") } } - private suspend fun httpLoader(manga: Manga, options: Options): FetchResult { + private fun fileLoader(file: File): FetchResult { + return SourceResult( + source = ImageSource(file = file.toOkioPath(), diskCacheKey = diskCacheKey), + mimeType = "image/*", + dataSource = DataSource.DISK + ) + } + + private suspend fun httpLoader(): FetchResult { // Only cache separately if it's a library item val coverCacheFile = if (manga.favorite) { coverCache.getCoverFile(manga) ?: error("No cover specified") } else { null } - if (coverCacheFile?.exists() == true && options.diskCachePolicy.readEnabled) { return fileLoader(coverCacheFile) } - val (response, body) = awaitGetCall(manga, options) - if (!response.isSuccessful) { - body.close() + var snapshot = readFromDiskCache() + try { + // Fetch from disk cache + if (snapshot != null) { + return SourceResult( + source = snapshot.toImageSource(), + mimeType = "image/*", + dataSource = DataSource.DISK + ) + } + + // Fetch from network + val response = executeNetworkRequest() + val responseBody = checkNotNull(response.body) { "Null response source" } + try { + snapshot = writeToDiskCache(snapshot, response) + // Read from disk cache + if (snapshot != null) { + return SourceResult( + source = snapshot.toImageSource(), + mimeType = "image/*", + dataSource = DataSource.NETWORK + ) + } + + // Read from response if cache is unused or unusable + return SourceResult( + source = ImageSource(source = responseBody.source(), context = options.context), + mimeType = "image/*", + dataSource = if (response.cacheResponse != null) DataSource.DISK else DataSource.NETWORK + ) + } catch (e: Exception) { + responseBody.closeQuietly() + throw e + } finally { + response.close() + } + } catch (e: Exception) { + snapshot?.closeQuietly() + throw e + } + } + + private suspend fun executeNetworkRequest(): Response { + val client = sourceLazy.value?.client ?: callFactoryLazy.value + val response = client.newCall(newRequest()).await() + if (!response.isSuccessful && response.code != HttpURLConnection.HTTP_NOT_MODIFIED) { + response.body?.closeQuietly() throw HttpException(response) } + return response + } - if (coverCacheFile != null && options.diskCachePolicy.writeEnabled) { - @Suppress("BlockingMethodInNonBlockingContext") - response.peekBody(Long.MAX_VALUE).source().use { input -> - coverCacheFile.parentFile?.mkdirs() - if (coverCacheFile.exists()) { - coverCacheFile.delete() - } - coverCacheFile.sink().buffer().use { output -> - output.writeAll(input) - } + private fun newRequest(): Request { + val request = Request.Builder() + .url(url) + .headers(options.headers) + // Support attaching custom data to the network request. + .tag(Parameters::class.java, options.parameters) + + val diskRead = options.diskCachePolicy.readEnabled + val networkRead = options.networkCachePolicy.readEnabled + when { + !networkRead && diskRead -> { + request.cacheControl(CacheControl.FORCE_CACHE) + } + networkRead && !diskRead -> if (options.diskCachePolicy.writeEnabled) { + request.cacheControl(CacheControl.FORCE_NETWORK) + } else { + request.cacheControl(CACHE_CONTROL_FORCE_NETWORK_NO_CACHE) + } + !networkRead && !diskRead -> { + // This causes the request to fail with a 504 Unsatisfiable Request. + request.cacheControl(CACHE_CONTROL_NO_NETWORK_NO_CACHE) } } - return SourceResult( - source = body.source(), - mimeType = "image/*", - dataSource = if (response.cacheResponse != null) DataSource.DISK else DataSource.NETWORK - ) + return request.build() } - private suspend fun awaitGetCall(manga: Manga, options: Options): Pair { - val call = getCall(manga, options) - val response = call.await() - return response to checkNotNull(response.body) { "Null response source" } + private fun readFromDiskCache(): DiskCache.Snapshot? { + return if (options.diskCachePolicy.readEnabled) diskCacheLazy.value[diskCacheKey!!] else null } - private fun getCall(manga: Manga, options: Options): Call { - val source = sourceManager.get(manga.source) as? HttpSource - val request = Request.Builder().url(manga.thumbnail_url!!).also { - if (source != null) { - it.headers(source.headers) + private fun writeToDiskCache(snapshot: DiskCache.Snapshot?, response: Response): DiskCache.Snapshot? { + if (!options.diskCachePolicy.writeEnabled) { + snapshot?.closeQuietly() + return null + } + val editor = if (snapshot != null) { + snapshot.closeAndEdit() + } else { + diskCacheLazy.value.edit(diskCacheKey!!) + } ?: return null + try { + diskCacheLazy.value.fileSystem.write(editor.data) { + response.body!!.source().readAll(this) } - - val networkRead = options.networkCachePolicy.readEnabled - val diskRead = options.diskCachePolicy.readEnabled - when { - !networkRead && diskRead -> { - it.cacheControl(CacheControl.FORCE_CACHE) - } - networkRead && !diskRead -> if (options.diskCachePolicy.writeEnabled) { - it.cacheControl(CacheControl.FORCE_NETWORK) - } else { - it.cacheControl(CACHE_CONTROL_FORCE_NETWORK_NO_CACHE) - } - !networkRead && !diskRead -> { - // This causes the request to fail with a 504 Unsatisfiable Request. - it.cacheControl(CACHE_CONTROL_NO_NETWORK_NO_CACHE) - } + return editor.commitAndGet() + } catch (e: Exception) { + try { + editor.abort() + } catch (ignored: Exception) { } - }.build() - - val client = source?.client?.newBuilder()?.cache(defaultClient.cache)?.build() ?: defaultClient - return client.newCall(request) + throw e + } } - private fun fileLoader(manga: Manga): FetchResult { - return fileLoader(File(manga.thumbnail_url!!.substringAfter("file://"))) - } - - private fun fileLoader(file: File): FetchResult { - return SourceResult( - source = file.source().buffer(), - mimeType = "image/*", - dataSource = DataSource.DISK - ) + private fun DiskCache.Snapshot.toImageSource(): ImageSource { + return ImageSource(file = data, diskCacheKey = diskCacheKey, closeable = this) } private fun getResourceType(cover: String?): Type? { @@ -159,6 +210,20 @@ class MangaCoverFetcher : Fetcher { File, URL } + class Factory( + private val callFactoryLazy: Lazy, + private val diskCacheLazy: Lazy + ) : Fetcher.Factory { + + private val coverCache: CoverCache by injectLazy() + private val sourceManager: SourceManager by injectLazy() + + override fun create(data: Manga, options: Options, imageLoader: ImageLoader): Fetcher { + val source = lazy { sourceManager.get(data.source) as? HttpSource } + return MangaCoverFetcher(data, source, options, coverCache, callFactoryLazy, diskCacheLazy) + } + } + companion object { const val USE_CUSTOM_COVER = "use_custom_cover" diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/coil/MangaCoverKeyer.kt b/app/src/main/java/eu/kanade/tachiyomi/data/coil/MangaCoverKeyer.kt new file mode 100644 index 000000000..6f3ce70ae --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/data/coil/MangaCoverKeyer.kt @@ -0,0 +1,11 @@ +package eu.kanade.tachiyomi.data.coil + +import coil.key.Keyer +import coil.request.Options +import eu.kanade.tachiyomi.data.database.models.Manga + +class MangaCoverKeyer : Keyer { + override fun key(data: Manga, options: Options): String? { + return data.thumbnail_url?.takeIf { it.isNotBlank() } + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/coil/TachiyomiImageDecoder.kt b/app/src/main/java/eu/kanade/tachiyomi/data/coil/TachiyomiImageDecoder.kt index 7847e6f4f..b8545b963 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/coil/TachiyomiImageDecoder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/coil/TachiyomiImageDecoder.kt @@ -1,13 +1,14 @@ package eu.kanade.tachiyomi.data.coil -import android.content.res.Resources import android.os.Build import androidx.core.graphics.drawable.toDrawable -import coil.bitmap.BitmapPool +import coil.ImageLoader import coil.decode.DecodeResult import coil.decode.Decoder -import coil.decode.Options -import coil.size.Size +import coil.decode.ImageDecoderDecoder +import coil.decode.ImageSource +import coil.fetch.SourceResult +import coil.request.Options import eu.kanade.tachiyomi.util.system.ImageUtil import okio.BufferedSource import tachiyomi.decoder.ImageDecoder @@ -15,26 +16,10 @@ import tachiyomi.decoder.ImageDecoder /** * A [Decoder] that uses built-in [ImageDecoder] to decode images that is not supported by the system. */ -class TachiyomiImageDecoder(private val resources: Resources) : Decoder { +class TachiyomiImageDecoder(private val resources: ImageSource, private val options: Options) : Decoder { - override fun handles(source: BufferedSource, mimeType: String?): Boolean { - val type = source.peek().inputStream().use { - ImageUtil.findImageType(it) - } - return when (type) { - ImageUtil.ImageType.AVIF, ImageUtil.ImageType.JXL -> true - ImageUtil.ImageType.HEIF -> Build.VERSION.SDK_INT < Build.VERSION_CODES.O - else -> false - } - } - - override suspend fun decode( - pool: BitmapPool, - source: BufferedSource, - size: Size, - options: Options - ): DecodeResult { - val decoder = source.use { + override suspend fun decode(): DecodeResult { + val decoder = resources.sourceOrNull()?.use { ImageDecoder.newInstance(it.inputStream()) } @@ -46,8 +31,31 @@ class TachiyomiImageDecoder(private val resources: Resources) : Decoder { check(bitmap != null) { "Failed to decode image." } return DecodeResult( - drawable = bitmap.toDrawable(resources), + drawable = bitmap.toDrawable(options.context.resources), isSampled = false ) } + + class Factory : Decoder.Factory { + + override fun create(result: SourceResult, options: Options, imageLoader: ImageLoader): Decoder? { + if (!isApplicable(result.source.source())) return null + return TachiyomiImageDecoder(result.source, options) + } + + private fun isApplicable(source: BufferedSource): Boolean { + val type = source.peek().inputStream().use { + ImageUtil.findImageType(it) + } + return when (type) { + ImageUtil.ImageType.AVIF, ImageUtil.ImageType.JXL -> true + ImageUtil.ImageType.HEIF -> Build.VERSION.SDK_INT < Build.VERSION_CODES.O + else -> false + } + } + + override fun equals(other: Any?) = other is ImageDecoderDecoder.Factory + + override fun hashCode() = javaClass.hashCode() + } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt index df73fbb9d..b1dfcd52e 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt @@ -1,7 +1,6 @@ package eu.kanade.tachiyomi.network import android.content.Context -import coil.util.CoilUtils import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.network.interceptor.CloudflareInterceptor @@ -50,8 +49,6 @@ import java.util.concurrent.TimeUnit /* SY --> */ open /* SY <-- */val client by lazy { baseClientBuilder.cache(Cache(cacheDir, cacheSize)).build() } - val coilClient by lazy { baseClientBuilder.cache(CoilUtils.createDefaultCache(context)).build() } - /* SY --> */ open /* SY <-- */val cloudflareClient by lazy { client.newBuilder() .addInterceptor(CloudflareInterceptor(context)) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionHolder.kt index fdb9c9e6c..e7afa7ac4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionHolder.kt @@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.ui.browse.extension import android.annotation.SuppressLint import android.view.View import androidx.core.view.isVisible -import coil.clear +import coil.dispose import coil.load import eu.davidea.viewholders.FlexibleViewHolder import eu.kanade.tachiyomi.R @@ -45,7 +45,7 @@ class ExtensionHolder(view: View, val adapter: ExtensionAdapter) : // SY <-- }.uppercase() - binding.icon.clear() + binding.icon.dispose() if (extension is Extension.Available) { binding.icon.load(extension.iconUrl) } else if (extension is Extension.Installed) { 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 c0a446457..844f41ea5 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 @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.latest import android.view.View import androidx.core.view.isVisible -import coil.clear +import coil.dispose import coil.imageLoader import coil.request.CachePolicy import coil.request.ImageRequest @@ -54,10 +54,10 @@ class LatestCardHolder(view: View, adapter: LatestCardAdapter) : } fun setImage(manga: Manga) { - binding.cover.clear() + binding.cover.dispose() if (!manga.thumbnail_url.isNullOrEmpty()) { - val crossfadeDuration = itemView.context.imageLoader.defaults.transition.let { - if (it is CrossfadeTransition) it.durationMillis else 0 + 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) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/process/MigrationProcessHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/process/MigrationProcessHolder.kt index 3785fd6bf..b43206173 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/process/MigrationProcessHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/advanced/process/MigrationProcessHolder.kt @@ -4,7 +4,7 @@ import android.view.View import android.widget.PopupMenu import androidx.core.view.isInvisible import androidx.core.view.isVisible -import coil.clear +import coil.dispose import eu.davidea.viewholders.FlexibleViewHolder import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.DatabaseHelper @@ -16,7 +16,7 @@ import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.util.lang.launchUI -import eu.kanade.tachiyomi.util.view.loadAnyAutoPause +import eu.kanade.tachiyomi.util.view.loadAutoPause import eu.kanade.tachiyomi.util.view.setVectorCompat import exh.source.MERGED_SOURCE_ID import exh.util.executeOnIO @@ -127,7 +127,7 @@ class MigrationProcessHolder( private fun MigrationMangaCardBinding.resetManga() { progress.isVisible = true - thumbnail.clear() + thumbnail.dispose() thumbnail.setImageDrawable(null) title.text = "" mangaSourceLabel.text = "" @@ -138,7 +138,7 @@ class MigrationProcessHolder( private suspend fun MigrationMangaCardBinding.attachManga(manga: Manga, source: Source) { progress.isVisible = false - thumbnail.loadAnyAutoPause(manga) + thumbnail.loadAutoPause(manga) title.text = if (manga.title.isBlank()) { view.context.getString(R.string.unknown) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrationMangaHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrationMangaHolder.kt index a85323da6..97b0f8b46 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrationMangaHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrationMangaHolder.kt @@ -1,8 +1,8 @@ package eu.kanade.tachiyomi.ui.browse.migration.manga import android.view.View -import coil.clear -import coil.loadAny +import coil.dispose +import coil.load import eu.davidea.viewholders.FlexibleViewHolder import eu.kanade.tachiyomi.databinding.SourceListItemBinding @@ -23,7 +23,7 @@ class MigrationMangaHolder( binding.title.text = item.manga.originalTitle // Update the cover - binding.thumbnail.clear() - binding.thumbnail.loadAny(item.manga) + binding.thumbnail.dispose() + binding.thumbnail.load(item.manga) } } 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 967ffc284..bd156eecd 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 @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.ui.browse.source.browse import androidx.core.view.isVisible -import coil.clear +import coil.dispose import coil.imageLoader import coil.request.ImageRequest import coil.transition.CrossfadeTransition @@ -66,10 +66,10 @@ class SourceComfortableGridHolder( // SY <-- override fun setImage(manga: Manga) { - binding.thumbnail.clear() + binding.thumbnail.dispose() if (!manga.thumbnail_url.isNullOrEmpty()) { - val crossfadeDuration = binding.root.context.imageLoader.defaults.transition.let { - if (it is CrossfadeTransition) it.durationMillis else 0 + 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) 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 880b3a423..49142f806 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 @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.ui.browse.source.browse import androidx.core.view.isVisible -import coil.clear +import coil.dispose import coil.imageLoader import coil.request.ImageRequest import coil.transition.CrossfadeTransition @@ -66,10 +66,10 @@ class SourceCompactGridHolder( // SY <-- override fun setImage(manga: Manga) { - binding.thumbnail.clear() + binding.thumbnail.dispose() if (!manga.thumbnail_url.isNullOrEmpty()) { - val crossfadeDuration = binding.root.context.imageLoader.defaults.transition.let { - if (it is CrossfadeTransition) it.durationMillis else 0 + 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) 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 7b25aa39e..4336722d1 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 @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.source.browse import android.view.View import androidx.core.view.isVisible -import coil.clear +import coil.dispose import coil.imageLoader import coil.request.CachePolicy import coil.request.ImageRequest @@ -106,10 +106,10 @@ class SourceEnhancedEHentaiListHolder(view: View, adapter: FlexibleAdapter<*>) : // For rounded corners binding.card.clipToOutline = true - binding.thumbnail.clear() + binding.thumbnail.dispose() if (!manga.thumbnail_url.isNullOrEmpty()) { - val crossfadeDuration = itemView.context.imageLoader.defaults.transition.let { - if (it is CrossfadeTransition) it.durationMillis else 0 + 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) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceListHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceListHolder.kt index 722a50587..1b8f82b9c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceListHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceListHolder.kt @@ -2,8 +2,8 @@ package eu.kanade.tachiyomi.ui.browse.source.browse import android.view.View import androidx.core.view.isVisible -import coil.clear -import coil.loadAny +import coil.dispose +import coil.load import eu.davidea.flexibleadapter.FlexibleAdapter import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher @@ -67,9 +67,9 @@ class SourceListHolder(private val view: View, adapter: FlexibleAdapter<*>) : // SY <-- override fun setImage(manga: Manga) { - binding.thumbnail.clear() + binding.thumbnail.dispose() if (!manga.thumbnail_url.isNullOrEmpty()) { - binding.thumbnail.loadAny(manga) { + binding.thumbnail.load(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 a67e9785b..fd31f1005 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 @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.source.globalsearch import android.view.View import androidx.core.view.isVisible -import coil.clear +import coil.dispose import coil.imageLoader import coil.request.ImageRequest import coil.transition.CrossfadeTransition @@ -53,10 +53,10 @@ class GlobalSearchCardHolder(view: View, adapter: GlobalSearchCardAdapter) : } fun setImage(manga: Manga) { - binding.cover.clear() + binding.cover.dispose() if (!manga.thumbnail_url.isNullOrEmpty()) { - val crossfadeDuration = itemView.context.imageLoader.defaults.transition.let { - if (it is CrossfadeTransition) it.durationMillis else 0 + 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) 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 edfca0a6b..fc4650b9c 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 @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.source.index import android.view.View import androidx.core.view.isVisible -import coil.clear +import coil.dispose import coil.imageLoader import coil.request.CachePolicy import coil.request.ImageRequest @@ -54,10 +54,10 @@ class IndexCardHolder(view: View, adapter: IndexCardAdapter) : } fun setImage(manga: Manga) { - binding.cover.clear() + binding.cover.dispose() if (!manga.thumbnail_url.isNullOrEmpty()) { - val crossfadeDuration = itemView.context.imageLoader.defaults.transition.let { - if (it is CrossfadeTransition) it.durationMillis else 0 + 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) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryComfortableGridHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryComfortableGridHolder.kt index 1ae45c48c..d5df15e96 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryComfortableGridHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryComfortableGridHolder.kt @@ -1,11 +1,13 @@ package eu.kanade.tachiyomi.ui.library import androidx.core.view.isVisible -import coil.clear +import androidx.recyclerview.widget.RecyclerView +import coil.dispose import eu.davidea.flexibleadapter.FlexibleAdapter +import eu.davidea.flexibleadapter.items.IFlexible import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.databinding.SourceComfortableGridItemBinding -import eu.kanade.tachiyomi.util.view.loadAnyAutoPause +import eu.kanade.tachiyomi.util.view.loadAutoPause import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import reactivecircus.flowbinding.android.view.clicks @@ -21,7 +23,7 @@ import reactivecircus.flowbinding.android.view.clicks */ class LibraryComfortableGridHolder( override val binding: SourceComfortableGridItemBinding, - adapter: FlexibleAdapter<*> + adapter: FlexibleAdapter> ) : LibraryHolder(binding.root, adapter) { // SY --> @@ -76,8 +78,8 @@ class LibraryComfortableGridHolder( // SY <-- // Update the cover. - binding.thumbnail.clear() - binding.thumbnail.loadAnyAutoPause(item.manga) + binding.thumbnail.dispose() + binding.thumbnail.loadAutoPause(item.manga) } // SY --> diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCompactGridHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCompactGridHolder.kt index 751b03276..e361d360e 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCompactGridHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCompactGridHolder.kt @@ -3,11 +3,11 @@ package eu.kanade.tachiyomi.ui.library import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.isVisible import androidx.core.view.updateLayoutParams -import coil.clear +import coil.dispose import eu.davidea.flexibleadapter.FlexibleAdapter import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.databinding.SourceCompactGridItemBinding -import eu.kanade.tachiyomi.util.view.loadAnyAutoPause +import eu.kanade.tachiyomi.util.view.loadAutoPause import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import reactivecircus.flowbinding.android.view.clicks @@ -98,11 +98,11 @@ class LibraryCompactGridHolder( // SY <-- // Update the cover. - binding.thumbnail.clear() + binding.thumbnail.dispose() if (coverOnly) { // Cover only mode: Hides title text unless thumbnail is unavailable if (!item.manga.thumbnail_url.isNullOrEmpty()) { - binding.thumbnail.loadAnyAutoPause(item.manga) + binding.thumbnail.loadAutoPause(item.manga) binding.title.isVisible = false } else { binding.title.text = item.manga.title @@ -110,7 +110,7 @@ class LibraryCompactGridHolder( } binding.thumbnail.foreground = null } else { - binding.thumbnail.loadAnyAutoPause(item.manga) + binding.thumbnail.loadAutoPause(item.manga) } } 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 92e01e85f..8f746c5c6 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryListHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryListHolder.kt @@ -2,8 +2,8 @@ package eu.kanade.tachiyomi.ui.library import android.view.View import androidx.core.view.isVisible -import coil.clear -import coil.loadAny +import coil.dispose +import coil.load import eu.davidea.flexibleadapter.FlexibleAdapter import eu.kanade.tachiyomi.databinding.SourceListItemBinding @@ -61,7 +61,7 @@ class LibraryListHolder( } // Update the cover - binding.thumbnail.clear() - binding.thumbnail.loadAny(item.manga) + binding.thumbnail.dispose() + binding.thumbnail.load(item.manga) } } 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 1b9637946..055249326 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 @@ -9,7 +9,7 @@ import android.widget.ScrollView import androidx.core.content.ContextCompat import androidx.core.os.bundleOf import androidx.core.view.children -import coil.loadAny +import coil.load import coil.transform.RoundedCornersTransformation import com.google.android.material.chip.Chip import com.google.android.material.chip.ChipGroup @@ -170,7 +170,7 @@ class EditMangaDialog : DialogController { fun loadCover() { val radius = context.resources.getDimension(R.dimen.card_radius) - binding.mangaCover.loadAny(manga) { + binding.mangaCover.load(manga) { transformations(RoundedCornersTransformation(radius)) } } @@ -178,7 +178,7 @@ class EditMangaDialog : DialogController { fun updateCover(uri: Uri) { willResetCover = false val radius = context.resources.getDimension(R.dimen.card_radius) - binding.mangaCover.loadAny(uri) { + binding.mangaCover.load(uri) { transformations(RoundedCornersTransformation(radius)) } customCoverUri = uri diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt index d97957189..996d70f35 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt @@ -667,7 +667,7 @@ class MangaPresenter( * @return cover as Bitmap or null if there is no thumbnail cached with the memoryCacheKey */ private fun coverBitmapFromImageLoader(context: Context, memoryCacheKey: MemoryCache.Key): Bitmap? { - return context.imageLoader.memoryCache[memoryCacheKey] + return context.imageLoader.memoryCache?.get(memoryCacheKey)?.bitmap } /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt index ab457e3bb..27d202ba8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt @@ -21,7 +21,7 @@ import eu.kanade.tachiyomi.source.online.MetadataSource import eu.kanade.tachiyomi.ui.base.controller.getMainAppBarHeight import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.util.system.copyToClipboard -import eu.kanade.tachiyomi.util.view.loadAnyAutoPause +import eu.kanade.tachiyomi.util.view.loadAutoPause import exh.merged.sql.models.MergedMangaReference import exh.metadata.metadata.base.RaisedSearchMetadata import exh.source.MERGED_SOURCE_ID @@ -358,8 +358,8 @@ class MangaInfoHeaderAdapter( setFavoriteButtonState(manga.favorite) // Set cover if changed. - binding.backdrop.loadAnyAutoPause(manga) - binding.mangaCover.loadAnyAutoPause(manga) + binding.backdrop.loadAutoPause(manga) + binding.mangaCover.loadAutoPause(manga) // Manga info section // SY --> diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/merged/EditMergedMangaHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/merged/EditMergedMangaHolder.kt index 4dd42f82f..a0b8e5b2b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/merged/EditMergedMangaHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/merged/EditMergedMangaHolder.kt @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.ui.manga.merged import android.view.View -import coil.loadAny +import coil.load import coil.transform.RoundedCornersTransformation import eu.davidea.viewholders.FlexibleViewHolder import eu.kanade.tachiyomi.R @@ -40,7 +40,7 @@ class EditMergedMangaHolder(view: View, val adapter: EditMergedMangaAdapter) : F reference = item.mergedMangaReference item.mergedManga?.let { val radius = itemView.context.resources.getDimension(R.dimen.card_radius) - binding.cover.loadAny(it) { + binding.cover.load(it) { transformations(RoundedCornersTransformation(radius)) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSearchHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSearchHolder.kt index 4183a93ea..beabf2ebe 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSearchHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSearchHolder.kt @@ -2,8 +2,8 @@ package eu.kanade.tachiyomi.ui.manga.track import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView -import coil.clear -import coil.loadAny +import coil.dispose +import coil.load import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.databinding.TrackSearchItemBinding import java.util.Locale @@ -20,9 +20,9 @@ class TrackSearchHolder( } binding.trackSearchTitle.text = track.title - binding.trackSearchCover.clear() + binding.trackSearchCover.dispose() if (track.cover_url.isNotEmpty()) { - binding.trackSearchCover.loadAny(track.cover_url) + binding.trackSearchCover.load(track.cover_url) } val hasStatus = track.publishing_status.isNotBlank() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderPageImageView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderPageImageView.kt index f60e91158..6a1a2bbe6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderPageImageView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderPageImageView.kt @@ -17,7 +17,7 @@ import androidx.annotation.CallSuper import androidx.annotation.StyleRes import androidx.appcompat.widget.AppCompatImageView import androidx.core.view.isVisible -import coil.clear +import coil.dispose import coil.imageLoader import coil.request.CachePolicy import coil.request.ImageRequest @@ -152,7 +152,7 @@ open class ReaderPageImageView @JvmOverloads constructor( fun recycle() = pageView?.let { when (it) { is SubsamplingScaleImageView -> it.recycle() - is AppCompatImageView -> it.clear() + is AppCompatImageView -> it.dispose() } it.isVisible = false } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryHolder.kt index a3ac1dea3..6ef3a38cd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryHolder.kt @@ -1,8 +1,8 @@ package eu.kanade.tachiyomi.ui.recent.history import android.view.View -import coil.clear -import coil.loadAny +import coil.dispose +import coil.load import eu.davidea.viewholders.FlexibleViewHolder import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory @@ -65,7 +65,7 @@ class HistoryHolder( } // Set cover - binding.cover.clear() - binding.cover.loadAny(item.manga) + binding.cover.dispose() + binding.cover.load(item.manga) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesHolder.kt index 76bb24bda..8fcdd22e0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesHolder.kt @@ -2,8 +2,8 @@ package eu.kanade.tachiyomi.ui.recent.updates import android.view.View import androidx.core.view.isVisible -import coil.clear -import coil.loadAny +import coil.dispose +import coil.load import eu.kanade.tachiyomi.databinding.UpdatesItemBinding import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.ui.manga.chapter.base.BaseChapterHolder @@ -58,7 +58,7 @@ class UpdatesHolder(private val view: View, private val adapter: UpdatesAdapter) binding.download.setState(item.status, item.progress) // Set cover - binding.mangaCover.clear() - binding.mangaCover.loadAny(item.manga) + binding.mangaCover.dispose() + binding.mangaCover.load(item.manga) } } 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 3bca8603c..a8fddfd39 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 @@ -8,7 +8,7 @@ import androidx.annotation.DrawableRes import androidx.appcompat.content.res.AppCompatResources import coil.ImageLoader import coil.imageLoader -import coil.loadAny +import coil.load import coil.request.ImageRequest import coil.target.ImageViewTarget import eu.kanade.tachiyomi.util.system.animatorDurationScale @@ -33,12 +33,13 @@ fun ImageView.setVectorCompat(@DrawableRes drawable: Int, @AttrRes tint: Int? = * and if the image is animated, this will also disable that animation * if [Context.animatorDurationScale] is 0 */ -fun ImageView.loadAnyAutoPause( +fun ImageView.loadAutoPause( data: Any?, loader: ImageLoader = context.imageLoader, builder: ImageRequest.Builder.() -> Unit = {} ) { - this.loadAny(data, loader) { + // Build the original request so we can add on our success listener + load(data, loader) { // Build the original request so we can add on our success listener val originalBuild = apply(builder).build() listener( diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 230e41f07..e936bcbe9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ aboutlib_version = "8.9.4" okhttp_version = "4.9.1" nucleus_version = "3.0.0" -coil_version = "1.4.0" +coil_version = "2.0.0-rc01" conductor_version = "3.1.2" flowbinding_version = "1.2.0" shizuku_version = "12.1.0"