mirror of
https://git.mihon.tech/mihonapp/mihon
synced 2024-11-26 23:28:58 +03:00
PreferenceModel: Add subtitle provider to ListPreference (#8322)
* PreferenceModel: Add subtitle provider to ListPreference So that it's possible to avoid value formatting when needed * cleanups
This commit is contained in:
parent
9fbd3fe33f
commit
3e86cb094b
9 changed files with 44 additions and 60 deletions
|
@ -82,7 +82,7 @@ internal fun PreferenceItem(
|
|||
ListPreferenceWidget(
|
||||
value = value,
|
||||
title = item.title,
|
||||
subtitle = item.subtitle,
|
||||
subtitle = item.internalSubtitleProvider(value, item.entries),
|
||||
icon = item.icon,
|
||||
entries = item.entries,
|
||||
onValueChange = { newValue ->
|
||||
|
@ -98,7 +98,7 @@ internal fun PreferenceItem(
|
|||
ListPreferenceWidget(
|
||||
value = item.value,
|
||||
title = item.title,
|
||||
subtitle = item.subtitle,
|
||||
subtitle = item.subtitleProvider(item.value, item.entries),
|
||||
icon = item.icon,
|
||||
entries = item.entries,
|
||||
onValueChange = { scope.launch { item.onValueChanged(it) } },
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
package eu.kanade.presentation.more.settings
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import eu.kanade.domain.ui.model.AppTheme
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.core.preference.Preference as PreferenceData
|
||||
|
||||
|
@ -47,6 +51,8 @@ sealed class Preference {
|
|||
val pref: PreferenceData<T>,
|
||||
override val title: String,
|
||||
override val subtitle: String? = "%s",
|
||||
val subtitleProvider: @Composable (value: T, entries: Map<T, String>) -> String? =
|
||||
{ v, e -> subtitle?.format(e[v]) },
|
||||
override val icon: ImageVector? = null,
|
||||
override val enabled: Boolean = true,
|
||||
override val onValueChanged: suspend (newValue: T) -> Boolean = { true },
|
||||
|
@ -55,6 +61,10 @@ sealed class Preference {
|
|||
) : PreferenceItem<T>() {
|
||||
internal fun internalSet(newValue: Any) = pref.set(newValue as T)
|
||||
internal suspend fun internalOnValueChanged(newValue: Any) = onValueChanged(newValue as T)
|
||||
|
||||
@Composable
|
||||
internal fun internalSubtitleProvider(value: Any?, entries: Map<out Any?, String>) =
|
||||
subtitleProvider(value as T, entries as Map<T, String>)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -64,6 +74,8 @@ sealed class Preference {
|
|||
val value: String,
|
||||
override val title: String,
|
||||
override val subtitle: String? = "%s",
|
||||
val subtitleProvider: @Composable (value: String, entries: Map<String, String>) -> String? =
|
||||
{ v, e -> subtitle?.format(e[v]) },
|
||||
override val icon: ImageVector? = null,
|
||||
override val enabled: Boolean = true,
|
||||
override val onValueChanged: suspend (newValue: String) -> Boolean = { true },
|
||||
|
@ -78,7 +90,15 @@ sealed class Preference {
|
|||
data class MultiSelectListPreference(
|
||||
val pref: PreferenceData<Set<String>>,
|
||||
override val title: String,
|
||||
override val subtitle: String? = null,
|
||||
override val subtitle: String? = "%s",
|
||||
val subtitleProvider: @Composable (value: Set<String>, entries: Map<String, String>) -> String? = { v, e ->
|
||||
val combined = remember(v) {
|
||||
v.map { e[it] }
|
||||
.takeIf { it.isNotEmpty() }
|
||||
?.joinToString()
|
||||
} ?: stringResource(id = R.string.none)
|
||||
subtitle?.format(combined)
|
||||
},
|
||||
override val icon: ImageVector? = null,
|
||||
override val enabled: Boolean = true,
|
||||
override val onValueChanged: suspend (newValue: Set<String>) -> Boolean = { true },
|
||||
|
|
|
@ -72,7 +72,6 @@ class SettingsAppearanceScreen : SearchableSettings {
|
|||
Preference.PreferenceItem.ListPreference(
|
||||
pref = themeModePref,
|
||||
title = stringResource(R.string.pref_theme_mode),
|
||||
subtitle = "%s",
|
||||
entries = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
mapOf(
|
||||
ThemeMode.SYSTEM to stringResource(R.string.theme_system),
|
||||
|
@ -129,7 +128,6 @@ class SettingsAppearanceScreen : SearchableSettings {
|
|||
Preference.PreferenceItem.ListPreference(
|
||||
pref = uiPreferences.relativeTime(),
|
||||
title = stringResource(R.string.pref_relative_format),
|
||||
subtitle = "%s",
|
||||
entries = mapOf(
|
||||
0 to stringResource(R.string.off),
|
||||
2 to stringResource(R.string.pref_relative_time_short),
|
||||
|
@ -139,7 +137,6 @@ class SettingsAppearanceScreen : SearchableSettings {
|
|||
Preference.PreferenceItem.ListPreference(
|
||||
pref = uiPreferences.dateFormat(),
|
||||
title = stringResource(R.string.pref_date_format),
|
||||
subtitle = "%s",
|
||||
entries = DateFormats
|
||||
.associateWith {
|
||||
val formattedDate = UiPreferences.dateFormat(it).format(now)
|
||||
|
|
|
@ -10,7 +10,6 @@ import androidx.compose.runtime.ReadOnlyComposable
|
|||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.produceState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
|
@ -27,7 +26,6 @@ import eu.kanade.presentation.more.settings.Preference
|
|||
import eu.kanade.presentation.more.settings.widget.TriStateListDialog
|
||||
import eu.kanade.presentation.util.collectAsState
|
||||
import eu.kanade.tachiyomi.R
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
@ -101,9 +99,11 @@ class SettingsDownloadScreen : SearchableSettings {
|
|||
return Preference.PreferenceItem.ListPreference(
|
||||
pref = currentDirPref,
|
||||
title = stringResource(R.string.pref_download_directory),
|
||||
subtitle = remember(currentDir) {
|
||||
UniFile.fromUri(context, currentDir.toUri())?.filePath
|
||||
} ?: stringResource(R.string.invalid_location, currentDir),
|
||||
subtitleProvider = { value, _ ->
|
||||
remember(value) {
|
||||
UniFile.fromUri(context, value.toUri())?.filePath
|
||||
} ?: stringResource(R.string.invalid_location, value)
|
||||
},
|
||||
entries = mapOf(
|
||||
defaultDirPair,
|
||||
customDirEntryKey to stringResource(R.string.custom_dir),
|
||||
|
@ -173,25 +173,10 @@ class SettingsDownloadScreen : SearchableSettings {
|
|||
downloadPreferences: DownloadPreferences,
|
||||
categories: () -> List<Category>,
|
||||
): Preference.PreferenceItem.MultiSelectListPreference {
|
||||
val none = stringResource(R.string.none)
|
||||
val pref = downloadPreferences.removeExcludeCategories()
|
||||
val entries = categories().associate { it.id.toString() to it.visualName }
|
||||
val subtitle by produceState(initialValue = "") {
|
||||
pref.changes()
|
||||
.stateIn(this)
|
||||
.collect { mutable ->
|
||||
value = mutable
|
||||
.mapNotNull { id -> entries[id] }
|
||||
.sortedBy { entries.values.indexOf(it) }
|
||||
.joinToString()
|
||||
.ifEmpty { none }
|
||||
}
|
||||
}
|
||||
return Preference.PreferenceItem.MultiSelectListPreference(
|
||||
pref = pref,
|
||||
pref = downloadPreferences.removeExcludeCategories(),
|
||||
title = stringResource(R.string.pref_remove_exclude_categories),
|
||||
subtitle = subtitle,
|
||||
entries = entries,
|
||||
entries = categories().associate { it.id.toString() to it.visualName },
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,6 @@ class SettingsGeneralScreen : SearchableSettings {
|
|||
Preference.PreferenceItem.BasicListPreference(
|
||||
value = currentLanguage,
|
||||
title = stringResource(R.string.pref_app_language),
|
||||
subtitle = "%s",
|
||||
entries = langs,
|
||||
onValueChanged = { newValue ->
|
||||
currentLanguage = newValue
|
||||
|
|
|
@ -177,28 +177,6 @@ class SettingsLibraryScreen : SearchableSettings {
|
|||
|
||||
val libraryUpdateInterval by libraryUpdateIntervalPref.collectAsState()
|
||||
|
||||
val deviceRestrictionEntries = mapOf(
|
||||
DEVICE_ONLY_ON_WIFI to stringResource(R.string.connected_to_wifi),
|
||||
DEVICE_NETWORK_NOT_METERED to stringResource(R.string.network_not_metered),
|
||||
DEVICE_CHARGING to stringResource(R.string.charging),
|
||||
DEVICE_BATTERY_NOT_LOW to stringResource(R.string.battery_not_low),
|
||||
)
|
||||
val deviceRestrictions = libraryUpdateDeviceRestrictionPref.collectAsState()
|
||||
.value
|
||||
.sorted()
|
||||
.map { deviceRestrictionEntries.getOrElse(it) { it } }
|
||||
.let { if (it.isEmpty()) stringResource(R.string.none) else it.joinToString() }
|
||||
|
||||
val mangaRestrictionEntries = mapOf(
|
||||
MANGA_HAS_UNREAD to stringResource(R.string.pref_update_only_completely_read),
|
||||
MANGA_NON_READ to stringResource(R.string.pref_update_only_started),
|
||||
MANGA_NON_COMPLETED to stringResource(R.string.pref_update_only_non_completed),
|
||||
)
|
||||
val mangaRestrictions = libraryUpdateMangaRestrictionPref.collectAsState()
|
||||
.value
|
||||
.map { mangaRestrictionEntries.getOrElse(it) { it } }
|
||||
.let { if (it.isEmpty()) stringResource(R.string.none) else it.joinToString() }
|
||||
|
||||
val included by libraryUpdateCategoriesPref.collectAsState()
|
||||
val excluded by libraryUpdateCategoriesExcludePref.collectAsState()
|
||||
var showDialog by rememberSaveable { mutableStateOf(false) }
|
||||
|
@ -224,7 +202,6 @@ class SettingsLibraryScreen : SearchableSettings {
|
|||
Preference.PreferenceItem.ListPreference(
|
||||
pref = libraryUpdateIntervalPref,
|
||||
title = stringResource(R.string.pref_library_update_interval),
|
||||
subtitle = "%s",
|
||||
entries = mapOf(
|
||||
0 to stringResource(R.string.update_never),
|
||||
12 to stringResource(R.string.update_12hour),
|
||||
|
@ -242,8 +219,13 @@ class SettingsLibraryScreen : SearchableSettings {
|
|||
pref = libraryUpdateDeviceRestrictionPref,
|
||||
enabled = libraryUpdateInterval > 0,
|
||||
title = stringResource(R.string.pref_library_update_restriction),
|
||||
subtitle = stringResource(R.string.restrictions, deviceRestrictions),
|
||||
entries = deviceRestrictionEntries,
|
||||
subtitle = stringResource(R.string.restrictions),
|
||||
entries = mapOf(
|
||||
DEVICE_ONLY_ON_WIFI to stringResource(R.string.connected_to_wifi),
|
||||
DEVICE_NETWORK_NOT_METERED to stringResource(R.string.network_not_metered),
|
||||
DEVICE_CHARGING to stringResource(R.string.charging),
|
||||
DEVICE_BATTERY_NOT_LOW to stringResource(R.string.battery_not_low),
|
||||
),
|
||||
onValueChanged = {
|
||||
// Post to event looper to allow the preference to be updated.
|
||||
ContextCompat.getMainExecutor(context).execute { LibraryUpdateJob.setupTask(context) }
|
||||
|
@ -253,8 +235,11 @@ class SettingsLibraryScreen : SearchableSettings {
|
|||
Preference.PreferenceItem.MultiSelectListPreference(
|
||||
pref = libraryUpdateMangaRestrictionPref,
|
||||
title = stringResource(R.string.pref_library_update_manga_restriction),
|
||||
subtitle = mangaRestrictions,
|
||||
entries = mangaRestrictionEntries,
|
||||
entries = mapOf(
|
||||
MANGA_HAS_UNREAD to stringResource(R.string.pref_update_only_completely_read),
|
||||
MANGA_NON_READ to stringResource(R.string.pref_update_only_started),
|
||||
MANGA_NON_COMPLETED to stringResource(R.string.pref_update_only_non_completed),
|
||||
),
|
||||
),
|
||||
Preference.PreferenceItem.TextPreference(
|
||||
title = stringResource(R.string.categories),
|
||||
|
|
|
@ -49,7 +49,6 @@ class SettingsSecurityScreen : SearchableSettings {
|
|||
Preference.PreferenceItem.ListPreference(
|
||||
pref = securityPreferences.lockAppAfter(),
|
||||
title = stringResource(R.string.lock_when_idle),
|
||||
subtitle = "%s",
|
||||
enabled = authSupported && useAuth,
|
||||
entries = LockAfterValues
|
||||
.associateWith {
|
||||
|
@ -72,7 +71,6 @@ class SettingsSecurityScreen : SearchableSettings {
|
|||
Preference.PreferenceItem.ListPreference(
|
||||
pref = securityPreferences.secureScreen(),
|
||||
title = stringResource(R.string.secure_screen),
|
||||
subtitle = "%s",
|
||||
entries = SecurityPreferences.SecureScreenMode.values()
|
||||
.associateWith { stringResource(it.titleResId) },
|
||||
),
|
||||
|
|
|
@ -39,7 +39,7 @@ fun <T> ListPreferenceWidget(
|
|||
|
||||
TextPreferenceWidget(
|
||||
title = title,
|
||||
subtitle = subtitle?.format(entries[value]),
|
||||
subtitle = subtitle,
|
||||
icon = icon,
|
||||
onPreferenceClick = { showDialog(true) },
|
||||
)
|
||||
|
|
|
@ -33,7 +33,7 @@ fun MultiSelectListPreferenceWidget(
|
|||
|
||||
TextPreferenceWidget(
|
||||
title = preference.title,
|
||||
subtitle = preference.subtitle,
|
||||
subtitle = preference.subtitleProvider(values, preference.entries),
|
||||
icon = preference.icon,
|
||||
onPreferenceClick = { showDialog(true) },
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue