remove clutter code

This commit is contained in:
javlon
2023-07-17 14:49:28 +02:00
parent a8176e6589
commit 33a45ac5b3
6 changed files with 109 additions and 230 deletions

View File

@@ -1,28 +1,14 @@
package org.koitharu.kotatsu.core.backup
import android.provider.Settings
import androidx.room.withTransaction
import org.json.JSONArray
import org.json.JSONObject
import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.core.db.MangaDatabase
import org.koitharu.kotatsu.core.model.ZoomMode
import org.koitharu.kotatsu.core.network.DoHProvider
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.prefs.ColorScheme
import org.koitharu.kotatsu.core.prefs.ListMode
import org.koitharu.kotatsu.core.prefs.ReaderMode
import org.koitharu.kotatsu.core.util.ext.getEnumValue
import org.koitharu.kotatsu.core.util.ext.takeIfReadable
import org.koitharu.kotatsu.core.util.ext.toUriOrNull
import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.parsers.util.json.JSONIterator
import org.koitharu.kotatsu.parsers.util.json.getFloatOrDefault
import org.koitharu.kotatsu.parsers.util.json.getStringOrNull
import org.koitharu.kotatsu.parsers.util.json.mapJSON
import org.koitharu.kotatsu.parsers.util.mapNotNullToSet
import org.koitharu.kotatsu.parsers.util.runCatchingCancellable
import java.io.File
import javax.inject.Inject
private const val PAGE_SIZE = 10
@@ -85,9 +71,9 @@ class BackupRepository @Inject constructor(
return entry
}
suspend fun dumpSettings(): BackupEntry {
fun dumpSettings(): BackupEntry {
val entry = BackupEntry(BackupEntry.SETTINGS, JSONArray())
val json = JsonSerializer(settings).toJson()
val json = JsonSerializer(settings.getAllValues()).toJson()
entry.data.put(json)
return entry
}
@@ -157,60 +143,7 @@ class BackupRepository @Inject constructor(
val result = CompositeResult()
for (item in entry.data.JSONIterator()) {
result += runCatchingCancellable {
settings.listMode = item.getString("list_mode").getEnumValue(ListMode.GRID)
settings.theme = item.getInt("theme")
settings.colorScheme = item.getString("color_scheme").getEnumValue(ColorScheme.default)
settings.isAmoledTheme = item.getBoolean("is_amoled_theme")
settings.gridSize = item.getInt("grid_size")
settings.readerPageSwitch =
item.getJSONArray("reader_page_switch").mapJSONToSet<String, String> { it }
settings.isReaderTapsAdaptive = item.getBoolean("is_reader_taps_adaptive")
settings.isTrafficWarningEnabled = item.getBoolean("is_traffic_waring_enabled")
settings.isAllFavouritesVisible = item.getBoolean("is_all_favourites_visible")
settings.isTrackerEnabled = item.getBoolean("is_tracker_enabled")
settings.isTrackerNotificationsEnabled = item.getBoolean("is_tracker_notifications_enabled")
settings.notificationSound =
item.getString("notification_sound").toUriOrNull() ?: Settings.System.DEFAULT_NOTIFICATION_URI
settings.notificationVibrate = item.getBoolean("notification_vibrate")
settings.notificationLight = item.getBoolean("notification_light")
settings.readerAnimation = item.getBoolean("reader_animation")
settings.defaultReaderMode = item.getString("default_reader_node").getEnumValue(ReaderMode.STANDARD)
settings.isReaderModeDetectionEnabled = item.getBoolean("is_reader_mode_detection_enabled")
settings.isHistoryGroupingEnabled = item.getBoolean("is_history_grouping_enabled")
settings.isReadingIndicatorsEnabled = item.getBoolean("is_reading_indicators_enabled")
settings.isHistoryExcludeNsfw = item.getBoolean("is_history_exclude_nsfw")
settings.isIncognitoModeEnabled = item.getBoolean("is_incognito_mode_enabled")
settings.chaptersReverse = item.getBoolean("chapters_reverse")
settings.zoomMode = item.getString("zoom_mode").getEnumValue(ZoomMode.FIT_CENTER)
settings.trackSources = item.getJSONArray("track_sources").mapJSONToSet<String, String> { it }
settings.isLoggingEnabled = item.getBoolean("is_logging_enabled")
settings.isMirrorSwitchingAvailable = item.getBoolean("is_mirror_switching_available")
settings.isExitConfirmationEnabled = item.getBoolean("is_exit_confirmation_enabled")
settings.isDynamicShortcutsEnabled = item.getBoolean("is_dynamic_shortcuts_enabled")
settings.isUnstableUpdatesAllowed = item.getBoolean("is_unstable_updates_allowed")
settings.sourcesOrder = item.getJSONArray("sources_order").mapJSONToArray<String, String> { it }
settings.hiddenSources = item.getJSONArray("hidden_sources").mapJSONToSet<String, String> { it }
settings.isSourcesGridMode = item.getBoolean("is_sources_grid_mode")
settings.userSpecifiedMangaDirectories = item.getJSONArray("user_specified_manga_directions")
.mapJSONToSet<String, String> { it }.mapNotNullToSet { File(it).takeIfReadable() }
File(item.getStringOrNull("manga_storage_dir") ?: "").takeIfReadable()?.let {
settings.mangaStorageDir = it
}
settings.isDownloadsSlowdownEnabled = item.getBoolean("is_downloads_slowdown_enabled")
settings.isDownloadsWiFiOnly = item.getBoolean("is_downloads_wifi_only")
settings.isSuggestionsEnabled = item.getBoolean("is_suggestions_enabled")
settings.isSuggestionsExcludeNsfw = item.getBoolean("is_suggestions_exclude_nsfw")
settings.isSuggestionsNotificationAvailable = item.getBoolean("is_suggestions_notification_available")
settings.suggestionsTagsBlacklist =
item.getJSONArray("suggestions_tags_blacklist").mapJSONToSet<String, String> { it }
settings.isReaderBarEnabled = item.getBoolean("is_reader_bar_enabled")
settings.isReaderSliderEnabled = item.getBoolean("is_reader_slider_enabled")
settings.isImagesProxyEnabled = item.getBoolean("is_images_proxy_enabled")
settings.dnsOverHttps = item.getString("dns_over_https").getEnumValue(DoHProvider.NONE)
settings.isSSLBypassEnabled = item.getBoolean("is_ssl_bypass_enabled")
settings.localListOrder = item.getString("local_list_order").getEnumValue(SortOrder.NEWEST)
settings.isWebtoonZoomEnable = item.getBoolean("is_webtoon_zoom_enabled")
settings.readerAutoscrollSpeed = item.getFloatOrDefault("reader_autoscroll_speed", 0f)
settings.restoreValuesFromMap(JsonDeserializer(item).toMap())
}
}
return result

View File

@@ -1,5 +1,6 @@
package org.koitharu.kotatsu.core.backup
import org.json.JSONArray
import org.json.JSONObject
import org.koitharu.kotatsu.core.db.entity.MangaEntity
import org.koitharu.kotatsu.core.db.entity.TagEntity
@@ -65,4 +66,29 @@ class JsonDeserializer(private val json: JSONObject) {
isVisibleInLibrary = json.getBooleanOrDefault("show_in_lib", true),
deletedAt = 0L,
)
fun toMap(): Map<String, Any?> {
val map = mutableMapOf<String, Any?>()
val keys = json.keys()
while (keys.hasNext()) {
val key = keys.next()
val value = json.get(key)
map[key] = value
}
return map
}
}
fun <K, T> JSONArray.mapJSONToSet(block: (K) -> T): Set<T> {
val len = length()
val result = androidx.collection.ArraySet<T>(len)
for (i in 0 until len) {
val jo = get(i) as K
result.add(block(jo))
}
return result
}

View File

@@ -1,14 +1,11 @@
package org.koitharu.kotatsu.core.backup
import org.json.JSONArray
import org.json.JSONObject
import org.koitharu.kotatsu.core.db.entity.MangaEntity
import org.koitharu.kotatsu.core.db.entity.TagEntity
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.favourites.data.FavouriteCategoryEntity
import org.koitharu.kotatsu.favourites.data.FavouriteEntity
import org.koitharu.kotatsu.history.data.HistoryEntity
import java.util.ArrayList
class JsonSerializer private constructor(private val json: JSONObject) {
@@ -71,88 +68,9 @@ class JsonSerializer private constructor(private val json: JSONObject) {
},
)
constructor(e: AppSettings) : this(
JSONObject().apply {
put("list_mode", e.listMode.name)
put("theme", e.theme)
put("color_scheme", e.colorScheme.name)
put("is_amoled_theme", e.isAmoledTheme)
put("grid_size", e.gridSize)
put("reader_page_switch", JSONArray(e.readerPageSwitch))
put("is_reader_taps_adaptive", e.isReaderTapsAdaptive)
put("is_traffic_waring_enabled", e.isTrafficWarningEnabled)
put("is_all_favourites_visible", e.isAllFavouritesVisible)
put("is_tracker_enabled", e.isTrackerEnabled)
put("is_tracker_notifications_enabled", e.isTrackerNotificationsEnabled)
put("notification_sound", e.notificationSound.toString())
put("notification_vibrate", e.notificationVibrate)
put("notification_light", e.notificationLight)
put("reader_animation", e.readerAnimation)
put("default_reader_node", e.defaultReaderMode.name)
put("is_reader_mode_detection_enabled", e.isReaderModeDetectionEnabled)
put("is_history_grouping_enabled", e.isHistoryGroupingEnabled)
put("is_reading_indicators_enabled", e.isReadingIndicatorsEnabled)
put("is_history_exclude_nsfw", e.isHistoryExcludeNsfw)
put("is_incognito_mode_enabled", e.isIncognitoModeEnabled) // maybe we should omit this
put("chapters_reverse", e.chaptersReverse)
put("zoom_mode", e.zoomMode)
put("track_sources", JSONArray(e.trackSources))
put("is_logging_enabled", e.isLoggingEnabled)
put("is_mirror_switching_available", e.isMirrorSwitchingAvailable)
put("is_exit_confirmation_enabled", e.isExitConfirmationEnabled)
put("is_dynamic_shortcuts_enabled", e.isDynamicShortcutsEnabled)
put("is_unstable_updates_allowed", e.isUnstableUpdatesAllowed)
put("sources_order", JSONArray(e.sourcesOrder))
put("hidden_sources", JSONArray(e.hiddenSources))
put("is_sources_grid_mode", e.isSourcesGridMode)
put(
"user_specified_manga_directions",
JSONArray(e.userSpecifiedMangaDirectories.map { it.absolutePath }),
)
put("manga_storage_dir", e.mangaStorageDir?.absolutePath)
put("is_downloads_slowdown_enabled", e.isDownloadsSlowdownEnabled)
put("is_downloads_wifi_only", e.isDownloadsWiFiOnly)
put("is_suggestions_enabled", e.isSuggestionsEnabled)
put("is_suggestions_exclude_nsfw", e.isSuggestionsExcludeNsfw)
put("is_suggestions_notification_available", e.isSuggestionsNotificationAvailable)
put("suggestions_tags_blacklist", JSONArray(e.suggestionsTagsBlacklist))
put("is_reader_bar_enabled", e.isReaderBarEnabled)
put("is_reader_slider_enabled", e.isReaderSliderEnabled)
put("is_images_proxy_enabled", e.isImagesProxyEnabled)
put("dns_over_https", e.dnsOverHttps.name)
put("is_ssl_bypass_enabled", e.isSSLBypassEnabled)
put("local_list_order", e.localListOrder.name)
put("is_webtoon_zoom_enabled", e.isWebtoonZoomEnable)
put("reader_autoscroll_speed", e.readerAutoscrollSpeed)
},
constructor(m: Map<String, *>) : this(
JSONObject(m),
)
fun toJson(): JSONObject = json
}
// I have copied these extension functions from parser library,
// because, library doesn't support mapping primitive types (string, int, float ...),
// I didn't know where to put this extension functions :(
inline fun <K, T> JSONArray.mapJSONToArray(
block: (K) -> T,
): List<T> {
val len = length()
val result = ArrayList<T>(len)
for (i in 0 until len) {
val jo = get(i) as K
result.add(block(jo))
}
return result
}
fun <K, T> JSONArray.mapJSONToSet(block: (K) -> T): Set<T> {
val len = length()
val result = androidx.collection.ArraySet<T>(len)
for (i in 0 until len) {
val jo = get(i) as K
result.add(block(jo))
}
return result
}

View File

@@ -13,7 +13,9 @@ import androidx.core.content.edit
import androidx.core.os.LocaleListCompat
import androidx.preference.PreferenceManager
import dagger.hilt.android.qualifiers.ApplicationContext
import org.json.JSONArray
import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.core.backup.mapJSONToSet
import org.koitharu.kotatsu.core.model.ZoomMode
import org.koitharu.kotatsu.core.network.DoHProvider
import org.koitharu.kotatsu.core.util.ext.connectivityManager
@@ -72,17 +74,14 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
get() = prefs.getEnumValue(KEY_LIST_MODE, ListMode.GRID)
set(value) = prefs.edit { putEnumValue(KEY_LIST_MODE, value) }
var theme: Int
val theme: Int
get() = prefs.getString(KEY_THEME, null)?.toIntOrNull() ?: AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
set(value) = prefs.edit { putString(KEY_THEME, value.toString()) }
var colorScheme: ColorScheme
val colorScheme: ColorScheme
get() = prefs.getEnumValue(KEY_COLOR_THEME, ColorScheme.default)
set(value) = prefs.edit { putEnumValue(KEY_COLOR_THEME, value) }
var isAmoledTheme: Boolean
val isAmoledTheme: Boolean
get() = prefs.getBoolean(KEY_THEME_AMOLED, false)
set(value) = prefs.edit { putBoolean(KEY_THEME_AMOLED, value) }
var gridSize: Int
get() = prefs.getInt(KEY_GRID_SIZE, 100)
@@ -99,12 +98,11 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
}
}
var readerPageSwitch: Set<String>
val readerPageSwitch: Set<String>
get() = prefs.getStringSet(KEY_READER_SWITCHERS, null) ?: setOf(PAGE_SWITCH_TAPS)
set(value) = prefs.edit { putStringSet(KEY_READER_SWITCHERS, value) }
var isReaderTapsAdaptive: Boolean
val isReaderTapsAdaptive: Boolean
get() = !prefs.getBoolean(KEY_READER_TAPS_LTR, false)
set(value) = prefs.edit { putBoolean(KEY_READER_TAPS_LTR, value) }
var isTrafficWarningEnabled: Boolean
get() = prefs.getBoolean(KEY_TRAFFIC_WARNING, true)
@@ -114,50 +112,41 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
get() = prefs.getBoolean(KEY_ALL_FAVOURITES_VISIBLE, true)
set(value) = prefs.edit { putBoolean(KEY_ALL_FAVOURITES_VISIBLE, value) }
var isTrackerEnabled: Boolean
val isTrackerEnabled: Boolean
get() = prefs.getBoolean(KEY_TRACKER_ENABLED, true)
set(value) = prefs.edit { putBoolean(KEY_TRACKER_ENABLED, value) }
var isTrackerNotificationsEnabled: Boolean
val isTrackerNotificationsEnabled: Boolean
get() = prefs.getBoolean(KEY_TRACKER_NOTIFICATIONS, true)
set(value) = prefs.edit { putBoolean(KEY_TRACKER_NOTIFICATIONS, value) }
var notificationSound: Uri
get() = prefs.getString(KEY_NOTIFICATIONS_SOUND, null)?.toUriOrNull()
?: Settings.System.DEFAULT_NOTIFICATION_URI
set(value) = prefs.edit { putString(KEY_NOTIFICATIONS_SOUND, value.toString()) }
var notificationVibrate: Boolean
val notificationVibrate: Boolean
get() = prefs.getBoolean(KEY_NOTIFICATIONS_VIBRATE, false)
set(value) = prefs.edit { putBoolean(KEY_NOTIFICATIONS_VIBRATE, value) }
var notificationLight: Boolean
val notificationLight: Boolean
get() = prefs.getBoolean(KEY_NOTIFICATIONS_LIGHT, true)
set(value) = prefs.edit { putBoolean(KEY_NOTIFICATIONS_LIGHT, value) }
var readerAnimation: Boolean
val readerAnimation: Boolean
get() = prefs.getBoolean(KEY_READER_ANIMATION, false)
set(value) = prefs.edit { putBoolean(KEY_READER_ANIMATION, value) }
var defaultReaderMode: ReaderMode
val defaultReaderMode: ReaderMode
get() = prefs.getEnumValue(KEY_READER_MODE, ReaderMode.STANDARD)
set(value) = prefs.edit { putEnumValue(KEY_READER_MODE, value) }
var isReaderModeDetectionEnabled: Boolean
val isReaderModeDetectionEnabled: Boolean
get() = prefs.getBoolean(KEY_READER_MODE_DETECT, true)
set(value) = prefs.edit { putBoolean(KEY_READER_MODE_DETECT, value) }
var isHistoryGroupingEnabled: Boolean
get() = prefs.getBoolean(KEY_HISTORY_GROUPING, true)
set(value) = prefs.edit { putBoolean(KEY_HISTORY_GROUPING, value) }
var isReadingIndicatorsEnabled: Boolean
val isReadingIndicatorsEnabled: Boolean
get() = prefs.getBoolean(KEY_READING_INDICATORS, true)
set(value) = prefs.edit { putBoolean(KEY_READING_INDICATORS, value) }
var isHistoryExcludeNsfw: Boolean
val isHistoryExcludeNsfw: Boolean
get() = prefs.getBoolean(KEY_HISTORY_EXCLUDE_NSFW, false)
set(value) = prefs.edit { putBoolean(KEY_HISTORY_EXCLUDE_NSFW, value) }
var isIncognitoModeEnabled: Boolean
get() = prefs.getBoolean(KEY_INCOGNITO_MODE, false)
@@ -167,41 +156,34 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
get() = prefs.getBoolean(KEY_REVERSE_CHAPTERS, false)
set(value) = prefs.edit { putBoolean(KEY_REVERSE_CHAPTERS, value) }
var zoomMode: ZoomMode
val zoomMode: ZoomMode
get() = prefs.getEnumValue(KEY_ZOOM_MODE, ZoomMode.FIT_CENTER)
set(value) = prefs.edit { putEnumValue(KEY_ZOOM_MODE, value) }
var trackSources: Set<String>
val trackSources: Set<String>
get() = prefs.getStringSet(KEY_TRACK_SOURCES, null) ?: arraySetOf(TRACK_FAVOURITES, TRACK_HISTORY)
set(value) = prefs.edit { putStringSet(KEY_TRACK_SOURCES, value) }
var appPassword: String?
get() = prefs.getString(KEY_APP_PASSWORD, null)
set(value) = prefs.edit { if (value != null) putString(KEY_APP_PASSWORD, value) else remove(KEY_APP_PASSWORD) }
var isLoggingEnabled: Boolean
val isLoggingEnabled: Boolean
get() = prefs.getBoolean(KEY_LOGGING_ENABLED, false)
set(value) = prefs.edit { putBoolean(KEY_LOGGING_ENABLED, value) }
var isBiometricProtectionEnabled: Boolean
get() = prefs.getBoolean(KEY_PROTECT_APP_BIOMETRIC, true)
set(value) = prefs.edit { putBoolean(KEY_PROTECT_APP_BIOMETRIC, value) }
var isMirrorSwitchingAvailable: Boolean
val isMirrorSwitchingAvailable: Boolean
get() = prefs.getBoolean(KEY_MIRROR_SWITCHING, true)
set(value) = prefs.edit { putBoolean(KEY_MIRROR_SWITCHING, value) }
var isExitConfirmationEnabled: Boolean
val isExitConfirmationEnabled: Boolean
get() = prefs.getBoolean(KEY_EXIT_CONFIRM, false)
set(value) = prefs.edit { putBoolean(KEY_EXIT_CONFIRM, value) }
var isDynamicShortcutsEnabled: Boolean
val isDynamicShortcutsEnabled: Boolean
get() = prefs.getBoolean(KEY_SHORTCUTS, true)
set(value) = prefs.edit { putBoolean(KEY_SHORTCUTS, value) }
var isUnstableUpdatesAllowed: Boolean
val isUnstableUpdatesAllowed: Boolean
get() = prefs.getBoolean(KEY_UPDATES_UNSTABLE, false)
set(value) = prefs.edit { putBoolean(KEY_UPDATES_UNSTABLE, value) }
val isContentPrefetchEnabled: Boolean
get() {
@@ -282,27 +264,23 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
}
}
var isDownloadsSlowdownEnabled: Boolean
val isDownloadsSlowdownEnabled: Boolean
get() = prefs.getBoolean(KEY_DOWNLOADS_SLOWDOWN, false)
set(value) = prefs.edit { putBoolean(KEY_DOWNLOADS_SLOWDOWN, value) }
var isDownloadsWiFiOnly: Boolean
val isDownloadsWiFiOnly: Boolean
get() = prefs.getBoolean(KEY_DOWNLOADS_WIFI, false)
set(value) = prefs.edit { putBoolean(KEY_DOWNLOADS_WIFI, value) }
var isSuggestionsEnabled: Boolean
get() = prefs.getBoolean(KEY_SUGGESTIONS, false)
set(value) = prefs.edit { putBoolean(KEY_SUGGESTIONS, value) }
var isSuggestionsExcludeNsfw: Boolean
val isSuggestionsExcludeNsfw: Boolean
get() = prefs.getBoolean(KEY_SUGGESTIONS_EXCLUDE_NSFW, false)
set(value) = prefs.edit { putBoolean(KEY_SUGGESTIONS_EXCLUDE_NSFW, value) }
var isSuggestionsNotificationAvailable: Boolean
val isSuggestionsNotificationAvailable: Boolean
get() = prefs.getBoolean(KEY_SUGGESTIONS_NOTIFICATIONS, true)
set(value) = prefs.edit { putBoolean(KEY_SUGGESTIONS_NOTIFICATIONS, value) }
var suggestionsTagsBlacklist: Set<String>
val suggestionsTagsBlacklist: Set<String>
get() {
val string = prefs.getString(KEY_SUGGESTIONS_EXCLUDE_TAGS, null)?.trimEnd(' ', ',')
if (string.isNullOrEmpty()) {
@@ -310,27 +288,21 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
}
return string.split(',').mapToSet { it.trim() }
}
set(value) = prefs.edit { putStringSet(KEY_SUGGESTIONS_EXCLUDE_TAGS, value) }
var isReaderBarEnabled: Boolean
val isReaderBarEnabled: Boolean
get() = prefs.getBoolean(KEY_READER_BAR, true)
set(value) = prefs.edit { putBoolean(KEY_READER_BAR, value) }
var isReaderSliderEnabled: Boolean
val isReaderSliderEnabled: Boolean
get() = prefs.getBoolean(KEY_READER_SLIDER, true)
set(value) = prefs.edit { putBoolean(KEY_READER_SLIDER, value) }
var isImagesProxyEnabled: Boolean
val isImagesProxyEnabled: Boolean
get() = prefs.getBoolean(KEY_IMAGES_PROXY, false)
set(value) = prefs.edit { putBoolean(KEY_IMAGES_PROXY, value) }
var dnsOverHttps: DoHProvider
val dnsOverHttps: DoHProvider
get() = prefs.getEnumValue(KEY_DOH, DoHProvider.NONE)
set(value) = prefs.edit { putEnumValue(KEY_DOH, value) }
var isSSLBypassEnabled: Boolean
val isSSLBypassEnabled: Boolean
get() = prefs.getBoolean(KEY_SSL_BYPASS, false)
set(value) = prefs.edit { putBoolean(KEY_SSL_BYPASS, value) }
val proxyType: Proxy.Type
get() {
@@ -354,10 +326,8 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
get() = prefs.getEnumValue(KEY_LOCAL_LIST_ORDER, SortOrder.NEWEST)
set(value) = prefs.edit { putEnumValue(KEY_LOCAL_LIST_ORDER, value) }
var isWebtoonZoomEnable: Boolean
val isWebtoonZoomEnable: Boolean
get() = prefs.getBoolean(KEY_WEBTOON_ZOOM, true)
set(value) = prefs.edit { putBoolean(KEY_WEBTOON_ZOOM, value) }
@get:FloatRange(from = 0.0, to = 1.0)
var readerAutoscrollSpeed: Float
@@ -409,6 +379,23 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
fun observe() = prefs.observe()
fun getAllValues(): Map<String, *> = prefs.all
fun restoreValuesFromMap(m: Map<String, *>) {
prefs.edit {
m.forEach { e ->
when (e.value) {
is Boolean -> putBoolean(e.key, e.value as Boolean)
is Int -> putInt(e.key, e.value as Int)
is Long -> putLong(e.key, e.value as Long)
is Float -> putFloat(e.key, e.value as Float)
is String -> putString(e.key, e.value as String)
is JSONArray -> putStringSet(e.key, (e.value as JSONArray).mapJSONToSet<String, String> { it })
}
}
}
}
private fun isBackgroundNetworkRestricted(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
connectivityManager.restrictBackgroundStatus == ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED

View File

@@ -8,6 +8,8 @@ import android.os.Bundle
import android.view.View
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.view.postDelayed
import androidx.lifecycle.Lifecycle
import androidx.preference.Preference
import androidx.preference.TwoStatePreference
@@ -24,6 +26,7 @@ import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar
import org.koitharu.kotatsu.core.os.AppShortcutManager
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.ui.BasePreferenceFragment
import org.koitharu.kotatsu.core.ui.util.ActivityRecreationHandle
import org.koitharu.kotatsu.core.util.FileSize
import org.koitharu.kotatsu.core.util.ext.awaitStateAtLeast
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
@@ -61,6 +64,9 @@ class UserDataSettingsFragment : BasePreferenceFragment(R.string.data_and_privac
@Inject
lateinit var appShortcutManager: AppShortcutManager
@Inject
lateinit var activityRecreationHandle: ActivityRecreationHandle
private val backupSelectCall = registerForActivityResult(
ActivityResultContracts.OpenDocument(),
this,
@@ -180,6 +186,19 @@ class UserDataSettingsFragment : BasePreferenceFragment(R.string.data_and_privac
findPreference<TwoStatePreference>(AppSettings.KEY_PROTECT_APP)
?.isChecked = !settings.appPassword.isNullOrEmpty()
}
AppSettings.KEY_THEME -> {
AppCompatDelegate.setDefaultNightMode(settings.theme)
}
AppSettings.KEY_COLOR_THEME,
AppSettings.KEY_THEME_AMOLED -> {
postRestart()
}
AppSettings.KEY_APP_LOCALE -> {
AppCompatDelegate.setApplicationLocales(settings.appLocales)
}
}
}
@@ -273,4 +292,11 @@ class UserDataSettingsFragment : BasePreferenceFragment(R.string.data_and_privac
}
}.show()
}
private fun postRestart() {
view?.postDelayed(400) {
activityRecreationHandle.recreateAll()
}
}
}

View File

@@ -5,7 +5,6 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.core.view.postDelayed
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.viewModels
import com.google.android.material.dialog.MaterialAlertDialogBuilder
@@ -13,20 +12,16 @@ import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.backup.CompositeResult
import org.koitharu.kotatsu.core.ui.AlertDialogFragment
import org.koitharu.kotatsu.core.ui.util.ActivityRecreationHandle
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.withArgs
import org.koitharu.kotatsu.databinding.DialogProgressBinding
import javax.inject.Inject
import kotlin.math.roundToInt
@AndroidEntryPoint
class RestoreDialogFragment : AlertDialogFragment<DialogProgressBinding>() {
@Inject
lateinit var activityRecreationHandle: ActivityRecreationHandle
private val viewModel: RestoreViewModel by viewModels()
@@ -76,7 +71,6 @@ class RestoreDialogFragment : AlertDialogFragment<DialogProgressBinding>() {
result.isAllSuccess -> {
builder.setTitle(R.string.data_restored)
.setMessage(R.string.data_restored_success)
postRestart()
}
result.isAllFailed -> builder.setTitle(R.string.error)
@@ -94,11 +88,6 @@ class RestoreDialogFragment : AlertDialogFragment<DialogProgressBinding>() {
dismiss()
}
private fun postRestart() {
view?.postDelayed(400) {
activityRecreationHandle.recreateAll()
}
}
companion object {