From bf12f5e36d13ab6d98967cf884b3fee8ff75d20e Mon Sep 17 00:00:00 2001 From: Matt Pumarlo Date: Wed, 24 Jun 2026 15:54:14 -0500 Subject: [PATCH] feat: add pause button to notifs --- kobrax_moonraker_bridge.py | 37 +++++++++++++++++++++++++++++++++++ web/themes/default/app.js | 36 ++++++++++++++++++++++++++++++++++ web/themes/default/index.html | 19 ++++++++++++++++-- web/translations/de.json | 2 ++ web/translations/en.json | 2 ++ web/translations/es.json | 2 ++ web/translations/fr.json | 2 ++ web/translations/it.json | 2 ++ web/translations/zh-cn.json | 2 ++ 9 files changed, 102 insertions(+), 2 deletions(-) diff --git a/kobrax_moonraker_bridge.py b/kobrax_moonraker_bridge.py index c4add92..fcc2c6d 100644 --- a/kobrax_moonraker_bridge.py +++ b/kobrax_moonraker_bridge.py @@ -848,6 +848,7 @@ class KobraXBridge: self._print_active: bool = False self._notify_every_minutes: int = 0 self._notify_every_layers: int = 0 + self._notifications_paused: bool = False self._last_progress_notif_time: float = 0.0 self._last_progress_notif_layer: int = 0 try: @@ -860,6 +861,7 @@ class KobraXBridge: _ncfg.read(_np, encoding="utf-8") self._notify_every_minutes = _ncfg.getint("notifications", "notify_every_minutes", fallback=0) self._notify_every_layers = _ncfg.getint("notifications", "notify_every_layers", fallback=0) + self._notifications_paused = _ncfg.getboolean("notifications", "paused", fallback=False) except Exception: self._notification_urls = [] @@ -1107,6 +1109,8 @@ class KobraXBridge: # ------------------------------------------------------------------------- def _notify(self, event: str, filename: str = ""): + if self._notifications_paused: + return matching = [e for e in self._notification_urls if event in e.get("events", [])] if not matching: return @@ -4370,6 +4374,7 @@ class KobraXBridge: "notifications": self._notification_urls, "notify_every_minutes": self._notify_every_minutes, "notify_every_layers": self._notify_every_layers, + "notifications_paused": self._notifications_paused, }) async def handle_api_settings_post(self, request): @@ -4463,6 +4468,9 @@ class KobraXBridge: cfg.set("notifications", "notify_every_layers", str(notify_every_layers)) self._notify_every_minutes = notify_every_minutes self._notify_every_layers = notify_every_layers + if "notifications_paused" in data: + self._notifications_paused = bool(data.get("notifications_paused")) + cfg.set("notifications", "paused", "true" if self._notifications_paused else "false") with open(config_path, "w", encoding="utf-8") as f: f.write("# KX-Bridge Konfigurationsdatei\n\n") @@ -4473,6 +4481,34 @@ class KobraXBridge: asyncio.get_event_loop().call_later(0.3, self._restart_bridge) return response + async def handle_api_notifications_pause(self, request): + """Toggle or set the global notifications-paused flag without restarting.""" + try: + data = await request.json() + except Exception: + data = {} + if isinstance(data, dict) and "paused" in data: + self._notifications_paused = bool(data.get("paused")) + else: + self._notifications_paused = not self._notifications_paused + try: + import configparser + config_path = self._find_config_path() + config_path.parent.mkdir(parents=True, exist_ok=True) + cfg = configparser.ConfigParser() + if config_path.is_file(): + cfg.read(config_path, encoding="utf-8") + if not cfg.has_section("notifications"): + cfg.add_section("notifications") + cfg.set("notifications", "paused", "true" if self._notifications_paused else "false") + with open(config_path, "w", encoding="utf-8") as f: + f.write("# KX-Bridge Konfigurationsdatei\n\n") + cfg.write(f) + except Exception as e: + log.warning(f"Notif-Pause speichern fehlgeschlagen: {e}") + log.info(f"Benachrichtigungen {'pausiert' if self._notifications_paused else 'aktiv'}") + return self._json_cors({"status": "ok", "paused": self._notifications_paused}) + async def handle_api_notifications_test(self, request): try: data = await request.json() @@ -5343,6 +5379,7 @@ def build_app(bridge: KobraXBridge) -> web.Application: r.add_get("/api/settings", bridge.handle_api_settings_get) r.add_post("/api/settings", bridge.handle_api_settings_post) r.add_post("/api/notifications/test", bridge.handle_api_notifications_test) + r.add_post("/api/notifications/pause", bridge.handle_api_notifications_pause) r.add_get("/api/update/check", bridge.handle_api_update_check) r.add_post("/api/update/apply", bridge.handle_api_update_apply) r.add_post("/api/file_ready/clear", bridge.handle_api_file_ready_clear) diff --git a/web/themes/default/app.js b/web/themes/default/app.js index fcc978b..d0404c1 100644 --- a/web/themes/default/app.js +++ b/web/themes/default/app.js @@ -530,6 +530,7 @@ function applyLang() { var nhEl = document.getElementById("notif-hint"); if (nhEl && T.settings_notifications_hint) nhEl.innerHTML = T.settings_notifications_hint; setText("lbl-notif-add", T.settings_notif_add); + notifUpdateToggleBtn(); setText("lbl-notif-interval", T.settings_notif_interval_lbl); setText("lbl-notif-min-unit", T.settings_notif_min_unit); setText("lbl-notif-layers-unit", T.settings_notif_layers_unit); @@ -1525,7 +1526,39 @@ function drawChart(id, _, series) { // ── Notifications ── var _notifRows = []; +var _notifPaused = false; var _NOTIF_EVENTS = ["started", "finished", "failed", "cancelled", "paused", "progress"]; +function notifUpdateToggleBtn() { + var btn = document.getElementById("btn-notif-toggle"); + var lbl = document.getElementById("lbl-notif-toggle"); + if (!btn) return; + if (_notifPaused) { + if (lbl) lbl.textContent = T.settings_notif_paused || "Paused"; + btn.style.background = "var(--warn, #c08a2d)"; + btn.style.color = "#fff"; + } else { + if (lbl) lbl.textContent = T.settings_notif_active || "Active"; + btn.style.background = "var(--ok, #2e9e4f)"; + btn.style.color = "#fff"; + } +} +function notifTogglePaused() { + var target = !_notifPaused; + var btn = document.getElementById("btn-notif-toggle"); + if (btn) btn.disabled = true; + post("/api/notifications/pause", { paused: target }) + .then(function (r) { + return r.json(); + }) + .then(function (d) { + if (btn) btn.disabled = false; + _notifPaused = d && typeof d.paused === "boolean" ? d.paused : target; + notifUpdateToggleBtn(); + }) + .catch(function () { + if (btn) btn.disabled = false; + }); +} function notifRenderList(entries) { _notifRows = entries.map(function (e) { return { @@ -1722,6 +1755,8 @@ function openSettings() { var wuw = document.getElementById("s-web-upload-warning"); if (wuw) wuw.checked = d.web_upload_warning === undefined ? true : !!d.web_upload_warning; notifRenderList(d.notifications || []); + _notifPaused = !!d.notifications_paused; + notifUpdateToggleBtn(); var enm = document.getElementById("s-notif-every-min"); if (enm) enm.value = d.notify_every_minutes || 0; var enl = document.getElementById("s-notif-every-layers"); @@ -2589,6 +2624,7 @@ function saveSettings() { Math.max(1, parseInt((document.getElementById("s-poll-interval") || {}).value, 10) || 3) ), notifications: notifCollect(), + notifications_paused: _notifPaused, notify_every_minutes: parseInt((document.getElementById("s-notif-every-min") || {}).value || "0", 10) || 0, notify_every_layers: diff --git a/web/themes/default/index.html b/web/themes/default/index.html index c61f155..e968fe5 100644 --- a/web/themes/default/index.html +++ b/web/themes/default/index.html @@ -1622,8 +1622,23 @@
-
- 🔔 Benachrichtigungen +
+ + 🔔 + Benachrichtigungen + +