Move to coil NetworkFetcher (#558)
* Move to coil NetworkFetcher * Fixup --------- Co-authored-by: GG Bond <whatever@tagkong.com>
This commit is contained in:
1 parent
0e2ca4e150
commit
d880b30ea9
4 files changed
+19
-63
No files matched your search
@@ -29,6 +29,7 @@ import androidx.lifecycle.coroutineScope
|
||||
import coil3.SingletonImageLoader
|
||||
import coil3.asCoilImage
|
||||
import coil3.decode.ImageDecoderDecoder
|
||||
import coil3.fetch.NetworkFetcher
|
||||
import coil3.request.crossfade
|
||||
import coil3.util.DebugLogger
|
||||
import com.hippo.ehviewer.client.EhCookieStore
|
||||
@@ -36,7 +37,6 @@ import com.hippo.ehviewer.client.EhTagDatabase
|
||||
import com.hippo.ehviewer.client.data.GalleryDetail
|
||||
import com.hippo.ehviewer.coil.DownloadThumbInterceptor
|
||||
import com.hippo.ehviewer.coil.MergeInterceptor
|
||||
import com.hippo.ehviewer.coil.installKtorHttpUriFetcher
|
||||
import com.hippo.ehviewer.dailycheck.checkDawn
|
||||
import com.hippo.ehviewer.dao.SearchDatabase
|
||||
import com.hippo.ehviewer.download.DownloadManager
|
||||
@@ -56,6 +56,7 @@ import com.hippo.ehviewer.util.isAtLeastQ
|
||||
import com.hippo.ehviewer.util.isAtLeastS
|
||||
import com.hippo.ehviewer.util.isCronetAvailable
|
||||
import com.hippo.ehviewer.util.resettableLazy
|
||||
import com.hippo.ehviewer.util.unsafeLazy
|
||||
import eu.kanade.tachiyomi.network.interceptor.UncaughtExceptionInterceptor
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||
@@ -181,7 +182,7 @@ class EhApplication : Application(), SingletonImageLoader.Factory {
|
||||
|
||||
override fun newImageLoader() = imageLoader {
|
||||
components {
|
||||
installKtorHttpUriFetcher()
|
||||
add(NetworkFetcher.Factory(unsafeLazy { ktorClient }))
|
||||
if (isAtLeastP) {
|
||||
add { result, options, _ -> ImageDecoderDecoder(result.source, options, false) }
|
||||
}
|
||||
|
||||
@@ -7,18 +7,31 @@ import coil3.decode.DecodeResult
|
||||
import coil3.decode.Decoder
|
||||
import coil3.request.CachePolicy
|
||||
import coil3.request.ImageRequest
|
||||
import coil3.request.httpHeaders
|
||||
import coil3.size.Size
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.CHROME_ACCEPT
|
||||
import com.hippo.ehviewer.client.CHROME_ACCEPT_LANGUAGE
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo
|
||||
import com.hippo.ehviewer.client.data.GalleryPreview
|
||||
import com.hippo.ehviewer.client.data.NormalGalleryPreview
|
||||
import com.hippo.ehviewer.client.url
|
||||
import com.hippo.ehviewer.spider.DownloadInfoMagics.encodeMagicRequestOrUrl
|
||||
import io.ktor.http.HttpHeaders
|
||||
import io.ktor.http.headers
|
||||
|
||||
private val header = headers {
|
||||
append(HttpHeaders.UserAgent, Settings.userAgent)
|
||||
append(HttpHeaders.Accept, CHROME_ACCEPT)
|
||||
append(HttpHeaders.AcceptLanguage, CHROME_ACCEPT_LANGUAGE)
|
||||
}
|
||||
|
||||
fun ImageRequest.Builder.ehUrl(info: GalleryInfo) = apply {
|
||||
val key = info.thumbKey!!
|
||||
data(encodeMagicRequestOrUrl(info))
|
||||
memoryCacheKey(key)
|
||||
diskCacheKey(key)
|
||||
httpHeaders(header)
|
||||
}
|
||||
|
||||
fun ImageRequest.Builder.ehPreview(preview: GalleryPreview) = apply {
|
||||
@@ -26,6 +39,7 @@ fun ImageRequest.Builder.ehPreview(preview: GalleryPreview) = apply {
|
||||
memoryCacheKey(preview.imageKey)
|
||||
diskCacheKey(preview.imageKey)
|
||||
if (preview is NormalGalleryPreview) size(Size.ORIGINAL)
|
||||
httpHeaders(header)
|
||||
}
|
||||
|
||||
private val stubImage = ColorDrawable(Color.BLACK).asCoilImage(true)
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
@file:Suppress("BlockingMethodInNonBlockingContext")
|
||||
|
||||
package com.hippo.ehviewer.coil
|
||||
|
||||
import android.webkit.MimeTypeMap
|
||||
import coil3.ComponentRegistry
|
||||
import coil3.ImageLoader
|
||||
import coil3.Uri
|
||||
import coil3.decode.DataSource
|
||||
import coil3.decode.ImageSource
|
||||
import coil3.fetch.FetchResult
|
||||
import coil3.fetch.Fetcher
|
||||
import coil3.fetch.SourceFetchResult
|
||||
import coil3.request.Options
|
||||
import com.hippo.ehviewer.client.ehRequest
|
||||
import com.hippo.ehviewer.util.copyTo
|
||||
import io.ktor.client.statement.bodyAsChannel
|
||||
|
||||
/**
|
||||
* A HttpUriFetcher impl use Ktor (Will do jvmheapless IO when backing engine is Cronet)
|
||||
* cacheHeader is never respected | recorded since thumb is immutable
|
||||
*/
|
||||
class KtorHttpUriFetcher(private val data: String, private val options: Options, private val imageLoader: ImageLoader) : Fetcher {
|
||||
override suspend fun fetch(): FetchResult {
|
||||
val diskCacheKey = options.diskCacheKey ?: data
|
||||
val diskCache = requireNotNull(imageLoader.diskCache)
|
||||
val snapshot = diskCache.openSnapshot(diskCacheKey) ?: run {
|
||||
val success = ehRequest(data, verbose = false).execute {
|
||||
diskCache.suspendEdit(diskCacheKey) {
|
||||
it.bodyAsChannel().copyTo(data.toFile())
|
||||
}
|
||||
}
|
||||
check(success)
|
||||
// diskcache snapshot MUST exist here
|
||||
requireNotNull(diskCache.openSnapshot(diskCacheKey))
|
||||
}
|
||||
return SourceFetchResult(
|
||||
source = ImageSource(snapshot.data, diskCache.fileSystem, diskCacheKey, snapshot),
|
||||
mimeType = getMimeType(data),
|
||||
dataSource = DataSource.DISK,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun ComponentRegistry.Builder.installKtorHttpUriFetcher() = add { data: Uri, options, loader ->
|
||||
if (data.scheme != "http" && data.scheme != "https") return@add null
|
||||
KtorHttpUriFetcher(data.toString(), options, loader)
|
||||
}
|
||||
|
||||
private fun getMimeType(url: String) = MimeTypeMap.getSingleton().getMimeTypeFromUrl(url)
|
||||
|
||||
private fun MimeTypeMap.getMimeTypeFromUrl(url: String?): String? {
|
||||
if (url.isNullOrBlank()) return null
|
||||
val extension = url
|
||||
.substringBeforeLast('#') // Strip the fragment.
|
||||
.substringBeforeLast('?') // Strip the query.
|
||||
.substringAfterLast('/') // Get the last path segment.
|
||||
.substringAfterLast('.', missingDelimiterValue = "") // Get the file extension.
|
||||
return getMimeTypeFromExtension(extension)
|
||||
}
|
||||
@@ -64,6 +64,7 @@ arrow-stack = { module = "io.arrow-kt:arrow-stack", version.ref = "arrow" }
|
||||
coil-bom = { module = "io.coil-kt.coil3:coil-bom", version.ref = "coil" }
|
||||
coil-compose = { module = "io.coil-kt.coil3:coil-compose" }
|
||||
coil-gif = { module = "io.coil-kt.coil3:coil-gif" }
|
||||
coil-network = { module = "io.coil-kt.coil3:coil-network" }
|
||||
|
||||
compose-bom = { module = "dev.chrisbanes.compose:compose-bom", version.ref = "compose-bom" }
|
||||
# For renovate
|
||||
@@ -119,7 +120,7 @@ splitties-systemservices = { module = "com.louiscad.splitties:splitties-systemse
|
||||
|
||||
[bundles]
|
||||
androidx-navigation = ["androidx-navigation-compose", "androidx-navigation-ui"]
|
||||
coil = ["coil-compose", "coil-gif"]
|
||||
coil = ["coil-compose", "coil-gif", "coil-network"]
|
||||
compose = ["compose-foundation", "compose-material-icons-extended", "compose-material3", "compose-material3-windowsizeclass", "compose-ui-util"]
|
||||
cronet = ["cronet-api", "cronet-gms"]
|
||||
kotlinx-serialization = ["kotlinx-serialization-cbor", "kotlinx-serialization-json", "kotlinx-serialization-json-okio"]
|
||||
|
||||
Reference in new issue
Block a user