Enlarge font in single date weather display (#55)
* Shorter date format * Enlarge font size in single date weather widget and make clickable * Fix off by one in route forecast * Fix indentation lint
This commit is contained in:
parent
e95e0c03f6
commit
7c28251b02
@ -163,7 +163,8 @@ class KarooHeadwindExtension : KarooExtension("karoo-headwind", "1.3") {
|
||||
add(gps)
|
||||
|
||||
var currentPosition = positionOnRoute + calculatedDistanceToNextFullHour
|
||||
var lastRequestedPosition = currentPosition
|
||||
var lastRequestedPosition = positionOnRoute
|
||||
|
||||
while (currentPosition < upcomingRoute.routeLength && size < 10) {
|
||||
val point = TurfMeasurement.along(
|
||||
upcomingRoute.routePolyline,
|
||||
@ -182,7 +183,7 @@ class KarooHeadwindExtension : KarooExtension("karoo-headwind", "1.3") {
|
||||
currentPosition += distancePerHour
|
||||
}
|
||||
|
||||
if (upcomingRoute.routeLength > lastRequestedPosition + 5_000) {
|
||||
if (upcomingRoute.routeLength > lastRequestedPosition + 1_000) {
|
||||
val point = TurfMeasurement.along(
|
||||
upcomingRoute.routePolyline,
|
||||
upcomingRoute.routeLength,
|
||||
|
||||
@ -5,6 +5,8 @@ import android.graphics.BitmapFactory
|
||||
import android.util.Log
|
||||
import androidx.compose.ui.unit.DpSize
|
||||
import androidx.glance.GlanceModifier
|
||||
import androidx.glance.action.actionStartActivity
|
||||
import androidx.glance.action.clickable
|
||||
import androidx.glance.appwidget.ExperimentalGlanceRemoteViewsApi
|
||||
import androidx.glance.appwidget.GlanceRemoteViews
|
||||
import androidx.glance.layout.Alignment
|
||||
@ -13,6 +15,7 @@ import androidx.glance.layout.fillMaxSize
|
||||
import de.timklge.karooheadwind.HeadingResponse
|
||||
import de.timklge.karooheadwind.HeadwindSettings
|
||||
import de.timklge.karooheadwind.KarooHeadwindExtension
|
||||
import de.timklge.karooheadwind.MainActivity
|
||||
import de.timklge.karooheadwind.OpenMeteoCurrentWeatherResponse
|
||||
import de.timklge.karooheadwind.OpenMeteoData
|
||||
import de.timklge.karooheadwind.TemperatureUnit
|
||||
@ -43,7 +46,6 @@ import kotlinx.coroutines.launch
|
||||
import java.time.Instant
|
||||
import java.time.ZoneId
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.format.FormatStyle
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@OptIn(ExperimentalGlanceRemoteViewsApi::class)
|
||||
@ -124,11 +126,13 @@ class WeatherDataType(
|
||||
|
||||
val interpretation = WeatherInterpretation.fromWeatherCode(data.current.weatherCode)
|
||||
val formattedTime = timeFormatter.format(Instant.ofEpochSecond(data.current.time))
|
||||
val formattedDate = Instant.ofEpochSecond(data.current.time).atZone(ZoneId.systemDefault()).toLocalDate().format(DateTimeFormatter.ofLocalizedDate(
|
||||
FormatStyle.SHORT))
|
||||
val formattedDate = getShortDateFormatter().format(Instant.ofEpochSecond(data.current.time))
|
||||
|
||||
val result = glance.compose(context, DpSize.Unspecified) {
|
||||
Box(modifier = GlanceModifier.fillMaxSize(), contentAlignment = Alignment.CenterEnd) {
|
||||
var modifier = GlanceModifier.fillMaxSize()
|
||||
if (!config.preview) modifier = modifier.clickable(onClick = actionStartActivity<MainActivity>())
|
||||
|
||||
Box(modifier = modifier, contentAlignment = Alignment.CenterEnd) {
|
||||
Weather(
|
||||
baseBitmap,
|
||||
current = interpretation,
|
||||
|
||||
@ -165,7 +165,7 @@ class WeatherForecastDataType(
|
||||
|
||||
var previousDate: String? = let {
|
||||
val unixTime = allData.getOrNull(positionOffset)?.data?.forecastData?.time?.getOrNull(hourOffset)
|
||||
val formattedDate = unixTime?.let { Instant.ofEpochSecond(unixTime).atZone(ZoneId.systemDefault()).toLocalDate().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)) }
|
||||
val formattedDate = unixTime?.let { getShortDateFormatter().format(Instant.ofEpochSecond(unixTime)) }
|
||||
|
||||
formattedDate
|
||||
}
|
||||
@ -182,8 +182,6 @@ class WeatherForecastDataType(
|
||||
val distanceAlongRoute = allData.getOrNull(positionIndex)?.requestedPosition?.distanceAlongRoute
|
||||
val position = allData.getOrNull(positionIndex)?.requestedPosition?.let { "${(it.distanceAlongRoute?.div(1000.0))?.toInt()} at ${it.lat}, ${it.lon}" }
|
||||
|
||||
Log.d(KarooHeadwindExtension.TAG, "Distance along route ${positionIndex}: $position")
|
||||
|
||||
if (baseIndex > hourOffset) {
|
||||
Spacer(
|
||||
modifier = GlanceModifier.fillMaxHeight().background(
|
||||
@ -192,6 +190,8 @@ class WeatherForecastDataType(
|
||||
)
|
||||
}
|
||||
|
||||
Log.d(KarooHeadwindExtension.TAG, "Distance along route ${positionIndex}: $position")
|
||||
|
||||
val distanceFromCurrent = upcomingRoute?.distanceAlongRoute?.let { currentDistanceAlongRoute ->
|
||||
distanceAlongRoute?.minus(currentDistanceAlongRoute)
|
||||
}
|
||||
@ -202,7 +202,7 @@ class WeatherForecastDataType(
|
||||
val interpretation = WeatherInterpretation.fromWeatherCode(data.current.weatherCode)
|
||||
val unixTime = data.current.time
|
||||
val formattedTime = timeFormatter.format(Instant.ofEpochSecond(unixTime))
|
||||
val formattedDate = Instant.ofEpochSecond(unixTime).atZone(ZoneId.systemDefault()).toLocalDate().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT))
|
||||
val formattedDate = getShortDateFormatter().format(Instant.ofEpochSecond(unixTime))
|
||||
val hasNewDate = formattedDate != previousDate || baseIndex == 0
|
||||
|
||||
Weather(
|
||||
@ -225,7 +225,7 @@ class WeatherForecastDataType(
|
||||
val interpretation = WeatherInterpretation.fromWeatherCode(data?.forecastData?.weatherCode?.get(baseIndex) ?: 0)
|
||||
val unixTime = data?.forecastData?.time?.get(baseIndex) ?: 0
|
||||
val formattedTime = timeFormatter.format(Instant.ofEpochSecond(unixTime))
|
||||
val formattedDate = Instant.ofEpochSecond(unixTime).atZone(ZoneId.systemDefault()).toLocalDate().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT))
|
||||
val formattedDate = getShortDateFormatter().format(Instant.ofEpochSecond(unixTime))
|
||||
val hasNewDate = formattedDate != previousDate || baseIndex == 0
|
||||
|
||||
Weather(
|
||||
|
||||
@ -24,7 +24,6 @@ import androidx.glance.layout.padding
|
||||
import androidx.glance.layout.width
|
||||
import androidx.glance.layout.wrapContentWidth
|
||||
import androidx.glance.preview.ExperimentalGlancePreviewApi
|
||||
import androidx.glance.preview.Preview
|
||||
import androidx.glance.text.FontFamily
|
||||
import androidx.glance.text.FontWeight
|
||||
import androidx.glance.text.Text
|
||||
@ -33,9 +32,19 @@ import androidx.glance.text.TextStyle
|
||||
import de.timklge.karooheadwind.R
|
||||
import de.timklge.karooheadwind.TemperatureUnit
|
||||
import de.timklge.karooheadwind.WeatherInterpretation
|
||||
import java.time.ZoneId
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.Locale
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.math.ceil
|
||||
|
||||
fun getShortDateFormatter(): DateTimeFormatter = DateTimeFormatter.ofPattern(
|
||||
when (Locale.getDefault().country) {
|
||||
"US" -> "MM/dd"
|
||||
else -> "dd.MM"
|
||||
}
|
||||
).withZone(ZoneId.systemDefault())
|
||||
|
||||
fun getWeatherIcon(interpretation: WeatherInterpretation): Int {
|
||||
return when (interpretation){
|
||||
WeatherInterpretation.CLEAR -> R.drawable.bx_clear
|
||||
@ -49,7 +58,6 @@ fun getWeatherIcon(interpretation: WeatherInterpretation): Int {
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalGlancePreviewApi::class)
|
||||
@Preview(widthDp = 200, heightDp = 150)
|
||||
@Composable
|
||||
fun Weather(
|
||||
baseBitmap: Bitmap,
|
||||
@ -69,7 +77,7 @@ fun Weather(
|
||||
isImperial: Boolean?
|
||||
) {
|
||||
|
||||
val fontSize = 14f
|
||||
val fontSize = if (singleDisplay) 19f else 14f
|
||||
|
||||
Column(modifier = if (singleDisplay) GlanceModifier.fillMaxSize().padding(1.dp) else GlanceModifier.fillMaxHeight().padding(1.dp).width(86.dp), horizontalAlignment = rowAlignment) {
|
||||
Row(modifier = GlanceModifier.defaultWeight().wrapContentWidth(), horizontalAlignment = rowAlignment, verticalAlignment = Alignment.CenterVertically) {
|
||||
@ -130,7 +138,7 @@ fun Weather(
|
||||
}
|
||||
|
||||
Image(
|
||||
modifier = GlanceModifier.height(16.dp).width(12.dp).padding(1.dp),
|
||||
modifier = if (singleDisplay) GlanceModifier.height(20.dp).width(16.dp) else GlanceModifier.height(16.dp).width(12.dp).padding(1.dp),
|
||||
provider = ImageProvider(R.drawable.thermometer),
|
||||
contentDescription = "Temperature",
|
||||
contentScale = ContentScale.Fit,
|
||||
@ -163,14 +171,13 @@ fun Weather(
|
||||
Spacer(modifier = GlanceModifier.width(5.dp))
|
||||
|
||||
Image(
|
||||
modifier = GlanceModifier.height(16.dp).width(12.dp).padding(1.dp),
|
||||
modifier = if (singleDisplay) GlanceModifier.height(20.dp).width(16.dp) else GlanceModifier.height(16.dp).width(12.dp).padding(1.dp),
|
||||
provider = ImageProvider(getArrowBitmapByBearing(baseBitmap, windBearing + 180)),
|
||||
contentDescription = "Current wind direction",
|
||||
contentScale = ContentScale.Fit,
|
||||
colorFilter = ColorFilter.tint(ColorProvider(Color.Black, Color.White))
|
||||
)
|
||||
|
||||
|
||||
Text(
|
||||
text = "$windSpeed,${windGusts}",
|
||||
style = TextStyle(color = ColorProvider(Color.Black, Color.White), fontFamily = FontFamily.Monospace, fontSize = TextUnit(fontSize, TextUnitType.Sp))
|
||||
|
||||
@ -26,12 +26,12 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import de.timklge.karooheadwind.HeadwindStats
|
||||
import de.timklge.karooheadwind.KarooHeadwindExtension
|
||||
import de.timklge.karooheadwind.PrecipitationUnit
|
||||
import de.timklge.karooheadwind.R
|
||||
import de.timklge.karooheadwind.TemperatureUnit
|
||||
import de.timklge.karooheadwind.WeatherInterpretation
|
||||
import de.timklge.karooheadwind.datatypes.WeatherDataType.Companion.timeFormatter
|
||||
import de.timklge.karooheadwind.datatypes.WeatherForecastDataType
|
||||
import de.timklge.karooheadwind.datatypes.getShortDateFormatter
|
||||
import de.timklge.karooheadwind.getGpsCoordinateFlow
|
||||
import de.timklge.karooheadwind.streamCurrentWeatherData
|
||||
import de.timklge.karooheadwind.streamStats
|
||||
@ -41,10 +41,7 @@ import io.hammerhead.karooext.KarooSystemService
|
||||
import io.hammerhead.karooext.models.UserProfile
|
||||
import java.time.Instant
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneId
|
||||
import java.time.ZoneOffset
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.format.FormatStyle
|
||||
import java.time.temporal.ChronoUnit
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@ -91,15 +88,10 @@ fun WeatherScreen(onFinish: () -> Unit) {
|
||||
val requestedWeatherPosition = weatherData.firstOrNull()?.requestedPosition
|
||||
|
||||
val formattedTime = currentWeatherData?.let { timeFormatter.format(Instant.ofEpochSecond(currentWeatherData.current.time)) }
|
||||
val formattedDate = currentWeatherData?.let { Instant.ofEpochSecond(currentWeatherData.current.time).atZone(ZoneId.systemDefault()).toLocalDate().format(
|
||||
DateTimeFormatter.ofLocalizedDate(
|
||||
FormatStyle.SHORT))
|
||||
}
|
||||
val formattedDate = currentWeatherData?.let { getShortDateFormatter().format(Instant.ofEpochSecond(currentWeatherData.current.time)) }
|
||||
|
||||
if (karooConnected == true && currentWeatherData != null) {
|
||||
WeatherWidget(
|
||||
dateLabel = formattedDate,
|
||||
timeLabel = formattedTime,
|
||||
baseBitmap = baseBitmap,
|
||||
current = WeatherInterpretation.fromWeatherCode(currentWeatherData.current.weatherCode),
|
||||
windBearing = currentWeatherData.current.windDirection.roundToInt(),
|
||||
@ -108,10 +100,11 @@ fun WeatherScreen(onFinish: () -> Unit) {
|
||||
precipitation = currentWeatherData.current.precipitation,
|
||||
temperature = currentWeatherData.current.temperature.toInt(),
|
||||
temperatureUnit = if(profile?.preferredUnit?.temperature == UserProfile.PreferredUnit.UnitType.METRIC) TemperatureUnit.CELSIUS else TemperatureUnit.FAHRENHEIT,
|
||||
isImperial = profile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL,
|
||||
precipitationUnit = if (profile?.preferredUnit?.distance != UserProfile.PreferredUnit.UnitType.IMPERIAL) PrecipitationUnit.MILLIMETERS else PrecipitationUnit.INCH,
|
||||
timeLabel = formattedTime,
|
||||
dateLabel = formattedDate,
|
||||
distance = requestedWeatherPosition?.let { l -> location?.distanceTo(l)?.times(1000) },
|
||||
includeDistanceLabel = false,
|
||||
isImperial = profile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL,
|
||||
)
|
||||
}
|
||||
|
||||
@ -208,7 +201,7 @@ fun WeatherScreen(onFinish: () -> Unit) {
|
||||
val interpretation = WeatherInterpretation.fromWeatherCode(data?.forecastData?.weatherCode?.get(index) ?: 0)
|
||||
val unixTime = data?.forecastData?.time?.get(index) ?: 0
|
||||
val formattedForecastTime = WeatherForecastDataType.timeFormatter.format(Instant.ofEpochSecond(unixTime))
|
||||
val formattedForecastDate = Instant.ofEpochSecond(unixTime).atZone(ZoneId.systemDefault()).toLocalDate().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT))
|
||||
val formattedForecastDate = getShortDateFormatter().format(Instant.ofEpochSecond(unixTime))
|
||||
|
||||
WeatherWidget(
|
||||
baseBitmap,
|
||||
@ -217,15 +210,14 @@ fun WeatherScreen(onFinish: () -> Unit) {
|
||||
windSpeed = data?.forecastData?.windSpeed?.get(index)?.roundToInt() ?: 0,
|
||||
windGusts = data?.forecastData?.windGusts?.get(index)?.roundToInt() ?: 0,
|
||||
precipitation = data?.forecastData?.precipitation?.get(index) ?: 0.0,
|
||||
precipitationProbability = data?.forecastData?.precipitationProbability?.get(index) ?: 0,
|
||||
temperature = data?.forecastData?.temperature?.get(index)?.roundToInt() ?: 0,
|
||||
temperatureUnit = if (profile?.preferredUnit?.temperature != UserProfile.PreferredUnit.UnitType.IMPERIAL) TemperatureUnit.CELSIUS else TemperatureUnit.FAHRENHEIT,
|
||||
timeLabel = formattedForecastTime,
|
||||
dateLabel = formattedForecastDate,
|
||||
distance = distanceFromCurrent,
|
||||
isImperial = profile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL,
|
||||
precipitationUnit = if (profile?.preferredUnit?.distance != UserProfile.PreferredUnit.UnitType.IMPERIAL) PrecipitationUnit.MILLIMETERS else PrecipitationUnit.INCH,
|
||||
includeDistanceLabel = true
|
||||
includeDistanceLabel = true,
|
||||
precipitationProbability = data?.forecastData?.precipitationProbability?.get(index) ?: 0,
|
||||
isImperial = profile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -23,7 +23,6 @@ import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import de.timklge.karooheadwind.PrecipitationUnit
|
||||
import de.timklge.karooheadwind.R
|
||||
import de.timklge.karooheadwind.TemperatureUnit
|
||||
import de.timklge.karooheadwind.WeatherInterpretation
|
||||
@ -47,9 +46,10 @@ fun WeatherWidget(
|
||||
distance: Double? = null,
|
||||
includeDistanceLabel: Boolean = false,
|
||||
precipitationProbability: Int? = null,
|
||||
precipitationUnit: PrecipitationUnit,
|
||||
isImperial: Boolean
|
||||
) {
|
||||
val fontSize = 20.sp
|
||||
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth().padding(5.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
@ -60,7 +60,7 @@ fun WeatherWidget(
|
||||
Text(
|
||||
text = dateLabel,
|
||||
style = TextStyle(
|
||||
fontSize = 14.sp
|
||||
fontSize = fontSize
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -81,7 +81,7 @@ fun WeatherWidget(
|
||||
Text(
|
||||
text = text,
|
||||
style = TextStyle(
|
||||
fontSize = 14.sp
|
||||
fontSize = fontSize
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -91,7 +91,7 @@ fun WeatherWidget(
|
||||
text = timeLabel,
|
||||
style = TextStyle(
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 14.sp
|
||||
fontSize = fontSize
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -104,7 +104,7 @@ fun WeatherWidget(
|
||||
modifier = Modifier.size(72.dp)
|
||||
)
|
||||
|
||||
Column {
|
||||
Column(horizontalAlignment = Alignment.End) {
|
||||
// Temperature (larger)
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
@ -134,10 +134,16 @@ fun WeatherWidget(
|
||||
val precipitationProbabilityLabel =
|
||||
if (precipitationProbability != null) "${precipitationProbability}% " else ""
|
||||
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.droplet_regular),
|
||||
contentDescription = "Precipitation",
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
|
||||
Text(
|
||||
text = "${precipitationProbabilityLabel}${ceil(precipitation).toInt()}${precipitationUnit.unitDisplay}",
|
||||
text = "${precipitationProbabilityLabel}${ceil(precipitation).toInt()}",
|
||||
style = TextStyle(
|
||||
fontSize = 14.sp
|
||||
fontSize = fontSize
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -151,7 +157,7 @@ fun WeatherWidget(
|
||||
bitmap = getArrowBitmapByBearing(baseBitmap, windBearing).asImageBitmap(),
|
||||
colorFilter = ColorFilter.tint(Color.Black),
|
||||
contentDescription = "Wind direction",
|
||||
modifier = Modifier.size(16.dp)
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
@ -159,7 +165,7 @@ fun WeatherWidget(
|
||||
Text(
|
||||
text = "$windSpeed,$windGusts",
|
||||
style = TextStyle(
|
||||
fontSize = 14.sp
|
||||
fontSize = fontSize
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
BIN
app/src/main/res/drawable/droplet_regular.png
Normal file
BIN
app/src/main/res/drawable/droplet_regular.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.7 KiB |
Loading…
x
Reference in New Issue
Block a user