Start cleaning up backup/restore code
The abstraction was useful for handling 2 systems, but it's no longer needed. Cleaning it up will make migrating to domain models easier down the line. (cherry picked from commit a2bb81b7db457c3927eaa1f03416a9b07985842b) # Conflicts: # app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt # app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestorer.kt # app/src/main/java/eu/kanade/tachiyomi/data/backup/models/Backup.kt # app/src/main/java/eu/kanade/tachiyomi/data/backup/models/BackupFlatMetadata.kt # app/src/main/java/eu/kanade/tachiyomi/data/backup/models/BackupMergedMangaReference.kt # app/src/main/java/eu/kanade/tachiyomi/data/backup/models/BackupSavedSearch.kt # app/src/main/java/eu/kanade/tachiyomi/data/backup/models/metadata/BackupSearchMetadata.kt # app/src/main/java/eu/kanade/tachiyomi/data/backup/models/metadata/BackupSearchTag.kt # app/src/main/java/eu/kanade/tachiyomi/data/backup/models/metadata/BackupSearchTitle.kt
This commit is contained in:
parent
b0fc4dd6d4
commit
6f6a9b677c
@ -297,14 +297,15 @@ tasks {
|
|||||||
// See https://kotlinlang.org/docs/reference/experimental.html#experimental-status-of-experimental-api(-markers)
|
// See https://kotlinlang.org/docs/reference/experimental.html#experimental-status-of-experimental-api(-markers)
|
||||||
withType<KotlinCompile> {
|
withType<KotlinCompile> {
|
||||||
kotlinOptions.freeCompilerArgs += listOf(
|
kotlinOptions.freeCompilerArgs += listOf(
|
||||||
"-opt-in=kotlinx.coroutines.InternalCoroutinesApi",
|
|
||||||
"-opt-in=coil.annotation.ExperimentalCoilApi",
|
"-opt-in=coil.annotation.ExperimentalCoilApi",
|
||||||
|
"-opt-in=com.google.accompanist.pager.ExperimentalPagerApi",
|
||||||
"-opt-in=androidx.compose.material3.ExperimentalMaterial3Api",
|
"-opt-in=androidx.compose.material3.ExperimentalMaterial3Api",
|
||||||
"-opt-in=androidx.compose.ui.ExperimentalComposeUiApi",
|
"-opt-in=androidx.compose.ui.ExperimentalComposeUiApi",
|
||||||
"-opt-in=androidx.compose.foundation.ExperimentalFoundationApi",
|
"-opt-in=androidx.compose.foundation.ExperimentalFoundationApi",
|
||||||
"-opt-in=androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi",
|
"-opt-in=androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi",
|
||||||
"-opt-in=androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi",
|
"-opt-in=androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi",
|
||||||
"-opt-in=com.google.accompanist.pager.ExperimentalPagerApi",
|
"-opt-in=kotlinx.coroutines.InternalCoroutinesApi",
|
||||||
|
"-opt-in=kotlinx.serialization.ExperimentalSerializationApi",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.net.Uri
|
|
||||||
|
|
||||||
abstract class AbstractBackupRestoreValidator {
|
|
||||||
abstract fun validate(context: Context, uri: Uri): Results
|
|
||||||
|
|
||||||
data class Results(val missingSources: List<String>, val missingTrackers: List<String>)
|
|
||||||
}
|
|
@ -13,7 +13,6 @@ import androidx.work.WorkManager
|
|||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
import androidx.work.workDataOf
|
import androidx.work.workDataOf
|
||||||
import com.hippo.unifile.UniFile
|
import com.hippo.unifile.UniFile
|
||||||
import eu.kanade.tachiyomi.data.backup.full.FullBackupManager
|
|
||||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.util.system.logcat
|
import eu.kanade.tachiyomi.util.system.logcat
|
||||||
@ -36,7 +35,7 @@ class BackupCreatorJob(private val context: Context, workerParams: WorkerParamet
|
|||||||
|
|
||||||
context.notificationManager.notify(Notifications.ID_BACKUP_PROGRESS, notifier.showBackupProgress().build())
|
context.notificationManager.notify(Notifications.ID_BACKUP_PROGRESS, notifier.showBackupProgress().build())
|
||||||
return try {
|
return try {
|
||||||
val location = FullBackupManager(context).createBackup(uri, flags, isAutoBackup)
|
val location = BackupManager(context).createBackup(uri, flags, isAutoBackup)
|
||||||
if (!isAutoBackup) notifier.showBackupComplete(UniFile.fromUri(context, location.toUri()))
|
if (!isAutoBackup) notifier.showBackupComplete(UniFile.fromUri(context, location.toUri()))
|
||||||
Result.success()
|
Result.success()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.full
|
package eu.kanade.tachiyomi.data.backup
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.backup.AbstractBackupRestoreValidator
|
import eu.kanade.tachiyomi.data.backup.models.BackupSerializer
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.BackupSerializer
|
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import okio.buffer
|
import okio.buffer
|
||||||
@ -13,10 +12,10 @@ import okio.source
|
|||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
class FullBackupRestoreValidator : AbstractBackupRestoreValidator() {
|
class BackupFileValidator(
|
||||||
|
private val sourceManager: SourceManager = Injekt.get(),
|
||||||
private val sourceManager: SourceManager = Injekt.get()
|
private val trackManager: TrackManager = Injekt.get(),
|
||||||
private val trackManager: TrackManager = Injekt.get()
|
) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks for critical backup file data.
|
* Checks for critical backup file data.
|
||||||
@ -24,8 +23,8 @@ class FullBackupRestoreValidator : AbstractBackupRestoreValidator() {
|
|||||||
* @throws Exception if manga cannot be found.
|
* @throws Exception if manga cannot be found.
|
||||||
* @return List of missing sources or missing trackers.
|
* @return List of missing sources or missing trackers.
|
||||||
*/
|
*/
|
||||||
override fun validate(context: Context, uri: Uri): Results {
|
fun validate(context: Context, uri: Uri): Results {
|
||||||
val backupManager = FullBackupManager(context)
|
val backupManager = BackupManager(context)
|
||||||
|
|
||||||
val backup = try {
|
val backup = try {
|
||||||
val backupString =
|
val backupString =
|
||||||
@ -63,4 +62,6 @@ class FullBackupRestoreValidator : AbstractBackupRestoreValidator() {
|
|||||||
|
|
||||||
return Results(missingSources, missingTrackers)
|
return Results(missingSources, missingTrackers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class Results(val missingSources: List<String>, val missingTrackers: List<String>)
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.full
|
package eu.kanade.tachiyomi.data.backup
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
@ -11,7 +11,6 @@ import eu.kanade.data.manga.mangaMapper
|
|||||||
import eu.kanade.domain.category.model.Category
|
import eu.kanade.domain.category.model.Category
|
||||||
import eu.kanade.domain.history.model.HistoryUpdate
|
import eu.kanade.domain.history.model.HistoryUpdate
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.backup.AbstractBackupManager
|
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CATEGORY
|
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CATEGORY
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CATEGORY_MASK
|
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CATEGORY_MASK
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CHAPTER
|
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CHAPTER
|
||||||
@ -24,21 +23,20 @@ import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_READ_MANGA
|
|||||||
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_READ_MANGA_MASK
|
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_READ_MANGA_MASK
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_TRACK
|
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_TRACK
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_TRACK_MASK
|
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_TRACK_MASK
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.Backup
|
import eu.kanade.tachiyomi.data.backup.models.Backup
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.BackupCategory
|
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.BackupFlatMetadata
|
import eu.kanade.tachiyomi.data.backup.models.BackupFlatMetadata
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.BackupFull
|
import eu.kanade.tachiyomi.data.backup.models.BackupHistory
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.BackupHistory
|
import eu.kanade.tachiyomi.data.backup.models.BackupManga
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.BackupManga
|
import eu.kanade.tachiyomi.data.backup.models.BackupMergedMangaReference
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.BackupMergedMangaReference
|
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.BackupSavedSearch
|
import eu.kanade.tachiyomi.data.backup.models.BackupSerializer
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.BackupSerializer
|
import eu.kanade.tachiyomi.data.backup.models.BackupSource
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.BackupSource
|
import eu.kanade.tachiyomi.data.backup.models.backupCategoryMapper
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.backupCategoryMapper
|
import eu.kanade.tachiyomi.data.backup.models.backupChapterMapper
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.backupChapterMapper
|
import eu.kanade.tachiyomi.data.backup.models.backupMergedMangaReferenceMapper
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.backupMergedMangaReferenceMapper
|
import eu.kanade.tachiyomi.data.backup.models.backupSavedSearchMapper
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.backupSavedSearchMapper
|
import eu.kanade.tachiyomi.data.backup.models.backupTrackMapper
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.backupTrackMapper
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
@ -57,7 +55,7 @@ import java.util.Date
|
|||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import eu.kanade.domain.manga.model.Manga as DomainManga
|
import eu.kanade.domain.manga.model.Manga as DomainManga
|
||||||
|
|
||||||
class FullBackupManager(context: Context) : AbstractBackupManager(context) {
|
class BackupManager(context: Context) : AbstractBackupManager(context) {
|
||||||
|
|
||||||
val parser = ProtoBuf
|
val parser = ProtoBuf
|
||||||
|
|
||||||
@ -67,6 +65,7 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
|
|||||||
* @param uri path of Uri
|
* @param uri path of Uri
|
||||||
* @param isAutoBackup backup called from scheduled backup job
|
* @param isAutoBackup backup called from scheduled backup job
|
||||||
*/
|
*/
|
||||||
|
@Suppress("BlockingMethodInNonBlockingContext")
|
||||||
override suspend fun createBackup(uri: Uri, flags: Int, isAutoBackup: Boolean): String {
|
override suspend fun createBackup(uri: Uri, flags: Int, isAutoBackup: Boolean): String {
|
||||||
// Create root object
|
// Create root object
|
||||||
var backup: Backup? = null
|
var backup: Backup? = null
|
||||||
@ -78,7 +77,7 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
|
|||||||
} + getMergedManga() // SY <--
|
} + getMergedManga() // SY <--
|
||||||
|
|
||||||
backup = Backup(
|
backup = Backup(
|
||||||
backupManga(databaseManga, flags),
|
backupMangas(databaseManga, flags),
|
||||||
backupCategories(flags),
|
backupCategories(flags),
|
||||||
emptyList(),
|
emptyList(),
|
||||||
backupExtensionInfo(databaseManga),
|
backupExtensionInfo(databaseManga),
|
||||||
@ -105,7 +104,7 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
|
|||||||
.forEach { it.delete() }
|
.forEach { it.delete() }
|
||||||
|
|
||||||
// Create new file to place backup
|
// Create new file to place backup
|
||||||
dir.createFile(BackupFull.getDefaultFilename())
|
dir.createFile(Backup.getBackupFilename())
|
||||||
} else {
|
} else {
|
||||||
UniFile.fromUri(context, uri)
|
UniFile.fromUri(context, uri)
|
||||||
}
|
}
|
||||||
@ -128,7 +127,7 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
|
|||||||
val fileUri = file.uri
|
val fileUri = file.uri
|
||||||
|
|
||||||
// Make sure it's a valid backup file
|
// Make sure it's a valid backup file
|
||||||
FullBackupRestoreValidator().validate(context, fileUri)
|
BackupFileValidator().validate(context, fileUri)
|
||||||
|
|
||||||
return fileUri.toString()
|
return fileUri.toString()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@ -138,12 +137,6 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun backupManga(mangas: List<DomainManga>, flags: Int): List<BackupManga> {
|
|
||||||
return mangas.map {
|
|
||||||
backupMangaObject(it, flags)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun backupExtensionInfo(mangas: List<DomainManga>): List<BackupSource> {
|
private fun backupExtensionInfo(mangas: List<DomainManga>): List<BackupSource> {
|
||||||
return mangas
|
return mangas
|
||||||
.asSequence()
|
.asSequence()
|
||||||
@ -170,6 +163,12 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun backupMangas(mangas: List<DomainManga>, flags: Int): List<BackupManga> {
|
||||||
|
return mangas.map {
|
||||||
|
backupManga(it, flags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
/**
|
/**
|
||||||
* Backup the saved searches from sources
|
* Backup the saved searches from sources
|
||||||
@ -188,7 +187,7 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
|
|||||||
* @param options options for the backup
|
* @param options options for the backup
|
||||||
* @return [BackupManga] containing manga in a serializable form
|
* @return [BackupManga] containing manga in a serializable form
|
||||||
*/
|
*/
|
||||||
private suspend fun backupMangaObject(manga: DomainManga, options: Int): BackupManga {
|
private suspend fun backupManga(manga: DomainManga, options: Int): BackupManga {
|
||||||
// Entry for this manga
|
// Entry for this manga
|
||||||
val mangaObject = BackupManga.copyFrom(manga /* SY --> */, if (options and BACKUP_CUSTOM_INFO_MASK == BACKUP_CUSTOM_INFO) customMangaManager else null /* SY <-- */)
|
val mangaObject = BackupManga.copyFrom(manga /* SY --> */, if (options and BACKUP_CUSTOM_INFO_MASK == BACKUP_CUSTOM_INFO) customMangaManager else null /* SY <-- */)
|
||||||
|
|
||||||
@ -248,7 +247,7 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
|
|||||||
return mangaObject
|
return mangaObject
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun restoreMangaNoFetch(manga: Manga, dbManga: Mangas) {
|
suspend fun restoreExistingManga(manga: Manga, dbManga: Mangas) {
|
||||||
manga.id = dbManga._id
|
manga.id = dbManga._id
|
||||||
manga.copyFrom(dbManga)
|
manga.copyFrom(dbManga)
|
||||||
updateManga(manga)
|
updateManga(manga)
|
||||||
@ -260,7 +259,7 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
|
|||||||
* @param manga manga that needs updating
|
* @param manga manga that needs updating
|
||||||
* @return Updated manga info.
|
* @return Updated manga info.
|
||||||
*/
|
*/
|
||||||
suspend fun restoreManga(manga: Manga): Manga {
|
suspend fun restoreNewManga(manga: Manga): Manga {
|
||||||
return manga.also {
|
return manga.also {
|
||||||
it.initialized = it.description != null
|
it.initialized = it.description != null
|
||||||
it.id = insertManga(it)
|
it.id = insertManga(it)
|
||||||
@ -313,7 +312,7 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
|
|||||||
* @param manga the manga whose categories have to be restored.
|
* @param manga the manga whose categories have to be restored.
|
||||||
* @param categories the categories to restore.
|
* @param categories the categories to restore.
|
||||||
*/
|
*/
|
||||||
internal suspend fun restoreCategoriesForManga(manga: Manga, categories: List<Int>, backupCategories: List<BackupCategory>) {
|
internal suspend fun restoreCategories(manga: Manga, categories: List<Int>, backupCategories: List<BackupCategory>) {
|
||||||
val dbCategories = handler.awaitList { categoriesQueries.getCategories() }
|
val dbCategories = handler.awaitList { categoriesQueries.getCategories() }
|
||||||
val mangaCategoriesToUpdate = mutableListOf<Pair<Long, Long>>()
|
val mangaCategoriesToUpdate = mutableListOf<Pair<Long, Long>>()
|
||||||
|
|
||||||
@ -345,7 +344,7 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
|
|||||||
*
|
*
|
||||||
* @param history list containing history to be restored
|
* @param history list containing history to be restored
|
||||||
*/
|
*/
|
||||||
internal suspend fun restoreHistoryForManga(history: List<BackupHistory>) {
|
internal suspend fun restoreHistory(history: List<BackupHistory>) {
|
||||||
// List containing history to be updated
|
// List containing history to be updated
|
||||||
val toUpdate = mutableListOf<HistoryUpdate>()
|
val toUpdate = mutableListOf<HistoryUpdate>()
|
||||||
for ((url, lastRead, readDuration) in history) {
|
for ((url, lastRead, readDuration) in history) {
|
||||||
@ -395,7 +394,7 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
|
|||||||
* @param manga the manga whose sync have to be restored.
|
* @param manga the manga whose sync have to be restored.
|
||||||
* @param tracks the track list to restore.
|
* @param tracks the track list to restore.
|
||||||
*/
|
*/
|
||||||
internal suspend fun restoreTrackForManga(manga: Manga, tracks: List<Track>) {
|
internal suspend fun restoreTracking(manga: Manga, tracks: List<Track>) {
|
||||||
// Fix foreign keys with the current manga id
|
// Fix foreign keys with the current manga id
|
||||||
tracks.map { it.manga_id = manga.id!! }
|
tracks.map { it.manga_id = manga.id!! }
|
||||||
|
|
||||||
@ -473,7 +472,7 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal suspend fun restoreChaptersForManga(manga: Manga, chapters: List<Chapter>) {
|
internal suspend fun restoreChapters(manga: Manga, chapters: List<Chapter>) {
|
||||||
val dbChapters = handler.awaitList { chaptersQueries.getChaptersByMangaId(manga.id!!) }
|
val dbChapters = handler.awaitList { chaptersQueries.getChaptersByMangaId(manga.id!!) }
|
||||||
|
|
||||||
chapters.forEach { chapter ->
|
chapters.forEach { chapter ->
|
@ -8,7 +8,6 @@ import android.os.IBinder
|
|||||||
import android.os.PowerManager
|
import android.os.PowerManager
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.backup.full.FullBackupRestore
|
|
||||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||||
import eu.kanade.tachiyomi.util.system.acquireWakeLock
|
import eu.kanade.tachiyomi.util.system.acquireWakeLock
|
||||||
import eu.kanade.tachiyomi.util.system.isServiceRunning
|
import eu.kanade.tachiyomi.util.system.isServiceRunning
|
||||||
@ -70,7 +69,7 @@ class BackupRestoreService : Service() {
|
|||||||
private lateinit var wakeLock: PowerManager.WakeLock
|
private lateinit var wakeLock: PowerManager.WakeLock
|
||||||
|
|
||||||
private lateinit var ioScope: CoroutineScope
|
private lateinit var ioScope: CoroutineScope
|
||||||
private var backupRestore: AbstractBackupRestore<*>? = null
|
private var restorer: AbstractBackupRestore<*>? = null
|
||||||
private lateinit var notifier: BackupNotifier
|
private lateinit var notifier: BackupNotifier
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
@ -94,7 +93,7 @@ class BackupRestoreService : Service() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun destroyJob() {
|
private fun destroyJob() {
|
||||||
backupRestore?.job?.cancel()
|
restorer?.job?.cancel()
|
||||||
ioScope.cancel()
|
ioScope.cancel()
|
||||||
if (wakeLock.isHeld) {
|
if (wakeLock.isHeld) {
|
||||||
wakeLock.release()
|
wakeLock.release()
|
||||||
@ -118,26 +117,26 @@ class BackupRestoreService : Service() {
|
|||||||
val uri = intent?.getParcelableExtra<Uri>(BackupConst.EXTRA_URI) ?: return START_NOT_STICKY
|
val uri = intent?.getParcelableExtra<Uri>(BackupConst.EXTRA_URI) ?: return START_NOT_STICKY
|
||||||
|
|
||||||
// Cancel any previous job if needed.
|
// Cancel any previous job if needed.
|
||||||
backupRestore?.job?.cancel()
|
restorer?.job?.cancel()
|
||||||
|
|
||||||
backupRestore = FullBackupRestore(this, notifier)
|
restorer = BackupRestorer(this, notifier)
|
||||||
|
|
||||||
val handler = CoroutineExceptionHandler { _, exception ->
|
val handler = CoroutineExceptionHandler { _, exception ->
|
||||||
logcat(LogPriority.ERROR, exception)
|
logcat(LogPriority.ERROR, exception)
|
||||||
backupRestore?.writeErrorLog()
|
restorer?.writeErrorLog()
|
||||||
|
|
||||||
notifier.showRestoreError(exception.message)
|
notifier.showRestoreError(exception.message)
|
||||||
stopSelf(startId)
|
stopSelf(startId)
|
||||||
}
|
}
|
||||||
val job = ioScope.launch(handler) {
|
val job = ioScope.launch(handler) {
|
||||||
if (backupRestore?.restoreBackup(uri) == false) {
|
if (restorer?.restoreBackup(uri) == false) {
|
||||||
notifier.showRestoreError(getString(R.string.restoring_backup_canceled))
|
notifier.showRestoreError(getString(R.string.restoring_backup_canceled))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
job.invokeOnCompletion {
|
job.invokeOnCompletion {
|
||||||
stopSelf(startId)
|
stopSelf(startId)
|
||||||
}
|
}
|
||||||
backupRestore?.job = job
|
restorer?.job = job
|
||||||
|
|
||||||
return START_NOT_STICKY
|
return START_NOT_STICKY
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,16 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.full
|
package eu.kanade.tachiyomi.data.backup
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.backup.AbstractBackupRestore
|
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupNotifier
|
import eu.kanade.tachiyomi.data.backup.models.BackupFlatMetadata
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.BackupCategory
|
import eu.kanade.tachiyomi.data.backup.models.BackupHistory
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.BackupFlatMetadata
|
import eu.kanade.tachiyomi.data.backup.models.BackupManga
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.BackupHistory
|
import eu.kanade.tachiyomi.data.backup.models.BackupMergedMangaReference
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.BackupManga
|
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.BackupMergedMangaReference
|
import eu.kanade.tachiyomi.data.backup.models.BackupSerializer
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.BackupSavedSearch
|
import eu.kanade.tachiyomi.data.backup.models.BackupSource
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.BackupSerializer
|
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.BackupSource
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
@ -24,12 +22,12 @@ import okio.gzip
|
|||||||
import okio.source
|
import okio.source
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
class FullBackupRestore(context: Context, notifier: BackupNotifier) : AbstractBackupRestore<FullBackupManager>(context, notifier) {
|
class BackupRestorer(context: Context, notifier: BackupNotifier) : AbstractBackupRestore<BackupManager>(context, notifier) {
|
||||||
|
|
||||||
|
@Suppress("BlockingMethodInNonBlockingContext")
|
||||||
override suspend fun performRestore(uri: Uri): Boolean {
|
override suspend fun performRestore(uri: Uri): Boolean {
|
||||||
backupManager = FullBackupManager(context)
|
backupManager = BackupManager(context)
|
||||||
|
|
||||||
@Suppress("BlockingMethodInNonBlockingContext")
|
|
||||||
val backupString = context.contentResolver.openInputStream(uri)!!.source().gzip().buffer().use { it.readByteArray() }
|
val backupString = context.contentResolver.openInputStream(uri)!!.source().gzip().buffer().use { it.readByteArray() }
|
||||||
val backup = backupManager.parser.decodeFromByteArray(BackupSerializer, backupString)
|
val backup = backupManager.parser.decodeFromByteArray(BackupSerializer, backupString)
|
||||||
|
|
||||||
@ -98,7 +96,17 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier) : AbstractBa
|
|||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
try {
|
try {
|
||||||
restoreMangaData(manga, chapters, categories, history, tracks, backupCategories/* SY --> */, mergedMangaReferences, flatMetadata, customManga/* SY <-- */)
|
val dbManga = backupManager.getMangaFromDatabase(manga.url, manga.source)
|
||||||
|
if (dbManga == null) {
|
||||||
|
// Manga not in database
|
||||||
|
restoreExistingManga(manga, chapters, categories, history, tracks, backupCategories/* SY --> */, mergedMangaReferences, flatMetadata, customManga/* SY <-- */)
|
||||||
|
} else {
|
||||||
|
// Manga in database
|
||||||
|
// Copy information from manga already in database
|
||||||
|
backupManager.restoreExistingManga(manga, dbManga)
|
||||||
|
// Fetch rest of manga information
|
||||||
|
restoreNewManga(manga, chapters, categories, history, tracks, backupCategories/* SY --> */, mergedMangaReferences, flatMetadata, customManga/* SY <-- */)
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
val sourceName = sourceMapping[manga.source] ?: manga.source.toString()
|
val sourceName = sourceMapping[manga.source] ?: manga.source.toString()
|
||||||
errors.add(Date() to "${manga.title} [$sourceName]: ${e.message}")
|
errors.add(Date() to "${manga.title} [$sourceName]: ${e.message}")
|
||||||
@ -108,41 +116,6 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier) : AbstractBa
|
|||||||
showRestoreProgress(restoreProgress, restoreAmount, manga.title)
|
showRestoreProgress(restoreProgress, restoreAmount, manga.title)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a manga restore observable
|
|
||||||
*
|
|
||||||
* @param manga manga data from json
|
|
||||||
* @param chapters chapters data from json
|
|
||||||
* @param categories categories data from json
|
|
||||||
* @param history history data from json
|
|
||||||
* @param tracks tracking data from json
|
|
||||||
*/
|
|
||||||
private suspend fun restoreMangaData(
|
|
||||||
manga: Manga,
|
|
||||||
chapters: List<Chapter>,
|
|
||||||
categories: List<Int>,
|
|
||||||
history: List<BackupHistory>,
|
|
||||||
tracks: List<Track>,
|
|
||||||
backupCategories: List<BackupCategory>,
|
|
||||||
// SY -->
|
|
||||||
mergedMangaReferences: List<BackupMergedMangaReference>,
|
|
||||||
flatMetadata: BackupFlatMetadata?,
|
|
||||||
customManga: CustomMangaManager.MangaJson?,
|
|
||||||
// SY -->
|
|
||||||
) {
|
|
||||||
val dbManga = backupManager.getMangaFromDatabase(manga.url, manga.source)
|
|
||||||
if (dbManga == null) {
|
|
||||||
// Manga not in database
|
|
||||||
restoreMangaFetch(manga, chapters, categories, history, tracks, backupCategories/* SY --> */, mergedMangaReferences, flatMetadata, customManga/* SY <-- */)
|
|
||||||
} else {
|
|
||||||
// Manga in database
|
|
||||||
// Copy information from manga already in database
|
|
||||||
backupManager.restoreMangaNoFetch(manga, dbManga)
|
|
||||||
// Fetch rest of manga information
|
|
||||||
restoreMangaNoFetch(manga, chapters, categories, history, tracks, backupCategories/* SY --> */, mergedMangaReferences, flatMetadata, customManga/* SY <-- */)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches manga information
|
* Fetches manga information
|
||||||
*
|
*
|
||||||
@ -150,7 +123,7 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier) : AbstractBa
|
|||||||
* @param chapters chapters of manga that needs updating
|
* @param chapters chapters of manga that needs updating
|
||||||
* @param categories categories that need updating
|
* @param categories categories that need updating
|
||||||
*/
|
*/
|
||||||
private suspend fun restoreMangaFetch(
|
private suspend fun restoreExistingManga(
|
||||||
manga: Manga,
|
manga: Manga,
|
||||||
chapters: List<Chapter>,
|
chapters: List<Chapter>,
|
||||||
categories: List<Int>,
|
categories: List<Int>,
|
||||||
@ -163,18 +136,14 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier) : AbstractBa
|
|||||||
customManga: CustomMangaManager.MangaJson?,
|
customManga: CustomMangaManager.MangaJson?,
|
||||||
// SY <--
|
// SY <--
|
||||||
) {
|
) {
|
||||||
try {
|
val fetchedManga = backupManager.restoreNewManga(manga)
|
||||||
val fetchedManga = backupManager.restoreManga(manga)
|
fetchedManga.id ?: return
|
||||||
fetchedManga.id ?: return
|
|
||||||
backupManager.restoreChaptersForManga(fetchedManga, chapters)
|
|
||||||
|
|
||||||
restoreExtraForManga(fetchedManga, categories, history, tracks, backupCategories /* SY --> */, mergedMangaReferences, flatMetadata, customManga/* SY <-- */)
|
backupManager.restoreChapters(fetchedManga, chapters)
|
||||||
} catch (e: Exception) {
|
restoreExtras(fetchedManga, categories, history, tracks, backupCategories/* SY --> */, mergedMangaReferences, flatMetadata, customManga/* SY <-- */)
|
||||||
errors.add(Date() to "${manga.title} - ${e.message}")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun restoreMangaNoFetch(
|
private suspend fun restoreNewManga(
|
||||||
backupManga: Manga,
|
backupManga: Manga,
|
||||||
chapters: List<Chapter>,
|
chapters: List<Chapter>,
|
||||||
categories: List<Int>,
|
categories: List<Int>,
|
||||||
@ -187,12 +156,11 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier) : AbstractBa
|
|||||||
customManga: CustomMangaManager.MangaJson?,
|
customManga: CustomMangaManager.MangaJson?,
|
||||||
// SY <--
|
// SY <--
|
||||||
) {
|
) {
|
||||||
backupManager.restoreChaptersForManga(backupManga, chapters)
|
backupManager.restoreChapters(backupManga, chapters)
|
||||||
|
restoreExtras(backupManga, categories, history, tracks, backupCategories/* SY --> */, mergedMangaReferences, flatMetadata, customManga/* SY <-- */)
|
||||||
restoreExtraForManga(backupManga, categories, history, tracks, backupCategories/* SY --> */, mergedMangaReferences, flatMetadata, customManga/* SY <-- */)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun restoreExtraForManga(
|
private suspend fun restoreExtras(
|
||||||
manga: Manga,
|
manga: Manga,
|
||||||
categories: List<Int>,
|
categories: List<Int>,
|
||||||
history: List<BackupHistory>,
|
history: List<BackupHistory>,
|
||||||
@ -204,23 +172,12 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier) : AbstractBa
|
|||||||
customManga: CustomMangaManager.MangaJson?,
|
customManga: CustomMangaManager.MangaJson?,
|
||||||
// SY <--
|
// SY <--
|
||||||
) {
|
) {
|
||||||
// Restore categories
|
backupManager.restoreCategories(manga, categories, backupCategories)
|
||||||
backupManager.restoreCategoriesForManga(manga, categories, backupCategories)
|
backupManager.restoreHistory(history)
|
||||||
|
backupManager.restoreTracking(manga, tracks)
|
||||||
// Restore history
|
|
||||||
backupManager.restoreHistoryForManga(history)
|
|
||||||
|
|
||||||
// Restore tracking
|
|
||||||
backupManager.restoreTrackForManga(manga, tracks)
|
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
// Restore merged manga references if its a merged manga
|
|
||||||
backupManager.restoreMergedMangaReferencesForManga(manga.id!!, mergedMangaReferences)
|
backupManager.restoreMergedMangaReferencesForManga(manga.id!!, mergedMangaReferences)
|
||||||
|
|
||||||
// Restore flat metadata for metadata sources
|
|
||||||
flatMetadata?.let { backupManager.restoreFlatMetadata(manga.id!!, it) }
|
flatMetadata?.let { backupManager.restoreFlatMetadata(manga.id!!, it) }
|
||||||
|
|
||||||
// Restore Custom Info
|
|
||||||
customManga?.id = manga.id!!
|
customManga?.id = manga.id!!
|
||||||
customManga?.let { customMangaManager.saveMangaInfo(it) }
|
customManga?.let { customMangaManager.saveMangaInfo(it) }
|
||||||
// SY <--
|
// SY <--
|
@ -1,12 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.full.models
|
|
||||||
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.Date
|
|
||||||
import java.util.Locale
|
|
||||||
|
|
||||||
object BackupFull {
|
|
||||||
fun getDefaultFilename(): String {
|
|
||||||
val date = SimpleDateFormat("yyyy-MM-dd_HH-mm", Locale.getDefault()).format(Date())
|
|
||||||
return "tachiyomi_$date.proto.gz"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,10 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.full.models
|
package eu.kanade.tachiyomi.data.backup.models
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.protobuf.ProtoNumber
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Backup(
|
data class Backup(
|
||||||
@ -12,4 +15,12 @@ data class Backup(
|
|||||||
@ProtoNumber(101) var backupSources: List<BackupSource> = emptyList(),
|
@ProtoNumber(101) var backupSources: List<BackupSource> = emptyList(),
|
||||||
// SY specific values
|
// SY specific values
|
||||||
@ProtoNumber(600) var backupSavedSearches: List<BackupSavedSearch> = emptyList(),
|
@ProtoNumber(600) var backupSavedSearches: List<BackupSavedSearch> = emptyList(),
|
||||||
)
|
) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun getBackupFilename(): String {
|
||||||
|
val date = SimpleDateFormat("yyyy-MM-dd_HH-mm", Locale.getDefault()).format(Date())
|
||||||
|
return "tachiyomi_$date.proto.gz"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.full.models
|
package eu.kanade.tachiyomi.data.backup.models
|
||||||
|
|
||||||
import eu.kanade.domain.category.model.Category
|
import eu.kanade.domain.category.model.Category
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
@ -1,4 +1,4 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.full.models
|
package eu.kanade.tachiyomi.data.backup.models
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.ChapterImpl
|
import eu.kanade.tachiyomi.data.database.models.ChapterImpl
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
@ -1,8 +1,8 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.full.models
|
package eu.kanade.tachiyomi.data.backup.models
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.metadata.BackupSearchMetadata
|
import eu.kanade.tachiyomi.data.backup.models.metadata.BackupSearchMetadata
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.metadata.BackupSearchTag
|
import eu.kanade.tachiyomi.data.backup.models.metadata.BackupSearchTag
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.metadata.BackupSearchTitle
|
import eu.kanade.tachiyomi.data.backup.models.metadata.BackupSearchTitle
|
||||||
import exh.metadata.metadata.base.FlatMetadata
|
import exh.metadata.metadata.base.FlatMetadata
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.protobuf.ProtoNumber
|
import kotlinx.serialization.protobuf.ProtoNumber
|
@ -1,18 +1,19 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.full.models
|
package eu.kanade.tachiyomi.data.backup.models
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.protobuf.ProtoNumber
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class BrokenBackupHistory(
|
|
||||||
@ProtoNumber(0) var url: String,
|
|
||||||
@ProtoNumber(1) var lastRead: Long,
|
|
||||||
@ProtoNumber(2) var readDuration: Long = 0,
|
|
||||||
)
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class BackupHistory(
|
data class BackupHistory(
|
||||||
@ProtoNumber(1) var url: String,
|
@ProtoNumber(1) var url: String,
|
||||||
@ProtoNumber(2) var lastRead: Long,
|
@ProtoNumber(2) var lastRead: Long,
|
||||||
@ProtoNumber(3) var readDuration: Long = 0,
|
@ProtoNumber(3) var readDuration: Long = 0,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Deprecated("Replaced with BackupHistory. This is retained for legacy reasons.")
|
||||||
|
@Serializable
|
||||||
|
data class BrokenBackupHistory(
|
||||||
|
@ProtoNumber(0) var url: String,
|
||||||
|
@ProtoNumber(1) var lastRead: Long,
|
||||||
|
@ProtoNumber(2) var readDuration: Long = 0,
|
||||||
|
)
|
@ -1,4 +1,4 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.full.models
|
package eu.kanade.tachiyomi.data.backup.models
|
||||||
|
|
||||||
import eu.kanade.data.listOfStringsAndAdapter
|
import eu.kanade.data.listOfStringsAndAdapter
|
||||||
import eu.kanade.domain.manga.model.Manga
|
import eu.kanade.domain.manga.model.Manga
|
||||||
@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
|
|||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.protobuf.ProtoNumber
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
@Serializable
|
@Serializable
|
||||||
data class BackupManga(
|
data class BackupManga(
|
||||||
// in 1.x some of these values have different names
|
// in 1.x some of these values have different names
|
@ -1,4 +1,4 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.full.models
|
package eu.kanade.tachiyomi.data.backup.models
|
||||||
|
|
||||||
import exh.merged.sql.models.MergedMangaReference
|
import exh.merged.sql.models.MergedMangaReference
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
@ -1,4 +1,4 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.full.models
|
package eu.kanade.tachiyomi.data.backup.models
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.protobuf.ProtoNumber
|
import kotlinx.serialization.protobuf.ProtoNumber
|
@ -1,4 +1,4 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.full.models
|
package eu.kanade.tachiyomi.data.backup.models
|
||||||
|
|
||||||
import kotlinx.serialization.Serializer
|
import kotlinx.serialization.Serializer
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.full.models
|
package eu.kanade.tachiyomi.data.backup.models
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
@ -1,4 +1,4 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.full.models
|
package eu.kanade.tachiyomi.data.backup.models
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.TrackImpl
|
import eu.kanade.tachiyomi.data.database.models.TrackImpl
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
@ -1,4 +1,4 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.full.models.metadata
|
package eu.kanade.tachiyomi.data.backup.models.metadata
|
||||||
|
|
||||||
import exh.metadata.sql.models.SearchMetadata
|
import exh.metadata.sql.models.SearchMetadata
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
@ -1,4 +1,4 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.full.models.metadata
|
package eu.kanade.tachiyomi.data.backup.models.metadata
|
||||||
|
|
||||||
import exh.metadata.sql.models.SearchTag
|
import exh.metadata.sql.models.SearchTag
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
@ -1,4 +1,4 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.full.models.metadata
|
package eu.kanade.tachiyomi.data.backup.models.metadata
|
||||||
|
|
||||||
import exh.metadata.sql.models.SearchTitle
|
import exh.metadata.sql.models.SearchTitle
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
@ -21,9 +21,9 @@ import com.hippo.unifile.UniFile
|
|||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupConst
|
import eu.kanade.tachiyomi.data.backup.BackupConst
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupCreatorJob
|
import eu.kanade.tachiyomi.data.backup.BackupCreatorJob
|
||||||
|
import eu.kanade.tachiyomi.data.backup.BackupFileValidator
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupRestoreService
|
import eu.kanade.tachiyomi.data.backup.BackupRestoreService
|
||||||
import eu.kanade.tachiyomi.data.backup.full.FullBackupRestoreValidator
|
import eu.kanade.tachiyomi.data.backup.models.Backup
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.BackupFull
|
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.requestPermissionsSafe
|
import eu.kanade.tachiyomi.ui.base.controller.requestPermissionsSafe
|
||||||
import eu.kanade.tachiyomi.util.preference.bindTo
|
import eu.kanade.tachiyomi.util.preference.bindTo
|
||||||
@ -206,11 +206,10 @@ class SettingsBackupController : SettingsController() {
|
|||||||
fun createBackup(flags: Int) {
|
fun createBackup(flags: Int) {
|
||||||
backupFlags = flags
|
backupFlags = flags
|
||||||
try {
|
try {
|
||||||
// Use Android's built-in file creator
|
|
||||||
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
|
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
|
||||||
.addCategory(Intent.CATEGORY_OPENABLE)
|
.addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
.setType("application/*")
|
.setType("application/*")
|
||||||
.putExtra(Intent.EXTRA_TITLE, BackupFull.getDefaultFilename())
|
.putExtra(Intent.EXTRA_TITLE, Backup.getBackupFilename())
|
||||||
|
|
||||||
startActivityForResult(intent, CODE_BACKUP_CREATE)
|
startActivityForResult(intent, CODE_BACKUP_CREATE)
|
||||||
} catch (e: ActivityNotFoundException) {
|
} catch (e: ActivityNotFoundException) {
|
||||||
@ -278,7 +277,7 @@ class SettingsBackupController : SettingsController() {
|
|||||||
val uri: Uri = args.getParcelable(KEY_URI)!!
|
val uri: Uri = args.getParcelable(KEY_URI)!!
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
val results = FullBackupRestoreValidator().validate(activity, uri)
|
val results = BackupFileValidator().validate(activity, uri)
|
||||||
|
|
||||||
var message = activity.getString(R.string.backup_restore_content_full)
|
var message = activity.getString(R.string.backup_restore_content_full)
|
||||||
if (results.missingSources.isNotEmpty()) {
|
if (results.missingSources.isNotEmpty()) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user