Browse Source

Extend track filter (#4344)

* Allow to filter for each tracker logged in

* Simplify filter logic

* Use variable names instead of it

and rename variables

* Change how trackFilters and items are setup

* Use variable name instead of it and try cleanup filterFnTracking

* Changes from feedback
Andreas 4 years ago
parent
commit
fea2e0a265

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

@@ -221,7 +221,7 @@ class PreferencesHelper(val context: Context) {
 
     fun filterCompleted() = flowPrefs.getInt(Keys.filterCompleted, ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value)
 
-    fun filterTracking() = flowPrefs.getInt(Keys.filterTracking, ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value)
+    fun filterTracking(name: String) = flowPrefs.getInt("${Keys.filterTracking}_$name", ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value)
 
     fun librarySortingMode() = flowPrefs.getInt(Keys.librarySortingMode, 0)
 

+ 29 - 10
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt

@@ -112,13 +112,16 @@ class LibraryPresenter(
      *
      * @param map the map to filter.
      */
-    private fun applyFilters(map: LibraryMap, trackMap: Map<Long, Boolean>): LibraryMap {
+    private fun applyFilters(map: LibraryMap, trackMap: Map<Long, Map<Int, Boolean>>): LibraryMap {
         val downloadedOnly = preferences.downloadedOnly().get()
         val filterDownloaded = preferences.filterDownloaded().get()
         val filterUnread = preferences.filterUnread().get()
         val filterCompleted = preferences.filterCompleted().get()
-        val tracking = preferences.filterTracking().get()
-        val isNotLogged = !trackManager.hasLoggedServices()
+        val loggedInServices = trackManager.services.filter { trackService -> trackService.isLogged }
+            .associate { trackService ->
+                Pair(trackService.id, preferences.filterTracking(trackService.name).get())
+            }
+        val isNotAnyLoggedIn = !loggedInServices.values.any()
 
         val filterFnUnread: (LibraryItem) -> Boolean = unread@{ item ->
             if (filterUnread == State.IGNORE.value) return@unread true
@@ -149,11 +152,27 @@ class LibraryPresenter(
         }
 
         val filterFnTracking: (LibraryItem) -> Boolean = tracking@{ item ->
-            if (isNotLogged || tracking == State.IGNORE.value) return@tracking true
+            if (isNotAnyLoggedIn) return@tracking true
+
+            val trackedManga = trackMap[item.manga.id ?: -1]
+
+            val containsExclude = loggedInServices.filterValues { it == State.EXCLUDE.value }
+            val containsInclude = loggedInServices.filterValues { it == State.INCLUDE.value }
+
+            if (!containsExclude.any() && !containsInclude.any()) return@tracking true
+
+            val exclude = trackedManga?.filterKeys { containsExclude.containsKey(it) }?.values ?: emptyList()
+            val include = trackedManga?.filterKeys { containsInclude.containsKey(it) }?.values ?: emptyList()
+
+            if (containsInclude.any() && containsExclude.any()) {
+                return@tracking if (exclude.isNotEmpty()) !exclude.any() else include.any()
+            }
+
+            if (containsExclude.any()) return@tracking !exclude.any()
 
-            val isTracking = trackMap[item.manga.id ?: -1] ?: false
+            if (containsInclude.any()) return@tracking include.any()
 
-            return@tracking if (tracking == State.INCLUDE.value) isTracking else !isTracking
+            return@tracking false
         }
 
         val filterFn: (LibraryItem) -> Boolean = filter@{ item ->
@@ -300,7 +319,7 @@ class LibraryPresenter(
      *
      * @return an observable of tracked manga.
      */
-    private fun getFilterObservable(): Observable<Map<Long, Boolean>> {
+    private fun getFilterObservable(): Observable<Map<Long, Map<Int, Boolean>>> {
         return getTracksObservable().combineLatest(filterTriggerRelay.observeOn(Schedulers.io())) { tracks, _ -> tracks }
     }
 
@@ -309,13 +328,13 @@ class LibraryPresenter(
      *
      * @return an observable of tracked manga.
      */
-    private fun getTracksObservable(): Observable<Map<Long, Boolean>> {
+    private fun getTracksObservable(): Observable<Map<Long, Map<Int, Boolean>>> {
         return db.getTracks().asRxObservable().map { tracks ->
             tracks.groupBy { it.manga_id }
                 .mapValues { tracksForMangaId ->
                     // Check if any of the trackers is logged in for the current manga id
-                    tracksForMangaId.value.any {
-                        trackManager.getService(it.sync_id)?.isLogged ?: false
+                    tracksForMangaId.value.associate {
+                        Pair(it.sync_id, trackManager.getService(it.sync_id)?.isLogged ?: false)
                     }
                 }
         }.observeOn(Schedulers.io())

+ 50 - 13
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt

@@ -8,14 +8,22 @@ import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.data.track.TrackManager
+import eu.kanade.tachiyomi.data.track.TrackService
+import eu.kanade.tachiyomi.data.track.anilist.Anilist
+import eu.kanade.tachiyomi.data.track.bangumi.Bangumi
+import eu.kanade.tachiyomi.data.track.kitsu.Kitsu
+import eu.kanade.tachiyomi.data.track.myanimelist.MyAnimeList
+import eu.kanade.tachiyomi.data.track.shikimori.Shikimori
 import eu.kanade.tachiyomi.widget.ExtendedNavigationView
 import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State
 import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog
+import uy.kohesive.injekt.Injekt
+import uy.kohesive.injekt.api.get
 import uy.kohesive.injekt.injectLazy
-import uy.kohesive.injekt.injectValue
 
 class LibrarySettingsSheet(
     router: Router,
+    private val trackManager: TrackManager = Injekt.get(),
     onGroupClickListener: (ExtendedNavigationView.Group) -> Unit
 ) : TabbedBottomSheetDialog(router) {
 
@@ -54,8 +62,6 @@ class LibrarySettingsSheet(
 
         private val filterGroup = FilterGroup()
 
-        private val trackManager: TrackManager by injectValue()
-
         init {
             setGroups(listOf(filterGroup))
         }
@@ -64,7 +70,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.value }
+            return filterGroup.items.filterIsInstance<Item.TriStateGroup>().any { it.state != State.IGNORE.value }
         }
 
         inner class FilterGroup : Group {
@@ -72,12 +78,41 @@ class LibrarySettingsSheet(
             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)
-            private val tracking = Item.TriStateGroup(R.string.action_filter_tracked, this)
+            private val trackFilters: Map<String, Item.TriStateGroup>
 
             override val header = null
-            override val items = listOf(downloaded, unread, completed, tracking)
+            override val items: List<Item>
             override val footer = null
 
+            init {
+                trackManager.services.filter { service -> service.isLogged }
+                    .also { services ->
+                        val size = services.size
+                        trackFilters = services.associate { service ->
+                            Pair(service.name, Item.TriStateGroup(getServiceResId(service, size), this))
+                        }
+                        val list: MutableList<Item> = mutableListOf(downloaded, unread, completed)
+                        if (size > 1) list.add(Item.Header(R.string.action_filter_tracked))
+                        list.addAll(trackFilters.values)
+                        items = list
+                    }
+            }
+
+            private fun getServiceResId(service: TrackService, size: Int): Int {
+                return if (size > 1) getServiceResId(service) else R.string.action_filter_tracked
+            }
+
+            private fun getServiceResId(service: TrackService): Int {
+                return when (service) {
+                    is Anilist -> R.string.anilist
+                    is MyAnimeList -> R.string.my_anime_list
+                    is Kitsu -> R.string.kitsu
+                    is Bangumi -> R.string.bangumi
+                    is Shikimori -> R.string.shikimori
+                    else -> R.string.unknown
+                }
+            }
+
             override fun initModels() {
                 if (preferences.downloadedOnly().get()) {
                     downloaded.state = State.INCLUDE.value
@@ -88,12 +123,8 @@ class LibrarySettingsSheet(
                 unread.state = preferences.filterUnread().get()
                 completed.state = preferences.filterCompleted().get()
 
-                if (!trackManager.hasLoggedServices()) {
-                    tracking.state = State.IGNORE.value
-                    tracking.isVisible = false
-                } else {
-                    tracking.state = preferences.filterTracking().get()
-                    tracking.isVisible = true
+                trackFilters.forEach { trackFilter ->
+                    trackFilter.value.state = preferences.filterTracking(trackFilter.key).get()
                 }
             }
 
@@ -110,7 +141,13 @@ class LibrarySettingsSheet(
                     downloaded -> preferences.filterDownloaded().set(newState)
                     unread -> preferences.filterUnread().set(newState)
                     completed -> preferences.filterCompleted().set(newState)
-                    tracking -> preferences.filterTracking().set(newState)
+                    else -> {
+                        trackFilters.forEach { trackFilter ->
+                            if (trackFilter.value == item) {
+                                preferences.filterTracking(trackFilter.key).set(newState)
+                            }
+                        }
+                    }
                 }
 
                 adapter.notifyItemChanged(item)

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

@@ -747,4 +747,11 @@
     <string name="spen_previous_page">Previous page</string>
     <string name="spen_next_page">Next page</string>
 
+    <!-- Tracker names -->
+    <string name="anilist" translatable="false">AniList</string>
+    <string name="my_anime_list" translatable="false">MyAnimeList</string>
+    <string name="kitsu" translatable="false">Kitsu</string>
+    <string name="bangumi" translatable="false">Bangumi</string>
+    <string name="shikimori" translatable="false">Shikimori</string>
+
 </resources>