From ea06631670992aef9bc911a7fcd526fb234b4fb3 Mon Sep 17 00:00:00 2001 From: Cuong-Tran Date: Fri, 15 Aug 2025 16:36:30 +0700 Subject: [PATCH] feat(library): Rework categories filter --- .../java/eu/kanade/domain/DomainModule.kt | 2 - .../ui/library/LibraryScreenModel.kt | 77 ++++++++++--------- .../data/category/CategoryRepositoryImpl.kt | 13 ---- .../tachiyomi/data/mangas_categories.sq | 9 --- .../GetCategoriesPerLibraryManga.kt | 13 ---- .../category/repository/CategoryRepository.kt | 4 - 6 files changed, 41 insertions(+), 77 deletions(-) delete mode 100644 domain/src/main/java/tachiyomi/domain/category/interactor/GetCategoriesPerLibraryManga.kt diff --git a/app/src/main/java/eu/kanade/domain/DomainModule.kt b/app/src/main/java/eu/kanade/domain/DomainModule.kt index 7bbba69ff..9ed2be9b8 100644 --- a/app/src/main/java/eu/kanade/domain/DomainModule.kt +++ b/app/src/main/java/eu/kanade/domain/DomainModule.kt @@ -48,7 +48,6 @@ import tachiyomi.data.updates.UpdatesRepositoryImpl import tachiyomi.domain.category.interactor.CreateCategoryWithName import tachiyomi.domain.category.interactor.DeleteCategory import tachiyomi.domain.category.interactor.GetCategories -import tachiyomi.domain.category.interactor.GetCategoriesPerLibraryManga import tachiyomi.domain.category.interactor.HideCategory import tachiyomi.domain.category.interactor.RenameCategory import tachiyomi.domain.category.interactor.ReorderCategory @@ -117,7 +116,6 @@ class DomainModule : InjektModule { addFactory { DeleteCategory(get(), get(), get()) } // KMK --> addFactory { HideCategory(get()) } - addFactory { GetCategoriesPerLibraryManga(get()) } // KMK <-- addSingletonFactory { MangaRepositoryImpl(get()) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt index 6785703d7..44fe1979f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt @@ -92,7 +92,6 @@ import tachiyomi.core.common.util.lang.launchNonCancellable import tachiyomi.core.common.util.lang.withIOContext import tachiyomi.domain.UnsortedPreferences import tachiyomi.domain.category.interactor.GetCategories -import tachiyomi.domain.category.interactor.GetCategoriesPerLibraryManga import tachiyomi.domain.category.interactor.SetMangaCategories import tachiyomi.domain.category.model.Category import tachiyomi.domain.chapter.interactor.GetChaptersByMangaId @@ -160,7 +159,6 @@ class LibraryScreenModel( // SY <-- // KMK --> private val smartSearchMerge: SmartSearchMerge = Injekt.get(), - private val getCategoriesPerLibraryManga: GetCategoriesPerLibraryManga = Injekt.get(), // KMK <-- ) : StateScreenModel(State()) { @@ -185,17 +183,22 @@ class LibraryScreenModel( ), combine(getTracksPerManga.subscribe(), getTrackingFiltersFlow(), ::Pair), // KMK --> - getCategoriesPerLibraryManga.subscribe(), + combine( + state.map { it.includedCategories }.distinctUntilChanged(), + state.map { it.excludedCategories }.distinctUntilChanged(), + ::Pair, + ), // KMK <-- getLibraryItemPreferencesFlow(), - ) { (searchQuery, categories, favorites), (tracksMap, trackingFilters), categoriesPerManga, itemPreferences -> + ) { (searchQuery, categories, favorites), (tracksMap, trackingFilters), (includedCategories, excludedCategories), itemPreferences -> val filteredFavorites = favorites .applyFilters( tracksMap, trackingFilters, itemPreferences, // KMK --> - categoriesPerManga, + includedCategories, + excludedCategories, // KMK <-- ) .let { @@ -422,7 +425,8 @@ class LibraryScreenModel( trackingFilter: Map, preferences: ItemPreferences, // KMK --> - categoriesPerManga: Map>, + includedCategories: ImmutableSet, + excludedCategories: ImmutableSet, // KMK <-- ): List { val downloadedOnly = preferences.globalFilterDownloaded @@ -433,6 +437,7 @@ class LibraryScreenModel( val filterBookmarked = preferences.filterBookmarked val filterCompleted = preferences.filterCompleted val filterIntervalCustom = preferences.filterIntervalCustom + val filterCategories = preferences.filterCategories val isNotLoggedInAnyTrack = trackingFilter.isEmpty() @@ -497,12 +502,12 @@ class LibraryScreenModel( // KMK --> val filterFnCategories: (LibraryItem) -> Boolean = categories@{ item -> - if (!state.value.filterCategory) return@categories true + if (!filterCategories) return@categories true - val mangaCategories = categoriesPerManga[item.libraryManga.id].orEmpty() + val mangaCategories = item.libraryManga.categories.filterNot { it == 0L }.toSet() - val isExcluded = state.value.excludedCategories.any { it in mangaCategories } - val isIncluded = state.value.includedCategories.isEmpty() || state.value.includedCategories.all { it in mangaCategories } + val isExcluded = excludedCategories.any { it in mangaCategories } + val isIncluded = includedCategories.isEmpty() || includedCategories.all { it in mangaCategories } !isExcluded && isIncluded } @@ -1445,32 +1450,32 @@ class LibraryScreenModel( groupBy { item -> item.libraryManga.manga.status }.mapKeys { - Category( - id = it.key + 1, - name = when (it.key) { - SManga.ONGOING.toLong() -> context.stringResource(MR.strings.ongoing) - SManga.LICENSED.toLong() -> context.stringResource(MR.strings.licensed) - SManga.CANCELLED.toLong() -> context.stringResource(MR.strings.cancelled) - SManga.ON_HIATUS.toLong() -> context.stringResource(MR.strings.on_hiatus) - SManga.PUBLISHING_FINISHED.toLong() -> context.stringResource(MR.strings.publishing_finished) - SManga.COMPLETED.toLong() -> context.stringResource(MR.strings.completed) - else -> context.stringResource(MR.strings.unknown) - }, - order = when (it.key) { - SManga.ONGOING.toLong() -> 1 - SManga.LICENSED.toLong() -> 2 - SManga.CANCELLED.toLong() -> 3 - SManga.ON_HIATUS.toLong() -> 4 - SManga.PUBLISHING_FINISHED.toLong() -> 5 - SManga.COMPLETED.toLong() -> 6 - else -> 7 - }, - flags = 0, - // KMK --> - hidden = false, - // KMK <-- - ) - } + Category( + id = it.key + 1, + name = when (it.key) { + SManga.ONGOING.toLong() -> context.stringResource(MR.strings.ongoing) + SManga.LICENSED.toLong() -> context.stringResource(MR.strings.licensed) + SManga.CANCELLED.toLong() -> context.stringResource(MR.strings.cancelled) + SManga.ON_HIATUS.toLong() -> context.stringResource(MR.strings.on_hiatus) + SManga.PUBLISHING_FINISHED.toLong() -> context.stringResource(MR.strings.publishing_finished) + SManga.COMPLETED.toLong() -> context.stringResource(MR.strings.completed) + else -> context.stringResource(MR.strings.unknown) + }, + order = when (it.key) { + SManga.ONGOING.toLong() -> 1 + SManga.LICENSED.toLong() -> 2 + SManga.CANCELLED.toLong() -> 3 + SManga.ON_HIATUS.toLong() -> 4 + SManga.PUBLISHING_FINISHED.toLong() -> 5 + SManga.COMPLETED.toLong() -> 6 + else -> 7 + }, + flags = 0, + // KMK --> + hidden = false, + // KMK <-- + ) + } } else -> emptyMap() }.toSortedMap(compareBy { it.order }) diff --git a/data/src/main/java/tachiyomi/data/category/CategoryRepositoryImpl.kt b/data/src/main/java/tachiyomi/data/category/CategoryRepositoryImpl.kt index 8a08acb0f..4d3ed4df6 100644 --- a/data/src/main/java/tachiyomi/data/category/CategoryRepositoryImpl.kt +++ b/data/src/main/java/tachiyomi/data/category/CategoryRepositoryImpl.kt @@ -1,7 +1,6 @@ package tachiyomi.data.category import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map import tachiyomi.data.Database import tachiyomi.data.DatabaseHandler import tachiyomi.domain.category.model.Category @@ -36,18 +35,6 @@ class CategoryRepositoryImpl( } } - // KMK --> - override fun getCategoriesPerLibraryMangaAsFlow(): Flow>> { - return handler.subscribeToList { - mangas_categoriesQueries.getCategoriesPerLibraryManga { mangaId, categoryId -> - mangaId to categoryId - } - }.map { list -> - list.groupBy({ it.first }, { it.second }).mapValues { it.value.toSet() } - } - } - // KMK <-- - // SY --> override suspend fun insert(category: Category): Long { return handler.awaitOneExecutable(true) { diff --git a/data/src/main/sqldelight/tachiyomi/data/mangas_categories.sq b/data/src/main/sqldelight/tachiyomi/data/mangas_categories.sq index 848a921fa..6d918c6e5 100644 --- a/data/src/main/sqldelight/tachiyomi/data/mangas_categories.sq +++ b/data/src/main/sqldelight/tachiyomi/data/mangas_categories.sq @@ -22,12 +22,3 @@ VALUES (:mangaId, :categoryId); deleteMangaCategoryByMangaId: DELETE FROM mangas_categories WHERE manga_id = :mangaId; - --- KMK --> -getCategoriesPerLibraryManga: -SELECT MC.manga_id, MC.category_id -FROM mangas_categories MC -JOIN mangas M -ON MC.manga_id = M._id -WHERE M.favorite = 1; --- KMK <-- diff --git a/domain/src/main/java/tachiyomi/domain/category/interactor/GetCategoriesPerLibraryManga.kt b/domain/src/main/java/tachiyomi/domain/category/interactor/GetCategoriesPerLibraryManga.kt deleted file mode 100644 index dcab9defa..000000000 --- a/domain/src/main/java/tachiyomi/domain/category/interactor/GetCategoriesPerLibraryManga.kt +++ /dev/null @@ -1,13 +0,0 @@ -package tachiyomi.domain.category.interactor - -import kotlinx.coroutines.flow.Flow -import tachiyomi.domain.category.repository.CategoryRepository - -class GetCategoriesPerLibraryManga( - private val categoryRepository: CategoryRepository, -) { - - fun subscribe(): Flow>> { - return categoryRepository.getCategoriesPerLibraryMangaAsFlow() - } -} diff --git a/domain/src/main/java/tachiyomi/domain/category/repository/CategoryRepository.kt b/domain/src/main/java/tachiyomi/domain/category/repository/CategoryRepository.kt index d389798c8..8ef20517b 100644 --- a/domain/src/main/java/tachiyomi/domain/category/repository/CategoryRepository.kt +++ b/domain/src/main/java/tachiyomi/domain/category/repository/CategoryRepository.kt @@ -16,10 +16,6 @@ interface CategoryRepository { fun getCategoriesByMangaIdAsFlow(mangaId: Long): Flow> - // KMK --> - fun getCategoriesPerLibraryMangaAsFlow(): Flow>> - // KMK <-- - // SY --> suspend fun insert(category: Category): Long // SY <--