fix #15: Replace precipitation and temperature unit settings with location rounding setting
This commit is contained in:
parent
9624b7ec7d
commit
d1cf6aa6d6
@ -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.
|
||||||
|
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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"
|
||||||
|
|||||||
@ -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¤t=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¤t=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}¤t=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}¤t=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))
|
||||||
}
|
}
|
||||||
@ -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())
|
||||||
|
|||||||
@ -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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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") } },
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user