Tri-state library filters (closes #1814)
Based on https://github.com/inorichi/tachiyomi/pull/2127. Co-authored-by: hXtreme <hXtreme@users.noreply.github.com> (cherry picked from commit 687f3d48ea03e09c2fe33a8d8e36e1adb87bbf4b) # Conflicts: # app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt # app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt # app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt # app/src/main/java/eu/kanade/tachiyomi/widget/ExtendedNavigationView.kt
This commit is contained in:
parent
8df978a91c
commit
573768482f
@ -1,11 +1,14 @@
|
|||||||
package eu.kanade.tachiyomi
|
package eu.kanade.tachiyomi
|
||||||
|
|
||||||
|
import androidx.core.content.edit
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupCreatorJob
|
import eu.kanade.tachiyomi.data.backup.BackupCreatorJob
|
||||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.updater.UpdaterJob
|
import eu.kanade.tachiyomi.data.updater.UpdaterJob
|
||||||
import eu.kanade.tachiyomi.extension.ExtensionUpdateJob
|
import eu.kanade.tachiyomi.extension.ExtensionUpdateJob
|
||||||
import eu.kanade.tachiyomi.ui.library.LibrarySort
|
import eu.kanade.tachiyomi.ui.library.LibrarySort
|
||||||
|
import eu.kanade.tachiyomi.widget.ExtendedNavigationView
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
object Migrations {
|
object Migrations {
|
||||||
@ -92,6 +95,23 @@ object Migrations {
|
|||||||
preferences.librarySortingMode().set(LibrarySort.ALPHA)
|
preferences.librarySortingMode().set(LibrarySort.ALPHA)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (oldVersion < 52) {
|
||||||
|
// Migrate library filters to tri-state versions
|
||||||
|
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
|
||||||
|
}
|
||||||
|
preferences.filterDownloaded().set(convertBooleanPrefToTriState("pref_filter_downloaded_key"))
|
||||||
|
preferences.filterUnread().set(convertBooleanPrefToTriState("pref_filter_unread_key"))
|
||||||
|
preferences.filterCompleted().set(convertBooleanPrefToTriState("pref_filter_completed_key"))
|
||||||
|
prefs.edit {
|
||||||
|
remove("pref_filter_downloaded_key")
|
||||||
|
remove("pref_filter_unread_key")
|
||||||
|
remove("pref_filter_completed_key")
|
||||||
|
}
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -109,17 +109,17 @@ object PreferenceKeys {
|
|||||||
|
|
||||||
const val downloadedOnly = "pref_downloaded_only"
|
const val downloadedOnly = "pref_downloaded_only"
|
||||||
|
|
||||||
const val filterDownloaded = "pref_filter_downloaded_key"
|
const val filterDownloaded = "pref_filter_library_downloaded"
|
||||||
|
|
||||||
const val filterUnread = "pref_filter_unread_key"
|
const val filterUnread = "pref_filter_library_unread"
|
||||||
|
|
||||||
const val filterCompleted = "pref_filter_completed_key"
|
const val filterCompleted = "pref_filter_library_completed"
|
||||||
|
|
||||||
const val filterStarted = "pref_filter_started_key"
|
const val filterStarted = "pref_filter_library_started"
|
||||||
|
|
||||||
const val filterTracked = "pref_filter_tracked_key"
|
const val filterTracked = "pref_filter_library_tracked"
|
||||||
|
|
||||||
const val filterLewd = "pref_filter_lewd_key"
|
const val filterLewd = "pref_filter_library_lewd"
|
||||||
|
|
||||||
const val librarySortingMode = "library_sorting_mode"
|
const val librarySortingMode = "library_sorting_mode"
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode
|
|||||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues.NsfwAllowance
|
import eu.kanade.tachiyomi.data.preference.PreferenceValues.NsfwAllowance
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.TrackService
|
||||||
import eu.kanade.tachiyomi.data.track.anilist.Anilist
|
import eu.kanade.tachiyomi.data.track.anilist.Anilist
|
||||||
|
import eu.kanade.tachiyomi.widget.ExtendedNavigationView
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
@ -210,18 +211,17 @@ class PreferencesHelper(val context: Context) {
|
|||||||
|
|
||||||
fun categoryTabs() = flowPrefs.getBoolean(Keys.categoryTabs, true)
|
fun categoryTabs() = flowPrefs.getBoolean(Keys.categoryTabs, true)
|
||||||
|
|
||||||
// J2K converted from boolean to integer
|
fun filterDownloaded() = flowPrefs.getInt(Keys.filterDownloaded, ExtendedNavigationView.Item.TriStateGroup.STATE_IGNORE)
|
||||||
fun filterDownloaded() = flowPrefs.getInt(Keys.filterDownloaded, 0)
|
|
||||||
|
|
||||||
fun filterUnread() = flowPrefs.getInt(Keys.filterUnread, 0)
|
fun filterUnread() = flowPrefs.getInt(Keys.filterUnread, ExtendedNavigationView.Item.TriStateGroup.STATE_IGNORE)
|
||||||
|
|
||||||
fun filterCompleted() = flowPrefs.getInt(Keys.filterCompleted, 0)
|
fun filterCompleted() = flowPrefs.getInt(Keys.filterCompleted, ExtendedNavigationView.Item.TriStateGroup.STATE_IGNORE)
|
||||||
|
|
||||||
fun filterStarted() = flowPrefs.getInt(Keys.filterStarted, 0)
|
fun filterStarted() = flowPrefs.getInt(Keys.filterStarted, ExtendedNavigationView.Item.TriStateGroup.STATE_IGNORE)
|
||||||
|
|
||||||
fun filterTracked() = flowPrefs.getInt(Keys.filterTracked, 0)
|
fun filterTracked() = flowPrefs.getInt(Keys.filterTracked, ExtendedNavigationView.Item.TriStateGroup.STATE_IGNORE)
|
||||||
|
|
||||||
fun filterLewd() = flowPrefs.getInt(Keys.filterLewd, 0)
|
fun filterLewd() = flowPrefs.getInt(Keys.filterLewd, ExtendedNavigationView.Item.TriStateGroup.STATE_IGNORE)
|
||||||
|
|
||||||
fun librarySortingMode() = flowPrefs.getInt(Keys.librarySortingMode, 0)
|
fun librarySortingMode() = flowPrefs.getInt(Keys.librarySortingMode, 0)
|
||||||
|
|
||||||
|
@ -13,19 +13,18 @@ import eu.kanade.tachiyomi.data.download.DownloadManager
|
|||||||
import eu.kanade.tachiyomi.data.library.CustomMangaManager
|
import eu.kanade.tachiyomi.data.library.CustomMangaManager
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
|
import eu.kanade.tachiyomi.source.LocalSource
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.source.model.Filter.TriState.Companion.STATE_EXCLUDE
|
|
||||||
import eu.kanade.tachiyomi.source.model.Filter.TriState.Companion.STATE_IGNORE
|
|
||||||
import eu.kanade.tachiyomi.source.model.Filter.TriState.Companion.STATE_INCLUDE
|
|
||||||
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.source.online.all.MergedSource
|
import eu.kanade.tachiyomi.source.online.all.MergedSource
|
||||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||||
import eu.kanade.tachiyomi.util.isLocal
|
|
||||||
import eu.kanade.tachiyomi.util.lang.combineLatest
|
import eu.kanade.tachiyomi.util.lang.combineLatest
|
||||||
import eu.kanade.tachiyomi.util.lang.isNullOrUnsubscribed
|
import eu.kanade.tachiyomi.util.lang.isNullOrUnsubscribed
|
||||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||||
import eu.kanade.tachiyomi.util.removeCovers
|
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 exh.EH_SOURCE_ID
|
import exh.EH_SOURCE_ID
|
||||||
import exh.EXH_SOURCE_ID
|
import exh.EXH_SOURCE_ID
|
||||||
import exh.MERGED_SOURCE_ID
|
import exh.MERGED_SOURCE_ID
|
||||||
@ -164,8 +163,8 @@ class LibraryPresenter(
|
|||||||
* @param map the map to filter.
|
* @param map the map to filter.
|
||||||
*/
|
*/
|
||||||
private fun applyFilters(map: LibraryMap): LibraryMap {
|
private fun applyFilters(map: LibraryMap): LibraryMap {
|
||||||
|
val downloadedOnly = preferences.downloadedOnly().get()
|
||||||
val filterDownloaded = preferences.filterDownloaded().get()
|
val filterDownloaded = preferences.filterDownloaded().get()
|
||||||
val filterDownloadedOnly = preferences.downloadedOnly().get()
|
|
||||||
val filterUnread = preferences.filterUnread().get()
|
val filterUnread = preferences.filterUnread().get()
|
||||||
val filterCompleted = preferences.filterCompleted().get()
|
val filterCompleted = preferences.filterCompleted().get()
|
||||||
// SY -->
|
// SY -->
|
||||||
@ -174,49 +173,71 @@ class LibraryPresenter(
|
|||||||
val filterLewd = preferences.filterLewd().get()
|
val filterLewd = preferences.filterLewd().get()
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
val filterFn: (LibraryItem) -> Boolean = f@{ item ->
|
val filterFnUnread: (LibraryItem) -> Boolean = unread@{ item ->
|
||||||
// Filter when there isn't unread chapters.
|
if (filterUnread == STATE_IGNORE) return@unread true
|
||||||
if (filterUnread == STATE_INCLUDE && item.manga.unread == 0) {
|
val isUnread = item.manga.unread != 0
|
||||||
return@f false
|
|
||||||
|
return@unread if (filterUnread == STATE_INCLUDE) isUnread
|
||||||
|
else !isUnread
|
||||||
|
}
|
||||||
|
|
||||||
|
val filterFnCompleted: (LibraryItem) -> Boolean = completed@{ item ->
|
||||||
|
if (filterCompleted == STATE_IGNORE) return@completed true
|
||||||
|
val isCompleted = item.manga.status == SManga.COMPLETED
|
||||||
|
|
||||||
|
return@completed if (filterCompleted == STATE_INCLUDE) isCompleted
|
||||||
|
else !isCompleted
|
||||||
|
}
|
||||||
|
|
||||||
|
val filterFnDownloaded: (LibraryItem) -> Boolean = downloaded@{ item ->
|
||||||
|
if (filterDownloaded == STATE_IGNORE && !downloadedOnly) return@downloaded true
|
||||||
|
val isDownloaded = when {
|
||||||
|
item.manga.source == LocalSource.ID -> true
|
||||||
|
item.downloadCount != -1 -> item.downloadCount > 0
|
||||||
|
else -> downloadManager.getDownloadCount(item.manga) > 0
|
||||||
}
|
}
|
||||||
if (filterUnread == STATE_EXCLUDE && item.manga.unread > 0) {
|
|
||||||
return@f false
|
return@downloaded if (downloadedOnly || filterDownloaded == STATE_INCLUDE) isDownloaded
|
||||||
}
|
else !isDownloaded
|
||||||
if (filterCompleted == STATE_INCLUDE && item.manga.status != SManga.COMPLETED) {
|
}
|
||||||
return@f false
|
|
||||||
}
|
// SY -->
|
||||||
if (filterCompleted == STATE_EXCLUDE && item.manga.status == SManga.COMPLETED) {
|
val filterFnStarted: (LibraryItem) -> Boolean = started@{ item ->
|
||||||
return@f false
|
if (filterStarted == STATE_IGNORE) return@started true
|
||||||
}
|
val hasRead = item.manga.read != 0
|
||||||
// SY -->
|
|
||||||
if (filterStarted == STATE_INCLUDE && item.manga.read == 0) {
|
return@started if (filterStarted == STATE_INCLUDE) hasRead
|
||||||
return@f false
|
else !hasRead
|
||||||
}
|
}
|
||||||
if (filterStarted == STATE_EXCLUDE && item.manga.read > 0) {
|
|
||||||
return@f false
|
val filterFnTracked: (LibraryItem) -> Boolean = tracked@{ item ->
|
||||||
}
|
if (filterTracked == STATE_IGNORE) return@tracked true
|
||||||
if (filterTracked != STATE_IGNORE) {
|
val hasTracks = db.getTracks(item.manga).executeAsBlocking().filterNot { it.sync_id == TrackManager.MDLIST && it.status == FollowStatus.UNFOLLOWED.int }.isNotEmpty()
|
||||||
val tracks = db.getTracks(item.manga).executeAsBlocking()
|
|
||||||
.filterNot { it.sync_id == TrackManager.MDLIST && it.status == FollowStatus.UNFOLLOWED.int }
|
return@tracked if (filterTracked == STATE_INCLUDE) hasTracks
|
||||||
if (filterTracked == STATE_INCLUDE && tracks.isEmpty()) return@f false
|
else !hasTracks
|
||||||
else if (filterTracked == STATE_EXCLUDE && tracks.isNotEmpty()) return@f false
|
}
|
||||||
}
|
|
||||||
if (filterLewd != STATE_IGNORE) {
|
val filterFnLewd: (LibraryItem) -> Boolean = lewd@{ item ->
|
||||||
val isLewd = item.manga.isLewd()
|
if (filterLewd == STATE_IGNORE) return@lewd true
|
||||||
if (filterLewd == STATE_INCLUDE && !isLewd) return@f false
|
val isLewd = item.manga.isLewd()
|
||||||
else if (filterLewd == STATE_EXCLUDE && isLewd) return@f false
|
|
||||||
}
|
return@lewd if (filterLewd == STATE_INCLUDE) isLewd
|
||||||
// Filter when there are no downloads.
|
else !isLewd
|
||||||
if (filterDownloaded != STATE_IGNORE || filterDownloadedOnly) {
|
}
|
||||||
val isDownloaded = when {
|
// SY <--
|
||||||
item.manga.isLocal() -> true
|
|
||||||
item.downloadCount != -1 -> item.downloadCount > 0
|
val filterFn: (LibraryItem) -> Boolean = filter@{ item ->
|
||||||
else -> downloadManager.getDownloadCount(item.manga) > 0
|
return@filter !(
|
||||||
}
|
!filterFnUnread(item) ||
|
||||||
return@f if (filterDownloaded == STATE_INCLUDE || filterDownloadedOnly) isDownloaded else !isDownloaded
|
!filterFnCompleted(item) ||
|
||||||
}
|
!filterFnDownloaded(item) ||
|
||||||
// SY <--
|
// SY -->
|
||||||
true
|
!filterFnStarted(item) ||
|
||||||
|
!filterFnTracked(item) ||
|
||||||
|
!filterFnLewd(item)
|
||||||
|
// SY <--
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return map.mapValues { entry -> entry.value.filter(filterFn) }
|
return map.mapValues { entry -> entry.value.filter(filterFn) }
|
||||||
|
@ -9,10 +9,10 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
|||||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode
|
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
import eu.kanade.tachiyomi.source.model.Filter.TriState.Companion.STATE_EXCLUDE
|
|
||||||
import eu.kanade.tachiyomi.source.model.Filter.TriState.Companion.STATE_IGNORE
|
|
||||||
import eu.kanade.tachiyomi.source.model.Filter.TriState.Companion.STATE_INCLUDE
|
|
||||||
import eu.kanade.tachiyomi.widget.ExtendedNavigationView
|
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.TabbedBottomSheetDialog
|
import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
@ -76,21 +76,17 @@ class LibrarySettingsSheet(
|
|||||||
* 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 {
|
||||||
// SY -->
|
return filterGroup.items.any { it.state != Item.TriStateGroup.STATE_IGNORE }
|
||||||
return filterGroup.items.any { it.state != STATE_IGNORE }
|
|
||||||
// SY <--
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class FilterGroup : Group {
|
inner class FilterGroup : Group {
|
||||||
|
|
||||||
// SY -->
|
|
||||||
private val downloaded = Item.TriStateGroup(R.string.action_filter_downloaded, this)
|
private val downloaded = Item.TriStateGroup(R.string.action_filter_downloaded, this)
|
||||||
private val unread = Item.TriStateGroup(R.string.action_filter_unread, this)
|
private val unread = Item.TriStateGroup(R.string.action_filter_unread, this)
|
||||||
private val completed = Item.TriStateGroup(R.string.completed, this)
|
private val completed = Item.TriStateGroup(R.string.completed, this)
|
||||||
private val started = Item.TriStateGroup(R.string.started, this)
|
private val started = Item.TriStateGroup(R.string.started, this)
|
||||||
private val tracked = Item.TriStateGroup(R.string.tracked, this)
|
private val tracked = Item.TriStateGroup(R.string.tracked, this)
|
||||||
private val lewd = Item.TriStateGroup(R.string.lewd, this)
|
private val lewd = Item.TriStateGroup(R.string.lewd, this)
|
||||||
// SY <--
|
|
||||||
|
|
||||||
override val header = null
|
override val header = null
|
||||||
// SY -->
|
// SY -->
|
||||||
@ -104,44 +100,37 @@ class LibrarySettingsSheet(
|
|||||||
// SY <--
|
// SY <--
|
||||||
override val footer = null
|
override val footer = null
|
||||||
|
|
||||||
// SY -->
|
override fun initModels() {
|
||||||
override fun initModels() { // j2k changes
|
if (preferences.downloadedOnly().get()) {
|
||||||
try {
|
downloaded.state = STATE_INCLUDE
|
||||||
|
downloaded.enabled = false
|
||||||
|
} else {
|
||||||
downloaded.state = preferences.filterDownloaded().get()
|
downloaded.state = preferences.filterDownloaded().get()
|
||||||
unread.state = preferences.filterUnread().get()
|
|
||||||
completed.state = preferences.filterCompleted().get()
|
|
||||||
completed.state = preferences.filterStarted().get()
|
|
||||||
if (Injekt.get<TrackManager>().hasLoggedServices()) {
|
|
||||||
tracked.state = preferences.filterTracked().get()
|
|
||||||
} else {
|
|
||||||
tracked.state = STATE_IGNORE
|
|
||||||
}
|
|
||||||
lewd.state = preferences.filterLewd().get()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
preferences.upgradeFilters()
|
|
||||||
}
|
}
|
||||||
|
unread.state = preferences.filterUnread().get()
|
||||||
|
completed.state = preferences.filterCompleted().get()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemClicked(item: Item) { // j2k changes
|
override fun onItemClicked(item: Item) {
|
||||||
item as Item.TriStateGroup
|
item as Item.TriStateGroup
|
||||||
val newState = when (item.state) {
|
val newState = when (item.state) {
|
||||||
STATE_IGNORE -> STATE_INCLUDE
|
STATE_IGNORE -> STATE_INCLUDE
|
||||||
STATE_INCLUDE -> STATE_EXCLUDE
|
STATE_INCLUDE -> STATE_EXCLUDE
|
||||||
else -> STATE_IGNORE
|
STATE_EXCLUDE -> STATE_IGNORE
|
||||||
|
else -> throw Exception("Unknown State")
|
||||||
}
|
}
|
||||||
item.state = newState
|
item.state = newState
|
||||||
when (item) {
|
when (item) {
|
||||||
downloaded -> preferences.filterDownloaded().set(item.state)
|
downloaded -> preferences.filterDownloaded().set(newState)
|
||||||
unread -> preferences.filterUnread().set(item.state)
|
unread -> preferences.filterUnread().set(newState)
|
||||||
completed -> preferences.filterCompleted().set(item.state)
|
completed -> preferences.filterCompleted().set(newState)
|
||||||
started -> preferences.filterStarted().set(item.state)
|
started -> preferences.filterStarted().set(newState)
|
||||||
tracked -> preferences.filterTracked().set(item.state)
|
tracked -> preferences.filterTracked().set(newState)
|
||||||
lewd -> preferences.filterLewd().set(item.state)
|
lewd -> preferences.filterLewd().set(newState)
|
||||||
}
|
}
|
||||||
|
|
||||||
adapter.notifyItemChanged(item)
|
adapter.notifyItemChanged(item)
|
||||||
}
|
}
|
||||||
// SY <--
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,11 +144,13 @@ class LibrarySettingsSheet(
|
|||||||
setGroups(listOf(SortGroup()))
|
setGroups(listOf(SortGroup()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SY -->
|
||||||
fun refreshMode() {
|
fun refreshMode() {
|
||||||
recycler.adapter = null
|
recycler.adapter = null
|
||||||
removeView(recycler)
|
removeView(recycler)
|
||||||
setGroups(listOf(SortGroup()))
|
setGroups(listOf(SortGroup()))
|
||||||
}
|
}
|
||||||
|
// SY <--
|
||||||
|
|
||||||
inner class SortGroup : Group {
|
inner class SortGroup : Group {
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import android.content.Context
|
|||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.annotation.AttrRes
|
||||||
import androidx.annotation.CallSuper
|
import androidx.annotation.CallSuper
|
||||||
import androidx.appcompat.content.res.AppCompatResources
|
import androidx.appcompat.content.res.AppCompatResources
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
@ -45,20 +46,20 @@ open class ExtendedNavigationView @JvmOverloads constructor(
|
|||||||
/**
|
/**
|
||||||
* A checkbox belonging to a group. The group must handle selections and restrictions.
|
* A checkbox belonging to a group. The group must handle selections and restrictions.
|
||||||
*/
|
*/
|
||||||
class CheckboxGroup(resTitle: Int, override val group: Group, checked: Boolean = false) :
|
class CheckboxGroup(resTitle: Int, override val group: Group, checked: Boolean = false, enabled: Boolean = true) :
|
||||||
Checkbox(resTitle, checked), GroupedItem
|
Checkbox(resTitle, checked, enabled), GroupedItem
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A radio belonging to a group (a sole radio makes no sense). The group must handle
|
* A radio belonging to a group (a sole radio makes no sense). The group must handle
|
||||||
* selections and restrictions.
|
* selections and restrictions.
|
||||||
*/
|
*/
|
||||||
class Radio(val resTitle: Int, override val group: Group, var checked: Boolean = false) :
|
class Radio(val resTitle: Int, override val group: Group, var checked: Boolean = false, var enabled: Boolean = true) :
|
||||||
Item(), GroupedItem
|
Item(), GroupedItem
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An item with which needs more than two states (selected/deselected).
|
* An item with which needs more than two states (selected/deselected).
|
||||||
*/
|
*/
|
||||||
abstract class MultiState(val resTitle: Int, var state: Int = 0) : Item() {
|
abstract class MultiState(val resTitle: Int, var state: Int = 0, var enabled: Boolean = true) : Item() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the drawable associated to every possible each state.
|
* Returns the drawable associated to every possible each state.
|
||||||
@ -71,21 +72,19 @@ open class ExtendedNavigationView @JvmOverloads constructor(
|
|||||||
* @param context any context.
|
* @param context any context.
|
||||||
* @param resId the vector resource to load and tint
|
* @param resId the vector resource to load and tint
|
||||||
*/
|
*/
|
||||||
// SY -->
|
fun tintVector(context: Context, resId: Int, @AttrRes colorAttrRes: Int = R.attr.colorAccent): Drawable {
|
||||||
fun tintVector(context: Context, resId: Int, colorId: Int = R.attr.colorAccent): Drawable {
|
|
||||||
return AppCompatResources.getDrawable(context, resId)!!.apply {
|
return AppCompatResources.getDrawable(context, resId)!!.apply {
|
||||||
setTint(context.getResourceColor(colorId))
|
setTint(context.getResourceColor(if (enabled) colorAttrRes else R.attr.colorControlNormal))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// SY <--
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An item with which needs more than two states (selected/deselected) belonging to a group.
|
* An item with which needs more than two states (selected/deselected) belonging to a group.
|
||||||
* The group must handle selections and restrictions.
|
* The group must handle selections and restrictions.
|
||||||
*/
|
*/
|
||||||
abstract class MultiStateGroup(resTitle: Int, override val group: Group, state: Int = 0) :
|
abstract class MultiStateGroup(resTitle: Int, override val group: Group, state: Int = 0, enabled: Boolean = true) :
|
||||||
MultiState(resTitle, state), GroupedItem
|
MultiState(resTitle, state, enabled), GroupedItem
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A multistate item for sorting lists (unselected, ascending, descending).
|
* A multistate item for sorting lists (unselected, ascending, descending).
|
||||||
@ -124,7 +123,11 @@ open class ExtendedNavigationView @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// SY <--
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A checkbox with 3 states (unselected, checked, explicitly unchecked).
|
||||||
|
*/
|
||||||
class TriStateGroup(resId: Int, group: Group) : MultiStateGroup(resId, group) {
|
class TriStateGroup(resId: Int, group: Group) : MultiStateGroup(resId, group) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -135,21 +138,13 @@ open class ExtendedNavigationView @JvmOverloads constructor(
|
|||||||
|
|
||||||
override fun getStateDrawable(context: Context): Drawable? {
|
override fun getStateDrawable(context: Context): Drawable? {
|
||||||
return when (state) {
|
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_INCLUDE -> tintVector(context, R.drawable.ic_check_box_24dp)
|
||||||
STATE_EXCLUDE -> tintVector(
|
STATE_EXCLUDE -> tintVector(context, R.drawable.ic_check_box_x_24dp)
|
||||||
context,
|
else -> throw Exception("Unknown state")
|
||||||
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
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// SY <--
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -258,13 +253,15 @@ open class ExtendedNavigationView @JvmOverloads constructor(
|
|||||||
val item = items[position] as Item.Radio
|
val item = items[position] as Item.Radio
|
||||||
holder.radio.setText(item.resTitle)
|
holder.radio.setText(item.resTitle)
|
||||||
holder.radio.isChecked = item.checked
|
holder.radio.isChecked = item.checked
|
||||||
|
|
||||||
|
holder.itemView.isClickable = item.enabled
|
||||||
|
holder.radio.isEnabled = item.enabled
|
||||||
}
|
}
|
||||||
is CheckboxHolder -> {
|
is CheckboxHolder -> {
|
||||||
val item = items[position] as Item.CheckboxGroup
|
val item = items[position] as Item.CheckboxGroup
|
||||||
holder.check.setText(item.resTitle)
|
holder.check.setText(item.resTitle)
|
||||||
holder.check.isChecked = item.checked
|
holder.check.isChecked = item.checked
|
||||||
|
|
||||||
// Allow disabling the holder
|
|
||||||
holder.itemView.isClickable = item.enabled
|
holder.itemView.isClickable = item.enabled
|
||||||
holder.check.isEnabled = item.enabled
|
holder.check.isEnabled = item.enabled
|
||||||
}
|
}
|
||||||
@ -273,6 +270,12 @@ open class ExtendedNavigationView @JvmOverloads constructor(
|
|||||||
val drawable = item.getStateDrawable(context)
|
val drawable = item.getStateDrawable(context)
|
||||||
holder.text.setText(item.resTitle)
|
holder.text.setText(item.resTitle)
|
||||||
holder.text.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null)
|
holder.text.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null)
|
||||||
|
|
||||||
|
holder.itemView.isClickable = item.enabled
|
||||||
|
holder.text.isEnabled = item.enabled
|
||||||
|
|
||||||
|
// Mimics checkbox/radio button
|
||||||
|
holder.text.alpha = if (item.enabled) 1f else 0.4f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user