|
|
|
@ -16,7 +16,6 @@ import eu.kanade.tachiyomi.data.backup.models.LongPreferenceValue
|
|
|
|
|
import eu.kanade.tachiyomi.data.backup.models.StringPreferenceValue
|
|
|
|
|
import eu.kanade.tachiyomi.data.backup.models.StringSetPreferenceValue
|
|
|
|
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
|
|
|
|
import eu.kanade.tachiyomi.source.model.copyFrom
|
|
|
|
|
import eu.kanade.tachiyomi.source.sourcePreferences
|
|
|
|
|
import eu.kanade.tachiyomi.util.BackupUtil
|
|
|
|
|
import eu.kanade.tachiyomi.util.system.createFileInCacheDir
|
|
|
|
@ -27,7 +26,6 @@ import tachiyomi.core.preference.AndroidPreferenceStore
|
|
|
|
|
import tachiyomi.core.preference.PreferenceStore
|
|
|
|
|
import tachiyomi.data.DatabaseHandler
|
|
|
|
|
import tachiyomi.data.Manga_sync
|
|
|
|
|
import tachiyomi.data.Mangas
|
|
|
|
|
import tachiyomi.data.UpdateStrategyColumnAdapter
|
|
|
|
|
import tachiyomi.domain.category.interactor.GetCategories
|
|
|
|
|
import tachiyomi.domain.chapter.interactor.GetChaptersByMangaId
|
|
|
|
@ -35,6 +33,8 @@ import tachiyomi.domain.chapter.model.Chapter
|
|
|
|
|
import tachiyomi.domain.history.model.HistoryUpdate
|
|
|
|
|
import tachiyomi.domain.library.service.LibraryPreferences
|
|
|
|
|
import tachiyomi.domain.manga.interactor.FetchInterval
|
|
|
|
|
import tachiyomi.domain.manga.interactor.GetManga
|
|
|
|
|
import tachiyomi.domain.manga.interactor.GetMangaByUrlAndSourceId
|
|
|
|
|
import tachiyomi.domain.manga.model.Manga
|
|
|
|
|
import tachiyomi.domain.track.model.Track
|
|
|
|
|
import tachiyomi.i18n.MR
|
|
|
|
@ -50,23 +50,25 @@ import kotlin.math.max
|
|
|
|
|
class BackupRestorer(
|
|
|
|
|
private val context: Context,
|
|
|
|
|
private val notifier: BackupNotifier,
|
|
|
|
|
|
|
|
|
|
private val handler: DatabaseHandler = Injekt.get(),
|
|
|
|
|
private val getCategories: GetCategories = Injekt.get(),
|
|
|
|
|
private val getManga: GetManga = Injekt.get(),
|
|
|
|
|
private val getMangaByUrlAndSourceId: GetMangaByUrlAndSourceId = Injekt.get(),
|
|
|
|
|
private val getChaptersByMangaId: GetChaptersByMangaId = Injekt.get(),
|
|
|
|
|
private val updateManga: UpdateManga = Injekt.get(),
|
|
|
|
|
private val fetchInterval: FetchInterval = Injekt.get(),
|
|
|
|
|
|
|
|
|
|
private val preferenceStore: PreferenceStore = Injekt.get(),
|
|
|
|
|
private val libraryPreferences: LibraryPreferences = Injekt.get(),
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
|
|
private val handler: DatabaseHandler = Injekt.get()
|
|
|
|
|
private val updateManga: UpdateManga = Injekt.get()
|
|
|
|
|
private val getCategories: GetCategories = Injekt.get()
|
|
|
|
|
private val getChaptersByMangaId: GetChaptersByMangaId = Injekt.get()
|
|
|
|
|
private val fetchInterval: FetchInterval = Injekt.get()
|
|
|
|
|
|
|
|
|
|
private val preferenceStore: PreferenceStore = Injekt.get()
|
|
|
|
|
private val libraryPreferences: LibraryPreferences = Injekt.get()
|
|
|
|
|
|
|
|
|
|
private var now = ZonedDateTime.now()
|
|
|
|
|
private var currentFetchWindow = fetchInterval.getWindow(now)
|
|
|
|
|
|
|
|
|
|
private var restoreAmount = 0
|
|
|
|
|
private var restoreProgress = 0
|
|
|
|
|
|
|
|
|
|
private var now = ZonedDateTime.now()
|
|
|
|
|
private var currentFetchWindow = fetchInterval.getWindow(now)
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Mapping of source ID to source name from backup data
|
|
|
|
|
*/
|
|
|
|
@ -76,27 +78,22 @@ class BackupRestorer(
|
|
|
|
|
|
|
|
|
|
suspend fun syncFromBackup(uri: Uri, sync: Boolean) {
|
|
|
|
|
val startTime = System.currentTimeMillis()
|
|
|
|
|
restoreProgress = 0
|
|
|
|
|
errors.clear()
|
|
|
|
|
|
|
|
|
|
performRestore(uri, sync)
|
|
|
|
|
prepareState()
|
|
|
|
|
restoreFromFile(uri, sync)
|
|
|
|
|
|
|
|
|
|
val endTime = System.currentTimeMillis()
|
|
|
|
|
val time = endTime - startTime
|
|
|
|
|
|
|
|
|
|
val logFile = writeErrorLog()
|
|
|
|
|
|
|
|
|
|
if (sync) {
|
|
|
|
|
notifier.showRestoreComplete(
|
|
|
|
|
time,
|
|
|
|
|
errors.size,
|
|
|
|
|
logFile.parent,
|
|
|
|
|
logFile.name,
|
|
|
|
|
contentTitle = context.stringResource(MR.strings.library_sync_complete),
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
notifier.showRestoreComplete(time, errors.size, logFile.parent, logFile.name)
|
|
|
|
|
}
|
|
|
|
|
notifier.showRestoreComplete(
|
|
|
|
|
time,
|
|
|
|
|
errors.size,
|
|
|
|
|
logFile.parent,
|
|
|
|
|
logFile.name,
|
|
|
|
|
sync,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun writeErrorLog(): File {
|
|
|
|
@ -118,7 +115,12 @@ class BackupRestorer(
|
|
|
|
|
return File("")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private suspend fun performRestore(uri: Uri, sync: Boolean) {
|
|
|
|
|
private fun prepareState() {
|
|
|
|
|
now = ZonedDateTime.now()
|
|
|
|
|
currentFetchWindow = fetchInterval.getWindow(now)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private suspend fun restoreFromFile(uri: Uri, sync: Boolean) {
|
|
|
|
|
val backup = BackupUtil.decodeBackup(context, uri)
|
|
|
|
|
|
|
|
|
|
restoreAmount = backup.backupManga.size + 3 // +3 for categories, app prefs, source prefs
|
|
|
|
@ -126,8 +128,6 @@ class BackupRestorer(
|
|
|
|
|
// Store source mapping for error messages
|
|
|
|
|
val backupMaps = backup.backupBrokenSources.map { BackupSource(it.name, it.sourceId) } + backup.backupSources
|
|
|
|
|
sourceMapping = backupMaps.associate { it.sourceId to it.name }
|
|
|
|
|
now = ZonedDateTime.now()
|
|
|
|
|
currentFetchWindow = fetchInterval.getWindow(now)
|
|
|
|
|
|
|
|
|
|
coroutineScope {
|
|
|
|
|
ensureActive()
|
|
|
|
@ -139,16 +139,27 @@ class BackupRestorer(
|
|
|
|
|
ensureActive()
|
|
|
|
|
restoreSourcePreferences(backup.backupSourcePreferences)
|
|
|
|
|
|
|
|
|
|
// Restore individual manga
|
|
|
|
|
backup.backupManga.forEach {
|
|
|
|
|
ensureActive()
|
|
|
|
|
restoreManga(it, backup.backupCategories, sync)
|
|
|
|
|
}
|
|
|
|
|
backup.backupManga.sortByNew()
|
|
|
|
|
.forEach {
|
|
|
|
|
ensureActive()
|
|
|
|
|
restoreManga(it, backup.backupCategories, sync)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: optionally trigger online library + tracker update
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private suspend fun List<BackupManga>.sortByNew(): List<BackupManga> {
|
|
|
|
|
val urlsBySource = handler.awaitList { mangasQueries.getAllMangaSourceAndUrl() }
|
|
|
|
|
.groupBy({ it.source }, { it.url })
|
|
|
|
|
|
|
|
|
|
return this
|
|
|
|
|
.sortedWith(
|
|
|
|
|
compareBy<BackupManga> { it.url in urlsBySource[it.source].orEmpty() }
|
|
|
|
|
.then(compareByDescending { it.lastModifiedAt }),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private suspend fun restoreCategories(backupCategories: List<BackupCategory>) {
|
|
|
|
|
if (backupCategories.isNotEmpty()) {
|
|
|
|
|
val dbCategories = getCategories.await()
|
|
|
|
@ -170,75 +181,72 @@ class BackupRestorer(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
restoreProgress += 1
|
|
|
|
|
showRestoreProgress(
|
|
|
|
|
notifier.showRestoreProgress(
|
|
|
|
|
context.stringResource(MR.strings.categories),
|
|
|
|
|
restoreProgress,
|
|
|
|
|
restoreAmount,
|
|
|
|
|
context.stringResource(MR.strings.categories),
|
|
|
|
|
context.stringResource(MR.strings.restoring_backup),
|
|
|
|
|
false,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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() }
|
|
|
|
|
val history =
|
|
|
|
|
backupManga.brokenHistory.map { BackupHistory(it.url, it.lastRead, it.readDuration) } + backupManga.history
|
|
|
|
|
val tracks = backupManga.getTrackingImpl()
|
|
|
|
|
|
|
|
|
|
private suspend fun restoreManga(
|
|
|
|
|
backupManga: BackupManga,
|
|
|
|
|
backupCategories: List<BackupCategory>,
|
|
|
|
|
sync: Boolean,
|
|
|
|
|
) {
|
|
|
|
|
try {
|
|
|
|
|
val dbManga = getMangaFromDatabase(manga.url, manga.source)
|
|
|
|
|
val dbManga = findExistingManga(backupManga)
|
|
|
|
|
val manga = backupManga.getMangaImpl()
|
|
|
|
|
val restoredManga = if (dbManga == null) {
|
|
|
|
|
// Manga not in database
|
|
|
|
|
restoreExistingManga(manga, chapters, categories, history, tracks, backupCategories)
|
|
|
|
|
restoreNewManga(manga)
|
|
|
|
|
} else {
|
|
|
|
|
// Manga in database
|
|
|
|
|
// Copy information from manga already in database
|
|
|
|
|
val updatedManga = restoreExistingManga(manga, dbManga)
|
|
|
|
|
// Fetch rest of manga information
|
|
|
|
|
restoreNewManga(updatedManga, chapters, categories, history, tracks, backupCategories)
|
|
|
|
|
restoreExistingManga(manga, dbManga)
|
|
|
|
|
}
|
|
|
|
|
updateManga.awaitUpdateFetchInterval(restoredManga, now, currentFetchWindow)
|
|
|
|
|
|
|
|
|
|
restoreMangaDetails(
|
|
|
|
|
manga = restoredManga,
|
|
|
|
|
chapters = backupManga.getChaptersImpl(),
|
|
|
|
|
categories = backupManga.categories,
|
|
|
|
|
backupCategories = backupCategories,
|
|
|
|
|
history = backupManga.brokenHistory.map { BackupHistory(it.url, it.lastRead, it.readDuration) } +
|
|
|
|
|
backupManga.history,
|
|
|
|
|
tracks = backupManga.getTrackingImpl(),
|
|
|
|
|
)
|
|
|
|
|
} catch (e: Exception) {
|
|
|
|
|
val sourceName = sourceMapping[manga.source] ?: manga.source.toString()
|
|
|
|
|
errors.add(Date() to "${manga.title} [$sourceName]: ${e.message}")
|
|
|
|
|
val sourceName = sourceMapping[backupManga.source] ?: backupManga.source.toString()
|
|
|
|
|
errors.add(Date() to "${backupManga.title} [$sourceName]: ${e.message}")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
restoreProgress += 1
|
|
|
|
|
if (sync) {
|
|
|
|
|
showRestoreProgress(
|
|
|
|
|
restoreProgress,
|
|
|
|
|
restoreAmount,
|
|
|
|
|
manga.title,
|
|
|
|
|
context.stringResource(MR.strings.syncing_library),
|
|
|
|
|
)
|
|
|
|
|
notifier.showRestoreProgress(backupManga.title, restoreProgress, restoreAmount, sync)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private suspend fun findExistingManga(backupManga: BackupManga): Manga? {
|
|
|
|
|
return getMangaByUrlAndSourceId.await(backupManga.url, backupManga.source)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private suspend fun restoreExistingManga(manga: Manga, dbManga: Manga): Manga {
|
|
|
|
|
return if (manga.lastModifiedAt > dbManga.lastModifiedAt) {
|
|
|
|
|
updateManga(dbManga.copyFrom(manga).copy(id = dbManga.id))
|
|
|
|
|
} else {
|
|
|
|
|
showRestoreProgress(
|
|
|
|
|
restoreProgress,
|
|
|
|
|
restoreAmount,
|
|
|
|
|
manga.title,
|
|
|
|
|
context.stringResource(MR.strings.restoring_backup),
|
|
|
|
|
)
|
|
|
|
|
updateManga(manga.copyFrom(dbManga).copy(id = dbManga.id))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns manga
|
|
|
|
|
*
|
|
|
|
|
* @return [Manga], null if not found
|
|
|
|
|
*/
|
|
|
|
|
private suspend fun getMangaFromDatabase(url: String, source: Long): Mangas? {
|
|
|
|
|
return handler.awaitOneOrNull { mangasQueries.getMangaByUrlAndSource(url, source) }
|
|
|
|
|
private fun Manga.copyFrom(newer: Manga): Manga {
|
|
|
|
|
return this.copy(
|
|
|
|
|
favorite = this.favorite || newer.favorite,
|
|
|
|
|
author = newer.author,
|
|
|
|
|
artist = newer.artist,
|
|
|
|
|
description = newer.description,
|
|
|
|
|
genre = newer.genre,
|
|
|
|
|
thumbnailUrl = newer.thumbnailUrl,
|
|
|
|
|
status = newer.status,
|
|
|
|
|
initialized = this.initialized || newer.initialized,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private suspend fun restoreExistingManga(manga: Manga, dbManga: Mangas): Manga {
|
|
|
|
|
var updatedManga = manga.copy(id = dbManga._id)
|
|
|
|
|
updatedManga = updatedManga.copyFrom(dbManga)
|
|
|
|
|
updateManga(updatedManga)
|
|
|
|
|
return updatedManga
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private suspend fun updateManga(manga: Manga): Long {
|
|
|
|
|
private suspend fun updateManga(manga: Manga): Manga {
|
|
|
|
|
handler.await(true) {
|
|
|
|
|
mangasQueries.update(
|
|
|
|
|
source = manga.source,
|
|
|
|
@ -263,28 +271,16 @@ class BackupRestorer(
|
|
|
|
|
updateStrategy = manga.updateStrategy.let(UpdateStrategyColumnAdapter::encode),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
return manga.id
|
|
|
|
|
return manga
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Fetches manga information
|
|
|
|
|
*
|
|
|
|
|
* @param manga manga that needs updating
|
|
|
|
|
* @param chapters chapters of manga that needs updating
|
|
|
|
|
* @param categories categories that need updating
|
|
|
|
|
*/
|
|
|
|
|
private suspend fun restoreExistingManga(
|
|
|
|
|
private suspend fun restoreNewManga(
|
|
|
|
|
manga: Manga,
|
|
|
|
|
chapters: List<Chapter>,
|
|
|
|
|
categories: List<Int>,
|
|
|
|
|
history: List<BackupHistory>,
|
|
|
|
|
tracks: List<Track>,
|
|
|
|
|
backupCategories: List<BackupCategory>,
|
|
|
|
|
): Manga {
|
|
|
|
|
val fetchedManga = restoreNewManga(manga)
|
|
|
|
|
restoreChapters(fetchedManga, chapters)
|
|
|
|
|
restoreExtras(fetchedManga, categories, history, tracks, backupCategories)
|
|
|
|
|
return fetchedManga
|
|
|
|
|
return manga.copy(
|
|
|
|
|
initialized = manga.description != null,
|
|
|
|
|
id = insertManga(manga),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private suspend fun restoreChapters(manga: Manga, chapters: List<Chapter>) {
|
|
|
|
@ -318,13 +314,10 @@ class BackupRestorer(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val (existingChapters, newChapters) = processed.partition { it.id > 0 }
|
|
|
|
|
updateKnownChapters(existingChapters)
|
|
|
|
|
insertChapters(newChapters)
|
|
|
|
|
updateKnownChapters(existingChapters)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Inserts list of chapters
|
|
|
|
|
*/
|
|
|
|
|
private suspend fun insertChapters(chapters: List<Chapter>) {
|
|
|
|
|
handler.await(true) {
|
|
|
|
|
chapters.forEach { chapter ->
|
|
|
|
@ -345,9 +338,6 @@ class BackupRestorer(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Updates a list of chapters with known database ids
|
|
|
|
|
*/
|
|
|
|
|
private suspend fun updateKnownChapters(chapters: List<Chapter>) {
|
|
|
|
|
handler.await(true) {
|
|
|
|
|
chapters.forEach { chapter ->
|
|
|
|
@ -369,19 +359,6 @@ class BackupRestorer(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Fetches manga information
|
|
|
|
|
*
|
|
|
|
|
* @param manga manga that needs updating
|
|
|
|
|
* @return Updated manga info.
|
|
|
|
|
*/
|
|
|
|
|
private suspend fun restoreNewManga(manga: Manga): Manga {
|
|
|
|
|
return manga.copy(
|
|
|
|
|
initialized = manga.description != null,
|
|
|
|
|
id = insertManga(manga),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Inserts manga and returns id
|
|
|
|
|
*
|
|
|
|
@ -414,29 +391,20 @@ class BackupRestorer(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private suspend fun restoreNewManga(
|
|
|
|
|
backupManga: Manga,
|
|
|
|
|
chapters: List<Chapter>,
|
|
|
|
|
categories: List<Int>,
|
|
|
|
|
history: List<BackupHistory>,
|
|
|
|
|
tracks: List<Track>,
|
|
|
|
|
backupCategories: List<BackupCategory>,
|
|
|
|
|
): Manga {
|
|
|
|
|
restoreChapters(backupManga, chapters)
|
|
|
|
|
restoreExtras(backupManga, categories, history, tracks, backupCategories)
|
|
|
|
|
return backupManga
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private suspend fun restoreExtras(
|
|
|
|
|
private suspend fun restoreMangaDetails(
|
|
|
|
|
manga: Manga,
|
|
|
|
|
categories: List<Int>,
|
|
|
|
|
chapters: List<Chapter>,
|
|
|
|
|
categories: List<Long>,
|
|
|
|
|
backupCategories: List<BackupCategory>,
|
|
|
|
|
history: List<BackupHistory>,
|
|
|
|
|
tracks: List<Track>,
|
|
|
|
|
backupCategories: List<BackupCategory>,
|
|
|
|
|
) {
|
|
|
|
|
): Manga {
|
|
|
|
|
restoreChapters(manga, chapters)
|
|
|
|
|
restoreCategories(manga, categories, backupCategories)
|
|
|
|
|
restoreHistory(history)
|
|
|
|
|
restoreTracking(manga, tracks)
|
|
|
|
|
updateManga.awaitUpdateFetchInterval(manga, now, currentFetchWindow)
|
|
|
|
|
return manga
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -445,23 +413,24 @@ class BackupRestorer(
|
|
|
|
|
* @param manga the manga whose categories have to be restored.
|
|
|
|
|
* @param categories the categories to restore.
|
|
|
|
|
*/
|
|
|
|
|
private suspend fun restoreCategories(manga: Manga, categories: List<Int>, backupCategories: List<BackupCategory>) {
|
|
|
|
|
private suspend fun restoreCategories(
|
|
|
|
|
manga: Manga,
|
|
|
|
|
categories: List<Long>,
|
|
|
|
|
backupCategories: List<BackupCategory>,
|
|
|
|
|
) {
|
|
|
|
|
val dbCategories = getCategories.await()
|
|
|
|
|
val mangaCategoriesToUpdate = mutableListOf<Pair<Long, Long>>()
|
|
|
|
|
val dbCategoriesByName = dbCategories.associateBy { it.name }
|
|
|
|
|
|
|
|
|
|
categories.forEach { backupCategoryOrder ->
|
|
|
|
|
backupCategories.firstOrNull {
|
|
|
|
|
it.order == backupCategoryOrder.toLong()
|
|
|
|
|
}?.let { backupCategory ->
|
|
|
|
|
dbCategories.firstOrNull { dbCategory ->
|
|
|
|
|
dbCategory.name == backupCategory.name
|
|
|
|
|
}?.let { dbCategory ->
|
|
|
|
|
mangaCategoriesToUpdate.add(Pair(manga.id, dbCategory.id))
|
|
|
|
|
val backupCategoriesByOrder = backupCategories.associateBy { it.order }
|
|
|
|
|
|
|
|
|
|
val mangaCategoriesToUpdate = categories.mapNotNull { backupCategoryOrder ->
|
|
|
|
|
backupCategoriesByOrder[backupCategoryOrder]?.let { backupCategory ->
|
|
|
|
|
dbCategoriesByName[backupCategory.name]?.let { dbCategory ->
|
|
|
|
|
Pair(manga.id, dbCategory.id)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update database
|
|
|
|
|
if (mangaCategoriesToUpdate.isNotEmpty()) {
|
|
|
|
|
handler.await(true) {
|
|
|
|
|
mangas_categoriesQueries.deleteMangaCategoryByMangaId(manga.id)
|
|
|
|
@ -472,11 +441,6 @@ class BackupRestorer(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Restore history from Json
|
|
|
|
|
*
|
|
|
|
|
* @param history list containing history to be restored
|
|
|
|
|
*/
|
|
|
|
|
private suspend fun restoreHistory(history: List<BackupHistory>) {
|
|
|
|
|
// List containing history to be updated
|
|
|
|
|
val toUpdate = mutableListOf<HistoryUpdate>()
|
|
|
|
@ -496,7 +460,7 @@ class BackupRestorer(
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
// If not in database create
|
|
|
|
|
// If not in database, create
|
|
|
|
|
handler
|
|
|
|
|
.awaitOneOrNull { chaptersQueries.getChapterByUrl(url) }
|
|
|
|
|
?.let {
|
|
|
|
@ -521,12 +485,6 @@ class BackupRestorer(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Restores the sync of a manga.
|
|
|
|
|
*
|
|
|
|
|
* @param manga the manga whose sync have to be restored.
|
|
|
|
|
* @param tracks the track list to restore.
|
|
|
|
|
*/
|
|
|
|
|
private suspend fun restoreTracking(manga: Manga, tracks: List<Track>) {
|
|
|
|
|
// Get tracks from database
|
|
|
|
|
val dbTracks = handler.awaitList { manga_syncQueries.getTracksByMangaId(manga.id) }
|
|
|
|
@ -611,11 +569,11 @@ class BackupRestorer(
|
|
|
|
|
BackupCreateJob.setupTask(context)
|
|
|
|
|
|
|
|
|
|
restoreProgress += 1
|
|
|
|
|
showRestoreProgress(
|
|
|
|
|
notifier.showRestoreProgress(
|
|
|
|
|
context.stringResource(MR.strings.app_settings),
|
|
|
|
|
restoreProgress,
|
|
|
|
|
restoreAmount,
|
|
|
|
|
context.stringResource(MR.strings.app_settings),
|
|
|
|
|
context.stringResource(MR.strings.restoring_backup),
|
|
|
|
|
false,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -626,11 +584,11 @@ class BackupRestorer(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
restoreProgress += 1
|
|
|
|
|
showRestoreProgress(
|
|
|
|
|
notifier.showRestoreProgress(
|
|
|
|
|
context.stringResource(MR.strings.source_settings),
|
|
|
|
|
restoreProgress,
|
|
|
|
|
restoreAmount,
|
|
|
|
|
context.stringResource(MR.strings.source_settings),
|
|
|
|
|
context.stringResource(MR.strings.restoring_backup),
|
|
|
|
|
false,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -674,8 +632,4 @@ class BackupRestorer(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun showRestoreProgress(progress: Int, amount: Int, title: String, contentTitle: String) {
|
|
|
|
|
notifier.showRestoreProgress(title, contentTitle, progress, amount)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|