From b3f748c0000ebdebdcb76ef55eb71f9f2f64d184 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Thu, 9 Jan 2025 08:19:43 +0200 Subject: [PATCH] Fix crashes (cherry picked from commit 4dba90361c4c1552b5a0d5de5e25e56444f24325) --- app/src/main/AndroidManifest.xml | 2 +- .../core/exceptions/CaughtException.kt | 4 +++- .../core/exceptions/WrapperIOException.kt | 5 +++++ .../kotatsu/core/network/AppProxySelector.kt | 2 +- .../kotatsu/core/network/GZipInterceptor.kt | 19 +++++++++++++------ .../kotatsu/core/util/ext/Throwable.kt | 11 +++++++++-- .../koitharu/kotatsu/local/data/PagesCache.kt | 1 + .../kotatsu/reader/domain/PageLoader.kt | 3 ++- .../kotatsu/reader/ui/ReaderInfoBarView.kt | 3 +++ .../koitharu/kotatsu/widget/WidgetUpdater.kt | 2 +- app/src/main/res/values/bools.xml | 1 + app/src/release/res/values/bools.xml | 5 +++++ 12 files changed, 45 insertions(+), 13 deletions(-) create mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/WrapperIOException.kt create mode 100644 app/src/release/res/values/bools.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e441e910f..48e80815b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -46,7 +46,7 @@ android:allowBackup="true" android:backupAgent="org.koitharu.kotatsu.settings.backup.AppBackupAgent" android:dataExtractionRules="@xml/backup_rules" - android:enableOnBackInvokedCallback="true" + android:enableOnBackInvokedCallback="@bool/is_predictive_back_enabled" android:fullBackupContent="@xml/backup_content" android:fullBackupOnly="true" android:icon="@mipmap/ic_launcher" diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/CaughtException.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/CaughtException.kt index 3548c0872..d606b4c6e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/CaughtException.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/CaughtException.kt @@ -1,3 +1,5 @@ package org.koitharu.kotatsu.core.exceptions -class CaughtException(cause: Throwable) : RuntimeException("${cause.javaClass.simpleName}(${cause.message})", cause) +class CaughtException( + override val cause: Throwable +) : RuntimeException("${cause.javaClass.simpleName}(${cause.message})", cause) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/WrapperIOException.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/WrapperIOException.kt new file mode 100644 index 000000000..d9c9c7aa9 --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/WrapperIOException.kt @@ -0,0 +1,5 @@ +package org.koitharu.kotatsu.core.exceptions + +import okio.IOException + +class WrapperIOException(override val cause: Exception) : IOException(cause) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/network/AppProxySelector.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/AppProxySelector.kt index 1424f1f31..4ac33ad07 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/network/AppProxySelector.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/AppProxySelector.kt @@ -35,7 +35,7 @@ class AppProxySelector( if (type == Proxy.Type.DIRECT) { return Proxy.NO_PROXY } - if (address.isNullOrEmpty() || port == 0) { + if (address.isNullOrEmpty() || port < 0 || port > 0xFFFF) { throw ProxyConfigException() } cachedProxy?.let { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/network/GZipInterceptor.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/GZipInterceptor.kt index 09a544105..f4f666dfb 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/network/GZipInterceptor.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/GZipInterceptor.kt @@ -1,19 +1,26 @@ package org.koitharu.kotatsu.core.network import okhttp3.Interceptor +import okhttp3.MultipartBody import okhttp3.Response import okio.IOException +import org.koitharu.kotatsu.core.exceptions.WrapperIOException import org.koitharu.kotatsu.core.network.CommonHeaders.CONTENT_ENCODING class GZipInterceptor : Interceptor { - override fun intercept(chain: Interceptor.Chain): Response { - val newRequest = chain.request().newBuilder() - newRequest.addHeader(CONTENT_ENCODING, "gzip") - return try { + override fun intercept(chain: Interceptor.Chain): Response = try { + val request = chain.request() + if (request.body is MultipartBody) { + chain.proceed(request) + } else { + val newRequest = request.newBuilder() + newRequest.addHeader(CONTENT_ENCODING, "gzip") chain.proceed(newRequest.build()) - } catch (e: NullPointerException) { - throw IOException(e) } + } catch (e: IOException) { + throw e + } catch (e: Exception) { + throw WrapperIOException(e) } } 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 5811cfa65..c201853cf 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 @@ -24,6 +24,7 @@ import org.koitharu.kotatsu.core.exceptions.ProxyConfigException import org.koitharu.kotatsu.core.exceptions.SyncApiException import org.koitharu.kotatsu.core.exceptions.UnsupportedFileException import org.koitharu.kotatsu.core.exceptions.UnsupportedSourceException +import org.koitharu.kotatsu.core.exceptions.WrapperIOException import org.koitharu.kotatsu.core.exceptions.WrongPasswordException import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.io.NullOutputStream @@ -54,6 +55,8 @@ fun Throwable.getDisplayMessage(resources: Resources): String = getDisplayMessag ?: resources.getString(R.string.error_occurred) private fun Throwable.getDisplayMessageOrNull(resources: Resources): String? = when (this) { + is CaughtException -> cause.getDisplayMessageOrNull(resources) + is WrapperIOException -> cause.getDisplayMessageOrNull(resources) is ScrobblerAuthRequiredException -> resources.getString( R.string.scrobbler_auth_required, resources.getString(scrobbler.titleResId), @@ -141,7 +144,8 @@ fun Throwable.getCauseUrl(): String? = when (this) { is ParseException -> url is NotFoundException -> url is TooManyRequestExceptions -> url - is CaughtException -> cause?.getCauseUrl() + is CaughtException -> cause.getCauseUrl() + is WrapperIOException -> cause.getCauseUrl() is NoDataReceivedException -> url is CloudFlareBlockedException -> url is CloudFlareProtectedException -> url @@ -175,7 +179,10 @@ fun Throwable.isReportable(): Boolean { return true } if (this is CaughtException) { - return cause?.isReportable() == true + return cause.isReportable() + } + if (this is WrapperIOException) { + return cause.isReportable() } if (ExceptionResolver.canResolve(this)) { return false diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/PagesCache.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/PagesCache.kt index 3b8a9dd11..b4a414dfa 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/PagesCache.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/PagesCache.kt @@ -22,6 +22,7 @@ import org.koitharu.kotatsu.core.util.ext.subdir import org.koitharu.kotatsu.core.util.ext.takeIfReadable import org.koitharu.kotatsu.core.util.ext.takeIfWriteable import org.koitharu.kotatsu.core.util.ext.writeAllCancellable +import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.parsers.util.suspendlazy.suspendLazy import java.io.File diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/PageLoader.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/PageLoader.kt index 04b5759b4..0e05ea9a1 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/PageLoader.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/PageLoader.kt @@ -185,7 +185,7 @@ class PageLoader @Inject constructor( prefetchLock.withLock { while (prefetchQueue.isNotEmpty()) { val page = prefetchQueue.pollFirst() ?: return@launch - if (cache.get(page.url) == null) { + if (cache.get(page.url) == null) { // FIXME use pageUrl synchronized(tasks) { tasks[page.id] = loadPageAsyncImpl(page, skipCache = false, isPrefetch = true) } @@ -203,6 +203,7 @@ class PageLoader @Inject constructor( val progress = MutableStateFlow(PROGRESS_UNDEFINED) val deferred = loaderScope.async { if (!skipCache) { + // FIXME use pageUrl cache.get(page.url)?.let { return@async it.toUri() } } counter.incrementAndGet() diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderInfoBarView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderInfoBarView.kt index 7a5ca06d2..34bca6de8 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderInfoBarView.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderInfoBarView.kt @@ -209,6 +209,9 @@ class ReaderInfoBarView @JvmOverloads constructor( } private fun Drawable.drawWithOutline(canvas: Canvas) { + if (bounds.isEmpty) { + return + } var requiredScale = (bounds.width() + paint.strokeWidth * 2f) / bounds.width().toFloat() setTint(colorOutline) canvas.withScale(requiredScale, requiredScale, bounds.exactCenterX(), bounds.exactCenterY()) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/widget/WidgetUpdater.kt b/app/src/main/kotlin/org/koitharu/kotatsu/widget/WidgetUpdater.kt index c5fd21e71..1508ec24a 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/widget/WidgetUpdater.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/widget/WidgetUpdater.kt @@ -30,7 +30,7 @@ class WidgetUpdater @Inject constructor( private fun updateWidgets(cls: Class<*>) { val intent = Intent(context, cls) intent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE - val ids = AppWidgetManager.getInstance(context) + val ids = (AppWidgetManager.getInstance(context) ?: return) .getAppWidgetIds(ComponentName(context, cls)) intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids) context.sendBroadcast(intent) diff --git a/app/src/main/res/values/bools.xml b/app/src/main/res/values/bools.xml index 8a68dc46b..dee4d7e61 100644 --- a/app/src/main/res/values/bools.xml +++ b/app/src/main/res/values/bools.xml @@ -6,4 +6,5 @@ true false true + true diff --git a/app/src/release/res/values/bools.xml b/app/src/release/res/values/bools.xml new file mode 100644 index 000000000..a491a51a2 --- /dev/null +++ b/app/src/release/res/values/bools.xml @@ -0,0 +1,5 @@ + + + + false +