Fix crashes

(cherry picked from commit 4dba90361c)
master
Koitharu 1 year ago
parent 58a9f7b25a
commit b3f748c000
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -46,7 +46,7 @@
android:allowBackup="true" android:allowBackup="true"
android:backupAgent="org.koitharu.kotatsu.settings.backup.AppBackupAgent" android:backupAgent="org.koitharu.kotatsu.settings.backup.AppBackupAgent"
android:dataExtractionRules="@xml/backup_rules" android:dataExtractionRules="@xml/backup_rules"
android:enableOnBackInvokedCallback="true" android:enableOnBackInvokedCallback="@bool/is_predictive_back_enabled"
android:fullBackupContent="@xml/backup_content" android:fullBackupContent="@xml/backup_content"
android:fullBackupOnly="true" android:fullBackupOnly="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"

@ -1,3 +1,5 @@
package org.koitharu.kotatsu.core.exceptions 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)

@ -0,0 +1,5 @@
package org.koitharu.kotatsu.core.exceptions
import okio.IOException
class WrapperIOException(override val cause: Exception) : IOException(cause)

@ -35,7 +35,7 @@ class AppProxySelector(
if (type == Proxy.Type.DIRECT) { if (type == Proxy.Type.DIRECT) {
return Proxy.NO_PROXY return Proxy.NO_PROXY
} }
if (address.isNullOrEmpty() || port == 0) { if (address.isNullOrEmpty() || port < 0 || port > 0xFFFF) {
throw ProxyConfigException() throw ProxyConfigException()
} }
cachedProxy?.let { cachedProxy?.let {

@ -1,19 +1,26 @@
package org.koitharu.kotatsu.core.network package org.koitharu.kotatsu.core.network
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.MultipartBody
import okhttp3.Response import okhttp3.Response
import okio.IOException import okio.IOException
import org.koitharu.kotatsu.core.exceptions.WrapperIOException
import org.koitharu.kotatsu.core.network.CommonHeaders.CONTENT_ENCODING import org.koitharu.kotatsu.core.network.CommonHeaders.CONTENT_ENCODING
class GZipInterceptor : Interceptor { class GZipInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response { override fun intercept(chain: Interceptor.Chain): Response = try {
val newRequest = chain.request().newBuilder() val request = chain.request()
if (request.body is MultipartBody) {
chain.proceed(request)
} else {
val newRequest = request.newBuilder()
newRequest.addHeader(CONTENT_ENCODING, "gzip") newRequest.addHeader(CONTENT_ENCODING, "gzip")
return try {
chain.proceed(newRequest.build()) chain.proceed(newRequest.build())
} catch (e: NullPointerException) {
throw IOException(e)
} }
} catch (e: IOException) {
throw e
} catch (e: Exception) {
throw WrapperIOException(e)
} }
} }

@ -24,6 +24,7 @@ import org.koitharu.kotatsu.core.exceptions.ProxyConfigException
import org.koitharu.kotatsu.core.exceptions.SyncApiException import org.koitharu.kotatsu.core.exceptions.SyncApiException
import org.koitharu.kotatsu.core.exceptions.UnsupportedFileException import org.koitharu.kotatsu.core.exceptions.UnsupportedFileException
import org.koitharu.kotatsu.core.exceptions.UnsupportedSourceException 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.WrongPasswordException
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
import org.koitharu.kotatsu.core.io.NullOutputStream import org.koitharu.kotatsu.core.io.NullOutputStream
@ -54,6 +55,8 @@ fun Throwable.getDisplayMessage(resources: Resources): String = getDisplayMessag
?: resources.getString(R.string.error_occurred) ?: resources.getString(R.string.error_occurred)
private fun Throwable.getDisplayMessageOrNull(resources: Resources): String? = when (this) { private fun Throwable.getDisplayMessageOrNull(resources: Resources): String? = when (this) {
is CaughtException -> cause.getDisplayMessageOrNull(resources)
is WrapperIOException -> cause.getDisplayMessageOrNull(resources)
is ScrobblerAuthRequiredException -> resources.getString( is ScrobblerAuthRequiredException -> resources.getString(
R.string.scrobbler_auth_required, R.string.scrobbler_auth_required,
resources.getString(scrobbler.titleResId), resources.getString(scrobbler.titleResId),
@ -141,7 +144,8 @@ fun Throwable.getCauseUrl(): String? = when (this) {
is ParseException -> url is ParseException -> url
is NotFoundException -> url is NotFoundException -> url
is TooManyRequestExceptions -> url is TooManyRequestExceptions -> url
is CaughtException -> cause?.getCauseUrl() is CaughtException -> cause.getCauseUrl()
is WrapperIOException -> cause.getCauseUrl()
is NoDataReceivedException -> url is NoDataReceivedException -> url
is CloudFlareBlockedException -> url is CloudFlareBlockedException -> url
is CloudFlareProtectedException -> url is CloudFlareProtectedException -> url
@ -175,7 +179,10 @@ fun Throwable.isReportable(): Boolean {
return true return true
} }
if (this is CaughtException) { if (this is CaughtException) {
return cause?.isReportable() == true return cause.isReportable()
}
if (this is WrapperIOException) {
return cause.isReportable()
} }
if (ExceptionResolver.canResolve(this)) { if (ExceptionResolver.canResolve(this)) {
return false return false

@ -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.takeIfReadable
import org.koitharu.kotatsu.core.util.ext.takeIfWriteable import org.koitharu.kotatsu.core.util.ext.takeIfWriteable
import org.koitharu.kotatsu.core.util.ext.writeAllCancellable 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.runCatchingCancellable
import org.koitharu.kotatsu.parsers.util.suspendlazy.suspendLazy import org.koitharu.kotatsu.parsers.util.suspendlazy.suspendLazy
import java.io.File import java.io.File

@ -185,7 +185,7 @@ class PageLoader @Inject constructor(
prefetchLock.withLock { prefetchLock.withLock {
while (prefetchQueue.isNotEmpty()) { while (prefetchQueue.isNotEmpty()) {
val page = prefetchQueue.pollFirst() ?: return@launch val page = prefetchQueue.pollFirst() ?: return@launch
if (cache.get(page.url) == null) { if (cache.get(page.url) == null) { // FIXME use pageUrl
synchronized(tasks) { synchronized(tasks) {
tasks[page.id] = loadPageAsyncImpl(page, skipCache = false, isPrefetch = true) tasks[page.id] = loadPageAsyncImpl(page, skipCache = false, isPrefetch = true)
} }
@ -203,6 +203,7 @@ class PageLoader @Inject constructor(
val progress = MutableStateFlow(PROGRESS_UNDEFINED) val progress = MutableStateFlow(PROGRESS_UNDEFINED)
val deferred = loaderScope.async { val deferred = loaderScope.async {
if (!skipCache) { if (!skipCache) {
// FIXME use pageUrl
cache.get(page.url)?.let { return@async it.toUri() } cache.get(page.url)?.let { return@async it.toUri() }
} }
counter.incrementAndGet() counter.incrementAndGet()

@ -209,6 +209,9 @@ class ReaderInfoBarView @JvmOverloads constructor(
} }
private fun Drawable.drawWithOutline(canvas: Canvas) { private fun Drawable.drawWithOutline(canvas: Canvas) {
if (bounds.isEmpty) {
return
}
var requiredScale = (bounds.width() + paint.strokeWidth * 2f) / bounds.width().toFloat() var requiredScale = (bounds.width() + paint.strokeWidth * 2f) / bounds.width().toFloat()
setTint(colorOutline) setTint(colorOutline)
canvas.withScale(requiredScale, requiredScale, bounds.exactCenterX(), bounds.exactCenterY()) { canvas.withScale(requiredScale, requiredScale, bounds.exactCenterX(), bounds.exactCenterY()) {

@ -30,7 +30,7 @@ class WidgetUpdater @Inject constructor(
private fun updateWidgets(cls: Class<*>) { private fun updateWidgets(cls: Class<*>) {
val intent = Intent(context, cls) val intent = Intent(context, cls)
intent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE intent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
val ids = AppWidgetManager.getInstance(context) val ids = (AppWidgetManager.getInstance(context) ?: return)
.getAppWidgetIds(ComponentName(context, cls)) .getAppWidgetIds(ComponentName(context, cls))
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids) intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)
context.sendBroadcast(intent) context.sendBroadcast(intent)

@ -6,4 +6,5 @@
<bool name="com_samsung_android_icon_container_has_icon_container">true</bool> <bool name="com_samsung_android_icon_container_has_icon_container">true</bool>
<bool name="is_color_themes_available">false</bool> <bool name="is_color_themes_available">false</bool>
<bool name="is_sync_enabled">true</bool> <bool name="is_sync_enabled">true</bool>
<bool name="is_predictive_back_enabled">true</bool>
</resources> </resources>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Disable predictive back due to crashes -->
<bool name="is_predictive_back_enabled">false</bool>
</resources>
Loading…
Cancel
Save