aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/modules/notifications/NotificationsModule.qml
diff options
context:
space:
mode:
Diffstat (limited to 'desktop/modules/notifications/NotificationsModule.qml')
-rw-r--r--desktop/modules/notifications/NotificationsModule.qml73
1 files changed, 73 insertions, 0 deletions
diff --git a/desktop/modules/notifications/NotificationsModule.qml b/desktop/modules/notifications/NotificationsModule.qml
new file mode 100644
index 0000000..6dea790
--- /dev/null
+++ b/desktop/modules/notifications/NotificationsModule.qml
@@ -0,0 +1,73 @@
+// Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+import Quickshell.Io
+import QtQuick
+import "../.."
+
+// notifyd's config.json: the daemon's timeouts and caps, and the balloon
+// shell's placement, DND rule and muted apps. The draft lives here, not in
+// the page, so the sidebar's unsaved mark survives the page unloading.
+Module {
+ id: nm
+ name: "notifications"
+ label: "Notifications"
+ // nf-fa-bell, present in Inconsolata Nerd Font.
+ icon: ""
+ settings: true
+ group: "Desktop"
+ keywords: ["notifyd", "timeout", "history", "queue", "mute", "dnd", "corner", "monitor", "balloon"]
+
+ property var draft: Notify.config
+ property string notice: ""
+ dirty: JSON.stringify(nm.draft) !== JSON.stringify(Notify.config)
+ readonly property bool valid: [nm.draft.liveCap, nm.draft.historyCap].every(v => v >= 1 && v <= 100)
+
+ // Not over unsaved edits.
+ function refresh() { if (!nm.dirty) nm.draft = Notify.config; }
+ function discard() { nm.draft = Notify.config; nm.notice = ""; }
+ function edit(patch) { nm.draft = Object.assign({}, nm.draft, patch); }
+
+ // Unknown keys in the file survive. The text goes on stdin to cat (the
+ // notes pattern: the exit code is the outcome); 1 is the write, 2 the
+ // reload, so a stopped daemon reads as saved-but-not-applied.
+ // Written in onStarted, then stdinEnabled cleared to give cat its EOF:
+ // the sequence notes' bodyWriter uses (NotesModule.qml).
+ function save() {
+ nm.notice = "";
+ nm.saver.data = JSON.stringify(Object.assign({}, Notify.rawConfig, nm.draft), null, 2) + "\n";
+ nm.saver.stdinEnabled = true;
+ nm.saver.running = false;
+ nm.saver.running = true;
+ }
+ property Process saver: Process {
+ property string data: ""
+ command: ["sh", "-c", 'mkdir -p "$(dirname "$1")" && cat > "$1" || exit 1; notifyctl reload || exit 2',
+ "sh", Notify.configPath]
+ onStarted: {
+ nm.saver.write(nm.saver.data);
+ nm.saver.stdinEnabled = false;
+ }
+ onExited: code => nm.notice = code === 0 ? "saved"
+ : code === 2 ? "saved; notifyd not reachable, it reads the file at its next start"
+ : "could not write " + Notify.configPath
+ }
+
+ page: Component {
+ Page {
+ title: "Notifications"
+ actions: Component {
+ SaveBar { dirty: nm.dirty; valid: nm.valid; note: "caps are 1 to 100"
+ onSave: nm.save(); onDiscard: nm.discard() }
+ }
+ NotificationsPage { width: parent.width; mod: nm }
+ }
+ }
+}