Upgrade coil to v2
This commit is contained in:
@@ -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'
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ fun mangaGridItemAD(
|
||||
badge = null
|
||||
imageRequest?.dispose()
|
||||
imageRequest = null
|
||||
CoilUtils.clear(binding.imageViewCover)
|
||||
CoilUtils.dispose(binding.imageViewCover)
|
||||
binding.imageViewCover.setImageDrawable(null)
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,7 @@ fun mangaListDetailedItemAD(
|
||||
badge = null
|
||||
imageRequest?.dispose()
|
||||
imageRequest = null
|
||||
CoilUtils.clear(binding.imageViewCover)
|
||||
CoilUtils.dispose(binding.imageViewCover)
|
||||
binding.imageViewCover.setImageDrawable(null)
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,7 @@ fun mangaListItemAD(
|
||||
badge = null
|
||||
imageRequest?.dispose()
|
||||
imageRequest = null
|
||||
CoilUtils.clear(binding.imageViewCover)
|
||||
CoilUtils.dispose(binding.imageViewCover)
|
||||
binding.imageViewCover.setImageDrawable(null)
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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()
|
||||
)
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
Reference in New Issue
Block a user