Tri-state library filters (closes #1814)

Based on https://github.com/inorichi/tachiyomi/pull/2127.

Co-authored-by: hXtreme <hXtreme@users.noreply.github.com>
This commit is contained in:
arkon
2020-09-14 17:52:00 -04:00
parent da5f10a2f1
commit 687f3d48ea
6 changed files with 128 additions and 51 deletions

View File

@@ -10,15 +10,17 @@ import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.MangaCategory
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.util.isLocal
import eu.kanade.tachiyomi.util.lang.combineLatest
import eu.kanade.tachiyomi.util.lang.isNullOrUnsubscribed
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.removeCovers
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_IGNORE
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_INCLUDE
import rx.Observable
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
@@ -110,34 +112,45 @@ class LibraryPresenter(
* @param map the map to filter.
*/
private fun applyFilters(map: LibraryMap): LibraryMap {
val filterDownloaded = preferences.downloadedOnly().get() || preferences.filterDownloaded().get()
val downloadedOnly = preferences.downloadedOnly().get()
val filterDownloaded = preferences.filterDownloaded().get()
val filterUnread = preferences.filterUnread().get()
val filterCompleted = preferences.filterCompleted().get()
val filterFn: (LibraryItem) -> Boolean = f@{ item ->
// Filter when there isn't unread chapters.
if (filterUnread && item.manga.unread == 0) {
return@f false
val filterFnUnread: (LibraryItem) -> Boolean = unread@{ item ->
if (filterUnread == STATE_IGNORE) return@unread true
val isUnread = item.manga.unread != 0
return@unread if (filterUnread == STATE_INCLUDE) isUnread
else !isUnread
}
val filterFnCompleted: (LibraryItem) -> Boolean = completed@{ item ->
if (filterCompleted == STATE_IGNORE) return@completed true
val isCompleted = item.manga.status == SManga.COMPLETED
return@completed if (filterCompleted == STATE_INCLUDE) isCompleted
else !isCompleted
}
val filterFnDownloaded: (LibraryItem) -> Boolean = downloaded@{ item ->
if (filterDownloaded == STATE_IGNORE) return@downloaded true
val isDownloaded = when {
item.manga.source == LocalSource.ID -> true
item.downloadCount != -1 -> item.downloadCount > 0
else -> downloadManager.getDownloadCount(item.manga) > 0
}
if (filterCompleted && item.manga.status != SManga.COMPLETED) {
return@f false
}
return@downloaded if (downloadedOnly || filterDownloaded == STATE_INCLUDE) isDownloaded
else !isDownloaded
}
// Filter when there are no downloads.
if (filterDownloaded) {
// Local manga are always downloaded
if (item.manga.isLocal()) {
return@f true
}
// Don't bother with directory checking if download count has been set.
if (item.downloadCount != -1) {
return@f item.downloadCount > 0
}
return@f downloadManager.getDownloadCount(item.manga) > 0
}
true
val filterFn: (LibraryItem) -> Boolean = filter@{ item ->
return@filter !(
!filterFnUnread(item) ||
!filterFnCompleted(item) ||
!filterFnDownloaded(item)
)
}
return map.mapValues { entry -> entry.value.filter(filterFn) }

View File

@@ -8,6 +8,9 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.widget.ExtendedNavigationView
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_EXCLUDE
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_IGNORE
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_INCLUDE
import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog
import uy.kohesive.injekt.injectLazy
@@ -59,33 +62,43 @@ class LibrarySettingsSheet(
* Returns true if there's at least one filter from [FilterGroup] active.
*/
fun hasActiveFilters(): Boolean {
return filterGroup.items.any { it.checked }
return filterGroup.items.any { it.state != Item.TriStateGroup.STATE_IGNORE }
}
inner class FilterGroup : Group {
private val downloaded = Item.CheckboxGroup(R.string.action_filter_downloaded, this)
private val unread = Item.CheckboxGroup(R.string.action_filter_unread, this)
private val completed = Item.CheckboxGroup(R.string.completed, this)
private val downloaded = Item.TriStateGroup(R.string.action_filter_downloaded, this)
private val unread = Item.TriStateGroup(R.string.action_filter_unread, this)
private val completed = Item.TriStateGroup(R.string.completed, this)
override val header = null
override val items = listOf(downloaded, unread, completed)
override val footer = null
override fun initModels() {
downloaded.checked = preferences.downloadedOnly().get() || preferences.filterDownloaded().get()
downloaded.enabled = !preferences.downloadedOnly().get()
unread.checked = preferences.filterUnread().get()
completed.checked = preferences.filterCompleted().get()
if (preferences.downloadedOnly().get()) {
downloaded.state = STATE_INCLUDE
downloaded.enabled = false
} else {
downloaded.state = preferences.filterDownloaded().get()
}
unread.state = preferences.filterUnread().get()
completed.state = preferences.filterCompleted().get()
}
override fun onItemClicked(item: Item) {
item as Item.CheckboxGroup
item.checked = !item.checked
item as Item.TriStateGroup
val newState = when (item.state) {
STATE_IGNORE -> STATE_INCLUDE
STATE_INCLUDE -> STATE_EXCLUDE
STATE_EXCLUDE -> STATE_IGNORE
else -> throw Exception("Unknown State")
}
item.state = newState
when (item) {
downloaded -> preferences.filterDownloaded().set(item.checked)
unread -> preferences.filterUnread().set(item.checked)
completed -> preferences.filterCompleted().set(item.checked)
downloaded -> preferences.filterDownloaded().set(newState)
unread -> preferences.filterUnread().set(newState)
completed -> preferences.filterCompleted().set(newState)
}
adapter.notifyItemChanged(item)