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
This commit is contained in:
parent
0869121176
commit
01959ce3b7
11
README.md
11
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.
|
||||
@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@ -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"
|
||||
}
|
||||
@ -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<HeadingRes
|
||||
val windBearing = data.current.windDirection + 180
|
||||
val diff = signedAngleDifference(bearing.diff, windBearing)
|
||||
|
||||
Log.d(KarooHeadwindExtension.TAG, "Wind bearing: $bearing vs $windBearing => $diff")
|
||||
Log.d(KarooHeadwindExtension.TAG, "Wind bearing: Heading $bearing vs wind $windBearing => $diff")
|
||||
|
||||
HeadingResponse.Value(diff)
|
||||
}
|
||||
|
||||
@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -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<StreamState>) {
|
||||
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<StreamData> {
|
||||
data class DirectionAndSpeed(val bearing: Double, val speed: Double?)
|
||||
|
||||
private fun previewFlow(): Flow<DirectionAndSpeed> {
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -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<BitmapWithBearing, Bitmap>()
|
||||
|
||||
fun getArrowBitmapByBearing(baseBitmap: Bitmap, bearing: Int): Bitmap {
|
||||
synchronized(bitmapsByBearing) {
|
||||
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 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.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()
|
||||
|
||||
bitmapsByBearing[bitmapWithBearing] = bitmap
|
||||
|
||||
return bitmap
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalGlancePreviewApi::class)
|
||||
@Composable
|
||||
fun HeadwindDirection(baseBitmap: Bitmap, bearing: Int, fontSize: Int,
|
||||
fun HeadwindDirection(
|
||||
baseBitmap: Bitmap, bearing: Int, fontSize: Int,
|
||||
overlayText: String, overlaySubText: String? = null,
|
||||
dayColor: Color = Color.Black, nightColor: Color = Color.White,
|
||||
viewSize: Pair<Int, Int>) {
|
||||
dayColor: Color = Color.Black, nightColor: Color = Color.White
|
||||
) {
|
||||
Box(
|
||||
modifier = GlanceModifier.fillMaxSize().padding(5.dp),
|
||||
contentAlignment = Alignment(
|
||||
|
||||
@ -46,3 +46,4 @@ class HeadwindSpeedDataType(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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<StreamState>) {
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -37,7 +37,38 @@ 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),
|
||||
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)
|
||||
)
|
||||
|
||||
@ -27,4 +27,6 @@
|
||||
<string name="headwind_speed_description">Current headwind speed</string>
|
||||
<string name="temperature">Temperature</string>
|
||||
<string name="temperature_description">Current temperature in configured unit</string>
|
||||
<string name="userwind_speed_description">Current headwind or wind speed based on user setting</string>
|
||||
<string name="userwind_speed">Set wind speed</string>
|
||||
</resources>
|
||||
@ -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" />
|
||||
|
||||
<DataType
|
||||
@ -39,6 +39,13 @@
|
||||
icon="@drawable/wind"
|
||||
typeId="headwindSpeed" />
|
||||
|
||||
<DataType
|
||||
description="@string/userwind_speed_description"
|
||||
displayName="@string/userwind_speed"
|
||||
graphical="false"
|
||||
icon="@drawable/wind"
|
||||
typeId="userwindSpeed" />
|
||||
|
||||
<DataType
|
||||
description="@string/relativeHumidity_description"
|
||||
displayName="@string/relativeHumidity"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user