|
|
|
@ -8,9 +8,10 @@ import androidx.collection.MutableScatterMap
|
|
|
|
import androidx.fragment.app.Fragment
|
|
|
|
import androidx.fragment.app.Fragment
|
|
|
|
import androidx.fragment.app.FragmentActivity
|
|
|
|
import androidx.fragment.app.FragmentActivity
|
|
|
|
import androidx.fragment.app.FragmentManager
|
|
|
|
import androidx.fragment.app.FragmentManager
|
|
|
|
import dagger.assisted.Assisted
|
|
|
|
import androidx.lifecycle.Lifecycle
|
|
|
|
import dagger.assisted.AssistedFactory
|
|
|
|
import androidx.lifecycle.LifecycleOwner
|
|
|
|
import dagger.assisted.AssistedInject
|
|
|
|
import androidx.lifecycle.lifecycleScope
|
|
|
|
|
|
|
|
import kotlinx.coroutines.async
|
|
|
|
import org.koitharu.kotatsu.R
|
|
|
|
import org.koitharu.kotatsu.R
|
|
|
|
import org.koitharu.kotatsu.browser.BrowserActivity
|
|
|
|
import org.koitharu.kotatsu.browser.BrowserActivity
|
|
|
|
import org.koitharu.kotatsu.browser.cloudflare.CloudFlareActivity
|
|
|
|
import org.koitharu.kotatsu.browser.cloudflare.CloudFlareActivity
|
|
|
|
@ -32,14 +33,15 @@ import org.koitharu.kotatsu.scrobbling.common.domain.ScrobblerAuthRequiredExcept
|
|
|
|
import org.koitharu.kotatsu.scrobbling.common.ui.ScrobblerAuthHelper
|
|
|
|
import org.koitharu.kotatsu.scrobbling.common.ui.ScrobblerAuthHelper
|
|
|
|
import org.koitharu.kotatsu.settings.sources.auth.SourceAuthActivity
|
|
|
|
import org.koitharu.kotatsu.settings.sources.auth.SourceAuthActivity
|
|
|
|
import java.security.cert.CertPathValidatorException
|
|
|
|
import java.security.cert.CertPathValidatorException
|
|
|
|
|
|
|
|
import javax.inject.Inject
|
|
|
|
import javax.inject.Provider
|
|
|
|
import javax.inject.Provider
|
|
|
|
import javax.net.ssl.SSLException
|
|
|
|
import javax.net.ssl.SSLException
|
|
|
|
import kotlin.coroutines.Continuation
|
|
|
|
import kotlin.coroutines.Continuation
|
|
|
|
import kotlin.coroutines.resume
|
|
|
|
import kotlin.coroutines.resume
|
|
|
|
import kotlin.coroutines.suspendCoroutine
|
|
|
|
import kotlin.coroutines.suspendCoroutine
|
|
|
|
|
|
|
|
|
|
|
|
class ExceptionResolver @AssistedInject constructor(
|
|
|
|
class ExceptionResolver private constructor(
|
|
|
|
@Assisted private val host: Host,
|
|
|
|
private val host: Host,
|
|
|
|
private val settings: AppSettings,
|
|
|
|
private val settings: AppSettings,
|
|
|
|
private val scrobblerAuthHelperProvider: Provider<ScrobblerAuthHelper>,
|
|
|
|
private val scrobblerAuthHelperProvider: Provider<ScrobblerAuthHelper>,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
@ -56,10 +58,11 @@ class ExceptionResolver @AssistedInject constructor(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fun showErrorDetails(e: Throwable, url: String? = null) {
|
|
|
|
fun showErrorDetails(e: Throwable, url: String? = null) {
|
|
|
|
host.router()?.showErrorDialog(e, url)
|
|
|
|
host.router.showErrorDialog(e, url)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
suspend fun resolve(e: Throwable): Boolean = when (e) {
|
|
|
|
suspend fun resolve(e: Throwable): Boolean = host.lifecycleScope.async {
|
|
|
|
|
|
|
|
when (e) {
|
|
|
|
is CloudFlareProtectedException -> resolveCF(e)
|
|
|
|
is CloudFlareProtectedException -> resolveCF(e)
|
|
|
|
is AuthRequiredException -> resolveAuthException(e.source)
|
|
|
|
is AuthRequiredException -> resolveAuthException(e.source)
|
|
|
|
is SSLException,
|
|
|
|
is SSLException,
|
|
|
|
@ -71,7 +74,7 @@ class ExceptionResolver @AssistedInject constructor(
|
|
|
|
is InteractiveActionRequiredException -> resolveBrowserAction(e)
|
|
|
|
is InteractiveActionRequiredException -> resolveBrowserAction(e)
|
|
|
|
|
|
|
|
|
|
|
|
is ProxyConfigException -> {
|
|
|
|
is ProxyConfigException -> {
|
|
|
|
host.router()?.openProxySettings()
|
|
|
|
host.router.openProxySettings()
|
|
|
|
false
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -99,6 +102,7 @@ class ExceptionResolver @AssistedInject constructor(
|
|
|
|
|
|
|
|
|
|
|
|
else -> false
|
|
|
|
else -> false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}.await()
|
|
|
|
|
|
|
|
|
|
|
|
private suspend fun resolveBrowserAction(
|
|
|
|
private suspend fun resolveBrowserAction(
|
|
|
|
e: InteractiveActionRequiredException
|
|
|
|
e: InteractiveActionRequiredException
|
|
|
|
@ -118,11 +122,11 @@ class ExceptionResolver @AssistedInject constructor(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private fun openInBrowser(url: String) {
|
|
|
|
private fun openInBrowser(url: String) {
|
|
|
|
host.router()?.openBrowser(url, null, null)
|
|
|
|
host.router.openBrowser(url, null, null)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private fun openAlternatives(manga: Manga) {
|
|
|
|
private fun openAlternatives(manga: Manga) {
|
|
|
|
host.router()?.openAlternatives(manga)
|
|
|
|
host.router.openAlternatives(manga)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private fun handleActivityResult(tag: String, result: Boolean) {
|
|
|
|
private fun handleActivityResult(tag: String, result: Boolean) {
|
|
|
|
@ -130,7 +134,7 @@ class ExceptionResolver @AssistedInject constructor(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private fun showSslErrorDialog() {
|
|
|
|
private fun showSslErrorDialog() {
|
|
|
|
val ctx = host.getContext() ?: return
|
|
|
|
val ctx = host.context ?: return
|
|
|
|
if (settings.isSSLBypassEnabled) {
|
|
|
|
if (settings.isSSLBypassEnabled) {
|
|
|
|
Toast.makeText(ctx, R.string.operation_not_supported, Toast.LENGTH_SHORT).show()
|
|
|
|
Toast.makeText(ctx, R.string.operation_not_supported, Toast.LENGTH_SHORT).show()
|
|
|
|
return
|
|
|
|
return
|
|
|
|
@ -147,27 +151,65 @@ class ExceptionResolver @AssistedInject constructor(
|
|
|
|
}.show()
|
|
|
|
}.show()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private inline fun Host.withContext(block: Context.() -> Unit) {
|
|
|
|
class Factory @Inject constructor(
|
|
|
|
getContext()?.apply(block)
|
|
|
|
private val settings: AppSettings,
|
|
|
|
|
|
|
|
private val scrobblerAuthHelperProvider: Provider<ScrobblerAuthHelper>,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fun create(fragment: Fragment) = ExceptionResolver(
|
|
|
|
|
|
|
|
host = Host.FragmentHost(fragment),
|
|
|
|
|
|
|
|
settings = settings,
|
|
|
|
|
|
|
|
scrobblerAuthHelperProvider = scrobblerAuthHelperProvider,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fun create(activity: FragmentActivity) = ExceptionResolver(
|
|
|
|
|
|
|
|
host = Host.ActivityHost(activity),
|
|
|
|
|
|
|
|
settings = settings,
|
|
|
|
|
|
|
|
scrobblerAuthHelperProvider = scrobblerAuthHelperProvider,
|
|
|
|
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private fun Host.router(): AppRouter? = when (this) {
|
|
|
|
private sealed interface Host : ActivityResultCaller, LifecycleOwner {
|
|
|
|
is FragmentActivity -> router
|
|
|
|
|
|
|
|
is Fragment -> router
|
|
|
|
val context: Context?
|
|
|
|
else -> null
|
|
|
|
|
|
|
|
|
|
|
|
val router: AppRouter
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val fragmentManager: FragmentManager
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline fun withContext(block: Context.() -> Unit) {
|
|
|
|
|
|
|
|
context?.apply(block)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
interface Host : ActivityResultCaller {
|
|
|
|
class ActivityHost(val activity: FragmentActivity) : Host,
|
|
|
|
|
|
|
|
ActivityResultCaller by activity,
|
|
|
|
|
|
|
|
LifecycleOwner by activity {
|
|
|
|
|
|
|
|
|
|
|
|
fun getChildFragmentManager(): FragmentManager
|
|
|
|
override val context: Context
|
|
|
|
|
|
|
|
get() = activity
|
|
|
|
|
|
|
|
|
|
|
|
fun getContext(): Context?
|
|
|
|
override val router: AppRouter
|
|
|
|
|
|
|
|
get() = activity.router
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
override val fragmentManager: FragmentManager
|
|
|
|
|
|
|
|
get() = activity.supportFragmentManager
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@AssistedFactory
|
|
|
|
class FragmentHost(val fragment: Fragment) : Host,
|
|
|
|
interface Factory {
|
|
|
|
ActivityResultCaller by fragment {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
override val context: Context?
|
|
|
|
|
|
|
|
get() = fragment.context
|
|
|
|
|
|
|
|
|
|
|
|
fun create(host: Host): ExceptionResolver
|
|
|
|
override val router: AppRouter
|
|
|
|
|
|
|
|
get() = fragment.router
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
override val fragmentManager: FragmentManager
|
|
|
|
|
|
|
|
get() = fragment.childFragmentManager
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
override val lifecycle: Lifecycle
|
|
|
|
|
|
|
|
get() = fragment.viewLifecycleOwner.lifecycle
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
companion object {
|
|
|
|
companion object {
|
|
|
|
|