diff --git a/app/src/google/java/com/geeksville/mesh/di/MapModule.kt b/app/src/google/java/com/geeksville/mesh/di/MapModule.kt
index 6576f1dc1..0ef9b5c94 100644
--- a/app/src/google/java/com/geeksville/mesh/di/MapModule.kt
+++ b/app/src/google/java/com/geeksville/mesh/di/MapModule.kt
@@ -17,9 +17,6 @@
package com.geeksville.mesh.di
-import com.geeksville.mesh.repository.map.CustomTileProviderRepository
-import com.geeksville.mesh.repository.map.SharedPreferencesCustomTileProviderRepository
-import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@@ -35,14 +32,3 @@ object MapModule {
@Provides @Singleton
fun provideJson(): Json = Json { prettyPrint = false }
}
-
-@Module
-@InstallIn(SingletonComponent::class)
-abstract class MapRepositoryModule {
-
- @Binds
- @Singleton
- abstract fun bindCustomTileProviderRepository(
- impl: SharedPreferencesCustomTileProviderRepository,
- ): CustomTileProviderRepository
-}
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 3d7cb4bb3..bc8cc637b 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
@@ -26,7 +26,6 @@ import com.geeksville.mesh.android.BuildUtils.debug
import com.geeksville.mesh.database.NodeRepository
import com.geeksville.mesh.database.PacketRepository
import com.geeksville.mesh.repository.datastore.RadioConfigRepository
-import com.geeksville.mesh.repository.map.CustomTileProviderRepository
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.model.TileProvider
import com.google.android.gms.maps.model.UrlTileProvider
@@ -50,6 +49,8 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.serialization.Serializable
import org.json.JSONObject
+import org.meshtastic.core.data.model.CustomTileProviderConfig
+import org.meshtastic.core.data.repository.CustomTileProviderRepository
import org.meshtastic.core.prefs.map.GoogleMapsPrefs
import org.meshtastic.core.prefs.map.MapPrefs
import timber.log.Timber
@@ -510,10 +511,3 @@ data class MapLayerItem(
var geoJsonLayerData: GeoJsonLayer? = null,
val layerType: LayerType,
)
-
-@Serializable
-data class CustomTileProviderConfig(
- val id: String = UUID.randomUUID().toString(),
- val name: String,
- val urlTemplate: String,
-)
diff --git a/app/src/google/java/com/geeksville/mesh/ui/map/components/CustomTileProviderManagerSheet.kt b/app/src/google/java/com/geeksville/mesh/ui/map/components/CustomTileProviderManagerSheet.kt
index 63f0d57e3..cad2a5fdb 100644
--- a/app/src/google/java/com/geeksville/mesh/ui/map/components/CustomTileProviderManagerSheet.kt
+++ b/app/src/google/java/com/geeksville/mesh/ui/map/components/CustomTileProviderManagerSheet.kt
@@ -51,9 +51,9 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import com.geeksville.mesh.ui.map.CustomTileProviderConfig
import com.geeksville.mesh.ui.map.MapViewModel
import kotlinx.coroutines.flow.collectLatest
+import org.meshtastic.core.data.model.CustomTileProviderConfig
import org.meshtastic.core.strings.R
@Suppress("LongMethod")
diff --git a/core/data/build.gradle.kts b/core/data/build.gradle.kts
index 313d80686..76c2256a4 100644
--- a/core/data/build.gradle.kts
+++ b/core/data/build.gradle.kts
@@ -17,9 +17,18 @@
plugins {
alias(libs.plugins.meshtastic.android.library)
+ alias(libs.plugins.meshtastic.hilt)
+ alias(libs.plugins.meshtastic.kotlinx.serialization)
alias(libs.plugins.kover)
}
android { namespace = "org.meshtastic.core.data" }
-dependencies {}
+dependencies {
+ implementation(projects.core.di)
+ implementation(projects.core.prefs)
+
+ implementation(libs.kotlinx.coroutines.android)
+ implementation(libs.kotlinx.serialization.json)
+ implementation(libs.timber)
+}
diff --git a/app/src/google/java/com/geeksville/mesh/repository/map/CustomTileProviderRepository.kt b/core/data/src/google/kotlin/org/meshtastic/core/data/di/GoogleDataModule.kt
similarity index 56%
rename from app/src/google/java/com/geeksville/mesh/repository/map/CustomTileProviderRepository.kt
rename to core/data/src/google/kotlin/org/meshtastic/core/data/di/GoogleDataModule.kt
index fc58be2ca..ef67c2e6a 100644
--- a/app/src/google/java/com/geeksville/mesh/repository/map/CustomTileProviderRepository.kt
+++ b/core/data/src/google/kotlin/org/meshtastic/core/data/di/GoogleDataModule.kt
@@ -15,19 +15,21 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.repository.map
+package org.meshtastic.core.data.di
-import com.geeksville.mesh.ui.map.CustomTileProviderConfig
-import kotlinx.coroutines.flow.Flow
+import dagger.Binds
+import dagger.Module
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import org.meshtastic.core.data.repository.CustomTileProviderRepository
+import org.meshtastic.core.data.repository.CustomTileProviderRepositoryImpl
+import javax.inject.Singleton
-interface CustomTileProviderRepository {
- fun getCustomTileProviders(): Flow>
+@Module
+@InstallIn(SingletonComponent::class)
+interface GoogleDataModule {
- suspend fun addCustomTileProvider(config: CustomTileProviderConfig)
-
- suspend fun updateCustomTileProvider(config: CustomTileProviderConfig)
-
- suspend fun deleteCustomTileProvider(configId: String)
-
- suspend fun getCustomTileProviderById(configId: String): CustomTileProviderConfig?
+ @Binds
+ @Singleton
+ fun bindCustomTileProviderRepository(impl: CustomTileProviderRepositoryImpl): CustomTileProviderRepository
}
diff --git a/core/data/src/google/kotlin/org/meshtastic/core/data/model/CustomTileProviderConfig.kt b/core/data/src/google/kotlin/org/meshtastic/core/data/model/CustomTileProviderConfig.kt
new file mode 100644
index 000000000..0e0e2f388
--- /dev/null
+++ b/core/data/src/google/kotlin/org/meshtastic/core/data/model/CustomTileProviderConfig.kt
@@ -0,0 +1,28 @@
+/*
+ * 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.data.model
+
+import kotlinx.serialization.Serializable
+import java.util.UUID
+
+@Serializable
+data class CustomTileProviderConfig(
+ val id: String = UUID.randomUUID().toString(),
+ val name: String,
+ val urlTemplate: String,
+)
diff --git a/app/src/google/java/com/geeksville/mesh/repository/map/SharedPreferencesCustomTileProviderRepository.kt b/core/data/src/google/kotlin/org/meshtastic/core/data/repository/CustomTileProviderRepository.kt
similarity index 82%
rename from app/src/google/java/com/geeksville/mesh/repository/map/SharedPreferencesCustomTileProviderRepository.kt
rename to core/data/src/google/kotlin/org/meshtastic/core/data/repository/CustomTileProviderRepository.kt
index 8c768c16e..f2c0262a8 100644
--- a/app/src/google/java/com/geeksville/mesh/repository/map/SharedPreferencesCustomTileProviderRepository.kt
+++ b/core/data/src/google/kotlin/org/meshtastic/core/data/repository/CustomTileProviderRepository.kt
@@ -15,9 +15,8 @@
* along with this program. If not, see .
*/
-package com.geeksville.mesh.repository.map
+package org.meshtastic.core.data.repository
-import com.geeksville.mesh.ui.map.CustomTileProviderConfig
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -25,14 +24,28 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.withContext
import kotlinx.serialization.SerializationException
import kotlinx.serialization.json.Json
+import org.meshtastic.core.data.model.CustomTileProviderConfig
import org.meshtastic.core.di.annotation.IoDispatcher
import org.meshtastic.core.prefs.map.MapTileProviderPrefs
import timber.log.Timber
import javax.inject.Inject
import javax.inject.Singleton
+import kotlin.collections.plus
+
+interface CustomTileProviderRepository {
+ fun getCustomTileProviders(): Flow>
+
+ suspend fun addCustomTileProvider(config: CustomTileProviderConfig)
+
+ suspend fun updateCustomTileProvider(config: CustomTileProviderConfig)
+
+ suspend fun deleteCustomTileProvider(configId: String)
+
+ suspend fun getCustomTileProviderById(configId: String): CustomTileProviderConfig?
+}
@Singleton
-class SharedPreferencesCustomTileProviderRepository
+class CustomTileProviderRepositoryImpl
@Inject
constructor(
private val json: Json,
@@ -46,31 +59,6 @@ constructor(
loadDataFromPrefs()
}
- private fun loadDataFromPrefs() {
- val jsonString = mapTileProviderPrefs.customTileProviders
- if (jsonString != null) {
- try {
- customTileProvidersStateFlow.value = json.decodeFromString>(jsonString)
- } catch (e: SerializationException) {
- Timber.tag("TileRepo").e(e, "Error deserializing tile providers")
- customTileProvidersStateFlow.value = emptyList()
- }
- } else {
- customTileProvidersStateFlow.value = emptyList()
- }
- }
-
- private suspend fun saveDataToPrefs(providers: List) {
- withContext(ioDispatcher) {
- try {
- val jsonString = json.encodeToString(providers)
- mapTileProviderPrefs.customTileProviders = jsonString
- } catch (e: SerializationException) {
- Timber.tag("TileRepo").e(e, "Error serializing tile providers")
- }
- }
- }
-
override fun getCustomTileProviders(): Flow> =
customTileProvidersStateFlow.asStateFlow()
@@ -94,4 +82,29 @@ constructor(
override suspend fun getCustomTileProviderById(configId: String): CustomTileProviderConfig? =
customTileProvidersStateFlow.value.find { it.id == configId }
+
+ private fun loadDataFromPrefs() {
+ val jsonString = mapTileProviderPrefs.customTileProviders
+ if (jsonString != null) {
+ try {
+ customTileProvidersStateFlow.value = json.decodeFromString>(jsonString)
+ } catch (e: SerializationException) {
+ Timber.e(e, "Error deserializing tile providers")
+ customTileProvidersStateFlow.value = emptyList()
+ }
+ } else {
+ customTileProvidersStateFlow.value = emptyList()
+ }
+ }
+
+ private suspend fun saveDataToPrefs(providers: List) {
+ withContext(ioDispatcher) {
+ try {
+ val jsonString = json.encodeToString(providers)
+ mapTileProviderPrefs.customTileProviders = jsonString
+ } catch (e: SerializationException) {
+ Timber.e(e, "Error serializing tile providers")
+ }
+ }
+ }
}