Fix notification centre icons and dismissal

This commit is contained in:
SirBlob committed 2026-09-24 03:12:31 +00:00
1 parent 77ba1dadff
commit ad46fe4a53
5 files changed
+50 -17

No files matched your search

@@ -1,18 +1,23 @@
.pragma library
// Each history file is one line of JSON, so the reader concatenates the
// directory and parses line by line. Newest first, by timestamp.
// Each history file is one line of JSON, and the reader prefixes every line
// with the file's name and a tab so an entry can be removed later. Newest
// first, by timestamp.
function parseHistory(raw) {
var lines = String(raw || "").split("\n")
var entries = []
for (var i = 0; i < lines.length; i++) {
var line = lines[i].trim()
if (!line) continue
var tab = line.indexOf("\t")
var fileName = tab >= 0 ? line.slice(0, tab) : ""
var json = tab >= 0 ? line.slice(tab + 1) : line
try {
var value = JSON.parse(line)
var value = JSON.parse(json)
if (!value || typeof value !== "object") continue
entries.push({
id: value.id || 0,
fileName: fileName,
app: value.app || "",
summary: value.summary || "",
body: value.body || "",
@@ -45,8 +45,9 @@ Item {
}
function clearAll() {
root.run("blob-shell notifications clearHistory")
root.run("blob-shell notifications clear")
root.entries = []
refreshTimer.restart()
}
function toggleSilence() {
@@ -57,16 +58,19 @@ Item {
function dismissEntry(index) {
var entry = root.entries[index]
if (!entry) return
root.run("blob-notify-dismiss " + entry.id)
root.run("blob-shell notifications remove " + Util.shellQuote(entry.fileName))
var next = []
for (var i = 0; i < root.entries.length; i++)
if (i !== index) next.push(root.entries[i])
root.entries = next
refreshTimer.restart()
}
Process {
id: historyProbe
command: ["bash", "-c", "cat " + root.historyDir + "/*.json 2>/dev/null || true"]
command: ["bash", "-c",
"for f in \"$1\"/*.json; do [[ -e $f ]] || continue; printf '%s\\t' \"${f##*/}\"; awk 1 \"$f\"; done",
"--", root.historyDir]
stdout: StdioCollector {
onStreamFinished: root.entries = HistoryModel.parseHistory(text)
}
@@ -139,13 +143,13 @@ Item {
spacing: Style.spaceReal(4)
CardIconButton {
icon: root.doNotDisturb ? "" : ""
icon: root.doNotDisturb ? "\uf1f6" : "\uf0f3"
active: root.doNotDisturb
onActivated: root.toggleSilence()
}
CardIconButton {
icon: ""
icon: "\uf1f8"
onActivated: root.clearAll()
}
}
@@ -177,7 +181,7 @@ Item {
Text {
anchors.horizontalCenter: parent.horizontalCenter
text: ""
text: "\uf0a2"
textFormat: Text.PlainText
color: Util.alpha(Color.blue, 0.6)
font.family: Style.font.family
@@ -48,7 +48,7 @@ Rectangle {
Text {
anchors.right: parent.right
text: ""
text: "\uf00d"
textFormat: Text.PlainText
color: closeHover.hovered ? Color.urgent : Color.magenta
font.family: Style.font.family
+22 -7
View File
@@ -26,8 +26,8 @@ Item {
readonly property string settingsPath: stateDir + "notifications.json"
// One file per on-screen popup, so live toasts survive shell restarts.
// A file exists exactly as long as its popup is showing: written when the
// toast appears, moved into historyDir when it expires, is dismissed, or is
// acted upon.
// toast appears, moved into historyDir when it expires unseen, and deleted
// when it is dismissed or acted upon.
readonly property string popupStateDir: stateDir + "notifications/"
// The notifications that already left the screen, one file each, trimmed to
// the newest historyLimit. This directory IS the history: `showHistory`
@@ -327,12 +327,14 @@ Item {
// id would dismiss that unrelated notification at the server.
var restored = isRestoredRow(entry)
var ref = !restored && originalId >= 0 ? liveRefs[originalId] : null
// The popup is leaving the screen — for any reason — so its file must not
// survive to the next shell restart. It becomes the newest history entry
// instead. Rows that never had a file (a history replay, the empty-history
// placeholder) archive to nothing, which the move tolerates.
// The popup is leaving the screen, so its file must not survive to the
// next shell restart. An expired toast was missed and becomes the newest
// history entry; a dismissed or acted-on one was seen and is deleted.
// Rows that never had a file (a history replay, the empty-history
// placeholder) archive or delete nothing, which both jobs tolerate.
if (entry) {
archivePopupFileFor(entry)
if (reason === "expire") archivePopupFileFor(entry)
else deletePopupFileFor(entry)
if (restored) delete restoredPopups[NotificationLogic.popupFileName(entry)]
}
popupModel.remove(index)
@@ -585,6 +587,15 @@ Item {
enqueuePopupFileJob(command, done)
}
function removeHistoryEntry(fileName) {
var name = String(fileName || "")
if (!/^[A-Za-z0-9._-]+\.json$/.test(name)) return false
enqueuePopupFileJob(["bash", "-c",
"rm -f \"$1/$2\" \"$3/${2%.json}\"-*", "--",
historyDir, name, imagesDir])
return true
}
function clearHistory() {
enqueuePopupFileJob(["bash", "-c",
"for f in \"$1\"/*.json; do\n" +
@@ -888,6 +899,10 @@ Item {
return "ok"
}
function remove(fileName: string): string {
return service.removeHistoryEntry(fileName) ? "ok" : "none"
}
function dismissAll(): string {
service.clearPopups()
return "ok"