TriState Filter on library

hXtreme
pull/2497/head
Jay 5 years ago
parent 5874a4d2df
commit 73b1ee5e15

@ -38,7 +38,7 @@ android {
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 29 targetSdkVersion 29
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
versionCode 42 versionCode 43
versionName "0.9.0" versionName "0.9.0"
buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\"" buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\""

@ -149,11 +149,11 @@ class PreferencesHelper(val context: Context) {
fun downloadBadge() = rxPrefs.getBoolean(Keys.downloadBadge, false) fun downloadBadge() = rxPrefs.getBoolean(Keys.downloadBadge, false)
fun filterDownloaded() = rxPrefs.getBoolean(Keys.filterDownloaded, false) fun filterDownloaded() = rxPrefs.getInteger(Keys.filterDownloaded, 0)
fun filterUnread() = rxPrefs.getBoolean(Keys.filterUnread, false) fun filterUnread() = rxPrefs.getInteger(Keys.filterUnread, 0)
fun filterCompleted() = rxPrefs.getBoolean(Keys.filterCompleted, false) fun filterCompleted() = rxPrefs.getInteger(Keys.filterCompleted, 0)
fun librarySortingMode() = rxPrefs.getInteger(Keys.librarySortingMode, 0) fun librarySortingMode() = rxPrefs.getInteger(Keys.librarySortingMode, 0)
@ -176,4 +176,13 @@ class PreferencesHelper(val context: Context) {
fun migrateFlags() = rxPrefs.getInteger("migrate_flags", Int.MAX_VALUE) fun migrateFlags() = rxPrefs.getInteger("migrate_flags", Int.MAX_VALUE)
fun trustedSignatures() = rxPrefs.getStringSet("trusted_signatures", emptySet()) fun trustedSignatures() = rxPrefs.getStringSet("trusted_signatures", emptySet())
fun upgradeFilters() {
val filterDl = rxPrefs.getBoolean(Keys.filterDownloaded, false).getOrDefault()
val filterUn = rxPrefs.getBoolean(Keys.filterUnread, false).getOrDefault()
val filterCm = rxPrefs.getBoolean(Keys.filterCompleted, false).getOrDefault()
filterDownloaded().set(if (filterDl) 1 else 0)
filterUnread().set(if (filterUn) 1 else 0)
filterCompleted().set(if (filterCm) 1 else 0)
}
} }

@ -5,10 +5,14 @@ import android.util.AttributeSet
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.ui.catalogue.filter.TriStateItem
import eu.kanade.tachiyomi.widget.ExtendedNavigationView import eu.kanade.tachiyomi.widget.ExtendedNavigationView
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.MultiSort.Companion.SORT_ASC import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.MultiSort.Companion.SORT_ASC
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.MultiSort.Companion.SORT_DESC import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.MultiSort.Companion.SORT_DESC
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.MultiSort.Companion.SORT_NONE import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.MultiSort.Companion.SORT_NONE
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.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_EXCLUDE
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
/** /**
@ -48,7 +52,7 @@ class LibraryNavigationView @JvmOverloads constructor(context: Context, attrs: A
* Returns true if there's at least one filter from [FilterGroup] active. * Returns true if there's at least one filter from [FilterGroup] active.
*/ */
fun hasActiveFilters(): Boolean { fun hasActiveFilters(): Boolean {
return (groups[0] as FilterGroup).items.any { it.checked } return (groups[0] as FilterGroup).items.any { it.state != STATE_IGNORE }
} }
/** /**
@ -69,11 +73,11 @@ class LibraryNavigationView @JvmOverloads constructor(context: Context, attrs: A
*/ */
inner class FilterGroup : Group { inner class FilterGroup : Group {
private val downloaded = Item.CheckboxGroup(R.string.action_filter_downloaded, this) private val downloaded = Item.TriStateGroup(R.string.action_filter_downloaded, this)
private val unread = Item.CheckboxGroup(R.string.action_filter_unread, this) private val unread = Item.TriStateGroup(R.string.action_filter_unread, this)
private val completed = Item.CheckboxGroup(R.string.completed, this) private val completed = Item.TriStateGroup(R.string.completed, this)
override val items = listOf(downloaded, unread, completed) override val items = listOf(downloaded, unread, completed)
@ -82,18 +86,28 @@ class LibraryNavigationView @JvmOverloads constructor(context: Context, attrs: A
override val footer = Item.Separator() override val footer = Item.Separator()
override fun initModels() { override fun initModels() {
downloaded.checked = preferences.filterDownloaded().getOrDefault() try {
unread.checked = preferences.filterUnread().getOrDefault() downloaded.state = preferences.filterDownloaded().getOrDefault()
completed.checked = preferences.filterCompleted().getOrDefault() unread.state = preferences.filterUnread().getOrDefault()
completed.state = preferences.filterCompleted().getOrDefault()
}
catch (e: Exception) {
preferences.upgradeFilters()
}
} }
override fun onItemClicked(item: Item) { override fun onItemClicked(item: Item) {
item as Item.CheckboxGroup item as Item.TriStateGroup
item.checked = !item.checked val newState = when (item.state) {
STATE_IGNORE -> STATE_INCLUDE
STATE_INCLUDE -> STATE_EXCLUDE
else -> STATE_IGNORE
}
item.state = newState
when (item) { when (item) {
downloaded -> preferences.filterDownloaded().set(item.checked) downloaded -> preferences.filterDownloaded().set(item.state)
unread -> preferences.filterUnread().set(item.checked) unread -> preferences.filterUnread().set(item.state)
completed -> preferences.filterCompleted().set(item.checked) completed -> preferences.filterCompleted().set(item.state)
} }
adapter.notifyItemChanged(item) adapter.notifyItemChanged(item)

@ -17,11 +17,14 @@ import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_EXCLUDE
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_INCLUDE
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.migration.MigrationFlags import eu.kanade.tachiyomi.ui.migration.MigrationFlags
import eu.kanade.tachiyomi.util.combineLatest import eu.kanade.tachiyomi.util.combineLatest
import eu.kanade.tachiyomi.util.isNullOrUnsubscribed import eu.kanade.tachiyomi.util.isNullOrUnsubscribed
import eu.kanade.tachiyomi.util.syncChaptersWithSource import eu.kanade.tachiyomi.util.syncChaptersWithSource
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_IGNORE
import rx.Observable import rx.Observable
import rx.Subscription import rx.Subscription
import rx.android.schedulers.AndroidSchedulers import rx.android.schedulers.AndroidSchedulers
@ -121,26 +124,22 @@ class LibraryPresenter(
val filterFn: (LibraryItem) -> Boolean = f@ { item -> val filterFn: (LibraryItem) -> Boolean = f@ { item ->
// Filter when there isn't unread chapters. // Filter when there isn't unread chapters.
if (filterUnread && item.manga.unread == 0) { if (filterUnread == STATE_INCLUDE && item.manga.unread == 0) return@f false
return@f false if (filterUnread == STATE_EXCLUDE && item.manga.unread > 0) return@f false
}
if (filterCompleted && item.manga.status != SManga.COMPLETED) { if (filterCompleted == STATE_INCLUDE && item.manga.status != SManga.COMPLETED)
return@f false
if (filterCompleted == STATE_EXCLUDE && item.manga.status == SManga.COMPLETED)
return@f false return@f false
}
// Filter when there are no downloads. // Filter when there are no downloads.
if (filterDownloaded) { if (filterDownloaded != STATE_IGNORE) {
// Local manga are always downloaded val isDownloaded = when {
if (item.manga.source == LocalSource.ID) { item.manga.source == LocalSource.ID -> true
return@f true item.downloadCount != -1 -> item.downloadCount > 0
} else -> downloadManager.getDownloadCount(item.manga) > 0
// Don't bother with directory checking if download count has been set.
if (item.downloadCount != -1) {
return@f item.downloadCount > 0
} }
return@f if (filterDownloaded == STATE_INCLUDE) isDownloaded else !isDownloaded
return@f downloadManager.getDownloadCount(item.manga) > 0
} }
true true
} }

@ -77,6 +77,18 @@ open class ExtendedNavigationView @JvmOverloads constructor(
setTint(context.getResourceColor(R.attr.colorAccent)) setTint(context.getResourceColor(R.attr.colorAccent))
} }
} }
/**
* Creates a vector tinted with the accent color.
*
* @param context any context.
* @param resId the vector resource to load and tint
*/
fun tintVector(context: Context, resId: Int, colorId: Int): Drawable {
return VectorDrawableCompat.create(context.resources, resId, context.theme)!!.apply {
setTint(context.getResourceColor(colorId))
}
}
} }
/** /**
@ -107,6 +119,25 @@ open class ExtendedNavigationView @JvmOverloads constructor(
} }
} }
class TriStateGroup(resId: Int, group: Group) : MultiStateGroup(resId, group) {
companion object {
const val STATE_IGNORE = 0
const val STATE_INCLUDE = 1
const val STATE_EXCLUDE = 2
}
override fun getStateDrawable(context: Context): Drawable? {
return when(state) {
STATE_INCLUDE -> tintVector(context, R.drawable.ic_check_box_24dp)
STATE_EXCLUDE -> tintVector(context, R.drawable.ic_check_box_x_24dp,
android.R.attr.textColorSecondary)
else -> tintVector(context, R.drawable.ic_check_box_outline_blank_24dp,
android.R.attr.textColorSecondary)
}
}
}
} }
/** /**

Loading…
Cancel
Save