refactor: use Uri instead of syncHolder

This commit is contained in:
KaiserBh 2023-07-15 01:29:21 +10:00
parent 4db4dd277c
commit c81400c807
3 changed files with 66 additions and 26 deletions

View File

@ -11,7 +11,6 @@ import androidx.work.WorkerParameters
import androidx.work.workDataOf import androidx.work.workDataOf
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.data.sync.SyncHolder
import eu.kanade.tachiyomi.util.system.cancelNotification import eu.kanade.tachiyomi.util.system.cancelNotification
import eu.kanade.tachiyomi.util.system.isRunning import eu.kanade.tachiyomi.util.system.isRunning
import eu.kanade.tachiyomi.util.system.workManager import eu.kanade.tachiyomi.util.system.workManager
@ -28,7 +27,6 @@ class BackupRestoreJob(private val context: Context, workerParams: WorkerParamet
val uri = inputData.getString(LOCATION_URI_KEY)?.toUri() val uri = inputData.getString(LOCATION_URI_KEY)?.toUri()
?: return Result.failure() ?: return Result.failure()
val sync = inputData.getBoolean(SYNC, false) val sync = inputData.getBoolean(SYNC, false)
val useBackupHolder = inputData.getBoolean(USE_BACKUP_HOLDER, false)
try { try {
setForeground(getForegroundInfo()) setForeground(getForegroundInfo())
@ -38,12 +36,7 @@ class BackupRestoreJob(private val context: Context, workerParams: WorkerParamet
return try { return try {
val restorer = BackupRestorer(context, notifier) val restorer = BackupRestorer(context, notifier)
if (useBackupHolder) { restorer.restoreBackup(uri, sync)
restorer.restoreBackup(uri, sync)
SyncHolder.backup = null
} else {
restorer.restoreBackup(uri, sync)
}
Result.success() Result.success()
} catch (e: Exception) { } catch (e: Exception) {
if (e is CancellationException) { if (e is CancellationException) {
@ -71,11 +64,10 @@ class BackupRestoreJob(private val context: Context, workerParams: WorkerParamet
return context.workManager.isRunning(TAG) return context.workManager.isRunning(TAG)
} }
fun start(context: Context, uri: Uri, sync: Boolean = false, useBackupHolder: Boolean = false) { fun start(context: Context, uri: Uri, sync: Boolean = false) {
val inputData = workDataOf( val inputData = workDataOf(
LOCATION_URI_KEY to uri.toString(), LOCATION_URI_KEY to uri.toString(),
SYNC to sync, SYNC to sync,
USE_BACKUP_HOLDER to useBackupHolder,
) )
val request = OneTimeWorkRequestBuilder<BackupRestoreJob>() val request = OneTimeWorkRequestBuilder<BackupRestoreJob>()
.addTag(TAG) .addTag(TAG)
@ -95,5 +87,3 @@ private const val TAG = "BackupRestore"
private const val LOCATION_URI_KEY = "location_uri" // String private const val LOCATION_URI_KEY = "location_uri" // String
private const val SYNC = "sync" // Boolean private const val SYNC = "sync" // Boolean
private const val USE_BACKUP_HOLDER = "use_backup_holder" // Boolean

View File

@ -7,7 +7,6 @@ import eu.kanade.tachiyomi.data.backup.models.BackupCategory
import eu.kanade.tachiyomi.data.backup.models.BackupHistory import eu.kanade.tachiyomi.data.backup.models.BackupHistory
import eu.kanade.tachiyomi.data.backup.models.BackupManga import eu.kanade.tachiyomi.data.backup.models.BackupManga
import eu.kanade.tachiyomi.data.backup.models.BackupSource import eu.kanade.tachiyomi.data.backup.models.BackupSource
import eu.kanade.tachiyomi.data.sync.SyncHolder
import eu.kanade.tachiyomi.util.BackupUtil import eu.kanade.tachiyomi.util.BackupUtil
import eu.kanade.tachiyomi.util.system.createFileInCacheDir import eu.kanade.tachiyomi.util.system.createFileInCacheDir
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
@ -79,11 +78,7 @@ class BackupRestorer(
} }
private suspend fun performRestore(uri: Uri, sync: Boolean): Boolean { private suspend fun performRestore(uri: Uri, sync: Boolean): Boolean {
val backup = if (sync) { val backup = BackupUtil.decodeBackup(context, uri)
SyncHolder.backup ?: throw IllegalStateException("syncBackup cannot be null when sync is true")
} else {
BackupUtil.decodeBackup(context, uri)
}
restoreAmount = backup.backupManga.size + 1 // +1 for categories restoreAmount = backup.backupManga.size + 1 // +1 for categories

View File

@ -1,9 +1,11 @@
package eu.kanade.tachiyomi.data.sync package eu.kanade.tachiyomi.data.sync
import android.content.Context import android.content.Context
import androidx.core.net.toUri import android.net.Uri
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_ALL import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_ALL
import eu.kanade.tachiyomi.data.backup.BackupManager import eu.kanade.tachiyomi.data.backup.BackupManager
import eu.kanade.tachiyomi.data.backup.BackupNotifier
import eu.kanade.tachiyomi.data.backup.BackupRestoreJob import eu.kanade.tachiyomi.data.backup.BackupRestoreJob
import eu.kanade.tachiyomi.data.backup.models.Backup import eu.kanade.tachiyomi.data.backup.models.Backup
import eu.kanade.tachiyomi.data.backup.models.BackupChapter import eu.kanade.tachiyomi.data.backup.models.BackupChapter
@ -13,6 +15,7 @@ import eu.kanade.tachiyomi.data.sync.models.SyncDevice
import eu.kanade.tachiyomi.data.sync.models.SyncStatus import eu.kanade.tachiyomi.data.sync.models.SyncStatus
import eu.kanade.tachiyomi.data.sync.service.SyncYomiSyncService import eu.kanade.tachiyomi.data.sync.service.SyncYomiSyncService
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.protobuf.ProtoBuf
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.util.system.logcat import tachiyomi.core.util.system.logcat
import tachiyomi.data.Chapters import tachiyomi.data.Chapters
@ -24,6 +27,9 @@ import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.sync.SyncPreferences import tachiyomi.domain.sync.SyncPreferences
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.time.Instant import java.time.Instant
/** /**
@ -42,10 +48,10 @@ class SyncManager(
}, },
private val getFavorites: GetFavorites = Injekt.get(), private val getFavorites: GetFavorites = Injekt.get(),
private val getCategories: GetCategories = Injekt.get(), private val getCategories: GetCategories = Injekt.get(),
) { ) {
private val backupManager: BackupManager = BackupManager(context) private val backupManager: BackupManager = BackupManager(context)
private val notifier: SyncNotifier = SyncNotifier(context) private val notifier: SyncNotifier = SyncNotifier(context)
private val backupNotify: BackupNotifier = BackupNotifier(context)
enum class SyncService(val value: Int) { enum class SyncService(val value: Int) {
NONE(0), NONE(0),
@ -80,7 +86,6 @@ class SyncManager(
// Create the Device object // Create the Device object
val device = SyncDevice( val device = SyncDevice(
id = syncPreferences.deviceID().get(),
name = syncPreferences.deviceName().get(), name = syncPreferences.deviceName().get(),
) )
@ -113,14 +118,41 @@ class SyncManager(
if (remoteBackup != null) { if (remoteBackup != null) {
val (filteredFavorites, nonFavorites) = filterFavoritesAndNonFavorites(remoteBackup) val (filteredFavorites, nonFavorites) = filterFavoritesAndNonFavorites(remoteBackup)
updateNonFavorites(nonFavorites) updateNonFavorites(nonFavorites)
SyncHolder.backup = backup.copy(
val newSyncData = backup.copy(
backupManga = filteredFavorites, backupManga = filteredFavorites,
backupCategories = remoteBackup.backupCategories, backupCategories = remoteBackup.backupCategories,
backupSources = remoteBackup.backupSources, backupSources = remoteBackup.backupSources,
backupBrokenSources = remoteBackup.backupBrokenSources, backupBrokenSources = remoteBackup.backupBrokenSources,
) )
BackupRestoreJob.start(context, "".toUri(), true)
syncPreferences.syncLastSync().set(Instant.now()) // It's local sync no need to restore data. (just update remote data)
if (filteredFavorites.isEmpty()) {
backupNotify.showRestoreComplete(0, 0, "", "", contentTitle = context.getString(R.string.sync_complete))
return
}
val backupUri = writeSyncDataToFile(context, newSyncData)
logcat(LogPriority.DEBUG) { "Got Backup Uri: $backupUri" }
if (backupUri != null) {
BackupRestoreJob.start(context, backupUri, sync = true)
syncPreferences.syncLastSync().set(Instant.now())
} else {
logcat(LogPriority.ERROR) { "Failed to write sync data to file" }
}
}
}
private fun writeSyncDataToFile(context: Context, backup: Backup): Uri? {
val file = File(context.filesDir, "tachiyomi_sync_data.proto.gz")
return try {
FileOutputStream(file).use { output ->
output.write(ProtoBuf.encodeToByteArray(Backup.serializer(), backup))
Uri.fromFile(file)
}
} catch (e: IOException) {
logcat(LogPriority.ERROR) { "Failed to write sync data locally" }
null
} }
} }
@ -143,7 +175,22 @@ class SyncManager(
val localChapters = handler.await { chaptersQueries.getChaptersByMangaId(localManga.id).executeAsList() } val localChapters = handler.await { chaptersQueries.getChaptersByMangaId(localManga.id).executeAsList() }
val localCategories = getCategories.await(localManga.id).map { it.order } val localCategories = getCategories.await(localManga.id).map { it.order }
return localManga.source != remoteManga.source || localManga.url != remoteManga.url || localManga.title != remoteManga.title || localManga.artist != remoteManga.artist || localManga.author != remoteManga.author || localManga.description != remoteManga.description || localManga.genre != remoteManga.genre || localManga.status.toInt() != remoteManga.status || localManga.thumbnailUrl != remoteManga.thumbnailUrl || localManga.dateAdded != remoteManga.dateAdded || localManga.chapterFlags.toInt() != remoteManga.chapterFlags || localManga.favorite != remoteManga.favorite || localManga.viewerFlags.toInt() != remoteManga.viewer_flags || localManga.updateStrategy != remoteManga.updateStrategy || areChaptersDifferent(localChapters, remoteManga.chapters) || localCategories != remoteManga.categories return localManga.source != remoteManga.source ||
localManga.url != remoteManga.url ||
localManga.title != remoteManga.title ||
localManga.artist != remoteManga.artist ||
localManga.author != remoteManga.author ||
localManga.description != remoteManga.description ||
localManga.genre != remoteManga.genre ||
localManga.status.toInt() != remoteManga.status ||
localManga.thumbnailUrl != remoteManga.thumbnailUrl ||
localManga.dateAdded != remoteManga.dateAdded ||
localManga.chapterFlags.toInt() != remoteManga.chapterFlags ||
localManga.favorite != remoteManga.favorite ||
localManga.viewerFlags.toInt() != remoteManga.viewer_flags ||
localManga.updateStrategy != remoteManga.updateStrategy ||
areChaptersDifferent(localChapters, remoteManga.chapters) ||
localCategories != remoteManga.categories
} }
/** /**
@ -161,7 +208,15 @@ class SyncManager(
return remoteChapters.any { remoteChapter -> return remoteChapters.any { remoteChapter ->
localChapterMap[remoteChapter.url]?.let { localChapter -> localChapterMap[remoteChapter.url]?.let { localChapter ->
localChapter.name != remoteChapter.name || localChapter.scanlator != remoteChapter.scanlator || localChapter.read != remoteChapter.read || localChapter.bookmark != remoteChapter.bookmark || localChapter.last_page_read != remoteChapter.lastPageRead || localChapter.date_fetch != remoteChapter.dateFetch || localChapter.date_upload != remoteChapter.dateUpload || localChapter.chapter_number != remoteChapter.chapterNumber || localChapter.source_order != remoteChapter.sourceOrder localChapter.name != remoteChapter.name ||
localChapter.scanlator != remoteChapter.scanlator ||
localChapter.read != remoteChapter.read ||
localChapter.bookmark != remoteChapter.bookmark ||
localChapter.last_page_read != remoteChapter.lastPageRead ||
localChapter.date_fetch != remoteChapter.dateFetch ||
localChapter.date_upload != remoteChapter.dateUpload ||
localChapter.chapter_number != remoteChapter.chapterNumber ||
localChapter.source_order != remoteChapter.sourceOrder
} ?: true } ?: true
} }
} }