From ed6809fa2835831b8d5739d195eff1dbf74df801 Mon Sep 17 00:00:00 2001 From: Two-Ai <81279822+Two-Ai@users.noreply.github.com> Date: Sat, 25 Feb 2023 11:46:40 -0500 Subject: [PATCH] Simplify filter logic (#9141) * Remove unnecessary else branch * Add TriStateFilter applyFilter * Simplify filterFnTracking filter logic --- .../domain/chapter/model/ChapterFilter.kt | 55 ++--------- .../source/browse/SourceFilterDialog.kt | 1 - .../ui/library/LibraryScreenModel.kt | 94 +++++-------------- .../tachiyomi/ui/manga/MangaScreenModel.kt | 25 +---- .../domain/manga/model/TriStateFilter.kt | 6 ++ 5 files changed, 45 insertions(+), 136 deletions(-) diff --git a/app/src/main/java/eu/kanade/domain/chapter/model/ChapterFilter.kt b/app/src/main/java/eu/kanade/domain/chapter/model/ChapterFilter.kt index 4ab9399a5d..b2fc31b635 100644 --- a/app/src/main/java/eu/kanade/domain/chapter/model/ChapterFilter.kt +++ b/app/src/main/java/eu/kanade/domain/chapter/model/ChapterFilter.kt @@ -3,12 +3,11 @@ package eu.kanade.domain.chapter.model import eu.kanade.domain.manga.model.downloadedFilter import eu.kanade.domain.manga.model.isLocal import eu.kanade.tachiyomi.data.download.DownloadManager -import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.ui.manga.ChapterItem import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.service.getChapterSort import tachiyomi.domain.manga.model.Manga -import tachiyomi.domain.manga.model.TriStateFilter +import tachiyomi.domain.manga.model.applyFilter /** * Applies the view filters to the list of chapters obtained from the database. @@ -20,30 +19,12 @@ fun List.applyFilters(manga: Manga, downloadManager: DownloadManager): val downloadedFilter = manga.downloadedFilter val bookmarkedFilter = manga.bookmarkedFilter - return filter { chapter -> - when (unreadFilter) { - TriStateFilter.DISABLED -> true - TriStateFilter.ENABLED_IS -> !chapter.read - TriStateFilter.ENABLED_NOT -> chapter.read - } - } + return filter { chapter -> applyFilter(unreadFilter) { !chapter.read } } + .filter { chapter -> applyFilter(bookmarkedFilter) { chapter.bookmark } } .filter { chapter -> - when (bookmarkedFilter) { - TriStateFilter.DISABLED -> true - TriStateFilter.ENABLED_IS -> chapter.bookmark - TriStateFilter.ENABLED_NOT -> !chapter.bookmark - } - } - .filter { chapter -> - val downloaded = downloadManager.isChapterDownloaded(chapter.name, chapter.scanlator, manga.title, manga.source) - val downloadState = when { - downloaded -> Download.State.DOWNLOADED - else -> Download.State.NOT_DOWNLOADED - } - when (downloadedFilter) { - TriStateFilter.DISABLED -> true - TriStateFilter.ENABLED_IS -> downloadState == Download.State.DOWNLOADED || isLocalManga - TriStateFilter.ENABLED_NOT -> downloadState != Download.State.DOWNLOADED && !isLocalManga + applyFilter(downloadedFilter) { + val downloaded = downloadManager.isChapterDownloaded(chapter.name, chapter.scanlator, manga.title, manga.source) + downloaded || isLocalManga } } .sortedWith(getChapterSort(manga)) @@ -59,26 +40,8 @@ fun List.applyFilters(manga: Manga): Sequence { val downloadedFilter = manga.downloadedFilter val bookmarkedFilter = manga.bookmarkedFilter return asSequence() - .filter { (chapter) -> - when (unreadFilter) { - TriStateFilter.DISABLED -> true - TriStateFilter.ENABLED_IS -> !chapter.read - TriStateFilter.ENABLED_NOT -> chapter.read - } - } - .filter { (chapter) -> - when (bookmarkedFilter) { - TriStateFilter.DISABLED -> true - TriStateFilter.ENABLED_IS -> chapter.bookmark - TriStateFilter.ENABLED_NOT -> !chapter.bookmark - } - } - .filter { - when (downloadedFilter) { - TriStateFilter.DISABLED -> true - TriStateFilter.ENABLED_IS -> it.isDownloaded || isLocalManga - TriStateFilter.ENABLED_NOT -> !it.isDownloaded && !isLocalManga - } - } + .filter { (chapter) -> applyFilter(unreadFilter) { !chapter.read } } + .filter { (chapter) -> applyFilter(bookmarkedFilter) { chapter.bookmark } } + .filter { applyFilter(downloadedFilter) { it.isDownloaded || isLocalManga } } .sortedWith { (chapter1), (chapter2) -> getChapterSort(manga).invoke(chapter1, chapter2) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterDialog.kt index fde13802f5..af68b4d5cf 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterDialog.kt @@ -177,6 +177,5 @@ private fun TriStateFilter.toTriStateInt(): Int { TriStateFilter.DISABLED -> Filter.TriState.STATE_IGNORE TriStateFilter.ENABLED_IS -> Filter.TriState.STATE_INCLUDE TriStateFilter.ENABLED_NOT -> Filter.TriState.STATE_EXCLUDE - else -> throw IllegalStateException("Unknown TriStateFilter state: $this") } } 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 7035c449e6..8955b891fd 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 @@ -59,6 +59,7 @@ import tachiyomi.domain.manga.interactor.GetLibraryManga import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.MangaUpdate import tachiyomi.domain.manga.model.TriStateFilter +import tachiyomi.domain.manga.model.applyFilter import tachiyomi.domain.track.interactor.GetTracksPerManga import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -171,7 +172,8 @@ class LibraryScreenModel( ): LibraryMap { val prefs = getLibraryItemPreferencesFlow().first() val downloadedOnly = prefs.globalFilterDownloaded - val filterDownloaded = prefs.filterDownloaded + val filterDownloaded = + if (downloadedOnly) TriStateFilter.ENABLED_IS else prefs.filterDownloaded val filterUnread = prefs.filterUnread val filterStarted = prefs.filterStarted val filterBookmarked = prefs.filterBookmarked @@ -183,61 +185,28 @@ class LibraryScreenModel( val includedTracks = loggedInTrackServices.mapNotNull { if (it.value == TriStateFilter.ENABLED_IS) it.key else null } val trackFiltersIsIgnored = includedTracks.isEmpty() && excludedTracks.isEmpty() - val filterFnDownloaded: (LibraryItem) -> Boolean = downloaded@{ - if (!downloadedOnly && filterDownloaded == TriStateFilter.DISABLED) return@downloaded true - - val isDownloaded = it.libraryManga.manga.isLocal() || - it.downloadCount > 0 || - downloadManager.getDownloadCount(it.libraryManga.manga) > 0 - return@downloaded if (downloadedOnly || filterDownloaded == TriStateFilter.ENABLED_IS) { - isDownloaded - } else { - !isDownloaded + val filterFnDownloaded: (LibraryItem) -> Boolean = { + applyFilter(filterDownloaded) { + it.libraryManga.manga.isLocal() || + it.downloadCount > 0 || + downloadManager.getDownloadCount(it.libraryManga.manga) > 0 } } - val filterFnUnread: (LibraryItem) -> Boolean = unread@{ - if (filterUnread == TriStateFilter.DISABLED) return@unread true - - val isUnread = it.libraryManga.unreadCount > 0 - return@unread if (filterUnread == TriStateFilter.ENABLED_IS) { - isUnread - } else { - !isUnread - } + val filterFnUnread: (LibraryItem) -> Boolean = { + applyFilter(filterUnread) { it.libraryManga.unreadCount > 0 } } - val filterFnStarted: (LibraryItem) -> Boolean = started@{ - if (filterStarted == TriStateFilter.DISABLED) return@started true - - val hasStarted = it.libraryManga.hasStarted - return@started if (filterStarted == TriStateFilter.ENABLED_IS) { - hasStarted - } else { - !hasStarted - } + val filterFnStarted: (LibraryItem) -> Boolean = { + applyFilter(filterStarted) { it.libraryManga.hasStarted } } - val filterFnBookmarked: (LibraryItem) -> Boolean = bookmarked@{ - if (filterBookmarked == TriStateFilter.DISABLED) return@bookmarked true - - val hasBookmarks = it.libraryManga.hasBookmarks - return@bookmarked if (filterBookmarked == TriStateFilter.ENABLED_IS) { - hasBookmarks - } else { - !hasBookmarks - } + val filterFnBookmarked: (LibraryItem) -> Boolean = { + applyFilter(filterBookmarked) { it.libraryManga.hasBookmarks } } - val filterFnCompleted: (LibraryItem) -> Boolean = completed@{ - if (filterCompleted == TriStateFilter.DISABLED) return@completed true - - val isCompleted = it.libraryManga.manga.status.toInt() == SManga.COMPLETED - return@completed if (filterCompleted == TriStateFilter.ENABLED_IS) { - isCompleted - } else { - !isCompleted - } + val filterFnCompleted: (LibraryItem) -> Boolean = { + applyFilter(filterCompleted) { it.libraryManga.manga.status.toInt() == SManga.COMPLETED } } val filterFnTracking: (LibraryItem) -> Boolean = tracking@{ item -> @@ -245,30 +214,19 @@ class LibraryScreenModel( val mangaTracks = trackMap[item.libraryManga.id].orEmpty() - val exclude = mangaTracks.fastFilter { it in excludedTracks } - val include = mangaTracks.fastFilter { it in includedTracks } + val isExcluded = excludedTracks.isNotEmpty() && mangaTracks.fastAny { it in excludedTracks } + val isIncluded = includedTracks.isEmpty() || mangaTracks.fastAny { it in includedTracks } - // TODO: Simplify the filter logic - if (includedTracks.isNotEmpty() && excludedTracks.isNotEmpty()) { - return@tracking if (exclude.isNotEmpty()) false else include.isNotEmpty() - } - - if (excludedTracks.isNotEmpty()) return@tracking exclude.isEmpty() - - if (includedTracks.isNotEmpty()) return@tracking include.isNotEmpty() - - return@tracking false + return@tracking !isExcluded && isIncluded } - val filterFn: (LibraryItem) -> Boolean = filter@{ - return@filter !( - !filterFnDownloaded(it) || - !filterFnUnread(it) || - !filterFnStarted(it) || - !filterFnBookmarked(it) || - !filterFnCompleted(it) || - !filterFnTracking(it) - ) + val filterFn: (LibraryItem) -> Boolean = { + filterFnDownloaded(it) && + filterFnUnread(it) && + filterFnStarted(it) && + filterFnBookmarked(it) && + filterFnCompleted(it) && + filterFnTracking(it) } return this.mapValues { entry -> entry.value.fastFilter(filterFn) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt index e203a77465..0ae05e24a2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt @@ -70,6 +70,7 @@ import tachiyomi.domain.manga.interactor.GetMangaWithChapters import tachiyomi.domain.manga.interactor.SetMangaChapterFlags import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.TriStateFilter +import tachiyomi.domain.manga.model.applyFilter import tachiyomi.domain.track.interactor.GetTracks import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -999,27 +1000,9 @@ sealed class MangaScreenState { val downloadedFilter = manga.downloadedFilter val bookmarkedFilter = manga.bookmarkedFilter return asSequence() - .filter { (chapter) -> - when (unreadFilter) { - TriStateFilter.DISABLED -> true - TriStateFilter.ENABLED_IS -> !chapter.read - TriStateFilter.ENABLED_NOT -> chapter.read - } - } - .filter { (chapter) -> - when (bookmarkedFilter) { - TriStateFilter.DISABLED -> true - TriStateFilter.ENABLED_IS -> chapter.bookmark - TriStateFilter.ENABLED_NOT -> !chapter.bookmark - } - } - .filter { - when (downloadedFilter) { - TriStateFilter.DISABLED -> true - TriStateFilter.ENABLED_IS -> it.isDownloaded || isLocalManga - TriStateFilter.ENABLED_NOT -> !it.isDownloaded && !isLocalManga - } - } + .filter { (chapter) -> applyFilter(unreadFilter) { !chapter.read } } + .filter { (chapter) -> applyFilter(bookmarkedFilter) { chapter.bookmark } } + .filter { applyFilter(downloadedFilter) { it.isDownloaded || isLocalManga } } .sortedWith { (chapter1), (chapter2) -> getChapterSort(manga).invoke(chapter1, chapter2) } } } diff --git a/domain/src/main/java/tachiyomi/domain/manga/model/TriStateFilter.kt b/domain/src/main/java/tachiyomi/domain/manga/model/TriStateFilter.kt index 86ed7a5c00..8a86316832 100644 --- a/domain/src/main/java/tachiyomi/domain/manga/model/TriStateFilter.kt +++ b/domain/src/main/java/tachiyomi/domain/manga/model/TriStateFilter.kt @@ -14,3 +14,9 @@ enum class TriStateFilter { } } } + +inline fun applyFilter(filter: TriStateFilter, predicate: () -> Boolean): Boolean = when (filter) { + TriStateFilter.DISABLED -> true + TriStateFilter.ENABLED_IS -> predicate() + TriStateFilter.ENABLED_NOT -> !predicate() +}