@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
return Proxy.NO_PROXY
|
||||
}
|
||||
if (address.isNullOrEmpty() || port == 0) {
|
||||
if (address.isNullOrEmpty() || port < 0 || port > 0xFFFF) {
|
||||
throw ProxyConfigException()
|
||||
}
|
||||
cachedProxy?.let {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -6,4 +6,5 @@
|
||||
<bool name="com_samsung_android_icon_container_has_icon_container">true</bool>
|
||||
<bool name="is_color_themes_available">false</bool>
|
||||
<bool name="is_sync_enabled">true</bool>
|
||||
<bool name="is_predictive_back_enabled">true</bool>
|
||||
</resources>
|
||||
|
||||
5
app/src/release/res/values/bools.xml
Normal file
5
app/src/release/res/values/bools.xml
Normal file
@@ -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>
|
||||
Reference in New Issue
Block a user