Decouple SettingsScreen from UiViewModel (#3137)

This commit is contained in:
Phil Oliver 2025-09-18 07:40:33 -04:00 committed by GitHub
parent 48da34ce1a
commit eedc3ef963
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 364 additions and 251 deletions

View file

@ -25,12 +25,15 @@ import com.geeksville.mesh.util.LanguageUtils
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import java.util.concurrent.ConcurrentHashMap
interface UiPrefs {
var lang: String
var theme: Int
val themeFlow: StateFlow<Int>
var appIntroCompleted: Boolean
val appIntroCompletedFlow: StateFlow<Boolean>
var hasShownNotPairedWarning: Boolean
var nodeSortOption: Int
var includeUnknown: Boolean
@ -45,19 +48,35 @@ interface UiPrefs {
fun setShouldProvideNodeLocation(nodeNum: Int, value: Boolean)
}
const val KEY_THEME = "theme"
const val KEY_APP_INTRO_COMPLETED = "app_intro_completed"
class UiPrefsImpl(private val prefs: SharedPreferences) : UiPrefs {
override var theme: Int by PrefDelegate(prefs, KEY_THEME, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
private var _themeFlow = MutableStateFlow(theme)
override val themeFlow = _themeFlow.asStateFlow()
override var appIntroCompleted: Boolean by PrefDelegate(prefs, KEY_APP_INTRO_COMPLETED, false)
private var _appIntroCompletedFlow = MutableStateFlow(appIntroCompleted)
override val appIntroCompletedFlow = _appIntroCompletedFlow.asStateFlow()
// Maps nodeNum to a flow for the for the "provide-location-nodeNum" pref
private val provideNodeLocationFlows = ConcurrentHashMap<Int, MutableStateFlow<Boolean>>()
private val sharedPreferencesListener =
SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
// Check if the changed key is one of our node location keys
provideNodeLocationFlows.keys.forEach { nodeNum ->
if (key == provideLocationKey(nodeNum)) {
val newValue = sharedPreferences.getBoolean(key, false)
provideNodeLocationFlows[nodeNum]?.tryEmit(newValue)
}
when (key) {
KEY_THEME -> _themeFlow.update { theme }
KEY_APP_INTRO_COMPLETED -> _appIntroCompletedFlow.update { appIntroCompleted }
// Check if the changed key is one of our node location keys
else ->
provideNodeLocationFlows.keys.forEach { nodeNum ->
if (key == provideLocationKey(nodeNum)) {
val newValue = sharedPreferences.getBoolean(key, false)
provideNodeLocationFlows[nodeNum]?.tryEmit(newValue)
}
}
}
}
@ -66,8 +85,6 @@ class UiPrefsImpl(private val prefs: SharedPreferences) : UiPrefs {
}
override var lang: String by PrefDelegate(prefs, "lang", LanguageUtils.SYSTEM_DEFAULT)
override var theme: Int by PrefDelegate(prefs, "theme", AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
override var appIntroCompleted: Boolean by PrefDelegate(prefs, "app_intro_completed", false)
override var hasShownNotPairedWarning: Boolean by PrefDelegate(prefs, "has_shown_not_paired_warning", false)
override var nodeSortOption: Int by PrefDelegate(prefs, "node-sort-option", NodeSortOption.VIA_FAVORITE.ordinal)
override var includeUnknown: Boolean by PrefDelegate(prefs, "include-unknown", false)