remove clutter code

pull/421/head
javlon 3 years ago
parent a8176e6589
commit 33a45ac5b3

@ -1,28 +1,14 @@
package org.koitharu.kotatsu.core.backup package org.koitharu.kotatsu.core.backup
import android.provider.Settings
import androidx.room.withTransaction import androidx.room.withTransaction
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.core.db.MangaDatabase 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.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.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.json.mapJSON
import org.koitharu.kotatsu.parsers.util.mapNotNullToSet
import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.parsers.util.runCatchingCancellable
import java.io.File
import javax.inject.Inject import javax.inject.Inject
private const val PAGE_SIZE = 10 private const val PAGE_SIZE = 10
@ -85,9 +71,9 @@ class BackupRepository @Inject constructor(
return entry return entry
} }
suspend fun dumpSettings(): BackupEntry { fun dumpSettings(): BackupEntry {
val entry = BackupEntry(BackupEntry.SETTINGS, JSONArray()) val entry = BackupEntry(BackupEntry.SETTINGS, JSONArray())
val json = JsonSerializer(settings).toJson() val json = JsonSerializer(settings.getAllValues()).toJson()
entry.data.put(json) entry.data.put(json)
return entry return entry
} }
@ -157,60 +143,7 @@ class BackupRepository @Inject constructor(
val result = CompositeResult() val result = CompositeResult()
for (item in entry.data.JSONIterator()) { for (item in entry.data.JSONIterator()) {
result += runCatchingCancellable { result += runCatchingCancellable {
settings.listMode = item.getString("list_mode").getEnumValue(ListMode.GRID) settings.restoreValuesFromMap(JsonDeserializer(item).toMap())
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)
} }
} }
return result return result

@ -1,5 +1,6 @@
package org.koitharu.kotatsu.core.backup package org.koitharu.kotatsu.core.backup
import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
import org.koitharu.kotatsu.core.db.entity.MangaEntity import org.koitharu.kotatsu.core.db.entity.MangaEntity
import org.koitharu.kotatsu.core.db.entity.TagEntity 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), isVisibleInLibrary = json.getBooleanOrDefault("show_in_lib", true),
deletedAt = 0L, 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
}

@ -1,14 +1,11 @@
package org.koitharu.kotatsu.core.backup package org.koitharu.kotatsu.core.backup
import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
import org.koitharu.kotatsu.core.db.entity.MangaEntity import org.koitharu.kotatsu.core.db.entity.MangaEntity
import org.koitharu.kotatsu.core.db.entity.TagEntity 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.FavouriteCategoryEntity
import org.koitharu.kotatsu.favourites.data.FavouriteEntity import org.koitharu.kotatsu.favourites.data.FavouriteEntity
import org.koitharu.kotatsu.history.data.HistoryEntity import org.koitharu.kotatsu.history.data.HistoryEntity
import java.util.ArrayList
class JsonSerializer private constructor(private val json: JSONObject) { class JsonSerializer private constructor(private val json: JSONObject) {
@ -71,88 +68,9 @@ class JsonSerializer private constructor(private val json: JSONObject) {
}, },
) )
constructor(e: AppSettings) : this( constructor(m: Map<String, *>) : this(
JSONObject().apply { JSONObject(m),
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)
},
) )
fun toJson(): JSONObject = json 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
}

@ -13,7 +13,9 @@ import androidx.core.content.edit
import androidx.core.os.LocaleListCompat import androidx.core.os.LocaleListCompat
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import org.json.JSONArray
import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.core.backup.mapJSONToSet
import org.koitharu.kotatsu.core.model.ZoomMode import org.koitharu.kotatsu.core.model.ZoomMode
import org.koitharu.kotatsu.core.network.DoHProvider import org.koitharu.kotatsu.core.network.DoHProvider
import org.koitharu.kotatsu.core.util.ext.connectivityManager 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) get() = prefs.getEnumValue(KEY_LIST_MODE, ListMode.GRID)
set(value) = prefs.edit { putEnumValue(KEY_LIST_MODE, value) } 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 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) 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) get() = prefs.getBoolean(KEY_THEME_AMOLED, false)
set(value) = prefs.edit { putBoolean(KEY_THEME_AMOLED, value) }
var gridSize: Int var gridSize: Int
get() = prefs.getInt(KEY_GRID_SIZE, 100) 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) 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) get() = !prefs.getBoolean(KEY_READER_TAPS_LTR, false)
set(value) = prefs.edit { putBoolean(KEY_READER_TAPS_LTR, value) }
var isTrafficWarningEnabled: Boolean var isTrafficWarningEnabled: Boolean
get() = prefs.getBoolean(KEY_TRAFFIC_WARNING, true) 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) get() = prefs.getBoolean(KEY_ALL_FAVOURITES_VISIBLE, true)
set(value) = prefs.edit { putBoolean(KEY_ALL_FAVOURITES_VISIBLE, value) } set(value) = prefs.edit { putBoolean(KEY_ALL_FAVOURITES_VISIBLE, value) }
var isTrackerEnabled: Boolean val isTrackerEnabled: Boolean
get() = prefs.getBoolean(KEY_TRACKER_ENABLED, true) 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) get() = prefs.getBoolean(KEY_TRACKER_NOTIFICATIONS, true)
set(value) = prefs.edit { putBoolean(KEY_TRACKER_NOTIFICATIONS, value) }
var notificationSound: Uri var notificationSound: Uri
get() = prefs.getString(KEY_NOTIFICATIONS_SOUND, null)?.toUriOrNull() get() = prefs.getString(KEY_NOTIFICATIONS_SOUND, null)?.toUriOrNull()
?: Settings.System.DEFAULT_NOTIFICATION_URI ?: Settings.System.DEFAULT_NOTIFICATION_URI
set(value) = prefs.edit { putString(KEY_NOTIFICATIONS_SOUND, value.toString()) } set(value) = prefs.edit { putString(KEY_NOTIFICATIONS_SOUND, value.toString()) }
var notificationVibrate: Boolean val notificationVibrate: Boolean
get() = prefs.getBoolean(KEY_NOTIFICATIONS_VIBRATE, false) 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) 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) 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) 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) get() = prefs.getBoolean(KEY_READER_MODE_DETECT, true)
set(value) = prefs.edit { putBoolean(KEY_READER_MODE_DETECT, value) }
var isHistoryGroupingEnabled: Boolean var isHistoryGroupingEnabled: Boolean
get() = prefs.getBoolean(KEY_HISTORY_GROUPING, true) get() = prefs.getBoolean(KEY_HISTORY_GROUPING, true)
set(value) = prefs.edit { putBoolean(KEY_HISTORY_GROUPING, value) } set(value) = prefs.edit { putBoolean(KEY_HISTORY_GROUPING, value) }
var isReadingIndicatorsEnabled: Boolean val isReadingIndicatorsEnabled: Boolean
get() = prefs.getBoolean(KEY_READING_INDICATORS, true) 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) get() = prefs.getBoolean(KEY_HISTORY_EXCLUDE_NSFW, false)
set(value) = prefs.edit { putBoolean(KEY_HISTORY_EXCLUDE_NSFW, value) }
var isIncognitoModeEnabled: Boolean var isIncognitoModeEnabled: Boolean
get() = prefs.getBoolean(KEY_INCOGNITO_MODE, false) 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) get() = prefs.getBoolean(KEY_REVERSE_CHAPTERS, false)
set(value) = prefs.edit { putBoolean(KEY_REVERSE_CHAPTERS, value) } set(value) = prefs.edit { putBoolean(KEY_REVERSE_CHAPTERS, value) }
var zoomMode: ZoomMode val zoomMode: ZoomMode
get() = prefs.getEnumValue(KEY_ZOOM_MODE, ZoomMode.FIT_CENTER) 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) get() = prefs.getStringSet(KEY_TRACK_SOURCES, null) ?: arraySetOf(TRACK_FAVOURITES, TRACK_HISTORY)
set(value) = prefs.edit { putStringSet(KEY_TRACK_SOURCES, value) }
var appPassword: String? var appPassword: String?
get() = prefs.getString(KEY_APP_PASSWORD, null) get() = prefs.getString(KEY_APP_PASSWORD, null)
set(value) = prefs.edit { if (value != null) putString(KEY_APP_PASSWORD, value) else remove(KEY_APP_PASSWORD) } 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) get() = prefs.getBoolean(KEY_LOGGING_ENABLED, false)
set(value) = prefs.edit { putBoolean(KEY_LOGGING_ENABLED, value) }
var isBiometricProtectionEnabled: Boolean var isBiometricProtectionEnabled: Boolean
get() = prefs.getBoolean(KEY_PROTECT_APP_BIOMETRIC, true) get() = prefs.getBoolean(KEY_PROTECT_APP_BIOMETRIC, true)
set(value) = prefs.edit { putBoolean(KEY_PROTECT_APP_BIOMETRIC, value) } set(value) = prefs.edit { putBoolean(KEY_PROTECT_APP_BIOMETRIC, value) }
var isMirrorSwitchingAvailable: Boolean val isMirrorSwitchingAvailable: Boolean
get() = prefs.getBoolean(KEY_MIRROR_SWITCHING, true) 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) 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) 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) get() = prefs.getBoolean(KEY_UPDATES_UNSTABLE, false)
set(value) = prefs.edit { putBoolean(KEY_UPDATES_UNSTABLE, value) }
val isContentPrefetchEnabled: Boolean val isContentPrefetchEnabled: Boolean
get() { 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) 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) get() = prefs.getBoolean(KEY_DOWNLOADS_WIFI, false)
set(value) = prefs.edit { putBoolean(KEY_DOWNLOADS_WIFI, value) }
var isSuggestionsEnabled: Boolean var isSuggestionsEnabled: Boolean
get() = prefs.getBoolean(KEY_SUGGESTIONS, false) get() = prefs.getBoolean(KEY_SUGGESTIONS, false)
set(value) = prefs.edit { putBoolean(KEY_SUGGESTIONS, value) } set(value) = prefs.edit { putBoolean(KEY_SUGGESTIONS, value) }
var isSuggestionsExcludeNsfw: Boolean val isSuggestionsExcludeNsfw: Boolean
get() = prefs.getBoolean(KEY_SUGGESTIONS_EXCLUDE_NSFW, false) 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) 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() { get() {
val string = prefs.getString(KEY_SUGGESTIONS_EXCLUDE_TAGS, null)?.trimEnd(' ', ',') val string = prefs.getString(KEY_SUGGESTIONS_EXCLUDE_TAGS, null)?.trimEnd(' ', ',')
if (string.isNullOrEmpty()) { if (string.isNullOrEmpty()) {
@ -310,27 +288,21 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
} }
return string.split(',').mapToSet { it.trim() } 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) 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) 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) 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) 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) get() = prefs.getBoolean(KEY_SSL_BYPASS, false)
set(value) = prefs.edit { putBoolean(KEY_SSL_BYPASS, value) }
val proxyType: Proxy.Type val proxyType: Proxy.Type
get() { get() {
@ -354,10 +326,8 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
get() = prefs.getEnumValue(KEY_LOCAL_LIST_ORDER, SortOrder.NEWEST) get() = prefs.getEnumValue(KEY_LOCAL_LIST_ORDER, SortOrder.NEWEST)
set(value) = prefs.edit { putEnumValue(KEY_LOCAL_LIST_ORDER, value) } set(value) = prefs.edit { putEnumValue(KEY_LOCAL_LIST_ORDER, value) }
var isWebtoonZoomEnable: Boolean val isWebtoonZoomEnable: Boolean
get() = prefs.getBoolean(KEY_WEBTOON_ZOOM, true) get() = prefs.getBoolean(KEY_WEBTOON_ZOOM, true)
set(value) = prefs.edit { putBoolean(KEY_WEBTOON_ZOOM, value) }
@get:FloatRange(from = 0.0, to = 1.0) @get:FloatRange(from = 0.0, to = 1.0)
var readerAutoscrollSpeed: Float var readerAutoscrollSpeed: Float
@ -409,6 +379,23 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
fun observe() = prefs.observe() 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 { private fun isBackgroundNetworkRestricted(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
connectivityManager.restrictBackgroundStatus == ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED connectivityManager.restrictBackgroundStatus == ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED

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

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

Loading…
Cancel
Save