16b5317b90
- Fixed an issue where migration progress wasn't updated after a manual source search - Fixed incorrect logic where the category migration flag was ignored due to checking the chapter flag instead
146 lines
6.1 KiB
Kotlin
146 lines
6.1 KiB
Kotlin
package mihon.domain.migration.usecases
|
|
|
|
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
|
import eu.kanade.domain.manga.interactor.UpdateManga
|
|
import eu.kanade.domain.manga.model.hasCustomCover
|
|
import eu.kanade.domain.manga.model.toSManga
|
|
import eu.kanade.domain.source.service.SourcePreferences
|
|
import eu.kanade.tachiyomi.data.cache.CoverCache
|
|
import eu.kanade.tachiyomi.data.download.DownloadManager
|
|
import eu.kanade.tachiyomi.data.track.EnhancedTracker
|
|
import eu.kanade.tachiyomi.data.track.TrackerManager
|
|
import kotlinx.coroutines.CancellationException
|
|
import mihon.domain.migration.models.MigrationFlag
|
|
import tachiyomi.domain.category.interactor.GetCategories
|
|
import tachiyomi.domain.category.interactor.SetMangaCategories
|
|
import tachiyomi.domain.chapter.interactor.GetChaptersByMangaId
|
|
import tachiyomi.domain.chapter.interactor.UpdateChapter
|
|
import tachiyomi.domain.chapter.model.toChapterUpdate
|
|
import tachiyomi.domain.manga.model.Manga
|
|
import tachiyomi.domain.manga.model.MangaUpdate
|
|
import tachiyomi.domain.source.service.SourceManager
|
|
import tachiyomi.domain.track.interactor.GetTracks
|
|
import tachiyomi.domain.track.interactor.InsertTrack
|
|
import java.time.Instant
|
|
|
|
class MigrateMangaUseCase(
|
|
private val sourcePreferences: SourcePreferences,
|
|
private val trackerManager: TrackerManager,
|
|
private val sourceManager: SourceManager,
|
|
private val downloadManager: DownloadManager,
|
|
private val updateManga: UpdateManga,
|
|
private val getChaptersByMangaId: GetChaptersByMangaId,
|
|
private val syncChaptersWithSource: SyncChaptersWithSource,
|
|
private val updateChapter: UpdateChapter,
|
|
private val getCategories: GetCategories,
|
|
private val setMangaCategories: SetMangaCategories,
|
|
private val getTracks: GetTracks,
|
|
private val insertTrack: InsertTrack,
|
|
private val coverCache: CoverCache,
|
|
) {
|
|
private val enhancedServices by lazy { trackerManager.trackers.filterIsInstance<EnhancedTracker>() }
|
|
|
|
suspend operator fun invoke(current: Manga, target: Manga, replace: Boolean) {
|
|
val targetSource = sourceManager.get(target.source) ?: return
|
|
val currentSource = sourceManager.get(current.source)
|
|
val flags = sourcePreferences.migrationFlags().get()
|
|
|
|
try {
|
|
val chapters = targetSource.getChapterList(target.toSManga())
|
|
|
|
try {
|
|
syncChaptersWithSource.await(chapters, target, targetSource)
|
|
} catch (_: Exception) {
|
|
// Worst case, chapters won't be synced
|
|
}
|
|
|
|
// Update chapters read, bookmark and dateFetch
|
|
if (MigrationFlag.CHAPTER in flags) {
|
|
val prevMangaChapters = getChaptersByMangaId.await(current.id)
|
|
val mangaChapters = getChaptersByMangaId.await(target.id)
|
|
|
|
val maxChapterRead = prevMangaChapters
|
|
.filter { it.read }
|
|
.maxOfOrNull { it.chapterNumber }
|
|
|
|
val updatedMangaChapters = mangaChapters.map { mangaChapter ->
|
|
var updatedChapter = mangaChapter
|
|
if (updatedChapter.isRecognizedNumber) {
|
|
val prevChapter = prevMangaChapters
|
|
.find { it.isRecognizedNumber && it.chapterNumber == updatedChapter.chapterNumber }
|
|
|
|
if (prevChapter != null) {
|
|
updatedChapter = updatedChapter.copy(
|
|
dateFetch = prevChapter.dateFetch,
|
|
bookmark = prevChapter.bookmark,
|
|
)
|
|
}
|
|
|
|
if (maxChapterRead != null && updatedChapter.chapterNumber <= maxChapterRead) {
|
|
updatedChapter = updatedChapter.copy(read = true)
|
|
}
|
|
}
|
|
|
|
updatedChapter
|
|
}
|
|
|
|
val chapterUpdates = updatedMangaChapters.map { it.toChapterUpdate() }
|
|
updateChapter.awaitAll(chapterUpdates)
|
|
}
|
|
|
|
// Update categories
|
|
if (MigrationFlag.CATEGORY in flags) {
|
|
val categoryIds = getCategories.await(current.id).map { it.id }
|
|
setMangaCategories.await(target.id, categoryIds)
|
|
}
|
|
|
|
// Update track
|
|
getTracks.await(current.id).mapNotNull { track ->
|
|
val updatedTrack = track.copy(mangaId = target.id)
|
|
|
|
val service = enhancedServices
|
|
.firstOrNull { it.isTrackFrom(updatedTrack, current, currentSource) }
|
|
|
|
if (service != null) {
|
|
service.migrateTrack(updatedTrack, target, targetSource)
|
|
} else {
|
|
updatedTrack
|
|
}
|
|
}
|
|
.takeIf { it.isNotEmpty() }
|
|
?.let { insertTrack.awaitAll(it) }
|
|
|
|
// Delete downloaded
|
|
if (MigrationFlag.REMOVE_DOWNLOAD in flags && currentSource != null) {
|
|
downloadManager.deleteManga(current, currentSource)
|
|
}
|
|
|
|
// Update custom cover (recheck if custom cover exists)
|
|
if (MigrationFlag.CUSTOM_COVER in flags && current.hasCustomCover()) {
|
|
coverCache.setCustomCoverToCache(target, coverCache.getCustomCoverFile(current.id).inputStream())
|
|
}
|
|
|
|
val currentMangaUpdate = MangaUpdate(
|
|
id = current.id,
|
|
favorite = false,
|
|
dateAdded = 0,
|
|
)
|
|
.takeIf { replace }
|
|
val targetMangaUpdate = MangaUpdate(
|
|
id = target.id,
|
|
favorite = true,
|
|
chapterFlags = current.chapterFlags,
|
|
viewerFlags = current.viewerFlags,
|
|
dateAdded = if (replace) current.dateAdded else Instant.now().toEpochMilli(),
|
|
notes = if (MigrationFlag.NOTES in flags) current.notes else null,
|
|
)
|
|
|
|
updateManga.awaitAll(listOfNotNull(currentMangaUpdate, targetMangaUpdate))
|
|
} catch (e: Throwable) {
|
|
if (e is CancellationException) {
|
|
throw e
|
|
}
|
|
}
|
|
}
|
|
}
|