refactor: migrate preferences to DataStore and decouple core:domain for KMP (#4731)

This commit is contained in:
James Rich 2026-03-05 20:37:35 -06:00 committed by GitHub
parent 87fdaa26ff
commit b9b68d2779
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
113 changed files with 1790 additions and 1320 deletions

View file

@ -25,7 +25,7 @@ import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.meshtastic.core.prefs.filter.FilterPrefs
import org.meshtastic.core.repository.FilterPrefs
import org.meshtastic.core.repository.MessageFilter
import javax.inject.Inject
@ -46,8 +46,8 @@ class MessageFilterIntegrationTest {
@Test
fun filterPrefsIntegration() = runTest {
filterPrefs.filterEnabled = true
filterPrefs.filterWords = setOf("test", "spam")
filterPrefs.setFilterEnabled(true)
filterPrefs.setFilterWords(setOf("test", "spam"))
filterService.rebuildPatterns()
assertTrue(filterService.shouldFilter("this is a test message"))

View file

@ -44,8 +44,8 @@ import kotlinx.coroutines.withTimeout
import no.nordicsemi.kotlin.ble.core.android.AndroidEnvironment
import org.meshtastic.core.common.ContextServices
import org.meshtastic.core.database.DatabaseManager
import org.meshtastic.core.prefs.mesh.MeshPrefs
import org.meshtastic.core.prefs.meshlog.MeshLogPrefs
import org.meshtastic.core.repository.MeshLogPrefs
import org.meshtastic.core.repository.MeshPrefs
import javax.inject.Inject
import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.seconds
@ -114,7 +114,7 @@ open class MeshUtilApplication :
// Initialize DatabaseManager asynchronously with current device address so DAO consumers have an active DB
val entryPoint = EntryPointAccessors.fromApplication(this, AppEntryPoint::class.java)
applicationScope.launch { entryPoint.databaseManager().init(entryPoint.meshPrefs().deviceAddress) }
applicationScope.launch { entryPoint.databaseManager().init(entryPoint.meshPrefs().deviceAddress.value) }
}
override fun onTerminate() {

View file

@ -42,7 +42,6 @@ import org.jetbrains.compose.resources.StringResource
import org.jetbrains.compose.resources.getString
import org.meshtastic.core.analytics.platform.PlatformAnalytics
import org.meshtastic.core.data.repository.FirmwareReleaseRepository
import org.meshtastic.core.data.repository.MeshLogRepository
import org.meshtastic.core.database.entity.asDeviceVersion
import org.meshtastic.core.datastore.UiPreferencesDataSource
import org.meshtastic.core.model.MeshActivity
@ -52,6 +51,7 @@ import org.meshtastic.core.model.TracerouteMapAvailability
import org.meshtastic.core.model.evaluateTracerouteMapAvailability
import org.meshtastic.core.model.service.TracerouteResponse
import org.meshtastic.core.model.util.dispatchMeshtasticUri
import org.meshtastic.core.repository.MeshLogRepository
import org.meshtastic.core.repository.MeshServiceNotifications
import org.meshtastic.core.repository.NodeRepository
import org.meshtastic.core.repository.PacketRepository

View file

@ -51,8 +51,8 @@ import org.meshtastic.core.model.ConnectionState
import org.meshtastic.core.model.InterfaceId
import org.meshtastic.core.model.MeshActivity
import org.meshtastic.core.model.util.anonymize
import org.meshtastic.core.prefs.radio.RadioPrefs
import org.meshtastic.core.repository.RadioInterfaceService
import org.meshtastic.core.repository.RadioPrefs
import org.meshtastic.proto.Heartbeat
import org.meshtastic.proto.ToRadio
import javax.inject.Inject
@ -92,7 +92,7 @@ constructor(
val connectionError: SharedFlow<String> = _connectionError.asSharedFlow()
// Thread-safe StateFlow for tracking device address changes
private val _currentDeviceAddressFlow = MutableStateFlow(radioPrefs.devAddr)
private val _currentDeviceAddressFlow = MutableStateFlow(radioPrefs.devAddr.value)
override val currentDeviceAddressFlow: StateFlow<String?> = _currentDeviceAddressFlow.asStateFlow()
private val logSends = false
@ -192,7 +192,7 @@ constructor(
*/
override fun getDeviceAddress(): String? {
// If the user has unpaired our device, treat things as if we don't have one
var address = radioPrefs.devAddr
var address = radioPrefs.devAddr.value
// If we are running on the emulator we default to the mock interface, so we can have some data to show to the
// user
@ -352,7 +352,7 @@ constructor(
Logger.d { "Setting bonded device to ${address.anonymize}" }
// Stores the address if non-null, otherwise removes the pref
radioPrefs.devAddr = address
radioPrefs.setDevAddr(address)
_currentDeviceAddressFlow.value = address
// Force the service to reconnect

View file

@ -23,10 +23,10 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import org.meshtastic.core.model.MyNodeInfo
import org.meshtastic.core.model.Node
import org.meshtastic.core.prefs.ui.UiPrefs
import org.meshtastic.core.repository.NodeRepository
import org.meshtastic.core.repository.RadioConfigRepository
import org.meshtastic.core.repository.ServiceRepository
import org.meshtastic.core.repository.UiPrefs
import org.meshtastic.core.ui.viewmodel.stateInWhileSubscribed
import org.meshtastic.proto.LocalConfig
import javax.inject.Inject
@ -50,11 +50,11 @@ constructor(
val ourNodeInfo: StateFlow<Node?> = nodeRepository.ourNodeInfo
private val _hasShownNotPairedWarning = MutableStateFlow(uiPrefs.hasShownNotPairedWarning)
private val _hasShownNotPairedWarning = MutableStateFlow(uiPrefs.hasShownNotPairedWarning.value)
val hasShownNotPairedWarning: StateFlow<Boolean> = _hasShownNotPairedWarning.asStateFlow()
fun suppressNoPairedWarning() {
_hasShownNotPairedWarning.value = true
uiPrefs.hasShownNotPairedWarning = true
uiPrefs.setHasShownNotPairedWarning(true)
}
}

View file

@ -27,8 +27,8 @@ import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
import dagger.hilt.android.EntryPointAccessors
import dagger.hilt.components.SingletonComponent
import org.meshtastic.core.data.repository.MeshLogRepository
import org.meshtastic.core.prefs.meshlog.MeshLogPrefs
import org.meshtastic.core.repository.MeshLogPrefs
import org.meshtastic.core.repository.MeshLogRepository
@HiltWorker
class MeshLogCleanupWorker
@ -53,14 +53,14 @@ constructor(
@Suppress("TooGenericExceptionCaught")
override suspend fun doWork(): Result = try {
val retentionDays = meshLogPrefs.retentionDays
if (!meshLogPrefs.loggingEnabled) {
val retentionDays = meshLogPrefs.retentionDays.value
if (!meshLogPrefs.loggingEnabled.value) {
logger.i { "Skipping cleanup because mesh log storage is disabled" }
} else if (retentionDays == MeshLogPrefs.NEVER_CLEAR_RETENTION_DAYS) {
} else if (retentionDays == 0) {
logger.i { "Skipping cleanup because retention is set to never delete" }
} else {
val retentionLabel =
if (retentionDays == MeshLogPrefs.ONE_HOUR_RETENTION_DAYS) {
if (retentionDays == -1) {
"1 hour"
} else {
"$retentionDays days"