mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-31 14:27:57 +01:00 
			
		
		
		
	Switch to Coil3
Co-authored-by: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com>
This commit is contained in:
		| @@ -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", | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|  | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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<NetworkHelper>().client } | ||||
|             val diskCacheInit = { CoilDiskCache.get(this@App) } | ||||
|             val callFactoryLazy = lazy { Injekt.get<NetworkHelper>().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() | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -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() | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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() | ||||
|     } | ||||
|   | ||||
| @@ -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() | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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() | ||||
|   | ||||
| @@ -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() | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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"] | ||||
|   | ||||
| @@ -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", | ||||
|         ) | ||||
|     } | ||||
|   | ||||
| @@ -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<UpdatesWithRelations>.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() | ||||
|         } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user