Simplify filter logic (#9141)

* Remove unnecessary else branch

* Add TriStateFilter applyFilter

* Simplify filterFnTracking filter logic
This commit is contained in:
Two-Ai 2023-02-25 11:46:40 -05:00 committed by GitHub
parent 86b9262a7e
commit ed6809fa28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 45 additions and 136 deletions

View File

@ -3,12 +3,11 @@ package eu.kanade.domain.chapter.model
import eu.kanade.domain.manga.model.downloadedFilter import eu.kanade.domain.manga.model.downloadedFilter
import eu.kanade.domain.manga.model.isLocal import eu.kanade.domain.manga.model.isLocal
import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.ui.manga.ChapterItem import eu.kanade.tachiyomi.ui.manga.ChapterItem
import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.chapter.service.getChapterSort import tachiyomi.domain.chapter.service.getChapterSort
import tachiyomi.domain.manga.model.Manga 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. * Applies the view filters to the list of chapters obtained from the database.
@ -20,30 +19,12 @@ fun List<Chapter>.applyFilters(manga: Manga, downloadManager: DownloadManager):
val downloadedFilter = manga.downloadedFilter val downloadedFilter = manga.downloadedFilter
val bookmarkedFilter = manga.bookmarkedFilter val bookmarkedFilter = manga.bookmarkedFilter
return filter { chapter -> return filter { chapter -> applyFilter(unreadFilter) { !chapter.read } }
when (unreadFilter) { .filter { chapter -> applyFilter(bookmarkedFilter) { chapter.bookmark } }
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 { chapter -> .filter { chapter ->
applyFilter(downloadedFilter) {
val downloaded = downloadManager.isChapterDownloaded(chapter.name, chapter.scanlator, manga.title, manga.source) val downloaded = downloadManager.isChapterDownloaded(chapter.name, chapter.scanlator, manga.title, manga.source)
val downloadState = when { downloaded || isLocalManga
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
} }
} }
.sortedWith(getChapterSort(manga)) .sortedWith(getChapterSort(manga))
@ -59,26 +40,8 @@ fun List<ChapterItem>.applyFilters(manga: Manga): Sequence<ChapterItem> {
val downloadedFilter = manga.downloadedFilter val downloadedFilter = manga.downloadedFilter
val bookmarkedFilter = manga.bookmarkedFilter val bookmarkedFilter = manga.bookmarkedFilter
return asSequence() return asSequence()
.filter { (chapter) -> .filter { (chapter) -> applyFilter(unreadFilter) { !chapter.read } }
when (unreadFilter) { .filter { (chapter) -> applyFilter(bookmarkedFilter) { chapter.bookmark } }
TriStateFilter.DISABLED -> true .filter { applyFilter(downloadedFilter) { it.isDownloaded || isLocalManga } }
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
}
}
.sortedWith { (chapter1), (chapter2) -> getChapterSort(manga).invoke(chapter1, chapter2) } .sortedWith { (chapter1), (chapter2) -> getChapterSort(manga).invoke(chapter1, chapter2) }
} }

View File

@ -177,6 +177,5 @@ private fun TriStateFilter.toTriStateInt(): Int {
TriStateFilter.DISABLED -> Filter.TriState.STATE_IGNORE TriStateFilter.DISABLED -> Filter.TriState.STATE_IGNORE
TriStateFilter.ENABLED_IS -> Filter.TriState.STATE_INCLUDE TriStateFilter.ENABLED_IS -> Filter.TriState.STATE_INCLUDE
TriStateFilter.ENABLED_NOT -> Filter.TriState.STATE_EXCLUDE TriStateFilter.ENABLED_NOT -> Filter.TriState.STATE_EXCLUDE
else -> throw IllegalStateException("Unknown TriStateFilter state: $this")
} }
} }

View File

@ -59,6 +59,7 @@ import tachiyomi.domain.manga.interactor.GetLibraryManga
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.manga.model.MangaUpdate import tachiyomi.domain.manga.model.MangaUpdate
import tachiyomi.domain.manga.model.TriStateFilter import tachiyomi.domain.manga.model.TriStateFilter
import tachiyomi.domain.manga.model.applyFilter
import tachiyomi.domain.track.interactor.GetTracksPerManga import tachiyomi.domain.track.interactor.GetTracksPerManga
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -171,7 +172,8 @@ class LibraryScreenModel(
): LibraryMap { ): LibraryMap {
val prefs = getLibraryItemPreferencesFlow().first() val prefs = getLibraryItemPreferencesFlow().first()
val downloadedOnly = prefs.globalFilterDownloaded val downloadedOnly = prefs.globalFilterDownloaded
val filterDownloaded = prefs.filterDownloaded val filterDownloaded =
if (downloadedOnly) TriStateFilter.ENABLED_IS else prefs.filterDownloaded
val filterUnread = prefs.filterUnread val filterUnread = prefs.filterUnread
val filterStarted = prefs.filterStarted val filterStarted = prefs.filterStarted
val filterBookmarked = prefs.filterBookmarked 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 includedTracks = loggedInTrackServices.mapNotNull { if (it.value == TriStateFilter.ENABLED_IS) it.key else null }
val trackFiltersIsIgnored = includedTracks.isEmpty() && excludedTracks.isEmpty() val trackFiltersIsIgnored = includedTracks.isEmpty() && excludedTracks.isEmpty()
val filterFnDownloaded: (LibraryItem) -> Boolean = downloaded@{ val filterFnDownloaded: (LibraryItem) -> Boolean = {
if (!downloadedOnly && filterDownloaded == TriStateFilter.DISABLED) return@downloaded true applyFilter(filterDownloaded) {
it.libraryManga.manga.isLocal() ||
val isDownloaded = it.libraryManga.manga.isLocal() ||
it.downloadCount > 0 || it.downloadCount > 0 ||
downloadManager.getDownloadCount(it.libraryManga.manga) > 0 downloadManager.getDownloadCount(it.libraryManga.manga) > 0
return@downloaded if (downloadedOnly || filterDownloaded == TriStateFilter.ENABLED_IS) {
isDownloaded
} else {
!isDownloaded
} }
} }
val filterFnUnread: (LibraryItem) -> Boolean = unread@{ val filterFnUnread: (LibraryItem) -> Boolean = {
if (filterUnread == TriStateFilter.DISABLED) return@unread true applyFilter(filterUnread) { it.libraryManga.unreadCount > 0 }
val isUnread = it.libraryManga.unreadCount > 0
return@unread if (filterUnread == TriStateFilter.ENABLED_IS) {
isUnread
} else {
!isUnread
}
} }
val filterFnStarted: (LibraryItem) -> Boolean = started@{ val filterFnStarted: (LibraryItem) -> Boolean = {
if (filterStarted == TriStateFilter.DISABLED) return@started true applyFilter(filterStarted) { it.libraryManga.hasStarted }
val hasStarted = it.libraryManga.hasStarted
return@started if (filterStarted == TriStateFilter.ENABLED_IS) {
hasStarted
} else {
!hasStarted
}
} }
val filterFnBookmarked: (LibraryItem) -> Boolean = bookmarked@{ val filterFnBookmarked: (LibraryItem) -> Boolean = {
if (filterBookmarked == TriStateFilter.DISABLED) return@bookmarked true applyFilter(filterBookmarked) { it.libraryManga.hasBookmarks }
val hasBookmarks = it.libraryManga.hasBookmarks
return@bookmarked if (filterBookmarked == TriStateFilter.ENABLED_IS) {
hasBookmarks
} else {
!hasBookmarks
}
} }
val filterFnCompleted: (LibraryItem) -> Boolean = completed@{ val filterFnCompleted: (LibraryItem) -> Boolean = {
if (filterCompleted == TriStateFilter.DISABLED) return@completed true applyFilter(filterCompleted) { it.libraryManga.manga.status.toInt() == SManga.COMPLETED }
val isCompleted = it.libraryManga.manga.status.toInt() == SManga.COMPLETED
return@completed if (filterCompleted == TriStateFilter.ENABLED_IS) {
isCompleted
} else {
!isCompleted
}
} }
val filterFnTracking: (LibraryItem) -> Boolean = tracking@{ item -> val filterFnTracking: (LibraryItem) -> Boolean = tracking@{ item ->
@ -245,30 +214,19 @@ class LibraryScreenModel(
val mangaTracks = trackMap[item.libraryManga.id].orEmpty() val mangaTracks = trackMap[item.libraryManga.id].orEmpty()
val exclude = mangaTracks.fastFilter { it in excludedTracks } val isExcluded = excludedTracks.isNotEmpty() && mangaTracks.fastAny { it in excludedTracks }
val include = mangaTracks.fastFilter { it in includedTracks } val isIncluded = includedTracks.isEmpty() || mangaTracks.fastAny { it in includedTracks }
// TODO: Simplify the filter logic return@tracking !isExcluded && isIncluded
if (includedTracks.isNotEmpty() && excludedTracks.isNotEmpty()) {
return@tracking if (exclude.isNotEmpty()) false else include.isNotEmpty()
} }
if (excludedTracks.isNotEmpty()) return@tracking exclude.isEmpty() val filterFn: (LibraryItem) -> Boolean = {
filterFnDownloaded(it) &&
if (includedTracks.isNotEmpty()) return@tracking include.isNotEmpty() filterFnUnread(it) &&
filterFnStarted(it) &&
return@tracking false filterFnBookmarked(it) &&
} filterFnCompleted(it) &&
filterFnTracking(it)
val filterFn: (LibraryItem) -> Boolean = filter@{
return@filter !(
!filterFnDownloaded(it) ||
!filterFnUnread(it) ||
!filterFnStarted(it) ||
!filterFnBookmarked(it) ||
!filterFnCompleted(it) ||
!filterFnTracking(it)
)
} }
return this.mapValues { entry -> entry.value.fastFilter(filterFn) } return this.mapValues { entry -> entry.value.fastFilter(filterFn) }

View File

@ -70,6 +70,7 @@ import tachiyomi.domain.manga.interactor.GetMangaWithChapters
import tachiyomi.domain.manga.interactor.SetMangaChapterFlags import tachiyomi.domain.manga.interactor.SetMangaChapterFlags
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.manga.model.TriStateFilter import tachiyomi.domain.manga.model.TriStateFilter
import tachiyomi.domain.manga.model.applyFilter
import tachiyomi.domain.track.interactor.GetTracks import tachiyomi.domain.track.interactor.GetTracks
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -999,27 +1000,9 @@ sealed class MangaScreenState {
val downloadedFilter = manga.downloadedFilter val downloadedFilter = manga.downloadedFilter
val bookmarkedFilter = manga.bookmarkedFilter val bookmarkedFilter = manga.bookmarkedFilter
return asSequence() return asSequence()
.filter { (chapter) -> .filter { (chapter) -> applyFilter(unreadFilter) { !chapter.read } }
when (unreadFilter) { .filter { (chapter) -> applyFilter(bookmarkedFilter) { chapter.bookmark } }
TriStateFilter.DISABLED -> true .filter { applyFilter(downloadedFilter) { it.isDownloaded || isLocalManga } }
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
}
}
.sortedWith { (chapter1), (chapter2) -> getChapterSort(manga).invoke(chapter1, chapter2) } .sortedWith { (chapter1), (chapter2) -> getChapterSort(manga).invoke(chapter1, chapter2) }
} }
} }

View File

@ -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()
}