Upgrade coil to v2

This commit is contained in:
Koitharu
2022-05-04 13:17:02 +03:00
parent 4c5314fe59
commit ffad6a4ae6
12 changed files with 73 additions and 53 deletions

View File

@@ -52,6 +52,7 @@ android {
'-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi',
'-opt-in=kotlinx.coroutines.FlowPreview',
'-opt-in=kotlin.contracts.ExperimentalContracts',
'-opt-in=coil.annotation.ExperimentalCoilApi',
]
}
lint {
@@ -86,7 +87,7 @@ dependencies {
implementation 'androidx.viewpager2:viewpager2:1.1.0-beta01'
implementation 'androidx.preference:preference-ktx:1.2.0'
implementation 'androidx.work:work-runtime-ktx:2.7.1'
implementation 'com.google.android.material:material:1.6.0-rc01'
implementation 'com.google.android.material:material:1.7.0-alpha01'
//noinspection LifecycleAnnotationProcessorWithJava8
kapt 'androidx.lifecycle:lifecycle-compiler:2.4.1'
@@ -101,11 +102,11 @@ dependencies {
implementation 'com.hannesdorfmann:adapterdelegates4-kotlin-dsl-viewbinding:4.3.2'
implementation 'io.insert-koin:koin-android:3.1.6'
implementation 'io.coil-kt:coil-base:1.4.0'
implementation 'io.coil-kt:coil-base:2.0.0-rc03'
implementation 'com.davemorrissey.labs:subsampling-scale-image-view-androidx:3.10.0'
implementation 'com.github.solkin:disk-lru-cache:1.4'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.8.1'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.1'

View File

@@ -5,12 +5,12 @@ import android.content.Context
import android.content.pm.ShortcutManager
import android.media.ThumbnailUtils
import android.os.Build
import android.util.Size
import androidx.core.content.pm.ShortcutInfoCompat
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.graphics.drawable.IconCompat
import coil.ImageLoader
import coil.request.ImageRequest
import coil.size.PixelSize
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.koitharu.kotatsu.R
@@ -54,7 +54,7 @@ class ShortcutsRepository(
val bmp = coil.execute(
ImageRequest.Builder(context)
.data(manga.coverUrl)
.size(iconSize)
.size(iconSize.width, iconSize.height)
.build()
).requireBitmap()
ThumbnailUtils.extractThumbnail(bmp, iconSize.width, iconSize.height, 0)
@@ -74,14 +74,14 @@ class ShortcutsRepository(
)
}
private fun getIconSize(context: Context): PixelSize {
private fun getIconSize(context: Context): Size {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
(context.getSystemService(Context.SHORTCUT_SERVICE) as ShortcutManager).let {
PixelSize(it.iconMaxWidth, it.iconMaxHeight)
Size(it.iconMaxWidth, it.iconMaxHeight)
}
} else {
(context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager).launcherLargeIconSize.let {
PixelSize(it, it)
Size(it, it)
}
}
}

View File

@@ -2,17 +2,19 @@ package org.koitharu.kotatsu.core.parser
import android.net.Uri
import coil.map.Mapper
import coil.request.Options
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl
import org.koitharu.kotatsu.parsers.model.MangaSource
class FaviconMapper() : Mapper<Uri, HttpUrl> {
class FaviconMapper : Mapper<Uri, HttpUrl> {
override fun map(data: Uri): HttpUrl {
override fun map(data: Uri, options: Options): HttpUrl? {
if (data.scheme != "favicon") {
return null
}
val mangaSource = MangaSource.valueOf(data.schemeSpecificPart)
val repo = MangaRepository(mangaSource) as RemoteMangaRepository
return repo.getFaviconUrl().toHttpUrl()
}
override fun handles(data: Uri) = data.scheme == "favicon"
}

View File

@@ -2,11 +2,13 @@ package org.koitharu.kotatsu.core.ui
import coil.ComponentRegistry
import coil.ImageLoader
import coil.util.CoilUtils
import coil.disk.DiskCache
import kotlinx.coroutines.Dispatchers
import okhttp3.OkHttpClient
import org.koin.android.ext.koin.androidContext
import org.koin.dsl.module
import org.koitharu.kotatsu.core.parser.FaviconMapper
import org.koitharu.kotatsu.local.data.CacheDir
import org.koitharu.kotatsu.local.data.CbzFetcher
val uiModule
@@ -14,15 +16,23 @@ val uiModule
single {
val httpClientFactory = {
get<OkHttpClient>().newBuilder()
.cache(CoilUtils.createDefaultCache(androidContext()))
.cache(null)
.build()
}
val diskCacheFactory = {
val context = androidContext()
val rootDir = context.externalCacheDir ?: context.cacheDir
DiskCache.Builder()
.directory(rootDir.resolve(CacheDir.THUMBS.dir))
.build()
}
ImageLoader.Builder(androidContext())
.okHttpClient(httpClientFactory)
.launchInterceptorChainOnMainThread(false)
.componentRegistry(
.interceptorDispatcher(Dispatchers.Default)
.diskCache(diskCacheFactory)
.components(
ComponentRegistry.Builder()
.add(CbzFetcher())
.add(CbzFetcher.Factory())
.add(FaviconMapper())
.build()
).build()

View File

@@ -283,7 +283,7 @@ class DetailsFragment :
.target(binding.imageViewCover)
if (currentCover != null) {
request.data(manga.largeCoverUrl ?: return)
.placeholderMemoryCacheKey(CoilUtils.metadata(binding.imageViewCover)?.memoryCacheKey)
.placeholderMemoryCacheKey(CoilUtils.result(binding.imageViewCover)?.request?.memoryCacheKey)
.fallback(currentCover)
} else {
request.crossfade(true)

View File

@@ -6,7 +6,6 @@ import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Bundle
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.graphics.Insets
import androidx.core.graphics.drawable.toBitmap
import androidx.core.view.updateLayoutParams
@@ -14,7 +13,7 @@ import androidx.core.view.updatePadding
import coil.ImageLoader
import coil.request.CachePolicy
import coil.request.ImageRequest
import coil.target.PoolableViewTarget
import coil.target.ViewTarget
import com.davemorrissey.labs.subscaleview.ImageSource
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
import org.koin.android.ext.android.inject
@@ -61,16 +60,12 @@ class ImageActivity : BaseActivity<ActivityImageBinding>() {
private class SsivTarget(
override val view: SubsamplingScaleImageView,
) : PoolableViewTarget<SubsamplingScaleImageView> {
override fun onStart(placeholder: Drawable?) = setDrawable(placeholder)
) : ViewTarget<SubsamplingScaleImageView> {
override fun onError(error: Drawable?) = setDrawable(error)
override fun onSuccess(result: Drawable) = setDrawable(result)
override fun onClear() = setDrawable(null)
override fun equals(other: Any?): Boolean {
return (this === other) || (other is SsivTarget && view == other.view)
}

View File

@@ -53,7 +53,7 @@ fun mangaGridItemAD(
badge = null
imageRequest?.dispose()
imageRequest = null
CoilUtils.clear(binding.imageViewCover)
CoilUtils.dispose(binding.imageViewCover)
binding.imageViewCover.setImageDrawable(null)
}
}

View File

@@ -57,7 +57,7 @@ fun mangaListDetailedItemAD(
badge = null
imageRequest?.dispose()
imageRequest = null
CoilUtils.clear(binding.imageViewCover)
CoilUtils.dispose(binding.imageViewCover)
binding.imageViewCover.setImageDrawable(null)
}
}

View File

@@ -55,7 +55,7 @@ fun mangaListItemAD(
badge = null
imageRequest?.dispose()
imageRequest = null
CoilUtils.clear(binding.imageViewCover)
CoilUtils.dispose(binding.imageViewCover)
binding.imageViewCover.setImageDrawable(null)
}
}

View File

@@ -2,41 +2,52 @@ package org.koitharu.kotatsu.local.data
import android.net.Uri
import android.webkit.MimeTypeMap
import coil.bitmap.BitmapPool
import coil.ImageLoader
import coil.decode.DataSource
import coil.decode.Options
import coil.fetch.FetchResult
import coil.decode.ImageSource
import coil.fetch.Fetcher
import coil.fetch.SourceResult
import coil.size.Size
import java.util.zip.ZipFile
import coil.request.Options
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runInterruptible
import okio.buffer
import okio.source
import java.util.zip.ZipFile
class CbzFetcher : Fetcher<Uri> {
class CbzFetcher(
private val uri: Uri,
private val options: Options
) : Fetcher {
override suspend fun fetch(
pool: BitmapPool,
data: Uri,
size: Size,
options: Options,
): FetchResult = runInterruptible(Dispatchers.IO) {
val zip = ZipFile(data.schemeSpecificPart)
val entry = zip.getEntry(data.fragment)
override suspend fun fetch() = runInterruptible(Dispatchers.IO) {
val zip = ZipFile(uri.schemeSpecificPart)
val entry = zip.getEntry(uri.fragment)
val ext = MimeTypeMap.getFileExtensionFromUrl(entry.name)
val bufferedSource = ExtraCloseableBufferedSource(
zip.getInputStream(entry).source().buffer(),
zip,
)
SourceResult(
source = ExtraCloseableBufferedSource(
zip.getInputStream(entry).source().buffer(),
zip,
source = ImageSource(
source = bufferedSource,
context = options.context,
metadata = CbzMetadata(uri),
),
mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext),
dataSource = DataSource.DISK
dataSource = DataSource.DISK,
)
}
override fun key(data: Uri) = data.toString()
class Factory : Fetcher.Factory<Uri> {
override fun handles(data: Uri) = data.scheme == "cbz"
override fun create(data: Uri, options: Options, imageLoader: ImageLoader): Fetcher? {
return if (data.scheme == "cbz") {
CbzFetcher(data, options)
} else {
null
}
}
}
class CbzMetadata(val uri: Uri) : ImageSource.Metadata()
}

View File

@@ -3,7 +3,7 @@ package org.koitharu.kotatsu.reader.ui.thumbnails.adapter
import android.graphics.drawable.Drawable
import coil.ImageLoader
import coil.request.ImageRequest
import coil.size.PixelSize
import coil.size.Size
import com.google.android.material.R as materialR
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
import kotlinx.coroutines.*
@@ -27,7 +27,7 @@ fun pageThumbnailAD(
var job: Job? = null
val gridWidth = itemView.context.resources.getDimensionPixelSize(R.dimen.preferred_grid_width)
val thumbSize = PixelSize(
val thumbSize = Size(
width = gridWidth,
height = (gridWidth * 13f / 18f).toInt()
)

View File

@@ -1,7 +1,8 @@
package org.koitharu.kotatsu.utils.progress
import coil.request.ErrorResult
import coil.request.ImageRequest
import coil.request.ImageResult
import coil.request.SuccessResult
import com.google.android.material.progressindicator.BaseProgressIndicator
class ImageRequestIndicatorListener(
@@ -10,9 +11,9 @@ class ImageRequestIndicatorListener(
override fun onCancel(request: ImageRequest) = indicator.hide()
override fun onError(request: ImageRequest, throwable: Throwable) = indicator.hide()
override fun onError(request: ImageRequest, result: ErrorResult) = indicator.hide()
override fun onStart(request: ImageRequest) = indicator.show()
override fun onSuccess(request: ImageRequest, metadata: ImageResult.Metadata) = indicator.hide()
override fun onSuccess(request: ImageRequest, result: SuccessResult) = indicator.hide()
}