Update parsers
This commit is contained in:
@@ -1,13 +1,17 @@
|
||||
package org.koitharu.kotatsu.browser
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import androidx.activity.result.contract.ActivityResultContract
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.exceptions.InteractiveActionRequiredException
|
||||
import org.koitharu.kotatsu.core.nav.AppRouter
|
||||
import org.koitharu.kotatsu.core.nav.router
|
||||
import org.koitharu.kotatsu.core.parser.ParserMangaRepository
|
||||
@@ -65,4 +69,23 @@ class BrowserActivity : BaseBrowserActivity() {
|
||||
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
class Contract : ActivityResultContract<InteractiveActionRequiredException, Unit>() {
|
||||
override fun createIntent(
|
||||
context: Context,
|
||||
input: InteractiveActionRequiredException
|
||||
): Intent = AppRouter.browserIntent(
|
||||
context = context,
|
||||
url = input.url,
|
||||
source = input.source,
|
||||
title = null,
|
||||
)
|
||||
|
||||
override fun parseResult(resultCode: Int, intent: Intent?): Unit = Unit
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val TAG = "BrowserActivity"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.koitharu.kotatsu.core.exceptions
|
||||
|
||||
import okio.IOException
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
|
||||
class InteractiveActionRequiredException(
|
||||
val source: MangaSource,
|
||||
val url: String,
|
||||
) : IOException("Interactive action is required for ${source.name}")
|
||||
@@ -12,8 +12,10 @@ import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.browser.BrowserActivity
|
||||
import org.koitharu.kotatsu.browser.cloudflare.CloudFlareActivity
|
||||
import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException
|
||||
import org.koitharu.kotatsu.core.exceptions.InteractiveActionRequiredException
|
||||
import org.koitharu.kotatsu.core.exceptions.ProxyConfigException
|
||||
import org.koitharu.kotatsu.core.exceptions.UnsupportedSourceException
|
||||
import org.koitharu.kotatsu.core.nav.AppRouter
|
||||
@@ -43,6 +45,9 @@ class ExceptionResolver @AssistedInject constructor(
|
||||
) {
|
||||
private val continuations = MutableScatterMap<String, Continuation<Boolean>>(1)
|
||||
|
||||
private val browserActionContract = host.registerForActivityResult(BrowserActivity.Contract()) {
|
||||
handleActivityResult(BrowserActivity.TAG, true)
|
||||
}
|
||||
private val sourceAuthContract = host.registerForActivityResult(SourceAuthActivity.Contract()) {
|
||||
handleActivityResult(SourceAuthActivity.TAG, it)
|
||||
}
|
||||
@@ -63,6 +68,8 @@ class ExceptionResolver @AssistedInject constructor(
|
||||
false
|
||||
}
|
||||
|
||||
is InteractiveActionRequiredException -> resolveBrowserAction(e)
|
||||
|
||||
is ProxyConfigException -> {
|
||||
host.router()?.openProxySettings()
|
||||
false
|
||||
@@ -93,6 +100,13 @@ class ExceptionResolver @AssistedInject constructor(
|
||||
else -> false
|
||||
}
|
||||
|
||||
private suspend fun resolveBrowserAction(
|
||||
e: InteractiveActionRequiredException
|
||||
): Boolean = suspendCoroutine { cont ->
|
||||
continuations[BrowserActivity.TAG] = cont
|
||||
browserActionContract.launch(e)
|
||||
}
|
||||
|
||||
private suspend fun resolveCF(e: CloudFlareProtectedException): Boolean = suspendCoroutine { cont ->
|
||||
continuations[CloudFlareActivity.TAG] = cont
|
||||
cloudflareContract.launch(e)
|
||||
@@ -171,6 +185,8 @@ class ExceptionResolver @AssistedInject constructor(
|
||||
|
||||
is ProxyConfigException -> R.string.settings
|
||||
|
||||
is InteractiveActionRequiredException -> R.string._continue
|
||||
|
||||
else -> 0
|
||||
}
|
||||
|
||||
|
||||
@@ -207,12 +207,7 @@ class AppRouter private constructor(
|
||||
fun openDirectoriesSettings() = startActivity(MangaDirectoriesActivity::class.java)
|
||||
|
||||
fun openBrowser(url: String, source: MangaSource?, title: String?) {
|
||||
startActivity(
|
||||
Intent(contextOrNull() ?: return, BrowserActivity::class.java)
|
||||
.setData(url.toUri())
|
||||
.putExtra(KEY_TITLE, title)
|
||||
.putExtra(KEY_SOURCE, source?.name),
|
||||
)
|
||||
startActivity(browserIntent(contextOrNull() ?: return, url, source, title))
|
||||
}
|
||||
|
||||
fun openColorFilterConfig(manga: Manga, page: MangaPage) {
|
||||
@@ -708,6 +703,16 @@ class AppRouter private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun browserIntent(
|
||||
context: Context,
|
||||
url: String,
|
||||
source: MangaSource?,
|
||||
title: String?
|
||||
): Intent = Intent(context, BrowserActivity::class.java)
|
||||
.setData(url.toUri())
|
||||
.putExtra(KEY_TITLE, title)
|
||||
.putExtra(KEY_SOURCE, source?.name)
|
||||
|
||||
fun suggestionsIntent(context: Context) = Intent(context, SuggestionsActivity::class.java)
|
||||
|
||||
fun homeIntent(context: Context) = Intent(context, MainActivity::class.java)
|
||||
|
||||
@@ -15,6 +15,7 @@ import okhttp3.OkHttpClient
|
||||
import okhttp3.Response
|
||||
import okhttp3.ResponseBody.Companion.asResponseBody
|
||||
import okio.Buffer
|
||||
import org.koitharu.kotatsu.core.exceptions.InteractiveActionRequiredException
|
||||
import org.koitharu.kotatsu.core.image.BitmapDecoderCompat
|
||||
import org.koitharu.kotatsu.core.network.MangaHttpClient
|
||||
import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar
|
||||
@@ -26,6 +27,7 @@ import org.koitharu.kotatsu.core.util.ext.toList
|
||||
import org.koitharu.kotatsu.core.util.ext.toMimeType
|
||||
import org.koitharu.kotatsu.core.util.ext.use
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaParser
|
||||
import org.koitharu.kotatsu.parsers.bitmap.Bitmap
|
||||
import org.koitharu.kotatsu.parsers.config.MangaSourceConfig
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
@@ -77,6 +79,11 @@ class MangaLoaderContextImpl @Inject constructor(
|
||||
return LocaleListCompat.getAdjustedDefault().toList()
|
||||
}
|
||||
|
||||
override fun requestBrowserAction(
|
||||
parser: MangaParser,
|
||||
url: String,
|
||||
): Nothing = throw InteractiveActionRequiredException(parser.source, url)
|
||||
|
||||
override fun redrawImageResponse(response: Response, redraw: (image: Bitmap) -> Bitmap): Response {
|
||||
return response.map { body ->
|
||||
BitmapDecoderCompat.decode(body.byteStream(), body.contentType()?.toMimeType(), isMutable = true)
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.koitharu.kotatsu.core.exceptions.CloudFlareBlockedException
|
||||
import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException
|
||||
import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException
|
||||
import org.koitharu.kotatsu.core.exceptions.IncompatiblePluginException
|
||||
import org.koitharu.kotatsu.core.exceptions.InteractiveActionRequiredException
|
||||
import org.koitharu.kotatsu.core.exceptions.NoDataReceivedException
|
||||
import org.koitharu.kotatsu.core.exceptions.NonFileUriException
|
||||
import org.koitharu.kotatsu.core.exceptions.ProxyConfigException
|
||||
@@ -68,6 +69,7 @@ private fun Throwable.getDisplayMessageOrNull(resources: Resources): String? = w
|
||||
)
|
||||
|
||||
is AuthRequiredException -> resources.getString(R.string.auth_required)
|
||||
is InteractiveActionRequiredException -> resources.getString(R.string.additional_action_required)
|
||||
is CloudFlareProtectedException -> resources.getString(R.string.captcha_required_message)
|
||||
is CloudFlareBlockedException -> resources.getString(R.string.blocked_by_server_message)
|
||||
is ActivityNotFoundException,
|
||||
@@ -132,7 +134,7 @@ private fun Throwable.getDisplayMessageOrNull(resources: Resources): String? = w
|
||||
}.takeUnless { it.isNullOrBlank() }
|
||||
|
||||
@DrawableRes
|
||||
fun Throwable.getDisplayIcon() = when (this) {
|
||||
fun Throwable.getDisplayIcon(): Int = when (this) {
|
||||
is AuthRequiredException -> R.drawable.ic_auth_key_large
|
||||
is CloudFlareProtectedException -> R.drawable.ic_bot_large
|
||||
is UnknownHostException,
|
||||
@@ -143,6 +145,7 @@ fun Throwable.getDisplayIcon() = when (this) {
|
||||
|
||||
is CloudFlareBlockedException -> R.drawable.ic_denied_large
|
||||
|
||||
is InteractiveActionRequiredException -> R.drawable.ic_interaction_large
|
||||
else -> R.drawable.ic_error_large
|
||||
}
|
||||
|
||||
@@ -155,6 +158,7 @@ fun Throwable.getCauseUrl(): String? = when (this) {
|
||||
is NoDataReceivedException -> url
|
||||
is CloudFlareBlockedException -> url
|
||||
is CloudFlareProtectedException -> url
|
||||
is InteractiveActionRequiredException -> url
|
||||
is HttpStatusException -> url
|
||||
is HttpException -> (response.delegate as? Response)?.request?.url?.toString()
|
||||
else -> null
|
||||
|
||||
12
app/src/main/res/drawable/ic_interaction_large.xml
Normal file
12
app/src/main/res/drawable/ic_interaction_large.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#000"
|
||||
android:pathData="M13 5C15.21 5 17 6.79 17 9C17 10.5 16.2 11.77 15 12.46V11.24C15.61 10.69 16 9.89 16 9C16 7.34 14.66 6 13 6S10 7.34 10 9C10 9.89 10.39 10.69 11 11.24V12.46C9.8 11.77 9 10.5 9 9C9 6.79 10.79 5 13 5M20 20.5C19.97 21.32 19.32 21.97 18.5 22H13C12.62 22 12.26 21.85 12 21.57L8 17.37L8.74 16.6C8.93 16.39 9.2 16.28 9.5 16.28H9.7L12 18V9C12 8.45 12.45 8 13 8S14 8.45 14 9V13.47L15.21 13.6L19.15 15.79C19.68 16.03 20 16.56 20 17.14V20.5M20 2H4C2.9 2 2 2.9 2 4V12C2 13.11 2.9 14 4 14H8V12L4 12L4 4H20L20 12H18V14H20V13.96L20.04 14C21.13 14 22 13.09 22 12V4C22 2.9 21.11 2 20 2Z" />
|
||||
</vector>
|
||||
@@ -836,4 +836,5 @@
|
||||
<string name="dont_ask_again">Don\'t ask again</string>
|
||||
<string name="incognito_mode_hint_nsfw">This manga may contain adult content. Do you want to use incognito mode?</string>
|
||||
<string name="incognito_for_nsfw">Incognito mode for NSFW manga</string>
|
||||
<string name="additional_action_required">Additional action is required</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user