From 8a0fea7bc0da02b147f377368df29e903a05d94a Mon Sep 17 00:00:00 2001 From: WhiredPlanck Date: Sat, 16 Nov 2024 21:32:30 +0800 Subject: [PATCH] feat: integrate UI creation for PreferenceDelegate --- .../data/prefs/PreferenceDelegateEnum.kt | 13 ++++++ .../data/prefs/PreferenceDelegateFragment.kt | 28 ++++++++++++ .../data/prefs/PreferenceDelegateOwner.kt | 38 +++++++++++++++- .../data/prefs/PreferenceDelegateProvider.kt | 30 +++++++++++++ .../trime/data/prefs/PreferenceDelegateUi.kt | 44 +++++++++++++++++++ .../osfans/trime/ui/main/PrefMainActivity.kt | 3 ++ 6 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/com/osfans/trime/data/prefs/PreferenceDelegateEnum.kt create mode 100644 app/src/main/java/com/osfans/trime/data/prefs/PreferenceDelegateFragment.kt create mode 100644 app/src/main/java/com/osfans/trime/data/prefs/PreferenceDelegateProvider.kt create mode 100644 app/src/main/java/com/osfans/trime/data/prefs/PreferenceDelegateUi.kt diff --git a/app/src/main/java/com/osfans/trime/data/prefs/PreferenceDelegateEnum.kt b/app/src/main/java/com/osfans/trime/data/prefs/PreferenceDelegateEnum.kt new file mode 100644 index 0000000000..5a6dd23422 --- /dev/null +++ b/app/src/main/java/com/osfans/trime/data/prefs/PreferenceDelegateEnum.kt @@ -0,0 +1,13 @@ +/* + * SPDX-FileCopyrightText: 2015 - 2024 Rime community + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package com.osfans.trime.data.prefs + +import androidx.annotation.StringRes + +interface PreferenceDelegateEnum { + @get:StringRes + val stringRes: Int +} diff --git a/app/src/main/java/com/osfans/trime/data/prefs/PreferenceDelegateFragment.kt b/app/src/main/java/com/osfans/trime/data/prefs/PreferenceDelegateFragment.kt new file mode 100644 index 0000000000..7cacdd3370 --- /dev/null +++ b/app/src/main/java/com/osfans/trime/data/prefs/PreferenceDelegateFragment.kt @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2015 - 2024 Rime community + * SPDX-License-Identifier: GPL-3.0-or-later + */ +package com.osfans.trime.data.prefs + +import android.os.Bundle +import androidx.annotation.CallSuper +import androidx.preference.PreferenceScreen +import com.osfans.trime.ui.components.PaddingPreferenceFragment + +abstract class PreferenceDelegateFragment( + private val preferenceProvider: PreferenceDelegateProvider, +) : PaddingPreferenceFragment() { + open fun onPreferenceUiCreated(screen: PreferenceScreen) {} + + @CallSuper + override fun onCreatePreferences( + savedInstanceState: Bundle?, + rootKey: String?, + ) { + preferenceScreen = + preferenceManager.createPreferenceScreen(preferenceManager.context).also { screen -> + preferenceProvider.createUi(screen) + onPreferenceUiCreated(screen) + } + } +} diff --git a/app/src/main/java/com/osfans/trime/data/prefs/PreferenceDelegateOwner.kt b/app/src/main/java/com/osfans/trime/data/prefs/PreferenceDelegateOwner.kt index e83caf2191..80d97f46da 100644 --- a/app/src/main/java/com/osfans/trime/data/prefs/PreferenceDelegateOwner.kt +++ b/app/src/main/java/com/osfans/trime/data/prefs/PreferenceDelegateOwner.kt @@ -5,10 +5,13 @@ package com.osfans.trime.data.prefs import android.content.SharedPreferences +import androidx.annotation.StringRes +import androidx.preference.PreferenceScreen abstract class PreferenceDelegateOwner( protected val sharedPreferences: SharedPreferences, -) { + @StringRes val title: Int = 0, +) : PreferenceDelegateProvider() { protected fun int( key: String, defaultValue: Int, @@ -57,4 +60,37 @@ abstract class PreferenceDelegateOwner( override fun deserialize(raw: String) = enumValueOf(raw.uppercase()) }, ) + + // TODO: replace all [enum] with this + protected inline fun enum( + @StringRes title: Int, + key: String, + defaultValue: T, + noinline enableUiOn: (() -> Boolean)? = null, + ): PreferenceDelegate.SerializableDelegate where T : Enum, T : PreferenceDelegateEnum { + val serializer = + object : PreferenceDelegate.Serializer { + override fun serialize(t: T) = t.name + + override fun deserialize(raw: String) = enumValueOf(raw.uppercase()) + } + val entryValues = enumValues().toList() + val entryLabels = entryValues.map { it.stringRes } + val pref = serializable(key, defaultValue, serializer) + val ui = PreferenceDelegateUi.StringList(title, key, defaultValue, serializer, entryValues, entryLabels) + pref.register() + ui.registerUi() + return pref + } + + override fun createUi(screen: PreferenceScreen) { + val ctx = screen.context + preferenceDelegatesUi.forEach { + screen.addPreference( + it.createUi(ctx).apply { + isEnabled = it.isEnabled() + }, + ) + } + } } diff --git a/app/src/main/java/com/osfans/trime/data/prefs/PreferenceDelegateProvider.kt b/app/src/main/java/com/osfans/trime/data/prefs/PreferenceDelegateProvider.kt new file mode 100644 index 0000000000..ec8c949f46 --- /dev/null +++ b/app/src/main/java/com/osfans/trime/data/prefs/PreferenceDelegateProvider.kt @@ -0,0 +1,30 @@ +/* + * SPDX-FileCopyrightText: 2015 - 2024 Rime community + * SPDX-License-Identifier: GPL-3.0-or-later + */ +package com.osfans.trime.data.prefs + +import androidx.preference.PreferenceScreen + +abstract class PreferenceDelegateProvider { + private val _preferenceDelegates: MutableMap> = mutableMapOf() + + private val _preferenceDelegatesUi: MutableList> = mutableListOf() + + val preferenceDelegates: Map> + get() = _preferenceDelegates + + val preferenceDelegatesUi: List> + get() = _preferenceDelegatesUi + + open fun createUi(screen: PreferenceScreen) { + } + + fun PreferenceDelegateUi<*>.registerUi() { + _preferenceDelegatesUi.add(this) + } + + fun PreferenceDelegate<*>.register() { + _preferenceDelegates[key] = this + } +} diff --git a/app/src/main/java/com/osfans/trime/data/prefs/PreferenceDelegateUi.kt b/app/src/main/java/com/osfans/trime/data/prefs/PreferenceDelegateUi.kt new file mode 100644 index 0000000000..7053f925a0 --- /dev/null +++ b/app/src/main/java/com/osfans/trime/data/prefs/PreferenceDelegateUi.kt @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: 2015 - 2024 Rime community + * SPDX-License-Identifier: GPL-3.0-or-later + */ +package com.osfans.trime.data.prefs + +import android.content.Context +import androidx.annotation.StringRes +import androidx.preference.ListPreference +import androidx.preference.Preference + +abstract class PreferenceDelegateUi( + val key: String, + private val enableUiOn: (() -> Boolean)? = null, +) { + abstract fun createUi(context: Context): T + + fun isEnabled() = enableUiOn?.invoke() ?: true + + class StringList( + @StringRes + val title: Int, + key: String, + val defaultValue: T, + val serializer: PreferenceDelegate.Serializer, + val entryValues: List, + @StringRes + val entryLabels: List, + enableUiOn: (() -> Boolean)? = null, + ) : PreferenceDelegateUi(key, enableUiOn) { + override fun createUi(context: Context) = + ListPreference(context).apply { + key = this@StringList.key + isIconSpaceReserved = false + isSingleLineTitle = false + entryValues = this@StringList.entryValues.map { serializer.serialize(it) }.toTypedArray() + summaryProvider = ListPreference.SimpleSummaryProvider.getInstance() + setDefaultValue(serializer.serialize(defaultValue)) + setTitle(this@StringList.title) + entries = this@StringList.entryLabels.map { context.getString(it) }.toTypedArray() + setDialogTitle(this@StringList.title) + } + } +} diff --git a/app/src/main/java/com/osfans/trime/ui/main/PrefMainActivity.kt b/app/src/main/java/com/osfans/trime/ui/main/PrefMainActivity.kt index 939e72bf32..f665056195 100644 --- a/app/src/main/java/com/osfans/trime/ui/main/PrefMainActivity.kt +++ b/app/src/main/java/com/osfans/trime/ui/main/PrefMainActivity.kt @@ -105,6 +105,9 @@ class PrefMainActivity : AppCompatActivity() { m.isVisible = it } } + navHostFragment.navController.addOnDestinationChangedListener { _, dest, _ -> + dest.label?.let { viewModel.setToolbarTitle(it.toString()) } + } supportActionBar?.setDisplayHomeAsUpEnabled(true) if (SetupActivity.shouldSetup()) {