diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt index 8916b9c51..b91fb9ed1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt @@ -585,6 +585,25 @@ class LibraryController( favSyncDialog?.dismiss() favSyncDialog = null } + is FavoritesSyncStatus.BadLibraryState.MangaInMultipleCategories -> { + releaseSyncLocks() + + favSyncDialog?.dismiss() + favSyncDialog = buildDialog() + ?.title("Favorites sync error") + ?.content(status.message + " Sync will not start until the gallery is in only one category.") + ?.cancelable(false) + ?.positiveText("Show gallery") + ?.onPositive { _, _ -> + openManga(status.manga) + presenter.favoritesSync.status.onNext(FavoritesSyncStatus.Idle()) + } + ?.negativeText("Ok") + ?.onNegative { _, _ -> + presenter.favoritesSync.status.onNext(FavoritesSyncStatus.Idle()) + } + ?.show() + } is FavoritesSyncStatus.Error -> { releaseSyncLocks() diff --git a/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt b/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt index 679136e00..960d3a976 100644 --- a/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt +++ b/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt @@ -69,6 +69,24 @@ class FavoritesSyncHelper(val context: Context) { return } + // Validate library state + status.onNext(FavoritesSyncStatus.Processing("Verifying local library")) + val libraryManga = db.getLibraryMangas().executeAsBlocking() + val seenManga = HashSet(libraryManga.size) + libraryManga.forEach { + if(it.source != EXH_SOURCE_ID && it.source != EH_SOURCE_ID) return@forEach + + if(it.id in seenManga) { + val inCategories = db.getCategoriesForManga(it).executeAsBlocking() + status.onNext(FavoritesSyncStatus.BadLibraryState + .MangaInMultipleCategories(it, inCategories)) + logger.w("Manga %s is in multiple categories!", it.id) + return + } else { + seenManga += it.id!! + } + } + //Download remote favorites val favorites = try { status.onNext(FavoritesSyncStatus.Processing("Downloading favorites from remote server")) @@ -387,6 +405,11 @@ class FavoritesSyncHelper(val context: Context) { sealed class FavoritesSyncStatus(val message: String) { class Error(message: String) : FavoritesSyncStatus(message) class Idle : FavoritesSyncStatus("Waiting for sync to start") + sealed class BadLibraryState(message: String) : FavoritesSyncStatus(message) { + class MangaInMultipleCategories(val manga: Manga, + val categories: List): + BadLibraryState("The gallery: ${manga.title} is in more than one category (${categories.joinToString { it.name }})!") + } class Initializing : FavoritesSyncStatus("Initializing sync") class Processing(message: String, isThrottle: Boolean = false) : FavoritesSyncStatus(if(isThrottle) "$message\n\nSync is currently throttling (to avoid being banned from ExHentai) and may take a long time to complete." diff --git a/app/src/main/java/exh/favorites/LocalFavoritesStorage.kt b/app/src/main/java/exh/favorites/LocalFavoritesStorage.kt index d34bfb549..96e526a48 100644 --- a/app/src/main/java/exh/favorites/LocalFavoritesStorage.kt +++ b/app/src/main/java/exh/favorites/LocalFavoritesStorage.kt @@ -115,14 +115,17 @@ class LocalFavoritesStorage { token = EHentaiSearchMetadata.galleryToken(it.second.url) category = it.first - // TODO Throw error here - if(this.category > 9) + if(this.category > MAX_CATEGORIES) return@mapNotNull null } } private fun validateDbManga(manga: Manga) = manga.favorite && (manga.source == EH_SOURCE_ID || manga.source == EXH_SOURCE_ID) + + companion object { + const val MAX_CATEGORIES = 9 + } } data class ChangeSet(val added: List,