diff --git a/app/src/debug/kotlin/org/koitharu/kotatsu/StrictModeNotifier.kt b/app/src/debug/kotlin/org/koitharu/kotatsu/StrictModeNotifier.kt
index 0fccd4e06..058e53c09 100644
--- a/app/src/debug/kotlin/org/koitharu/kotatsu/StrictModeNotifier.kt
+++ b/app/src/debug/kotlin/org/koitharu/kotatsu/StrictModeNotifier.kt
@@ -9,11 +9,12 @@ import android.os.Build
import android.os.StrictMode
import android.os.strictmode.Violation
import androidx.annotation.RequiresApi
+import androidx.core.app.PendingIntentCompat
import androidx.core.content.getSystemService
import androidx.fragment.app.strictmode.FragmentStrictMode
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asExecutor
-import org.koitharu.kotatsu.core.ErrorReporterReceiver
+import org.koitharu.kotatsu.core.util.ShareHelper
import kotlin.math.absoluteValue
import androidx.fragment.app.strictmode.Violation as FragmentViolation
@@ -51,7 +52,15 @@ class StrictModeNotifier(
.setSummaryText(violation.message)
.bigText(violation.stackTraceToString()),
).setShowWhen(true)
- .setContentIntent(ErrorReporterReceiver.getPendingIntent(context, violation))
+ .setContentIntent(
+ PendingIntentCompat.getActivity(
+ context,
+ 0,
+ ShareHelper(context).getShareTextIntent(violation.stackTraceToString()),
+ 0,
+ false,
+ ),
+ )
.setAutoCancel(true)
.setGroup(CHANNEL_ID)
.build()
diff --git a/app/src/debug/kotlin/org/koitharu/kotatsu/core/network/CurlLoggingInterceptor.kt b/app/src/debug/kotlin/org/koitharu/kotatsu/core/network/CurlLoggingInterceptor.kt
index 3a550ec35..e6a9ce01c 100644
--- a/app/src/debug/kotlin/org/koitharu/kotatsu/core/network/CurlLoggingInterceptor.kt
+++ b/app/src/debug/kotlin/org/koitharu/kotatsu/core/network/CurlLoggingInterceptor.kt
@@ -53,9 +53,6 @@ class CurlLoggingInterceptor(
private fun String.escape() = replace(escapeRegex) { match ->
"\\" + match.value
}
- // .replace("\"", "\\\"")
- // .replace("[", "\\[")
- // .replace("]", "\\]")
private fun log(msg: String) {
Log.d("CURL", msg)
diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ShareHelper.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ShareHelper.kt
index fc486cb4f..3fa1b6e3f 100644
--- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ShareHelper.kt
+++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ShareHelper.kt
@@ -1,6 +1,7 @@
package org.koitharu.kotatsu.core.util
import android.content.Context
+import android.content.Intent
import android.net.Uri
import androidx.core.app.ShareCompat
import androidx.core.content.FileProvider
@@ -75,11 +76,9 @@ class ShareHelper(private val context: Context) {
.startChooser()
}
- fun shareText(text: String) {
- ShareCompat.IntentBuilder(context)
- .setText(text)
- .setType(TYPE_TEXT)
- .setChooserTitle(R.string.share)
- .startChooser()
- }
+ fun getShareTextIntent(text: String): Intent = ShareCompat.IntentBuilder(context)
+ .setText(text)
+ .setType(TYPE_TEXT)
+ .setChooserTitle(R.string.share)
+ .createChooserIntent()
}
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 8f06f8487..d46cb250f 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
@@ -36,8 +36,11 @@ import org.koitharu.kotatsu.parsers.exception.NotFoundException
import org.koitharu.kotatsu.parsers.exception.ParseException
import org.koitharu.kotatsu.parsers.exception.TooManyRequestExceptions
import org.koitharu.kotatsu.scrobbling.common.domain.ScrobblerAuthRequiredException
+import java.net.ConnectException
+import java.net.NoRouteToHostException
import java.net.SocketTimeoutException
import java.net.UnknownHostException
+import java.util.Locale
private const val MSG_NO_SPACE_LEFT = "No space left on device"
private const val IMAGE_FORMAT_NOT_SUPPORTED = "Image format not supported"
@@ -82,13 +85,20 @@ private fun Throwable.getDisplayMessageOrNull(resources: Resources): String? = w
is ContentUnavailableException -> message
is ParseException -> shortMessage
+ is ConnectException,
is UnknownHostException,
+ is NoRouteToHostException,
is SocketTimeoutException -> resources.getString(R.string.network_error)
- is ImageDecodeException -> resources.getString(
- R.string.error_image_format,
- format.ifNullOrEmpty { resources.getString(R.string.unknown) },
- )
+ is ImageDecodeException -> {
+ val type = format?.substringBefore('/')
+ val formatString = format.ifNullOrEmpty { resources.getString(R.string.unknown).lowercase(Locale.getDefault()) }
+ if (type.isNullOrEmpty() || type == "image") {
+ resources.getString(R.string.error_image_format, formatString)
+ } else {
+ resources.getString(R.string.error_not_image, formatString)
+ }
+ }
is NoDataReceivedException -> resources.getString(R.string.error_no_data_received)
is IncompatiblePluginException -> {
@@ -96,6 +106,7 @@ private fun Throwable.getDisplayMessageOrNull(resources: Resources): String? = w
resources.getString(R.string.plugin_incompatible_with_cause, it)
} ?: resources.getString(R.string.plugin_incompatible)
}
+
is WrongPasswordException -> resources.getString(R.string.wrong_password)
is NotFoundException -> resources.getString(R.string.not_found_404)
is UnsupportedSourceException -> resources.getString(R.string.unsupported_source)
@@ -112,6 +123,8 @@ fun Throwable.getDisplayIcon() = when (this) {
is CloudFlareProtectedException -> R.drawable.ic_bot_large
is UnknownHostException,
is SocketTimeoutException,
+ is ConnectException,
+ is NoRouteToHostException,
is ProtocolException -> R.drawable.ic_plug_large
is CloudFlareBlockedException -> R.drawable.ic_denied_large
@@ -133,6 +146,7 @@ fun Throwable.getCauseUrl(): String? = when (this) {
private fun getHttpDisplayMessage(statusCode: Int, resources: Resources): String? = when (statusCode) {
404 -> resources.getString(R.string.not_found_404)
+ 403 -> resources.getString(R.string.access_denied_403)
in 500..599 -> resources.getString(R.string.server_error, statusCode)
else -> null
}
@@ -165,6 +179,8 @@ fun Throwable.isReportable(): Boolean {
|| this is CloudFlareProtectedException
|| this is BadBackupFormatException
|| this is WrongPasswordException
+ || this is TooManyRequestExceptions
+ || this is HttpStatusException
) {
return false
}
diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/pages/MangaPageFetcher.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/pages/MangaPageFetcher.kt
index 62e5fb898..e63304849 100644
--- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/pages/MangaPageFetcher.kt
+++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/pages/MangaPageFetcher.kt
@@ -79,16 +79,14 @@ class MangaPageFetcher(
}
}
- private fun Response.toNetworkResponse(): NetworkResponse {
- return NetworkResponse(
- code = code,
- requestMillis = sentRequestAtMillis,
- responseMillis = receivedResponseAtMillis,
- headers = headers.toNetworkHeaders(),
- body = body?.source()?.let(::NetworkResponseBody),
- delegate = this,
- )
- }
+ private fun Response.toNetworkResponse() = NetworkResponse(
+ code = code,
+ requestMillis = sentRequestAtMillis,
+ responseMillis = receivedResponseAtMillis,
+ headers = headers.toNetworkHeaders(),
+ body = body?.source()?.let(::NetworkResponseBody),
+ delegate = this,
+ )
private fun Headers.toNetworkHeaders(): NetworkHeaders {
val headers = NetworkHeaders.Builder()
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index d37afee10..4cab81d95 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -739,6 +739,7 @@
User manual
Telegram group
Unsupported image format: %s
+ Invalid format: expected image but got %s
Start download
Save selected manga? This may consume traffic and disk space
Save manga
@@ -759,4 +760,5 @@
Portrait
Landscape
"]]>
+ Access denied (403)