add settings backup
This commit is contained in:
1
.idea/gradle.xml
generated
1
.idea/gradle.xml
generated
@@ -4,6 +4,7 @@
|
|||||||
<component name="GradleSettings">
|
<component name="GradleSettings">
|
||||||
<option name="linkedExternalProjectsSettings">
|
<option name="linkedExternalProjectsSettings">
|
||||||
<GradleProjectSettings>
|
<GradleProjectSettings>
|
||||||
|
<option name="testRunner" value="GRADLE" />
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
<option name="gradleJvm" value="jbr-17" />
|
<option name="gradleJvm" value="jbr-17" />
|
||||||
<option name="modules">
|
<option name="modules">
|
||||||
|
|||||||
@@ -13,5 +13,6 @@ class BackupEntry(
|
|||||||
const val HISTORY = "history"
|
const val HISTORY = "history"
|
||||||
const val CATEGORIES = "categories"
|
const val CATEGORIES = "categories"
|
||||||
const val FAVOURITES = "favourites"
|
const val FAVOURITES = "favourites"
|
||||||
|
const val SETTINGS = "settings"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,36 @@
|
|||||||
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.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
|
||||||
|
|
||||||
class BackupRepository @Inject constructor(private val db: MangaDatabase) {
|
class BackupRepository @Inject constructor(
|
||||||
|
private val db: MangaDatabase,
|
||||||
|
private val settings: AppSettings,
|
||||||
|
) {
|
||||||
|
|
||||||
suspend fun dumpHistory(): BackupEntry {
|
suspend fun dumpHistory(): BackupEntry {
|
||||||
var offset = 0
|
var offset = 0
|
||||||
@@ -67,6 +85,13 @@ class BackupRepository @Inject constructor(private val db: MangaDatabase) {
|
|||||||
return entry
|
return entry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun dumpSettings(): BackupEntry {
|
||||||
|
val entry = BackupEntry(BackupEntry.SETTINGS, JSONArray())
|
||||||
|
val json = JsonSerializer(settings).toJson()
|
||||||
|
entry.data.put(json)
|
||||||
|
return entry
|
||||||
|
}
|
||||||
|
|
||||||
fun createIndex(): BackupEntry {
|
fun createIndex(): BackupEntry {
|
||||||
val entry = BackupEntry(BackupEntry.INDEX, JSONArray())
|
val entry = BackupEntry(BackupEntry.INDEX, JSONArray())
|
||||||
val json = JSONObject()
|
val json = JSONObject()
|
||||||
@@ -127,4 +152,67 @@ class BackupRepository @Inject constructor(private val db: MangaDatabase) {
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun restoreSettings(entry: BackupEntry): CompositeResult {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,14 +34,14 @@ class JsonDeserializer(private val json: JSONObject) {
|
|||||||
largeCoverUrl = json.getStringOrNull("large_cover_url"),
|
largeCoverUrl = json.getStringOrNull("large_cover_url"),
|
||||||
state = json.getStringOrNull("state"),
|
state = json.getStringOrNull("state"),
|
||||||
author = json.getStringOrNull("author"),
|
author = json.getStringOrNull("author"),
|
||||||
source = json.getString("source")
|
source = json.getString("source"),
|
||||||
)
|
)
|
||||||
|
|
||||||
fun toTagEntity() = TagEntity(
|
fun toTagEntity() = TagEntity(
|
||||||
id = json.getLong("id"),
|
id = json.getLong("id"),
|
||||||
title = json.getString("title"),
|
title = json.getString("title"),
|
||||||
key = json.getString("key"),
|
key = json.getString("key"),
|
||||||
source = json.getString("source")
|
source = json.getString("source"),
|
||||||
)
|
)
|
||||||
|
|
||||||
fun toHistoryEntity() = HistoryEntity(
|
fun toHistoryEntity() = HistoryEntity(
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
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) {
|
||||||
|
|
||||||
@@ -15,7 +18,7 @@ class JsonSerializer private constructor(private val json: JSONObject) {
|
|||||||
put("category_id", e.categoryId)
|
put("category_id", e.categoryId)
|
||||||
put("sort_key", e.sortKey)
|
put("sort_key", e.sortKey)
|
||||||
put("created_at", e.createdAt)
|
put("created_at", e.createdAt)
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
constructor(e: FavouriteCategoryEntity) : this(
|
constructor(e: FavouriteCategoryEntity) : this(
|
||||||
@@ -27,7 +30,7 @@ class JsonSerializer private constructor(private val json: JSONObject) {
|
|||||||
put("order", e.order)
|
put("order", e.order)
|
||||||
put("track", e.track)
|
put("track", e.track)
|
||||||
put("show_in_lib", e.isVisibleInLibrary)
|
put("show_in_lib", e.isVisibleInLibrary)
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
constructor(e: HistoryEntity) : this(
|
constructor(e: HistoryEntity) : this(
|
||||||
@@ -39,7 +42,7 @@ class JsonSerializer private constructor(private val json: JSONObject) {
|
|||||||
put("page", e.page)
|
put("page", e.page)
|
||||||
put("scroll", e.scroll)
|
put("scroll", e.scroll)
|
||||||
put("percent", e.percent)
|
put("percent", e.percent)
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
constructor(e: TagEntity) : this(
|
constructor(e: TagEntity) : this(
|
||||||
@@ -48,7 +51,7 @@ class JsonSerializer private constructor(private val json: JSONObject) {
|
|||||||
put("title", e.title)
|
put("title", e.title)
|
||||||
put("key", e.key)
|
put("key", e.key)
|
||||||
put("source", e.source)
|
put("source", e.source)
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
constructor(e: MangaEntity) : this(
|
constructor(e: MangaEntity) : this(
|
||||||
@@ -65,8 +68,91 @@ class JsonSerializer private constructor(private val json: JSONObject) {
|
|||||||
put("state", e.state)
|
put("state", e.state)
|
||||||
put("author", e.author)
|
put("author", e.author)
|
||||||
put("source", e.source)
|
put("source", e.source)
|
||||||
}
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
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)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -72,14 +72,17 @@ 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) }
|
||||||
|
|
||||||
val theme: Int
|
var 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()) }
|
||||||
|
|
||||||
val colorScheme: ColorScheme
|
var 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) }
|
||||||
|
|
||||||
val isAmoledTheme: Boolean
|
var 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)
|
||||||
@@ -96,11 +99,12 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val readerPageSwitch: Set<String>
|
var 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) }
|
||||||
val isReaderTapsAdaptive: Boolean
|
var 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)
|
||||||
@@ -110,41 +114,50 @@ 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) }
|
||||||
|
|
||||||
val isTrackerEnabled: Boolean
|
var 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) }
|
||||||
|
|
||||||
val isTrackerNotificationsEnabled: Boolean
|
var 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()) }
|
||||||
|
|
||||||
val notificationVibrate: Boolean
|
var 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) }
|
||||||
|
|
||||||
val notificationLight: Boolean
|
var 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) }
|
||||||
|
|
||||||
val readerAnimation: Boolean
|
var 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) }
|
||||||
|
|
||||||
val defaultReaderMode: ReaderMode
|
var 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) }
|
||||||
|
|
||||||
val isReaderModeDetectionEnabled: Boolean
|
var 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) }
|
||||||
|
|
||||||
val isReadingIndicatorsEnabled: Boolean
|
var 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) }
|
||||||
|
|
||||||
val isHistoryExcludeNsfw: Boolean
|
var 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)
|
||||||
@@ -154,34 +167,41 @@ 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) }
|
||||||
|
|
||||||
val zoomMode: ZoomMode
|
var 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) }
|
||||||
|
|
||||||
val trackSources: Set<String>
|
var 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) }
|
||||||
|
|
||||||
val isLoggingEnabled: Boolean
|
var 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) }
|
||||||
|
|
||||||
val isMirrorSwitchingAvailable: Boolean
|
var 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) }
|
||||||
|
|
||||||
val isExitConfirmationEnabled: Boolean
|
var 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) }
|
||||||
|
|
||||||
val isDynamicShortcutsEnabled: Boolean
|
var isDynamicShortcutsEnabled: Boolean
|
||||||
get() = prefs.getBoolean(KEY_SHORTCUTS, true)
|
get() = prefs.getBoolean(KEY_SHORTCUTS, true)
|
||||||
|
set(value) = prefs.edit { putBoolean(KEY_SHORTCUTS, value) }
|
||||||
|
|
||||||
val isUnstableUpdatesAllowed: Boolean
|
var 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() {
|
||||||
@@ -262,23 +282,27 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val isDownloadsSlowdownEnabled: Boolean
|
var 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) }
|
||||||
|
|
||||||
val isDownloadsWiFiOnly: Boolean
|
var 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) }
|
||||||
|
|
||||||
val isSuggestionsExcludeNsfw: Boolean
|
var 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) }
|
||||||
|
|
||||||
val isSuggestionsNotificationAvailable: Boolean
|
var 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) }
|
||||||
|
|
||||||
val suggestionsTagsBlacklist: Set<String>
|
var 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()) {
|
||||||
@@ -286,21 +310,27 @@ 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) }
|
||||||
|
|
||||||
val isReaderBarEnabled: Boolean
|
var 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) }
|
||||||
|
|
||||||
val isReaderSliderEnabled: Boolean
|
var 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) }
|
||||||
|
|
||||||
val isImagesProxyEnabled: Boolean
|
var 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) }
|
||||||
|
|
||||||
val dnsOverHttps: DoHProvider
|
var dnsOverHttps: DoHProvider
|
||||||
get() = prefs.getEnumValue(KEY_DOH, DoHProvider.NONE)
|
get() = prefs.getEnumValue(KEY_DOH, DoHProvider.NONE)
|
||||||
|
set(value) = prefs.edit { putEnumValue(KEY_DOH, value) }
|
||||||
|
|
||||||
val isSSLBypassEnabled: Boolean
|
var 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() {
|
||||||
@@ -324,8 +354,10 @@ 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) }
|
||||||
|
|
||||||
val isWebtoonZoomEnable: Boolean
|
var 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
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.koitharu.kotatsu.core.util.ext
|
package org.koitharu.kotatsu.core.util.ext
|
||||||
|
|
||||||
|
import android.content.SharedPreferences
|
||||||
import androidx.annotation.FloatRange
|
import androidx.annotation.FloatRange
|
||||||
import org.koitharu.kotatsu.parsers.util.levenshteinDistance
|
import org.koitharu.kotatsu.parsers.util.levenshteinDistance
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
@@ -40,3 +41,9 @@ fun CharSequence.sanitize(): CharSequence {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun Char.isReplacement() = this in '\uFFF0'..'\uFFFF'
|
fun Char.isReplacement() = this in '\uFFF0'..'\uFFFF'
|
||||||
|
|
||||||
|
fun <E : Enum<E>> String.getEnumValue(defaultValue: E): E {
|
||||||
|
return defaultValue.javaClass.enumConstants?.find {
|
||||||
|
it.name == this
|
||||||
|
} ?: defaultValue
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import org.koitharu.kotatsu.core.backup.BackupRepository
|
|||||||
import org.koitharu.kotatsu.core.backup.BackupZipInput
|
import org.koitharu.kotatsu.core.backup.BackupZipInput
|
||||||
import org.koitharu.kotatsu.core.backup.BackupZipOutput
|
import org.koitharu.kotatsu.core.backup.BackupZipOutput
|
||||||
import org.koitharu.kotatsu.core.db.MangaDatabase
|
import org.koitharu.kotatsu.core.db.MangaDatabase
|
||||||
|
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||||
import java.io.*
|
import java.io.*
|
||||||
|
|
||||||
class AppBackupAgent : BackupAgent() {
|
class AppBackupAgent : BackupAgent() {
|
||||||
@@ -31,7 +32,8 @@ class AppBackupAgent : BackupAgent() {
|
|||||||
|
|
||||||
override fun onFullBackup(data: FullBackupDataOutput) {
|
override fun onFullBackup(data: FullBackupDataOutput) {
|
||||||
super.onFullBackup(data)
|
super.onFullBackup(data)
|
||||||
val file = createBackupFile(this, BackupRepository(MangaDatabase(applicationContext)))
|
val file =
|
||||||
|
createBackupFile(this, BackupRepository(MangaDatabase(applicationContext), AppSettings(applicationContext)))
|
||||||
try {
|
try {
|
||||||
fullBackupFile(file, data)
|
fullBackupFile(file, data)
|
||||||
} finally {
|
} finally {
|
||||||
@@ -48,7 +50,7 @@ class AppBackupAgent : BackupAgent() {
|
|||||||
mtime: Long
|
mtime: Long
|
||||||
) {
|
) {
|
||||||
if (destination?.name?.endsWith(".bk.zip") == true) {
|
if (destination?.name?.endsWith(".bk.zip") == true) {
|
||||||
restoreBackupFile(data.fileDescriptor, size, BackupRepository(MangaDatabase(applicationContext)))
|
restoreBackupFile(data.fileDescriptor, size, BackupRepository(MangaDatabase(applicationContext), AppSettings(applicationContext)))
|
||||||
destination.delete()
|
destination.delete()
|
||||||
} else {
|
} else {
|
||||||
super.onRestoreFile(data, size, destination, type, mode, mtime)
|
super.onRestoreFile(data, size, destination, type, mode, mtime)
|
||||||
@@ -62,6 +64,7 @@ class AppBackupAgent : BackupAgent() {
|
|||||||
backup.put(repository.dumpHistory())
|
backup.put(repository.dumpHistory())
|
||||||
backup.put(repository.dumpCategories())
|
backup.put(repository.dumpCategories())
|
||||||
backup.put(repository.dumpFavourites())
|
backup.put(repository.dumpFavourites())
|
||||||
|
backup.put(repository.dumpSettings())
|
||||||
backup.finish()
|
backup.finish()
|
||||||
backup.file
|
backup.file
|
||||||
}
|
}
|
||||||
@@ -81,6 +84,7 @@ class AppBackupAgent : BackupAgent() {
|
|||||||
repository.restoreHistory(backup.getEntry(BackupEntry.HISTORY))
|
repository.restoreHistory(backup.getEntry(BackupEntry.HISTORY))
|
||||||
repository.restoreCategories(backup.getEntry(BackupEntry.CATEGORIES))
|
repository.restoreCategories(backup.getEntry(BackupEntry.CATEGORIES))
|
||||||
repository.restoreFavourites(backup.getEntry(BackupEntry.FAVOURITES))
|
repository.restoreFavourites(backup.getEntry(BackupEntry.FAVOURITES))
|
||||||
|
repository.restoreSettings(backup.getEntry(BackupEntry.SETTINGS))
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
backup.close()
|
backup.close()
|
||||||
@@ -102,4 +106,4 @@ class AppBackupAgent : BackupAgent() {
|
|||||||
bytes = read(buffer, 0, buffer.size.coerceAtMost(bytesLeft))
|
bytes = read(buffer, 0, buffer.size.coerceAtMost(bytesLeft))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,13 +29,15 @@ class BackupViewModel @Inject constructor(
|
|||||||
progress.value = 0f
|
progress.value = 0f
|
||||||
backup.put(repository.dumpHistory())
|
backup.put(repository.dumpHistory())
|
||||||
|
|
||||||
progress.value = 0.3f
|
progress.value = 0.25f
|
||||||
backup.put(repository.dumpCategories())
|
backup.put(repository.dumpCategories())
|
||||||
|
|
||||||
progress.value = 0.6f
|
progress.value = 0.5f
|
||||||
backup.put(repository.dumpFavourites())
|
backup.put(repository.dumpFavourites())
|
||||||
|
|
||||||
progress.value = 0.9f
|
progress.value = 0.75f
|
||||||
|
backup.put(repository.dumpSettings())
|
||||||
|
|
||||||
backup.finish()
|
backup.finish()
|
||||||
progress.value = 1f
|
progress.value = 1f
|
||||||
backup.close()
|
backup.close()
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ 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
|
||||||
@@ -12,16 +13,21 @@ 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()
|
||||||
|
|
||||||
override fun onCreateViewBinding(
|
override fun onCreateViewBinding(
|
||||||
@@ -67,8 +73,11 @@ class RestoreDialogFragment : AlertDialogFragment<DialogProgressBinding>() {
|
|||||||
private fun onRestoreDone(result: CompositeResult) {
|
private fun onRestoreDone(result: CompositeResult) {
|
||||||
val builder = MaterialAlertDialogBuilder(context ?: return)
|
val builder = MaterialAlertDialogBuilder(context ?: return)
|
||||||
when {
|
when {
|
||||||
result.isAllSuccess -> builder.setTitle(R.string.data_restored)
|
result.isAllSuccess -> {
|
||||||
.setMessage(R.string.data_restored_success)
|
builder.setTitle(R.string.data_restored)
|
||||||
|
.setMessage(R.string.data_restored_success)
|
||||||
|
postRestart()
|
||||||
|
}
|
||||||
|
|
||||||
result.isAllFailed -> builder.setTitle(R.string.error)
|
result.isAllFailed -> builder.setTitle(R.string.error)
|
||||||
.setMessage(
|
.setMessage(
|
||||||
@@ -85,6 +94,12 @@ class RestoreDialogFragment : AlertDialogFragment<DialogProgressBinding>() {
|
|||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun postRestart() {
|
||||||
|
view?.postDelayed(400) {
|
||||||
|
activityRecreationHandle.recreateAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
const val ARG_FILE = "file"
|
const val ARG_FILE = "file"
|
||||||
|
|||||||
@@ -50,12 +50,15 @@ class RestoreViewModel @Inject constructor(
|
|||||||
progress.value = 0f
|
progress.value = 0f
|
||||||
result += repository.restoreHistory(backup.getEntry(BackupEntry.HISTORY))
|
result += repository.restoreHistory(backup.getEntry(BackupEntry.HISTORY))
|
||||||
|
|
||||||
progress.value = 0.3f
|
progress.value = 0.25f
|
||||||
result += repository.restoreCategories(backup.getEntry(BackupEntry.CATEGORIES))
|
result += repository.restoreCategories(backup.getEntry(BackupEntry.CATEGORIES))
|
||||||
|
|
||||||
progress.value = 0.6f
|
progress.value = 0.5f
|
||||||
result += repository.restoreFavourites(backup.getEntry(BackupEntry.FAVOURITES))
|
result += repository.restoreFavourites(backup.getEntry(BackupEntry.FAVOURITES))
|
||||||
|
|
||||||
|
progress.value = 0.75f
|
||||||
|
result += repository.restoreSettings(backup.getEntry(BackupEntry.SETTINGS))
|
||||||
|
|
||||||
progress.value = 1f
|
progress.value = 1f
|
||||||
onRestoreDone.call(result)
|
onRestoreDone.call(result)
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
Reference in New Issue
Block a user