diff --git a/README.md b/README.md index 5b3316604..bf6f5aade 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,6 @@ Here is the libraries - [RikkaX](https://github.com/RikkaApps/RikkaX) - [Libarchive](http://www.libarchive.org/) - [Coil](https://coil-kt.github.io/coil/) -- [Ktor](https://ktor.io/) - [Jsoup](https://jsoup.org/) Specially thanks [Tachiyomi](https://tachiyomi.org/) for its reader implementation! diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9f9ea2717..684c7fc42 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -13,7 +13,7 @@ plugins { android { compileSdk = 33 - buildToolsVersion = "33.0.2" + buildToolsVersion = "34.0.0 rc2" ndkVersion = "25.2.9519653" androidResources.generateLocaleConfig = true @@ -222,8 +222,6 @@ dependencies { // https://coil-kt.github.io/coil/changelog/ implementation("io.coil-kt:coil-compose:2.3.0") - - implementation("io.ktor:ktor-client-okhttp:2.3.0") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.0") implementation("org.jetbrains.kotlinx:kotlinx-serialization-cbor:1.5.0") implementation("org.jsoup:jsoup:1.16.1") diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index c57e445f3..b6ac9d700 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -13,9 +13,6 @@ -keep class androidx.viewpager.widget.ViewPager$LayoutParams { int position; } -# Ktor logger --dontwarn org.slf4j.impl.StaticLoggerBinder - -keepattributes LineNumberTable,SourceFile -renamesourcefileattribute SourceFile diff --git a/app/src/main/java/com/hippo/ehviewer/EhApplication.kt b/app/src/main/java/com/hippo/ehviewer/EhApplication.kt index 75357333c..833045e11 100644 --- a/app/src/main/java/com/hippo/ehviewer/EhApplication.kt +++ b/app/src/main/java/com/hippo/ehviewer/EhApplication.kt @@ -43,8 +43,6 @@ import com.hippo.yorozuya.FileUtils import eu.kanade.tachiyomi.core.preference.AndroidPreferenceStore import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences import eu.kanade.tachiyomi.util.lang.launchIO -import io.ktor.client.HttpClient -import io.ktor.client.engine.okhttp.OkHttp import kotlinx.coroutines.DelicateCoroutinesApi import okhttp3.Cache import okhttp3.OkHttpClient @@ -184,14 +182,6 @@ class EhApplication : Application(), DefaultLifecycleObserver, ImageLoaderFactor ).build() } - val ktorClient by lazy { - HttpClient(OkHttp) { - engine { - preconfigured = nonCacheOkHttpClient - } - } - } - val galleryDetailCache by lazy { LruCache(25).also { favouriteStatusRouter.addListener { gid, slot -> diff --git a/app/src/main/java/com/hippo/ehviewer/client/EhCookieStore.kt b/app/src/main/java/com/hippo/ehviewer/client/EhCookieStore.kt index 9171cd58a..f0043f40e 100644 --- a/app/src/main/java/com/hippo/ehviewer/client/EhCookieStore.kt +++ b/app/src/main/java/com/hippo/ehviewer/client/EhCookieStore.kt @@ -19,8 +19,6 @@ import com.hippo.ehviewer.EhApplication import com.hippo.network.CookieDatabase import com.hippo.network.CookieSet import eu.kanade.tachiyomi.util.lang.launchIO -import io.ktor.client.plugins.cookies.CookiesStorage -import io.ktor.http.Url import okhttp3.Cookie import okhttp3.CookieJar import okhttp3.HttpUrl @@ -28,9 +26,7 @@ import okhttp3.HttpUrl.Companion.toHttpUrl import java.util.Collections import java.util.regex.Pattern -typealias KtorCookie = io.ktor.http.Cookie - -object EhCookieStore : CookieJar, CookiesStorage { +object EhCookieStore : CookieJar { private val db: CookieDatabase = CookieDatabase(EhApplication.application, "okhttp3-cookie.db") private val map: MutableMap = db.allCookies @@ -205,21 +201,6 @@ object EhCookieStore : CookieJar, CookiesStorage { } } - override suspend fun addCookie(requestUrl: Url, cookie: io.ktor.http.Cookie) {} - - // This should never be closed - override fun close() {} - - private val okhttpCookieToKtorCookieMap = hashMapOf() - override suspend fun get(requestUrl: Url): List { - return loadForRequest(requestUrl.toString().toHttpUrl()).map { - okhttpCookieToKtorCookieMap[it] ?: KtorCookie( - it.name, - it.value, - ).apply { okhttpCookieToKtorCookieMap[it] = this } - } - } - override fun saveFromResponse(url: HttpUrl, cookies: List) { for (cookie in cookies) { // See https://github.com/Ehviewer-Overhauled/Ehviewer/issues/873 diff --git a/app/src/main/java/com/hippo/ehviewer/client/EhRequestBuilder.kt b/app/src/main/java/com/hippo/ehviewer/client/EhRequestBuilder.kt index d6def3fee..f1f5221ab 100644 --- a/app/src/main/java/com/hippo/ehviewer/client/EhRequestBuilder.kt +++ b/app/src/main/java/com/hippo/ehviewer/client/EhRequestBuilder.kt @@ -15,7 +15,6 @@ */ package com.hippo.ehviewer.client -import io.ktor.http.HttpMessageBuilder import okhttp3.FormBody import okhttp3.MediaType import okhttp3.MediaType.Companion.toMediaType @@ -45,8 +44,6 @@ fun jsonArrayOf(vararg element: Any?) = JSONArray().apply { element.forEach { pu inline fun Request.Builder.jsonBody(builder: JSONObject.() -> Unit) = post(JSONObject().apply(builder).toString().toRequestBody(MEDIA_TYPE_JSON)) -fun HttpMessageBuilder.referer(value: String?): Unit = value?.let { headers.append("Referer", it) } ?: Unit - const val CHROME_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36" const val CHROME_ACCEPT = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" const val CHROME_ACCEPT_LANGUAGE = "en-US,en;q=0.5" diff --git a/app/src/main/java/com/hippo/ehviewer/spider/SpiderDen.kt b/app/src/main/java/com/hippo/ehviewer/spider/SpiderDen.kt index 926f7b768..34839cb9a 100644 --- a/app/src/main/java/com/hippo/ehviewer/spider/SpiderDen.kt +++ b/app/src/main/java/com/hippo/ehviewer/spider/SpiderDen.kt @@ -18,13 +18,13 @@ package com.hippo.ehviewer.spider import android.graphics.ImageDecoder import android.os.ParcelFileDescriptor import android.os.ParcelFileDescriptor.MODE_READ_WRITE -import com.hippo.ehviewer.EhApplication +import com.hippo.ehviewer.EhApplication.Companion.nonCacheOkHttpClient import com.hippo.ehviewer.EhDB import com.hippo.ehviewer.Settings import com.hippo.ehviewer.client.EhUtils.getSuitableTitle import com.hippo.ehviewer.client.data.GalleryInfo +import com.hippo.ehviewer.client.ehRequest import com.hippo.ehviewer.client.getImageKey -import com.hippo.ehviewer.client.referer import com.hippo.ehviewer.coil.edit import com.hippo.ehviewer.coil.read import com.hippo.ehviewer.gallery.SUPPORT_IMAGE_EXTENSIONS @@ -34,22 +34,18 @@ import com.hippo.unifile.UniFile import com.hippo.unifile.openOutputStream import com.hippo.util.sendTo import com.hippo.yorozuya.FileUtils -import io.ktor.client.plugins.onDownload -import io.ktor.client.request.prepareGet -import io.ktor.client.statement.HttpResponse -import io.ktor.client.statement.bodyAsChannel -import io.ktor.http.ContentType -import io.ktor.http.contentLength -import io.ktor.http.contentType -import io.ktor.utils.io.jvm.nio.copyTo +import kotlinx.coroutines.currentCoroutineContext +import kotlinx.coroutines.ensureActive import moe.tarsin.coroutines.runSuspendCatching +import okhttp3.Response +import okhttp3.executeAsync +import okio.buffer +import okio.sink import java.io.IOException import java.util.Locale import kotlin.io.path.readText import com.hippo.ehviewer.EhApplication.Companion.imageCache as sCache -private val client = EhApplication.ktorClient - class SpiderDen(private val mGalleryInfo: GalleryInfo) { private val mGid = mGalleryInfo.gid var downloadDir: UniFile? = getGalleryDownloadDir(mGid)?.takeIf { it.isDirectory } @@ -138,30 +134,34 @@ class SpiderDen(private val mGalleryInfo: GalleryInfo) { referer: String?, notifyProgress: (Long, Long, Int) -> Unit, ): Boolean { - return client.prepareGet(url) { - var state: Long = 0 - referer(referer) - onDownload { bytesSentTotal, contentLength -> - notifyProgress(contentLength, bytesSentTotal, (bytesSentTotal - state).toInt()) - state = bytesSentTotal - } - }.execute { - if (it.status.value >= 400) return@execute false - saveFromHttpResponse(index, it) + // TODO: Use HttpEngine[https://developer.android.com/reference/android/net/http/HttpEngine] directly here if available + // Since we don't want unnecessary copy between jvm heap & native heap + nonCacheOkHttpClient.newCall(ehRequest(url, referer)).executeAsync().use { + if (it.code >= 400) return false + return saveFromHttpResponse(index, it, notifyProgress) } } - private suspend fun saveFromHttpResponse(index: Int, body: HttpResponse): Boolean { - val contentType = body.contentType() - val extension = contentType?.contentSubtype ?: "jpg" - val length = body.contentLength() ?: return false + private suspend fun saveFromHttpResponse(index: Int, response: Response, notifyProgress: (Long, Long, Int) -> Unit): Boolean { + val contentType = response.body.contentType() + val extension = contentType?.subtype ?: "jpg" + val length = response.body.contentLength() suspend fun doSave(outFile: UniFile): Long { - val ret: Long - outFile.openOutputStream().use { - ret = body.bodyAsChannel().copyTo(it.channel) + var ret: Long = 1 + outFile.openOutputStream().sink().buffer().use { sink -> + response.body.source().use { source -> + while (true) { + currentCoroutineContext().ensureActive() + val bytesRead = source.read(sink.buffer, 8192) + sink.emitCompleteSegments() + ret += bytesRead + notifyProgress(length, ret, bytesRead.toInt()) + if (bytesRead.toInt() < 0) break + } + } } - if (contentType == ContentType.Image.GIF) { + if (extension.lowercase() == "gif") { outFile.openFileDescriptor("rw").use { rewriteGifSource2(it.fd) } diff --git a/docs/README/en.md b/docs/README/en.md index 79dc1b7aa..30b4708dd 100644 --- a/docs/README/en.md +++ b/docs/README/en.md @@ -86,7 +86,6 @@ Here is the libraries - [RikkaX](https://github.com/RikkaApps/RikkaX) - [Libarchive](http://www.libarchive.org/) - [Coil](https://coil-kt.github.io/coil/) -- [Ktor](https://ktor.io/) - [Jsoup](https://jsoup.org/) Specially thanks [Tachiyomi](https://tachiyomi.org/) for its reader implementation! diff --git a/docs/README/zh-cn.md b/docs/README/zh-cn.md index b7aa9efcc..ecfc41215 100644 --- a/docs/README/zh-cn.md +++ b/docs/README/zh-cn.md @@ -86,7 +86,6 @@ - [RikkaX](https://github.com/RikkaApps/RikkaX) - [Libarchive](http://www.libarchive.org/) - [Coil](https://coil-kt.github.io/coil/) -- [Ktor](https://ktor.io/) - [Jsoup](https://jsoup.org/) 特别感谢[Tachiyomi](https://tachiyomi.org/)的阅读器实现 diff --git a/docs/README/zh-tw.md b/docs/README/zh-tw.md index fe7c342f9..1d497846f 100644 --- a/docs/README/zh-tw.md +++ b/docs/README/zh-tw.md @@ -86,7 +86,6 @@ - [RikkaX](https://github.com/RikkaApps/RikkaX) - [Libarchive](http://www.libarchive.org/) - [Coil](https://coil-kt.github.io/coil/) -- [Ktor](https://ktor.io/) - [Jsoup](https://jsoup.org/) # 許可證書