C++ / fmt (pull_request) Failing after 5s
C++ / build (pull_request) Failing after 11s
C++ / clang-tidy (pull_request) Failing after 10s
JS/TS / fmt (pull_request) Successful in 12s
JS/TS / lint (pull_request) Successful in 10s
Python / static (pull_request) Failing after 27s
Rust / build (pull_request) Successful in 54s
Python / verify (pull_request) Failing after 1m26s
Rust / fmt (pull_request) Successful in 46s
Rust / clippy (pull_request) Successful in 1m6s
108 lines
2.1 KiB
QML
108 lines
2.1 KiB
QML
pragma Singleton
|
|
pragma ComponentBehavior: Bound
|
|
|
|
import Quickshell
|
|
import Quickshell.Io
|
|
import Quickshell.Services.Notifications
|
|
import ZShell.Services
|
|
import qs.Components
|
|
import qs.Helpers
|
|
import qs.Paths
|
|
import qs.Services
|
|
import ZShell.Config
|
|
|
|
Singleton {
|
|
id: root
|
|
|
|
readonly property var appCooldownMap: new Map()
|
|
property alias dnd: props.dnd
|
|
readonly property alias groups: store.groups
|
|
property alias list: store.rows
|
|
readonly property alias popupGroups: store.popupGroups
|
|
readonly property list<NotificationRow> notClosed: store.rows.filter(n => !n.closed)
|
|
readonly property list<NotificationRow> popups: store.rows.filter(n => n.popup)
|
|
|
|
function shouldThrottle(appName: string): bool {
|
|
if (props.dnd || ShellState.anySidebarOpen())
|
|
return false;
|
|
|
|
const key = (appName || "unknown").trim().toLowerCase();
|
|
const cooldownSec = Config.notifs.appNotifCooldown;
|
|
const cooldownMs = Math.max(0, cooldownSec * 1000);
|
|
|
|
if (cooldownMs <= 0)
|
|
return true;
|
|
|
|
const now = Date.now();
|
|
const until = appCooldownMap.get(key) ?? 0;
|
|
|
|
if (now < until)
|
|
return false;
|
|
|
|
appCooldownMap.set(key, now + cooldownMs);
|
|
return true;
|
|
}
|
|
|
|
PersistentProperties {
|
|
id: props
|
|
|
|
property bool dnd
|
|
|
|
reloadableId: "notifs"
|
|
}
|
|
|
|
NotificationStore {
|
|
id: store
|
|
|
|
path: `${Paths.state}/notifs.sqlite`
|
|
}
|
|
|
|
NotificationServer {
|
|
id: server
|
|
|
|
actionsSupported: true
|
|
bodyHyperlinksSupported: true
|
|
bodyImagesSupported: true
|
|
bodyMarkupSupported: true
|
|
imageSupported: true
|
|
keepOnReload: true
|
|
persistenceSupported: true
|
|
|
|
onNotification: notif => {
|
|
notif.tracked = true;
|
|
store.insert(notif, root.shouldThrottle(notif.appName));
|
|
}
|
|
}
|
|
|
|
CustomShortcut {
|
|
description: "Clear all notifications"
|
|
name: "clearnotifs"
|
|
|
|
onPressed: store.clear()
|
|
}
|
|
|
|
IpcHandler {
|
|
function clear(): void {
|
|
store.clear();
|
|
}
|
|
|
|
function disableDnd(): void {
|
|
props.dnd = false;
|
|
}
|
|
|
|
function enableDnd(): void {
|
|
props.dnd = true;
|
|
}
|
|
|
|
function isDndEnabled(): bool {
|
|
return props.dnd;
|
|
}
|
|
|
|
function toggleDnd(): void {
|
|
props.dnd = !props.dnd;
|
|
}
|
|
|
|
target: "notifs"
|
|
}
|
|
}
|