From 98203af3e4a034501f0f8dfa7218cfe8a0371e4f Mon Sep 17 00:00:00 2001 From: tux Date: Tue, 7 Oct 2025 03:25:48 +0530 Subject: [PATCH] feat: add notification timeout manager --- widgets/notifications/manager.ts | 50 ++++++++++++++++++++++++++ widgets/notifications/notification.tsx | 20 +++++++++++ 2 files changed, 70 insertions(+) create mode 100644 widgets/notifications/manager.ts diff --git a/widgets/notifications/manager.ts b/widgets/notifications/manager.ts new file mode 100644 index 0000000..7d17344 --- /dev/null +++ b/widgets/notifications/manager.ts @@ -0,0 +1,50 @@ +import GLib from "gi://GLib"; + +type TimeoutManager = { + setupTimeout: () => void; + clearTimeout: () => void; + handleHover: () => void; + handleHoverLost: () => void; + cleanup: () => void; +}; + +export const createTimeoutManager = ( + dismissCallback: () => void, + timeoutDelay: number, +): TimeoutManager => { + let isHovered = false; + let timeoutId: number | null = null; + + const clearTimeout = () => { + if (timeoutId !== null) { + GLib.source_remove(timeoutId); + timeoutId = null; + } + }; + + const setupTimeout = () => { + clearTimeout(); + + if (!isHovered) { + timeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, timeoutDelay, () => { + clearTimeout(); + dismissCallback(); + return GLib.SOURCE_REMOVE; + }); + } + }; + + return { + setupTimeout, + clearTimeout, + handleHover: () => { + isHovered = true; + clearTimeout(); + }, + handleHoverLost: () => { + isHovered = false; + setupTimeout(); + }, + cleanup: clearTimeout, + }; +}; diff --git a/widgets/notifications/notification.tsx b/widgets/notifications/notification.tsx index d11d60c..a244e12 100644 --- a/widgets/notifications/notification.tsx +++ b/widgets/notifications/notification.tsx @@ -3,6 +3,8 @@ import Adw from "gi://Adw"; import AstalNotifd from "gi://AstalNotifd"; import GLib from "gi://GLib"; import Pango from "gi://Pango"; +import { createTimeoutManager } from "./manager"; +import { onCleanup, onMount } from "ags"; const isIcon = (icon?: string | null) => { const iconTheme = Gtk.IconTheme.get_for_display(Gdk.Display.get_default()!); @@ -33,7 +35,20 @@ const urgency = (n: AstalNotifd.Notification) => { const { VERTICAL } = Gtk.Orientation; const { START, END, CENTER } = Gtk.Align; +// Keep track of notification validity +const TIMEOUT_DELAY = 3000; + export const Notification = ({ n }: { n: AstalNotifd.Notification }) => { + const timeoutManager = createTimeoutManager(() => n.dismiss(), TIMEOUT_DELAY); + + onMount(() => { + timeoutManager.setupTimeout(); + }); + + onCleanup(() => { + timeoutManager.cleanup(); + }); + return ( { orientation={VERTICAL} spacing={20} > + timeoutManager.handleHover()} + onLeave={() => timeoutManager.handleHoverLost()} + /> + {(n.appIcon || isIcon(n.desktopEntry)) && (