refactor: migrate from Hilt to Koin and expand KMP common modules (#4746)

Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
James Rich 2026-03-09 20:19:46 -05:00 committed by GitHub
parent a5390a80e7
commit 875cf1cff2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
440 changed files with 3738 additions and 3508 deletions

View file

@ -0,0 +1,132 @@
/*
* Copyright (c) 2026 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 org.meshtastic.core.prefs.di
import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.SharedPreferencesMigration
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.preferencesDataStoreFile
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import org.koin.core.annotation.Module
import org.koin.core.annotation.Named
import org.koin.core.annotation.Single
@Suppress("TooManyFunctions")
@Module
class CorePrefsAndroidModule {
private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
@Single
@Named("AnalyticsDataStore")
fun provideAnalyticsDataStore(context: Context): DataStore<Preferences> = PreferenceDataStoreFactory.create(
migrations = listOf(SharedPreferencesMigration(context, "analytics-prefs")),
scope = scope,
produceFile = { context.preferencesDataStoreFile("analytics_ds") },
)
@Single
@Named("HomoglyphEncodingDataStore")
fun provideHomoglyphEncodingDataStore(context: Context): DataStore<Preferences> = PreferenceDataStoreFactory.create(
migrations = listOf(SharedPreferencesMigration(context, "homoglyph-encoding-prefs")),
scope = scope,
produceFile = { context.preferencesDataStoreFile("homoglyph_encoding_ds") },
)
@Single
@Named("AppDataStore")
fun provideAppDataStore(context: Context): DataStore<Preferences> = PreferenceDataStoreFactory.create(
migrations = listOf(SharedPreferencesMigration(context, "prefs")),
scope = scope,
produceFile = { context.preferencesDataStoreFile("app_ds") },
)
@Single
@Named("CustomEmojiDataStore")
fun provideCustomEmojiDataStore(context: Context): DataStore<Preferences> = PreferenceDataStoreFactory.create(
migrations = listOf(SharedPreferencesMigration(context, "org.geeksville.emoji.prefs")),
scope = scope,
produceFile = { context.preferencesDataStoreFile("custom_emoji_ds") },
)
@Single
@Named("MapDataStore")
fun provideMapDataStore(context: Context): DataStore<Preferences> = PreferenceDataStoreFactory.create(
migrations = listOf(SharedPreferencesMigration(context, "map_prefs")),
scope = scope,
produceFile = { context.preferencesDataStoreFile("map_ds") },
)
@Single
@Named("MapConsentDataStore")
fun provideMapConsentDataStore(context: Context): DataStore<Preferences> = PreferenceDataStoreFactory.create(
migrations = listOf(SharedPreferencesMigration(context, "map_consent_preferences")),
scope = scope,
produceFile = { context.preferencesDataStoreFile("map_consent_ds") },
)
@Single
@Named("MapTileProviderDataStore")
fun provideMapTileProviderDataStore(context: Context): DataStore<Preferences> = PreferenceDataStoreFactory.create(
migrations = listOf(SharedPreferencesMigration(context, "map_tile_provider_prefs")),
scope = scope,
produceFile = { context.preferencesDataStoreFile("map_tile_provider_ds") },
)
@Single
@Named("MeshDataStore")
fun provideMeshDataStore(context: Context): DataStore<Preferences> = PreferenceDataStoreFactory.create(
migrations = listOf(SharedPreferencesMigration(context, "mesh-prefs")),
scope = scope,
produceFile = { context.preferencesDataStoreFile("mesh_ds") },
)
@Single
@Named("RadioDataStore")
fun provideRadioDataStore(context: Context): DataStore<Preferences> = PreferenceDataStoreFactory.create(
migrations = listOf(SharedPreferencesMigration(context, "radio-prefs")),
scope = scope,
produceFile = { context.preferencesDataStoreFile("radio_ds") },
)
@Single
@Named("UiDataStore")
fun provideUiDataStore(context: Context): DataStore<Preferences> = PreferenceDataStoreFactory.create(
migrations = listOf(SharedPreferencesMigration(context, "ui-prefs")),
scope = scope,
produceFile = { context.preferencesDataStoreFile("ui_ds") },
)
@Single
@Named("MeshLogDataStore")
fun provideMeshLogDataStore(context: Context): DataStore<Preferences> = PreferenceDataStoreFactory.create(
migrations = listOf(SharedPreferencesMigration(context, "meshlog-prefs")),
scope = scope,
produceFile = { context.preferencesDataStoreFile("meshlog_ds") },
)
@Single
@Named("FilterDataStore")
fun provideFilterDataStore(context: Context): DataStore<Preferences> = PreferenceDataStoreFactory.create(
migrations = listOf(SharedPreferencesMigration(context, "filter-prefs")),
scope = scope,
produceFile = { context.preferencesDataStoreFile("filter_ds") },
)
}

View file

@ -28,20 +28,16 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import org.koin.core.annotation.Named
import org.koin.core.annotation.Single
import org.meshtastic.core.di.CoroutineDispatchers
import org.meshtastic.core.prefs.di.AnalyticsDataStore
import org.meshtastic.core.prefs.di.AppDataStore
import org.meshtastic.core.repository.AnalyticsPrefs
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.uuid.Uuid
@Singleton
class AnalyticsPrefsImpl
@Inject
constructor(
@AnalyticsDataStore private val analyticsDataStore: DataStore<Preferences>,
@AppDataStore private val appDataStore: DataStore<Preferences>,
@Single
class AnalyticsPrefsImpl(
@Named("AnalyticsDataStore") private val analyticsDataStore: DataStore<Preferences>,
@Named("AppDataStore") private val appDataStore: DataStore<Preferences>,
dispatchers: CoroutineDispatchers,
) : AnalyticsPrefs {
private val scope = CoroutineScope(SupervisorJob() + dispatchers.default)

View file

@ -0,0 +1,24 @@
/*
* Copyright (c) 2026 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 org.meshtastic.core.prefs.di
import org.koin.core.annotation.ComponentScan
import org.koin.core.annotation.Module
@Module
@ComponentScan("org.meshtastic.core.prefs")
class CorePrefsModule

View file

@ -27,17 +27,14 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import org.koin.core.annotation.Named
import org.koin.core.annotation.Single
import org.meshtastic.core.di.CoroutineDispatchers
import org.meshtastic.core.prefs.di.CustomEmojiDataStore
import org.meshtastic.core.repository.CustomEmojiPrefs
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class CustomEmojiPrefsImpl
@Inject
constructor(
@CustomEmojiDataStore private val dataStore: DataStore<Preferences>,
@Single
class CustomEmojiPrefsImpl(
@Named("CustomEmojiDataStore") private val dataStore: DataStore<Preferences>,
dispatchers: CoroutineDispatchers,
) : CustomEmojiPrefs {
private val scope = CoroutineScope(SupervisorJob() + dispatchers.default)

View file

@ -28,17 +28,14 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import org.koin.core.annotation.Named
import org.koin.core.annotation.Single
import org.meshtastic.core.di.CoroutineDispatchers
import org.meshtastic.core.prefs.di.FilterDataStore
import org.meshtastic.core.repository.FilterPrefs
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class FilterPrefsImpl
@Inject
constructor(
@FilterDataStore private val dataStore: DataStore<Preferences>,
@Single
class FilterPrefsImpl(
@Named("FilterDataStore") private val dataStore: DataStore<Preferences>,
dispatchers: CoroutineDispatchers,
) : FilterPrefs {
private val scope = CoroutineScope(SupervisorJob() + dispatchers.default)

View file

@ -27,17 +27,14 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import org.koin.core.annotation.Named
import org.koin.core.annotation.Single
import org.meshtastic.core.di.CoroutineDispatchers
import org.meshtastic.core.prefs.di.HomoglyphEncodingDataStore
import org.meshtastic.core.repository.HomoglyphPrefs
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class HomoglyphPrefsImpl
@Inject
constructor(
@HomoglyphEncodingDataStore private val dataStore: DataStore<Preferences>,
@Single
class HomoglyphPrefsImpl(
@Named("HomoglyphEncodingDataStore") private val dataStore: DataStore<Preferences>,
dispatchers: CoroutineDispatchers,
) : HomoglyphPrefs {
private val scope = CoroutineScope(SupervisorJob() + dispatchers.default)

View file

@ -27,18 +27,15 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import org.koin.core.annotation.Named
import org.koin.core.annotation.Single
import org.meshtastic.core.di.CoroutineDispatchers
import org.meshtastic.core.prefs.di.MapConsentDataStore
import org.meshtastic.core.repository.MapConsentPrefs
import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class MapConsentPrefsImpl
@Inject
constructor(
@MapConsentDataStore private val dataStore: DataStore<Preferences>,
@Single
class MapConsentPrefsImpl(
@Named("MapConsentDataStore") private val dataStore: DataStore<Preferences>,
dispatchers: CoroutineDispatchers,
) : MapConsentPrefs {
private val scope = CoroutineScope(SupervisorJob() + dispatchers.default)

View file

@ -29,17 +29,14 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import org.koin.core.annotation.Named
import org.koin.core.annotation.Single
import org.meshtastic.core.di.CoroutineDispatchers
import org.meshtastic.core.prefs.di.MapDataStore
import org.meshtastic.core.repository.MapPrefs
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class MapPrefsImpl
@Inject
constructor(
@MapDataStore private val dataStore: DataStore<Preferences>,
@Single
class MapPrefsImpl(
@Named("MapDataStore") private val dataStore: DataStore<Preferences>,
dispatchers: CoroutineDispatchers,
) : MapPrefs {
private val scope = CoroutineScope(SupervisorJob() + dispatchers.default)

View file

@ -27,17 +27,14 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import org.koin.core.annotation.Named
import org.koin.core.annotation.Single
import org.meshtastic.core.di.CoroutineDispatchers
import org.meshtastic.core.prefs.di.MapTileProviderDataStore
import org.meshtastic.core.repository.MapTileProviderPrefs
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class MapTileProviderPrefsImpl
@Inject
constructor(
@MapTileProviderDataStore private val dataStore: DataStore<Preferences>,
@Single
class MapTileProviderPrefsImpl(
@Named("MapTileProviderDataStore") private val dataStore: DataStore<Preferences>,
dispatchers: CoroutineDispatchers,
) : MapTileProviderPrefs {
private val scope = CoroutineScope(SupervisorJob() + dispatchers.default)

View file

@ -29,19 +29,16 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import org.koin.core.annotation.Named
import org.koin.core.annotation.Single
import org.meshtastic.core.di.CoroutineDispatchers
import org.meshtastic.core.prefs.di.MeshDataStore
import org.meshtastic.core.repository.MeshPrefs
import java.util.Locale
import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class MeshPrefsImpl
@Inject
constructor(
@MeshDataStore private val dataStore: DataStore<Preferences>,
@Single
class MeshPrefsImpl(
@Named("MeshDataStore") private val dataStore: DataStore<Preferences>,
dispatchers: CoroutineDispatchers,
) : MeshPrefs {
private val scope = CoroutineScope(SupervisorJob() + dispatchers.default)

View file

@ -28,17 +28,14 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import org.koin.core.annotation.Named
import org.koin.core.annotation.Single
import org.meshtastic.core.di.CoroutineDispatchers
import org.meshtastic.core.prefs.di.MeshLogDataStore
import org.meshtastic.core.repository.MeshLogPrefs
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class MeshLogPrefsImpl
@Inject
constructor(
@MeshLogDataStore private val dataStore: DataStore<Preferences>,
@Single
class MeshLogPrefsImpl(
@Named("MeshLogDataStore") private val dataStore: DataStore<Preferences>,
dispatchers: CoroutineDispatchers,
) : MeshLogPrefs {
private val scope = CoroutineScope(SupervisorJob() + dispatchers.default)

View file

@ -27,17 +27,14 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import org.koin.core.annotation.Named
import org.koin.core.annotation.Single
import org.meshtastic.core.di.CoroutineDispatchers
import org.meshtastic.core.prefs.di.RadioDataStore
import org.meshtastic.core.repository.RadioPrefs
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class RadioPrefsImpl
@Inject
constructor(
@RadioDataStore private val dataStore: DataStore<Preferences>,
@Single
class RadioPrefsImpl(
@Named("RadioDataStore") private val dataStore: DataStore<Preferences>,
dispatchers: CoroutineDispatchers,
) : RadioPrefs {
private val scope = CoroutineScope(SupervisorJob() + dispatchers.default)

View file

@ -27,18 +27,15 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import org.koin.core.annotation.Named
import org.koin.core.annotation.Single
import org.meshtastic.core.di.CoroutineDispatchers
import org.meshtastic.core.prefs.di.UiDataStore
import org.meshtastic.core.repository.UiPrefs
import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class UiPrefsImpl
@Inject
constructor(
@UiDataStore private val dataStore: DataStore<Preferences>,
@Single
class UiPrefsImpl(
@Named("UiDataStore") private val dataStore: DataStore<Preferences>,
dispatchers: CoroutineDispatchers,
) : UiPrefs {
private val scope = CoroutineScope(SupervisorJob() + dispatchers.default)