From a2aad23eae2d5d31de912667197cf626f1cd7818 Mon Sep 17 00:00:00 2001 From: Andreas Date: Sun, 24 Jan 2021 21:24:00 +0100 Subject: [PATCH] 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 (cherry picked from commit fea2e0a26557051a375af236086203507230d78d) # Conflicts: # app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt # app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt --- .../data/preference/PreferencesHelper.kt | 2 +- .../tachiyomi/data/track/mdlist/MdList.kt | 2 +- .../ui/library/LibraryCategoryAdapter.kt | 3 +- .../tachiyomi/ui/library/LibraryPresenter.kt | 39 ++++++++--- .../ui/library/LibrarySettingsSheet.kt | 67 ++++++++++++++----- app/src/main/res/values/strings.xml | 7 ++ app/src/main/res/values/strings_sy.xml | 2 + 7 files changed, 92 insertions(+), 30 deletions(-) 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 a09c44b1e..25e6bef1f 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/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 filterStarted() = flowPrefs.getInt(Keys.filterStarted, ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/mdlist/MdList.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/mdlist/MdList.kt index d15279222..83db110f5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/mdlist/MdList.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/mdlist/MdList.kt @@ -24,7 +24,7 @@ class MdList(private val context: Context, id: Int) : TrackService(id) { private val mdex by lazy { MdUtil.getEnabledMangaDex() } private val db: DatabaseHelper by injectLazy() - override val name = "MDList" + override val name = context.getString(R.string.mdlist) override fun getLogo(): Int { return R.drawable.ic_tracker_mangadex_logo diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt index 879cac187..6ea5679ef 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt @@ -50,6 +50,7 @@ class LibraryCategoryAdapter(view: LibraryCategoryView, val controller: LibraryC private val hasLoggedServices by lazy { trackManager.hasLoggedServices() } + private val services = trackManager.services.map { it.name } // Keep compatibility as searchText field was replaced when we upgraded FlexibleAdapter var searchText @@ -97,7 +98,7 @@ class LibraryCategoryAdapter(view: LibraryCategoryView, val controller: LibraryC preferences.filterCompleted().get() == Filter.TriState.STATE_IGNORE && preferences.filterStarted().get() == Filter.TriState.STATE_IGNORE && preferences.filterUnread().get() == Filter.TriState.STATE_IGNORE && - preferences.filterTracking().get() == Filter.TriState.STATE_IGNORE && + services.all { preferences.filterTracking(it).get() == Filter.TriState.STATE_IGNORE } && preferences.filterLewd().get() == Filter.TriState.STATE_IGNORE // EXH --> 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 540d1d1ab..f8e26be41 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt @@ -158,13 +158,16 @@ class LibraryPresenter( * * @param map the map to filter. */ - private fun applyFilters(map: LibraryMap, trackMap: Map): LibraryMap { + private fun applyFilters(map: LibraryMap, trackMap: Map>): 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() // SY --> val filterStarted = preferences.filterStarted().get() val filterLewd = preferences.filterLewd().get() @@ -199,11 +202,27 @@ class LibraryPresenter( } val filterFnTracking: (LibraryItem) -> Boolean = tracking@{ item -> - if (isNotLogged || tracking == State.IGNORE.value) return@tracking true + if (isNotAnyLoggedIn) return@tracking true - val isTracking = trackMap[item.manga.id ?: -1] ?: false + val trackedManga = trackMap[item.manga.id ?: -1] - return@tracking if (tracking == State.INCLUDE.value) isTracking else !isTracking + 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() + + if (containsInclude.any()) return@tracking include.any() + + return@tracking false } // SY --> @@ -437,7 +456,7 @@ class LibraryPresenter( * * @return an observable of tracked manga. */ - private fun getFilterObservable(): Observable> { + private fun getFilterObservable(): Observable>> { return getTracksObservable().combineLatest(filterTriggerRelay.observeOn(Schedulers.io())) { tracks, _ -> tracks } } @@ -446,13 +465,13 @@ class LibraryPresenter( * * @return an observable of tracked manga. */ - private fun getTracksObservable(): Observable> { + private fun getTracksObservable(): Observable>> { 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)?.let { tracker -> tracker.isLogged && ((tracker.id == TrackManager.MDLIST && it.status != FollowStatus.UNFOLLOWED.int) || tracker.id != TrackManager.MDLIST) } ?: false + tracksForMangaId.value.associate { + Pair(it.sync_id, trackManager.getService(it.sync_id)?.let { tracker -> tracker.isLogged && ((tracker.id == TrackManager.MDLIST && it.status != FollowStatus.UNFOLLOWED.int) || tracker.id != TrackManager.MDLIST) } ?: false) } } }.observeOn(Schedulers.io()) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt index 1baa4d165..52562d628 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt @@ -9,16 +9,23 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper 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.mdlist.MdList +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) { @@ -67,8 +74,6 @@ class LibrarySettingsSheet( private val filterGroup = FilterGroup() - private val trackManager: TrackManager by injectValue() - init { setGroups(listOf(filterGroup)) } @@ -77,7 +82,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().any { it.state != State.IGNORE.value } } inner class FilterGroup : Group { @@ -85,7 +90,7 @@ 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 // SY --> private val started = Item.TriStateGroup(R.string.started, this) @@ -93,13 +98,39 @@ class LibrarySettingsSheet( // SY <-- override val header = null - - // SY --> - override val items = listOf(downloaded, unread, completed, tracking, started, lewd) - - // SY <-- + override val items: List 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 = mutableListOf(downloaded, unread, completed, started, lewd) + 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 + is MdList -> R.string.mdlist + else -> R.string.unknown + } + } + override fun initModels() { if (preferences.downloadedOnly().get()) { downloaded.state = State.INCLUDE.value @@ -110,12 +141,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() } // SY --> @@ -137,11 +164,17 @@ class LibrarySettingsSheet( downloaded -> preferences.filterDownloaded().set(newState) unread -> preferences.filterUnread().set(newState) completed -> preferences.filterCompleted().set(newState) - tracking -> preferences.filterTracking().set(newState) // SY --> started -> preferences.filterStarted().set(newState) lewd -> preferences.filterLewd().set(newState) // SY <-- + else -> { + trackFilters.forEach { trackFilter -> + if (trackFilter.value == item) { + preferences.filterTracking(trackFilter.key).set(newState) + } + } + } } adapter.notifyItemChanged(item) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ffccbee51..c1f18b3b7 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -749,4 +749,11 @@ Previous page Next page + + AniList + MyAnimeList + Kitsu + Bangumi + Shikimori + diff --git a/app/src/main/res/values/strings_sy.xml b/app/src/main/res/values/strings_sy.xml index b745671c5..50685c938 100644 --- a/app/src/main/res/values/strings_sy.xml +++ b/app/src/main/res/values/strings_sy.xml @@ -568,6 +568,7 @@ Refresh to get proper info + MDList Unfollowed MangaDex settings Sync Mangadex manga to your library @@ -658,4 +659,5 @@ moments ago +