Files
tpanel/widgets/notifications/index.tsx
2025-10-12 06:12:35 +05:30

65 lines
1.7 KiB
TypeScript

import {
For,
createBinding,
createComputed,
createState,
onCleanup,
} from "ags";
import { Astal, Gdk, Gtk } from "ags/gtk4";
import AstalNotifd from "gi://AstalNotifd";
import { Notification } from "./notification";
export const WINDOW_NAME = "notifications";
export const Notifications = (gdkmonitor: Gdk.Monitor) => {
const notifd = AstalNotifd.get_default();
const isDndMode = createBinding(notifd, "dont-disturb");
const { TOP, RIGHT } = Astal.WindowAnchor;
const [notifications, setNotifications] = createState(
new Array<AstalNotifd.Notification>(),
);
const notifiedHandler = notifd.connect("notified", (_, id, replaced) => {
const notification = notifd.get_notification(id);
if (replaced && notifications.get().some((n) => n.id === id)) {
setNotifications((ns) => ns.map((n) => (n.id === id ? notification : n)));
} else {
setNotifications((ns) => [notification, ...ns]);
}
});
const resolvedHandler = notifd.connect("resolved", (_, id) => {
setNotifications((ns) => ns.filter((n) => n.id !== id));
});
onCleanup(() => {
notifd.disconnect(notifiedHandler);
notifd.disconnect(resolvedHandler);
});
const shouldShowWindow = createComputed(
[notifications, isDndMode],
(notifs, dndEnabled) => {
return !dndEnabled && notifs.length > 0;
},
);
return (
<window
$={(self) => onCleanup(() => self.destroy())}
name={WINDOW_NAME}
cssClasses={["notifications"]}
gdkmonitor={gdkmonitor}
visible={shouldShowWindow}
anchor={TOP | RIGHT}
>
<box orientation={Gtk.Orientation.VERTICAL} spacing={10}>
<For each={notifications}>{(n) => <Notification n={n} />}</For>
</box>
</window>
);
};