fix #15: Replace precipitation and temperature unit settings with location rounding setting

This commit is contained in:
Tim Kluge 2024-12-19 22:32:10 +01:00
parent 9624b7ec7d
commit d1cf6aa6d6
8 changed files with 67 additions and 49 deletions

View File

@ -33,7 +33,7 @@ If you are using a Karoo 2, you can use manual sideloading:
After installing this app on your Karoo and opening it once from the main menu, you can add the following new data fields to your data pages: After installing this app on your Karoo and opening it once from the main menu, you can add the following new data fields to your data pages:
- Headwind (graphical, 1x1 field): Shows the headwind direction and speed as a circle with a triangular direction indicator. The speed is shown at the center in your set unit of measurement (default is kilometers per hour if you have set up metric units in your Karoo, otherwise miles per hour). Both direction and speed are relative to the current riding direction. - Headwind (graphical, 1x1 field): Shows the headwind direction and speed as a circle with a triangular direction indicator. The speed is shown at the center in your set unit of measurement (default is kilometers per hour if you have set up metric units in your Karoo, otherwise miles per hour). Both direction and speed are relative to the current riding direction by default, i. e., riding directly into a wind of 20 km/h will show a headwind speed of 20 km/h, while riding in the same direction will show -20 km/h. You can change this behavior in the app settings to show the absolute wind speed instead.
- Weather forecast (graphical, 2x1 field): Shows three columns indicating the current weather conditions (sunny, cloudy, ...), wind direction, precipitation and temperature forecasted for the next three hours. Tap on this widget to cycle through the 12 hour forecast. - Weather forecast (graphical, 2x1 field): Shows three columns indicating the current weather conditions (sunny, cloudy, ...), wind direction, precipitation and temperature forecasted for the next three hours. Tap on this widget to cycle through the 12 hour forecast.
- Additionally, data fields that only show the current data value for headwind speed, humidity, cloud cover, absolute wind speed, absolute wind gust speed, absolute wind direction, rainfall and surface pressure can be added if desired. - Additionally, data fields that only show the current data value for headwind speed, humidity, cloud cover, absolute wind speed, absolute wind gust speed, absolute wind direction, rainfall and surface pressure can be added if desired.

View File

@ -15,8 +15,8 @@ android {
applicationId = "de.timklge.karooheadwind" applicationId = "de.timklge.karooheadwind"
minSdk = 26 minSdk = 26
targetSdk = 35 targetSdk = 35
versionCode = 4 versionCode = 5
versionName = "1.1" versionName = "1.1.1"
} }
signingConfigs { signingConfigs {

View File

@ -3,8 +3,8 @@
"packageName": "de.timklge.karooheadwind", "packageName": "de.timklge.karooheadwind",
"iconUrl": "https://github.com/timklge/karoo-headwind/releases/latest/download/karoo-headwind.png", "iconUrl": "https://github.com/timklge/karoo-headwind/releases/latest/download/karoo-headwind.png",
"latestApkUrl": "https://github.com/timklge/karoo-headwind/releases/latest/download/app-release.apk", "latestApkUrl": "https://github.com/timklge/karoo-headwind/releases/latest/download/app-release.apk",
"latestVersion": "1.1", "latestVersion": "1.1.1",
"latestVersionCode": 4, "latestVersionCode": 5,
"developer": "timklge", "developer": "timklge",
"description": "Provides headwind direction, wind speed and other weather data fields", "description": "Provides headwind direction, wind speed and other weather data fields",
"releaseNotes": "Add hourly forecast and temperature datafields" "releaseNotes": "Add hourly forecast and temperature datafields"

View File

@ -122,12 +122,9 @@ fun Context.streamSettings(karooSystemService: KarooSystemService): Flow<Headwin
val defaultSettings = jsonWithUnknownKeys.decodeFromString<HeadwindSettings>(HeadwindSettings.defaultSettings) val defaultSettings = jsonWithUnknownKeys.decodeFromString<HeadwindSettings>(HeadwindSettings.defaultSettings)
val preferredUnits = karooSystemService.streamUserProfile().first().preferredUnit val preferredUnits = karooSystemService.streamUserProfile().first().preferredUnit
val preferredMetric = preferredUnits.distance == UserProfile.PreferredUnit.UnitType.METRIC
defaultSettings.copy( defaultSettings.copy(
windUnit = if (preferredUnits.distance == UserProfile.PreferredUnit.UnitType.METRIC) WindUnit.KILOMETERS_PER_HOUR else WindUnit.MILES_PER_HOUR, windUnit = if (preferredUnits.distance == UserProfile.PreferredUnit.UnitType.METRIC) WindUnit.KILOMETERS_PER_HOUR else WindUnit.MILES_PER_HOUR,
precipitationUnit = if (preferredMetric) PrecipitationUnit.MILLIMETERS else PrecipitationUnit.INCH,
temperatureUnit = if (preferredUnits.temperature == UserProfile.PreferredUnit.UnitType.METRIC) TemperatureUnit.CELSIUS else TemperatureUnit.FAHRENHEIT
) )
} }
} catch(e: Throwable){ } catch(e: Throwable){
@ -162,10 +159,13 @@ fun KarooSystemService.streamUserProfile(): Flow<UserProfile> {
} }
@OptIn(FlowPreview::class) @OptIn(FlowPreview::class)
suspend fun KarooSystemService.makeOpenMeteoHttpRequest(gpsCoordinates: GpsCoordinates, settings: HeadwindSettings): HttpResponseState.Complete { suspend fun KarooSystemService.makeOpenMeteoHttpRequest(gpsCoordinates: GpsCoordinates, settings: HeadwindSettings, profile: UserProfile?): HttpResponseState.Complete {
val precipitationUnit = if (profile?.preferredUnit?.distance != UserProfile.PreferredUnit.UnitType.IMPERIAL) PrecipitationUnit.MILLIMETERS else PrecipitationUnit.INCH
val temperatureUnit = if (profile?.preferredUnit?.temperature != UserProfile.PreferredUnit.UnitType.IMPERIAL) TemperatureUnit.CELSIUS else TemperatureUnit.FAHRENHEIT
return callbackFlow { return callbackFlow {
// https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41&current=surface_pressure,temperature_2m,relative_humidity_2m,precipitation,weather_code,cloud_cover,wind_speed_10m,wind_direction_10m,wind_gusts_10m&hourly=temperature_2m,precipitation_probability,precipitation,weather_code,wind_speed_10m,wind_direction_10m,wind_gusts_10m&timeformat=unixtime&past_hours=1&forecast_days=1&forecast_hours=12 // https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41&current=surface_pressure,temperature_2m,relative_humidity_2m,precipitation,weather_code,cloud_cover,wind_speed_10m,wind_direction_10m,wind_gusts_10m&hourly=temperature_2m,precipitation_probability,precipitation,weather_code,wind_speed_10m,wind_direction_10m,wind_gusts_10m&timeformat=unixtime&past_hours=1&forecast_days=1&forecast_hours=12
val url = "https://api.open-meteo.com/v1/forecast?latitude=${gpsCoordinates.lat}&longitude=${gpsCoordinates.lon}&current=surface_pressure,temperature_2m,relative_humidity_2m,precipitation,weather_code,cloud_cover,wind_speed_10m,wind_direction_10m,wind_gusts_10m&hourly=temperature_2m,precipitation_probability,precipitation,weather_code,wind_speed_10m,wind_direction_10m,wind_gusts_10m&timeformat=unixtime&past_hours=0&forecast_days=1&forecast_hours=12&wind_speed_unit=${settings.windUnit.id}&precipitation_unit=${settings.precipitationUnit.id}&temperature_unit=${settings.temperatureUnit.id}" val url = "https://api.open-meteo.com/v1/forecast?latitude=${gpsCoordinates.lat}&longitude=${gpsCoordinates.lon}&current=surface_pressure,temperature_2m,relative_humidity_2m,precipitation,weather_code,cloud_cover,wind_speed_10m,wind_direction_10m,wind_gusts_10m&hourly=temperature_2m,precipitation_probability,precipitation,weather_code,wind_speed_10m,wind_direction_10m,wind_gusts_10m&timeformat=unixtime&past_hours=0&forecast_days=1&forecast_hours=12&wind_speed_unit=${settings.windUnit.id}&precipitation_unit=${precipitationUnit.id}&temperature_unit=${temperatureUnit.id}"
Log.d(KarooHeadwindExtension.TAG, "Http request to ${url}...") Log.d(KarooHeadwindExtension.TAG, "Http request to ${url}...")
@ -246,7 +246,7 @@ fun KarooSystemService.getHeadingFlow(): Flow<Double> {
} }
@OptIn(FlowPreview::class) @OptIn(FlowPreview::class)
fun KarooSystemService.getGpsCoordinateFlow(): Flow<GpsCoordinates> { fun KarooSystemService.getGpsCoordinateFlow(context: Context): Flow<GpsCoordinates> {
// return flowOf(GpsCoordinates(52.5164069,13.3784)) // return flowOf(GpsCoordinates(52.5164069,13.3784))
return streamDataFlow(DataType.Type.LOCATION) return streamDataFlow(DataType.Type.LOCATION)
@ -263,7 +263,12 @@ fun KarooSystemService.getGpsCoordinateFlow(): Flow<GpsCoordinates> {
null null
} }
} }
.map { it.round() } .combine(context.streamSettings(this)) { gps, settings -> gps to settings }
.map { (gps, settings) ->
val rounded = gps.round(settings.roundLocationTo.km.toDouble())
Log.d(KarooHeadwindExtension.TAG, "Round location to ${settings.roundLocationTo.km} - $rounded")
rounded
}
.distinctUntilChanged { old, new -> old.distanceTo(new).absoluteValue < 0.001 } .distinctUntilChanged { old, new -> old.distanceTo(new).absoluteValue < 0.001 }
.debounce(Duration.ofSeconds(10)) .debounce(Duration.ofSeconds(10))
} }

View File

@ -14,9 +14,12 @@ import de.timklge.karooheadwind.datatypes.TemperatureDataType
import de.timklge.karooheadwind.datatypes.WeatherDataType import de.timklge.karooheadwind.datatypes.WeatherDataType
import de.timklge.karooheadwind.datatypes.WeatherForecastDataType import de.timklge.karooheadwind.datatypes.WeatherForecastDataType
import de.timklge.karooheadwind.datatypes.WindSpeedDataType import de.timklge.karooheadwind.datatypes.WindSpeedDataType
import de.timklge.karooheadwind.screens.HeadwindSettings
import de.timklge.karooheadwind.screens.HeadwindStats import de.timklge.karooheadwind.screens.HeadwindStats
import de.timklge.karooheadwind.screens.HeadwindWidgetSettings
import io.hammerhead.karooext.KarooSystemService import io.hammerhead.karooext.KarooSystemService
import io.hammerhead.karooext.extension.KarooExtension import io.hammerhead.karooext.extension.KarooExtension
import io.hammerhead.karooext.models.UserProfile
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
@ -32,7 +35,7 @@ import kotlinx.coroutines.launch
import kotlin.time.Duration.Companion.hours import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.minutes
class KarooHeadwindExtension : KarooExtension("karoo-headwind", "1.1") { class KarooHeadwindExtension : KarooExtension("karoo-headwind", "1.1.1") {
companion object { companion object {
const val TAG = "karoo-headwind" const val TAG = "karoo-headwind"
} }
@ -59,6 +62,9 @@ class KarooHeadwindExtension : KarooExtension("karoo-headwind", "1.1") {
) )
} }
data class StreamData(val settings: HeadwindSettings, val gps: GpsCoordinates,
val profile: UserProfile? = null)
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
@ -73,7 +79,7 @@ class KarooHeadwindExtension : KarooExtension("karoo-headwind", "1.1") {
} }
val gpsFlow = karooSystem val gpsFlow = karooSystem
.getGpsCoordinateFlow() .getGpsCoordinateFlow(this@KarooHeadwindExtension)
.transformLatest { value: GpsCoordinates -> .transformLatest { value: GpsCoordinates ->
while(true){ while(true){
emit(value) emit(value)
@ -83,8 +89,9 @@ class KarooHeadwindExtension : KarooExtension("karoo-headwind", "1.1") {
streamSettings(karooSystem) streamSettings(karooSystem)
.filter { it.welcomeDialogAccepted } .filter { it.welcomeDialogAccepted }
.combine(gpsFlow) { settings, gps -> settings to gps } .combine(gpsFlow) { settings, gps -> StreamData(settings, gps) }
.map { (settings, gps) -> .combine(karooSystem.streamUserProfile()) { data, profile -> data.copy(profile = profile) }
.map { (settings, gps, profile) ->
Log.d(TAG, "Acquired updated gps coordinates: $gps") Log.d(TAG, "Acquired updated gps coordinates: $gps")
val lastKnownStats = try { val lastKnownStats = try {
@ -94,7 +101,7 @@ class KarooHeadwindExtension : KarooExtension("karoo-headwind", "1.1") {
HeadwindStats() HeadwindStats()
} }
val response = karooSystem.makeOpenMeteoHttpRequest(gps, settings) val response = karooSystem.makeOpenMeteoHttpRequest(gps, settings, profile)
if (response.error != null){ if (response.error != null){
try { try {
val stats = lastKnownStats.copy(failedWeatherRequest = System.currentTimeMillis()) val stats = lastKnownStats.copy(failedWeatherRequest = System.currentTimeMillis())

View File

@ -14,8 +14,11 @@ import de.timklge.karooheadwind.KarooHeadwindExtension
import de.timklge.karooheadwind.OpenMeteoCurrentWeatherResponse import de.timklge.karooheadwind.OpenMeteoCurrentWeatherResponse
import de.timklge.karooheadwind.WeatherInterpretation import de.timklge.karooheadwind.WeatherInterpretation
import de.timklge.karooheadwind.screens.HeadwindSettings import de.timklge.karooheadwind.screens.HeadwindSettings
import de.timklge.karooheadwind.screens.PrecipitationUnit
import de.timklge.karooheadwind.screens.TemperatureUnit
import de.timklge.karooheadwind.streamCurrentWeatherData import de.timklge.karooheadwind.streamCurrentWeatherData
import de.timklge.karooheadwind.streamSettings import de.timklge.karooheadwind.streamSettings
import de.timklge.karooheadwind.streamUserProfile
import io.hammerhead.karooext.KarooSystemService import io.hammerhead.karooext.KarooSystemService
import io.hammerhead.karooext.extension.DataTypeImpl import io.hammerhead.karooext.extension.DataTypeImpl
import io.hammerhead.karooext.internal.Emitter import io.hammerhead.karooext.internal.Emitter
@ -24,6 +27,7 @@ import io.hammerhead.karooext.models.DataPoint
import io.hammerhead.karooext.models.DataType import io.hammerhead.karooext.models.DataType
import io.hammerhead.karooext.models.StreamState import io.hammerhead.karooext.models.StreamState
import io.hammerhead.karooext.models.UpdateGraphicConfig import io.hammerhead.karooext.models.UpdateGraphicConfig
import io.hammerhead.karooext.models.UserProfile
import io.hammerhead.karooext.models.ViewConfig import io.hammerhead.karooext.models.ViewConfig
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -75,17 +79,19 @@ class WeatherDataType(
de.timklge.karooheadwind.R.drawable.arrow_0 de.timklge.karooheadwind.R.drawable.arrow_0
) )
data class StreamData(val data: OpenMeteoCurrentWeatherResponse, val settings: HeadwindSettings) data class StreamData(val data: OpenMeteoCurrentWeatherResponse, val settings: HeadwindSettings,
val profile: UserProfile? = null)
val viewJob = CoroutineScope(Dispatchers.IO).launch { val viewJob = CoroutineScope(Dispatchers.IO).launch {
context.streamCurrentWeatherData() context.streamCurrentWeatherData()
.combine(context.streamSettings(karooSystem)) { data, settings -> StreamData(data, settings) } .combine(context.streamSettings(karooSystem)) { data, settings -> StreamData(data, settings) }
.combine(karooSystem.streamUserProfile()) { data, profile -> data.copy(profile = profile) }
.onCompletion { .onCompletion {
// Clear view on completion // Clear view on completion
val result = glance.compose(context, DpSize.Unspecified) { } val result = glance.compose(context, DpSize.Unspecified) { }
emitter.updateView(result.remoteViews) emitter.updateView(result.remoteViews)
} }
.collect { (data, settings) -> .collect { (data, settings, userProfile) ->
Log.d(KarooHeadwindExtension.TAG, "Updating weather view") Log.d(KarooHeadwindExtension.TAG, "Updating weather view")
val interpretation = WeatherInterpretation.fromWeatherCode(data.current.weatherCode) val interpretation = WeatherInterpretation.fromWeatherCode(data.current.weatherCode)
val formattedTime = timeFormatter.format(Instant.ofEpochSecond(data.current.time)) val formattedTime = timeFormatter.format(Instant.ofEpochSecond(data.current.time))
@ -100,9 +106,9 @@ class WeatherDataType(
windSpeedUnit = settings.windUnit, windSpeedUnit = settings.windUnit,
precipitation = data.current.precipitation, precipitation = data.current.precipitation,
precipitationProbability = null, precipitationProbability = null,
precipitationUnit = settings.precipitationUnit, precipitationUnit = if (userProfile?.preferredUnit?.distance != UserProfile.PreferredUnit.UnitType.IMPERIAL) PrecipitationUnit.MILLIMETERS else PrecipitationUnit.INCH,
temperature = data.current.temperature.roundToInt(), temperature = data.current.temperature.roundToInt(),
temperatureUnit = settings.temperatureUnit, temperatureUnit = if (userProfile?.preferredUnit?.temperature != UserProfile.PreferredUnit.UnitType.IMPERIAL) TemperatureUnit.CELSIUS else TemperatureUnit.FAHRENHEIT,
timeLabel = formattedTime timeLabel = formattedTime
) )
} }

View File

@ -34,8 +34,11 @@ import de.timklge.karooheadwind.saveSettings
import de.timklge.karooheadwind.saveWidgetSettings import de.timklge.karooheadwind.saveWidgetSettings
import de.timklge.karooheadwind.screens.HeadwindSettings import de.timklge.karooheadwind.screens.HeadwindSettings
import de.timklge.karooheadwind.screens.HeadwindWidgetSettings import de.timklge.karooheadwind.screens.HeadwindWidgetSettings
import de.timklge.karooheadwind.screens.PrecipitationUnit
import de.timklge.karooheadwind.screens.TemperatureUnit
import de.timklge.karooheadwind.streamCurrentWeatherData import de.timklge.karooheadwind.streamCurrentWeatherData
import de.timklge.karooheadwind.streamSettings import de.timklge.karooheadwind.streamSettings
import de.timklge.karooheadwind.streamUserProfile
import de.timklge.karooheadwind.streamWidgetSettings import de.timklge.karooheadwind.streamWidgetSettings
import io.hammerhead.karooext.KarooSystemService import io.hammerhead.karooext.KarooSystemService
import io.hammerhead.karooext.extension.DataTypeImpl import io.hammerhead.karooext.extension.DataTypeImpl
@ -45,6 +48,7 @@ import io.hammerhead.karooext.models.DataPoint
import io.hammerhead.karooext.models.DataType import io.hammerhead.karooext.models.DataType
import io.hammerhead.karooext.models.StreamState import io.hammerhead.karooext.models.StreamState
import io.hammerhead.karooext.models.UpdateGraphicConfig import io.hammerhead.karooext.models.UpdateGraphicConfig
import io.hammerhead.karooext.models.UserProfile
import io.hammerhead.karooext.models.ViewConfig import io.hammerhead.karooext.models.ViewConfig
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -118,18 +122,20 @@ class WeatherForecastDataType(
de.timklge.karooheadwind.R.drawable.arrow_0 de.timklge.karooheadwind.R.drawable.arrow_0
) )
data class StreamData(val data: OpenMeteoCurrentWeatherResponse, val settings: HeadwindSettings, val widgetSettings: HeadwindWidgetSettings? = null) data class StreamData(val data: OpenMeteoCurrentWeatherResponse, val settings: HeadwindSettings,
val widgetSettings: HeadwindWidgetSettings? = null, val profile: UserProfile? = null)
val viewJob = CoroutineScope(Dispatchers.IO).launch { val viewJob = CoroutineScope(Dispatchers.IO).launch {
context.streamCurrentWeatherData() context.streamCurrentWeatherData()
.combine(context.streamSettings(karooSystem)) { data, settings -> StreamData(data, settings) } .combine(context.streamSettings(karooSystem)) { data, settings -> StreamData(data, settings) }
.combine(karooSystem.streamUserProfile()) { data, profile -> data.copy(profile = profile) }
.combine(context.streamWidgetSettings()) { data, widgetSettings -> data.copy(widgetSettings = widgetSettings) } .combine(context.streamWidgetSettings()) { data, widgetSettings -> data.copy(widgetSettings = widgetSettings) }
.onCompletion { .onCompletion {
// Clear view on completion // Clear view on completion
val result = glance.compose(context, DpSize.Unspecified) { } val result = glance.compose(context, DpSize.Unspecified) { }
emitter.updateView(result.remoteViews) emitter.updateView(result.remoteViews)
} }
.collect { (data, settings, widgetSettings) -> .collect { (data, settings, widgetSettings, userProfile) ->
Log.d(KarooHeadwindExtension.TAG, "Updating weather view") Log.d(KarooHeadwindExtension.TAG, "Updating weather view")
val result = glance.compose(context, DpSize.Unspecified) { val result = glance.compose(context, DpSize.Unspecified) {
@ -161,9 +167,9 @@ class WeatherForecastDataType(
windSpeedUnit = settings.windUnit, windSpeedUnit = settings.windUnit,
precipitation = data.forecastData.precipitation[index], precipitation = data.forecastData.precipitation[index],
precipitationProbability = data.forecastData.precipitationProbability[index], precipitationProbability = data.forecastData.precipitationProbability[index],
precipitationUnit = settings.precipitationUnit, precipitationUnit = if (userProfile?.preferredUnit?.distance != UserProfile.PreferredUnit.UnitType.IMPERIAL) PrecipitationUnit.MILLIMETERS else PrecipitationUnit.INCH,
temperature = data.forecastData.temperature[index].roundToInt(), temperature = data.forecastData.temperature[index].roundToInt(),
temperatureUnit = settings.temperatureUnit, temperatureUnit = if (userProfile?.preferredUnit?.temperature != UserProfile.PreferredUnit.UnitType.IMPERIAL) TemperatureUnit.CELSIUS else TemperatureUnit.FAHRENHEIT,
timeLabel = formattedTime timeLabel = formattedTime
) )
} }

View File

@ -71,13 +71,18 @@ enum class TemperatureUnit(val id: String, val label: String, val unitDisplay: S
FAHRENHEIT("fahrenheit", "Fahrenheit (°F)", "°F") FAHRENHEIT("fahrenheit", "Fahrenheit (°F)", "°F")
} }
enum class RoundLocationSetting(val id: String, val label: String, val km: Int){
KM_1("1 km", "1 km", 1),
KM_2("2 km", "2 km", 2),
KM_5("5 km", "5 km", 5)
}
@Serializable @Serializable
data class HeadwindSettings( data class HeadwindSettings(
val windUnit: WindUnit = WindUnit.KILOMETERS_PER_HOUR, val windUnit: WindUnit = WindUnit.KILOMETERS_PER_HOUR,
val precipitationUnit: PrecipitationUnit = PrecipitationUnit.MILLIMETERS,
val temperatureUnit: TemperatureUnit = TemperatureUnit.CELSIUS,
val welcomeDialogAccepted: Boolean = false, val welcomeDialogAccepted: Boolean = false,
val windDirectionIndicatorTextSetting: WindDirectionIndicatorTextSetting = WindDirectionIndicatorTextSetting.HEADWIND_SPEED, val windDirectionIndicatorTextSetting: WindDirectionIndicatorTextSetting = WindDirectionIndicatorTextSetting.HEADWIND_SPEED,
val roundLocationTo: RoundLocationSetting = RoundLocationSetting.KM_2
){ ){
companion object { companion object {
val defaultSettings = Json.encodeToString(HeadwindSettings()) val defaultSettings = Json.encodeToString(HeadwindSettings())
@ -113,23 +118,21 @@ fun MainScreen() {
val karooSystem = remember { KarooSystemService(ctx) } val karooSystem = remember { KarooSystemService(ctx) }
var selectedWindUnit by remember { mutableStateOf(WindUnit.KILOMETERS_PER_HOUR) } var selectedWindUnit by remember { mutableStateOf(WindUnit.KILOMETERS_PER_HOUR) }
var selectedPrecipitationUnit by remember { mutableStateOf(PrecipitationUnit.MILLIMETERS) }
var selectedTemperatureUnit by remember { mutableStateOf(TemperatureUnit.CELSIUS) }
var welcomeDialogVisible by remember { mutableStateOf(false) } var welcomeDialogVisible by remember { mutableStateOf(false) }
var selectedWindDirectionIndicatorTextSetting by remember { mutableStateOf(WindDirectionIndicatorTextSetting.HEADWIND_SPEED) } var selectedWindDirectionIndicatorTextSetting by remember { mutableStateOf(WindDirectionIndicatorTextSetting.HEADWIND_SPEED) }
var selectedRoundLocationSetting by remember { mutableStateOf(RoundLocationSetting.KM_2) }
val stats by ctx.streamStats().collectAsState(HeadwindStats()) val stats by ctx.streamStats().collectAsState(HeadwindStats())
val location by karooSystem.getGpsCoordinateFlow().collectAsState(initial = null) val location by karooSystem.getGpsCoordinateFlow(ctx).collectAsState(initial = null)
var savedDialogVisible by remember { mutableStateOf(false) } var savedDialogVisible by remember { mutableStateOf(false) }
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
ctx.streamSettings(karooSystem).collect { settings -> ctx.streamSettings(karooSystem).collect { settings ->
selectedWindUnit = settings.windUnit selectedWindUnit = settings.windUnit
selectedPrecipitationUnit = settings.precipitationUnit
welcomeDialogVisible = !settings.welcomeDialogAccepted welcomeDialogVisible = !settings.welcomeDialogAccepted
selectedWindDirectionIndicatorTextSetting = settings.windDirectionIndicatorTextSetting selectedWindDirectionIndicatorTextSetting = settings.windDirectionIndicatorTextSetting
selectedTemperatureUnit = settings.temperatureUnit selectedRoundLocationSetting = settings.roundLocationTo
} }
} }
@ -164,28 +167,21 @@ fun MainScreen() {
selectedWindUnit = WindUnit.entries.find { unit -> unit.id == selectedOption.id }!! selectedWindUnit = WindUnit.entries.find { unit -> unit.id == selectedOption.id }!!
} }
val precipitationUnitDropdownOptions = PrecipitationUnit.entries.toList().map { unit -> DropdownOption(unit.id, unit.label) } val roundLocationDropdownOptions = RoundLocationSetting.entries.toList().map { unit -> DropdownOption(unit.id, unit.label) }
val precipitationUnitInitialSelection by remember(selectedPrecipitationUnit) { val roundLocationInitialSelection by remember(selectedRoundLocationSetting) {
mutableStateOf(precipitationUnitDropdownOptions.find { option -> option.id == selectedPrecipitationUnit.id }!!) mutableStateOf(roundLocationDropdownOptions.find { option -> option.id == selectedRoundLocationSetting.id }!!)
} }
Dropdown(label = "Precipitation Unit", options = precipitationUnitDropdownOptions, selected = precipitationUnitInitialSelection) { selectedOption -> Dropdown(label = "Round Location", options = roundLocationDropdownOptions, selected = roundLocationInitialSelection) { selectedOption ->
selectedPrecipitationUnit = PrecipitationUnit.entries.find { unit -> unit.id == selectedOption.id }!! selectedRoundLocationSetting = RoundLocationSetting.entries.find { unit -> unit.id == selectedOption.id }!!
} }
val temperatureUnitDropdownOptions = TemperatureUnit.entries.toList().map { unit -> DropdownOption(unit.id, unit.label) }
val temperatureUnitInitialSelection by remember(selectedTemperatureUnit) {
mutableStateOf(temperatureUnitDropdownOptions.find { option -> option.id == selectedTemperatureUnit.id }!!)
}
Dropdown(label = "Temperature Unit", options = temperatureUnitDropdownOptions, selected = temperatureUnitInitialSelection) { selectedOption ->
selectedTemperatureUnit = TemperatureUnit.entries.find { unit -> unit.id == selectedOption.id }!!
}
FilledTonalButton(modifier = Modifier FilledTonalButton(modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.height(50.dp), onClick = { .height(50.dp), onClick = {
val newSettings = HeadwindSettings(windUnit = selectedWindUnit, precipitationUnit = selectedPrecipitationUnit, val newSettings = HeadwindSettings(windUnit = selectedWindUnit,
temperatureUnit = selectedTemperatureUnit, welcomeDialogAccepted = true, windDirectionIndicatorTextSetting = selectedWindDirectionIndicatorTextSetting,
welcomeDialogAccepted = true, windDirectionIndicatorTextSetting = selectedWindDirectionIndicatorTextSetting) roundLocationTo = selectedRoundLocationSetting)
coroutineScope.launch { coroutineScope.launch {
saveSettings(ctx, newSettings) saveSettings(ctx, newSettings)
@ -237,8 +233,6 @@ fun MainScreen() {
confirmButton = { Button(onClick = { confirmButton = { Button(onClick = {
coroutineScope.launch { coroutineScope.launch {
saveSettings(ctx, HeadwindSettings(windUnit = selectedWindUnit, saveSettings(ctx, HeadwindSettings(windUnit = selectedWindUnit,
precipitationUnit = selectedPrecipitationUnit,
temperatureUnit = selectedTemperatureUnit,
welcomeDialogAccepted = true)) welcomeDialogAccepted = true))
} }
}) { Text("OK") } }, }) { Text("OK") } },