mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
refactor: migrate preferences to DataStore and decouple core:domain for KMP (#4731)
This commit is contained in:
parent
87fdaa26ff
commit
b9b68d2779
113 changed files with 1790 additions and 1320 deletions
|
|
@ -32,6 +32,7 @@ import kotlinx.coroutines.flow.update
|
|||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.meshtastic.core.common.BuildConfigProvider
|
||||
import org.meshtastic.core.common.database.DatabaseManager
|
||||
import org.meshtastic.core.domain.usecase.settings.ExportDataUseCase
|
||||
import org.meshtastic.core.domain.usecase.settings.IsOtaCapableUseCase
|
||||
import org.meshtastic.core.domain.usecase.settings.MeshLocationUseCase
|
||||
|
|
@ -43,11 +44,10 @@ import org.meshtastic.core.domain.usecase.settings.SetThemeUseCase
|
|||
import org.meshtastic.core.model.MyNodeInfo
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.model.RadioController
|
||||
import org.meshtastic.core.prefs.meshlog.MeshLogPrefs
|
||||
import org.meshtastic.core.prefs.ui.UiPrefs
|
||||
import org.meshtastic.core.repository.DatabaseManager
|
||||
import org.meshtastic.core.repository.MeshLogPrefs
|
||||
import org.meshtastic.core.repository.NodeRepository
|
||||
import org.meshtastic.core.repository.RadioConfigRepository
|
||||
import org.meshtastic.core.repository.UiPrefs
|
||||
import org.meshtastic.core.ui.viewmodel.stateInWhileSubscribed
|
||||
import org.meshtastic.proto.LocalConfig
|
||||
import java.io.BufferedWriter
|
||||
|
|
@ -126,10 +126,10 @@ constructor(
|
|||
}
|
||||
|
||||
// MeshLog retention period (bounded by MeshLogPrefsImpl constants)
|
||||
private val _meshLogRetentionDays = MutableStateFlow(meshLogPrefs.retentionDays)
|
||||
private val _meshLogRetentionDays = MutableStateFlow(meshLogPrefs.retentionDays.value)
|
||||
val meshLogRetentionDays: StateFlow<Int> = _meshLogRetentionDays.asStateFlow()
|
||||
|
||||
private val _meshLogLoggingEnabled = MutableStateFlow(meshLogPrefs.loggingEnabled)
|
||||
private val _meshLogLoggingEnabled = MutableStateFlow(meshLogPrefs.loggingEnabled.value)
|
||||
val meshLogLoggingEnabled: StateFlow<Boolean> = _meshLogLoggingEnabled.asStateFlow()
|
||||
|
||||
fun setMeshLogRetentionDays(days: Int) {
|
||||
|
|
|
|||
|
|
@ -36,13 +36,13 @@ import kotlinx.coroutines.withContext
|
|||
import org.meshtastic.core.common.util.nowInstant
|
||||
import org.meshtastic.core.common.util.toDate
|
||||
import org.meshtastic.core.common.util.toInstant
|
||||
import org.meshtastic.core.data.repository.MeshLogRepository
|
||||
import org.meshtastic.core.database.entity.MeshLog
|
||||
import org.meshtastic.core.database.entity.Packet
|
||||
import org.meshtastic.core.model.getTracerouteResponse
|
||||
import org.meshtastic.core.model.util.decodeOrNull
|
||||
import org.meshtastic.core.model.util.toReadableString
|
||||
import org.meshtastic.core.prefs.meshlog.MeshLogPrefs
|
||||
import org.meshtastic.core.repository.MeshLogPrefs
|
||||
import org.meshtastic.core.repository.MeshLogRepository
|
||||
import org.meshtastic.core.repository.NodeRepository
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.debug_clear
|
||||
|
|
@ -230,10 +230,10 @@ constructor(
|
|||
.mapLatest { logs -> withContext(Dispatchers.Default) { toUiState(logs) } }
|
||||
.stateInWhileSubscribed(initialValue = persistentListOf())
|
||||
|
||||
private val _retentionDays = MutableStateFlow(meshLogPrefs.retentionDays)
|
||||
private val _retentionDays = MutableStateFlow(meshLogPrefs.retentionDays.value)
|
||||
val retentionDays: StateFlow<Int> = _retentionDays.asStateFlow()
|
||||
|
||||
private val _loggingEnabled = MutableStateFlow(meshLogPrefs.loggingEnabled)
|
||||
private val _loggingEnabled = MutableStateFlow(meshLogPrefs.loggingEnabled.value)
|
||||
val loggingEnabled: StateFlow<Boolean> = _loggingEnabled.asStateFlow()
|
||||
|
||||
// --- Managers ---
|
||||
|
|
@ -265,18 +265,18 @@ constructor(
|
|||
|
||||
fun setRetentionDays(days: Int) {
|
||||
val clamped = days.coerceIn(MeshLogPrefs.MIN_RETENTION_DAYS, MeshLogPrefs.MAX_RETENTION_DAYS)
|
||||
meshLogPrefs.retentionDays = clamped
|
||||
meshLogPrefs.setRetentionDays(clamped)
|
||||
_retentionDays.value = clamped
|
||||
viewModelScope.launch { meshLogRepository.deleteLogsOlderThan(clamped) }
|
||||
}
|
||||
|
||||
fun setLoggingEnabled(enabled: Boolean) {
|
||||
meshLogPrefs.loggingEnabled = enabled
|
||||
meshLogPrefs.setLoggingEnabled(enabled)
|
||||
_loggingEnabled.value = enabled
|
||||
if (!enabled) {
|
||||
viewModelScope.launch { meshLogRepository.deleteAll() }
|
||||
} else {
|
||||
viewModelScope.launch { meshLogRepository.deleteLogsOlderThan(meshLogPrefs.retentionDays) }
|
||||
viewModelScope.launch { meshLogRepository.deleteLogsOlderThan(meshLogPrefs.retentionDays.value) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
|||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import org.meshtastic.core.prefs.filter.FilterPrefs
|
||||
import org.meshtastic.core.repository.FilterPrefs
|
||||
import org.meshtastic.core.repository.MessageFilter
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -33,32 +33,32 @@ constructor(
|
|||
private val messageFilter: MessageFilter,
|
||||
) : ViewModel() {
|
||||
|
||||
private val _filterEnabled = MutableStateFlow(filterPrefs.filterEnabled)
|
||||
private val _filterEnabled = MutableStateFlow(filterPrefs.filterEnabled.value)
|
||||
val filterEnabled: StateFlow<Boolean> = _filterEnabled.asStateFlow()
|
||||
|
||||
private val _filterWords = MutableStateFlow(filterPrefs.filterWords.toList().sorted())
|
||||
private val _filterWords = MutableStateFlow(filterPrefs.filterWords.value.toList().sorted())
|
||||
val filterWords: StateFlow<List<String>> = _filterWords.asStateFlow()
|
||||
|
||||
fun setFilterEnabled(enabled: Boolean) {
|
||||
filterPrefs.filterEnabled = enabled
|
||||
filterPrefs.setFilterEnabled(enabled)
|
||||
_filterEnabled.value = enabled
|
||||
}
|
||||
|
||||
fun addFilterWord(word: String) {
|
||||
if (word.isBlank()) return
|
||||
val trimmed = word.trim()
|
||||
val current = filterPrefs.filterWords.toMutableSet()
|
||||
val current = filterPrefs.filterWords.value.toMutableSet()
|
||||
if (current.add(trimmed)) {
|
||||
filterPrefs.filterWords = current
|
||||
filterPrefs.setFilterWords(current)
|
||||
_filterWords.value = current.toList().sorted()
|
||||
messageFilter.rebuildPatterns()
|
||||
}
|
||||
}
|
||||
|
||||
fun removeFilterWord(word: String) {
|
||||
val current = filterPrefs.filterWords.toMutableSet()
|
||||
val current = filterPrefs.filterWords.value.toMutableSet()
|
||||
if (current.remove(word)) {
|
||||
filterPrefs.filterWords = current
|
||||
filterPrefs.setFilterWords(current)
|
||||
_filterWords.value = current.toList().sorted()
|
||||
messageFilter.rebuildPatterns()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,9 +58,9 @@ import org.meshtastic.core.model.MyNodeInfo
|
|||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.model.Position
|
||||
import org.meshtastic.core.navigation.SettingsRoutes
|
||||
import org.meshtastic.core.prefs.analytics.AnalyticsPrefs
|
||||
import org.meshtastic.core.prefs.homoglyph.HomoglyphPrefs
|
||||
import org.meshtastic.core.prefs.map.MapConsentPrefs
|
||||
import org.meshtastic.core.repository.AnalyticsPrefs
|
||||
import org.meshtastic.core.repository.HomoglyphPrefs
|
||||
import org.meshtastic.core.repository.MapConsentPrefs
|
||||
import org.meshtastic.core.repository.NodeRepository
|
||||
import org.meshtastic.core.repository.PacketRepository
|
||||
import org.meshtastic.core.repository.RadioConfigRepository
|
||||
|
|
@ -131,13 +131,13 @@ constructor(
|
|||
private val adminActionsUseCase: AdminActionsUseCase,
|
||||
private val processRadioResponseUseCase: ProcessRadioResponseUseCase,
|
||||
) : ViewModel() {
|
||||
var analyticsAllowedFlow = analyticsPrefs.getAnalyticsAllowedChangesFlow()
|
||||
var analyticsAllowedFlow = analyticsPrefs.analyticsAllowed
|
||||
|
||||
fun toggleAnalyticsAllowed() {
|
||||
toggleAnalyticsUseCase()
|
||||
}
|
||||
|
||||
val homoglyphEncodingEnabledFlow = homoglyphEncodingPrefs.getHomoglyphEncodingEnabledChangesFlow()
|
||||
val homoglyphEncodingEnabledFlow = homoglyphEncodingPrefs.homoglyphEncodingEnabled
|
||||
|
||||
fun toggleHomoglyphCharactersEncodingEnabled() {
|
||||
toggleHomoglyphEncodingUseCase()
|
||||
|
|
|
|||
|
|
@ -61,7 +61,8 @@ fun MQTTConfigScreen(viewModel: RadioConfigViewModel = hiltViewModel(), onBack:
|
|||
|
||||
val currentMapReportSettings = formState.value.map_report_settings ?: ModuleConfig.MapReportSettings()
|
||||
if (!(currentMapReportSettings.should_report_location ?: false)) {
|
||||
val settings = currentMapReportSettings.copy(should_report_location = viewModel.shouldReportLocation(destNum))
|
||||
val settings =
|
||||
currentMapReportSettings.copy(should_report_location = viewModel.shouldReportLocation(destNum).value)
|
||||
formState.value = formState.value.copy(map_report_settings = settings)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import org.junit.After
|
|||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.meshtastic.core.common.BuildConfigProvider
|
||||
import org.meshtastic.core.common.database.DatabaseManager
|
||||
import org.meshtastic.core.domain.usecase.settings.ExportDataUseCase
|
||||
import org.meshtastic.core.domain.usecase.settings.IsOtaCapableUseCase
|
||||
import org.meshtastic.core.domain.usecase.settings.MeshLocationUseCase
|
||||
|
|
@ -39,11 +40,10 @@ import org.meshtastic.core.domain.usecase.settings.SetMeshLogSettingsUseCase
|
|||
import org.meshtastic.core.domain.usecase.settings.SetProvideLocationUseCase
|
||||
import org.meshtastic.core.domain.usecase.settings.SetThemeUseCase
|
||||
import org.meshtastic.core.model.RadioController
|
||||
import org.meshtastic.core.prefs.meshlog.MeshLogPrefs
|
||||
import org.meshtastic.core.prefs.ui.UiPrefs
|
||||
import org.meshtastic.core.repository.DatabaseManager
|
||||
import org.meshtastic.core.repository.MeshLogPrefs
|
||||
import org.meshtastic.core.repository.NodeRepository
|
||||
import org.meshtastic.core.repository.RadioConfigRepository
|
||||
import org.meshtastic.core.repository.UiPrefs
|
||||
import org.robolectric.annotation.Config
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ import org.junit.After
|
|||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
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
|
||||
import org.meshtastic.core.repository.NodeRepository
|
||||
import org.meshtastic.core.ui.util.AlertManager
|
||||
|
||||
|
|
@ -56,8 +56,8 @@ class DebugViewModelTest {
|
|||
every { meshLogRepository.getAllLogs() } returns flowOf(emptyList())
|
||||
every { nodeRepository.myNodeInfo } returns MutableStateFlow(null)
|
||||
every { nodeRepository.nodeDBbyNum } returns MutableStateFlow(emptyMap())
|
||||
every { meshLogPrefs.retentionDays } returns 7
|
||||
every { meshLogPrefs.loggingEnabled } returns true
|
||||
every { meshLogPrefs.retentionDays.value } returns 7
|
||||
every { meshLogPrefs.loggingEnabled.value } returns true
|
||||
|
||||
viewModel =
|
||||
DebugViewModel(
|
||||
|
|
@ -77,7 +77,7 @@ class DebugViewModelTest {
|
|||
fun `setRetentionDays updates prefs and deletes old logs`() = runTest {
|
||||
viewModel.setRetentionDays(14)
|
||||
|
||||
verify { meshLogPrefs.retentionDays = 14 }
|
||||
verify { meshLogPrefs.setRetentionDays(14) }
|
||||
coVerify { meshLogRepository.deleteLogsOlderThan(14) }
|
||||
assertEquals(14, viewModel.retentionDays.value)
|
||||
}
|
||||
|
|
@ -86,7 +86,7 @@ class DebugViewModelTest {
|
|||
fun `setLoggingEnabled false deletes all logs`() = runTest {
|
||||
viewModel.setLoggingEnabled(false)
|
||||
|
||||
verify { meshLogPrefs.loggingEnabled = false }
|
||||
verify { meshLogPrefs.setLoggingEnabled(false) }
|
||||
coVerify { meshLogRepository.deleteAll() }
|
||||
assertEquals(false, viewModel.loggingEnabled.value)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import io.mockk.verify
|
|||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.meshtastic.core.prefs.filter.FilterPrefs
|
||||
import org.meshtastic.core.repository.FilterPrefs
|
||||
import org.meshtastic.core.repository.MessageFilter
|
||||
|
||||
class FilterSettingsViewModelTest {
|
||||
|
|
@ -34,8 +34,8 @@ class FilterSettingsViewModelTest {
|
|||
|
||||
@Before
|
||||
fun setUp() {
|
||||
every { filterPrefs.filterEnabled } returns true
|
||||
every { filterPrefs.filterWords } returns setOf("apple", "banana")
|
||||
every { filterPrefs.filterEnabled.value } returns true
|
||||
every { filterPrefs.filterWords.value } returns setOf("apple", "banana")
|
||||
|
||||
viewModel = FilterSettingsViewModel(filterPrefs = filterPrefs, messageFilter = messageFilter)
|
||||
}
|
||||
|
|
@ -43,7 +43,7 @@ class FilterSettingsViewModelTest {
|
|||
@Test
|
||||
fun `setFilterEnabled updates prefs and state`() {
|
||||
viewModel.setFilterEnabled(false)
|
||||
verify { filterPrefs.filterEnabled = false }
|
||||
verify { filterPrefs.setFilterEnabled(false) }
|
||||
assertEquals(false, viewModel.filterEnabled.value)
|
||||
}
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ class FilterSettingsViewModelTest {
|
|||
fun `addFilterWord updates prefs and rebuilds patterns`() {
|
||||
viewModel.addFilterWord("cherry")
|
||||
|
||||
verify { filterPrefs.filterWords = any() }
|
||||
verify { filterPrefs.setFilterWords(any()) }
|
||||
verify { messageFilter.rebuildPatterns() }
|
||||
assertEquals(listOf("apple", "banana", "cherry"), viewModel.filterWords.value)
|
||||
}
|
||||
|
|
@ -60,7 +60,7 @@ class FilterSettingsViewModelTest {
|
|||
fun `removeFilterWord updates prefs and rebuilds patterns`() {
|
||||
viewModel.removeFilterWord("apple")
|
||||
|
||||
verify { filterPrefs.filterWords = any() }
|
||||
verify { filterPrefs.setFilterWords(any()) }
|
||||
verify { messageFilter.rebuildPatterns() }
|
||||
assertEquals(listOf("banana"), viewModel.filterWords.value)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,9 +45,9 @@ import org.meshtastic.core.domain.usecase.settings.RadioResponseResult
|
|||
import org.meshtastic.core.domain.usecase.settings.ToggleAnalyticsUseCase
|
||||
import org.meshtastic.core.domain.usecase.settings.ToggleHomoglyphEncodingUseCase
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.prefs.analytics.AnalyticsPrefs
|
||||
import org.meshtastic.core.prefs.homoglyph.HomoglyphPrefs
|
||||
import org.meshtastic.core.prefs.map.MapConsentPrefs
|
||||
import org.meshtastic.core.repository.AnalyticsPrefs
|
||||
import org.meshtastic.core.repository.HomoglyphPrefs
|
||||
import org.meshtastic.core.repository.MapConsentPrefs
|
||||
import org.meshtastic.core.repository.NodeRepository
|
||||
import org.meshtastic.core.repository.PacketRepository
|
||||
import org.meshtastic.core.repository.RadioConfigRepository
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue