mirror of
https://github.com/mihonapp/mihon.git
synced 2024-11-10 04:37:25 +01:00
Refactor backup and restore to support cross device sync. (#9699)
* refactor: backup and restore to support cross device sync. * chore: Updated string resources * refactor: change function name. * refactor: Use URI SyncHolder.kt not needed anymore.
This commit is contained in:
parent
46e3b9e40d
commit
7b2764e8f7
@ -81,7 +81,7 @@ class BackupManager(
|
||||
backupMangas(databaseManga, flags),
|
||||
backupCategories(flags),
|
||||
emptyList(),
|
||||
backupExtensionInfo(databaseManga),
|
||||
prepExtensionInfoForSync(databaseManga),
|
||||
)
|
||||
|
||||
var file: UniFile? = null
|
||||
@ -135,7 +135,7 @@ class BackupManager(
|
||||
}
|
||||
}
|
||||
|
||||
private fun backupExtensionInfo(mangas: List<Manga>): List<BackupSource> {
|
||||
fun prepExtensionInfoForSync(mangas: List<Manga>): List<BackupSource> {
|
||||
return mangas
|
||||
.asSequence()
|
||||
.map(Manga::source)
|
||||
@ -150,7 +150,7 @@ class BackupManager(
|
||||
*
|
||||
* @return list of [BackupCategory] to be backed up
|
||||
*/
|
||||
private suspend fun backupCategories(options: Int): List<BackupCategory> {
|
||||
suspend fun backupCategories(options: Int): List<BackupCategory> {
|
||||
// Check if user wants category information in backup
|
||||
return if (options and BACKUP_CATEGORY_MASK == BACKUP_CATEGORY) {
|
||||
getCategories.await()
|
||||
@ -161,7 +161,7 @@ class BackupManager(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun backupMangas(mangas: List<Manga>, flags: Int): List<BackupManga> {
|
||||
suspend fun backupMangas(mangas: List<Manga>, flags: Int): List<BackupManga> {
|
||||
return mangas.map {
|
||||
backupManga(it, flags)
|
||||
}
|
||||
@ -514,7 +514,7 @@ class BackupManager(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun updateManga(manga: Manga): Long {
|
||||
suspend fun updateManga(manga: Manga): Long {
|
||||
handler.await(true) {
|
||||
mangasQueries.update(
|
||||
source = manga.source,
|
||||
|
@ -79,9 +79,9 @@ class BackupNotifier(private val context: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
fun showRestoreProgress(content: String = "", progress: Int = 0, maxAmount: Int = 100): NotificationCompat.Builder {
|
||||
fun showRestoreProgress(content: String = "", contentTitle: String = context.getString(R.string.restoring_backup), progress: Int = 0, maxAmount: Int = 100): NotificationCompat.Builder {
|
||||
val builder = with(progressNotificationBuilder) {
|
||||
setContentTitle(context.getString(R.string.restoring_backup))
|
||||
setContentTitle(contentTitle)
|
||||
|
||||
if (!preferences.hideNotificationContent().get()) {
|
||||
setContentText(content)
|
||||
@ -114,7 +114,7 @@ class BackupNotifier(private val context: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
fun showRestoreComplete(time: Long, errorCount: Int, path: String?, file: String?) {
|
||||
fun showRestoreComplete(time: Long, errorCount: Int, path: String?, file: String?, contentTitle: String = context.getString(R.string.restore_completed)) {
|
||||
context.cancelNotification(Notifications.ID_RESTORE_PROGRESS)
|
||||
|
||||
val timeString = context.getString(
|
||||
@ -126,7 +126,7 @@ class BackupNotifier(private val context: Context) {
|
||||
)
|
||||
|
||||
with(completeNotificationBuilder) {
|
||||
setContentTitle(context.getString(R.string.restore_completed))
|
||||
setContentTitle(contentTitle)
|
||||
setContentText(context.resources.getQuantityString(R.plurals.restore_completed_message, errorCount, timeString, errorCount))
|
||||
|
||||
clearActions()
|
||||
|
@ -26,6 +26,7 @@ class BackupRestoreJob(private val context: Context, workerParams: WorkerParamet
|
||||
override suspend fun doWork(): Result {
|
||||
val uri = inputData.getString(LOCATION_URI_KEY)?.toUri()
|
||||
?: return Result.failure()
|
||||
val sync = inputData.getBoolean(SYNC, false)
|
||||
|
||||
try {
|
||||
setForeground(getForegroundInfo())
|
||||
@ -35,7 +36,7 @@ class BackupRestoreJob(private val context: Context, workerParams: WorkerParamet
|
||||
|
||||
return try {
|
||||
val restorer = BackupRestorer(context, notifier)
|
||||
restorer.restoreBackup(uri)
|
||||
restorer.syncFromBackup(uri, sync)
|
||||
Result.success()
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) {
|
||||
@ -63,9 +64,10 @@ class BackupRestoreJob(private val context: Context, workerParams: WorkerParamet
|
||||
return context.workManager.isRunning(TAG)
|
||||
}
|
||||
|
||||
fun start(context: Context, uri: Uri) {
|
||||
fun start(context: Context, uri: Uri, sync: Boolean = false) {
|
||||
val inputData = workDataOf(
|
||||
LOCATION_URI_KEY to uri.toString(),
|
||||
SYNC to sync,
|
||||
)
|
||||
val request = OneTimeWorkRequestBuilder<BackupRestoreJob>()
|
||||
.addTag(TAG)
|
||||
@ -83,3 +85,5 @@ class BackupRestoreJob(private val context: Context, workerParams: WorkerParamet
|
||||
private const val TAG = "BackupRestore"
|
||||
|
||||
private const val LOCATION_URI_KEY = "location_uri" // String
|
||||
|
||||
private const val SYNC = "sync" // Boolean
|
||||
|
@ -36,12 +36,12 @@ class BackupRestorer(
|
||||
|
||||
private val errors = mutableListOf<Pair<Date, String>>()
|
||||
|
||||
suspend fun restoreBackup(uri: Uri): Boolean {
|
||||
suspend fun syncFromBackup(uri: Uri, sync: Boolean): Boolean {
|
||||
val startTime = System.currentTimeMillis()
|
||||
restoreProgress = 0
|
||||
errors.clear()
|
||||
|
||||
if (!performRestore(uri)) {
|
||||
if (!performRestore(uri, sync)) {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -50,7 +50,11 @@ class BackupRestorer(
|
||||
|
||||
val logFile = writeErrorLog()
|
||||
|
||||
notifier.showRestoreComplete(time, errors.size, logFile.parent, logFile.name)
|
||||
if (sync) {
|
||||
notifier.showRestoreComplete(time, errors.size, logFile.parent, logFile.name, contentTitle = context.getString(R.string.library_sync_complete))
|
||||
} else {
|
||||
notifier.showRestoreComplete(time, errors.size, logFile.parent, logFile.name)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@ -73,7 +77,7 @@ class BackupRestorer(
|
||||
return File("")
|
||||
}
|
||||
|
||||
private suspend fun performRestore(uri: Uri): Boolean {
|
||||
private suspend fun performRestore(uri: Uri, sync: Boolean): Boolean {
|
||||
val backup = BackupUtil.decodeBackup(context, uri)
|
||||
|
||||
restoreAmount = backup.backupManga.size + 1 // +1 for categories
|
||||
@ -94,7 +98,7 @@ class BackupRestorer(
|
||||
return@coroutineScope false
|
||||
}
|
||||
|
||||
restoreManga(it, backup.backupCategories)
|
||||
restoreManga(it, backup.backupCategories, sync)
|
||||
}
|
||||
// TODO: optionally trigger online library + tracker update
|
||||
true
|
||||
@ -105,10 +109,10 @@ class BackupRestorer(
|
||||
backupManager.restoreCategories(backupCategories)
|
||||
|
||||
restoreProgress += 1
|
||||
showRestoreProgress(restoreProgress, restoreAmount, context.getString(R.string.categories))
|
||||
showRestoreProgress(restoreProgress, restoreAmount, context.getString(R.string.categories), context.getString(R.string.restoring_backup))
|
||||
}
|
||||
|
||||
private suspend fun restoreManga(backupManga: BackupManga, backupCategories: List<BackupCategory>) {
|
||||
private suspend fun restoreManga(backupManga: BackupManga, backupCategories: List<BackupCategory>, sync: Boolean) {
|
||||
val manga = backupManga.getMangaImpl()
|
||||
val chapters = backupManga.getChaptersImpl()
|
||||
val categories = backupManga.categories.map { it.toInt() }
|
||||
@ -134,7 +138,11 @@ class BackupRestorer(
|
||||
}
|
||||
|
||||
restoreProgress += 1
|
||||
showRestoreProgress(restoreProgress, restoreAmount, manga.title)
|
||||
if (sync) {
|
||||
showRestoreProgress(restoreProgress, restoreAmount, manga.title, context.getString(R.string.syncing_library))
|
||||
} else {
|
||||
showRestoreProgress(restoreProgress, restoreAmount, manga.title, context.getString(R.string.restoring_backup))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -182,7 +190,7 @@ class BackupRestorer(
|
||||
* @param amount total restoreAmount of manga
|
||||
* @param title title of restored manga
|
||||
*/
|
||||
private fun showRestoreProgress(progress: Int, amount: Int, title: String) {
|
||||
notifier.showRestoreProgress(title, progress, amount)
|
||||
private fun showRestoreProgress(progress: Int, amount: Int, title: String, contentTitle: String) {
|
||||
notifier.showRestoreProgress(title, contentTitle, progress, amount)
|
||||
}
|
||||
}
|
||||
|
@ -516,6 +516,10 @@
|
||||
<string name="restoring_backup_canceled">Canceled restore</string>
|
||||
<string name="backup_info">You should keep copies of backups in other places as well.</string>
|
||||
|
||||
<!-- Sync section -->
|
||||
<string name="syncing_library">Syncing library</string>
|
||||
<string name="library_sync_complete">Library sync complete</string>
|
||||
|
||||
<!-- Advanced section -->
|
||||
<string name="label_network">Network</string>
|
||||
<string name="pref_clear_cookies">Clear cookies</string>
|
||||
|
Loading…
Reference in New Issue
Block a user