127 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
			
		
		
	
	
			127 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
import { Gtk, Gdk } from "ags/gtk4";
 | 
						|
import Adw from "gi://Adw";
 | 
						|
import GLib from "gi://GLib";
 | 
						|
import AstalNotifd from "gi://AstalNotifd";
 | 
						|
import Pango from "gi://Pango";
 | 
						|
import { timeout } from "ags/time";
 | 
						|
 | 
						|
function isIcon(icon?: string | null) {
 | 
						|
    const iconTheme = Gtk.IconTheme.get_for_display(Gdk.Display.get_default()!);
 | 
						|
    return icon && iconTheme.has_icon(icon);
 | 
						|
}
 | 
						|
 | 
						|
function fileExists(path: string) {
 | 
						|
    return GLib.file_test(path, GLib.FileTest.EXISTS);
 | 
						|
}
 | 
						|
 | 
						|
function time(time: number, format = "%H:%M") {
 | 
						|
    return GLib.DateTime.new_from_unix_local(time).format(format)!;
 | 
						|
}
 | 
						|
 | 
						|
function urgency(n: AstalNotifd.Notification) {
 | 
						|
    const { LOW, NORMAL, CRITICAL } = AstalNotifd.Urgency;
 | 
						|
    switch (n.urgency) {
 | 
						|
        case LOW:
 | 
						|
            return "low";
 | 
						|
        case CRITICAL:
 | 
						|
            return "critical";
 | 
						|
        case NORMAL:
 | 
						|
        default:
 | 
						|
            return "normal";
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
export default function Notification({
 | 
						|
    notification: n,
 | 
						|
    onHoverLost,
 | 
						|
}: {
 | 
						|
    notification: AstalNotifd.Notification;
 | 
						|
    onHoverLost: () => void;
 | 
						|
}) {
 | 
						|
    const timer = timeout(3000, () => {
 | 
						|
        onHoverLost();
 | 
						|
    });
 | 
						|
    return (
 | 
						|
        <Adw.Clamp maximumSize={400}>
 | 
						|
            <box
 | 
						|
                widthRequest={400}
 | 
						|
                class={`Notification ${urgency(n)}`}
 | 
						|
                orientation={Gtk.Orientation.VERTICAL}
 | 
						|
            >
 | 
						|
                <Gtk.EventControllerMotion
 | 
						|
                    onEnter={() => timer.cancel()}
 | 
						|
                    onLeave={onHoverLost}
 | 
						|
                />
 | 
						|
                <box class="header">
 | 
						|
                    {(n.appIcon || isIcon(n.desktopEntry)) && (
 | 
						|
                        <image
 | 
						|
                            class="app-icon"
 | 
						|
                            visible={Boolean(n.appIcon || n.desktopEntry)}
 | 
						|
                            iconName={n.appIcon || n.desktopEntry}
 | 
						|
                        />
 | 
						|
                    )}
 | 
						|
                    <label
 | 
						|
                        class="app-name"
 | 
						|
                        halign={Gtk.Align.START}
 | 
						|
                        ellipsize={Pango.EllipsizeMode.END}
 | 
						|
                        label={n.appName || "Unknown"}
 | 
						|
                    />
 | 
						|
                    <label
 | 
						|
                        class="time"
 | 
						|
                        hexpand
 | 
						|
                        halign={Gtk.Align.END}
 | 
						|
                        label={time(n.time)}
 | 
						|
                    />
 | 
						|
                    <button onClicked={() => n.dismiss()}>
 | 
						|
                        <image iconName="window-close-symbolic" />
 | 
						|
                    </button>
 | 
						|
                </box>
 | 
						|
                <Gtk.Separator visible />
 | 
						|
                <box class="content">
 | 
						|
                    {n.image && fileExists(n.image) && (
 | 
						|
                        <image valign={Gtk.Align.START} class="image" file={n.image} />
 | 
						|
                    )}
 | 
						|
                    {n.image && isIcon(n.image) && (
 | 
						|
                        <box valign={Gtk.Align.START} class="icon-image">
 | 
						|
                            <image
 | 
						|
                                iconName={n.image}
 | 
						|
                                halign={Gtk.Align.CENTER}
 | 
						|
                                valign={Gtk.Align.CENTER}
 | 
						|
                            />
 | 
						|
                        </box>
 | 
						|
                    )}
 | 
						|
                    <box orientation={Gtk.Orientation.VERTICAL}>
 | 
						|
                        <label
 | 
						|
                            class="summary"
 | 
						|
                            halign={Gtk.Align.START}
 | 
						|
                            xalign={0}
 | 
						|
                            label={n.summary}
 | 
						|
                            ellipsize={Pango.EllipsizeMode.END}
 | 
						|
                        />
 | 
						|
                        {n.body && (
 | 
						|
                            <label
 | 
						|
                                class="body"
 | 
						|
                                wrap
 | 
						|
                                useMarkup
 | 
						|
                                halign={Gtk.Align.START}
 | 
						|
                                xalign={0}
 | 
						|
                                justify={Gtk.Justification.FILL}
 | 
						|
                                label={n.body}
 | 
						|
                            />
 | 
						|
                        )}
 | 
						|
                    </box>
 | 
						|
                </box>
 | 
						|
                {n.actions.length > 0 && (
 | 
						|
                    <box class="actions">
 | 
						|
                        {n.actions.map(({ label, id }) => (
 | 
						|
                            <button hexpand onClicked={() => n.invoke(id)}>
 | 
						|
                                <label label={label} halign={Gtk.Align.CENTER} hexpand />
 | 
						|
                            </button>
 | 
						|
                        ))}
 | 
						|
                    </box>
 | 
						|
                )}
 | 
						|
            </box>
 | 
						|
        </Adw.Clamp>
 | 
						|
    );
 | 
						|
}
 |