From 54a62679574db230fd72a5c7819d5f7715cf17c0 Mon Sep 17 00:00:00 2001
From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>
Date: Sun, 12 Jan 2025 23:00:18 +1100
Subject: notification popups
---
modules/notifpopups.tsx | 163 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 163 insertions(+)
create mode 100644 modules/notifpopups.tsx
(limited to 'modules/notifpopups.tsx')
diff --git a/modules/notifpopups.tsx b/modules/notifpopups.tsx
new file mode 100644
index 0000000..a9a898c
--- /dev/null
+++ b/modules/notifpopups.tsx
@@ -0,0 +1,163 @@
+import { GLib, register, timeout } from "astal";
+import { Astal, Gtk, Widget } from "astal/gtk3";
+import AstalNotifd from "gi://AstalNotifd";
+
+const urgencyToString = (urgency: AstalNotifd.Urgency) => {
+ switch (urgency) {
+ case AstalNotifd.Urgency.LOW:
+ return "low";
+ case AstalNotifd.Urgency.NORMAL:
+ return "normal";
+ case AstalNotifd.Urgency.CRITICAL:
+ return "critical";
+ }
+};
+
+const getTime = (time: number) => {
+ const messageTime = GLib.DateTime.new_from_unix_local(time);
+ const todayDay = GLib.DateTime.new_now_local().get_day_of_year();
+ if (messageTime.get_day_of_year() === todayDay) {
+ const aMinuteAgo = GLib.DateTime.new_now_local().add_seconds(-60);
+ return aMinuteAgo !== null && messageTime.compare(aMinuteAgo) > 0 ? "Now" : messageTime.format("%H:%M");
+ } else if (messageTime.get_day_of_year() === todayDay - 1) return "Yesterday";
+ return messageTime.format("%d/%m");
+};
+
+const Icon = ({ icon }: { icon: string }) => {
+ if (GLib.file_test(icon, GLib.FileTest.EXISTS))
+ return (
+
+ );
+ if (Astal.Icon.lookup_icon(icon)) return ;
+ return null;
+};
+
+@register()
+class NotifPopup extends Widget.Box {
+ readonly #revealer;
+ #destroyed = false;
+
+ constructor({ notification }: { notification: AstalNotifd.Notification }) {
+ super();
+
+ this.#revealer = (
+
+
+
+
+ {(notification.appIcon || notification.desktopEntry) && (
+
+ )}
+
+
+
+
+
+ {notification.image && }
+
+
+
+
+
+
+
+
+
+
+ ) as Widget.Revealer;
+ this.add(this.#revealer);
+
+ // Init animation
+ const width = this.get_preferred_width()[1];
+ this.css = `margin-left: ${width}px; margin-right: -${width}px;`;
+ timeout(1, () => {
+ this.css = `transition: 150ms cubic-bezier(0.05, 0.9, 0.1, 1.1); margin-left: 0; margin-right: 0;`;
+ });
+
+ // Close popup after timeout
+ // timeout(
+ // notification.expireTimeout > 0
+ // ? notification.expireTimeout
+ // : notification.urgency === AstalNotifd.Urgency.CRITICAL
+ // ? 10000
+ // : 5000,
+ // () => this.destroyWithAnims()
+ // );
+ }
+
+ destroyWithAnims() {
+ if (this.#destroyed) return;
+ this.#destroyed = true;
+
+ const animTime = 120;
+ const animMargin = this.get_allocated_width();
+ this.css = `transition: ${animTime}ms cubic-bezier(0.85, 0, 0.15, 1);
+ margin-left: ${animMargin}px; margin-right: -${animMargin}px;`;
+ timeout(animTime, () => {
+ this.#revealer.revealChild = false;
+ timeout(this.#revealer.transitionDuration, () => this.destroy());
+ });
+ }
+}
+
+export default () => (
+
+ {
+ const notifd = AstalNotifd.get_default();
+ const map = new Map();
+ self.hook(notifd, "notified", (self, id) => {
+ const notification = notifd.get_notification(id);
+ const popup = () as NotifPopup;
+ map.set(notification.id, popup);
+ self.add(
+ event.button === Astal.MouseButton.MIDDLE && notification.dismiss()}
+ // Close on hover lost
+ onHoverLost={() => popup.destroyWithAnims()}
+ >
+ {popup}
+
+ );
+ });
+ self.hook(notifd, "resolved", (_, id) => {
+ const popup = map.get(id);
+ if (popup) {
+ popup.destroyWithAnims();
+ map.delete(id);
+ }
+ });
+
+ // Change input region to child region so can click through empty space
+ self.connect("size-allocate", () => self.get_window()?.set_child_input_shapes());
+ }}
+ />
+
+);
--
cgit v1.2.3-freya