From 01959ce3b7f24ef91e9ace3b63c080915bd4f647 Mon Sep 17 00:00:00 2001 From: timklge <2026103+timklge@users.noreply.github.com> Date: Sat, 8 Feb 2025 14:28:30 +0100 Subject: [PATCH] ref #35: Set headwind data type field to direction according to user setting, add userwind data type (#36) * ref #35: Set headwind data type fields to values according to user settings * Use single datafield per type, add userwindSpeed data type to expose (head-)wind speed depending on user setting * Enable minification for release builds * Fix signed angle difference in headwind view * Remove bitmap cache * Format --- README.md | 11 ++ app/build.gradle.kts | 6 +- app/manifest.json | 6 +- .../de/timklge/karooheadwind/HeadingFlow.kt | 5 +- .../karooheadwind/KarooHeadwindExtension.kt | 7 +- .../datatypes/HeadwindDirectionDataType.kt | 100 ++++++++++++------ .../datatypes/HeadwindDirectionView.kt | 56 ++++------ .../datatypes/HeadwindSpeedDataType.kt | 3 +- .../datatypes/TailwindAndRideSpeedDataType.kt | 11 +- .../datatypes/UserWindSpeedDataType.kt | 69 ++++++++++++ .../timklge/karooheadwind/datatypes/Views.kt | 37 ++++++- app/src/main/res/values/strings.xml | 2 + app/src/main/res/xml/extension_info.xml | 9 +- 13 files changed, 233 insertions(+), 89 deletions(-) create mode 100644 app/src/main/kotlin/de/timklge/karooheadwind/datatypes/UserWindSpeedDataType.kt diff --git a/README.md b/README.md index 575ffcc..160617b 100644 --- a/README.md +++ b/README.md @@ -45,3 +45,14 @@ The app will automatically attempt to download weather data for your current app - Icons are from [boxicons.com](https://boxicons.com) ([MIT-licensed](icon_credits.txt)) - Made possible by the generous usage terms of [open-meteo.com](https://open-meteo.com) - Uses [karoo-ext](https://github.com/hammerheadnav/karoo-ext) (Apache2-licensed) + +## Extension Developers: Headwind Data Type + +If the user has installed the headwind extension on his karoo, you can stream the headwind data type from other extensions via `karoo-ext`. +Use extension id `karoo-headwind` with datatype ids `headwind` and `userwindSpeed`. + +- The `headwind` datatype contains a single field that either represents an error code or the wind direction. A `-1.0` indicates missing gps receiption, `-2.0` no weather data, `-3.0` that the headwind extension +has not been set up. Otherwise, the value is the wind direction in degrees; if the user has set the headwind indicator to depict the absolute wind direction, the field will contain the absolute wind direction; otherwise +it will contain the headwind direction. +- The `userwindSpeed` datatype contains a single field with the wind speed in the user's defined unit. If the user has set the headwind indicator to show the absolute wind speed, +this field will contain the absolute wind speed; otherwise it will contain the headwind speed. \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 1769ebf..dfe393f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -15,8 +15,8 @@ android { applicationId = "de.timklge.karooheadwind" minSdk = 26 targetSdk = 35 - versionCode = 10 - versionName = "1.2.2" + versionCode = 11 + versionName = "1.2.3" } signingConfigs { @@ -38,7 +38,7 @@ android { } release { signingConfig = signingConfigs.getByName("release") - isMinifyEnabled = false + isMinifyEnabled = true proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } } diff --git a/app/manifest.json b/app/manifest.json index cf409ee..a225906 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -3,9 +3,9 @@ "packageName": "de.timklge.karooheadwind", "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", - "latestVersion": "1.2.2", - "latestVersionCode": 10, + "latestVersion": "1.2.3", + "latestVersionCode": 11, "developer": "timklge", "description": "Provides headwind direction, wind speed and other weather data fields", - "releaseNotes": "Reduce font size in tailwind indicators, update gps bearing retrieval" + "releaseNotes": "Update gps bearing retrieval, data type exposure for other extensions, optimize build" } \ No newline at end of file diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/HeadingFlow.kt b/app/src/main/kotlin/de/timklge/karooheadwind/HeadingFlow.kt index 3740a84..73120cc 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/HeadingFlow.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/HeadingFlow.kt @@ -4,8 +4,6 @@ import android.content.Context import android.util.Log import de.timklge.karooheadwind.datatypes.GpsCoordinates import io.hammerhead.karooext.KarooSystemService -import io.hammerhead.karooext.models.DataType -import io.hammerhead.karooext.models.StreamState import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine @@ -15,7 +13,6 @@ import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.scan sealed class HeadingResponse { @@ -35,7 +32,7 @@ fun KarooSystemService.getRelativeHeadingFlow(context: Context): Flow $diff") + Log.d(KarooHeadwindExtension.TAG, "Wind bearing: Heading $bearing vs wind $windBearing => $diff") HeadingResponse.Value(diff) } diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/KarooHeadwindExtension.kt b/app/src/main/kotlin/de/timklge/karooheadwind/KarooHeadwindExtension.kt index e2cd036..58c53cd 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/KarooHeadwindExtension.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/KarooHeadwindExtension.kt @@ -12,6 +12,7 @@ import de.timklge.karooheadwind.datatypes.HeadwindSpeedDataType import de.timklge.karooheadwind.datatypes.TailwindAndRideSpeedDataType import de.timklge.karooheadwind.datatypes.HeadwindDirectionDataType import de.timklge.karooheadwind.datatypes.TemperatureDataType +import de.timklge.karooheadwind.datatypes.UserWindSpeedDataType import de.timklge.karooheadwind.datatypes.WeatherDataType import de.timklge.karooheadwind.datatypes.WeatherForecastDataType import de.timklge.karooheadwind.datatypes.WindSpeedDataType @@ -41,12 +42,11 @@ import kotlin.math.absoluteValue import kotlin.time.Duration.Companion.hours import kotlin.time.Duration.Companion.minutes -class KarooHeadwindExtension : KarooExtension("karoo-headwind", "1.2.2") { +class KarooHeadwindExtension : KarooExtension("karoo-headwind", "1.2.3") { companion object { const val TAG = "karoo-headwind" } - lateinit var karooSystem: KarooSystemService private var updateLastKnownGpsJob: Job? = null @@ -67,7 +67,8 @@ class KarooHeadwindExtension : KarooExtension("karoo-headwind", "1.2.2") { TemperatureDataType(applicationContext), WindDirectionDataType(karooSystem, applicationContext), PrecipitationDataType(applicationContext), - SurfacePressureDataType(applicationContext) + SurfacePressureDataType(applicationContext), + UserWindSpeedDataType(karooSystem, applicationContext) ) } diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindDirectionDataType.kt b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindDirectionDataType.kt index 03c6a64..8ef6d5d 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindDirectionDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindDirectionDataType.kt @@ -11,8 +11,8 @@ import de.timklge.karooheadwind.KarooHeadwindExtension import de.timklge.karooheadwind.getRelativeHeadingFlow import de.timklge.karooheadwind.screens.HeadwindSettings import de.timklge.karooheadwind.screens.WindDirectionIndicatorSetting -import de.timklge.karooheadwind.screens.WindDirectionIndicatorTextSetting import de.timklge.karooheadwind.streamCurrentWeatherData +import de.timklge.karooheadwind.streamDataFlow import de.timklge.karooheadwind.streamSettings import io.hammerhead.karooext.KarooSystemService import io.hammerhead.karooext.extension.DataTypeImpl @@ -30,8 +30,9 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.launch -import kotlin.math.cos import kotlin.math.roundToInt @OptIn(ExperimentalGlanceRemoteViewsApi::class) @@ -44,9 +45,41 @@ class HeadwindDirectionDataType( override fun startStream(emitter: Emitter) { val job = CoroutineScope(Dispatchers.IO).launch { karooSystem.getRelativeHeadingFlow(applicationContext) - .collect { diff -> - val value = (diff as? HeadingResponse.Value)?.diff ?: 0.0 - emitter.onNext(StreamState.Streaming(DataPoint(dataTypeId, mapOf(DataType.Field.SINGLE to value)))) + .combine(applicationContext.streamCurrentWeatherData()) { headingResponse, data -> StreamData(headingResponse, data?.current?.windDirection, data?.current?.windSpeed) } + .combine(applicationContext.streamSettings(karooSystem)) { data, settings -> data.copy(settings = settings) } + .collect { streamData -> + val value = (streamData.headingResponse as? HeadingResponse.Value)?.diff + + var returnValue = 0.0 + if (value == null || streamData.absoluteWindDirection == null || streamData.settings == null || streamData.windSpeed == null){ + var errorCode = 1.0 + var headingResponse = streamData.headingResponse + + if (headingResponse is HeadingResponse.Value && (streamData.absoluteWindDirection == null || streamData.windSpeed == null)){ + headingResponse = HeadingResponse.NoWeatherData + } + + if (streamData.settings?.welcomeDialogAccepted == false){ + errorCode = ERROR_APP_NOT_SET_UP.toDouble() + } else if (headingResponse is HeadingResponse.NoGps){ + errorCode = ERROR_NO_GPS.toDouble() + } else { + errorCode = ERROR_NO_WEATHER_DATA.toDouble() + } + + returnValue = errorCode + } else { + var windDirection = when (streamData.settings.windDirectionIndicatorSetting){ + WindDirectionIndicatorSetting.HEADWIND_DIRECTION -> value + WindDirectionIndicatorSetting.WIND_DIRECTION -> streamData.absoluteWindDirection + 180 + } + + if (windDirection < 0) windDirection += 360 + + returnValue = windDirection + } + + emitter.onNext(StreamState.Streaming(DataPoint(dataTypeId, mapOf(DataType.Field.SINGLE to returnValue)))) } } emitter.setCancellable { @@ -56,13 +89,16 @@ class HeadwindDirectionDataType( data class StreamData(val headingResponse: HeadingResponse?, val absoluteWindDirection: Double?, val windSpeed: Double?, val settings: HeadwindSettings? = null) - private fun previewFlow(): Flow { + data class DirectionAndSpeed(val bearing: Double, val speed: Double?) + + private fun previewFlow(): Flow { return flow { while (true) { val bearing = (0..360).random().toDouble() val windSpeed = (0..20).random() - emit(StreamData(HeadingResponse.Value(bearing), bearing, windSpeed.toDouble(), HeadwindSettings())) + emit(DirectionAndSpeed(bearing, windSpeed.toDouble())) + delay(2_000) } } @@ -85,44 +121,34 @@ class HeadwindDirectionDataType( val flow = if (config.preview) { previewFlow() } else { - karooSystem.getRelativeHeadingFlow(context) - .combine(context.streamCurrentWeatherData()) { headingResponse, data -> StreamData(headingResponse, data?.current?.windDirection, data?.current?.windSpeed) } - .combine(context.streamSettings(karooSystem)) { data, settings -> data.copy(settings = settings) } + val directionFlow = karooSystem.streamDataFlow(dataTypeId).mapNotNull { (it as? StreamState.Streaming)?.dataPoint?.singleValue } + val speedFlow = karooSystem.streamDataFlow(DataType.dataTypeId("karoo-headwind", "userwindSpeed")).map { (it as? StreamState.Streaming)?.dataPoint?.singleValue } + + combine(directionFlow, speedFlow) { direction, speed -> + DirectionAndSpeed(direction, speed) + } } val viewJob = CoroutineScope(Dispatchers.IO).launch { flow.collect { streamData -> Log.d(KarooHeadwindExtension.TAG, "Updating headwind direction view") - val value = (streamData.headingResponse as? HeadingResponse.Value)?.diff - if (value == null || streamData.absoluteWindDirection == null || streamData.settings == null || streamData.windSpeed == null){ - var headingResponse = streamData.headingResponse - - if (headingResponse is HeadingResponse.Value && (streamData.absoluteWindDirection == null || streamData.windSpeed == null)){ - headingResponse = HeadingResponse.NoWeatherData - } - - emitter.updateView(getErrorWidget(glance, context, streamData.settings, headingResponse).remoteViews) - + val errorCode = streamData.bearing.let { if(it < 0) it.toInt() else null } + if (errorCode != null) { + emitter.updateView(getErrorWidget(glance, context, errorCode).remoteViews) return@collect } - val windSpeed = streamData.windSpeed - val windDirection = when (streamData.settings.windDirectionIndicatorSetting){ - WindDirectionIndicatorSetting.HEADWIND_DIRECTION -> value - WindDirectionIndicatorSetting.WIND_DIRECTION -> streamData.absoluteWindDirection + 180 - } - val text = when (streamData.settings.windDirectionIndicatorTextSetting) { - WindDirectionIndicatorTextSetting.HEADWIND_SPEED -> { - val headwindSpeed = cos( (windDirection + 180) * Math.PI / 180.0) * windSpeed - headwindSpeed.roundToInt().toString() - } - WindDirectionIndicatorTextSetting.WIND_SPEED -> windSpeed.roundToInt().toString() - WindDirectionIndicatorTextSetting.NONE -> "" - } + val windDirection = streamData.bearing + val windSpeed = streamData.speed val result = glance.compose(context, DpSize.Unspecified) { - HeadwindDirection(baseBitmap, windDirection.roundToInt(), config.textSize, text, viewSize = config.viewSize) + HeadwindDirection( + baseBitmap, + windDirection.roundToInt(), + config.textSize, + windSpeed?.toInt()?.toString() ?: "" + ) } emitter.updateView(result.remoteViews) @@ -134,4 +160,10 @@ class HeadwindDirectionDataType( viewJob.cancel() } } + + companion object { + const val ERROR_NO_GPS = -1 + const val ERROR_NO_WEATHER_DATA = -2 + const val ERROR_APP_NOT_SET_UP = -3 + } } \ No newline at end of file diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindDirectionView.kt b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindDirectionView.kt index 37fd07e..b529dde 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindDirectionView.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindDirectionView.kt @@ -22,7 +22,6 @@ import androidx.glance.layout.Row import androidx.glance.layout.fillMaxSize import androidx.glance.layout.padding import androidx.glance.layout.size -import androidx.glance.preview.ExperimentalGlancePreviewApi import androidx.glance.text.FontFamily import androidx.glance.text.FontWeight import androidx.glance.text.Text @@ -30,47 +29,34 @@ import androidx.glance.text.TextStyle import de.timklge.karooheadwind.KarooHeadwindExtension import kotlin.math.roundToInt -data class BitmapWithBearing(val bitmap: Bitmap, val bearing: Int) - -val bitmapsByBearing = mutableMapOf() - fun getArrowBitmapByBearing(baseBitmap: Bitmap, bearing: Int): Bitmap { - synchronized(bitmapsByBearing) { - val bearingRounded = (((bearing + 360) / 10.0).roundToInt() * 10) % 360 + val bearingRounded = (((bearing + 360) / 10.0).roundToInt() * 10) % 360 - val bitmapWithBearing = BitmapWithBearing(baseBitmap, bearingRounded) - val storedBitmap = bitmapsByBearing[bitmapWithBearing] - if (storedBitmap != null) return storedBitmap + val bitmap = Bitmap.createBitmap(128, 128, Bitmap.Config.ARGB_8888) + val canvas = Canvas(bitmap) - val bitmap = Bitmap.createBitmap(128, 128, Bitmap.Config.ARGB_8888) - val canvas = Canvas(bitmap) - - val paint = Paint().apply { - color = android.graphics.Color.BLACK - style = Paint.Style.STROKE -// strokeWidth = 15f - isAntiAlias = true - } - - canvas.save() - canvas.scale((bitmap.width / baseBitmap.width.toFloat()), (bitmap.height / baseBitmap.height.toFloat()), (bitmap.width / 2).toFloat(), (bitmap.height / 2).toFloat()) - Log.d(KarooHeadwindExtension.TAG, "Drawing arrow at $bearingRounded") - canvas.rotate(bearing.toFloat(), (bitmap.width / 2).toFloat(), (bitmap.height / 2).toFloat()) - canvas.drawBitmap(baseBitmap, ((bitmap.width - baseBitmap.width) / 2).toFloat(), ((bitmap.height - baseBitmap.height) / 2).toFloat(), paint) - canvas.restore() - - bitmapsByBearing[bitmapWithBearing] = bitmap - - return bitmap + val paint = Paint().apply { + color = android.graphics.Color.BLACK + style = Paint.Style.STROKE + isAntiAlias = true } + + canvas.save() + canvas.scale((bitmap.width / baseBitmap.width.toFloat()), (bitmap.height / baseBitmap.height.toFloat()), (bitmap.width / 2).toFloat(), (bitmap.height / 2).toFloat()) + Log.d(KarooHeadwindExtension.TAG, "Drawing arrow at $bearingRounded") + canvas.rotate(bearingRounded.toFloat(), (bitmap.width / 2).toFloat(), (bitmap.height / 2).toFloat()) + canvas.drawBitmap(baseBitmap, ((bitmap.width - baseBitmap.width) / 2).toFloat(), ((bitmap.height - baseBitmap.height) / 2).toFloat(), paint) + canvas.restore() + + return bitmap } -@OptIn(ExperimentalGlancePreviewApi::class) @Composable -fun HeadwindDirection(baseBitmap: Bitmap, bearing: Int, fontSize: Int, - overlayText: String, overlaySubText: String? = null, - dayColor: Color = Color.Black, nightColor: Color = Color.White, - viewSize: Pair) { +fun HeadwindDirection( + baseBitmap: Bitmap, bearing: Int, fontSize: Int, + overlayText: String, overlaySubText: String? = null, + dayColor: Color = Color.Black, nightColor: Color = Color.White +) { Box( modifier = GlanceModifier.fillMaxSize().padding(5.dp), contentAlignment = Alignment( diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindSpeedDataType.kt b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindSpeedDataType.kt index f34a370..5f1d6c8 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindSpeedDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindSpeedDataType.kt @@ -45,4 +45,5 @@ class HeadwindSpeedDataType( job.cancel() } } -} \ No newline at end of file +} + diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/TailwindAndRideSpeedDataType.kt b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/TailwindAndRideSpeedDataType.kt index d73f801..8b94884 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/TailwindAndRideSpeedDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/TailwindAndRideSpeedDataType.kt @@ -199,8 +199,15 @@ class TailwindAndRideSpeedDataType( } val result = glance.compose(context, DpSize.Unspecified) { - HeadwindDirection(baseBitmap, windDirection.roundToInt(), config.textSize, text, subtextWithSign, - dayColor, nightColor, viewSize = config.viewSize) + HeadwindDirection( + baseBitmap, + windDirection.roundToInt(), + config.textSize, + text, + subtextWithSign, + dayColor, + nightColor + ) } emitter.updateView(result.remoteViews) diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/UserWindSpeedDataType.kt b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/UserWindSpeedDataType.kt new file mode 100644 index 0000000..cca613b --- /dev/null +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/UserWindSpeedDataType.kt @@ -0,0 +1,69 @@ +package de.timklge.karooheadwind.datatypes + +import android.content.Context +import de.timklge.karooheadwind.HeadingResponse +import de.timklge.karooheadwind.OpenMeteoCurrentWeatherResponse +import de.timklge.karooheadwind.getRelativeHeadingFlow +import de.timklge.karooheadwind.screens.HeadwindSettings +import de.timklge.karooheadwind.screens.WindDirectionIndicatorTextSetting +import de.timklge.karooheadwind.streamCurrentWeatherData +import de.timklge.karooheadwind.streamSettings +import io.hammerhead.karooext.KarooSystemService +import io.hammerhead.karooext.extension.DataTypeImpl +import io.hammerhead.karooext.internal.Emitter +import io.hammerhead.karooext.models.DataPoint +import io.hammerhead.karooext.models.DataType +import io.hammerhead.karooext.models.StreamState +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.launch +import kotlin.math.cos + +class UserWindSpeedDataType( + private val karooSystem: KarooSystemService, + private val context: Context +) : DataTypeImpl("karoo-headwind", "userwindSpeed"){ + + data class StreamData(val headingResponse: HeadingResponse, val weatherResponse: OpenMeteoCurrentWeatherResponse?, val settings: HeadwindSettings) + + override fun startStream(emitter: Emitter) { + val job = CoroutineScope(Dispatchers.IO).launch { + karooSystem.getRelativeHeadingFlow(context) + .combine(context.streamCurrentWeatherData()) { value, data -> value to data } + .combine(context.streamSettings(karooSystem)) { (value, data), settings -> StreamData(value, data, settings) } + .filter { it.weatherResponse != null } + .collect { streamData -> + val windSpeed = streamData.weatherResponse?.current?.windSpeed ?: 0.0 + val windDirection = (streamData.headingResponse as? HeadingResponse.Value)?.diff ?: 0.0 + + if (streamData.settings.windDirectionIndicatorTextSetting == WindDirectionIndicatorTextSetting.HEADWIND_SPEED){ + val headwindSpeed = cos((windDirection + 180) * Math.PI / 180.0) * windSpeed + + emitter.onNext( + StreamState.Streaming( + DataPoint( + dataTypeId, + mapOf(DataType.Field.SINGLE to headwindSpeed) + ) + ) + ) + } else { + emitter.onNext( + StreamState.Streaming( + DataPoint( + dataTypeId, + mapOf(DataType.Field.SINGLE to windSpeed) + ) + ) + ) + } + } + } + + emitter.setCancellable { + job.cancel() + } + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/Views.kt b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/Views.kt index 81d054d..f1d3dec 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/Views.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/Views.kt @@ -37,10 +37,41 @@ suspend fun getErrorWidget(glance: GlanceRemoteViews, context: Context, settings Log.d(KarooHeadwindExtension.TAG, "Error widget: $errorMessage") - Text(text = errorMessage, style = TextStyle(fontSize = TextUnit(16f, TextUnitType.Sp), - textAlign = TextAlign.Center, - color = ColorProvider(Color.Black, Color.White) + Text(text = errorMessage, + style = TextStyle( + fontSize = TextUnit(16f, TextUnitType.Sp), + textAlign = TextAlign.Center, + color = ColorProvider(Color.Black, Color.White) + ) ) + } + } +} + +@OptIn(ExperimentalGlanceRemoteViewsApi::class) +suspend fun getErrorWidget(glance: GlanceRemoteViews, context: Context, errorCode: Int): RemoteViewsCompositionResult { + return glance.compose(context, DpSize.Unspecified) { + Box(modifier = GlanceModifier.fillMaxSize().padding(5.dp), contentAlignment = Alignment.Center) { + val errorMessage = when (errorCode) { + HeadwindDirectionDataType.ERROR_APP_NOT_SET_UP -> { + "Headwind app not set up" + } + HeadwindDirectionDataType.ERROR_NO_GPS -> { + "No GPS signal" + } + else -> { + "Weather data download failed" + } + } + + Log.d(KarooHeadwindExtension.TAG, "Error widget: $errorMessage") + + Text(text = errorMessage, + style = TextStyle( + fontSize = TextUnit(16f, TextUnitType.Sp), + textAlign = TextAlign.Center, + color = ColorProvider(Color.Black, Color.White) + ) ) } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a870a54..98e2457 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -27,4 +27,6 @@ Current headwind speed Temperature Current temperature in configured unit + Current headwind or wind speed based on user setting + Set wind speed \ No newline at end of file diff --git a/app/src/main/res/xml/extension_info.xml b/app/src/main/res/xml/extension_info.xml index c232717..d45cc54 100644 --- a/app/src/main/res/xml/extension_info.xml +++ b/app/src/main/res/xml/extension_info.xml @@ -15,7 +15,7 @@ description="@string/tailwind_and_speed_description" displayName="@string/tailwind_and_speed" graphical="true" - icon="@drawable/ic_launcher" + icon="@drawable/wind" typeId="tailwind-and-ride-speed" /> + +