diff --git a/app/src/main/java/com/hippo/ehviewer/EhApplication.kt b/app/src/main/java/com/hippo/ehviewer/EhApplication.kt index 11079b74d..7b94655b5 100644 --- a/app/src/main/java/com/hippo/ehviewer/EhApplication.kt +++ b/app/src/main/java/com/hippo/ehviewer/EhApplication.kt @@ -18,6 +18,7 @@ package com.hippo.ehviewer import android.app.Application import android.content.ComponentCallbacks2 +import android.net.Uri import androidx.appcompat.app.AppCompatDelegate import androidx.collection.LruCache import androidx.lifecycle.ProcessLifecycleOwner @@ -29,6 +30,7 @@ import com.google.net.cronet.okhttptransport.RedirectStrategy.withoutRedirects import com.hippo.ehviewer.client.EhCookieStore import com.hippo.ehviewer.client.EhTagDatabase import com.hippo.ehviewer.client.data.GalleryDetail +import com.hippo.ehviewer.coil.CronetHttpUriFetcher import com.hippo.ehviewer.coil.MergeInterceptor import com.hippo.ehviewer.dailycheck.checkDawn import com.hippo.ehviewer.download.DownloadManager @@ -54,6 +56,7 @@ import eu.kanade.tachiyomi.network.interceptor.CloudflareInterceptor import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.withUIContext import kotlinx.coroutines.launch +import moe.tarsin.kt.unreachable import okhttp3.AsyncDns import okhttp3.android.AndroidAsyncDns import okio.Path.Companion.toOkioPath @@ -142,8 +145,16 @@ class EhApplication : Application(), ImageLoaderFactory { } override fun newImageLoader() = imageLoader { - okHttpClient(nonCacheOkHttpClient) components { + if (isCronetSupported) { + callFactory { unreachable() } + add { data: Uri, options, loader -> + if (data.scheme != "http" && data.scheme != "https") return@add null + CronetHttpUriFetcher(data.toString(), options, loader) + } + } else { + okHttpClient(nonCacheOkHttpClient) + } add { result, options, _ -> ImageDecoderDecoder(result.source, options, false) } add(MergeInterceptor) } diff --git a/app/src/main/java/com/hippo/ehviewer/coil/CronetHttpUriFetcher.kt b/app/src/main/java/com/hippo/ehviewer/coil/CronetHttpUriFetcher.kt new file mode 100644 index 000000000..17c14f93e --- /dev/null +++ b/app/src/main/java/com/hippo/ehviewer/coil/CronetHttpUriFetcher.kt @@ -0,0 +1,55 @@ +package com.hippo.ehviewer.coil + +import android.webkit.MimeTypeMap +import coil.ImageLoader +import coil.decode.DataSource +import coil.decode.ImageSource +import coil.fetch.FetchResult +import coil.fetch.Fetcher +import coil.fetch.SourceResult +import coil.request.Options +import com.hippo.ehviewer.spider.awaitBodyFully +import com.hippo.ehviewer.spider.cronetRequest +import com.hippo.ehviewer.spider.execute +import java.io.RandomAccessFile + +class CronetHttpUriFetcher(val data: String, val options: Options, val imageLoader: ImageLoader) : Fetcher { + override suspend fun fetch(): FetchResult { + val diskCacheKey = options.diskCacheKey ?: data + val diskCache = requireNotNull(imageLoader.diskCache) + val snapshot = diskCache.openSnapshot(diskCacheKey) ?: kotlin.run { + cronetRequest(data) { + disableCache() + }.execute { + val success = diskCache.suspendEdit(diskCacheKey) { + RandomAccessFile(data.toFile(), "rw").use { f -> + val chan = f.channel + awaitBodyFully { buffer -> + chan.write(buffer) + } + } + } + check(success) + } + requireNotNull(diskCache.openSnapshot(diskCacheKey)) + } + val src = ImageSource(snapshot.data, diskCache.fileSystem, diskCacheKey, snapshot) + return SourceResult( + source = src, + mimeType = getMimeType(data), + dataSource = DataSource.DISK, + ) + } +} + +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) +} diff --git a/app/src/main/java/moe/tarsin/kt/PreConditions.kt b/app/src/main/java/moe/tarsin/kt/PreConditions.kt new file mode 100644 index 000000000..bc8c4f771 --- /dev/null +++ b/app/src/main/java/moe/tarsin/kt/PreConditions.kt @@ -0,0 +1,3 @@ +package moe.tarsin.kt + +fun unreachable(): Nothing = error("Unreachable!!!")