From 96423e451b0c2f874cdf1ae61694eeee0289c766 Mon Sep 17 00:00:00 2001 From: Honey Date: Fri, 24 Jul 2026 23:38:32 +0200 Subject: [PATCH] Weather: show city name above the current conditions, toggleable Just the city itself (first segment of the geocode label), not the full "City, State, Country" string -- too cluttered for a dashboard header. Off by default for manually-entered coordinates since there's no resolved place name to show there regardless of the toggle. New show_city setting, on by default, alongside the other display toggles in Weather settings. --- screens/weather.py | 26 +++++++++++++++++++++++--- web/app.py | 1 + web/templates/settings_weather.html | 4 ++++ 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/screens/weather.py b/screens/weather.py index 5357fd4..a8e8de1 100644 --- a/screens/weather.py +++ b/screens/weather.py @@ -8,7 +8,7 @@ import requests from PIL import Image, ImageDraw from screens.base import Screen -from screens.render_utils import load_font, text_width +from screens.render_utils import load_font, text_width, truncate_to_width from screens.weather_icons import WMO_CODES, draw_weather_icon BLACK = (0, 0, 0) @@ -36,6 +36,7 @@ class WeatherScreen(Screen): "show_high_low": True, "show_rain_chance": True, "show_hourly_graph": True, + "show_city": True, } def get_poll_interval(self, settings: dict) -> int: @@ -212,8 +213,27 @@ class WeatherScreen(Screen): text_gap = temp_h * 0.22 text_block_h = temp_h + text_gap + desc_h + ((text_gap + extra_h) if extra_line else 0) current_h = max(icon_size, text_block_h) - top_pad = (height - current_h) / 2 if lower_sections == 0 else height * 0.05 - block_top = top_pad + + # City name, above the icon/temp block -- just the city itself, not + # the full "City, State, Country" geocode label (too long/cluttered + # for a dashboard header). Nothing to show for manually-entered + # coordinates, since there's no resolved place name for those. + city_font = load_font(size=int(scale * 0.045), bold=True) + city_label = "" + city_h = city_gap = city_top = 0 + if settings.get("show_city", True) and settings.get("city"): + city_label = truncate_to_width(draw, settings["city"].split(",")[0].strip(), city_font, width - 2 * pad) + if city_label: + city_left, city_top, city_right, city_bottom = draw.textbbox((0, 0), city_label, font=city_font) + city_h = city_bottom - city_top + city_gap = height * 0.025 + + total_top_h = city_h + city_gap + current_h + top_pad = (height - total_top_h) / 2 if lower_sections == 0 else height * 0.05 + + if city_label: + draw.text((pad, top_pad - city_top), city_label, font=city_font, fill="black") + block_top = top_pad + city_h + city_gap icon_cx = pad + icon_size / 2 icon_cy = block_top + current_h / 2 diff --git a/web/app.py b/web/app.py index 64fdbd8..78916da 100644 --- a/web/app.py +++ b/web/app.py @@ -71,6 +71,7 @@ def create_app(config, screens: dict, scheduler) -> Flask: forecast_days = 3 update_minutes = max(1, int(request.form.get("update_minutes", 30) or 30)) display_toggles = { + "show_city": "show_city" in request.form, "show_hourly_graph": "show_hourly_graph" in request.form, "show_feels_like": "show_feels_like" in request.form, "show_high_low": "show_high_low" in request.form, diff --git a/web/templates/settings_weather.html b/web/templates/settings_weather.html index ee925e6..85a9f53 100644 --- a/web/templates/settings_weather.html +++ b/web/templates/settings_weather.html @@ -35,6 +35,10 @@

Weather itself only refreshes the panel when something actually changed, so a shorter interval here mostly just means fresher data, not more flashing.

+