import { App, Gtk, Gdk, Widget } from 'astal/gtk3'; import { Variable } from 'astal'; import GLib from 'gi://GLib'; import AstalApps from 'gi://AstalApps'; const Applications = AstalApps.Apps.new(); import AstalNotifd from 'gi://AstalNotifd'; import NotifGestureWrapper from './gesture'; // import SmoothProgress from '../misc/smooth-progress'; // Make a variable to connect to for Widgets // to know when there are notifs or not export const HasNotifs = Variable(false); const setTime = (time: number): string => GLib.DateTime .new_from_unix_local(time) .format('%H:%M') ?? ''; const NotifIcon = ({ notifObj }: { notifObj: AstalNotifd.Notification }) => { let icon: string | undefined; if (notifObj.get_image() && notifObj.get_image() !== '') { icon = notifObj.get_image(); App.add_icons(icon); } else if (notifObj.get_app_icon() !== '' && Widget.Icon.lookup_icon(notifObj.get_app_icon())) { icon = notifObj.get_app_icon(); } else { icon = Applications.fuzzy_query( notifObj.get_app_name(), )[0]?.get_icon_name(); } return ( <box valign={Gtk.Align.CENTER} className="icon" css={` min-width: 78px; min-height: 78px; `} > {icon && ( <icon icon={icon} css="font-size: 58px;" halign={Gtk.Align.CENTER} hexpand valign={Gtk.Align.CENTER} vexpand /> )} </box> ); }; const setupButton = (self: Gtk.Widget) => { const display = Gdk.Display.get_default(); // OnHover self.connect('enter-notify-event', () => { if (!display) { return; } self.get_window()?.set_cursor(Gdk.Cursor.new_from_name( display, 'pointer', )); }); // OnHoverLost self.connect('leave-notify-event', () => { if (!display) { return; } self.get_window()?.set_cursor(null); }); }; const BlockedApps = [ 'Spotify', ]; export const Notification = ({ id = 0, popup_timer = 0, slide_in_from = 'Left' as 'Left' | 'Right', }): NotifGestureWrapper | undefined => { const notifications = AstalNotifd.get_default(); const notifObj = notifications.get_notification(id); if (!notifObj) { return; } if (BlockedApps.find((app) => app === notifObj.app_name)) { notifObj.dismiss(); return; } HasNotifs.set(notifications.get_notifications().length > 0); // const progress = SmoothProgress({ className: 'smooth-progress' }); return ( <NotifGestureWrapper id={id} popup_timer={popup_timer} slide_in_from={slide_in_from} /* setup_notif={(self) => { if (self.is_popup) { self.connect('notify::popup-timer', () => { progress.fraction = self.popup_timer / 5; }); } else { progress.destroy(); } }}*/ > <box vertical className={`notification ${notifObj.get_urgency()} widget`}> {/* Content */} <box> <NotifIcon notifObj={notifObj} /> {/* Top of Content */} <box vertical css="min-width: 400px"> <box> {/* Title */} <label className="title" halign={Gtk.Align.START} valign={Gtk.Align.END} xalign={0} hexpand max_width_chars={24} truncate wrap label={notifObj.get_summary()} use_markup={notifObj.get_summary().startsWith('<')} /> {/* Time */} <label className="time" valign={Gtk.Align.CENTER} halign={Gtk.Align.END} label={setTime(notifObj.get_time())} /> {/* Close button */} <button className="close-button" valign={Gtk.Align.START} halign={Gtk.Align.END} setup={setupButton} onButtonReleaseEvent={() => { notifObj.dismiss(); }} > <icon icon="window-close-symbolic" /> </button> </box> {/* Description */} <label className="description" hexpand use_markup xalign={0} label={notifObj.get_body()} wrap /> </box> </box> {/* progress */} {/* Actions */} <box className="actions"> {notifObj.get_actions().map((action) => ( <button className="action-button" hexpand setup={setupButton} onButtonReleaseEvent={() => notifObj.invoke(action.id)} > <label label={action.label} /> </button> ))} </box> </box> </NotifGestureWrapper> ) as NotifGestureWrapper; };