import GLib from "gi://GLib" import { App, Astal, Gdk, Gtk } from "astal/gtk3" import Notifd from "gi://AstalNotifd" import { Variable, bind } from "astal" import { MAX_TIMEOUT } from "../notif-config" const notifd = Notifd.get_default() export const dndIcon = Variable.derive([bind(notifd, "dontDisturb")], (dnd) => dnd ? "notifications-disabled-symbolic" : "preferences-system-notifications-symbolic", ) export function DndToggle() { return ( ) } notifd.default_timeout = MAX_TIMEOUT // notifications restored from the daemon's cache on startup are stale for (const n of notifd.notifications) { n.dismiss() } // the daemon honors app-requested timeouts, so enforce our own cap for // notifications that ask for more (or none at all). critical notifications // are exempt and stay until dismissed. notifd.connect("notified", (_, id: number) => { const n = notifd.get_notification(id) if (!n || n.urgency === Notifd.Urgency.CRITICAL) return if (n.expire_timeout <= 0 || n.expire_timeout > MAX_TIMEOUT) { GLib.timeout_add(GLib.PRIORITY_DEFAULT, MAX_TIMEOUT, () => { if (notifd.notifications.includes(n)) n.dismiss() return GLib.SOURCE_REMOVE }) } }) function formatTime(n: Notifd.Notification) { return GLib.DateTime.new_from_unix_local(n.time).format("%H:%M")! } export function NotificationCard(n: Notifd.Notification) { const critical = n.urgency === Notifd.Urgency.CRITICAL return ( {n.image !== "" && ( )} {n.actions.filter((a) => a.label).length > 0 && ( {n.actions .filter((a) => a.label) .map((a) => ( ))} )} ) } export default function Notifications(gdkmonitor: Gdk.Monitor) { const { TOP, RIGHT } = Astal.WindowAnchor return ( ns.length > 0)} > {bind(notifd, "notifications").as((ns) => [...ns] .sort((a, b) => b.time - a.time) .map((n) => NotificationCard(n)), )} ) }