mirror of
https://github.com/mihonapp/mihon.git
synced 2025-08-26 08:01:31 +02:00
Compare commits
3 Commits
b2c53ad54e
...
c8c494343d
Author | SHA1 | Date | |
---|---|---|---|
|
c8c494343d | ||
|
97d769e414 | ||
|
b992d0a6a5 |
@@ -9,6 +9,7 @@ import eu.kanade.tachiyomi.data.backup.models.backupChapterMapper
|
||||
import eu.kanade.tachiyomi.data.backup.models.backupTrackMapper
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
import tachiyomi.domain.category.interactor.GetCategories
|
||||
import tachiyomi.domain.category.model.Category
|
||||
import tachiyomi.domain.history.interactor.GetHistory
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
@@ -17,25 +18,22 @@ import uy.kohesive.injekt.api.get
|
||||
|
||||
class MangaBackupCreator(
|
||||
private val handler: DatabaseHandler = Injekt.get(),
|
||||
private val getCategories: GetCategories = Injekt.get(),
|
||||
private val getHistory: GetHistory = Injekt.get(),
|
||||
) {
|
||||
suspend fun backupMangas(mangas: List<Manga>, options: BackupOptions): List<BackupManga> {
|
||||
val categoriesMap: Map<Long, List<Category>>? = if (options.categories) {
|
||||
handler.awaitList {
|
||||
categoriesQueries.getCategoriesWithMangaId { mangaId, categoryId, name, order, flags ->
|
||||
Pair(mangaId, Category(categoryId, name, order, flags))
|
||||
}
|
||||
}.groupBy({ x -> x.first }, { x -> x.second })
|
||||
val categoriesMap = if (options.categories) {
|
||||
getCategories.awaitWithMangaId()
|
||||
} else {
|
||||
null
|
||||
emptyMap()
|
||||
}
|
||||
|
||||
val trackingMap = if (options.tracking) {
|
||||
handler.awaitList {
|
||||
manga_syncQueries.getTracks(backupTrackMapper)
|
||||
}.groupBy({ x -> x.first }, { x -> x.second })
|
||||
}.groupBy({ it.first }, { it.second })
|
||||
} else {
|
||||
null
|
||||
emptyMap()
|
||||
}
|
||||
|
||||
return mangas.map {
|
||||
@@ -46,8 +44,8 @@ class MangaBackupCreator(
|
||||
private suspend fun backupManga(
|
||||
manga: Manga,
|
||||
options: BackupOptions,
|
||||
categoriesMap: Map<Long, List<Category>>?,
|
||||
trackingMap: Map<Long, List<BackupTracking>>?
|
||||
categoriesMap: Map<Long, List<Category>>,
|
||||
trackingMap: Map<Long, List<BackupTracking>>
|
||||
): BackupManga {
|
||||
// Entry for this manga
|
||||
val mangaObject = manga.toBackupManga()
|
||||
@@ -70,17 +68,15 @@ class MangaBackupCreator(
|
||||
}
|
||||
|
||||
if (options.categories) {
|
||||
assert(categoriesMap != null)
|
||||
// Backup categories for this manga
|
||||
val categoriesForManga = categoriesMap!![manga.id]
|
||||
val categoriesForManga = categoriesMap[manga.id]
|
||||
if (categoriesForManga?.isNotEmpty() == true) {
|
||||
mangaObject.categories = categoriesForManga.map { it.order }
|
||||
}
|
||||
}
|
||||
|
||||
if (options.tracking) {
|
||||
assert(trackingMap != null)
|
||||
val tracks = trackingMap!![manga.id]
|
||||
val tracks = trackingMap[manga.id]
|
||||
if (tracks?.isNotEmpty() == true) {
|
||||
mangaObject.tracking = tracks
|
||||
}
|
||||
|
@@ -17,7 +17,11 @@ import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.ensureActive
|
||||
import kotlinx.coroutines.launch
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.domain.category.interactor.GetCategories
|
||||
import tachiyomi.domain.category.model.Category
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.File
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
@@ -31,6 +35,8 @@ class BackupRestorer(
|
||||
private val categoriesRestorer: CategoriesRestorer = CategoriesRestorer(),
|
||||
private val preferenceRestorer: PreferenceRestorer = PreferenceRestorer(context),
|
||||
private val mangaRestorer: MangaRestorer = MangaRestorer(),
|
||||
|
||||
private val getCategories: GetCategories = Injekt.get(),
|
||||
) {
|
||||
|
||||
private var restoreAmount = 0
|
||||
@@ -112,12 +118,20 @@ class BackupRestorer(
|
||||
backupMangas: List<BackupManga>,
|
||||
backupCategories: List<BackupCategory>,
|
||||
) = launch {
|
||||
if (backupMangas.isEmpty()) {
|
||||
return@launch
|
||||
}
|
||||
|
||||
// prepare data:
|
||||
val dbCategoriesByName: Map<String, Category> = getCategories.await()
|
||||
.associateBy { it.name }
|
||||
|
||||
mangaRestorer.sortByNew(backupMangas)
|
||||
.forEach {
|
||||
ensureActive()
|
||||
|
||||
try {
|
||||
mangaRestorer.restoreManga(it, backupCategories)
|
||||
mangaRestorer.restoreManga(it, backupCategories, dbCategoriesByName)
|
||||
} catch (e: Exception) {
|
||||
val sourceName = sourceMapping[it.source] ?: it.source.toString()
|
||||
errors.add(Date() to "${it.title} [$sourceName]: ${e.message}")
|
||||
|
@@ -8,7 +8,6 @@ import eu.kanade.tachiyomi.data.backup.models.BackupManga
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupTracking
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
import tachiyomi.data.UpdateStrategyColumnAdapter
|
||||
import tachiyomi.domain.category.interactor.GetCategories
|
||||
import tachiyomi.domain.category.model.Category
|
||||
import tachiyomi.domain.chapter.interactor.GetChaptersByMangaId
|
||||
import tachiyomi.domain.chapter.model.Chapter
|
||||
@@ -26,7 +25,6 @@ import kotlin.math.max
|
||||
|
||||
class MangaRestorer(
|
||||
private val handler: DatabaseHandler = Injekt.get(),
|
||||
private val getCategories: GetCategories = Injekt.get(),
|
||||
private val getMangaByUrlAndSourceId: GetMangaByUrlAndSourceId = Injekt.get(),
|
||||
private val getChaptersByMangaId: GetChaptersByMangaId = Injekt.get(),
|
||||
private val updateManga: UpdateManga = Injekt.get(),
|
||||
@@ -37,7 +35,6 @@ class MangaRestorer(
|
||||
|
||||
private var now = ZonedDateTime.now()
|
||||
private var currentFetchWindow = fetchInterval.getWindow(now)
|
||||
private var dbCategoriesMapByNameCache: Map<String, Category>? = null
|
||||
|
||||
init {
|
||||
now = ZonedDateTime.now()
|
||||
@@ -58,6 +55,7 @@ class MangaRestorer(
|
||||
suspend fun restoreManga(
|
||||
backupManga: BackupManga,
|
||||
backupCategories: List<BackupCategory>,
|
||||
dbCategoriesByName: Map<String, Category>,
|
||||
) {
|
||||
handler.await(inTransaction = true) {
|
||||
val dbManga = findExistingManga(backupManga)
|
||||
@@ -71,8 +69,9 @@ class MangaRestorer(
|
||||
restoreMangaDetails(
|
||||
manga = restoredManga,
|
||||
chapters = backupManga.chapters,
|
||||
categories = backupManga.categories,
|
||||
mangaCategories = backupManga.categories,
|
||||
backupCategories = backupCategories,
|
||||
dbCategoriesByName = dbCategoriesByName,
|
||||
history = backupManga.history + backupManga.brokenHistory.map { it.toBackupHistory() },
|
||||
tracks = backupManga.tracking,
|
||||
excludedScanlators = backupManga.excludedScanlators,
|
||||
@@ -271,13 +270,14 @@ class MangaRestorer(
|
||||
private suspend fun restoreMangaDetails(
|
||||
manga: Manga,
|
||||
chapters: List<BackupChapter>,
|
||||
categories: List<Long>,
|
||||
mangaCategories: List<Long>,
|
||||
backupCategories: List<BackupCategory>,
|
||||
dbCategoriesByName: Map<String, Category>,
|
||||
history: List<BackupHistory>,
|
||||
tracks: List<BackupTracking>,
|
||||
excludedScanlators: List<String>,
|
||||
): Manga {
|
||||
restoreCategories(manga, categories, backupCategories)
|
||||
restoreCategories(manga, mangaCategories, backupCategories, dbCategoriesByName)
|
||||
restoreChapters(manga, chapters)
|
||||
restoreTracking(manga, tracks)
|
||||
restoreHistory(history)
|
||||
@@ -290,22 +290,17 @@ class MangaRestorer(
|
||||
* Restores the categories a manga is in.
|
||||
*
|
||||
* @param manga the manga whose categories have to be restored.
|
||||
* @param categories the categories to restore.
|
||||
* @param mangaCategories the categories to restore.
|
||||
*/
|
||||
private suspend fun restoreCategories(
|
||||
manga: Manga,
|
||||
categories: List<Long>,
|
||||
mangaCategories: List<Long>,
|
||||
backupCategories: List<BackupCategory>,
|
||||
dbCategoriesByName: Map<String, Category>,
|
||||
) {
|
||||
if (this.dbCategoriesMapByNameCache == null) {
|
||||
val dbCategories = getCategories.await()
|
||||
this.dbCategoriesMapByNameCache = dbCategories.associateBy { it.name }
|
||||
}
|
||||
val dbCategoriesByName = this.dbCategoriesMapByNameCache!!
|
||||
|
||||
val backupCategoriesByOrder = backupCategories.associateBy { it.order }
|
||||
|
||||
val mangaCategoriesToUpdate = categories.mapNotNull { backupCategoryOrder ->
|
||||
val mangaCategoriesToUpdate = mangaCategories.mapNotNull { backupCategoryOrder ->
|
||||
backupCategoriesByOrder[backupCategoryOrder]?.let { backupCategory ->
|
||||
dbCategoriesByName[backupCategory.name]?.let { dbCategory ->
|
||||
Pair(manga.id, dbCategory.id)
|
||||
|
@@ -29,6 +29,14 @@ class CategoryRepositoryImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getCategoriesWithMangaId(): Map<Long, List<Category>> {
|
||||
return handler.awaitList {
|
||||
categoriesQueries.getCategoriesWithMangaId { mangaId, categoryId, name, order, flags ->
|
||||
Pair(mangaId, Category(categoryId, name, order, flags))
|
||||
}
|
||||
}.groupBy({ it.first }, { it.second })
|
||||
}
|
||||
|
||||
override fun getCategoriesByMangaIdAsFlow(mangaId: Long): Flow<List<Category>> {
|
||||
return handler.subscribeToList {
|
||||
categoriesQueries.getCategoriesByMangaId(mangaId, ::mapCategory)
|
||||
|
@@ -23,4 +23,8 @@ class GetCategories(
|
||||
suspend fun await(mangaId: Long): List<Category> {
|
||||
return categoryRepository.getCategoriesByMangaId(mangaId)
|
||||
}
|
||||
|
||||
suspend fun awaitWithMangaId(): Map<Long, List<Category>> {
|
||||
return categoryRepository.getCategoriesWithMangaId()
|
||||
}
|
||||
}
|
||||
|
@@ -14,6 +14,8 @@ interface CategoryRepository {
|
||||
|
||||
suspend fun getCategoriesByMangaId(mangaId: Long): List<Category>
|
||||
|
||||
suspend fun getCategoriesWithMangaId(): Map<Long, List<Category>>
|
||||
|
||||
fun getCategoriesByMangaIdAsFlow(mangaId: Long): Flow<List<Category>>
|
||||
|
||||
suspend fun insert(category: Category)
|
||||
|
Reference in New Issue
Block a user