diff --git a/scheduler.py b/scheduler.py index 03b8d6d..e81fb38 100644 --- a/scheduler.py +++ b/scheduler.py @@ -88,6 +88,18 @@ class Scheduler: self.config.resume_rotation() self._wake.set() + def invalidate_screen(self, screen_id: str): + """Force the next tick to re-check() this screen instead of reusing + its cached state, however much of its poll_interval is left. + Without this, a settings change (e.g. weather's forecast_days) sits + in config.json immediately but the screen keeps rendering whatever + it last fetched under the *old* settings until its own poll_interval + happens to elapse -- up to 30 minutes for weather's default.""" + cache = self._caches.get(screen_id) + if cache is not None: + cache.checked_at = 0.0 + self._wake.set() + def get_status(self) -> dict: with self._status_lock: status = dict(self._status) diff --git a/web/app.py b/web/app.py index 54ed337..64fdbd8 100644 --- a/web/app.py +++ b/web/app.py @@ -55,6 +55,7 @@ def create_app(config, screens: dict, scheduler) -> Flask: "boost_cover": "boost_cover" in request.form, "grayscale_cover": "grayscale_cover" in request.form, }) + scheduler.invalidate_screen("navidrome") return redirect(url_for("settings_navidrome", saved=1)) return render_template("settings_navidrome.html", settings=config.get_screen_settings("navidrome")) @@ -92,6 +93,7 @@ def create_app(config, screens: dict, scheduler) -> Flask: "update_minutes": update_minutes, **display_toggles, }) + scheduler.invalidate_screen("weather") return redirect(url_for("settings_weather", saved=1)) else: config.update_screen_settings("weather", { @@ -102,6 +104,7 @@ def create_app(config, screens: dict, scheduler) -> Flask: "update_minutes": update_minutes, **display_toggles, }) + scheduler.invalidate_screen("weather") return redirect(url_for("settings_weather", saved=1)) return render_template("settings_weather.html", settings=config.get_screen_settings("weather"), error=error) @@ -131,9 +134,11 @@ def create_app(config, screens: dict, scheduler) -> Flask: "results": results, "update_minutes": update_minutes, }) + scheduler.invalidate_screen("departures") return redirect(url_for("settings_departures", found=found["name"])) else: config.update_screen_settings("departures", {"results": results, "update_minutes": update_minutes}) + scheduler.invalidate_screen("departures") return redirect(url_for("settings_departures", saved=1)) return render_template("settings_departures.html", settings=config.get_screen_settings("departures"), error=error) @@ -188,6 +193,7 @@ def create_app(config, screens: dict, scheduler) -> Flask: if not error: config.update_screen_settings("journey", updates) + scheduler.invalidate_screen("journey") found_parts = [v for k, v in (("origin", origin_query), ("destination", destination_query)) if v] if found_parts: current = config.get_screen_settings("journey") @@ -236,13 +242,16 @@ def create_app(config, screens: dict, scheduler) -> Flask: "uploaded_filename": dest.name, **common_updates, }) + scheduler.invalidate_screen("picture") return redirect(url_for("settings_picture", saved=1)) elif url: config.update_screen_settings("picture", {"mode": "url", "image_url": url, **common_updates}) + scheduler.invalidate_screen("picture") return redirect(url_for("settings_picture", saved=1)) else: # Neither a new upload nor a URL change -- just update fit/boost/grayscale. config.update_screen_settings("picture", common_updates) + scheduler.invalidate_screen("picture") return redirect(url_for("settings_picture", saved=1)) return render_template("settings_picture.html", settings=config.get_screen_settings("picture"), error=error)