Cleanup of mat preferences logic

remove injektion of Preference helper, so it will use whatever context it needs to use

Added new bindTo method for tristate for both prefs needed, support of default values too

Fix default value for int list preferences
This commit is contained in:
Jays2Kings 2022-05-08 19:04:21 -04:00
parent 251a7cf320
commit a3fd820060
10 changed files with 75 additions and 89 deletions

View file

@ -131,9 +131,6 @@ object PreferenceKeys {
const val libraryUpdateInterval = "pref_library_update_interval_key" const val libraryUpdateInterval = "pref_library_update_interval_key"
const val libraryUpdateCategories = "library_update_categories"
const val libraryUpdateCategoriesExclude = "library_update_categories_exclude"
const val filterDownloaded = "pref_filter_downloaded_key" const val filterDownloaded = "pref_filter_downloaded_key"
const val filterUnread = "pref_filter_unread_key" const val filterUnread = "pref_filter_unread_key"
@ -160,9 +157,6 @@ object PreferenceKeys {
const val downloadNew = "download_new" const val downloadNew = "download_new"
const val downloadNewCategories = "download_new_categories"
const val downloadNewCategoriesExclude = "download_new_categories_exclude"
const val libraryLayout = "pref_display_library_layout" const val libraryLayout = "pref_display_library_layout"
const val gridSize = "grid_size_float" const val gridSize = "grid_size_float"

View file

@ -260,8 +260,8 @@ class PreferencesHelper(val context: Context) {
fun libraryUpdateMangaRestriction() = flowPrefs.getStringSet("library_update_manga_restriction", setOf(MANGA_HAS_UNREAD, MANGA_NON_COMPLETED, MANGA_NON_READ)) fun libraryUpdateMangaRestriction() = flowPrefs.getStringSet("library_update_manga_restriction", setOf(MANGA_HAS_UNREAD, MANGA_NON_COMPLETED, MANGA_NON_READ))
fun libraryUpdateCategories() = flowPrefs.getStringSet(Keys.libraryUpdateCategories, emptySet()) fun libraryUpdateCategories() = flowPrefs.getStringSet("library_update_categories", emptySet())
fun libraryUpdateCategoriesExclude() = flowPrefs.getStringSet(Keys.libraryUpdateCategoriesExclude, emptySet()) fun libraryUpdateCategoriesExclude() = flowPrefs.getStringSet("library_update_categories_exclude", emptySet())
fun libraryLayout() = flowPrefs.getInt(Keys.libraryLayout, LibraryItem.LAYOUT_COMFORTABLE_GRID) fun libraryLayout() = flowPrefs.getInt(Keys.libraryLayout, LibraryItem.LAYOUT_COMFORTABLE_GRID)
@ -309,8 +309,8 @@ class PreferencesHelper(val context: Context) {
fun downloadNewChapters() = flowPrefs.getBoolean(Keys.downloadNew, false) fun downloadNewChapters() = flowPrefs.getBoolean(Keys.downloadNew, false)
fun downloadNewChaptersInCategories() = flowPrefs.getStringSet(Keys.downloadNewCategories, emptySet()) fun downloadNewChaptersInCategories() = flowPrefs.getStringSet("download_new_categories", emptySet())
fun excludeCategoriesInDownloadNew() = flowPrefs.getStringSet(Keys.downloadNewCategoriesExclude, emptySet()) fun excludeCategoriesInDownloadNew() = flowPrefs.getStringSet("download_new_categories_exclude", emptySet())
fun autoDownloadAfterReading() = flowPrefs.getInt("auto_download_after_reading", 0) fun autoDownloadAfterReading() = flowPrefs.getInt("auto_download_after_reading", 0)

View file

@ -27,6 +27,7 @@ import eu.kanade.tachiyomi.widget.preference.IntListMatPreference
import eu.kanade.tachiyomi.widget.preference.ListMatPreference import eu.kanade.tachiyomi.widget.preference.ListMatPreference
import eu.kanade.tachiyomi.widget.preference.MultiListMatPreference import eu.kanade.tachiyomi.widget.preference.MultiListMatPreference
import eu.kanade.tachiyomi.widget.preference.TriStateListPreference import eu.kanade.tachiyomi.widget.preference.TriStateListPreference
import com.fredporciuncula.flow.preferences.Preference as FlowPreference
@DslMarker @DslMarker
@Target(AnnotationTarget.TYPE) @Target(AnnotationTarget.TYPE)
@ -72,10 +73,7 @@ inline fun PreferenceGroup.listPreference(
inline fun PreferenceGroup.intListPreference( inline fun PreferenceGroup.intListPreference(
activity: Activity?, activity: Activity?,
block: ( block: (@DSL IntListMatPreference).() -> Unit,
@DSL
IntListMatPreference
).() -> Unit,
): ):
IntListMatPreference { IntListMatPreference {
return initThenAdd(IntListMatPreference(activity, context), block) return initThenAdd(IntListMatPreference(activity, context), block)
@ -83,22 +81,14 @@ inline fun PreferenceGroup.intListPreference(
inline fun PreferenceGroup.multiSelectListPreferenceMat( inline fun PreferenceGroup.multiSelectListPreferenceMat(
activity: Activity?, activity: Activity?,
block: ( block: (@DSL MultiListMatPreference).() -> Unit,
@DSL
MultiListMatPreference
).()
-> Unit,
): MultiListMatPreference { ): MultiListMatPreference {
return initThenAdd(MultiListMatPreference(activity, context), block) return initThenAdd(MultiListMatPreference(activity, context), block)
} }
inline fun PreferenceGroup.triStateListPreference( inline fun PreferenceGroup.triStateListPreference(
activity: Activity?, activity: Activity?,
block: ( block: (@DSL TriStateListPreference).() -> Unit,
@DSL
TriStateListPreference
).()
-> Unit,
): TriStateListPreference { ): TriStateListPreference {
return initThenAdd(TriStateListPreference(activity, context), block) return initThenAdd(TriStateListPreference(activity, context), block)
} }
@ -168,23 +158,39 @@ inline fun Preference.onChange(crossinline block: (Any?) -> Boolean) {
setOnPreferenceChangeListener { _, newValue -> block(newValue) } setOnPreferenceChangeListener { _, newValue -> block(newValue) }
} }
fun <T> Preference.bindTo(preference: com.fredporciuncula.flow.preferences.Preference<T>) { fun <T> Preference.bindTo(preference: FlowPreference<T>) {
key = preference.key key = preference.key
defaultValue = preference.defaultValue defaultValue = preference.defaultValue
} }
fun <T> ListPreference.bindTo(preference: com.fredporciuncula.flow.preferences.Preference<T>) { fun <T> ListPreference.bindTo(preference: FlowPreference<T>) {
key = preference.key key = preference.key
defaultValue = preference.defaultValue.toString() defaultValue = preference.defaultValue.toString()
} }
fun <T> ListMatPreference.bindTo(preference: com.fredporciuncula.flow.preferences.Preference<T>) { fun <T> ListMatPreference.bindTo(preference: FlowPreference<T>) {
key = preference.key key = preference.key
val defValue = preference.defaultValue val defValue = preference.defaultValue
defaultValue = if (defValue is Set<*>) defValue else defValue.toString() defaultValue = if (defValue is Set<*>) defValue else defValue.toString()
} }
fun <T> IntListMatPreference.bindTo(preference: com.fredporciuncula.flow.preferences.Preference<T>) { @Deprecated(
"Do not bind tri-states prefs with a single preference",
ReplaceWith("bindTo(preference, excludePreference = )"),
DeprecationLevel.ERROR,
)
fun <T> TriStateListPreference.bindTo(preference: FlowPreference<T>) { key = preference.key }
fun TriStateListPreference.bindTo(
includePreference: FlowPreference<Set<String>>,
excludePreference: FlowPreference<Set<String>>,
) {
key = includePreference.key
excludeKey = excludePreference.key
defaultValue = includePreference.defaultValue to excludePreference.defaultValue
}
fun <T> IntListMatPreference.bindTo(preference: FlowPreference<T>) {
key = preference.key key = preference.key
defaultValue = preference.defaultValue defaultValue = preference.defaultValue
} }

View file

@ -136,11 +136,7 @@ class SettingsAppearanceController : SettingsController() {
intListPreference(activity) { intListPreference(activity) {
key = Keys.sideNavIconAlignment key = Keys.sideNavIconAlignment
titleRes = R.string.side_nav_icon_alignment titleRes = R.string.side_nav_icon_alignment
entriesRes = arrayOf( entriesRes = arrayOf(R.string.top, R.string.center, R.string.bottom)
R.string.top,
R.string.center,
R.string.bottom,
)
entryRange = 0..2 entryRange = 0..2
defaultValue = 1 defaultValue = 1
isVisible = max( isVisible = max(

View file

@ -86,8 +86,9 @@ class SettingsDownloadController : SettingsController() {
titleRes = R.string.download_new_chapters titleRes = R.string.download_new_chapters
} }
triStateListPreference(activity) { triStateListPreference(activity) {
key = Keys.downloadNewCategories preferences.apply {
excludeKey = Keys.downloadNewCategoriesExclude bindTo(downloadNewChaptersInCategories(), excludeCategoriesInDownloadNew())
}
titleRes = R.string.categories titleRes = R.string.categories
entries = categories.map { it.name } entries = categories.map { it.name }
entryValues = categories.map { it.id.toString() } entryValues = categories.map { it.id.toString() }

View file

@ -162,8 +162,9 @@ class SettingsLibraryController : SettingsController() {
} }
triStateListPreference(activity) { triStateListPreference(activity) {
key = Keys.libraryUpdateCategories preferences.apply {
excludeKey = Keys.libraryUpdateCategoriesExclude bindTo(libraryUpdateCategories(), libraryUpdateCategoriesExclude())
}
titleRes = R.string.categories titleRes = R.string.categories
val categories = listOf(Category.createDefault(context)) + dbCategories val categories = listOf(Category.createDefault(context)) + dbCategories

View file

@ -3,14 +3,13 @@ package eu.kanade.tachiyomi.widget.preference
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import androidx.core.content.edit
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
class IntListMatPreference @JvmOverloads constructor( class IntListMatPreference @JvmOverloads constructor(
activity: Activity?, activity: Activity?,
context: Context, context: Context,
attrs: attrs: AttributeSet? = null,
AttributeSet? =
null,
) : ) :
MatPreference(activity, context, attrs) { MatPreference(activity, context, attrs) {
var entryValues: List<Int> = emptyList() var entryValues: List<Int> = emptyList()
@ -25,23 +24,23 @@ class IntListMatPreference @JvmOverloads constructor(
var customSelectedValue: Int? = null var customSelectedValue: Int? = null
override var customSummaryProvider: SummaryProvider<MatPreference>? = SummaryProvider<MatPreference> { override var customSummaryProvider: SummaryProvider<MatPreference>? = SummaryProvider<MatPreference> {
val index = entryValues.indexOf(prefs.getInt(key, defValue).get()) val index = entryValues.indexOf(sharedPreferences?.getInt(key, defValue) ?: defValue)
if (entries.isEmpty() || index == -1) "" if (entries.isEmpty() || index == -1) ""
else entries[index] else entries[index]
} }
override fun onSetInitialValue(defaultValue: Any?) { override fun onSetInitialValue(defaultValue: Any?) {
super.onSetInitialValue(defaultValue) super.onSetInitialValue(defaultValue)
defValue = defaultValue as? Int ?: defValue defValue = defaultValue?.toString()?.toIntOrNull() ?: defValue
} }
override fun dialog(): MaterialAlertDialogBuilder { override fun dialog(): MaterialAlertDialogBuilder {
return super.dialog().apply { return super.dialog().apply {
val default = entryValues.indexOf(customSelectedValue ?: prefs.getInt(key, defValue).get()) val default = entryValues.indexOf(customSelectedValue ?: sharedPreferences?.getInt(key, defValue))
setSingleChoiceItems(entries.toTypedArray(), default) { dialog, pos -> setSingleChoiceItems(entries.toTypedArray(), default) { dialog, pos ->
val value = entryValues[pos] val value = entryValues[pos]
if (key != null) { if (key != null) {
prefs.getInt(key, defValue).set(value) sharedPreferences?.edit { putInt(key, value) }
} }
callChangeListener(value) callChangeListener(value)
notifyChanged() notifyChanged()

View file

@ -4,7 +4,7 @@ import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import androidx.preference.Preference import androidx.core.content.edit
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
open class ListMatPreference @JvmOverloads constructor( open class ListMatPreference @JvmOverloads constructor(
@ -15,8 +15,6 @@ open class ListMatPreference @JvmOverloads constructor(
) : ) :
MatPreference(activity, context, attrs) { MatPreference(activity, context, attrs) {
var sharedPref: String? = null
var otherPref: Preference? = null
var entryValues: List<String> = emptyList() var entryValues: List<String> = emptyList()
var entriesRes: Array<Int> var entriesRes: Array<Int>
get() = emptyArray() get() = emptyArray()
@ -30,7 +28,7 @@ open class ListMatPreference @JvmOverloads constructor(
} }
override var customSummaryProvider: SummaryProvider<MatPreference>? = SummaryProvider<MatPreference> { override var customSummaryProvider: SummaryProvider<MatPreference>? = SummaryProvider<MatPreference> {
val index = entryValues.indexOf(prefs.getStringPref(key, defValue).get()) val index = entryValues.indexOf(sharedPreferences?.getString(key, defValue))
if (entries.isEmpty() || index == -1) "" if (entries.isEmpty() || index == -1) ""
else entries[index] else entries[index]
} }
@ -43,32 +41,12 @@ open class ListMatPreference @JvmOverloads constructor(
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
open fun MaterialAlertDialogBuilder.setListItems() { open fun MaterialAlertDialogBuilder.setListItems() {
val default = entryValues.indexOf( val default = entryValues.indexOf(sharedPreferences?.getString(key, defValue) ?: defValue)
if (sharedPref != null) {
val settings = context.getSharedPreferences(sharedPref, Context.MODE_PRIVATE)
settings.getString(key, "")
} else prefs.getStringPref(key, defValue).get(),
)
setSingleChoiceItems(entries.toTypedArray(), default) { dialog, pos -> setSingleChoiceItems(entries.toTypedArray(), default) { dialog, pos ->
val value = entryValues[pos] val value = entryValues[pos]
if (sharedPref != null) { sharedPreferences?.edit { putString(key, value) }
val oldDef = if (default > -1) entries[default] else "" this@ListMatPreference.summary = this@ListMatPreference.summary
val settings = context.getSharedPreferences(sharedPref, Context.MODE_PRIVATE) callChangeListener(value)
val edit = settings.edit()
edit.putString(key, value)
edit.apply()
otherPref?.callChangeListener(value)
if (oldDef == otherPref?.summary || otherPref?.summary.isNullOrEmpty()) otherPref?.summary =
entries[pos]
else otherPref?.summary = otherPref?.summary?.toString()?.replace(
oldDef,
entries[pos],
) ?: entries[pos]
} else {
prefs.getStringPref(key, defValue).set(value)
this@ListMatPreference.summary = this@ListMatPreference.summary
callChangeListener(value)
}
dialog.dismiss() dialog.dismiss()
} }
} }

View file

@ -6,6 +6,7 @@ import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.AppCompatCheckedTextView import androidx.appcompat.widget.AppCompatCheckedTextView
import androidx.core.content.edit
import androidx.core.view.children import androidx.core.view.children
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import eu.kanade.tachiyomi.util.system.disableItems import eu.kanade.tachiyomi.util.system.disableItems
@ -43,7 +44,7 @@ class MultiListMatPreference @JvmOverloads constructor(
} }
override var customSummaryProvider: SummaryProvider<MatPreference>? = SummaryProvider<MatPreference> { override var customSummaryProvider: SummaryProvider<MatPreference>? = SummaryProvider<MatPreference> {
var values = prefs.getStringSet(key, defValue).get().mapNotNull { value -> var values = (sharedPreferences?.getStringSet(key, defValue) ?: defValue).mapNotNull { value ->
entryValues.indexOf(value).takeUnless { it == -1 } entryValues.indexOf(value).takeUnless { it == -1 }
}.toIntArray().sorted().map { entries[it] } }.toIntArray().sorted().map { entries[it] }
allSelectionRes?.let { allRes -> allSelectionRes?.let { allRes ->
@ -63,7 +64,7 @@ class MultiListMatPreference @JvmOverloads constructor(
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
override fun MaterialAlertDialogBuilder.setListItems() { override fun MaterialAlertDialogBuilder.setListItems() {
val set = prefs.getStringSet(key, defValue).get() val set = sharedPreferences?.getStringSet(key, defValue) ?: defValue
val items = if (allSelectionRes != null) { val items = if (allSelectionRes != null) {
if (showAllLast) entries + listOf(context.getString(allSelectionRes!!)) if (showAllLast) entries + listOf(context.getString(allSelectionRes!!))
else listOf(context.getString(allSelectionRes!!)) + entries else listOf(context.getString(allSelectionRes!!)) + entries
@ -83,7 +84,7 @@ class MultiListMatPreference @JvmOverloads constructor(
entryValues.getOrNull(it - if (allSelectionRes != null && !showAllLast) 1 else 0) entryValues.getOrNull(it - if (allSelectionRes != null && !showAllLast) 1 else 0)
}.toSet() }.toSet()
if (allSelectionRes != null && !allIsAlwaysSelected && selected[allPos]) value = emptySet() if (allSelectionRes != null && !allIsAlwaysSelected && selected[allPos]) value = emptySet()
prefs.getStringSet(key, emptySet()).set(value) sharedPreferences?.edit { putStringSet(key, value) }
callChangeListener(value) callChangeListener(value)
notifyChanged() notifyChanged()
} }

View file

@ -4,9 +4,11 @@ import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import androidx.core.content.edit
import androidx.core.text.buildSpannedString import androidx.core.text.buildSpannedString
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.setting.defaultValue
import eu.kanade.tachiyomi.util.system.setTriStateItems import eu.kanade.tachiyomi.util.system.setTriStateItems
import eu.kanade.tachiyomi.widget.TriStateCheckBox import eu.kanade.tachiyomi.widget.TriStateCheckBox
@ -36,30 +38,36 @@ class TriStateListPreference @JvmOverloads constructor(
} }
private var defValue: Set<String> = emptySet() private var defValue: Set<String> = emptySet()
private var exlDefValue: Set<String> = emptySet()
override fun onSetInitialValue(defaultValue: Any?) { override fun onSetInitialValue(defaultValue: Any?) {
super.onSetInitialValue(defaultValue) super.onSetInitialValue(defaultValue)
defValue = (defaultValue as? Collection<*>).orEmpty().mapNotNull { it as? String }.toSet() defValue = when (defaultValue) {
is Pair<*, *> -> {
val firstCollection = (defaultValue.first as? Collection<*>).orEmpty()
val secondCollection = (defaultValue.second as? Collection<*>).orEmpty()
exlDefValue = secondCollection.mapNotNull { it as? String }.toSet()
firstCollection.mapNotNull { it as? String }.toSet()
}
else -> (defaultValue as? Collection<*>).orEmpty().mapNotNull { it as? String }.toSet()
}
} }
override var customSummaryProvider: SummaryProvider<MatPreference>? = SummaryProvider<MatPreference> { override var customSummaryProvider: SummaryProvider<MatPreference>? = SummaryProvider<MatPreference> {
var includedStrings = prefs.getStringSet(key, defValue).get().mapNotNull { value -> var includedStrings = sharedPreferences?.getStringSet(key, defValue)?.mapNotNull { value ->
entryValues.indexOf(value).takeUnless { it == -1 } entryValues.indexOf(value).takeUnless { it == -1 }
}.toIntArray().sorted().map { entries[it] } }?.toIntArray()?.sorted()?.map { entries[it] } ?: return@SummaryProvider ""
allSelectionRes?.let { allRes -> allSelectionRes?.let { allRes ->
when { when {
includedStrings.isEmpty() -> includedStrings = listOf(context.getString(allRes)) includedStrings.isEmpty() -> includedStrings = listOf(context.getString(allRes))
allIsAlwaysSelected && !showAllLast -> allIsAlwaysSelected && !showAllLast ->
includedStrings = includedStrings = listOf(context.getString(allRes)) + includedStrings
listOf(context.getString(allRes)) + includedStrings
allIsAlwaysSelected -> includedStrings = includedStrings + context.getString(allRes) allIsAlwaysSelected -> includedStrings = includedStrings + context.getString(allRes)
} }
} }
val excludedStrings = excludeKey?.let { val excludedStrings = excludeKey?.let { excludeKey ->
prefs.getStringSet(it, defValue).get().mapNotNull { value -> sharedPreferences?.getStringSet(excludeKey, exlDefValue)?.mapNotNull { value ->
entryValues.indexOf(value).takeUnless { entryValues.indexOf(value).takeUnless { it == -1 }
it == -1
}
} }
}?.toIntArray()?.sorted()?.map { entries[it] }?.takeIf { it.isNotEmpty() } }?.toIntArray()?.sorted()?.map { entries[it] }?.takeIf { it.isNotEmpty() }
?: listOf(context.getString(R.string.none)) ?: listOf(context.getString(R.string.none))
@ -72,14 +80,14 @@ class TriStateListPreference @JvmOverloads constructor(
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
override fun MaterialAlertDialogBuilder.setListItems() { override fun MaterialAlertDialogBuilder.setListItems() {
val set = prefs.getStringSet(key, defValue).get() val set = sharedPreferences?.getStringSet(key, defValue) ?: defValue
val items = if (allSelectionRes != null) { val items = if (allSelectionRes != null) {
if (showAllLast) entries + listOf(context.getString(allSelectionRes!!)) if (showAllLast) entries + listOf(context.getString(allSelectionRes!!))
else listOf(context.getString(allSelectionRes!!)) + entries else listOf(context.getString(allSelectionRes!!)) + entries
} else entries } else entries
val allPos = if (showAllLast) items.size - 1 else 0 val allPos = if (showAllLast) items.size - 1 else 0
val excludedSet = excludeKey?.let { val excludedSet = excludeKey?.let {
prefs.getStringSet(it, defValue).get() sharedPreferences?.getStringSet(it, defValue) ?: defValue
}.orEmpty() }.orEmpty()
val allValue = intArrayOf( val allValue = intArrayOf(
if (set.isEmpty()) TriStateCheckBox.State.CHECKED.ordinal if (set.isEmpty()) TriStateCheckBox.State.CHECKED.ordinal
@ -99,8 +107,10 @@ class TriStateListPreference @JvmOverloads constructor(
var includedItems = set var includedItems = set
var excludedItems = excludedSet var excludedItems = excludedSet
setPositiveButton(android.R.string.ok) { _, _ -> setPositiveButton(android.R.string.ok) { _, _ ->
prefs.getStringSet(key, emptySet()).set(includedItems) sharedPreferences?.edit {
excludeKey?.let { prefs.getStringSet(it, emptySet()).set(excludedItems) } putStringSet(key, includedItems)
excludeKey?.let { putStringSet(it, excludedItems) }
}
callChangeListener(includedItems to excludedItems) callChangeListener(includedItems to excludedItems)
notifyChanged() notifyChanged()
} }