mirror of
https://github.com/mihonapp/mihon.git
synced 2024-11-15 23:12:48 +01:00
refactor: use Uri instead of syncHolder
This commit is contained in:
parent
4db4dd277c
commit
c81400c807
@ -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
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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)
|
|
||||||
|
// 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())
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user