From b98e5331230c35eb462d74421ff0f9df81ae90bc Mon Sep 17 00:00:00 2001 From: Phil Oliver <3497406+poliver@users.noreply.github.com> Date: Tue, 23 Sep 2025 05:51:03 -0400 Subject: [PATCH] Modularize prefs classes (#3171) --- .../geeksville/mesh/MeshUtilApplication.kt | 2 +- .../mesh/android/GeeksvilleApplication.kt | 2 +- .../geeksville/mesh/ui/map/MapViewModel.kt | 2 +- .../geeksville/mesh/MeshUtilApplication.kt | 2 +- .../mesh/android/GeeksvilleApplication.kt | 2 +- ...PreferencesCustomTileProviderRepository.kt | 2 +- .../geeksville/mesh/ui/map/MapViewModel.kt | 4 +- .../java/com/geeksville/mesh/MainActivity.kt | 2 +- .../mesh/android/prefs/PrefsModule.kt | 170 ------------------ .../geeksville/mesh/model/MetricsViewModel.kt | 2 +- .../java/com/geeksville/mesh/model/UIState.kt | 2 +- .../repository/radio/RadioInterfaceService.kt | 6 +- .../geeksville/mesh/service/MeshService.kt | 4 +- .../mesh/ui/common/EmojiPickerViewModel.kt | 2 +- .../ui/connections/ConnectionsViewModel.kt | 2 +- .../mesh/ui/map/BaseMapViewModel.kt | 2 +- .../mesh/ui/settings/SettingsViewModel.kt | 2 +- .../ui/settings/radio/RadioConfigViewModel.kt | 4 +- core/prefs/build.gradle.kts | 7 +- .../core/prefs/di}/GoogleMapsModule.kt | 29 +-- .../core/prefs/map}/GoogleMapsPrefs.kt | 10 +- .../core}/prefs/NullableStringPrefDelegate.kt | 4 +- .../meshtastic/core}/prefs/PrefDelegate.kt | 9 +- .../core}/prefs/StringSetPrefDelegate.kt | 4 +- .../core/prefs/analytics}/AnalyticsPrefs.kt | 16 +- .../meshtastic/core/prefs/di/PrefsModule.kt | 163 +++++++++++++++++ .../core/prefs/emoji}/CustomEmojiPrefs.kt | 10 +- .../core/prefs/map}/MapConsentPrefs.kt | 9 +- .../meshtastic/core/prefs/map}/MapPrefs.kt | 9 +- .../core/prefs/map}/MapTileProviderPrefs.kt | 10 +- .../meshtastic/core/prefs/mesh}/MeshPrefs.kt | 9 +- .../core/prefs/radio}/RadioPrefs.kt | 9 +- .../org/meshtastic/core/prefs/ui}/UiPrefs.kt | 12 +- 33 files changed, 290 insertions(+), 234 deletions(-) delete mode 100644 app/src/main/java/com/geeksville/mesh/android/prefs/PrefsModule.kt rename {app/src/google/java/com/geeksville/mesh/android/prefs => core/prefs/src/google/kotlin/org/meshtastic/core/prefs/di}/GoogleMapsModule.kt (61%) rename {app/src/google/java/com/geeksville/mesh/android/prefs => core/prefs/src/google/kotlin/org/meshtastic/core/prefs/map}/GoogleMapsPrefs.kt (77%) rename {app/src/main/java/com/geeksville/mesh/android => core/prefs/src/main/kotlin/org/meshtastic/core}/prefs/NullableStringPrefDelegate.kt (95%) rename {app/src/main/java/com/geeksville/mesh/android => core/prefs/src/main/kotlin/org/meshtastic/core}/prefs/PrefDelegate.kt (91%) rename {app/src/main/java/com/geeksville/mesh/android => core/prefs/src/main/kotlin/org/meshtastic/core}/prefs/StringSetPrefDelegate.kt (94%) rename {app/src/main/java/com/geeksville/mesh/android/prefs => core/prefs/src/main/kotlin/org/meshtastic/core/prefs/analytics}/AnalyticsPrefs.kt (70%) create mode 100644 core/prefs/src/main/kotlin/org/meshtastic/core/prefs/di/PrefsModule.kt rename {app/src/main/java/com/geeksville/mesh/android/prefs => core/prefs/src/main/kotlin/org/meshtastic/core/prefs/emoji}/CustomEmojiPrefs.kt (72%) rename {app/src/main/java/com/geeksville/mesh/android/prefs => core/prefs/src/main/kotlin/org/meshtastic/core/prefs/map}/MapConsentPrefs.kt (79%) rename {app/src/main/java/com/geeksville/mesh/android/prefs => core/prefs/src/main/kotlin/org/meshtastic/core/prefs/map}/MapPrefs.kt (81%) rename {app/src/main/java/com/geeksville/mesh/android/prefs => core/prefs/src/main/kotlin/org/meshtastic/core/prefs/map}/MapTileProviderPrefs.kt (71%) rename {app/src/main/java/com/geeksville/mesh/android/prefs => core/prefs/src/main/kotlin/org/meshtastic/core/prefs/mesh}/MeshPrefs.kt (80%) rename {app/src/main/java/com/geeksville/mesh/android/prefs => core/prefs/src/main/kotlin/org/meshtastic/core/prefs/radio}/RadioPrefs.kt (72%) rename {app/src/main/java/com/geeksville/mesh/android/prefs => core/prefs/src/main/kotlin/org/meshtastic/core/prefs/ui}/UiPrefs.kt (92%) diff --git a/app/src/fdroid/java/com/geeksville/mesh/MeshUtilApplication.kt b/app/src/fdroid/java/com/geeksville/mesh/MeshUtilApplication.kt index 52925a6cd..5782d5ce0 100644 --- a/app/src/fdroid/java/com/geeksville/mesh/MeshUtilApplication.kt +++ b/app/src/fdroid/java/com/geeksville/mesh/MeshUtilApplication.kt @@ -18,8 +18,8 @@ package com.geeksville.mesh import com.geeksville.mesh.android.GeeksvilleApplication -import com.geeksville.mesh.android.prefs.AnalyticsPrefs import dagger.hilt.android.HiltAndroidApp +import org.meshtastic.core.prefs.analytics.AnalyticsPrefs import javax.inject.Inject @HiltAndroidApp diff --git a/app/src/fdroid/java/com/geeksville/mesh/android/GeeksvilleApplication.kt b/app/src/fdroid/java/com/geeksville/mesh/android/GeeksvilleApplication.kt index 8117c46c0..32ed72d5f 100644 --- a/app/src/fdroid/java/com/geeksville/mesh/android/GeeksvilleApplication.kt +++ b/app/src/fdroid/java/com/geeksville/mesh/android/GeeksvilleApplication.kt @@ -28,8 +28,8 @@ import com.geeksville.mesh.analytics.AnalyticsProvider import com.geeksville.mesh.analytics.NopAnalytics import com.geeksville.mesh.android.BuildUtils.debug import com.geeksville.mesh.android.BuildUtils.info -import com.geeksville.mesh.android.prefs.AnalyticsPrefs import org.meshtastic.core.model.DeviceHardware +import org.meshtastic.core.prefs.analytics.AnalyticsPrefs import timber.log.Timber abstract class GeeksvilleApplication : diff --git a/app/src/fdroid/java/com/geeksville/mesh/ui/map/MapViewModel.kt b/app/src/fdroid/java/com/geeksville/mesh/ui/map/MapViewModel.kt index b51c9b7d9..79060fbc5 100644 --- a/app/src/fdroid/java/com/geeksville/mesh/ui/map/MapViewModel.kt +++ b/app/src/fdroid/java/com/geeksville/mesh/ui/map/MapViewModel.kt @@ -17,11 +17,11 @@ package com.geeksville.mesh.ui.map -import com.geeksville.mesh.android.prefs.MapPrefs import com.geeksville.mesh.database.NodeRepository import com.geeksville.mesh.database.PacketRepository import com.geeksville.mesh.repository.datastore.RadioConfigRepository import dagger.hilt.android.lifecycle.HiltViewModel +import org.meshtastic.core.prefs.map.MapPrefs import javax.inject.Inject @HiltViewModel diff --git a/app/src/google/java/com/geeksville/mesh/MeshUtilApplication.kt b/app/src/google/java/com/geeksville/mesh/MeshUtilApplication.kt index 997df57a0..30e8ff1d6 100644 --- a/app/src/google/java/com/geeksville/mesh/MeshUtilApplication.kt +++ b/app/src/google/java/com/geeksville/mesh/MeshUtilApplication.kt @@ -18,8 +18,8 @@ package com.geeksville.mesh import com.geeksville.mesh.android.GeeksvilleApplication -import com.geeksville.mesh.android.prefs.AnalyticsPrefs import dagger.hilt.android.HiltAndroidApp +import org.meshtastic.core.prefs.analytics.AnalyticsPrefs import javax.inject.Inject @HiltAndroidApp diff --git a/app/src/google/java/com/geeksville/mesh/android/GeeksvilleApplication.kt b/app/src/google/java/com/geeksville/mesh/android/GeeksvilleApplication.kt index 110be10b6..d89f97be2 100644 --- a/app/src/google/java/com/geeksville/mesh/android/GeeksvilleApplication.kt +++ b/app/src/google/java/com/geeksville/mesh/android/GeeksvilleApplication.kt @@ -48,7 +48,6 @@ import com.datadog.android.trace.opentelemetry.DatadogOpenTelemetry import com.geeksville.mesh.BuildConfig import com.geeksville.mesh.analytics.AnalyticsProvider import com.geeksville.mesh.analytics.FirebaseAnalytics -import com.geeksville.mesh.android.prefs.AnalyticsPrefs import com.geeksville.mesh.util.exceptionReporter import com.google.android.gms.common.ConnectionResult import com.google.android.gms.common.GoogleApiAvailabilityLight @@ -60,6 +59,7 @@ import com.google.firebase.initialize import com.suddenh4x.ratingdialog.AppRating import io.opentelemetry.api.GlobalOpenTelemetry import org.meshtastic.core.model.DeviceHardware +import org.meshtastic.core.prefs.analytics.AnalyticsPrefs import timber.log.Timber abstract class GeeksvilleApplication : diff --git a/app/src/google/java/com/geeksville/mesh/repository/map/SharedPreferencesCustomTileProviderRepository.kt b/app/src/google/java/com/geeksville/mesh/repository/map/SharedPreferencesCustomTileProviderRepository.kt index 92d5c43c7..d48034a37 100644 --- a/app/src/google/java/com/geeksville/mesh/repository/map/SharedPreferencesCustomTileProviderRepository.kt +++ b/app/src/google/java/com/geeksville/mesh/repository/map/SharedPreferencesCustomTileProviderRepository.kt @@ -17,7 +17,6 @@ package com.geeksville.mesh.repository.map -import com.geeksville.mesh.android.prefs.MapTileProviderPrefs import com.geeksville.mesh.di.IoDispatcher import com.geeksville.mesh.ui.map.CustomTileProviderConfig import kotlinx.coroutines.CoroutineDispatcher @@ -27,6 +26,7 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.withContext import kotlinx.serialization.SerializationException import kotlinx.serialization.json.Json +import org.meshtastic.core.prefs.map.MapTileProviderPrefs import timber.log.Timber import javax.inject.Inject import javax.inject.Singleton diff --git a/app/src/google/java/com/geeksville/mesh/ui/map/MapViewModel.kt b/app/src/google/java/com/geeksville/mesh/ui/map/MapViewModel.kt index dd7905380..3d7cb4bb3 100644 --- a/app/src/google/java/com/geeksville/mesh/ui/map/MapViewModel.kt +++ b/app/src/google/java/com/geeksville/mesh/ui/map/MapViewModel.kt @@ -23,8 +23,6 @@ import androidx.core.net.toFile import androidx.lifecycle.viewModelScope import com.geeksville.mesh.ConfigProtos import com.geeksville.mesh.android.BuildUtils.debug -import com.geeksville.mesh.android.prefs.GoogleMapsPrefs -import com.geeksville.mesh.android.prefs.MapPrefs import com.geeksville.mesh.database.NodeRepository import com.geeksville.mesh.database.PacketRepository import com.geeksville.mesh.repository.datastore.RadioConfigRepository @@ -52,6 +50,8 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import kotlinx.serialization.Serializable import org.json.JSONObject +import org.meshtastic.core.prefs.map.GoogleMapsPrefs +import org.meshtastic.core.prefs.map.MapPrefs import timber.log.Timber import java.io.File import java.io.FileOutputStream diff --git a/app/src/main/java/com/geeksville/mesh/MainActivity.kt b/app/src/main/java/com/geeksville/mesh/MainActivity.kt index 73f8a0a41..74e7c76b7 100644 --- a/app/src/main/java/com/geeksville/mesh/MainActivity.kt +++ b/app/src/main/java/com/geeksville/mesh/MainActivity.kt @@ -41,7 +41,6 @@ import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.android.GeeksvilleApplication import com.geeksville.mesh.android.Logging -import com.geeksville.mesh.android.prefs.UiPrefs import com.geeksville.mesh.model.UIViewModel import com.geeksville.mesh.ui.MainScreen import com.geeksville.mesh.ui.common.theme.AppTheme @@ -50,6 +49,7 @@ import com.geeksville.mesh.ui.intro.AppIntroductionScreen import com.geeksville.mesh.ui.sharing.toSharedContact import dagger.hilt.android.AndroidEntryPoint import org.meshtastic.core.navigation.DEEP_LINK_BASE_URI +import org.meshtastic.core.prefs.ui.UiPrefs import javax.inject.Inject @AndroidEntryPoint diff --git a/app/src/main/java/com/geeksville/mesh/android/prefs/PrefsModule.kt b/app/src/main/java/com/geeksville/mesh/android/prefs/PrefsModule.kt deleted file mode 100644 index e4eff087d..000000000 --- a/app/src/main/java/com/geeksville/mesh/android/prefs/PrefsModule.kt +++ /dev/null @@ -1,170 +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 . - */ - -package com.geeksville.mesh.android.prefs - -import android.content.Context -import android.content.SharedPreferences -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext -import dagger.hilt.components.SingletonComponent -import javax.inject.Qualifier -import javax.inject.Singleton - -// These pref store qualifiers are private to prevent prefs stores from being injected directly. -// Consuming code should always inject one of the prefs repositories. - -@Qualifier -@Retention(AnnotationRetention.BINARY) -private annotation class AnalyticsSharedPreferences - -@Qualifier -@Retention(AnnotationRetention.BINARY) -private annotation class AppSharedPreferences - -@Qualifier -@Retention(AnnotationRetention.BINARY) -private annotation class CustomEmojiSharedPreferences - -@Qualifier -@Retention(AnnotationRetention.BINARY) -private annotation class MapSharedPreferences - -@Qualifier -@Retention(AnnotationRetention.BINARY) -private annotation class MapConsentSharedPreferences - -@Qualifier -@Retention(AnnotationRetention.BINARY) -private annotation class MapTileProviderSharedPreferences - -@Qualifier -@Retention(AnnotationRetention.BINARY) -private annotation class MeshSharedPreferences - -@Qualifier -@Retention(AnnotationRetention.BINARY) -private annotation class RadioSharedPreferences - -@Qualifier -@Retention(AnnotationRetention.BINARY) -private annotation class UiSharedPreferences - -@Suppress("TooManyFunctions") -@InstallIn(SingletonComponent::class) -@Module -object PrefsModule { - - @Provides - @Singleton - @AnalyticsSharedPreferences - fun provideAnalyticsSharedPreferences(@ApplicationContext context: Context): SharedPreferences = - context.getSharedPreferences("analytics-prefs", Context.MODE_PRIVATE) - - @Provides - @Singleton - @AppSharedPreferences - fun provideAppSharedPreferences(@ApplicationContext context: Context): SharedPreferences = - context.getSharedPreferences("prefs", Context.MODE_PRIVATE) - - @Provides - @Singleton - @CustomEmojiSharedPreferences - fun provideCustomEmojiSharedPreferences(@ApplicationContext context: Context): SharedPreferences = - context.getSharedPreferences("org.geeksville.emoji.prefs", Context.MODE_PRIVATE) - - @Provides - @Singleton - @MapSharedPreferences - fun provideMapSharedPreferences(@ApplicationContext context: Context): SharedPreferences = - context.getSharedPreferences("map_prefs", Context.MODE_PRIVATE) - - @Provides - @Singleton - @MapConsentSharedPreferences - fun provideMapConsentSharedPreferences(@ApplicationContext context: Context): SharedPreferences = - context.getSharedPreferences("map_consent_preferences", Context.MODE_PRIVATE) - - @Provides - @Singleton - @MapTileProviderSharedPreferences - fun provideMapTileProviderSharedPreferences(@ApplicationContext context: Context): SharedPreferences = - context.getSharedPreferences("map_tile_provider_prefs", Context.MODE_PRIVATE) - - @Provides - @Singleton - @MeshSharedPreferences - fun provideMeshSharedPreferences(@ApplicationContext context: Context): SharedPreferences = - context.getSharedPreferences("mesh-prefs", Context.MODE_PRIVATE) - - @Provides - @Singleton - @RadioSharedPreferences - fun provideRadioSharedPreferences(@ApplicationContext context: Context): SharedPreferences = - context.getSharedPreferences("radio-prefs", Context.MODE_PRIVATE) - - @Provides - @Singleton - @UiSharedPreferences - fun provideUiSharedPreferences(@ApplicationContext context: Context): SharedPreferences = - context.getSharedPreferences("ui-prefs", Context.MODE_PRIVATE) - - @Provides - @Singleton - fun provideAnalyticsPrefs( - @AnalyticsSharedPreferences analyticsPreferences: SharedPreferences, - @AppSharedPreferences appPreferences: SharedPreferences, - ): AnalyticsPrefs = AnalyticsPrefsImpl(analyticsPreferences, appPreferences) - - @Provides - @Singleton - fun provideCustomEmojiPrefs(@CustomEmojiSharedPreferences sharedPreferences: SharedPreferences): CustomEmojiPrefs = - CustomEmojiPrefsImpl(sharedPreferences) - - @Provides - @Singleton - fun provideMapPrefs(@MapSharedPreferences sharedPreferences: SharedPreferences): MapPrefs = - MapPrefsImpl(sharedPreferences) - - @Provides - @Singleton - fun provideMapConsentPrefs(@MapConsentSharedPreferences sharedPreferences: SharedPreferences): MapConsentPrefs = - MapConsentPrefsImpl(sharedPreferences) - - @Provides - @Singleton - fun provideMapTileProviderPrefs( - @MapTileProviderSharedPreferences sharedPreferences: SharedPreferences, - ): MapTileProviderPrefs = MapTileProviderPrefsImpl(sharedPreferences) - - @Provides - @Singleton - fun provideMeshPrefs(@MeshSharedPreferences sharedPreferences: SharedPreferences): MeshPrefs = - MeshPrefsImpl(sharedPreferences) - - @Provides - @Singleton - fun provideRadioPrefs(@RadioSharedPreferences sharedPreferences: SharedPreferences): RadioPrefs = - RadioPrefsImpl(sharedPreferences) - - @Provides - @Singleton - fun provideUiPrefs(@UiSharedPreferences sharedPreferences: SharedPreferences): UiPrefs = - UiPrefsImpl(sharedPreferences) -} diff --git a/app/src/main/java/com/geeksville/mesh/model/MetricsViewModel.kt b/app/src/main/java/com/geeksville/mesh/model/MetricsViewModel.kt index ff325a593..f72f90cd5 100644 --- a/app/src/main/java/com/geeksville/mesh/model/MetricsViewModel.kt +++ b/app/src/main/java/com/geeksville/mesh/model/MetricsViewModel.kt @@ -36,7 +36,6 @@ import com.geeksville.mesh.Portnums import com.geeksville.mesh.Portnums.PortNum import com.geeksville.mesh.TelemetryProtos.Telemetry import com.geeksville.mesh.android.Logging -import com.geeksville.mesh.android.prefs.MapPrefs import com.geeksville.mesh.database.MeshLogRepository import com.geeksville.mesh.database.entity.FirmwareRelease import com.geeksville.mesh.database.entity.MeshLog @@ -62,6 +61,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.meshtastic.core.model.DeviceHardware import org.meshtastic.core.navigation.NodesRoutes +import org.meshtastic.core.prefs.map.MapPrefs import org.meshtastic.core.strings.R import org.meshtastic.feature.map.model.CustomTileSource import java.io.BufferedWriter diff --git a/app/src/main/java/com/geeksville/mesh/model/UIState.kt b/app/src/main/java/com/geeksville/mesh/model/UIState.kt index 1f4a53907..ee6f228a5 100644 --- a/app/src/main/java/com/geeksville/mesh/model/UIState.kt +++ b/app/src/main/java/com/geeksville/mesh/model/UIState.kt @@ -39,7 +39,6 @@ import com.geeksville.mesh.LocalOnlyProtos.LocalModuleConfig import com.geeksville.mesh.MeshProtos import com.geeksville.mesh.Position 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 @@ -83,6 +82,7 @@ import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.meshtastic.core.model.DeviceHardware +import org.meshtastic.core.prefs.ui.UiPrefs import org.meshtastic.core.strings.R import javax.inject.Inject diff --git a/app/src/main/java/com/geeksville/mesh/repository/radio/RadioInterfaceService.kt b/app/src/main/java/com/geeksville/mesh/repository/radio/RadioInterfaceService.kt index fe12885a5..e448b421f 100644 --- a/app/src/main/java/com/geeksville/mesh/repository/radio/RadioInterfaceService.kt +++ b/app/src/main/java/com/geeksville/mesh/repository/radio/RadioInterfaceService.kt @@ -27,7 +27,6 @@ import com.geeksville.mesh.android.BinaryLogFile import com.geeksville.mesh.android.BuildUtils import com.geeksville.mesh.android.GeeksvilleApplication import com.geeksville.mesh.android.Logging -import com.geeksville.mesh.android.prefs.RadioPrefs import com.geeksville.mesh.concurrent.handledLaunch import com.geeksville.mesh.repository.bluetooth.BluetoothRepository import com.geeksville.mesh.repository.network.NetworkRepository @@ -49,6 +48,7 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch +import org.meshtastic.core.prefs.radio.RadioPrefs import javax.inject.Inject import javax.inject.Singleton @@ -195,9 +195,7 @@ constructor( private fun broadcastConnectionChanged(newState: ConnectionState) { debug("Broadcasting connection state change to $newState") - processLifecycle.coroutineScope.launch(dispatchers.default) { - _connectionState.emit(newState) - } + processLifecycle.coroutineScope.launch(dispatchers.default) { _connectionState.emit(newState) } } // Send a packet/command out the radio link, this routine can block if it needs to diff --git a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt index b0bc11933..6d9876769 100644 --- a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt @@ -58,8 +58,6 @@ import com.geeksville.mesh.analytics.DataPair import com.geeksville.mesh.android.GeeksvilleApplication import com.geeksville.mesh.android.Logging import com.geeksville.mesh.android.hasLocationPermission -import com.geeksville.mesh.android.prefs.MeshPrefs -import com.geeksville.mesh.android.prefs.UiPrefs import com.geeksville.mesh.concurrent.handledLaunch import com.geeksville.mesh.copy import com.geeksville.mesh.database.MeshLogRepository @@ -103,6 +101,8 @@ import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.meshtastic.core.model.getFullTracerouteResponse +import org.meshtastic.core.prefs.mesh.MeshPrefs +import org.meshtastic.core.prefs.ui.UiPrefs import org.meshtastic.core.strings.R import java.util.Random import java.util.UUID diff --git a/app/src/main/java/com/geeksville/mesh/ui/common/EmojiPickerViewModel.kt b/app/src/main/java/com/geeksville/mesh/ui/common/EmojiPickerViewModel.kt index b97cb8961..9eabbfc7b 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/common/EmojiPickerViewModel.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/common/EmojiPickerViewModel.kt @@ -18,8 +18,8 @@ package com.geeksville.mesh.ui.common import androidx.lifecycle.ViewModel -import com.geeksville.mesh.android.prefs.CustomEmojiPrefs import dagger.hilt.android.lifecycle.HiltViewModel +import org.meshtastic.core.prefs.emoji.CustomEmojiPrefs import javax.inject.Inject @HiltViewModel diff --git a/app/src/main/java/com/geeksville/mesh/ui/connections/ConnectionsViewModel.kt b/app/src/main/java/com/geeksville/mesh/ui/connections/ConnectionsViewModel.kt index 491aee075..67d21df88 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/connections/ConnectionsViewModel.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/connections/ConnectionsViewModel.kt @@ -20,7 +20,6 @@ package com.geeksville.mesh.ui.connections import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.geeksville.mesh.LocalOnlyProtos.LocalConfig -import com.geeksville.mesh.android.prefs.UiPrefs import com.geeksville.mesh.database.NodeRepository import com.geeksville.mesh.database.entity.MyNodeEntity import com.geeksville.mesh.model.Node @@ -32,6 +31,7 @@ import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.stateIn +import org.meshtastic.core.prefs.ui.UiPrefs import javax.inject.Inject @HiltViewModel diff --git a/app/src/main/java/com/geeksville/mesh/ui/map/BaseMapViewModel.kt b/app/src/main/java/com/geeksville/mesh/ui/map/BaseMapViewModel.kt index aafb5f67d..29e1c92c4 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/map/BaseMapViewModel.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/map/BaseMapViewModel.kt @@ -19,7 +19,6 @@ package com.geeksville.mesh.ui.map import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.geeksville.mesh.android.prefs.MapPrefs import com.geeksville.mesh.database.NodeRepository import com.geeksville.mesh.database.PacketRepository import com.geeksville.mesh.database.entity.Packet @@ -32,6 +31,7 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.flow.stateIn +import org.meshtastic.core.prefs.map.MapPrefs @Suppress("TooManyFunctions") abstract class BaseMapViewModel( diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/SettingsViewModel.kt b/app/src/main/java/com/geeksville/mesh/ui/settings/SettingsViewModel.kt index 8d64499ba..a73c5a599 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/SettingsViewModel.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/settings/SettingsViewModel.kt @@ -27,7 +27,6 @@ import com.geeksville.mesh.MeshProtos import com.geeksville.mesh.Portnums import com.geeksville.mesh.Position import com.geeksville.mesh.android.Logging -import com.geeksville.mesh.android.prefs.UiPrefs import com.geeksville.mesh.database.MeshLogRepository import com.geeksville.mesh.database.NodeRepository import com.geeksville.mesh.database.entity.MyNodeEntity @@ -48,6 +47,7 @@ import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import org.meshtastic.core.prefs.ui.UiPrefs import java.io.BufferedWriter import java.io.FileNotFoundException import java.io.FileWriter diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/RadioConfigViewModel.kt b/app/src/main/java/com/geeksville/mesh/ui/settings/radio/RadioConfigViewModel.kt index 92a0cf8c0..44569533a 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/RadioConfigViewModel.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/settings/radio/RadioConfigViewModel.kt @@ -45,8 +45,6 @@ import com.geeksville.mesh.Position import com.geeksville.mesh.android.GeeksvilleApplication import com.geeksville.mesh.android.Logging import com.geeksville.mesh.android.isAnalyticsAvailable -import com.geeksville.mesh.android.prefs.AnalyticsPrefs -import com.geeksville.mesh.android.prefs.MapConsentPrefs import com.geeksville.mesh.config import com.geeksville.mesh.database.entity.MyNodeEntity import com.geeksville.mesh.deviceProfile @@ -77,6 +75,8 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.json.JSONObject import org.meshtastic.core.navigation.SettingsRoutes +import org.meshtastic.core.prefs.analytics.AnalyticsPrefs +import org.meshtastic.core.prefs.map.MapConsentPrefs import org.meshtastic.core.strings.R import java.io.FileOutputStream import javax.inject.Inject diff --git a/core/prefs/build.gradle.kts b/core/prefs/build.gradle.kts index 5f811dbf2..58b95ea1d 100644 --- a/core/prefs/build.gradle.kts +++ b/core/prefs/build.gradle.kts @@ -17,9 +17,14 @@ plugins { alias(libs.plugins.meshtastic.android.library) + alias(libs.plugins.meshtastic.hilt) alias(libs.plugins.kover) } android { namespace = "org.meshtastic.core.prefs" } -dependencies {} +dependencies { + implementation(libs.bundles.coroutines) + implementation(libs.appcompat) + googleImplementation(libs.maps.compose) +} diff --git a/app/src/google/java/com/geeksville/mesh/android/prefs/GoogleMapsModule.kt b/core/prefs/src/google/kotlin/org/meshtastic/core/prefs/di/GoogleMapsModule.kt similarity index 61% rename from app/src/google/java/com/geeksville/mesh/android/prefs/GoogleMapsModule.kt rename to core/prefs/src/google/kotlin/org/meshtastic/core/prefs/di/GoogleMapsModule.kt index 56328c08a..79d0eb3ff 100644 --- a/app/src/google/java/com/geeksville/mesh/android/prefs/GoogleMapsModule.kt +++ b/core/prefs/src/google/kotlin/org/meshtastic/core/prefs/di/GoogleMapsModule.kt @@ -15,37 +15,40 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.android.prefs +package org.meshtastic.core.prefs.di import android.content.Context import android.content.SharedPreferences +import dagger.Binds import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent +import org.meshtastic.core.prefs.map.GoogleMapsPrefs +import org.meshtastic.core.prefs.map.GoogleMapsPrefsImpl import javax.inject.Qualifier import javax.inject.Singleton -// Pref store qualifiers are private to prevent prefs stores from being injected directly. +// Pref store qualifiers are internal to prevent prefs stores from being injected directly. // Consuming code should always inject one of the prefs repositories. @Qualifier @Retention(AnnotationRetention.BINARY) -private annotation class GoogleMapsSharedPreferences +internal annotation class GoogleMapsSharedPreferences @InstallIn(SingletonComponent::class) @Module -object GoogleMapsModule { +interface GoogleMapsModule { - @Provides - @Singleton - @GoogleMapsSharedPreferences - fun provideGoogleMapsSharedPreferences(@ApplicationContext context: Context): SharedPreferences = - context.getSharedPreferences("google_maps_prefs", Context.MODE_PRIVATE) + @Binds fun bindGoogleMapsPrefs(googleMapsPrefsImpl: GoogleMapsPrefsImpl): GoogleMapsPrefs - @Provides - @Singleton - fun provideGoogleMapsPrefs(@GoogleMapsSharedPreferences sharedPreferences: SharedPreferences): GoogleMapsPrefs = - GoogleMapsPrefsImpl(sharedPreferences) + companion object { + + @Provides + @Singleton + @GoogleMapsSharedPreferences + fun provideGoogleMapsSharedPreferences(@ApplicationContext context: Context): SharedPreferences = + context.getSharedPreferences("google_maps_prefs", Context.MODE_PRIVATE) + } } diff --git a/app/src/google/java/com/geeksville/mesh/android/prefs/GoogleMapsPrefs.kt b/core/prefs/src/google/kotlin/org/meshtastic/core/prefs/map/GoogleMapsPrefs.kt similarity index 77% rename from app/src/google/java/com/geeksville/mesh/android/prefs/GoogleMapsPrefs.kt rename to core/prefs/src/google/kotlin/org/meshtastic/core/prefs/map/GoogleMapsPrefs.kt index bf39bc344..725f2b59f 100644 --- a/app/src/google/java/com/geeksville/mesh/android/prefs/GoogleMapsPrefs.kt +++ b/core/prefs/src/google/kotlin/org/meshtastic/core/prefs/map/GoogleMapsPrefs.kt @@ -15,10 +15,15 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.android.prefs +package org.meshtastic.core.prefs.map import android.content.SharedPreferences import com.google.maps.android.compose.MapType +import org.meshtastic.core.prefs.NullableStringPrefDelegate +import org.meshtastic.core.prefs.StringSetPrefDelegate +import org.meshtastic.core.prefs.di.GoogleMapsSharedPreferences +import javax.inject.Inject +import javax.inject.Singleton /** Interface for prefs specific to Google Maps. For general map prefs, see MapPrefs. */ interface GoogleMapsPrefs { @@ -27,7 +32,8 @@ interface GoogleMapsPrefs { var hiddenLayerUrls: Set } -class GoogleMapsPrefsImpl(prefs: SharedPreferences) : GoogleMapsPrefs { +@Singleton +class GoogleMapsPrefsImpl @Inject constructor(@GoogleMapsSharedPreferences prefs: SharedPreferences) : GoogleMapsPrefs { override var selectedGoogleMapType: String? by NullableStringPrefDelegate(prefs, "selected_google_map_type", MapType.NORMAL.name) override var selectedCustomTileUrl: String? by NullableStringPrefDelegate(prefs, "selected_custom_tile_url", null) diff --git a/app/src/main/java/com/geeksville/mesh/android/prefs/NullableStringPrefDelegate.kt b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/NullableStringPrefDelegate.kt similarity index 95% rename from app/src/main/java/com/geeksville/mesh/android/prefs/NullableStringPrefDelegate.kt rename to core/prefs/src/main/kotlin/org/meshtastic/core/prefs/NullableStringPrefDelegate.kt index 9d1755b0b..f8fbd059f 100644 --- a/app/src/main/java/com/geeksville/mesh/android/prefs/NullableStringPrefDelegate.kt +++ b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/NullableStringPrefDelegate.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.android.prefs +package org.meshtastic.core.prefs import android.content.SharedPreferences import androidx.core.content.edit @@ -29,7 +29,7 @@ import kotlin.reflect.KProperty * @param key The key used to store and retrieve the value. * @param defaultValue The default value to return if no value is found. */ -class NullableStringPrefDelegate( +internal class NullableStringPrefDelegate( private val prefs: SharedPreferences, private val key: String, private val defaultValue: String?, diff --git a/app/src/main/java/com/geeksville/mesh/android/prefs/PrefDelegate.kt b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/PrefDelegate.kt similarity index 91% rename from app/src/main/java/com/geeksville/mesh/android/prefs/PrefDelegate.kt rename to core/prefs/src/main/kotlin/org/meshtastic/core/prefs/PrefDelegate.kt index 22948a914..28ce21b65 100644 --- a/app/src/main/java/com/geeksville/mesh/android/prefs/PrefDelegate.kt +++ b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/PrefDelegate.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.android.prefs +package org.meshtastic.core.prefs import android.content.SharedPreferences import androidx.core.content.edit @@ -30,8 +30,11 @@ import kotlin.reflect.KProperty * @param defaultValue The default value to return if no value is found. * @throws IllegalArgumentException if the type is not supported. */ -class PrefDelegate(private val prefs: SharedPreferences, private val key: String, private val defaultValue: T) : - ReadWriteProperty { +internal class PrefDelegate( + private val prefs: SharedPreferences, + private val key: String, + private val defaultValue: T, +) : ReadWriteProperty { @Suppress("UNCHECKED_CAST") override fun getValue(thisRef: Any?, property: KProperty<*>): T = when (defaultValue) { diff --git a/app/src/main/java/com/geeksville/mesh/android/prefs/StringSetPrefDelegate.kt b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/StringSetPrefDelegate.kt similarity index 94% rename from app/src/main/java/com/geeksville/mesh/android/prefs/StringSetPrefDelegate.kt rename to core/prefs/src/main/kotlin/org/meshtastic/core/prefs/StringSetPrefDelegate.kt index 714b4936b..4cae1b099 100644 --- a/app/src/main/java/com/geeksville/mesh/android/prefs/StringSetPrefDelegate.kt +++ b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/StringSetPrefDelegate.kt @@ -15,14 +15,14 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.android.prefs +package org.meshtastic.core.prefs import android.content.SharedPreferences import androidx.core.content.edit import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty -class StringSetPrefDelegate( +internal class StringSetPrefDelegate( private val prefs: SharedPreferences, private val key: String, private val defaultValue: Set, diff --git a/app/src/main/java/com/geeksville/mesh/android/prefs/AnalyticsPrefs.kt b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/analytics/AnalyticsPrefs.kt similarity index 70% rename from app/src/main/java/com/geeksville/mesh/android/prefs/AnalyticsPrefs.kt rename to core/prefs/src/main/kotlin/org/meshtastic/core/prefs/analytics/AnalyticsPrefs.kt index 445c66cfc..89ab8b721 100644 --- a/app/src/main/java/com/geeksville/mesh/android/prefs/AnalyticsPrefs.kt +++ b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/analytics/AnalyticsPrefs.kt @@ -15,10 +15,16 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.android.prefs +package org.meshtastic.core.prefs.analytics import android.content.SharedPreferences +import org.meshtastic.core.prefs.NullableStringPrefDelegate +import org.meshtastic.core.prefs.PrefDelegate +import org.meshtastic.core.prefs.di.AnalyticsSharedPreferences +import org.meshtastic.core.prefs.di.AppSharedPreferences import java.util.UUID +import javax.inject.Inject +import javax.inject.Singleton interface AnalyticsPrefs { var analyticsAllowed: Boolean @@ -26,7 +32,13 @@ interface AnalyticsPrefs { } // Having an additional app prefs store is maintaining the existing behavior. -class AnalyticsPrefsImpl(analyticsPrefs: SharedPreferences, appPrefs: SharedPreferences) : AnalyticsPrefs { +@Singleton +class AnalyticsPrefsImpl +@Inject +constructor( + @AnalyticsSharedPreferences analyticsPrefs: SharedPreferences, + @AppSharedPreferences appPrefs: SharedPreferences, +) : AnalyticsPrefs { override var analyticsAllowed: Boolean by PrefDelegate(analyticsPrefs, "allowed", true) private var _installId: String? by NullableStringPrefDelegate(appPrefs, "appPrefs_install_id", null) diff --git a/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/di/PrefsModule.kt b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/di/PrefsModule.kt new file mode 100644 index 000000000..6aadabaea --- /dev/null +++ b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/di/PrefsModule.kt @@ -0,0 +1,163 @@ +/* + * 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 . + */ + +package org.meshtastic.core.prefs.di + +import android.content.Context +import android.content.SharedPreferences +import dagger.Binds +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import org.meshtastic.core.prefs.analytics.AnalyticsPrefs +import org.meshtastic.core.prefs.analytics.AnalyticsPrefsImpl +import org.meshtastic.core.prefs.emoji.CustomEmojiPrefs +import org.meshtastic.core.prefs.emoji.CustomEmojiPrefsImpl +import org.meshtastic.core.prefs.map.MapConsentPrefs +import org.meshtastic.core.prefs.map.MapConsentPrefsImpl +import org.meshtastic.core.prefs.map.MapPrefs +import org.meshtastic.core.prefs.map.MapPrefsImpl +import org.meshtastic.core.prefs.map.MapTileProviderPrefs +import org.meshtastic.core.prefs.map.MapTileProviderPrefsImpl +import org.meshtastic.core.prefs.mesh.MeshPrefs +import org.meshtastic.core.prefs.mesh.MeshPrefsImpl +import org.meshtastic.core.prefs.radio.RadioPrefs +import org.meshtastic.core.prefs.radio.RadioPrefsImpl +import org.meshtastic.core.prefs.ui.UiPrefs +import org.meshtastic.core.prefs.ui.UiPrefsImpl +import javax.inject.Qualifier +import javax.inject.Singleton + +// These pref store qualifiers are internal to prevent prefs stores from being injected directly. +// Consuming code should always inject one of the prefs repositories. + +@Qualifier +@Retention(AnnotationRetention.BINARY) +internal annotation class AnalyticsSharedPreferences + +@Qualifier +@Retention(AnnotationRetention.BINARY) +internal annotation class AppSharedPreferences + +@Qualifier +@Retention(AnnotationRetention.BINARY) +internal annotation class CustomEmojiSharedPreferences + +@Qualifier +@Retention(AnnotationRetention.BINARY) +internal annotation class MapSharedPreferences + +@Qualifier +@Retention(AnnotationRetention.BINARY) +internal annotation class MapConsentSharedPreferences + +@Qualifier +@Retention(AnnotationRetention.BINARY) +internal annotation class MapTileProviderSharedPreferences + +@Qualifier +@Retention(AnnotationRetention.BINARY) +internal annotation class MeshSharedPreferences + +@Qualifier +@Retention(AnnotationRetention.BINARY) +internal annotation class RadioSharedPreferences + +@Qualifier +@Retention(AnnotationRetention.BINARY) +internal annotation class UiSharedPreferences + +@Suppress("TooManyFunctions") +@InstallIn(SingletonComponent::class) +@Module +interface PrefsModule { + + @Binds fun bindAnalyticsPrefs(analyticsPrefsImpl: AnalyticsPrefsImpl): AnalyticsPrefs + + @Binds fun bindCustomEmojiPrefs(customEmojiPrefsImpl: CustomEmojiPrefsImpl): CustomEmojiPrefs + + @Binds fun bindMapConsentPrefs(mapConsentPrefsImpl: MapConsentPrefsImpl): MapConsentPrefs + + @Binds fun bindMapPrefs(mapPrefsImpl: MapPrefsImpl): MapPrefs + + @Binds fun bindMapTileProviderPrefs(mapTileProviderPrefsImpl: MapTileProviderPrefsImpl): MapTileProviderPrefs + + @Binds fun bindMeshPrefs(meshPrefsImpl: MeshPrefsImpl): MeshPrefs + + @Binds fun bindRadioPrefs(radioPrefsImpl: RadioPrefsImpl): RadioPrefs + + @Binds fun bindUiPrefs(uiPrefsImpl: UiPrefsImpl): UiPrefs + + companion object { + + @Provides + @Singleton + @AnalyticsSharedPreferences + fun provideAnalyticsSharedPreferences(@ApplicationContext context: Context): SharedPreferences = + context.getSharedPreferences("analytics-prefs", Context.MODE_PRIVATE) + + @Provides + @Singleton + @AppSharedPreferences + fun provideAppSharedPreferences(@ApplicationContext context: Context): SharedPreferences = + context.getSharedPreferences("prefs", Context.MODE_PRIVATE) + + @Provides + @Singleton + @CustomEmojiSharedPreferences + fun provideCustomEmojiSharedPreferences(@ApplicationContext context: Context): SharedPreferences = + context.getSharedPreferences("org.geeksville.emoji.prefs", Context.MODE_PRIVATE) + + @Provides + @Singleton + @MapSharedPreferences + fun provideMapSharedPreferences(@ApplicationContext context: Context): SharedPreferences = + context.getSharedPreferences("map_prefs", Context.MODE_PRIVATE) + + @Provides + @Singleton + @MapConsentSharedPreferences + fun provideMapConsentSharedPreferences(@ApplicationContext context: Context): SharedPreferences = + context.getSharedPreferences("map_consent_preferences", Context.MODE_PRIVATE) + + @Provides + @Singleton + @MapTileProviderSharedPreferences + fun provideMapTileProviderSharedPreferences(@ApplicationContext context: Context): SharedPreferences = + context.getSharedPreferences("map_tile_provider_prefs", Context.MODE_PRIVATE) + + @Provides + @Singleton + @MeshSharedPreferences + fun provideMeshSharedPreferences(@ApplicationContext context: Context): SharedPreferences = + context.getSharedPreferences("mesh-prefs", Context.MODE_PRIVATE) + + @Provides + @Singleton + @RadioSharedPreferences + fun provideRadioSharedPreferences(@ApplicationContext context: Context): SharedPreferences = + context.getSharedPreferences("radio-prefs", Context.MODE_PRIVATE) + + @Provides + @Singleton + @UiSharedPreferences + fun provideUiSharedPreferences(@ApplicationContext context: Context): SharedPreferences = + context.getSharedPreferences("ui-prefs", Context.MODE_PRIVATE) + } +} diff --git a/app/src/main/java/com/geeksville/mesh/android/prefs/CustomEmojiPrefs.kt b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/emoji/CustomEmojiPrefs.kt similarity index 72% rename from app/src/main/java/com/geeksville/mesh/android/prefs/CustomEmojiPrefs.kt rename to core/prefs/src/main/kotlin/org/meshtastic/core/prefs/emoji/CustomEmojiPrefs.kt index eb9f51eab..986265590 100644 --- a/app/src/main/java/com/geeksville/mesh/android/prefs/CustomEmojiPrefs.kt +++ b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/emoji/CustomEmojiPrefs.kt @@ -15,14 +15,20 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.android.prefs +package org.meshtastic.core.prefs.emoji import android.content.SharedPreferences +import org.meshtastic.core.prefs.NullableStringPrefDelegate +import org.meshtastic.core.prefs.di.CustomEmojiSharedPreferences +import javax.inject.Inject +import javax.inject.Singleton interface CustomEmojiPrefs { var customEmojiFrequency: String? } -class CustomEmojiPrefsImpl(prefs: SharedPreferences) : CustomEmojiPrefs { +@Singleton +class CustomEmojiPrefsImpl @Inject constructor(@CustomEmojiSharedPreferences prefs: SharedPreferences) : + CustomEmojiPrefs { override var customEmojiFrequency: String? by NullableStringPrefDelegate(prefs, "pref_key_custom_emoji_freq", null) } diff --git a/app/src/main/java/com/geeksville/mesh/android/prefs/MapConsentPrefs.kt b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/map/MapConsentPrefs.kt similarity index 79% rename from app/src/main/java/com/geeksville/mesh/android/prefs/MapConsentPrefs.kt rename to core/prefs/src/main/kotlin/org/meshtastic/core/prefs/map/MapConsentPrefs.kt index b265f8ff9..ae1a76890 100644 --- a/app/src/main/java/com/geeksville/mesh/android/prefs/MapConsentPrefs.kt +++ b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/map/MapConsentPrefs.kt @@ -15,10 +15,13 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.android.prefs +package org.meshtastic.core.prefs.map import android.content.SharedPreferences import androidx.core.content.edit +import org.meshtastic.core.prefs.di.MapConsentSharedPreferences +import javax.inject.Inject +import javax.inject.Singleton interface MapConsentPrefs { fun shouldReportLocation(nodeNum: Int?): Boolean @@ -26,7 +29,9 @@ interface MapConsentPrefs { fun setShouldReportLocation(nodeNum: Int?, value: Boolean) } -class MapConsentPrefsImpl(private val prefs: SharedPreferences) : MapConsentPrefs { +@Singleton +class MapConsentPrefsImpl @Inject constructor(@MapConsentSharedPreferences private val prefs: SharedPreferences) : + MapConsentPrefs { override fun shouldReportLocation(nodeNum: Int?) = prefs.getBoolean(nodeNum.toString(), false) override fun setShouldReportLocation(nodeNum: Int?, value: Boolean) { diff --git a/app/src/main/java/com/geeksville/mesh/android/prefs/MapPrefs.kt b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/map/MapPrefs.kt similarity index 81% rename from app/src/main/java/com/geeksville/mesh/android/prefs/MapPrefs.kt rename to core/prefs/src/main/kotlin/org/meshtastic/core/prefs/map/MapPrefs.kt index f095639bd..ac2f1d7ce 100644 --- a/app/src/main/java/com/geeksville/mesh/android/prefs/MapPrefs.kt +++ b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/map/MapPrefs.kt @@ -15,9 +15,13 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.android.prefs +package org.meshtastic.core.prefs.map import android.content.SharedPreferences +import org.meshtastic.core.prefs.PrefDelegate +import org.meshtastic.core.prefs.di.MapSharedPreferences +import javax.inject.Inject +import javax.inject.Singleton /** Interface for general map prefs. For Google-specific prefs, see GoogleMapsPrefs. */ interface MapPrefs { @@ -27,7 +31,8 @@ interface MapPrefs { var showPrecisionCircleOnMap: Boolean } -class MapPrefsImpl(prefs: SharedPreferences) : MapPrefs { +@Singleton +class MapPrefsImpl @Inject constructor(@MapSharedPreferences prefs: SharedPreferences) : MapPrefs { override var mapStyle: Int by PrefDelegate(prefs, "map_style_id", 0) override var showOnlyFavorites: Boolean by PrefDelegate(prefs, "show_only_favorites", false) override var showWaypointsOnMap: Boolean by PrefDelegate(prefs, "show_waypoints", true) diff --git a/app/src/main/java/com/geeksville/mesh/android/prefs/MapTileProviderPrefs.kt b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/map/MapTileProviderPrefs.kt similarity index 71% rename from app/src/main/java/com/geeksville/mesh/android/prefs/MapTileProviderPrefs.kt rename to core/prefs/src/main/kotlin/org/meshtastic/core/prefs/map/MapTileProviderPrefs.kt index a97f5a1f6..9c86a4b13 100644 --- a/app/src/main/java/com/geeksville/mesh/android/prefs/MapTileProviderPrefs.kt +++ b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/map/MapTileProviderPrefs.kt @@ -15,14 +15,20 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.android.prefs +package org.meshtastic.core.prefs.map import android.content.SharedPreferences +import org.meshtastic.core.prefs.NullableStringPrefDelegate +import org.meshtastic.core.prefs.di.MapTileProviderSharedPreferences +import javax.inject.Inject +import javax.inject.Singleton interface MapTileProviderPrefs { var customTileProviders: String? } -class MapTileProviderPrefsImpl(prefs: SharedPreferences) : MapTileProviderPrefs { +@Singleton +class MapTileProviderPrefsImpl @Inject constructor(@MapTileProviderSharedPreferences prefs: SharedPreferences) : + MapTileProviderPrefs { override var customTileProviders: String? by NullableStringPrefDelegate(prefs, "custom_tile_providers", null) } diff --git a/app/src/main/java/com/geeksville/mesh/android/prefs/MeshPrefs.kt b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/mesh/MeshPrefs.kt similarity index 80% rename from app/src/main/java/com/geeksville/mesh/android/prefs/MeshPrefs.kt rename to core/prefs/src/main/kotlin/org/meshtastic/core/prefs/mesh/MeshPrefs.kt index 335000f1a..a268bd6bd 100644 --- a/app/src/main/java/com/geeksville/mesh/android/prefs/MeshPrefs.kt +++ b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/mesh/MeshPrefs.kt @@ -15,10 +15,14 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.android.prefs +package org.meshtastic.core.prefs.mesh import android.content.SharedPreferences import androidx.core.content.edit +import org.meshtastic.core.prefs.NullableStringPrefDelegate +import org.meshtastic.core.prefs.di.MeshSharedPreferences +import javax.inject.Inject +import javax.inject.Singleton interface MeshPrefs { var deviceAddress: String? @@ -28,7 +32,8 @@ interface MeshPrefs { fun setShouldProvideNodeLocation(nodeNum: Int?, value: Boolean) } -class MeshPrefsImpl(private val prefs: SharedPreferences) : MeshPrefs { +@Singleton +class MeshPrefsImpl @Inject constructor(@MeshSharedPreferences private val prefs: SharedPreferences) : MeshPrefs { override var deviceAddress: String? by NullableStringPrefDelegate(prefs, "device_address", null) override fun shouldProvideNodeLocation(nodeNum: Int?): Boolean = diff --git a/app/src/main/java/com/geeksville/mesh/android/prefs/RadioPrefs.kt b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/radio/RadioPrefs.kt similarity index 72% rename from app/src/main/java/com/geeksville/mesh/android/prefs/RadioPrefs.kt rename to core/prefs/src/main/kotlin/org/meshtastic/core/prefs/radio/RadioPrefs.kt index f53beb804..45d986c3c 100644 --- a/app/src/main/java/com/geeksville/mesh/android/prefs/RadioPrefs.kt +++ b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/radio/RadioPrefs.kt @@ -15,14 +15,19 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.android.prefs +package org.meshtastic.core.prefs.radio import android.content.SharedPreferences +import org.meshtastic.core.prefs.NullableStringPrefDelegate +import org.meshtastic.core.prefs.di.RadioSharedPreferences +import javax.inject.Inject +import javax.inject.Singleton interface RadioPrefs { var devAddr: String? } -class RadioPrefsImpl(prefs: SharedPreferences) : RadioPrefs { +@Singleton +class RadioPrefsImpl @Inject constructor(@RadioSharedPreferences prefs: SharedPreferences) : RadioPrefs { override var devAddr: String? by NullableStringPrefDelegate(prefs, "devAddr2", null) } diff --git a/app/src/main/java/com/geeksville/mesh/android/prefs/UiPrefs.kt b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/ui/UiPrefs.kt similarity index 92% rename from app/src/main/java/com/geeksville/mesh/android/prefs/UiPrefs.kt rename to core/prefs/src/main/kotlin/org/meshtastic/core/prefs/ui/UiPrefs.kt index a79941c29..5a2ac697a 100644 --- a/app/src/main/java/com/geeksville/mesh/android/prefs/UiPrefs.kt +++ b/core/prefs/src/main/kotlin/org/meshtastic/core/prefs/ui/UiPrefs.kt @@ -15,17 +15,20 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.android.prefs +package org.meshtastic.core.prefs.ui import android.content.SharedPreferences import androidx.appcompat.app.AppCompatDelegate import androidx.core.content.edit -import com.geeksville.mesh.model.NodeSortOption import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update +import org.meshtastic.core.prefs.PrefDelegate +import org.meshtastic.core.prefs.di.UiSharedPreferences import java.util.concurrent.ConcurrentHashMap +import javax.inject.Inject +import javax.inject.Singleton interface UiPrefs { var theme: Int @@ -49,7 +52,8 @@ interface UiPrefs { const val KEY_THEME = "theme" const val KEY_APP_INTRO_COMPLETED = "app_intro_completed" -class UiPrefsImpl(private val prefs: SharedPreferences) : UiPrefs { +@Singleton +class UiPrefsImpl @Inject constructor(@UiSharedPreferences private val prefs: SharedPreferences) : UiPrefs { override var theme: Int by PrefDelegate(prefs, KEY_THEME, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) private var _themeFlow = MutableStateFlow(theme) @@ -83,7 +87,7 @@ class UiPrefsImpl(private val prefs: SharedPreferences) : UiPrefs { } 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 nodeSortOption: Int by PrefDelegate(prefs, "node-sort-option", -1) override var includeUnknown: Boolean by PrefDelegate(prefs, "include-unknown", false) override var showDetails: Boolean by PrefDelegate(prefs, "show-details", false) override var onlyOnline: Boolean by PrefDelegate(prefs, "only-online", false)