mirror of
https://github.com/mihonapp/mihon.git
synced 2025-08-22 06:11:32 +02:00
Compare commits
2 Commits
0af90999c8
...
c201b341a7
Author | SHA1 | Date | |
---|---|---|---|
|
c201b341a7 | ||
|
56fb4f62a1 |
@@ -6,7 +6,6 @@ import android.content.Intent
|
||||
import android.net.Uri
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
@@ -68,7 +67,7 @@ class CreateBackupScreen : Screen() {
|
||||
LazyColumnWithAction(
|
||||
contentPadding = contentPadding,
|
||||
actionLabel = stringResource(MR.strings.action_create),
|
||||
actionEnabled = state.options.anyEnabled(),
|
||||
actionEnabled = state.options.canCreate(),
|
||||
onClickAction = {
|
||||
if (!BackupCreateJob.isManualJobRunning(context)) {
|
||||
try {
|
||||
@@ -103,7 +102,7 @@ class CreateBackupScreen : Screen() {
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ColumnScope.Options(
|
||||
private fun Options(
|
||||
options: ImmutableList<BackupOptions.Entry>,
|
||||
state: CreateBackupScreenModel.State,
|
||||
model: CreateBackupScreenModel,
|
||||
|
@@ -63,7 +63,7 @@ class RestoreBackupScreen(
|
||||
LazyColumnWithAction(
|
||||
contentPadding = contentPadding,
|
||||
actionLabel = stringResource(MR.strings.action_restore),
|
||||
actionEnabled = state.canRestore && state.options.anyEnabled(),
|
||||
actionEnabled = state.canRestore && state.options.canRestore(),
|
||||
onClickAction = {
|
||||
model.startRestore()
|
||||
navigator.pop()
|
||||
|
@@ -51,34 +51,32 @@ class BackupCreator(
|
||||
suspend fun backup(uri: Uri, options: BackupOptions): String {
|
||||
var file: UniFile? = null
|
||||
try {
|
||||
file = (
|
||||
if (isAutoBackup) {
|
||||
// Get dir of file and create
|
||||
val dir = UniFile.fromUri(context, uri)
|
||||
file = if (isAutoBackup) {
|
||||
// Get dir of file and create
|
||||
val dir = UniFile.fromUri(context, uri)
|
||||
|
||||
// Delete older backups
|
||||
dir?.listFiles { _, filename -> FILENAME_REGEX.matches(filename) }
|
||||
.orEmpty()
|
||||
.sortedByDescending { it.name }
|
||||
.drop(MAX_AUTO_BACKUPS - 1)
|
||||
.forEach { it.delete() }
|
||||
// Delete older backups
|
||||
dir?.listFiles { _, filename -> FILENAME_REGEX.matches(filename) }
|
||||
.orEmpty()
|
||||
.sortedByDescending { it.name }
|
||||
.drop(MAX_AUTO_BACKUPS - 1)
|
||||
.forEach { it.delete() }
|
||||
|
||||
// Create new file to place backup
|
||||
dir?.createFile(getFilename())
|
||||
} else {
|
||||
UniFile.fromUri(context, uri)
|
||||
}
|
||||
)
|
||||
// Create new file to place backup
|
||||
dir?.createFile(getFilename())
|
||||
} else {
|
||||
UniFile.fromUri(context, uri)
|
||||
}
|
||||
|
||||
if (file == null || !file.isFile) {
|
||||
throw IllegalStateException(context.stringResource(MR.strings.create_backup_file_error))
|
||||
}
|
||||
|
||||
val databaseManga = getFavorites.await()
|
||||
val backupManga = backupMangas(getFavorites.await(), options)
|
||||
val backup = Backup(
|
||||
backupManga = backupMangas(databaseManga, options),
|
||||
backupManga = backupManga,
|
||||
backupCategories = backupCategories(options),
|
||||
backupSources = backupSources(databaseManga),
|
||||
backupSources = backupSources(backupManga),
|
||||
backupPreferences = backupAppPreferences(options),
|
||||
backupSourcePreferences = backupSourcePreferences(options),
|
||||
)
|
||||
@@ -116,27 +114,29 @@ class BackupCreator(
|
||||
private suspend fun backupCategories(options: BackupOptions): List<BackupCategory> {
|
||||
if (!options.categories) return emptyList()
|
||||
|
||||
return categoriesBackupCreator.backupCategories()
|
||||
return categoriesBackupCreator()
|
||||
}
|
||||
|
||||
private suspend fun backupMangas(mangas: List<Manga>, options: BackupOptions): List<BackupManga> {
|
||||
return mangaBackupCreator.backupMangas(mangas, options)
|
||||
if (!options.libraryEntries) return emptyList()
|
||||
|
||||
return mangaBackupCreator(mangas, options)
|
||||
}
|
||||
|
||||
private fun backupSources(mangas: List<Manga>): List<BackupSource> {
|
||||
return sourcesBackupCreator.backupSources(mangas)
|
||||
private fun backupSources(mangas: List<BackupManga>): List<BackupSource> {
|
||||
return sourcesBackupCreator(mangas)
|
||||
}
|
||||
|
||||
private fun backupAppPreferences(options: BackupOptions): List<BackupPreference> {
|
||||
if (!options.appSettings) return emptyList()
|
||||
|
||||
return preferenceBackupCreator.backupAppPreferences(includePrivatePreferences = options.privateSettings)
|
||||
return preferenceBackupCreator.createApp(includePrivatePreferences = options.privateSettings)
|
||||
}
|
||||
|
||||
private fun backupSourcePreferences(options: BackupOptions): List<BackupSourcePreferences> {
|
||||
if (!options.sourceSettings) return emptyList()
|
||||
|
||||
return preferenceBackupCreator.backupSourcePreferences(includePrivatePreferences = options.privateSettings)
|
||||
return preferenceBackupCreator.createSource(includePrivatePreferences = options.privateSettings)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@@ -26,7 +26,7 @@ data class BackupOptions(
|
||||
privateSettings,
|
||||
)
|
||||
|
||||
fun anyEnabled() = libraryEntries || appSettings || sourceSettings
|
||||
fun canCreate() = libraryEntries || categories || appSettings || sourceSettings
|
||||
|
||||
companion object {
|
||||
val libraryOptions = persistentListOf(
|
||||
@@ -35,12 +35,6 @@ data class BackupOptions(
|
||||
getter = BackupOptions::libraryEntries,
|
||||
setter = { options, enabled -> options.copy(libraryEntries = enabled) },
|
||||
),
|
||||
Entry(
|
||||
label = MR.strings.categories,
|
||||
getter = BackupOptions::categories,
|
||||
setter = { options, enabled -> options.copy(categories = enabled) },
|
||||
enabled = { it.libraryEntries },
|
||||
),
|
||||
Entry(
|
||||
label = MR.strings.chapters,
|
||||
getter = BackupOptions::chapters,
|
||||
@@ -59,6 +53,11 @@ data class BackupOptions(
|
||||
setter = { options, enabled -> options.copy(history = enabled) },
|
||||
enabled = { it.libraryEntries },
|
||||
),
|
||||
Entry(
|
||||
label = MR.strings.categories,
|
||||
getter = BackupOptions::categories,
|
||||
setter = { options, enabled -> options.copy(categories = enabled) },
|
||||
),
|
||||
)
|
||||
|
||||
val settingsOptions = persistentListOf(
|
||||
|
@@ -11,7 +11,7 @@ class CategoriesBackupCreator(
|
||||
private val getCategories: GetCategories = Injekt.get(),
|
||||
) {
|
||||
|
||||
suspend fun backupCategories(): List<BackupCategory> {
|
||||
suspend operator fun invoke(): List<BackupCategory> {
|
||||
return getCategories.await()
|
||||
.filterNot(Category::isSystemCategory)
|
||||
.map(backupCategoryMapper)
|
||||
|
@@ -20,7 +20,7 @@ class MangaBackupCreator(
|
||||
private val getHistory: GetHistory = Injekt.get(),
|
||||
) {
|
||||
|
||||
suspend fun backupMangas(mangas: List<Manga>, options: BackupOptions): List<BackupManga> {
|
||||
suspend operator fun invoke(mangas: List<Manga>, options: BackupOptions): List<BackupManga> {
|
||||
return mangas.map {
|
||||
backupManga(it, options)
|
||||
}
|
||||
|
@@ -22,12 +22,12 @@ class PreferenceBackupCreator(
|
||||
private val preferenceStore: PreferenceStore = Injekt.get(),
|
||||
) {
|
||||
|
||||
fun backupAppPreferences(includePrivatePreferences: Boolean): List<BackupPreference> {
|
||||
fun createApp(includePrivatePreferences: Boolean): List<BackupPreference> {
|
||||
return preferenceStore.getAll().toBackupPreferences()
|
||||
.withPrivatePreferences(includePrivatePreferences)
|
||||
}
|
||||
|
||||
fun backupSourcePreferences(includePrivatePreferences: Boolean): List<BackupSourcePreferences> {
|
||||
fun createSource(includePrivatePreferences: Boolean): List<BackupSourcePreferences> {
|
||||
return sourceManager.getCatalogueSources()
|
||||
.filterIsInstance<ConfigurableSource>()
|
||||
.map {
|
||||
|
@@ -1,8 +1,8 @@
|
||||
package eu.kanade.tachiyomi.data.backup.create.creators
|
||||
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupManga
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupSource
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
@@ -11,10 +11,10 @@ class SourcesBackupCreator(
|
||||
private val sourceManager: SourceManager = Injekt.get(),
|
||||
) {
|
||||
|
||||
fun backupSources(mangas: List<Manga>): List<BackupSource> {
|
||||
operator fun invoke(mangas: List<BackupManga>): List<BackupSource> {
|
||||
return mangas
|
||||
.asSequence()
|
||||
.map(Manga::source)
|
||||
.map(BackupManga::source)
|
||||
.distinct()
|
||||
.map(sourceManager::getOrStub)
|
||||
.map { it.toBackupSource() }
|
||||
|
@@ -67,8 +67,11 @@ class BackupRestorer(
|
||||
val backupMaps = backup.backupSources + backup.backupBrokenSources.map { it.toBackupSource() }
|
||||
sourceMapping = backupMaps.associate { it.sourceId to it.name }
|
||||
|
||||
if (options.library) {
|
||||
restoreAmount += backup.backupManga.size + 1 // +1 for categories
|
||||
if (options.libraryEntries) {
|
||||
restoreAmount += backup.backupManga.size
|
||||
}
|
||||
if (options.categories) {
|
||||
restoreAmount += 1
|
||||
}
|
||||
if (options.appSettings) {
|
||||
restoreAmount += 1
|
||||
@@ -78,7 +81,7 @@ class BackupRestorer(
|
||||
}
|
||||
|
||||
coroutineScope {
|
||||
if (options.library) {
|
||||
if (options.categories) {
|
||||
restoreCategories(backup.backupCategories)
|
||||
}
|
||||
if (options.appSettings) {
|
||||
@@ -87,8 +90,8 @@ class BackupRestorer(
|
||||
if (options.sourceSettings) {
|
||||
restoreSourcePreferences(backup.backupSourcePreferences)
|
||||
}
|
||||
if (options.library) {
|
||||
restoreManga(backup.backupManga, backup.backupCategories)
|
||||
if (options.libraryEntries) {
|
||||
restoreManga(backup.backupManga, if (options.categories) backup.backupCategories else emptyList())
|
||||
}
|
||||
|
||||
// TODO: optionally trigger online library + tracker update
|
||||
@@ -97,7 +100,7 @@ class BackupRestorer(
|
||||
|
||||
private fun CoroutineScope.restoreCategories(backupCategories: List<BackupCategory>) = launch {
|
||||
ensureActive()
|
||||
categoriesRestorer.restoreCategories(backupCategories)
|
||||
categoriesRestorer(backupCategories)
|
||||
|
||||
restoreProgress += 1
|
||||
notifier.showRestoreProgress(
|
||||
@@ -117,7 +120,7 @@ class BackupRestorer(
|
||||
ensureActive()
|
||||
|
||||
try {
|
||||
mangaRestorer.restoreManga(it, backupCategories)
|
||||
mangaRestorer.restore(it, backupCategories)
|
||||
} catch (e: Exception) {
|
||||
val sourceName = sourceMapping[it.source] ?: it.source.toString()
|
||||
errors.add(Date() to "${it.title} [$sourceName]: ${e.message}")
|
||||
@@ -130,7 +133,7 @@ class BackupRestorer(
|
||||
|
||||
private fun CoroutineScope.restoreAppPreferences(preferences: List<BackupPreference>) = launch {
|
||||
ensureActive()
|
||||
preferenceRestorer.restoreAppPreferences(preferences)
|
||||
preferenceRestorer.restoreApp(preferences)
|
||||
|
||||
restoreProgress += 1
|
||||
notifier.showRestoreProgress(
|
||||
@@ -143,7 +146,7 @@ class BackupRestorer(
|
||||
|
||||
private fun CoroutineScope.restoreSourcePreferences(preferences: List<BackupSourcePreferences>) = launch {
|
||||
ensureActive()
|
||||
preferenceRestorer.restoreSourcePreferences(preferences)
|
||||
preferenceRestorer.restoreSource(preferences)
|
||||
|
||||
restoreProgress += 1
|
||||
notifier.showRestoreProgress(
|
||||
|
@@ -5,25 +5,32 @@ import kotlinx.collections.immutable.persistentListOf
|
||||
import tachiyomi.i18n.MR
|
||||
|
||||
data class RestoreOptions(
|
||||
val library: Boolean = true,
|
||||
val libraryEntries: Boolean = true,
|
||||
val categories: Boolean = true,
|
||||
val appSettings: Boolean = true,
|
||||
val sourceSettings: Boolean = true,
|
||||
) {
|
||||
|
||||
fun asBooleanArray() = booleanArrayOf(
|
||||
library,
|
||||
libraryEntries,
|
||||
categories,
|
||||
appSettings,
|
||||
sourceSettings,
|
||||
)
|
||||
|
||||
fun anyEnabled() = library || appSettings || sourceSettings
|
||||
fun canRestore() = libraryEntries || categories || appSettings || sourceSettings
|
||||
|
||||
companion object {
|
||||
val options = persistentListOf(
|
||||
Entry(
|
||||
label = MR.strings.label_library,
|
||||
getter = RestoreOptions::library,
|
||||
setter = { options, enabled -> options.copy(library = enabled) },
|
||||
getter = RestoreOptions::libraryEntries,
|
||||
setter = { options, enabled -> options.copy(libraryEntries = enabled) },
|
||||
),
|
||||
Entry(
|
||||
label = MR.strings.categories,
|
||||
getter = RestoreOptions::categories,
|
||||
setter = { options, enabled -> options.copy(categories = enabled) },
|
||||
),
|
||||
Entry(
|
||||
label = MR.strings.app_settings,
|
||||
@@ -38,9 +45,10 @@ data class RestoreOptions(
|
||||
)
|
||||
|
||||
fun fromBooleanArray(array: BooleanArray) = RestoreOptions(
|
||||
library = array[0],
|
||||
appSettings = array[1],
|
||||
sourceSettings = array[2],
|
||||
libraryEntries = array[0],
|
||||
categories = array[1],
|
||||
appSettings = array[2],
|
||||
sourceSettings = array[3],
|
||||
)
|
||||
}
|
||||
|
||||
|
@@ -13,7 +13,7 @@ class CategoriesRestorer(
|
||||
private val libraryPreferences: LibraryPreferences = Injekt.get(),
|
||||
) {
|
||||
|
||||
suspend fun restoreCategories(backupCategories: List<BackupCategory>) {
|
||||
suspend operator fun invoke(backupCategories: List<BackupCategory>) {
|
||||
if (backupCategories.isNotEmpty()) {
|
||||
val dbCategories = getCategories.await()
|
||||
val dbCategoriesByName = dbCategories.associateBy { it.name }
|
||||
|
@@ -53,7 +53,7 @@ class MangaRestorer(
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun restoreManga(
|
||||
suspend fun restore(
|
||||
backupManga: BackupManga,
|
||||
backupCategories: List<BackupCategory>,
|
||||
) {
|
||||
|
@@ -22,14 +22,14 @@ class PreferenceRestorer(
|
||||
private val preferenceStore: PreferenceStore = Injekt.get(),
|
||||
) {
|
||||
|
||||
fun restoreAppPreferences(preferences: List<BackupPreference>) {
|
||||
fun restoreApp(preferences: List<BackupPreference>) {
|
||||
restorePreferences(preferences, preferenceStore)
|
||||
|
||||
LibraryUpdateJob.setupTask(context)
|
||||
BackupCreateJob.setupTask(context)
|
||||
}
|
||||
|
||||
fun restoreSourcePreferences(preferences: List<BackupSourcePreferences>) {
|
||||
fun restoreSource(preferences: List<BackupSourcePreferences>) {
|
||||
preferences.forEach {
|
||||
val sourcePrefs = AndroidPreferenceStore(context, sourcePreferences(it.sourceKey))
|
||||
restorePreferences(it.prefs, sourcePrefs)
|
||||
|
Reference in New Issue
Block a user