diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/browser/BrowserActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/browser/BrowserActivity.kt index af49d1dcd..15c03582d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/browser/BrowserActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/browser/BrowserActivity.kt @@ -14,7 +14,6 @@ import androidx.core.view.isVisible import androidx.core.view.updatePadding import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.BaseActivity -import org.koitharu.kotatsu.core.util.ext.catchingWebViewUnavailability import org.koitharu.kotatsu.databinding.ActivityBrowserBinding import org.koitharu.kotatsu.parsers.network.UserAgents import com.google.android.material.R as materialR @@ -26,7 +25,7 @@ class BrowserActivity : BaseActivity(), BrowserCallback override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - if (!catchingWebViewUnavailability { setContentView(ActivityBrowserBinding.inflate(layoutInflater)) }) { + if (!setContentViewWebViewSafe { ActivityBrowserBinding.inflate(layoutInflater) }) { return } supportActionBar?.run { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareActivity.kt index caf926f30..179ae74c8 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareActivity.kt @@ -27,7 +27,6 @@ import org.koitharu.kotatsu.core.network.CommonHeaders import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.util.TaggedActivityResult -import org.koitharu.kotatsu.core.util.ext.catchingWebViewUnavailability import org.koitharu.kotatsu.databinding.ActivityBrowserBinding import org.koitharu.kotatsu.parsers.network.UserAgents import javax.inject.Inject @@ -45,13 +44,7 @@ class CloudFlareActivity : BaseActivity(), CloudFlareCal override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - if (!catchingWebViewUnavailability { - setContentView( - ActivityBrowserBinding.inflate( - layoutInflater, - ), - ) - }) { + if (!setContentViewWebViewSafe { ActivityBrowserBinding.inflate(layoutInflater) }) { return } supportActionBar?.run { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseActivity.kt index bb27f8a59..7e889dd46 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseActivity.kt @@ -8,6 +8,7 @@ import android.os.Bundle import android.view.KeyEvent import android.view.View import android.view.ViewGroup +import android.widget.Toast import androidx.annotation.CallSuper import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.view.ActionMode @@ -29,6 +30,7 @@ import org.koitharu.kotatsu.core.ui.util.ActionModeDelegate import org.koitharu.kotatsu.core.ui.util.BaseActivityEntryPoint import org.koitharu.kotatsu.core.ui.util.WindowInsetsDelegate import org.koitharu.kotatsu.core.util.ext.getThemeColor +import org.koitharu.kotatsu.core.util.ext.isWebViewUnavailable @Suppress("LeakingThis") abstract class BaseActivity : @@ -164,6 +166,21 @@ abstract class BaseActivity : intent?.putExtra(EXTRA_DATA, intent.data) } + protected fun setContentViewWebViewSafe(viewBindingProducer: () -> B): Boolean { + return try { + setContentView(viewBindingProducer()) + true + } catch (e: Exception) { + if (e.isWebViewUnavailable()) { + Toast.makeText(this, R.string.web_view_unavailable, Toast.LENGTH_LONG).show() + finishAfterTransition() + false + } else { + throw e + } + } + } + companion object { const val EXTRA_DATA = "data" diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Android.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Android.kt index b237755a0..3e1c622a4 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Android.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Android.kt @@ -27,7 +27,6 @@ import android.provider.Settings import android.view.View import android.view.ViewPropertyAnimator import android.view.Window -import android.widget.Toast import androidx.activity.result.ActivityResultLauncher import androidx.annotation.IntegerRes import androidx.annotation.WorkerThread @@ -216,21 +215,6 @@ fun Context.findActivity(): Activity? = when (this) { else -> null } -inline fun Activity.catchingWebViewUnavailability(block: () -> Unit): Boolean { - return try { - block() - true - } catch (e: Exception) { - if (e.isWebViewUnavailable()) { - Toast.makeText(this, R.string.web_view_unavailable, Toast.LENGTH_LONG).show() - finishAfterTransition() - false - } else { - throw e - } - } -} - fun Context.checkNotificationPermission(): Boolean = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED } else { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Throwable.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Throwable.kt index 21e6e838e..aeb3de5c8 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Throwable.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Throwable.kt @@ -2,7 +2,6 @@ package org.koitharu.kotatsu.core.util.ext import android.content.ActivityNotFoundException import android.content.res.Resources -import android.util.AndroidRuntimeException import androidx.annotation.DrawableRes import androidx.collection.arraySetOf import coil.network.HttpException @@ -115,8 +114,8 @@ private val reportableExceptions = arraySetOf>( ) fun Throwable.isWebViewUnavailable(): Boolean { - return (this is AndroidRuntimeException && message?.contains("WebView") == true) || - cause?.isWebViewUnavailable() == true + val trace = stackTraceToString() + return trace.contains("android.webkit.WebView.") } @Suppress("FunctionName") diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/tapgrid/TapGridDispatcher.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/tapgrid/TapGridDispatcher.kt index 96ec3d580..9987cd4cf 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/tapgrid/TapGridDispatcher.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/tapgrid/TapGridDispatcher.kt @@ -32,7 +32,8 @@ class TapGridDispatcher( if (!isDispatching) { return true } - return listener.onGridTouch(getArea(event.rawX, event.rawY)) + val area = getArea(event.rawX, event.rawY) ?: return false + return listener.onGridTouch(area) } override fun onDoubleTapEvent(e: MotionEvent): Boolean { @@ -42,11 +43,12 @@ class TapGridDispatcher( override fun onLongPress(event: MotionEvent) { if (isDispatching) { - listener.onGridLongTouch(getArea(event.rawX, event.rawY)) + val area = getArea(event.rawX, event.rawY) ?: return + listener.onGridLongTouch(area) } } - private fun getArea(x: Float, y: Float): TapGridArea { + private fun getArea(x: Float, y: Float): TapGridArea? { val xIndex = (x * 2f / width).roundToInt() val yIndex = (y * 2f / height).roundToInt() val area = when (xIndex) { @@ -73,7 +75,8 @@ class TapGridDispatcher( else -> null } - return checkNotNull(area) { "Invalid area ($xIndex, $yIndex)" } + assert(area != null) { "Invalid area ($xIndex, $yIndex)" } + return area } interface OnGridTouchListener { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt index 7dd9ba8a2..20fe6d072 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt @@ -22,7 +22,6 @@ import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.parser.RemoteMangaRepository import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.util.TaggedActivityResult -import org.koitharu.kotatsu.core.util.ext.catchingWebViewUnavailability import org.koitharu.kotatsu.core.util.ext.getSerializableExtraCompat import org.koitharu.kotatsu.databinding.ActivityBrowserBinding import org.koitharu.kotatsu.parsers.MangaParserAuthProvider @@ -43,7 +42,7 @@ class SourceAuthActivity : BaseActivity(), BrowserCallba @SuppressLint("SetJavaScriptEnabled") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - if (!catchingWebViewUnavailability { setContentView(ActivityBrowserBinding.inflate(layoutInflater)) }) { + if (!setContentViewWebViewSafe { ActivityBrowserBinding.inflate(layoutInflater) }) { return } val source = intent?.getSerializableExtraCompat(EXTRA_SOURCE)