diff --git a/app/build.gradle b/app/build.gradle
index 8c4c64798..0f51ebe02 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -179,6 +179,7 @@ dependencies {
implementation libs.conscrypt.android
debugImplementation libs.leakcanary.android
+ nightlyImplementation libs.leakcanary.android
debugImplementation libs.workinspector
testImplementation libs.junit
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 4aa9c02b2..25e2daa2a 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
@@ -52,6 +52,7 @@ import java.net.SocketException
import java.net.SocketTimeoutException
import java.net.UnknownHostException
import java.util.Locale
+import java.util.zip.ZipException
private const val MSG_NO_SPACE_LEFT = "No space left on device"
private const val MSG_CONNECTION_RESET = "Connection reset"
@@ -92,6 +93,7 @@ private fun Throwable.getDisplayMessageOrNull(resources: Resources): String? = w
}
}
+ is ZipException -> resources.getString(R.string.error_corrupted_zip, this.message.orEmpty())
is SQLiteFullException -> resources.getString(R.string.error_no_space_left)
is UnsupportedFileException -> resources.getString(R.string.text_file_not_supported)
is BadBackupFormatException -> resources.getString(R.string.unsupported_backup_message)
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index c42a30453..4b14b5788 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -859,4 +859,5 @@
Main screen
Show floating Continue button
Allows to continue reading in a one click. This button will not appear in incognito mode or when the history is empty
+ Corrupted ZIP archive (%s)
diff --git a/app/src/nightly/kotlin/org/koitharu/kotatsu/KotatsuApp.kt b/app/src/nightly/kotlin/org/koitharu/kotatsu/KotatsuApp.kt
index 983e1297c..cc96dd243 100644
--- a/app/src/nightly/kotlin/org/koitharu/kotatsu/KotatsuApp.kt
+++ b/app/src/nightly/kotlin/org/koitharu/kotatsu/KotatsuApp.kt
@@ -1,5 +1,34 @@
package org.koitharu.kotatsu
+import android.content.Context
+import android.content.SharedPreferences
+import androidx.preference.PreferenceManager
+import leakcanary.LeakCanary
import org.koitharu.kotatsu.core.BaseApp
-class KotatsuApp : BaseApp()
+class KotatsuApp : BaseApp(), SharedPreferences.OnSharedPreferenceChangeListener {
+
+ override fun attachBaseContext(base: Context) {
+ super.attachBaseContext(base)
+ val prefs = PreferenceManager.getDefaultSharedPreferences(this)
+ configureLeakCanary(isEnabled = prefs.getBoolean(KEY_LEAK_CANARY, false))
+ prefs.registerOnSharedPreferenceChangeListener(this)
+ }
+
+ override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String?) {
+ if (key == KEY_LEAK_CANARY) {
+ configureLeakCanary(sharedPreferences.getBoolean(KEY_LEAK_CANARY, false))
+ }
+ }
+
+ private fun configureLeakCanary(isEnabled: Boolean) {
+ LeakCanary.config = LeakCanary.config.copy(
+ dumpHeap = isEnabled,
+ )
+ }
+
+ private companion object {
+
+ const val KEY_LEAK_CANARY = "debug.leak_canary"
+ }
+}
diff --git a/app/src/nightly/kotlin/org/koitharu/kotatsu/settings/DebugSettingsFragment.kt b/app/src/nightly/kotlin/org/koitharu/kotatsu/settings/DebugSettingsFragment.kt
new file mode 100644
index 000000000..0f8e60cb0
--- /dev/null
+++ b/app/src/nightly/kotlin/org/koitharu/kotatsu/settings/DebugSettingsFragment.kt
@@ -0,0 +1,32 @@
+package org.koitharu.kotatsu.settings
+
+import android.os.Bundle
+import androidx.preference.Preference
+import leakcanary.LeakCanary
+import org.koitharu.kotatsu.R
+import org.koitharu.kotatsu.core.ui.BasePreferenceFragment
+import org.koitharu.kotatsu.settings.utils.SplitSwitchPreference
+
+class DebugSettingsFragment : BasePreferenceFragment(R.string.debug), Preference.OnPreferenceClickListener {
+
+ override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
+ addPreferencesFromResource(R.xml.pref_debug)
+ findPreference(KEY_LEAK_CANARY)?.let { pref ->
+ pref.onContainerClickListener = this
+ }
+ }
+
+ override fun onPreferenceClick(preference: Preference): Boolean = when (preference.key) {
+ KEY_LEAK_CANARY -> {
+ startActivity(LeakCanary.newLeakDisplayActivityIntent())
+ true
+ }
+
+ else -> super.onPreferenceTreeClick(preference)
+ }
+
+ private companion object {
+
+ const val KEY_LEAK_CANARY = "debug.leak_canary"
+ }
+}
diff --git a/app/src/nightly/res/drawable/ic_debug.xml b/app/src/nightly/res/drawable/ic_debug.xml
new file mode 100644
index 000000000..82391c50e
--- /dev/null
+++ b/app/src/nightly/res/drawable/ic_debug.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/nightly/res/values/bools.xml b/app/src/nightly/res/values/bools.xml
new file mode 100644
index 000000000..184d0d82a
--- /dev/null
+++ b/app/src/nightly/res/values/bools.xml
@@ -0,0 +1,5 @@
+
+
+ false
+ true
+
diff --git a/app/src/nightly/res/values/strings.xml b/app/src/nightly/res/values/strings.xml
index c73c49bd9..897415a9a 100644
--- a/app/src/nightly/res/values/strings.xml
+++ b/app/src/nightly/res/values/strings.xml
@@ -1,3 +1,4 @@
Kotatsu Nightly
+ May affect performance
diff --git a/app/src/nightly/res/xml/pref_debug.xml b/app/src/nightly/res/xml/pref_debug.xml
new file mode 100644
index 000000000..a771fc4e7
--- /dev/null
+++ b/app/src/nightly/res/xml/pref_debug.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/app/src/nightly/res/xml/pref_root_debug.xml b/app/src/nightly/res/xml/pref_root_debug.xml
index 33ea42ab9..4d36aaccb 100644
--- a/app/src/nightly/res/xml/pref_root_debug.xml
+++ b/app/src/nightly/res/xml/pref_root_debug.xml
@@ -1,2 +1,11 @@
-
+
+
+
+
+