Migrate UiState prefs to repo (#2775)

This commit is contained in:
Phil Oliver 2025-08-18 17:44:44 -04:00 committed by GitHub
parent d574ba738d
commit 4be0cd7f81
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 31 additions and 75 deletions

View file

@ -18,12 +18,9 @@
package com.geeksville.mesh.model
import android.app.Application
import android.content.SharedPreferences
import android.net.Uri
import android.os.RemoteException
import androidx.appcompat.app.AppCompatDelegate
import androidx.compose.material3.SnackbarHostState
import androidx.core.content.edit
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
@ -42,6 +39,7 @@ import com.geeksville.mesh.Portnums
import com.geeksville.mesh.Position
import com.geeksville.mesh.R
import com.geeksville.mesh.android.Logging
import com.geeksville.mesh.android.prefs.UiPrefs
import com.geeksville.mesh.channel
import com.geeksville.mesh.channelSet
import com.geeksville.mesh.channelSettings
@ -67,7 +65,6 @@ import com.geeksville.mesh.ui.MainMenuAction
import com.geeksville.mesh.ui.node.components.NodeMenuAction
import com.geeksville.mesh.util.getShortDate
import com.geeksville.mesh.util.positionToMeter
import com.geeksville.mesh.util.toggleBooleanPreference
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
@ -199,17 +196,17 @@ constructor(
private val quickChatActionRepository: QuickChatActionRepository,
private val locationRepository: LocationRepository,
firmwareReleaseRepository: FirmwareReleaseRepository,
private val preferences: SharedPreferences,
private val uiPrefs: UiPrefs,
private val meshServiceNotifications: MeshServiceNotifications,
) : ViewModel(),
Logging {
private val _theme = MutableStateFlow(preferences.getInt("theme", AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM))
private val _theme = MutableStateFlow(uiPrefs.theme)
val theme: StateFlow<Int> = _theme.asStateFlow()
fun setTheme(theme: Int) {
_theme.value = theme
preferences.edit { putInt("theme", theme) }
uiPrefs.theme = theme
}
private val _lastTraceRouteTime = MutableStateFlow<Long?>(null)
@ -322,50 +319,50 @@ constructor(
private val nodeFilterText = MutableStateFlow("")
private val nodeSortOption =
MutableStateFlow(
NodeSortOption.entries.getOrElse(
preferences.getInt("node-sort-option", NodeSortOption.VIA_FAVORITE.ordinal),
) {
NodeSortOption.VIA_FAVORITE
},
)
private val includeUnknown = MutableStateFlow(preferences.getBoolean("include-unknown", false))
private val showDetails = MutableStateFlow(preferences.getBoolean("show-details", false))
private val onlyOnline = MutableStateFlow(preferences.getBoolean("only-online", false))
private val onlyDirect = MutableStateFlow(preferences.getBoolean("only-direct", false))
MutableStateFlow(NodeSortOption.entries.getOrElse(uiPrefs.nodeSortOption) { NodeSortOption.VIA_FAVORITE })
private val includeUnknown = MutableStateFlow(uiPrefs.includeUnknown)
private val showDetails = MutableStateFlow(uiPrefs.showDetails)
private val onlyOnline = MutableStateFlow(uiPrefs.onlyOnline)
private val onlyDirect = MutableStateFlow(uiPrefs.onlyDirect)
private val _showIgnored = MutableStateFlow(preferences.getBoolean("show-ignored", false))
private val _showIgnored = MutableStateFlow(uiPrefs.showIgnored)
val showIgnored: StateFlow<Boolean> = _showIgnored
private val _showQuickChat = MutableStateFlow(preferences.getBoolean("show-quick-chat", false))
private val _showQuickChat = MutableStateFlow(uiPrefs.showQuickChat)
val showQuickChat: StateFlow<Boolean> = _showQuickChat
private val _hasShownNotPairedWarning =
MutableStateFlow(preferences.getBoolean(HAS_SHOWN_NOT_PAIRED_WARNING_PREF, false))
private val _hasShownNotPairedWarning = MutableStateFlow(uiPrefs.hasShownNotPairedWarning)
val hasShownNotPairedWarning: StateFlow<Boolean> = _hasShownNotPairedWarning.asStateFlow()
fun suppressNoPairedWarning() {
_hasShownNotPairedWarning.value = true
preferences.edit { putBoolean(HAS_SHOWN_NOT_PAIRED_WARNING_PREF, true) }
uiPrefs.hasShownNotPairedWarning = true
}
fun toggleShowIgnored() = preferences.toggleBooleanPreference(_showIgnored, "show-ignored")
fun toggleShowIgnored() = toggle(_showIgnored) { uiPrefs.showIgnored = it }
fun toggleShowQuickChat() = preferences.toggleBooleanPreference(_showQuickChat, "show-quick-chat")
fun toggleShowQuickChat() = toggle(_showQuickChat) { uiPrefs.showQuickChat = it }
fun setSortOption(sort: NodeSortOption) {
nodeSortOption.value = sort
preferences.edit { putInt("node-sort-option", sort.ordinal) }
uiPrefs.nodeSortOption = sort.ordinal
}
fun toggleShowDetails() = preferences.toggleBooleanPreference(showDetails, "show-details")
fun toggleShowDetails() = toggle(showDetails) { uiPrefs.showDetails = it }
fun toggleIncludeUnknown() = preferences.toggleBooleanPreference(includeUnknown, "include-unknown")
fun toggleIncludeUnknown() = toggle(includeUnknown) { uiPrefs.includeUnknown = it }
fun toggleOnlyOnline() = preferences.toggleBooleanPreference(onlyOnline, "only-online")
fun toggleOnlyOnline() = toggle(onlyOnline) { uiPrefs.onlyOnline = it }
fun toggleOnlyDirect() = preferences.toggleBooleanPreference(onlyDirect, "only-direct")
fun toggleOnlyDirect() = toggle(onlyDirect) { uiPrefs.onlyDirect = it }
private fun toggle(state: MutableStateFlow<Boolean>, onChanged: (newValue: Boolean) -> Unit) {
(!state.value).let { toggled ->
state.update { toggled }
onChanged(toggled)
}
}
data class NodeFilterState(
val filterText: String,
@ -679,10 +676,6 @@ constructor(
if (unreadCount == 0) meshServiceNotifications.cancelMessageNotification(contact)
}
companion object {
const val HAS_SHOWN_NOT_PAIRED_WARNING_PREF = "has_shown_not_paired_warning"
}
// Connection state to our radio device
val connectionState
get() = radioConfigRepository.connectionState
@ -803,10 +796,7 @@ constructor(
viewModelScope.launch { setProvideLocation(getProvidePref()) }
}
private fun getProvidePref(): Boolean {
val value = preferences.getBoolean("provide-location-$myNodeNum", false)
return value
}
private fun getProvidePref(): Boolean = uiPrefs.shouldProvideNodeLocation(myNodeNum)
private val _provideLocation = MutableStateFlow(getProvidePref())
val provideLocation: StateFlow<Boolean>
@ -814,7 +804,7 @@ constructor(
fun setProvideLocation(value: Boolean) {
viewModelScope.launch {
preferences.edit { putBoolean("provide-location-$myNodeNum", value) }
uiPrefs.setShouldProvideNodeLocation(myNodeNum, value)
_provideLocation.value = value
if (value) {
meshService?.startProvideLocation()
@ -991,8 +981,7 @@ constructor(
// region Main menu actions logic
private val _showAppIntro: MutableStateFlow<Boolean> =
MutableStateFlow(preferences.getBoolean("app_intro_completed", false).not())
private val _showAppIntro: MutableStateFlow<Boolean> = MutableStateFlow(!uiPrefs.appIntroCompleted)
val showAppIntro: StateFlow<Boolean> = _showAppIntro.asStateFlow()
fun onMainMenuAction(action: MainMenuAction) {
@ -1006,7 +995,7 @@ constructor(
// endregion
fun onAppIntroCompleted() {
preferences.edit { putBoolean("app_intro_completed", true) }
uiPrefs.appIntroCompleted = true
_showAppIntro.update { false }
}
}

View file

@ -1,33 +0,0 @@
/*
* Copyright (c) 2025 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.geeksville.mesh.util
import android.content.SharedPreferences
import androidx.core.content.edit
import kotlinx.coroutines.flow.MutableStateFlow
fun SharedPreferences.toggleBooleanPreference(
state: MutableStateFlow<Boolean>,
key: String,
onChanged: (Boolean) -> Unit = {},
) {
val newValue = !state.value
state.value = newValue
this.edit { putBoolean(key, newValue) }
onChanged(newValue)
}