166 lines
4.2 KiB
QML
166 lines
4.2 KiB
QML
pragma Singleton
|
|
pragma ComponentBehavior: Bound
|
|
|
|
import QtQuick
|
|
import Quickshell
|
|
import Quickshell.Io
|
|
import Quickshell.Services.Notifications
|
|
import Caelestia
|
|
import qs.components.misc
|
|
import qs.services
|
|
import qs.config
|
|
import qs.utils
|
|
|
|
Singleton {
|
|
id: root
|
|
|
|
property list<NotifData> list: []
|
|
readonly property list<NotifData> notClosed: list.filter(n => !n.closed)
|
|
readonly property list<NotifData> popups: list.filter(n => n.popup)
|
|
property alias dnd: props.dnd
|
|
|
|
property bool loaded
|
|
|
|
function hasFullscreen(): bool {
|
|
for (const monitor of Hypr.monitors.values) {
|
|
if (monitor?.activeWorkspace?.toplevels.values.some(t => t.lastIpcObject.fullscreen > 1))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function shouldShowPopup(): bool {
|
|
if (props.dnd || [...Visibilities.screens.values()].some(v => v.sidebar))
|
|
return false;
|
|
if (Config.notifs.fullscreen === "off" && hasFullscreen())
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
onDndChanged: {
|
|
if (!Config.utilities.toasts.dndChanged)
|
|
return;
|
|
|
|
if (dnd)
|
|
Toaster.toast(qsTr("Do not disturb enabled"), qsTr("Popup notifications are now disabled"), "do_not_disturb_on");
|
|
else
|
|
Toaster.toast(qsTr("Do not disturb disabled"), qsTr("Popup notifications are now enabled"), "do_not_disturb_off");
|
|
}
|
|
|
|
onListChanged: {
|
|
if (loaded)
|
|
saveTimer.restart();
|
|
}
|
|
|
|
Timer {
|
|
id: saveTimer
|
|
|
|
interval: 1000
|
|
onTriggered: storage.setText(JSON.stringify(root.notClosed.map(n => ({
|
|
time: n.time,
|
|
id: n.id,
|
|
summary: n.summary,
|
|
body: n.body,
|
|
appIcon: n.appIcon,
|
|
appName: n.appName,
|
|
image: n.image,
|
|
expireTimeout: n.expireTimeout,
|
|
urgency: n.urgency,
|
|
resident: n.resident,
|
|
hasActionIcons: n.hasActionIcons,
|
|
actions: n.actions
|
|
}))))
|
|
}
|
|
|
|
PersistentProperties {
|
|
id: props
|
|
|
|
property bool dnd
|
|
|
|
reloadableId: "notifs"
|
|
}
|
|
|
|
NotificationServer {
|
|
id: server
|
|
|
|
keepOnReload: false
|
|
actionsSupported: true
|
|
bodyHyperlinksSupported: true
|
|
bodyImagesSupported: true
|
|
bodyMarkupSupported: true
|
|
imageSupported: true
|
|
persistenceSupported: true
|
|
|
|
onNotification: notif => {
|
|
notif.tracked = true;
|
|
|
|
const comp = notifComp.createObject(root, {
|
|
popup: root.shouldShowPopup(),
|
|
notification: notif
|
|
});
|
|
root.list = [comp, ...root.list];
|
|
}
|
|
}
|
|
|
|
FileView {
|
|
id: storage
|
|
|
|
printErrors: false
|
|
path: `${Paths.state}/notifs.json`
|
|
onLoaded: {
|
|
const data = JSON.parse(text());
|
|
for (const notif of data)
|
|
root.list.push(notifComp.createObject(root, notif));
|
|
root.list.sort((a, b) => b.time - a.time);
|
|
root.loaded = true;
|
|
}
|
|
onLoadFailed: err => {
|
|
if (err === FileViewError.FileNotFound) {
|
|
root.loaded = true;
|
|
Qt.callLater(() => setText("[]"));
|
|
}
|
|
}
|
|
}
|
|
|
|
// qmllint disable unresolved-type
|
|
CustomShortcut {
|
|
// qmllint enable unresolved-type
|
|
name: "clearNotifs"
|
|
description: "Clear all notifications"
|
|
onPressed: {
|
|
for (const notif of root.list.slice())
|
|
notif.close();
|
|
}
|
|
}
|
|
|
|
IpcHandler {
|
|
function clear(): void {
|
|
for (const notif of root.list.slice())
|
|
notif.close();
|
|
}
|
|
|
|
function isDndEnabled(): bool {
|
|
return props.dnd;
|
|
}
|
|
|
|
function toggleDnd(): void {
|
|
props.dnd = !props.dnd;
|
|
}
|
|
|
|
function enableDnd(): void {
|
|
props.dnd = true;
|
|
}
|
|
|
|
function disableDnd(): void {
|
|
props.dnd = false;
|
|
}
|
|
|
|
target: "notifs"
|
|
}
|
|
|
|
Component {
|
|
id: notifComp
|
|
|
|
NotifData {}
|
|
}
|
|
}
|