127 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			127 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import { bind } from "astal";
 | 
						|
import { Gtk } from "astal/gtk4";
 | 
						|
import Notifd from "gi://AstalNotifd";
 | 
						|
import { NotificationIcon } from "./Icon";
 | 
						|
import { createTimeoutManager } from "../../../util/notifd";
 | 
						|
 | 
						|
export function NotificationWidget({
 | 
						|
    notification,
 | 
						|
}: {
 | 
						|
    notification: Notifd.Notification;
 | 
						|
}) {
 | 
						|
    const { START, CENTER, END } = Gtk.Align;
 | 
						|
    const actions = notification.actions || [];
 | 
						|
    const TIMEOUT_DELAY = 3000;
 | 
						|
 | 
						|
    // Keep track of notification validity
 | 
						|
    const notifd = Notifd.get_default();
 | 
						|
    const timeoutManager = createTimeoutManager(
 | 
						|
        () => notification.dismiss(),
 | 
						|
        TIMEOUT_DELAY,
 | 
						|
    );
 | 
						|
    return (
 | 
						|
        <box
 | 
						|
            setup={(self) => {
 | 
						|
                // Set up timeout
 | 
						|
                timeoutManager.setupTimeout();
 | 
						|
                const clickGesture = Gtk.GestureClick.new();
 | 
						|
                clickGesture.set_button(0); // 0 means any button
 | 
						|
                clickGesture.connect("pressed", (gesture, _) => {
 | 
						|
                    try {
 | 
						|
                        // Get which button was pressed (1=left, 2=middle, 3=right)
 | 
						|
                        const button = gesture.get_current_button();
 | 
						|
 | 
						|
                        if (button === 1) {
 | 
						|
                            // PRIMARY/LEFT
 | 
						|
                            if (actions.length > 0) n.invoke(actions[0]);
 | 
						|
                        } else if (button === 2) {
 | 
						|
                            // MIDDLE
 | 
						|
                            notifd.notifications?.forEach((n) => {
 | 
						|
                                n.dismiss();
 | 
						|
                            });
 | 
						|
                        } else if (button === 3) {
 | 
						|
                            // SECONDARY/RIGHT
 | 
						|
                            notification.dismiss();
 | 
						|
                        }
 | 
						|
                    } catch (error) {
 | 
						|
                        console.error(error);
 | 
						|
                    }
 | 
						|
                });
 | 
						|
                self.add_controller(clickGesture);
 | 
						|
 | 
						|
                self.connect("unrealize", () => {
 | 
						|
                    timeoutManager.cleanup();
 | 
						|
                });
 | 
						|
            }}
 | 
						|
            onHoverEnter={timeoutManager.handleHover}
 | 
						|
            onHoverLeave={timeoutManager.handleHoverLost}
 | 
						|
            vertical
 | 
						|
            vexpand={false}
 | 
						|
            cssClasses={["notification", `${urgency(notification)}`]}
 | 
						|
            name={notification.id.toString()}
 | 
						|
        >
 | 
						|
            <box cssClasses={["header"]}>
 | 
						|
                <label
 | 
						|
                    cssClasses={["app-name"]}
 | 
						|
                    halign={CENTER}
 | 
						|
                    label={bind(notification, "app_name")}
 | 
						|
                />
 | 
						|
                <label
 | 
						|
                    cssClasses={["time"]}
 | 
						|
                    hexpand
 | 
						|
                    halign={END}
 | 
						|
                    label={time(notification.time)}
 | 
						|
                />
 | 
						|
            </box>
 | 
						|
            <Gtk.Separator />
 | 
						|
            <box cssClasses={["content"]}>
 | 
						|
                <box
 | 
						|
                    cssClasses={["thumb"]}
 | 
						|
                    visible={Boolean(NotificationIcon(notification))}
 | 
						|
                    halign={CENTER}
 | 
						|
                    valign={CENTER}
 | 
						|
                    vexpand={true}
 | 
						|
                >
 | 
						|
                    {NotificationIcon(notification)}
 | 
						|
                </box>
 | 
						|
                <box
 | 
						|
                    vertical
 | 
						|
                    cssClasses={["text-content"]}
 | 
						|
                    hexpand={true}
 | 
						|
                    halign={CENTER}
 | 
						|
                    valign={CENTER}
 | 
						|
                >
 | 
						|
                    <label
 | 
						|
                        cssClasses={["title"]}
 | 
						|
                        valign={CENTER}
 | 
						|
                        wrap={false}
 | 
						|
                        label={bind(notification, "summary")}
 | 
						|
                    />
 | 
						|
                    {notification.body && (
 | 
						|
                        <label
 | 
						|
                            cssClasses={["body"]}
 | 
						|
                            valign={CENTER}
 | 
						|
                            wrap={true}
 | 
						|
                            maxWidthChars={50}
 | 
						|
                            label={bind(notification, "body")}
 | 
						|
                        />
 | 
						|
                    )}
 | 
						|
                </box>
 | 
						|
            </box>
 | 
						|
            {actions.length > 0 && (
 | 
						|
                <box cssClasses={["actions"]}>
 | 
						|
                    {actions.map(({ label, action }) => (
 | 
						|
                        <button
 | 
						|
                            hexpand
 | 
						|
                            cssClasses={["action-button"]}
 | 
						|
                            onClicked={() => notification.invoke(action)}
 | 
						|
                        >
 | 
						|
                            <label label={label} halign={CENTER} hexpand />
 | 
						|
                        </button>
 | 
						|
                    ))}
 | 
						|
                </box>
 | 
						|
            )}
 | 
						|
        </box>
 | 
						|
    );
 | 
						|
}
 |