* fix #23: Show date of weather data in weather forecast, main menu * Use localized date format
This commit is contained in:
parent
a948ed4561
commit
69626dce67
@ -39,6 +39,7 @@ 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)
|
||||
@ -99,6 +100,8 @@ 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 result = glance.compose(context, DpSize.Unspecified) {
|
||||
Box(modifier = GlanceModifier.fillMaxSize(), contentAlignment = Alignment.CenterEnd) {
|
||||
@ -114,11 +117,13 @@ class WeatherDataType(
|
||||
temperature = data.current.temperature.roundToInt(),
|
||||
temperatureUnit = if (userProfile?.preferredUnit?.temperature != UserProfile.PreferredUnit.UnitType.IMPERIAL) TemperatureUnit.CELSIUS else TemperatureUnit.FAHRENHEIT,
|
||||
timeLabel = formattedTime,
|
||||
dateLabel = formattedDate,
|
||||
rowAlignment = when (config.alignment){
|
||||
ViewConfig.Alignment.LEFT -> Alignment.Horizontal.Start
|
||||
ViewConfig.Alignment.CENTER -> Alignment.Horizontal.CenterHorizontally
|
||||
ViewConfig.Alignment.RIGHT -> Alignment.Horizontal.End
|
||||
}
|
||||
},
|
||||
singleDisplay = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,6 +55,7 @@ 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
|
||||
|
||||
class CycleHoursAction : ActionCallback {
|
||||
@ -139,6 +140,13 @@ class WeatherForecastDataType(
|
||||
Row(modifier = GlanceModifier.fillMaxSize().clickable(onClick = actionRunCallback<CycleHoursAction>()), horizontalAlignment = Alignment.Horizontal.CenterHorizontally) {
|
||||
val hourOffset = widgetSettings?.currentForecastHourOffset ?: 0
|
||||
|
||||
var previousDate: String? = let {
|
||||
val unixTime = data.forecastData.time.firstOrNull()
|
||||
val formattedDate = unixTime?.let { Instant.ofEpochSecond(it).atZone(ZoneId.systemDefault()).toLocalDate().toString() }
|
||||
|
||||
formattedDate
|
||||
}
|
||||
|
||||
for (index in hourOffset..hourOffset + 2){
|
||||
if (index >= data.forecastData.weatherCode.size) {
|
||||
break
|
||||
@ -155,6 +163,8 @@ class WeatherForecastDataType(
|
||||
val interpretation = WeatherInterpretation.fromWeatherCode(data.forecastData.weatherCode[index])
|
||||
val unixTime = data.forecastData.time[index]
|
||||
val formattedTime = timeFormatter.format(Instant.ofEpochSecond(unixTime))
|
||||
val formattedDate = Instant.ofEpochSecond(unixTime).atZone(ZoneId.systemDefault()).toLocalDate().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT))
|
||||
val hasNewDate = formattedDate != previousDate || index == 0
|
||||
|
||||
Weather(baseBitmap,
|
||||
current = interpretation,
|
||||
@ -167,8 +177,11 @@ class WeatherForecastDataType(
|
||||
precipitationUnit = if (userProfile?.preferredUnit?.distance != UserProfile.PreferredUnit.UnitType.IMPERIAL) PrecipitationUnit.MILLIMETERS else PrecipitationUnit.INCH,
|
||||
temperature = data.forecastData.temperature[index].roundToInt(),
|
||||
temperatureUnit = if (userProfile?.preferredUnit?.temperature != UserProfile.PreferredUnit.UnitType.IMPERIAL) TemperatureUnit.CELSIUS else TemperatureUnit.FAHRENHEIT,
|
||||
timeLabel = formattedTime
|
||||
timeLabel = formattedTime,
|
||||
dateLabel = if (hasNewDate) formattedDate else null
|
||||
)
|
||||
|
||||
previousDate = formattedDate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,9 +17,12 @@ import androidx.glance.layout.ContentScale
|
||||
import androidx.glance.layout.Row
|
||||
import androidx.glance.layout.Spacer
|
||||
import androidx.glance.layout.fillMaxHeight
|
||||
import androidx.glance.layout.fillMaxSize
|
||||
import androidx.glance.layout.fillMaxWidth
|
||||
import androidx.glance.layout.height
|
||||
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
|
||||
@ -51,14 +54,15 @@ fun getWeatherIcon(interpretation: WeatherInterpretation): Int {
|
||||
@Composable
|
||||
fun Weather(baseBitmap: Bitmap, current: WeatherInterpretation, windBearing: Int, windSpeed: Int, windGusts: Int, windSpeedUnit: WindUnit,
|
||||
precipitation: Double, precipitationProbability: Int?, precipitationUnit: PrecipitationUnit,
|
||||
temperature: Int, temperatureUnit: TemperatureUnit, timeLabel: String? = null, rowAlignment: Alignment.Horizontal = Alignment.Horizontal.CenterHorizontally) {
|
||||
temperature: Int, temperatureUnit: TemperatureUnit, timeLabel: String? = null, rowAlignment: Alignment.Horizontal = Alignment.Horizontal.CenterHorizontally,
|
||||
dateLabel: String? = null, singleDisplay: Boolean = false) {
|
||||
|
||||
val fontSize = 14f
|
||||
|
||||
Column(modifier = GlanceModifier.fillMaxHeight().padding(2.dp).width(85.dp), horizontalAlignment = rowAlignment) {
|
||||
Row(modifier = GlanceModifier.defaultWeight(), horizontalAlignment = rowAlignment, verticalAlignment = Alignment.CenterVertically) {
|
||||
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) {
|
||||
Image(
|
||||
modifier = GlanceModifier.defaultWeight(),
|
||||
modifier = GlanceModifier.defaultWeight().wrapContentWidth().padding(1.dp),
|
||||
provider = ImageProvider(getWeatherIcon(current)),
|
||||
contentDescription = "Current weather information",
|
||||
contentScale = ContentScale.Fit,
|
||||
@ -66,6 +70,19 @@ fun Weather(baseBitmap: Bitmap, current: WeatherInterpretation, windBearing: Int
|
||||
)
|
||||
}
|
||||
|
||||
if (dateLabel != null && !singleDisplay){
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Text(
|
||||
text = dateLabel,
|
||||
style = TextStyle(
|
||||
color = ColorProvider(Color.Black, Color.White),
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontSize = TextUnit(fontSize, TextUnitType.Sp)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Row(verticalAlignment = Alignment.CenterVertically, horizontalAlignment = rowAlignment) {
|
||||
if (timeLabel != null){
|
||||
Text(
|
||||
@ -78,7 +95,7 @@ fun Weather(baseBitmap: Bitmap, current: WeatherInterpretation, windBearing: Int
|
||||
}
|
||||
|
||||
Image(
|
||||
modifier = GlanceModifier.height(20.dp).width(12.dp),
|
||||
modifier = GlanceModifier.height(16.dp).width(12.dp).padding(1.dp),
|
||||
provider = ImageProvider(R.drawable.thermometer),
|
||||
contentDescription = "Temperature",
|
||||
contentScale = ContentScale.Fit,
|
||||
@ -91,14 +108,16 @@ fun Weather(baseBitmap: Bitmap, current: WeatherInterpretation, windBearing: Int
|
||||
)
|
||||
}
|
||||
|
||||
Row(verticalAlignment = Alignment.CenterVertically, horizontalAlignment = rowAlignment) {
|
||||
/* Image(
|
||||
modifier = GlanceModifier.height(20.dp).width(12.dp),
|
||||
provider = ImageProvider(R.drawable.water_regular),
|
||||
contentDescription = "Rain",
|
||||
contentScale = ContentScale.Fit,
|
||||
colorFilter = ColorFilter.tint(ColorProvider(Color.Black, Color.White))
|
||||
) */
|
||||
Row(verticalAlignment = Alignment.CenterVertically, horizontalAlignment = rowAlignment, modifier = GlanceModifier.fillMaxWidth()) {
|
||||
if (dateLabel != null && singleDisplay){
|
||||
Text(
|
||||
text = "$dateLabel",
|
||||
style = TextStyle(color = ColorProvider(Color.Black, Color.White),
|
||||
fontFamily = FontFamily.Monospace, fontSize = TextUnit(fontSize, TextUnitType.Sp))
|
||||
)
|
||||
|
||||
Spacer(modifier = GlanceModifier.width(5.dp))
|
||||
}
|
||||
|
||||
val precipitationProbabilityLabel = if (precipitationProbability != null) "${precipitationProbability}%," else ""
|
||||
Text(
|
||||
@ -109,7 +128,7 @@ fun Weather(baseBitmap: Bitmap, current: WeatherInterpretation, windBearing: Int
|
||||
Spacer(modifier = GlanceModifier.width(5.dp))
|
||||
|
||||
Image(
|
||||
modifier = GlanceModifier.height(20.dp).width(12.dp),
|
||||
modifier = GlanceModifier.height(16.dp).width(12.dp).padding(1.dp),
|
||||
provider = ImageProvider(getArrowBitmapByBearing(baseBitmap, windBearing + 180)),
|
||||
contentDescription = "Current wind direction",
|
||||
contentScale = ContentScale.Fit,
|
||||
|
||||
@ -222,16 +222,19 @@ fun MainScreen() {
|
||||
if (stats.failedWeatherRequest != null && (stats.lastSuccessfulWeatherRequest == null || stats.failedWeatherRequest!! > stats.lastSuccessfulWeatherRequest!!)){
|
||||
val successfulTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(stats.lastSuccessfulWeatherRequest ?: 0), ZoneOffset.systemDefault()).toLocalTime().truncatedTo(
|
||||
ChronoUnit.SECONDS)
|
||||
val successfulDate = LocalDateTime.ofInstant(Instant.ofEpochMilli(stats.lastSuccessfulWeatherRequest ?: 0), ZoneOffset.systemDefault()).toLocalDate()
|
||||
val lastTryTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(stats.failedWeatherRequest ?: 0), ZoneOffset.systemDefault()).toLocalTime().truncatedTo(
|
||||
ChronoUnit.SECONDS)
|
||||
val lastTryDate = LocalDateTime.ofInstant(Instant.ofEpochMilli(stats.failedWeatherRequest ?: 0), ZoneOffset.systemDefault()).toLocalDate()
|
||||
|
||||
val successStr = if(lastPosition != null) " Last data received at ${successfulTime}${lastPositionDistanceStr}." else ""
|
||||
Text(modifier = Modifier.padding(5.dp), text = "Failed to update weather data; last try at ${lastTryTime}.${successStr}")
|
||||
val successStr = if(lastPosition != null) " Last data received at $successfulDate ${successfulTime}${lastPositionDistanceStr}." else ""
|
||||
Text(modifier = Modifier.padding(5.dp), text = "Failed to update weather data; last try at $lastTryDate ${lastTryTime}.${successStr}")
|
||||
} else if(stats.lastSuccessfulWeatherRequest != null){
|
||||
val localDate = LocalDateTime.ofInstant(Instant.ofEpochMilli(stats.lastSuccessfulWeatherRequest ?: 0), ZoneOffset.systemDefault()).toLocalDate()
|
||||
val localTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(stats.lastSuccessfulWeatherRequest ?: 0), ZoneOffset.systemDefault()).toLocalTime().truncatedTo(
|
||||
ChronoUnit.SECONDS)
|
||||
|
||||
Text(modifier = Modifier.padding(5.dp), text = "Last weather data received at ${localTime}${lastPositionDistanceStr}")
|
||||
Text(modifier = Modifier.padding(5.dp), text = "Last weather data received at $localDate ${localTime}${lastPositionDistanceStr}")
|
||||
} else {
|
||||
Text(modifier = Modifier.padding(5.dp), text = "No weather data received yet, waiting for GPS fix...")
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user