Landscape orientation, redesigned web UI, rotation on/off + minutes, weather by city name

- Panel is mounted sideways: render landscape (600x400), rotate to the
  panel's native portrait orientation right before writing to hardware.
- Web UI: card-based layout, dark mode, active nav highlighting, save
  confirmation toasts, error banners.
- Rotation: separate enabled/disabled toggle (off pins to the first screen
  in the list) and the interval is now in minutes instead of raw seconds.
  Migrates existing config.json from the old interval_seconds field.
- Weather: type a city name instead of hunting down coordinates, resolved
  via Open-Meteo's free geocoding API. Manual lat/long still available as
  a fallback.
This commit is contained in:
Honey committed 2026-07-21 22:51:16 +02:00
1 parent 7c197e20a5
commit 61348be674
11 files changed
+393 -104

No files matched your search

+9 -3
View File
@@ -17,7 +17,8 @@ DEFAULT_CONFIG_PATH = Path(__file__).resolve().parent / "config.json"
DEFAULT_ROTATION = {
"screens": ["clock", "weather"],
"interval_seconds": 300,
"interval_minutes": 5,
"enabled": True,
}
@@ -35,6 +36,11 @@ class Config:
data = {}
data.setdefault("rotation", dict(DEFAULT_ROTATION))
# Migrate configs written before rotation had minutes/enabled.
if "interval_seconds" in data["rotation"] and "interval_minutes" not in data["rotation"]:
data["rotation"]["interval_minutes"] = max(1, round(data["rotation"].pop("interval_seconds") / 60))
data["rotation"].setdefault("interval_minutes", DEFAULT_ROTATION["interval_minutes"])
data["rotation"].setdefault("enabled", DEFAULT_ROTATION["enabled"])
data.setdefault("navidrome_priority", True)
data.setdefault("settings", {})
for screen_id, screen in screens.items():
@@ -72,9 +78,9 @@ class Config:
with self._lock:
return dict(self._data["rotation"])
def set_rotation(self, screens: list[str], interval_seconds: int) -> None:
def set_rotation(self, screens: list[str], interval_minutes: int, enabled: bool) -> None:
with self._lock:
self._data["rotation"] = {"screens": screens, "interval_seconds": interval_seconds}
self._data["rotation"] = {"screens": screens, "interval_minutes": interval_minutes, "enabled": enabled}
self.save()
def get_navidrome_priority(self) -> bool: