Add wide mode for tailwind and tailwind with speed data fields (#80)

This commit is contained in:
timklge 2025-03-27 21:08:35 +01:00 committed by GitHub
parent bcf47a9578
commit 5d7ba99f57
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 99 additions and 48 deletions

View File

@ -157,7 +157,8 @@ class HeadwindDirectionDataType(
windDirection.roundToInt(), windDirection.roundToInt(),
config.textSize, config.textSize,
windSpeed?.toInt()?.toString() ?: "", windSpeed?.toInt()?.toString() ?: "",
preview = config.preview preview = config.preview,
wideMode = false
) )
} }

View File

@ -21,12 +21,17 @@ import androidx.glance.layout.Box
import androidx.glance.layout.Column import androidx.glance.layout.Column
import androidx.glance.layout.ContentScale import androidx.glance.layout.ContentScale
import androidx.glance.layout.Row import androidx.glance.layout.Row
import androidx.glance.layout.Spacer
import androidx.glance.layout.fillMaxHeight
import androidx.glance.layout.fillMaxSize import androidx.glance.layout.fillMaxSize
import androidx.glance.layout.padding import androidx.glance.layout.padding
import androidx.glance.layout.size import androidx.glance.layout.size
import androidx.glance.layout.width
import androidx.glance.layout.wrapContentHeight
import androidx.glance.text.FontFamily import androidx.glance.text.FontFamily
import androidx.glance.text.FontWeight import androidx.glance.text.FontWeight
import androidx.glance.text.Text import androidx.glance.text.Text
import androidx.glance.text.TextAlign
import androidx.glance.text.TextStyle import androidx.glance.text.TextStyle
import de.timklge.karooheadwind.MainActivity import de.timklge.karooheadwind.MainActivity
import kotlin.math.roundToInt import kotlin.math.roundToInt
@ -56,7 +61,8 @@ fun getArrowBitmapByBearing(baseBitmap: Bitmap, bearing: Int): Bitmap {
fun HeadwindDirection( fun HeadwindDirection(
baseBitmap: Bitmap, bearing: Int, fontSize: Int, baseBitmap: Bitmap, bearing: Int, fontSize: Int,
overlayText: String, overlaySubText: String? = null, overlayText: String, overlaySubText: String? = null,
nightColor: Color = Color.Black, dayColor: Color = Color.White, preview: Boolean = false nightColor: Color = Color.Black, dayColor: Color = Color.White, preview: Boolean = false,
wideMode: Boolean
) { ) {
val baseModifier = GlanceModifier.fillMaxSize().padding(5.dp).background(dayColor, nightColor).cornerRadius(10.dp) val baseModifier = GlanceModifier.fillMaxSize().padding(5.dp).background(dayColor, nightColor).cornerRadius(10.dp)
@ -83,6 +89,38 @@ fun HeadwindDirection(
style = TextStyle(color = ColorProvider(Color.Black, Color.White), fontSize = (0.6 * fontSize).sp, fontFamily = FontFamily.Monospace), style = TextStyle(color = ColorProvider(Color.Black, Color.White), fontSize = (0.6 * fontSize).sp, fontFamily = FontFamily.Monospace),
modifier = GlanceModifier.padding(1.dp) modifier = GlanceModifier.padding(1.dp)
) )
} else {
if (wideMode){
Row(modifier = GlanceModifier.fillMaxSize(), verticalAlignment = Alignment.CenterVertically, horizontalAlignment = Alignment.CenterHorizontally) {
Column(modifier = GlanceModifier.defaultWeight(), horizontalAlignment = Alignment.CenterHorizontally, verticalAlignment = Alignment.CenterVertically) {
Column(modifier = GlanceModifier.size(50.dp)) {
Image(
provider = ImageProvider(getArrowBitmapByBearing(baseBitmap, bearing)),
contentDescription = "Relative wind direction indicator",
contentScale = ContentScale.Fit,
colorFilter = ColorFilter.tint(ColorProvider(Color.Black, Color.White))
)
}
Text(
overlaySubText,
maxLines = 1,
style = TextStyle(color = ColorProvider(Color.Black, Color.White), fontSize = (0.35 * fontSize).sp, fontFamily = FontFamily.Monospace),
modifier = GlanceModifier.padding(1.dp)
)
}
// Spacer(modifier = GlanceModifier.width(10.dp))
Column(modifier = GlanceModifier.defaultWeight().fillMaxHeight(), verticalAlignment = Alignment.CenterVertically, horizontalAlignment = Alignment.CenterHorizontally) {
Text(
overlayText,
maxLines = 1,
modifier = GlanceModifier.padding(5.dp),
style = TextStyle(color = ColorProvider(Color.Black, Color.White), fontSize = (0.75 * fontSize).sp, fontFamily = FontFamily.Monospace, fontWeight = FontWeight.Bold)
)
}
}
} else { } else {
Row(modifier = GlanceModifier.fillMaxSize(), verticalAlignment = Alignment.CenterVertically) { Row(modifier = GlanceModifier.fillMaxSize(), verticalAlignment = Alignment.CenterVertically) {
Column(horizontalAlignment = Alignment.CenterHorizontally, verticalAlignment = Alignment.CenterVertically) { Column(horizontalAlignment = Alignment.CenterHorizontally, verticalAlignment = Alignment.CenterVertically) {
@ -113,7 +151,7 @@ fun HeadwindDirection(
) )
} }
} }
}
} }
} }
} }

View File

@ -17,6 +17,7 @@ import de.timklge.karooheadwind.KarooHeadwindExtension
import de.timklge.karooheadwind.R import de.timklge.karooheadwind.R
import de.timklge.karooheadwind.WindDirectionIndicatorSetting import de.timklge.karooheadwind.WindDirectionIndicatorSetting
import de.timklge.karooheadwind.WindDirectionIndicatorTextSetting import de.timklge.karooheadwind.WindDirectionIndicatorTextSetting
import de.timklge.karooheadwind.datatypes.TailwindDataType.StreamData
import de.timklge.karooheadwind.getRelativeHeadingFlow import de.timklge.karooheadwind.getRelativeHeadingFlow
import de.timklge.karooheadwind.streamCurrentWeatherData import de.timklge.karooheadwind.streamCurrentWeatherData
import de.timklge.karooheadwind.streamDataFlow import de.timklge.karooheadwind.streamDataFlow
@ -37,6 +38,7 @@ import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -78,14 +80,18 @@ class TailwindAndRideSpeedDataType(
val rideSpeed: Double? = null, val rideSpeed: Double? = null,
val isImperial: Boolean? = null) val isImperial: Boolean? = null)
private fun previewFlow(): Flow<StreamData> { private fun previewFlow(profileFlow: Flow<UserProfile>): Flow<de.timklge.karooheadwind.datatypes.TailwindDataType.StreamData> {
return flow { return flow {
val profile = profileFlow.first()
while (true) { while (true) {
val bearing = (0..360).random().toDouble() val bearing = (0..360).random().toDouble()
val windSpeed = (0..20).random() val windSpeed = (0..20).random()
val rideSpeed = (10..40).random().toDouble() val rideSpeed = (10..40).random().toDouble()
val gustSpeed = windSpeed * ((10..40).random().toDouble() / 10)
val isImperial = profile.preferredUnit.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL
emit(StreamData(HeadingResponse.Value(bearing), bearing, windSpeed.toDouble(), HeadwindSettings(), rideSpeed)) emit(StreamData(HeadingResponse.Value(bearing), bearing, windSpeed.toDouble(), HeadwindSettings(), rideSpeed, gustSpeed = gustSpeed, isImperial = isImperial))
delay(2_000) delay(2_000)
} }
@ -111,24 +117,20 @@ class TailwindAndRideSpeedDataType(
} }
val flow = if (config.preview) { val flow = if (config.preview) {
previewFlow() previewFlow(karooSystem.streamUserProfile())
} else { } else {
karooSystem.getRelativeHeadingFlow(context) combine(karooSystem.getRelativeHeadingFlow(context), context.streamCurrentWeatherData(), context.streamSettings(karooSystem), karooSystem.streamUserProfile(), streamSpeedInMs()) { headingResponse, weatherData, settings, userProfile, rideSpeedInMs ->
.combine(context.streamCurrentWeatherData()) { value, data -> value to data }
.combine(context.streamSettings(karooSystem)) { (value, data), settings ->
StreamData(value, data.firstOrNull()?.data?.current?.windDirection, data.firstOrNull()?.data?.current?.windSpeed, settings)
}
.combine(karooSystem.streamUserProfile()) { streamData, userProfile ->
val isImperial = userProfile.preferredUnit.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL val isImperial = userProfile.preferredUnit.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL
streamData.copy(isImperial = isImperial) val absoluteWindDirection = weatherData.firstOrNull()?.data?.current?.windDirection
} val windSpeed = weatherData.firstOrNull()?.data?.current?.windSpeed
.combine(streamSpeedInMs()) { streamData, rideSpeedInMs -> val gustSpeed = weatherData.firstOrNull()?.data?.current?.windGusts
val rideSpeed = if (streamData.isImperial == true){ val rideSpeed = if (isImperial){
rideSpeedInMs * 2.23694 rideSpeedInMs * 2.23694
} else { } else {
rideSpeedInMs * 3.6 rideSpeedInMs * 3.6
} }
streamData.copy(rideSpeed = rideSpeed)
StreamData(headingResponse, absoluteWindDirection, windSpeed, settings, rideSpeed = rideSpeed, isImperial = isImperial, gustSpeed = gustSpeed)
} }
} }
@ -159,6 +161,13 @@ class TailwindAndRideSpeedDataType(
val text = streamData.rideSpeed?.let { String.format(Locale.current.platformLocale, "%.1f", it) } ?: "" val text = streamData.rideSpeed?.let { String.format(Locale.current.platformLocale, "%.1f", it) } ?: ""
val wideMode = config.gridSize.first == 60
val gustSpeedAddon = if (wideMode) {
"-${streamData.gustSpeed?.roundToInt() ?: 0}"
} else {
""
}
val subtextWithSign = when (streamData.settings.windDirectionIndicatorTextSetting) { val subtextWithSign = when (streamData.settings.windDirectionIndicatorTextSetting) {
WindDirectionIndicatorTextSetting.HEADWIND_SPEED -> { WindDirectionIndicatorTextSetting.HEADWIND_SPEED -> {
val headwindSpeed = cos( (windDirection + 180) * Math.PI / 180.0) * windSpeed val headwindSpeed = cos( (windDirection + 180) * Math.PI / 180.0) * windSpeed
@ -167,9 +176,9 @@ class TailwindAndRideSpeedDataType(
val sign = if (headwindSpeed < 0) "+" else { val sign = if (headwindSpeed < 0) "+" else {
if (headwindSpeed > 0) "-" else "" if (headwindSpeed > 0) "-" else ""
} }
"$sign${headwindSpeed.roundToInt().absoluteValue} ${windSpeed.roundToInt()}" "$sign${headwindSpeed.roundToInt().absoluteValue} ${windSpeed.roundToInt()}${gustSpeedAddon}"
} }
WindDirectionIndicatorTextSetting.WIND_SPEED -> windSpeed.roundToInt().toString() WindDirectionIndicatorTextSetting.WIND_SPEED -> "${windSpeed.roundToInt()}${gustSpeedAddon}"
WindDirectionIndicatorTextSetting.NONE -> "" WindDirectionIndicatorTextSetting.NONE -> ""
} }
@ -196,7 +205,8 @@ class TailwindAndRideSpeedDataType(
subtextWithSign, subtextWithSign,
dayColor, dayColor,
nightColor, nightColor,
preview = config.preview preview = config.preview,
wideMode = wideMode,
) )
} }

View File

@ -160,7 +160,7 @@ class TailwindDataType(
if (streamData.settings.windDirectionIndicatorSetting == WindDirectionIndicatorSetting.HEADWIND_DIRECTION) { if (streamData.settings.windDirectionIndicatorSetting == WindDirectionIndicatorSetting.HEADWIND_DIRECTION) {
val headwindSpeed = cos( (windDirection + 180) * Math.PI / 180.0) * windSpeed val headwindSpeed = cos( (windDirection + 180) * Math.PI / 180.0) * windSpeed
val windSpeedInKmh = if (streamData.isImperial == true){ val windSpeedInKmh = if (streamData.isImperial){
headwindSpeed / 2.23694 * 3.6 headwindSpeed / 2.23694 * 3.6
} else { } else {
headwindSpeed headwindSpeed
@ -177,7 +177,9 @@ class TailwindDataType(
mainText, mainText,
subtext, subtext,
dayColor, dayColor,
nightColor nightColor,
wideMode = config.gridSize.first == 60,
preview = config.preview,
) )
} }