diff --git a/app/build.gradle b/app/build.gradle index be30aff7f0..145a37756f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -38,7 +38,7 @@ android { minSdkVersion 21 targetSdkVersion 29 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - versionCode 42 + versionCode 43 versionName "0.9.0" buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\"" diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt index 8af98a9e83..69cee9c5a9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt @@ -149,11 +149,11 @@ class PreferencesHelper(val context: Context) { 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) @@ -176,4 +176,13 @@ class PreferencesHelper(val context: Context) { fun migrateFlags() = rxPrefs.getInteger("migrate_flags", Int.MAX_VALUE) 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) + } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryNavigationView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryNavigationView.kt index aa9f0b666c..64c5aa7c66 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryNavigationView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryNavigationView.kt @@ -5,10 +5,14 @@ import android.util.AttributeSet import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferencesHelper 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.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_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 /** @@ -48,7 +52,7 @@ class LibraryNavigationView @JvmOverloads constructor(context: Context, attrs: A * Returns true if there's at least one filter from [FilterGroup] active. */ 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 { - 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) @@ -82,18 +86,28 @@ class LibraryNavigationView @JvmOverloads constructor(context: Context, attrs: A override val footer = Item.Separator() override fun initModels() { - downloaded.checked = preferences.filterDownloaded().getOrDefault() - unread.checked = preferences.filterUnread().getOrDefault() - completed.checked = preferences.filterCompleted().getOrDefault() + try { + downloaded.state = preferences.filterDownloaded().getOrDefault() + unread.state = preferences.filterUnread().getOrDefault() + completed.state = preferences.filterCompleted().getOrDefault() + } + catch (e: Exception) { + preferences.upgradeFilters() + } } 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 + else -> STATE_IGNORE + } + 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(item.state) + unread -> preferences.filterUnread().set(item.state) + completed -> preferences.filterCompleted().set(item.state) } adapter.notifyItemChanged(item) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt index a2f84f4345..0585da4ba9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt @@ -17,11 +17,14 @@ import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga 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.migration.MigrationFlags import eu.kanade.tachiyomi.util.combineLatest import eu.kanade.tachiyomi.util.isNullOrUnsubscribed import eu.kanade.tachiyomi.util.syncChaptersWithSource +import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_IGNORE import rx.Observable import rx.Subscription import rx.android.schedulers.AndroidSchedulers @@ -121,26 +124,22 @@ class LibraryPresenter( val filterFn: (LibraryItem) -> Boolean = f@ { item -> // Filter when there isn't unread chapters. - if (filterUnread && item.manga.unread == 0) { - return@f false - } + if (filterUnread == STATE_INCLUDE && item.manga.unread == 0) 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 - } // Filter when there are no downloads. - if (filterDownloaded) { - // Local manga are always downloaded - if (item.manga.source == LocalSource.ID) { - return@f true + if (filterDownloaded != STATE_IGNORE) { + val isDownloaded = when { + item.manga.source == LocalSource.ID -> 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 downloadManager.getDownloadCount(item.manga) > 0 + return@f if (filterDownloaded == STATE_INCLUDE) isDownloaded else !isDownloaded } true } diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/ExtendedNavigationView.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/ExtendedNavigationView.kt index 04ab00a585..d55d60962a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/ExtendedNavigationView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/ExtendedNavigationView.kt @@ -77,6 +77,18 @@ open class ExtendedNavigationView @JvmOverloads constructor( 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) + } + } + } } /**