|
|
@@ -1,6 +1,7 @@
|
|
|
package io.legado.app.help.coil
|
|
|
|
|
|
import android.net.Uri
|
|
|
+import android.util.Base64
|
|
|
import coil.ImageLoader
|
|
|
import coil.decode.DataSource
|
|
|
import coil.decode.ImageSource
|
|
|
@@ -9,16 +10,12 @@ import coil.fetch.Fetcher
|
|
|
import coil.fetch.SourceResult
|
|
|
import coil.network.HttpException
|
|
|
import coil.request.Options
|
|
|
-
|
|
|
import io.legado.app.data.entities.BaseSource
|
|
|
-import io.legado.app.help.http.await
|
|
|
import io.legado.app.model.ReadManga
|
|
|
import io.legado.app.utils.ImageUtils
|
|
|
import kotlinx.coroutines.Dispatchers
|
|
|
import kotlinx.coroutines.withContext
|
|
|
import okhttp3.Call
|
|
|
-import okhttp3.HttpUrl
|
|
|
-import okhttp3.HttpUrl.Companion.toHttpUrl
|
|
|
import okhttp3.OkHttpClient
|
|
|
import okhttp3.Request
|
|
|
import okio.Buffer
|
|
|
@@ -34,47 +31,65 @@ class CoverFetcher(
|
|
|
val source = options.tags.tag<BaseSource>()
|
|
|
val isManga = options.parameters.value("manga") as? Boolean == true
|
|
|
|
|
|
- val request = Request.Builder()
|
|
|
- .url(url)
|
|
|
- .headers(options.headers)
|
|
|
- .build()
|
|
|
+ val bytes = if (url.startsWith("data:", true)) {
|
|
|
+ val base64Data = url.substringAfter("base64,", "")
|
|
|
+ if (base64Data.isEmpty()) {
|
|
|
+ throw IOException("Invalid data URI")
|
|
|
+ }
|
|
|
+ Base64.decode(base64Data, Base64.DEFAULT)
|
|
|
+ } else {
|
|
|
+ val request = Request.Builder()
|
|
|
+ .url(url)
|
|
|
+ .headers(options.headers)
|
|
|
+ .build()
|
|
|
+
|
|
|
+ val response = withContext(Dispatchers.IO) {
|
|
|
+ callFactory.newCall(request).execute()
|
|
|
+ }
|
|
|
+ val body = response.body
|
|
|
|
|
|
- val response = callFactory.newCall(request).execute()
|
|
|
- val body = response.body
|
|
|
+ if (!response.isSuccessful) {
|
|
|
+ body.close()
|
|
|
+ throw HttpException(response)
|
|
|
+ }
|
|
|
|
|
|
- if (!response.isSuccessful) {
|
|
|
- body.close()
|
|
|
- throw HttpException(response)
|
|
|
+ val b = body.use { body ->
|
|
|
+ body.bytes()
|
|
|
+ }
|
|
|
+ b
|
|
|
}
|
|
|
|
|
|
if (ImageUtils.skipDecode(source, !isManga)) {
|
|
|
return SourceResult(
|
|
|
- source = ImageSource(source = body.source(), context = options.context),
|
|
|
+ source = ImageSource(source = Buffer().write(bytes), context = options.context),
|
|
|
mimeType = null,
|
|
|
- dataSource = DataSource.NETWORK
|
|
|
+ dataSource = if (url.startsWith(
|
|
|
+ "data:",
|
|
|
+ true
|
|
|
+ )
|
|
|
+ ) DataSource.MEMORY else DataSource.NETWORK
|
|
|
)
|
|
|
}
|
|
|
|
|
|
return withContext(Dispatchers.IO) {
|
|
|
- try {
|
|
|
- val bytes = body.bytes()
|
|
|
- val decodedBytes = if (isManga) {
|
|
|
- ImageUtils.decode(url, bytes, false, source, ReadManga.book)
|
|
|
- } else {
|
|
|
- ImageUtils.decode(url, bytes, true, source)
|
|
|
- } ?: throw IOException("图片解密失败")
|
|
|
+ val decodedBytes = if (isManga) {
|
|
|
+ ImageUtils.decode(url, bytes, false, source, ReadManga.book)
|
|
|
+ } else {
|
|
|
+ ImageUtils.decode(url, bytes, true, source)
|
|
|
+ } ?: throw IOException("图片解密失败")
|
|
|
|
|
|
- SourceResult(
|
|
|
- source = ImageSource(
|
|
|
- source = Buffer().write(decodedBytes),
|
|
|
- context = options.context
|
|
|
- ),
|
|
|
- mimeType = null,
|
|
|
- dataSource = DataSource.NETWORK
|
|
|
- )
|
|
|
- } finally {
|
|
|
- body.close()
|
|
|
- }
|
|
|
+ SourceResult(
|
|
|
+ source = ImageSource(
|
|
|
+ source = Buffer().write(decodedBytes),
|
|
|
+ context = options.context
|
|
|
+ ),
|
|
|
+ mimeType = null,
|
|
|
+ dataSource = if (url.startsWith(
|
|
|
+ "data:",
|
|
|
+ true
|
|
|
+ )
|
|
|
+ ) DataSource.MEMORY else DataSource.NETWORK
|
|
|
+ )
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -83,7 +98,8 @@ class CoverFetcher(
|
|
|
private val okHttpClientManga: OkHttpClient
|
|
|
) : Fetcher.Factory<Uri> {
|
|
|
override fun create(data: Uri, options: Options, imageLoader: ImageLoader): Fetcher? {
|
|
|
- if (data.scheme != "http" && data.scheme != "https") return null
|
|
|
+ val scheme = data.scheme
|
|
|
+ if (scheme != "http" && scheme != "https" && scheme != "data") return null
|
|
|
|
|
|
val isManga = options.parameters.value("manga") as? Boolean == true
|
|
|
val client = if (isManga) okHttpClientManga else okHttpClient
|
|
|
@@ -91,4 +107,4 @@ class CoverFetcher(
|
|
|
return CoverFetcher(data.toString(), options, client)
|
|
|
}
|
|
|
}
|
|
|
-}
|
|
|
+}
|