Refactor preferences module
This commit is contained in:
@@ -4,6 +4,7 @@ import android.content.Context
|
||||
import android.location.Geocoder
|
||||
import de.mm20.launcher2.crashreporter.CrashReporter
|
||||
import de.mm20.launcher2.ktx.formatToString
|
||||
import de.mm20.launcher2.preferences.weather.WeatherLocation
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.IOException
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
package de.mm20.launcher2.weather
|
||||
|
||||
import de.mm20.launcher2.backup.Backupable
|
||||
import de.mm20.launcher2.weather.brightsky.BrightSkyProvider
|
||||
import de.mm20.launcher2.weather.here.HereProvider
|
||||
import de.mm20.launcher2.weather.metno.MetNoProvider
|
||||
import de.mm20.launcher2.weather.openweathermap.OpenWeatherMapProvider
|
||||
import de.mm20.launcher2.weather.plugin.PluginWeatherProvider
|
||||
import de.mm20.launcher2.weather.settings.WeatherSettings
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.core.qualifier.named
|
||||
import org.koin.dsl.module
|
||||
|
||||
val weatherModule = module {
|
||||
single<WeatherRepository> { WeatherRepositoryImpl(androidContext(), get(), get(), get()) }
|
||||
single<WeatherSettings> { WeatherSettings(androidContext()) }
|
||||
factory<Backupable>(named<WeatherSettings>()) { get<WeatherSettings>() }
|
||||
factory<WeatherProvider> { (providerId: String) ->
|
||||
when (providerId) {
|
||||
OpenWeatherMapProvider.Id -> OpenWeatherMapProvider(androidContext())
|
||||
|
||||
@@ -1,16 +1,2 @@
|
||||
package de.mm20.launcher2.weather
|
||||
|
||||
sealed interface WeatherLocation {
|
||||
val name: String
|
||||
|
||||
data class LatLon(
|
||||
override val name: String,
|
||||
val lat: Double,
|
||||
val lon: Double,
|
||||
) : WeatherLocation
|
||||
|
||||
data class Id(
|
||||
override val name: String,
|
||||
val locationId: String,
|
||||
) : WeatherLocation
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package de.mm20.launcher2.weather
|
||||
|
||||
import de.mm20.launcher2.preferences.weather.WeatherLocation
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.get
|
||||
import org.koin.core.parameter.parametersOf
|
||||
|
||||
@@ -13,13 +13,13 @@ import de.mm20.launcher2.permissions.PermissionGroup
|
||||
import de.mm20.launcher2.permissions.PermissionsManager
|
||||
import de.mm20.launcher2.plugin.PluginRepository
|
||||
import de.mm20.launcher2.plugin.PluginType
|
||||
import de.mm20.launcher2.preferences.LatLon
|
||||
import de.mm20.launcher2.preferences.weather.WeatherLocation
|
||||
import de.mm20.launcher2.preferences.weather.WeatherSettings
|
||||
import de.mm20.launcher2.weather.brightsky.BrightSkyProvider
|
||||
import de.mm20.launcher2.weather.here.HereProvider
|
||||
import de.mm20.launcher2.weather.metno.MetNoProvider
|
||||
import de.mm20.launcher2.weather.openweathermap.OpenWeatherMapProvider
|
||||
import de.mm20.launcher2.weather.settings.LatLon
|
||||
import de.mm20.launcher2.weather.settings.ProviderSettings
|
||||
import de.mm20.launcher2.weather.settings.WeatherSettings
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.*
|
||||
import org.koin.core.component.KoinComponent
|
||||
@@ -65,7 +65,7 @@ internal class WeatherRepositoryImpl(
|
||||
}
|
||||
|
||||
override fun searchLocations(query: String): Flow<List<WeatherLocation>> {
|
||||
return settings.data.map {
|
||||
return settings.map {
|
||||
val provider = WeatherProvider.getInstance(it.provider)
|
||||
provider.findLocation(query)
|
||||
}
|
||||
@@ -86,7 +86,7 @@ internal class WeatherRepositoryImpl(
|
||||
}
|
||||
}
|
||||
scope.launch {
|
||||
settings.data.collectLatest {
|
||||
settings.collectLatest {
|
||||
requestUpdate()
|
||||
}
|
||||
}
|
||||
@@ -178,7 +178,7 @@ class WeatherUpdateWorker(val context: Context, params: WorkerParameters) :
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
Log.d("WeatherUpdateWorker", "Requesting weather data")
|
||||
val settingsData = settings.data.first()
|
||||
val settingsData = settings.first()
|
||||
val provider = WeatherProvider.getInstance(settingsData.provider)
|
||||
|
||||
val updateInterval = provider.getUpdateInterval()
|
||||
|
||||
@@ -5,10 +5,10 @@ import android.icu.text.SimpleDateFormat
|
||||
import android.icu.util.Calendar
|
||||
import android.util.Log
|
||||
import de.mm20.launcher2.crashreporter.CrashReporter
|
||||
import de.mm20.launcher2.preferences.weather.WeatherLocation
|
||||
import de.mm20.launcher2.weather.Forecast
|
||||
import de.mm20.launcher2.weather.GeocoderWeatherProvider
|
||||
import de.mm20.launcher2.weather.R
|
||||
import de.mm20.launcher2.weather.WeatherLocation
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import retrofit2.create
|
||||
|
||||
@@ -3,9 +3,9 @@ package de.mm20.launcher2.weather.here
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import de.mm20.launcher2.crashreporter.CrashReporter
|
||||
import de.mm20.launcher2.preferences.weather.WeatherLocation
|
||||
import de.mm20.launcher2.weather.Forecast
|
||||
import de.mm20.launcher2.weather.R
|
||||
import de.mm20.launcher2.weather.WeatherLocation
|
||||
import de.mm20.launcher2.weather.WeatherProvider
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
|
||||
@@ -7,13 +7,11 @@ import android.util.Base64
|
||||
import android.util.Log
|
||||
import androidx.annotation.WorkerThread
|
||||
import de.mm20.launcher2.crashreporter.CrashReporter
|
||||
import de.mm20.launcher2.preferences.weather.WeatherLocation
|
||||
import de.mm20.launcher2.preferences.weather.WeatherSettings
|
||||
import de.mm20.launcher2.weather.Forecast
|
||||
import de.mm20.launcher2.weather.GeocoderWeatherProvider
|
||||
import de.mm20.launcher2.weather.R
|
||||
import de.mm20.launcher2.weather.WeatherLocation
|
||||
import de.mm20.launcher2.weather.WeatherProvider
|
||||
import de.mm20.launcher2.weather.settings.ProviderSettings
|
||||
import de.mm20.launcher2.weather.settings.WeatherSettings
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
+1
-1
@@ -3,9 +3,9 @@ package de.mm20.launcher2.weather.openweathermap
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import de.mm20.launcher2.crashreporter.CrashReporter
|
||||
import de.mm20.launcher2.preferences.weather.WeatherLocation
|
||||
import de.mm20.launcher2.weather.Forecast
|
||||
import de.mm20.launcher2.weather.R
|
||||
import de.mm20.launcher2.weather.WeatherLocation
|
||||
import de.mm20.launcher2.weather.WeatherProvider
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
|
||||
+1
-1
@@ -13,8 +13,8 @@ import de.mm20.launcher2.crashreporter.CrashReporter
|
||||
import de.mm20.launcher2.plugin.config.WeatherPluginConfig
|
||||
import de.mm20.launcher2.plugin.contracts.PluginContract
|
||||
import de.mm20.launcher2.plugin.contracts.WeatherPluginContract
|
||||
import de.mm20.launcher2.preferences.weather.WeatherLocation
|
||||
import de.mm20.launcher2.weather.Forecast
|
||||
import de.mm20.launcher2.weather.WeatherLocation
|
||||
import de.mm20.launcher2.weather.WeatherProvider
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
package de.mm20.launcher2.weather.settings
|
||||
|
||||
import android.content.Context
|
||||
import de.mm20.launcher2.settings.BaseSettings
|
||||
import de.mm20.launcher2.weather.WeatherLocation
|
||||
import de.mm20.launcher2.weather.WeatherProviderInfo
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
class WeatherSettings(
|
||||
private val context: Context,
|
||||
) : BaseSettings<WeatherSettingsData>(
|
||||
context,
|
||||
"weather_settings.json",
|
||||
WeatherSettingsSerializer,
|
||||
emptyList(),
|
||||
) {
|
||||
internal val data
|
||||
get() = context.dataStore.data
|
||||
|
||||
val location = data.map {
|
||||
val providerSettings = it.providerSettings[it.provider]
|
||||
val id = providerSettings?.locationId
|
||||
val name = providerSettings?.locationName
|
||||
|
||||
if (id != null && name != null) {
|
||||
WeatherLocation.Id(name, id)
|
||||
} else if (it.location != null && it.locationName != null) {
|
||||
WeatherLocation.LatLon(it.locationName, it.location.lat, it.location.lon)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
val autoLocation = data.map { it.autoLocation }
|
||||
|
||||
fun setLocation(location: WeatherLocation) {
|
||||
updateData {
|
||||
val providerSettings =
|
||||
it.providerSettings.getOrDefault(it.provider, ProviderSettings())
|
||||
when (location) {
|
||||
is WeatherLocation.LatLon -> {
|
||||
it.copy(
|
||||
location = LatLon(lat = location.lat, lon = location.lon),
|
||||
locationName = location.name,
|
||||
lastUpdate = 0L,
|
||||
autoLocation = false,
|
||||
providerSettings = it.providerSettings.toMutableMap().apply {
|
||||
put(
|
||||
it.provider,
|
||||
providerSettings.copy(
|
||||
locationId = null,
|
||||
locationName = null,
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
is WeatherLocation.Id -> {
|
||||
it.copy(
|
||||
location = null,
|
||||
locationName = null,
|
||||
autoLocation = false,
|
||||
lastUpdate = 0L,
|
||||
providerSettings = it.providerSettings.toMutableMap().apply {
|
||||
put(
|
||||
it.provider,
|
||||
providerSettings.copy(
|
||||
locationId = location.locationId,
|
||||
locationName = location.name
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setLastLocation(location: LatLon) {
|
||||
updateData {
|
||||
it.copy(
|
||||
lastLocation = location,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val lastUpdate = data.map { it.lastUpdate }
|
||||
|
||||
fun setLastUpdate(lastUpdate: Long) {
|
||||
updateData {
|
||||
it.copy(lastUpdate = lastUpdate)
|
||||
}
|
||||
}
|
||||
|
||||
val providerId = data.map { it.provider }
|
||||
|
||||
fun setProvider(provider: WeatherProviderInfo) {
|
||||
setProviderId(provider.id)
|
||||
}
|
||||
|
||||
fun setAutoLocation(autoLocation: Boolean) {
|
||||
updateData {
|
||||
it.copy(
|
||||
autoLocation = autoLocation,
|
||||
lastUpdate = 0L,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun setProviderId(providerId: String) {
|
||||
updateData {
|
||||
it.copy(
|
||||
provider = providerId,
|
||||
lastUpdate = 0L,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package de.mm20.launcher2.weather.settings
|
||||
|
||||
import androidx.datastore.core.CorruptionException
|
||||
import androidx.datastore.core.Serializer
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.SerializationException
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.decodeFromStream
|
||||
import kotlinx.serialization.json.encodeToStream
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
|
||||
|
||||
@Serializable
|
||||
data class LatLon(
|
||||
val lat: Double,
|
||||
val lon: Double,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ProviderSettings(
|
||||
val locationId: String? = null,
|
||||
val locationName: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class WeatherSettingsData(
|
||||
val schemaVersion: Int = 1,
|
||||
val provider: String = "metno",
|
||||
val autoLocation: Boolean = true,
|
||||
val location: LatLon? = null,
|
||||
val locationName: String? = null,
|
||||
val lastLocation: LatLon? = null,
|
||||
val lastUpdate: Long = 0L,
|
||||
val providerSettings: Map<String, ProviderSettings> = emptyMap(),
|
||||
)
|
||||
|
||||
internal object WeatherSettingsSerializer : Serializer<WeatherSettingsData>{
|
||||
internal val json = Json {
|
||||
ignoreUnknownKeys = true
|
||||
encodeDefaults = true
|
||||
}
|
||||
|
||||
override val defaultValue: WeatherSettingsData
|
||||
get() = WeatherSettingsData()
|
||||
|
||||
override suspend fun readFrom(input: InputStream): WeatherSettingsData {
|
||||
try {
|
||||
return json.decodeFromStream(input)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
throw (CorruptionException("Cannot read json.", e))
|
||||
} catch (e: SerializationException) {
|
||||
throw (CorruptionException("Cannot read json.", e))
|
||||
} catch (e: IOException) {
|
||||
throw (CorruptionException("Cannot read json.", e))
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun writeTo(t: WeatherSettingsData, output: OutputStream) {
|
||||
json.encodeToStream(t, output)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user