From f72b6e4d7c1f2f93d705402e4d80c94160bef54d Mon Sep 17 00:00:00 2001 From: AntsyLich <59261191+AntsyLich@users.noreply.github.com> Date: Sat, 2 Mar 2024 20:08:15 +0600 Subject: [PATCH] Switch to Coil3 Co-authored-by: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com> --- app/build.gradle.kts | 2 +- .../browse/components/BrowseIcons.kt | 2 +- .../manga/components/MangaCover.kt | 2 +- .../manga/components/MangaCoverDialog.kt | 12 ++-- .../manga/components/MangaInfoHeader.kt | 2 +- app/src/main/java/eu/kanade/tachiyomi/App.kt | 36 +++++----- .../tachiyomi/data/coil/MangaCoverFetcher.kt | 70 +++++++++++-------- .../tachiyomi/data/coil/MangaCoverKeyer.kt | 4 +- .../data/coil/TachiyomiImageDecoder.kt | 22 +++--- .../data/library/LibraryUpdateNotifier.kt | 9 +-- .../ui/manga/MangaCoverScreenModel.kt | 8 +-- .../tachiyomi/ui/reader/SaveImageNotifier.kt | 8 +-- .../ui/reader/viewer/ReaderPageImageView.kt | 11 +-- .../util/system/DrawableExtensions.kt | 2 +- gradle.properties | 2 +- gradle/libs.versions.toml | 11 +-- presentation-core/build.gradle.kts | 2 +- .../widget/BaseUpdatesGridGlanceWidget.kt | 23 +++--- 18 files changed, 124 insertions(+), 104 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c250b0f31..4147d11af 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -284,7 +284,7 @@ tasks { "-opt-in=androidx.compose.foundation.ExperimentalFoundationApi", "-opt-in=androidx.compose.animation.ExperimentalAnimationApi", "-opt-in=androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi", - "-opt-in=coil.annotation.ExperimentalCoilApi", + "-opt-in=coil3.annotation.ExperimentalCoilApi", "-opt-in=com.google.accompanist.permissions.ExperimentalPermissionsApi", "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", "-opt-in=kotlinx.coroutines.FlowPreview", diff --git a/app/src/main/java/eu/kanade/presentation/browse/components/BrowseIcons.kt b/app/src/main/java/eu/kanade/presentation/browse/components/BrowseIcons.kt index b4710fc40..950b55192 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/components/BrowseIcons.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/components/BrowseIcons.kt @@ -25,7 +25,7 @@ import androidx.compose.ui.res.imageResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import androidx.core.graphics.drawable.toBitmap -import coil.compose.AsyncImage +import coil3.compose.AsyncImage import eu.kanade.domain.source.model.icon import eu.kanade.presentation.util.rememberResourceBitmapPainter import eu.kanade.tachiyomi.R diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/MangaCover.kt b/app/src/main/java/eu/kanade/presentation/manga/components/MangaCover.kt index cfb4f5fcb..4fb1cf87b 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/MangaCover.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/MangaCover.kt @@ -11,7 +11,7 @@ import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.painter.ColorPainter import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.semantics.Role -import coil.compose.AsyncImage +import coil3.compose.AsyncImage import eu.kanade.presentation.util.rememberResourceBitmapPainter import eu.kanade.tachiyomi.R diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/MangaCoverDialog.kt b/app/src/main/java/eu/kanade/presentation/manga/components/MangaCoverDialog.kt index a71d08674..a70511326 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/MangaCoverDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/MangaCoverDialog.kt @@ -37,10 +37,10 @@ import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import androidx.core.view.updatePadding -import coil.imageLoader -import coil.request.CachePolicy -import coil.request.ImageRequest -import coil.size.Size +import coil3.imageLoader +import coil3.request.CachePolicy +import coil3.request.ImageRequest +import coil3.size.Size import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBarActions import eu.kanade.presentation.components.DropdownMenu @@ -168,7 +168,9 @@ fun MangaCoverDialog( .data(coverDataProvider()) .size(Size.ORIGINAL) .memoryCachePolicy(CachePolicy.DISABLED) - .target { drawable -> + .target { image -> + val drawable = image.asDrawable(view.context.resources) + // Copy bitmap in case it came from memory cache // Because SSIV needs to thoroughly read the image val copy = (drawable as? BitmapDrawable)?.let { diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/MangaInfoHeader.kt b/app/src/main/java/eu/kanade/presentation/manga/components/MangaInfoHeader.kt index 0ad66a9a8..ac4946c99 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/MangaInfoHeader.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/MangaInfoHeader.kt @@ -73,7 +73,7 @@ import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import coil.compose.AsyncImage +import coil3.compose.AsyncImage import eu.kanade.presentation.components.DropdownMenu import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.source.model.SManga diff --git a/app/src/main/java/eu/kanade/tachiyomi/App.kt b/app/src/main/java/eu/kanade/tachiyomi/App.kt index dfe5dad41..6c29060c1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/App.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/App.kt @@ -15,12 +15,14 @@ import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.ProcessLifecycleOwner import androidx.lifecycle.lifecycleScope -import coil.ImageLoader -import coil.ImageLoaderFactory -import coil.decode.GifDecoder -import coil.decode.ImageDecoderDecoder -import coil.disk.DiskCache -import coil.util.DebugLogger +import coil3.ImageLoader +import coil3.SingletonImageLoader +import coil3.disk.DiskCache +import coil3.disk.directory +import coil3.network.okhttp.OkHttpNetworkFetcherFactory +import coil3.request.allowRgb565 +import coil3.request.crossfade +import coil3.util.DebugLogger import eu.kanade.domain.DomainModule import eu.kanade.domain.base.BasePreferences import eu.kanade.domain.ui.UiPreferences @@ -58,7 +60,7 @@ import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy import java.security.Security -class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory { +class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factory { private val basePreferences: BasePreferences by injectLazy() private val networkPreferences: NetworkPreferences by injectLazy() @@ -131,24 +133,19 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory { } } - override fun newImageLoader(): ImageLoader { + override fun newImageLoader(context: Context): ImageLoader { return ImageLoader.Builder(this).apply { - val callFactoryInit = { Injekt.get().client } - val diskCacheInit = { CoilDiskCache.get(this@App) } + val callFactoryLazy = lazy { Injekt.get().client } + val diskCacheLazy = lazy { CoilDiskCache.get(this@App) } components { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - add(ImageDecoderDecoder.Factory()) - } else { - add(GifDecoder.Factory()) - } + add(OkHttpNetworkFetcherFactory(callFactoryLazy::value)) add(TachiyomiImageDecoder.Factory()) - add(MangaCoverFetcher.MangaFactory(lazy(callFactoryInit), lazy(diskCacheInit))) - add(MangaCoverFetcher.MangaCoverFactory(lazy(callFactoryInit), lazy(diskCacheInit))) + add(MangaCoverFetcher.MangaFactory(callFactoryLazy, diskCacheLazy)) + add(MangaCoverFetcher.MangaCoverFactory(callFactoryLazy, diskCacheLazy)) add(MangaKeyer()) add(MangaCoverKeyer()) } - callFactory(callFactoryInit) - diskCache(diskCacheInit) + diskCache(diskCacheLazy::value) crossfade((300 * this@App.animatorDurationScale).toInt()) allowRgb565(DeviceUtil.isLowRamDevice(this@App)) if (networkPreferences.verboseLogging().get()) logger(DebugLogger()) @@ -156,7 +153,6 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory { // Coil spawns a new thread for every image load by default fetcherDispatcher(Dispatchers.IO.limitedParallelism(8)) decoderDispatcher(Dispatchers.IO.limitedParallelism(2)) - transformationDispatcher(Dispatchers.IO.limitedParallelism(2)) }.build() } 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 978f65bc9..a3d1061ef 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,19 +1,18 @@ package eu.kanade.tachiyomi.data.coil import androidx.core.net.toUri -import coil.ImageLoader -import coil.decode.DataSource -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.Options -import coil.request.Parameters +import coil3.Extras +import coil3.ImageLoader +import coil3.decode.DataSource +import coil3.decode.ImageSource +import coil3.disk.DiskCache +import coil3.fetch.FetchResult +import coil3.fetch.Fetcher +import coil3.fetch.SourceFetchResult +import coil3.getOrDefault +import coil3.request.Options import com.hippo.unifile.UniFile import eu.kanade.tachiyomi.data.cache.CoverCache -import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher.Companion.USE_CUSTOM_COVER import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.source.online.HttpSource import logcat.LogPriority @@ -22,6 +21,7 @@ import okhttp3.Call import okhttp3.Request import okhttp3.Response import okhttp3.internal.http.HTTP_NOT_MODIFIED +import okio.FileSystem import okio.Path.Companion.toOkioPath import okio.Source import okio.buffer @@ -42,7 +42,7 @@ import java.io.File * handled by Coil's [DiskCache]. * * Available request parameter: - * - [USE_CUSTOM_COVER]: Use custom cover if set by user, default is true + * - [USE_CUSTOM_COVER_KEY]: Use custom cover if set by user, default is true */ class MangaCoverFetcher( private val url: String?, @@ -61,7 +61,7 @@ class MangaCoverFetcher( override suspend fun fetch(): FetchResult { // Use custom cover if exists - val useCustomCover = options.parameters.value(USE_CUSTOM_COVER) ?: true + val useCustomCover = options.extras.getOrDefault(USE_CUSTOM_COVER_KEY) if (useCustomCover) { val customCoverFile = customCoverFileLazy.value if (customCoverFile.exists()) { @@ -80,8 +80,12 @@ class MangaCoverFetcher( } private fun fileLoader(file: File): FetchResult { - return SourceResult( - source = ImageSource(file = file.toOkioPath(), diskCacheKey = diskCacheKey), + return SourceFetchResult( + source = ImageSource( + file = file.toOkioPath(), + fileSystem = FileSystem.SYSTEM, + diskCacheKey = diskCacheKey + ), mimeType = "image/*", dataSource = DataSource.DISK, ) @@ -92,8 +96,8 @@ class MangaCoverFetcher( .openInputStream() .source() .buffer() - return SourceResult( - source = ImageSource(source = source, context = options.context), + return SourceFetchResult( + source = ImageSource(source = source, fileSystem = FileSystem.SYSTEM), mimeType = "image/*", dataSource = DataSource.DISK, ) @@ -121,7 +125,7 @@ class MangaCoverFetcher( } // Read from snapshot - return SourceResult( + return SourceFetchResult( source = snapshot.toImageSource(), mimeType = "image/*", dataSource = DataSource.DISK, @@ -141,7 +145,7 @@ class MangaCoverFetcher( // Read from disk cache snapshot = writeToDiskCache(response) if (snapshot != null) { - return SourceResult( + return SourceFetchResult( source = snapshot.toImageSource(), mimeType = "image/*", dataSource = DataSource.NETWORK, @@ -149,8 +153,8 @@ class MangaCoverFetcher( } // Read from response if cache is unused or unusable - return SourceResult( - source = ImageSource(source = responseBody.source(), context = options.context), + return SourceFetchResult( + source = ImageSource(source = responseBody.source(), fileSystem = FileSystem.SYSTEM), mimeType = "image/*", dataSource = if (response.cacheResponse != null) DataSource.DISK else DataSource.NETWORK, ) @@ -169,17 +173,20 @@ class MangaCoverFetcher( val response = client.newCall(newRequest()).await() if (!response.isSuccessful && response.code != HTTP_NOT_MODIFIED) { response.close() - throw HttpException(response) + throw Exception(response.message) } return response } private fun newRequest(): Request { - val request = Request.Builder() - .url(url!!) - .headers(sourceLazy.value?.headers ?: options.headers) - // Support attaching custom data to the network request. - .tag(Parameters::class.java, options.parameters) + val request = Request.Builder().apply { + url(url!!) + + val sourceHeaders = sourceLazy.value?.headers + if (sourceHeaders != null) { + headers(sourceHeaders) + } + } when { options.networkCachePolicy.readEnabled -> { @@ -264,7 +271,12 @@ class MangaCoverFetcher( } private fun DiskCache.Snapshot.toImageSource(): ImageSource { - return ImageSource(file = data, diskCacheKey = diskCacheKey, closeable = this) + return ImageSource( + file = data, + fileSystem = FileSystem.SYSTEM, + diskCacheKey = diskCacheKey, + closeable = this, + ) } private fun getResourceType(cover: String?): Type? { @@ -330,7 +342,7 @@ class MangaCoverFetcher( } companion object { - const val USE_CUSTOM_COVER = "use_custom_cover" + val USE_CUSTOM_COVER_KEY = Extras.Key(true) private val CACHE_CONTROL_NO_STORE = CacheControl.Builder().noStore().build() private val CACHE_CONTROL_NO_NETWORK_NO_CACHE = CacheControl.Builder().noCache().onlyIfCached().build() 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 index bc85b22f4..56e0291aa 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/coil/MangaCoverKeyer.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/coil/MangaCoverKeyer.kt @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.data.coil -import coil.key.Keyer -import coil.request.Options +import coil3.key.Keyer +import coil3.request.Options import eu.kanade.domain.manga.model.hasCustomCover import eu.kanade.tachiyomi.data.cache.CoverCache import tachiyomi.domain.manga.model.MangaCover 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 acbda8cc5..3f6c13906 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,13 @@ package eu.kanade.tachiyomi.data.coil -import androidx.core.graphics.drawable.toDrawable -import coil.ImageLoader -import coil.decode.DecodeResult -import coil.decode.Decoder -import coil.decode.ImageDecoderDecoder -import coil.decode.ImageSource -import coil.fetch.SourceResult -import coil.request.Options +import coil3.ImageLoader +import coil3.asCoilImage +import coil3.decode.DecodeResult +import coil3.decode.Decoder +import coil3.decode.ImageSource +import coil3.fetch.SourceFetchResult +import coil3.request.Options +import coil3.request.allowRgb565 import okio.BufferedSource import tachiyomi.core.common.util.system.ImageUtil import tachiyomi.decoder.ImageDecoder @@ -30,14 +30,14 @@ class TachiyomiImageDecoder(private val resources: ImageSource, private val opti check(bitmap != null) { "Failed to decode image" } return DecodeResult( - drawable = bitmap.toDrawable(options.context.resources), + image = bitmap.asCoilImage(), isSampled = false, ) } class Factory : Decoder.Factory { - override fun create(result: SourceResult, options: Options, imageLoader: ImageLoader): Decoder? { + override fun create(result: SourceFetchResult, options: Options, imageLoader: ImageLoader): Decoder? { if (!isApplicable(result.source.source())) return null return TachiyomiImageDecoder(result.source, options) } @@ -52,7 +52,7 @@ class TachiyomiImageDecoder(private val resources: ImageSource, private val opti } } - override fun equals(other: Any?) = other is ImageDecoderDecoder.Factory + override fun equals(other: Any?) = other is Factory override fun hashCode() = javaClass.hashCode() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt index 4d13dc724..e18bf76c4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt @@ -9,9 +9,10 @@ import android.graphics.BitmapFactory import android.net.Uri import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat -import coil.imageLoader -import coil.request.ImageRequest -import coil.transform.CircleCropTransformation +import coil3.imageLoader +import coil3.request.ImageRequest +import coil3.request.transformations +import coil3.transform.CircleCropTransformation import eu.kanade.presentation.util.formatChapterNumber import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.core.security.SecurityPreferences @@ -294,7 +295,7 @@ class LibraryUpdateNotifier( .transformations(CircleCropTransformation()) .size(NOTIF_ICON_SIZE) .build() - val drawable = context.imageLoader.execute(request).drawable + val drawable = context.imageLoader.execute(request).image?.asDrawable(context.resources) return drawable?.getBitmapOrNull() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaCoverScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaCoverScreenModel.kt index 3cbfa540b..75a98c5df 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaCoverScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaCoverScreenModel.kt @@ -5,9 +5,9 @@ import android.net.Uri import androidx.compose.material3.SnackbarHostState import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.screenModelScope -import coil.imageLoader -import coil.request.ImageRequest -import coil.size.Size +import coil3.imageLoader +import coil3.request.ImageRequest +import coil3.size.Size import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.saver.Image @@ -96,7 +96,7 @@ class MangaCoverScreenModel( .build() return withIOContext { - val result = context.imageLoader.execute(req).drawable + val result = context.imageLoader.execute(req).image?.asDrawable(context.resources) // TODO: Handle animated cover val bitmap = result?.getBitmapOrNull() ?: return@withIOContext null diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/SaveImageNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/SaveImageNotifier.kt index ab0146a0e..373ed97a8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/SaveImageNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/SaveImageNotifier.kt @@ -4,9 +4,9 @@ import android.content.Context import android.graphics.Bitmap import android.net.Uri import androidx.core.app.NotificationCompat -import coil.imageLoader -import coil.request.CachePolicy -import coil.request.ImageRequest +import coil3.imageLoader +import coil3.request.CachePolicy +import coil3.request.ImageRequest import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.notification.NotificationHandler import eu.kanade.tachiyomi.data.notification.NotificationReceiver @@ -37,7 +37,7 @@ class SaveImageNotifier(private val context: Context) { .memoryCachePolicy(CachePolicy.DISABLED) .size(720, 1280) .target( - onSuccess = { showCompleteNotification(uri, it.getBitmapOrNull()) }, + onSuccess = { showCompleteNotification(uri, it.asDrawable(context.resources).getBitmapOrNull()) }, onError = { onError(null) }, ) .build() 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 c60e404e7..fbb1302e8 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 @@ -18,10 +18,11 @@ import androidx.annotation.StyleRes import androidx.appcompat.widget.AppCompatImageView import androidx.core.os.postDelayed import androidx.core.view.isVisible -import coil.dispose -import coil.imageLoader -import coil.request.CachePolicy -import coil.request.ImageRequest +import coil3.dispose +import coil3.imageLoader +import coil3.request.CachePolicy +import coil3.request.ImageRequest +import coil3.request.crossfade import com.davemorrissey.labs.subscaleview.ImageSource import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView.EASE_IN_OUT_QUAD @@ -348,7 +349,7 @@ open class ReaderPageImageView @JvmOverloads constructor( .diskCachePolicy(CachePolicy.DISABLED) .target( onSuccess = { result -> - setImageDrawable(result) + setImageDrawable(result.asDrawable(context.resources)) (result as? Animatable)?.start() isVisible = true this@ReaderPageImageView.onImageLoaded() diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/DrawableExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/system/DrawableExtensions.kt index 2a09aeca9..2877768af 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/system/DrawableExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/system/DrawableExtensions.kt @@ -4,7 +4,7 @@ import android.graphics.Bitmap import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable import androidx.core.graphics.drawable.toBitmap -import coil.drawable.ScaleDrawable +import coil3.gif.ScaleDrawable fun Drawable.getBitmapOrNull(): Bitmap? = when (this) { is BitmapDrawable -> bitmap diff --git a/gradle.properties b/gradle.properties index 22e7dfed5..2eec6929d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,5 +6,5 @@ kotlin.mpp.androidSourceSetLayoutVersion=2 org.gradle.caching=true org.gradle.configureondemand=true -org.gradle.jvmargs=-Xmx4g -Dfile.encoding=UTF-8 +org.gradle.jvmargs=-Xmx3g -Dfile.encoding=UTF-8 org.gradle.parallel=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5c94f3789..97be75a27 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -43,10 +43,11 @@ preferencektx = "androidx.preference:preference-ktx:1.2.1" injekt-core = "com.github.inorichi.injekt:injekt-core:65b0440" -coil-bom = { module = "io.coil-kt:coil-bom", version = "2.6.0" } -coil-core = { module = "io.coil-kt:coil" } -coil-gif = { module = "io.coil-kt:coil-gif" } -coil-compose = { module = "io.coil-kt:coil-compose" } +coil-bom = { module = "io.coil-kt.coil3:coil-bom", version = "3.0.0-alpha06" } +coil-core = { module = "io.coil-kt.coil3:coil" } +coil-gif = { module = "io.coil-kt.coil3:coil-gif" } +coil-compose = { module = "io.coil-kt.coil3:coil-compose" } +coil-network-okhttp = { module = "io.coil-kt.coil3:coil-network-okhttp" } subsamplingscaleimageview = "com.github.tachiyomiorg:subsampling-scale-image-view:7e57335" image-decoder = "com.github.tachiyomiorg:image-decoder:fbd6601290" @@ -105,7 +106,7 @@ archive = ["common-compress", "junrar"] okhttp = ["okhttp-core", "okhttp-logging", "okhttp-brotli", "okhttp-dnsoverhttps"] js-engine = ["quickjs-android"] sqlite = ["sqlite-framework", "sqlite-ktx", "sqlite-android"] -coil = ["coil-core", "coil-gif", "coil-compose"] +coil = ["coil-core", "coil-gif", "coil-compose", "coil-network-okhttp"] shizuku = ["shizuku-api", "shizuku-provider"] sqldelight = ["sqldelight-android-driver", "sqldelight-coroutines", "sqldelight-android-paging"] voyager = ["voyager-navigator", "voyager-screenmodel", "voyager-tab-navigator", "voyager-transitions"] diff --git a/presentation-core/build.gradle.kts b/presentation-core/build.gradle.kts index cfae8ba2a..e30c5869c 100644 --- a/presentation-core/build.gradle.kts +++ b/presentation-core/build.gradle.kts @@ -52,7 +52,7 @@ tasks { "-opt-in=androidx.compose.foundation.ExperimentalFoundationApi", "-opt-in=androidx.compose.animation.ExperimentalAnimationApi", "-opt-in=androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi", - "-opt-in=coil.annotation.ExperimentalCoilApi", + "-opt-in=coil3.annotation.ExperimentalCoilApi", "-opt-in=kotlinx.coroutines.FlowPreview", ) } diff --git a/presentation-widget/src/main/java/tachiyomi/presentation/widget/BaseUpdatesGridGlanceWidget.kt b/presentation-widget/src/main/java/tachiyomi/presentation/widget/BaseUpdatesGridGlanceWidget.kt index e4977bfd3..4fa7850a8 100644 --- a/presentation-widget/src/main/java/tachiyomi/presentation/widget/BaseUpdatesGridGlanceWidget.kt +++ b/presentation-widget/src/main/java/tachiyomi/presentation/widget/BaseUpdatesGridGlanceWidget.kt @@ -21,13 +21,15 @@ import androidx.glance.background import androidx.glance.layout.fillMaxSize import androidx.glance.layout.padding import androidx.glance.unit.ColorProvider -import coil.executeBlocking -import coil.imageLoader -import coil.request.CachePolicy -import coil.request.ImageRequest -import coil.size.Precision -import coil.size.Scale -import coil.transform.RoundedCornersTransformation +import coil3.annotation.ExperimentalCoilApi +import coil3.executeBlocking +import coil3.imageLoader +import coil3.request.CachePolicy +import coil3.request.ImageRequest +import coil3.request.transformations +import coil3.size.Precision +import coil3.size.Scale +import coil3.transform.RoundedCornersTransformation import eu.kanade.tachiyomi.core.security.SecurityPreferences import eu.kanade.tachiyomi.util.system.dpToPx import kotlinx.collections.immutable.ImmutableList @@ -105,6 +107,7 @@ abstract class BaseUpdatesGridGlanceWidget( } } + @OptIn(ExperimentalCoilApi::class) private suspend fun List.prepareData( rowCount: Int, columnCount: Int, @@ -140,7 +143,11 @@ abstract class BaseUpdatesGridGlanceWidget( } } .build() - Pair(updatesView.mangaId, context.imageLoader.executeBlocking(request).drawable?.toBitmap()) + val bitmap = context.imageLoader.executeBlocking(request) + .image + ?.asDrawable(context.resources) + ?.toBitmap() + Pair(updatesView.mangaId, bitmap) } .toImmutableList() }