205 lines
6.1 KiB
TypeScript
205 lines
6.1 KiB
TypeScript
import { App, Gtk, Gdk, Widget } from 'astal/gtk3';
|
|
import { Variable } from 'astal';
|
|
|
|
import GLib from 'gi://GLib?version=2.0';
|
|
|
|
import AstalApps from 'gi://AstalApps?version=0.1';
|
|
const Applications = AstalApps.Apps.new();
|
|
|
|
import AstalNotifd from 'gi://AstalNotifd?version=0.1';
|
|
const Notifications = AstalNotifd.get_default();
|
|
|
|
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;
|
|
|
|
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}
|
|
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.window.set_cursor(Gdk.Cursor.new_from_name(
|
|
display,
|
|
'pointer',
|
|
));
|
|
});
|
|
|
|
// OnHoverLost
|
|
self.connect('leave-notify-event', () => {
|
|
if (!display) {
|
|
return;
|
|
}
|
|
self.window.set_cursor(null);
|
|
});
|
|
};
|
|
|
|
const BlockedApps = [
|
|
'Spotify',
|
|
];
|
|
|
|
export const Notification = ({
|
|
id = 0,
|
|
popup_timer = 0,
|
|
slide_in_from = 'Left' as 'Left' | 'Right',
|
|
}): ReturnType<typeof NotifGestureWrapper> | undefined => {
|
|
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('timer-update', () => {
|
|
progress.fraction = self.popup_timer / 5;
|
|
});
|
|
}
|
|
else {
|
|
progress.destroy();
|
|
}
|
|
}}
|
|
>
|
|
<box vertical className={`notification ${notifObj.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.summary}
|
|
use_markup={notifObj.summary.startsWith('<')}
|
|
/>
|
|
|
|
{/* Time */}
|
|
<label
|
|
className="time"
|
|
valign={Gtk.Align.CENTER}
|
|
halign={Gtk.Align.END}
|
|
label={setTime(notifObj.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.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 ReturnType<typeof NotifGestureWrapper>;
|
|
};
|