diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/data/CreateBackupScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/data/CreateBackupScreen.kt index 9811a3cce3..27aa0598fd 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/data/CreateBackupScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/data/CreateBackupScreen.kt @@ -29,16 +29,11 @@ import cafe.adriel.voyager.navigator.currentOrThrow import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.WarningBanner import eu.kanade.presentation.util.Screen -import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags import eu.kanade.tachiyomi.data.backup.create.BackupCreateJob import eu.kanade.tachiyomi.data.backup.create.BackupCreator +import eu.kanade.tachiyomi.data.backup.create.BackupOptions import eu.kanade.tachiyomi.util.system.DeviceUtil import eu.kanade.tachiyomi.util.system.toast -import kotlinx.collections.immutable.PersistentSet -import kotlinx.collections.immutable.minus -import kotlinx.collections.immutable.persistentMapOf -import kotlinx.collections.immutable.persistentSetOf -import kotlinx.collections.immutable.plus import kotlinx.coroutines.flow.update import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.LabeledCheckbox @@ -101,13 +96,13 @@ class CreateBackupScreen : Screen() { modifier = Modifier.padding(horizontal = MaterialTheme.padding.medium), ) } - BackupChoices.forEach { (k, v) -> + BackupOptions.entries.forEach { option -> item { LabeledCheckbox( - label = stringResource(v), - checked = state.flags.contains(k), + label = stringResource(option.label), + checked = option.getter(state.options), onCheckedChange = { - model.toggleFlag(k) + model.toggle(option.setter, it) }, modifier = Modifier.padding(horizontal = MaterialTheme.padding.medium), ) @@ -145,37 +140,28 @@ class CreateBackupScreen : Screen() { private class CreateBackupScreenModel : StateScreenModel(State()) { - fun toggleFlag(flag: Int) { + fun toggle(setter: (BackupOptions, Boolean) -> BackupOptions, enabled: Boolean) { mutableState.update { - if (it.flags.contains(flag)) { - it.copy(flags = it.flags - flag) - } else { - it.copy(flags = it.flags + flag) - } + it.copy( + options = setter(it.options, enabled), + ) } } fun createBackup(context: Context, uri: Uri) { - val flags = state.value.flags.fold(initial = 0, operation = { a, b -> a or b }) - BackupCreateJob.startNow(context, uri, flags) + BackupCreateJob.startNow(context, uri, state.value.options) } @Immutable data class State( - val flags: PersistentSet = persistentSetOf( - BackupCreateFlags.BACKUP_CATEGORY, - BackupCreateFlags.BACKUP_CHAPTER, - BackupCreateFlags.BACKUP_TRACK, - BackupCreateFlags.BACKUP_HISTORY, + val options: BackupOptions = BackupOptions( + libraryEntries = true, + categories = true, + chapters = true, + tracking = true, + history = true, + appSettings = false, + sourceSettings = false, ), ) } - -private val BackupChoices = persistentMapOf( - BackupCreateFlags.BACKUP_CATEGORY to MR.strings.categories, - BackupCreateFlags.BACKUP_CHAPTER to MR.strings.chapters, - BackupCreateFlags.BACKUP_TRACK to MR.strings.track, - BackupCreateFlags.BACKUP_HISTORY to MR.strings.history, - BackupCreateFlags.BACKUP_APP_PREFS to MR.strings.app_settings, - BackupCreateFlags.BACKUP_SOURCE_PREFS to MR.strings.source_settings, -) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/BackupCreateFlags.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/BackupCreateFlags.kt deleted file mode 100644 index 25c843a0d6..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/BackupCreateFlags.kt +++ /dev/null @@ -1,17 +0,0 @@ -package eu.kanade.tachiyomi.data.backup.create - -internal object BackupCreateFlags { - const val BACKUP_CATEGORY = 0x1 - const val BACKUP_CHAPTER = 0x2 - const val BACKUP_HISTORY = 0x4 - const val BACKUP_TRACK = 0x8 - const val BACKUP_APP_PREFS = 0x10 - const val BACKUP_SOURCE_PREFS = 0x20 - - const val AutomaticDefaults = BACKUP_CATEGORY or - BACKUP_CHAPTER or - BACKUP_HISTORY or - BACKUP_TRACK or - BACKUP_APP_PREFS or - BACKUP_SOURCE_PREFS -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/BackupCreateJob.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/BackupCreateJob.kt index c2f1e5ded7..303e6d3db5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/BackupCreateJob.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/BackupCreateJob.kt @@ -47,10 +47,12 @@ class BackupCreateJob(private val context: Context, workerParams: WorkerParamete setForegroundSafely() - val flags = inputData.getInt(BACKUP_FLAGS_KEY, BackupCreateFlags.AutomaticDefaults) + val options = inputData.getBooleanArray(OPTIONS_KEY) + ?.let { BackupOptions.fromBooleanArray(it) } + ?: BackupOptions.AutomaticDefaults return try { - val location = BackupCreator(context, isAutoBackup).backup(uri, flags) + val location = BackupCreator(context, isAutoBackup).backup(uri, options) if (!isAutoBackup) { notifier.showBackupComplete(UniFile.fromUri(context, location.toUri())!!) } @@ -112,11 +114,11 @@ class BackupCreateJob(private val context: Context, workerParams: WorkerParamete } } - fun startNow(context: Context, uri: Uri, flags: Int) { + fun startNow(context: Context, uri: Uri, options: BackupOptions) { val inputData = workDataOf( IS_AUTO_BACKUP_KEY to false, LOCATION_URI_KEY to uri.toString(), - BACKUP_FLAGS_KEY to flags, + OPTIONS_KEY to options.toBooleanArray(), ) val request = OneTimeWorkRequestBuilder() .addTag(TAG_MANUAL) @@ -132,4 +134,4 @@ private const val TAG_MANUAL = "$TAG_AUTO:manual" private const val IS_AUTO_BACKUP_KEY = "is_auto_backup" // Boolean private const val LOCATION_URI_KEY = "location_uri" // String -private const val BACKUP_FLAGS_KEY = "backup_flags" // Int +private const val OPTIONS_KEY = "options" // BooleanArray diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/BackupCreator.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/BackupCreator.kt index 695e74759d..6b3cfa5a4c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/BackupCreator.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/BackupCreator.kt @@ -5,9 +5,6 @@ import android.net.Uri import com.hippo.unifile.UniFile import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.data.backup.BackupFileValidator -import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags.BACKUP_APP_PREFS -import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags.BACKUP_CATEGORY -import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags.BACKUP_SOURCE_PREFS import eu.kanade.tachiyomi.data.backup.create.creators.CategoriesBackupCreator import eu.kanade.tachiyomi.data.backup.create.creators.MangaBackupCreator import eu.kanade.tachiyomi.data.backup.create.creators.PreferenceBackupCreator @@ -52,7 +49,7 @@ class BackupCreator( private val sourcesBackupCreator: SourcesBackupCreator = SourcesBackupCreator(), ) { - suspend fun backup(uri: Uri, flags: Int): String { + suspend fun backup(uri: Uri, options: BackupOptions): String { var file: UniFile? = null try { file = ( @@ -80,11 +77,11 @@ class BackupCreator( val databaseManga = getFavorites.await() val backup = Backup( - backupManga = backupMangas(databaseManga, flags), - backupCategories = backupCategories(flags), + backupManga = backupMangas(databaseManga, options), + backupCategories = backupCategories(options), backupSources = backupSources(databaseManga), - backupPreferences = backupAppPreferences(flags), - backupSourcePreferences = backupSourcePreferences(flags), + backupPreferences = backupAppPreferences(options), + backupSourcePreferences = backupSourcePreferences(options), ) val byteArray = parser.encodeToByteArray(BackupSerializer, backup) @@ -117,28 +114,28 @@ class BackupCreator( } } - private suspend fun backupCategories(options: Int): List { - if (options and BACKUP_CATEGORY != BACKUP_CATEGORY) return emptyList() + private suspend fun backupCategories(options: BackupOptions): List { + if (!options.categories) return emptyList() return categoriesBackupCreator.backupCategories() } - private suspend fun backupMangas(mangas: List, flags: Int): List { - return mangaBackupCreator.backupMangas(mangas, flags) + private suspend fun backupMangas(mangas: List, options: BackupOptions): List { + return mangaBackupCreator.backupMangas(mangas, options) } private fun backupSources(mangas: List): List { return sourcesBackupCreator.backupSources(mangas) } - private fun backupAppPreferences(flags: Int): List { - if (flags and BACKUP_APP_PREFS != BACKUP_APP_PREFS) return emptyList() + private fun backupAppPreferences(options: BackupOptions): List { + if (!options.appSettings) return emptyList() return preferenceBackupCreator.backupAppPreferences() } - private fun backupSourcePreferences(flags: Int): List { - if (flags and BACKUP_SOURCE_PREFS != BACKUP_SOURCE_PREFS) return emptyList() + private fun backupSourcePreferences(options: BackupOptions): List { + if (!options.sourceSettings) return emptyList() return preferenceBackupCreator.backupSourcePreferences() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/BackupOptions.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/BackupOptions.kt new file mode 100644 index 0000000000..c7c59c97b6 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/BackupOptions.kt @@ -0,0 +1,86 @@ +package eu.kanade.tachiyomi.data.backup.create + +import dev.icerock.moko.resources.StringResource +import kotlinx.collections.immutable.persistentListOf +import tachiyomi.i18n.MR + +data class BackupOptions( + val libraryEntries: Boolean = true, + val categories: Boolean = true, + val chapters: Boolean = true, + val tracking: Boolean = true, + val history: Boolean = true, + val appSettings: Boolean = true, + val sourceSettings: Boolean = true, +) { + fun toBooleanArray() = booleanArrayOf( + libraryEntries, + categories, + chapters, + tracking, + history, + appSettings, + sourceSettings, + ) + + companion object { + val AutomaticDefaults = BackupOptions( + libraryEntries = true, + categories = true, + chapters = true, + tracking = true, + history = true, + appSettings = true, + sourceSettings = true, + ) + + fun fromBooleanArray(booleanArray: BooleanArray) = BackupOptions( + libraryEntries = booleanArray[0], + categories = booleanArray[1], + chapters = booleanArray[2], + tracking = booleanArray[3], + history = booleanArray[4], + appSettings = booleanArray[5], + sourceSettings = booleanArray[6], + ) + + val entries = persistentListOf( + BackupOptionEntry( + label = MR.strings.categories, + getter = BackupOptions::categories, + setter = { options, enabled -> options.copy(categories = enabled) }, + ), + BackupOptionEntry( + label = MR.strings.chapters, + getter = BackupOptions::chapters, + setter = { options, enabled -> options.copy(chapters = enabled) }, + ), + BackupOptionEntry( + label = MR.strings.track, + getter = BackupOptions::tracking, + setter = { options, enabled -> options.copy(tracking = enabled) }, + ), + BackupOptionEntry( + label = MR.strings.history, + getter = BackupOptions::history, + setter = { options, enabled -> options.copy(history = enabled) }, + ), + BackupOptionEntry( + label = MR.strings.app_settings, + getter = BackupOptions::appSettings, + setter = { options, enabled -> options.copy(appSettings = enabled) }, + ), + BackupOptionEntry( + label = MR.strings.source_settings, + getter = BackupOptions::sourceSettings, + setter = { options, enabled -> options.copy(sourceSettings = enabled) }, + ), + ) + } +} + +data class BackupOptionEntry( + val label: StringResource, + val getter: (BackupOptions) -> Boolean, + val setter: (BackupOptions, Boolean) -> BackupOptions, +) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/creators/MangaBackupCreator.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/creators/MangaBackupCreator.kt index 67182ba83d..1c03f7fce1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/creators/MangaBackupCreator.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/creators/MangaBackupCreator.kt @@ -1,6 +1,6 @@ package eu.kanade.tachiyomi.data.backup.create.creators -import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags +import eu.kanade.tachiyomi.data.backup.create.BackupOptions import eu.kanade.tachiyomi.data.backup.models.BackupChapter import eu.kanade.tachiyomi.data.backup.models.BackupHistory import eu.kanade.tachiyomi.data.backup.models.BackupManga @@ -20,18 +20,17 @@ class MangaBackupCreator( private val getHistory: GetHistory = Injekt.get(), ) { - suspend fun backupMangas(mangas: List, flags: Int): List { + suspend fun backupMangas(mangas: List, options: BackupOptions): List { return mangas.map { - backupManga(it, flags) + backupManga(it, options) } } - private suspend fun backupManga(manga: Manga, options: Int): BackupManga { + private suspend fun backupManga(manga: Manga, options: BackupOptions): BackupManga { // Entry for this manga val mangaObject = manga.toBackupManga() - // Check if user wants chapter information in backup - if (options and BackupCreateFlags.BACKUP_CHAPTER == BackupCreateFlags.BACKUP_CHAPTER) { + if (options.chapters) { // Backup all the chapters handler.awaitList { chaptersQueries.getChaptersByMangaId( @@ -44,8 +43,7 @@ class MangaBackupCreator( ?.let { mangaObject.chapters = it } } - // Check if user wants category information in backup - if (options and BackupCreateFlags.BACKUP_CATEGORY == BackupCreateFlags.BACKUP_CATEGORY) { + if (options.categories) { // Backup categories for this manga val categoriesForManga = getCategories.await(manga.id) if (categoriesForManga.isNotEmpty()) { @@ -53,16 +51,14 @@ class MangaBackupCreator( } } - // Check if user wants track information in backup - if (options and BackupCreateFlags.BACKUP_TRACK == BackupCreateFlags.BACKUP_TRACK) { + if (options.tracking) { val tracks = handler.awaitList { manga_syncQueries.getTracksByMangaId(manga.id, backupTrackMapper) } if (tracks.isNotEmpty()) { mangaObject.tracking = tracks } } - // Check if user wants history information in backup - if (options and BackupCreateFlags.BACKUP_HISTORY == BackupCreateFlags.BACKUP_HISTORY) { + if (options.history) { val historyByMangaId = getHistory.await(manga.id) if (historyByMangaId.isNotEmpty()) { val history = historyByMangaId.map { history -> diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/creators/PreferenceBackupCreator.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/creators/PreferenceBackupCreator.kt index c75612de94..304f909ad5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/creators/PreferenceBackupCreator.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/creators/PreferenceBackupCreator.kt @@ -40,7 +40,7 @@ class PreferenceBackupCreator( @Suppress("UNCHECKED_CAST") private fun Map.toBackupPreferences(): List { return this.filterKeys { - !Preference.isPrivate(it) && !Preference.isAppState(it) + !Preference.isAppState(it) && !Preference.isPrivate(it) } .mapNotNull { (key, value) -> when (value) {