diff --git a/app/src/main/java/com/pranshulgg/weather_master_app/data/worker/widgets/WidgetWeatherMapper.kt b/app/src/main/java/com/pranshulgg/weather_master_app/data/worker/widgets/WidgetWeatherMapper.kt index 2283eb586..20ea30ddf 100644 --- a/app/src/main/java/com/pranshulgg/weather_master_app/data/worker/widgets/WidgetWeatherMapper.kt +++ b/app/src/main/java/com/pranshulgg/weather_master_app/data/worker/widgets/WidgetWeatherMapper.kt @@ -74,10 +74,14 @@ fun widgetWeatherMapper( ) val icon = it.weatherCondition.toIcon(matchingDaily, it.time) + + val precipitationProbability = it.precipitationProbability + WidgetHourlyItem( time = formattedTime, temp = "${temperature}°", - conditionIcon = icon + conditionIcon = icon, + precipitationProbability = precipitationProbability ) } diff --git a/app/src/main/java/com/pranshulgg/weather_master_app/data/worker/widgets/WidgetWeatherUpdater.kt b/app/src/main/java/com/pranshulgg/weather_master_app/data/worker/widgets/WidgetWeatherUpdater.kt index 39029d7a5..c05068570 100644 --- a/app/src/main/java/com/pranshulgg/weather_master_app/data/worker/widgets/WidgetWeatherUpdater.kt +++ b/app/src/main/java/com/pranshulgg/weather_master_app/data/worker/widgets/WidgetWeatherUpdater.kt @@ -10,6 +10,7 @@ import androidx.glance.appwidget.updateAll import com.pranshulgg.weather_master_app.widgets.WeatherWidgetStateDefinition import com.pranshulgg.weather_master_app.widgets.config.WidgetConfig import com.pranshulgg.weather_master_app.widgets.glance.GlanceWidget +import com.pranshulgg.weather_master_app.widgets.hourly.WidgetHourly import com.pranshulgg.weather_master_app.widgets.pill.WidgetPill import com.pranshulgg.weather_master_app.widgets.summary.SummaryWidget import com.pranshulgg.weather_master_app.widgets.weather.WeatherWidget @@ -31,6 +32,8 @@ class WeatherWidgetUpdater( private val widgetWeather4 = Weather4Widget() + private val widgetHourly = WidgetHourly() + suspend fun update(json: String) { val manager = GlanceAppWidgetManager(context) suspend fun updateWidgets( @@ -54,6 +57,7 @@ class WeatherWidgetUpdater( updateWidgets(widgetGlance, manager.getGlanceIds(GlanceWidget::class.java)) updateWidgets(widgetClockDaily, manager.getGlanceIds(ClockDailyWidget::class.java)) updateWidgets(widgetWeather4, manager.getGlanceIds(Weather4Widget::class.java)) + updateWidgets(widgetHourly, manager.getGlanceIds(WidgetHourly::class.java)) } diff --git a/app/src/main/java/com/pranshulgg/weather_master_app/widgets/config/WidgetConfig.kt b/app/src/main/java/com/pranshulgg/weather_master_app/widgets/config/WidgetConfig.kt index 424b79da3..e49db860a 100644 --- a/app/src/main/java/com/pranshulgg/weather_master_app/widgets/config/WidgetConfig.kt +++ b/app/src/main/java/com/pranshulgg/weather_master_app/widgets/config/WidgetConfig.kt @@ -20,6 +20,7 @@ data class WidgetConfig( val dailyCount: Int = 4, val showDailyInsteadOfCurrent: Boolean = false, val isWeatherBackground: Boolean = false, - val isDisplayHourly: Boolean = false + val isDisplayHourly: Boolean = false, + val showPrecipitationProbability: Boolean = false, -) \ No newline at end of file + ) \ No newline at end of file diff --git a/app/src/main/java/com/pranshulgg/weather_master_app/widgets/config/WidgetConfigActivity.kt b/app/src/main/java/com/pranshulgg/weather_master_app/widgets/config/WidgetConfigActivity.kt index 6c59012ef..e04e5e0fe 100644 --- a/app/src/main/java/com/pranshulgg/weather_master_app/widgets/config/WidgetConfigActivity.kt +++ b/app/src/main/java/com/pranshulgg/weather_master_app/widgets/config/WidgetConfigActivity.kt @@ -20,6 +20,8 @@ import com.pranshulgg.weather_master_app.core.ui.theme.isThemeDark import com.pranshulgg.weather_master_app.data.worker.widgets.WeatherWidgetUpdater import com.pranshulgg.weather_master_app.widgets.glance.GlanceWidgetReceiver import com.pranshulgg.weather_master_app.widgets.glance.ui.GlanceWidgetConfig +import com.pranshulgg.weather_master_app.widgets.hourly.WidgetHourlyReceiver +import com.pranshulgg.weather_master_app.widgets.hourly.ui.HourlyWidgetConfig import com.pranshulgg.weather_master_app.widgets.weather.WeatherWidgetReceiver import com.pranshulgg.weather_master_app.widgets.weather.ui.WeatherWidgetConfig import com.pranshulgg.weather_master_app.widgets.weather4.Weather4WidgerReceiver @@ -126,6 +128,10 @@ class WidgetConfigActivity : ComponentActivity() { Weather4WidgerReceiver::class.java.name -> { Weather4Config { onDone(it) } } + + WidgetHourlyReceiver::class.java.name -> { + HourlyWidgetConfig { onDone(it) } + } } } } diff --git a/app/src/main/java/com/pranshulgg/weather_master_app/widgets/hourly/WidgetHourly.kt b/app/src/main/java/com/pranshulgg/weather_master_app/widgets/hourly/WidgetHourly.kt new file mode 100644 index 000000000..4a2250163 --- /dev/null +++ b/app/src/main/java/com/pranshulgg/weather_master_app/widgets/hourly/WidgetHourly.kt @@ -0,0 +1,138 @@ +package com.pranshulgg.weather_master_app.widgets.hourly + +import android.content.Context +import android.os.Build +import androidx.compose.runtime.Composable +import androidx.compose.ui.unit.dp +import androidx.glance.ColorFilter +import androidx.glance.GlanceId +import androidx.glance.GlanceModifier +import androidx.glance.GlanceTheme +import androidx.glance.ImageProvider +import androidx.glance.action.actionStartActivity +import androidx.glance.action.clickable +import androidx.glance.appwidget.GlanceAppWidget +import androidx.glance.appwidget.SizeMode +import androidx.glance.appwidget.cornerRadius +import androidx.glance.appwidget.provideContent +import androidx.glance.background +import androidx.glance.currentState +import androidx.glance.layout.Alignment +import androidx.glance.layout.Box +import androidx.glance.layout.Row +import androidx.glance.layout.fillMaxHeight +import androidx.glance.layout.fillMaxSize +import androidx.glance.layout.fillMaxWidth +import com.pranshulgg.weather_master_app.MainActivity +import com.pranshulgg.weather_master_app.R +import com.pranshulgg.weather_master_app.widgets.WeatherWidgetStateDefinition +import com.pranshulgg.weather_master_app.widgets.WeatherWidgetStateJson +import com.pranshulgg.weather_master_app.widgets.model.WidgetWeather +import com.pranshulgg.weather_master_app.widgets.ui.ReloadButton +import com.pranshulgg.weather_master_app.widgets.ui.colors.WidgetColors +import com.pranshulgg.weather_master_app.widgets.ui.colors.WidgetTheme +import com.pranshulgg.weather_master_app.widgets.weather.components.WidgetHourlyItem +import kotlinx.serialization.json.Json + + +class WidgetHourly : GlanceAppWidget() { + + override val sizeMode = SizeMode.Exact + override val stateDefinition = + WeatherWidgetStateDefinition + + override suspend fun provideGlance( + context: Context, + id: GlanceId + ) { + + + provideContent { + val widgetState = + currentState() + val widgetColors = WidgetColors() + + val json = widgetState.json + val state = json?.let { + Json.decodeFromString(it) + } + val config = widgetState.config + + if (state != null) { + val modifier = when (config.widgetTheme) { + WidgetTheme.TRANSPARENT -> GlanceModifier.fillMaxSize() + else -> GlanceModifier.fillMaxSize() + .appWidgetBackgroundShape( + config.widgetTheme, + widgetColors + ) + } + + val textColor = widgetColors + .getTextColor(config.widgetTextTheme, config.widgetTheme) + ?: Pair(GlanceTheme.colors.onSurface, null) + + val textColorVariant = widgetColors + .getTextVariantColor(config.widgetTextTheme, config.widgetTheme) + ?: GlanceTheme.colors.onSurfaceVariant + Box( + modifier.clickable(actionStartActivity()) + ) { + + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalAlignment = Alignment.CenterHorizontally, + modifier = GlanceModifier.fillMaxWidth().fillMaxHeight() + ) { + val hourlyIconSize = 22 * config.iconSize + val hourlyTextSize = 14 * config.fontSize + state.hourly.take(config.hourlyCount).forEach { + WidgetHourlyItem( + it.time, + it.temp, + it.conditionIcon, + hourlyTextSize, + hourlyIconSize, + textColor.first, + textColorVariant, + verticalPadding = 10.dp, + precipitationProbability = if (config.showPrecipitationProbability) + it.precipitationProbability else null + ) + } + } + + } + } else { + ReloadButton() + } + } + } + +} + + +@Composable +private fun GlanceModifier.appWidgetBackgroundShape( + theme: WidgetTheme, + widgetColors: WidgetColors +): GlanceModifier { + + + val color = widgetColors.getBackgroundColor( + theme + ) + + + return if (Build.VERSION.SDK_INT >= 31) { + this + .cornerRadius(android.R.dimen.system_app_widget_background_radius) + .background(color ?: GlanceTheme.colors.widgetBackground) + } else { + this + .background( + ImageProvider(R.drawable.weather_widget_background), + colorFilter = ColorFilter.tint(color ?: GlanceTheme.colors.widgetBackground) + ) + } +} diff --git a/app/src/main/java/com/pranshulgg/weather_master_app/widgets/hourly/WidgetHourlyReceiver.kt b/app/src/main/java/com/pranshulgg/weather_master_app/widgets/hourly/WidgetHourlyReceiver.kt new file mode 100644 index 000000000..9e57ea183 --- /dev/null +++ b/app/src/main/java/com/pranshulgg/weather_master_app/widgets/hourly/WidgetHourlyReceiver.kt @@ -0,0 +1,10 @@ +package com.pranshulgg.weather_master_app.widgets.hourly + +import androidx.glance.appwidget.GlanceAppWidgetReceiver +import com.pranshulgg.weather_master_app.widgets.pill.WidgetPill + + +class WidgetHourlyReceiver : GlanceAppWidgetReceiver() { + override val glanceAppWidget = WidgetHourly() + +} \ No newline at end of file diff --git a/app/src/main/java/com/pranshulgg/weather_master_app/widgets/weather/components/WidgetHourlyItem.kt b/app/src/main/java/com/pranshulgg/weather_master_app/widgets/weather/components/WidgetHourlyItem.kt index aac777849..b057f679d 100644 --- a/app/src/main/java/com/pranshulgg/weather_master_app/widgets/weather/components/WidgetHourlyItem.kt +++ b/app/src/main/java/com/pranshulgg/weather_master_app/widgets/weather/components/WidgetHourlyItem.kt @@ -2,6 +2,7 @@ package com.pranshulgg.weather_master_app.widgets.weather.components import android.graphics.Color import androidx.compose.runtime.Composable +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.glance.GlanceModifier @@ -28,12 +29,14 @@ fun WidgetHourlyItem( fontSize: Float, iconSize: Float, textColor: ColorProvider, - textColorVariant: ColorProvider + textColorVariant: ColorProvider, + verticalPadding: Dp = 5.dp, + precipitationProbability: Int? = null ) { Column( horizontalAlignment = Alignment.CenterHorizontally, - modifier = GlanceModifier.padding(horizontal = 5.dp, vertical = 5.dp) + modifier = GlanceModifier.padding(horizontal = 5.dp, vertical = verticalPadding) ) { Text( temp, @@ -43,6 +46,17 @@ fun WidgetHourlyItem( fontSize = fontSize.sp ) ) + + if (precipitationProbability != null) { + Text( + "${precipitationProbability}%", + style = TextStyle( + color = textColorVariant, + fontSize = (fontSize * 0.9).sp + ) + ) + } + Spacer(GlanceModifier.height(3.dp)) Image( provider = ImageProvider(icon), diff --git a/app/src/main/java/com/pranshulgg/weather_master_app/widgets/weather/ui/WeatherWidgetConfig.kt b/app/src/main/java/com/pranshulgg/weather_master_app/widgets/weather/ui/WeatherWidgetConfig.kt index c41a46560..a6437d4ce 100644 --- a/app/src/main/java/com/pranshulgg/weather_master_app/widgets/weather/ui/WeatherWidgetConfig.kt +++ b/app/src/main/java/com/pranshulgg/weather_master_app/widgets/weather/ui/WeatherWidgetConfig.kt @@ -72,6 +72,8 @@ fun WeatherWidgetConfig(onDone: (WidgetConfig) -> Unit = {}) { var widgetTextTheme by remember { mutableStateOf(WidgetTextTheme.AUTO) } var selectedIconSize by remember { mutableFloatStateOf(1f) } + var showPrecipitationProbability by remember { mutableStateOf(false) } + val widgetThemeOptions = WidgetTheme.entries.filter { it != WidgetTheme.TRANSPARENT } .map { DialogOption(it.toString(), stringResource(it.label)) } @@ -106,7 +108,8 @@ fun WeatherWidgetConfig(onDone: (WidgetConfig) -> Unit = {}) { selectedFontSize, selectedIconSize, widgetTextTheme, - widgetTheme + widgetTheme, + showPrecipitationProbability ) } } @@ -210,6 +213,15 @@ fun WeatherWidgetConfig(onDone: (WidgetConfig) -> Unit = {}) { widgetTheme = selected } ), + SettingTile.SwitchTile( + leading = { SettingsTileIcon(R.drawable.rainy_light_24px) }, + title = stringResource(R.string.settings_widget_show_precip_probability), + description = stringResource(R.string.settings_widget_show_precip_probability_secondary), + checked = showPrecipitationProbability, + onCheckedChange = { + showPrecipitationProbability = it + } + ), SettingTile.DialogOptionTile( leading = { SettingsTileIcon(R.drawable.format_paint_24px) }, title = stringResource(R.string.settings_widget_text_color), @@ -240,7 +252,8 @@ fun WeatherWidgetConfig(onDone: (WidgetConfig) -> Unit = {}) { fontSize = selectedFontSize, iconSize = selectedIconSize, widgetTheme = widgetTheme, - widgetTextTheme = widgetTextTheme + widgetTextTheme = widgetTextTheme, + showPrecipitationProbability = showPrecipitationProbability ) ) }, @@ -269,6 +282,7 @@ private fun GlanceWidgetPreview( iconSize: Float, textTheme: WidgetTextTheme, widgetTheme: WidgetTheme, + showPrecipitationProbability: Boolean ) { val textColor = when (textTheme) { @@ -313,7 +327,8 @@ private fun GlanceWidgetPreview( widgetColor, textColor, textColorSecondary, - hourlyContainerColor + hourlyContainerColor, + showPrecipitationProbability ) WidgetVariant.COMPACT -> CompactWidgetPreview( @@ -335,7 +350,8 @@ private fun LargeWidgetPreview( widgetColor: Color, textColor: Color, textColorSecondary: Color, - hourlyContainerColor: Color + hourlyContainerColor: Color, + showPrecipitationProbability: Boolean ) { @@ -386,6 +402,13 @@ private fun LargeWidgetPreview( fontWeight = FontWeight.Medium, color = textColor ) + if (showPrecipitationProbability) { + Text( + "${temp * 2}%", + fontSize = (hourlyTextSize * 0.9).sp, + color = textColorSecondary + ) + } Gap(3.dp) WeatherIconBox(icon, hourlyIconSize.dp) Gap(3.dp) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 974215bc4..f1b7b5c04 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -463,6 +463,8 @@ in cm + Show precipitation probability + Displays the precipitation probability only when the selected source provides it diff --git a/app/src/main/res/xml/hourly_widget_info.xml b/app/src/main/res/xml/hourly_widget_info.xml new file mode 100644 index 000000000..d765f9fad --- /dev/null +++ b/app/src/main/res/xml/hourly_widget_info.xml @@ -0,0 +1,10 @@ + + \ No newline at end of file