瀏覽代碼

Use tristate checkboxes for chapters list filters

arkon 4 年之前
父節點
當前提交
fb3756420b

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/Migrations.kt

@@ -98,8 +98,8 @@ object Migrations {
                 val prefs = PreferenceManager.getDefaultSharedPreferences(context)
                 fun convertBooleanPrefToTriState(key: String): Int {
                     val oldPrefValue = prefs.getBoolean(key, false)
-                    return if (oldPrefValue) ExtendedNavigationView.Item.TriStateGroup.STATE_INCLUDE
-                    else ExtendedNavigationView.Item.TriStateGroup.STATE_IGNORE
+                    return if (oldPrefValue) ExtendedNavigationView.Item.TriStateGroup.State.INCLUDE.value
+                    else ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value
                 }
                 prefs.edit {
                     putInt(PreferenceKeys.filterDownloaded, convertBooleanPrefToTriState("pref_filter_downloaded_key"))

+ 3 - 3
app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt

@@ -213,11 +213,11 @@ class PreferencesHelper(val context: Context) {
 
     fun categoryTabs() = flowPrefs.getBoolean(Keys.categoryTabs, true)
 
-    fun filterDownloaded() = flowPrefs.getInt(Keys.filterDownloaded, ExtendedNavigationView.Item.TriStateGroup.STATE_IGNORE)
+    fun filterDownloaded() = flowPrefs.getInt(Keys.filterDownloaded, ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value)
 
-    fun filterUnread() = flowPrefs.getInt(Keys.filterUnread, ExtendedNavigationView.Item.TriStateGroup.STATE_IGNORE)
+    fun filterUnread() = flowPrefs.getInt(Keys.filterUnread, ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value)
 
-    fun filterCompleted() = flowPrefs.getInt(Keys.filterCompleted, ExtendedNavigationView.Item.TriStateGroup.STATE_IGNORE)
+    fun filterCompleted() = flowPrefs.getInt(Keys.filterCompleted, ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value)
 
     fun librarySortingMode() = flowPrefs.getInt(Keys.librarySortingMode, 0)
 

+ 7 - 8
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt

@@ -19,8 +19,7 @@ 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 eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State
 import rx.Observable
 import rx.Subscription
 import rx.android.schedulers.AndroidSchedulers
@@ -118,30 +117,30 @@ class LibraryPresenter(
         val filterCompleted = preferences.filterCompleted().get()
 
         val filterFnUnread: (LibraryItem) -> Boolean = unread@{ item ->
-            if (filterUnread == STATE_IGNORE) return@unread true
+            if (filterUnread == State.IGNORE.value) return@unread true
             val isUnread = item.manga.unread != 0
 
-            return@unread if (filterUnread == STATE_INCLUDE) isUnread
+            return@unread if (filterUnread == State.INCLUDE.value) isUnread
             else !isUnread
         }
 
         val filterFnCompleted: (LibraryItem) -> Boolean = completed@{ item ->
-            if (filterCompleted == STATE_IGNORE) return@completed true
+            if (filterCompleted == State.IGNORE.value) return@completed true
             val isCompleted = item.manga.status == SManga.COMPLETED
 
-            return@completed if (filterCompleted == STATE_INCLUDE) isCompleted
+            return@completed if (filterCompleted == State.INCLUDE.value) isCompleted
             else !isCompleted
         }
 
         val filterFnDownloaded: (LibraryItem) -> Boolean = downloaded@{ item ->
-            if (!downloadedOnly && filterDownloaded == STATE_IGNORE) return@downloaded true
+            if (!downloadedOnly && filterDownloaded == State.IGNORE.value) return@downloaded true
             val isDownloaded = when {
                 item.manga.isLocal() -> true
                 item.downloadCount != -1 -> item.downloadCount > 0
                 else -> downloadManager.getDownloadCount(item.manga) > 0
             }
 
-            return@downloaded if (downloadedOnly || filterDownloaded == STATE_INCLUDE) isDownloaded
+            return@downloaded if (downloadedOnly || filterDownloaded == State.INCLUDE.value) isDownloaded
             else !isDownloaded
         }
 

+ 6 - 8
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt

@@ -8,9 +8,7 @@ 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.ExtendedNavigationView.Item.TriStateGroup.State
 import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog
 import uy.kohesive.injekt.injectLazy
 
@@ -62,7 +60,7 @@ class LibrarySettingsSheet(
          * Returns true if there's at least one filter from [FilterGroup] active.
          */
         fun hasActiveFilters(): Boolean {
-            return filterGroup.items.any { it.state != STATE_IGNORE }
+            return filterGroup.items.any { it.state != State.IGNORE.value }
         }
 
         inner class FilterGroup : Group {
@@ -77,7 +75,7 @@ class LibrarySettingsSheet(
 
             override fun initModels() {
                 if (preferences.downloadedOnly().get()) {
-                    downloaded.state = STATE_INCLUDE
+                    downloaded.state = State.INCLUDE.value
                     downloaded.enabled = false
                 } else {
                     downloaded.state = preferences.filterDownloaded().get()
@@ -89,9 +87,9 @@ class LibrarySettingsSheet(
             override fun onItemClicked(item: Item) {
                 item as Item.TriStateGroup
                 val newState = when (item.state) {
-                    STATE_IGNORE -> STATE_INCLUDE
-                    STATE_INCLUDE -> STATE_EXCLUDE
-                    STATE_EXCLUDE -> STATE_IGNORE
+                    State.IGNORE.value -> State.INCLUDE.value
+                    State.INCLUDE.value -> State.EXCLUDE.value
+                    State.EXCLUDE.value -> State.IGNORE.value
                     else -> throw Exception("Unknown State")
                 }
                 item.state = newState

+ 61 - 38
app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt

@@ -27,6 +27,7 @@ import eu.kanade.tachiyomi.util.prepUpdateCover
 import eu.kanade.tachiyomi.util.removeCovers
 import eu.kanade.tachiyomi.util.shouldDownloadNewChapters
 import eu.kanade.tachiyomi.util.updateCoverLastModified
+import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State
 import rx.Observable
 import rx.Subscription
 import rx.android.schedulers.AndroidSchedulers
@@ -368,17 +369,28 @@ class MangaPresenter(
      */
     private fun applyChapterFilters(chapters: List<ChapterItem>): Observable<List<ChapterItem>> {
         var observable = Observable.from(chapters).subscribeOn(Schedulers.io())
-        if (onlyUnread()) {
+
+        val unreadFilter = onlyUnread()
+        if (unreadFilter == State.INCLUDE) {
             observable = observable.filter { !it.read }
-        } else if (onlyRead()) {
+        } else if (unreadFilter == State.EXCLUDE) {
             observable = observable.filter { it.read }
         }
-        if (onlyDownloaded()) {
+
+        val downloadedFilter = onlyDownloaded()
+        if (downloadedFilter == State.INCLUDE) {
             observable = observable.filter { it.isDownloaded || it.manga.isLocal() }
+        } else if (downloadedFilter == State.EXCLUDE) {
+            observable = observable.filter { !it.isDownloaded && !it.manga.isLocal() }
         }
-        if (onlyBookmarked()) {
+
+        val bookmarkedFilter = onlyBookmarked()
+        if (bookmarkedFilter == State.INCLUDE) {
             observable = observable.filter { it.bookmark }
+        } else if (bookmarkedFilter == State.EXCLUDE) {
+            observable = observable.filter { !it.bookmark }
         }
+
         val sortFunction: (Chapter, Chapter) -> Int = when (manga.sorting) {
             Manga.SORTING_SOURCE -> when (sortDescending()) {
                 true -> { c1, c2 -> c1.source_order.compareTo(c2.source_order) }
@@ -394,6 +406,7 @@ class MangaPresenter(
             }
             else -> throw NotImplementedError("Unimplemented sorting method")
         }
+
         return observable.toSortedList(sortFunction)
     }
 
@@ -412,7 +425,7 @@ class MangaPresenter(
         }
 
         // Force UI update if downloaded filter active and download finished.
-        if (onlyDownloaded() && download.status == Download.DOWNLOADED) {
+        if (onlyDownloaded() != State.IGNORE && download.status == Download.DOWNLOADED) {
             refreshChapters()
         }
     }
@@ -477,7 +490,7 @@ class MangaPresenter(
     fun deleteChapters(chapters: List<ChapterItem>) {
         Observable.just(chapters)
             .doOnNext { deleteChaptersInternal(chapters) }
-            .doOnNext { if (onlyDownloaded()) refreshChapters() }
+            .doOnNext { if (onlyDownloaded() != State.IGNORE) refreshChapters() }
             .subscribeOn(Schedulers.io())
             .observeOn(AndroidSchedulers.mainThread())
             .subscribeFirst(
@@ -518,40 +531,42 @@ class MangaPresenter(
 
     /**
      * Sets the read filter and requests an UI update.
-     * @param onlyUnread whether to display only unread chapters or all chapters.
-     */
-    fun setUnreadFilter(onlyUnread: Boolean) {
-        manga.readFilter = if (onlyUnread) Manga.SHOW_UNREAD else Manga.SHOW_ALL
-        db.updateFlags(manga).executeAsBlocking()
-        refreshChapters()
-    }
-
-    /**
-     * Sets the read filter and requests an UI update.
-     * @param onlyRead whether to display only read chapters or all chapters.
+     * @param state whether to display only unread chapters or all chapters.
      */
-    fun setReadFilter(onlyRead: Boolean) {
-        manga.readFilter = if (onlyRead) Manga.SHOW_READ else Manga.SHOW_ALL
+    fun setUnreadFilter(state: State) {
+        manga.readFilter = when (state) {
+            State.IGNORE -> Manga.SHOW_ALL
+            State.INCLUDE -> Manga.SHOW_UNREAD
+            State.EXCLUDE -> Manga.SHOW_READ
+        }
         db.updateFlags(manga).executeAsBlocking()
         refreshChapters()
     }
 
     /**
      * Sets the download filter and requests an UI update.
-     * @param onlyDownloaded whether to display only downloaded chapters or all chapters.
+     * @param state whether to display only downloaded chapters or all chapters.
      */
-    fun setDownloadedFilter(onlyDownloaded: Boolean) {
-        manga.downloadedFilter = if (onlyDownloaded) Manga.SHOW_DOWNLOADED else Manga.SHOW_ALL
+    fun setDownloadedFilter(state: State) {
+        manga.downloadedFilter = when (state) {
+            State.IGNORE -> Manga.SHOW_ALL
+            State.INCLUDE -> Manga.SHOW_DOWNLOADED
+            State.EXCLUDE -> Manga.SHOW_NOT_DOWNLOADED
+        }
         db.updateFlags(manga).executeAsBlocking()
         refreshChapters()
     }
 
     /**
      * Sets the bookmark filter and requests an UI update.
-     * @param onlyBookmarked whether to display only bookmarked chapters or all chapters.
+     * @param state whether to display only bookmarked chapters or all chapters.
      */
-    fun setBookmarkedFilter(onlyBookmarked: Boolean) {
-        manga.bookmarkedFilter = if (onlyBookmarked) Manga.SHOW_BOOKMARKED else Manga.SHOW_ALL
+    fun setBookmarkedFilter(state: State) {
+        manga.bookmarkedFilter = when (state) {
+            State.IGNORE -> Manga.SHOW_ALL
+            State.INCLUDE -> Manga.SHOW_BOOKMARKED
+            State.EXCLUDE -> Manga.SHOW_NOT_BOOKMARKED
+        }
         db.updateFlags(manga).executeAsBlocking()
         refreshChapters()
     }
@@ -585,29 +600,37 @@ class MangaPresenter(
     /**
      * Whether the display only downloaded filter is enabled.
      */
-    fun onlyDownloaded(): Boolean {
-        return forceDownloaded() || manga.downloadedFilter == Manga.SHOW_DOWNLOADED
+    fun onlyDownloaded(): State {
+        if (forceDownloaded()) {
+            return State.INCLUDE
+        }
+        return when (manga.downloadedFilter) {
+            Manga.SHOW_DOWNLOADED -> State.INCLUDE
+            Manga.SHOW_NOT_DOWNLOADED -> State.EXCLUDE
+            else -> State.IGNORE
+        }
     }
 
     /**
      * Whether the display only downloaded filter is enabled.
      */
-    fun onlyBookmarked(): Boolean {
-        return manga.bookmarkedFilter == Manga.SHOW_BOOKMARKED
+    fun onlyBookmarked(): State {
+        return when (manga.bookmarkedFilter) {
+            Manga.SHOW_BOOKMARKED -> State.INCLUDE
+            Manga.SHOW_NOT_BOOKMARKED -> State.EXCLUDE
+            else -> State.IGNORE
+        }
     }
 
     /**
      * Whether the display only unread filter is enabled.
      */
-    fun onlyUnread(): Boolean {
-        return manga.readFilter == Manga.SHOW_UNREAD
-    }
-
-    /**
-     * Whether the display only read filter is enabled.
-     */
-    fun onlyRead(): Boolean {
-        return manga.readFilter == Manga.SHOW_READ
+    fun onlyUnread(): State {
+        return when (manga.readFilter) {
+            Manga.SHOW_UNREAD -> State.INCLUDE
+            Manga.SHOW_READ -> State.EXCLUDE
+            else -> State.IGNORE
+        }
     }
 
     /**

+ 25 - 17
app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersSettingsSheet.kt

@@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.ui.manga.MangaPresenter
 import eu.kanade.tachiyomi.util.view.popupMenu
 import eu.kanade.tachiyomi.widget.ExtendedNavigationView
+import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State
 import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog
 
 class ChaptersSettingsSheet(
@@ -81,36 +82,43 @@ class ChaptersSettingsSheet(
          * 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 != State.IGNORE.value }
         }
 
         inner class FilterGroup : Group {
 
-            private val read = Item.CheckboxGroup(R.string.action_filter_read, this)
-            private val unread = Item.CheckboxGroup(R.string.action_filter_unread, this)
-            private val downloaded = Item.CheckboxGroup(R.string.action_filter_downloaded, this)
-            private val bookmarked = Item.CheckboxGroup(R.string.action_filter_bookmarked, this)
+            private val unread = Item.TriStateGroup(R.string.action_filter_unread, this)
+            private val downloaded = Item.TriStateGroup(R.string.action_filter_downloaded, this)
+            private val bookmarked = Item.TriStateGroup(R.string.action_filter_bookmarked, this)
 
             override val header = null
-            override val items = listOf(read, unread, downloaded, bookmarked)
+            override val items = listOf(unread, downloaded, bookmarked)
             override val footer = null
 
             override fun initModels() {
-                read.checked = presenter.onlyRead()
-                unread.checked = presenter.onlyUnread()
-                downloaded.checked = presenter.onlyDownloaded()
-                downloaded.enabled = !presenter.forceDownloaded()
-                bookmarked.checked = presenter.onlyBookmarked()
+                if (presenter.forceDownloaded()) {
+                    downloaded.state = State.INCLUDE.value
+                    downloaded.enabled = false
+                } else {
+                    downloaded.state = presenter.onlyDownloaded().value
+                }
+                unread.state = presenter.onlyUnread().value
+                bookmarked.state = presenter.onlyBookmarked().value
             }
 
             override fun onItemClicked(item: Item) {
-                item as Item.CheckboxGroup
-                item.checked = !item.checked
+                item as Item.TriStateGroup
+                val newState = when (item.state) {
+                    State.IGNORE.value -> State.INCLUDE
+                    State.INCLUDE.value -> State.EXCLUDE
+                    State.EXCLUDE.value -> State.IGNORE
+                    else -> throw Exception("Unknown State")
+                }
+                item.state = newState.value
                 when (item) {
-                    read -> presenter.setReadFilter(item.checked)
-                    unread -> presenter.setUnreadFilter(item.checked)
-                    downloaded -> presenter.setDownloadedFilter(item.checked)
-                    bookmarked -> presenter.setBookmarkedFilter(item.checked)
+                    downloaded -> presenter.setDownloadedFilter(newState)
+                    unread -> presenter.setUnreadFilter(newState)
+                    bookmarked -> presenter.setBookmarkedFilter(newState)
                 }
 
                 initModels()

+ 7 - 7
app/src/main/java/eu/kanade/tachiyomi/widget/ExtendedNavigationView.kt

@@ -112,17 +112,17 @@ 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
+            enum class State(val value: Int) {
+                IGNORE(0),
+                INCLUDE(1),
+                EXCLUDE(2)
             }
 
             override fun getStateDrawable(context: Context): Drawable? {
                 return when (state) {
-                    STATE_IGNORE -> tintVector(context, R.drawable.ic_check_box_outline_blank_24dp, R.attr.colorControlNormal)
-                    STATE_INCLUDE -> tintVector(context, R.drawable.ic_check_box_24dp)
-                    STATE_EXCLUDE -> tintVector(context, R.drawable.ic_check_box_x_24dp)
+                    State.IGNORE.value -> tintVector(context, R.drawable.ic_check_box_outline_blank_24dp, R.attr.colorControlNormal)
+                    State.INCLUDE.value -> tintVector(context, R.drawable.ic_check_box_24dp)
+                    State.EXCLUDE.value -> tintVector(context, R.drawable.ic_check_box_x_24dp)
                     else -> throw Exception("Unknown state")
                 }
             }

+ 0 - 1
app/src/main/res/values/strings.xml

@@ -35,7 +35,6 @@
     <string name="action_filter_downloaded">Downloaded</string>
     <string name="action_filter_bookmarked">Bookmarked</string>
     <string name="action_filter_unread">Unread</string>
-    <string name="action_filter_read">Read</string>
     <string name="action_filter_empty">Remove filter</string>
     <string name="action_sort_alpha">Alphabetically</string>
     <string name="action_sort_total">Total chapters</string>