diff options
Diffstat (limited to 'examples/js/notifications')
-rw-r--r-- | examples/js/notifications/README.md | 5 | ||||
-rw-r--r-- | examples/js/notifications/app.ts | 9 | ||||
-rw-r--r-- | examples/js/notifications/notifications/Notification.scss | 125 | ||||
-rw-r--r-- | examples/js/notifications/notifications/Notification.tsx | 107 | ||||
-rw-r--r-- | examples/js/notifications/notifications/NotificationPopups.tsx | 105 | ||||
-rw-r--r-- | examples/js/notifications/style.scss | 1 |
6 files changed, 0 insertions, 352 deletions
diff --git a/examples/js/notifications/README.md b/examples/js/notifications/README.md deleted file mode 100644 index 60dad60..0000000 --- a/examples/js/notifications/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Notifications Popups - - - -A replacement for dunst and other daemons using [Notifd](https://aylur.github.io/astal/guide/libraries/notifd). diff --git a/examples/js/notifications/app.ts b/examples/js/notifications/app.ts deleted file mode 100644 index ed53292..0000000 --- a/examples/js/notifications/app.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { App } from "astal/gtk3" -import style from "./style.scss" -import NotificationPopups from "./notifications/NotificationPopups" - -App.start({ - instanceName: "notifications", - css: style, - main: () => App.get_monitors().map(NotificationPopups), -}) diff --git a/examples/js/notifications/notifications/Notification.scss b/examples/js/notifications/notifications/Notification.scss deleted file mode 100644 index a32f08b..0000000 --- a/examples/js/notifications/notifications/Notification.scss +++ /dev/null @@ -1,125 +0,0 @@ -@use "sass:string"; - -@function gtkalpha($c, $a) { - @return string.unquote("alpha(#{$c},#{$a})"); -} - -// https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gtk/theme/Adwaita/_colors-public.scss -$fg-color: #{"@theme_fg_color"}; -$bg-color: #{"@theme_bg_color"}; -$error: red; - -window.NotificationPopups { - all: unset; -} - -eventbox.Notification { - - &:first-child>box { - margin-top: 1rem; - } - - &:last-child>box { - margin-bottom: 1rem; - } - - // eventboxes can not take margins so we style its inner box instead - >box { - min-width: 400px; - border-radius: 13px; - background-color: $bg-color; - margin: .5rem 1rem .5rem 1rem; - box-shadow: 2px 3px 8px 0 gtkalpha(black, .4); - border: 1pt solid gtkalpha($fg-color, .03); - } - - &.critical>box { - border: 1pt solid gtkalpha($error, .4); - - .header { - - .app-name { - color: gtkalpha($error, .8); - - } - - .app-icon { - color: gtkalpha($error, .6); - } - } - } - - .header { - padding: .5rem; - color: gtkalpha($fg-color, 0.5); - - .app-icon { - margin: 0 .4rem; - } - - .app-name { - margin-right: .3rem; - font-weight: bold; - - &:first-child { - margin-left: .4rem; - } - } - - .time { - margin: 0 .4rem; - } - - button { - padding: .2rem; - min-width: 0; - min-height: 0; - } - } - - separator { - margin: 0 .4rem; - background-color: gtkalpha($fg-color, .1); - } - - .content { - margin: 1rem; - margin-top: .5rem; - - .summary { - font-size: 1.2em; - color: $fg-color; - } - - .body { - color: gtkalpha($fg-color, 0.8); - } - - .image { - border: 1px solid gtkalpha($fg-color, .02); - margin-right: .5rem; - border-radius: 9px; - min-width: 100px; - min-height: 100px; - background-size: cover; - background-position: center; - } - } - - .actions { - margin: 1rem; - margin-top: 0; - - button { - margin: 0 .3rem; - - &:first-child { - margin-left: 0; - } - - &:last-child { - margin-right: 0; - } - } - } -} diff --git a/examples/js/notifications/notifications/Notification.tsx b/examples/js/notifications/notifications/Notification.tsx deleted file mode 100644 index 5149d5b..0000000 --- a/examples/js/notifications/notifications/Notification.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import { GLib } from "astal" -import { Gtk, Astal } from "astal/gtk3" -import { type EventBox } from "astal/gtk3/widget" -import Notifd from "gi://AstalNotifd" - -const isIcon = (icon: string) => - !!Astal.Icon.lookup_icon(icon) - -const fileExists = (path: string) => - GLib.file_test(path, GLib.FileTest.EXISTS) - -const time = (time: number, format = "%H:%M") => GLib.DateTime - .new_from_unix_local(time) - .format(format)! - -const urgency = (n: Notifd.Notification) => { - const { LOW, NORMAL, CRITICAL } = Notifd.Urgency - // match operator when? - switch (n.urgency) { - case LOW: return "low" - case CRITICAL: return "critical" - case NORMAL: - default: return "normal" - } -} - -type Props = { - setup(self: EventBox): void - onHoverLost(self: EventBox): void - notification: Notifd.Notification -} - -export default function Notification(props: Props) { - const { notification: n, onHoverLost, setup } = props - const { START, CENTER, END } = Gtk.Align - - return <eventbox - className={`Notification ${urgency(n)}`} - setup={setup} - onHoverLost={onHoverLost}> - <box vertical> - <box className="header"> - {(n.appIcon || n.desktopEntry) && <icon - className="app-icon" - visible={Boolean(n.appIcon || n.desktopEntry)} - icon={n.appIcon || n.desktopEntry} - />} - <label - className="app-name" - halign={START} - truncate - label={n.appName || "Unknown"} - /> - <label - className="time" - hexpand - halign={END} - label={time(n.time)} - /> - <button onClicked={() => n.dismiss()}> - <icon icon="window-close-symbolic" /> - </button> - </box> - <Gtk.Separator visible /> - <box className="content"> - {n.image && fileExists(n.image) && <box - valign={START} - className="image" - css={`background-image: url('${n.image}')`} - />} - {n.image && isIcon(n.image) && <box - expand={false} - valign={START} - className="icon-image"> - <icon icon={n.image} expand halign={CENTER} valign={CENTER} /> - </box>} - <box vertical> - <label - className="summary" - halign={START} - xalign={0} - label={n.summary} - truncate - /> - {n.body && <label - className="body" - wrap - useMarkup - halign={START} - xalign={0} - justifyFill - label={n.body} - />} - </box> - </box> - {n.get_actions().length > 0 && <box className="actions"> - {n.get_actions().map(({ label, id }) => ( - <button - hexpand - onClicked={() => n.invoke(id)}> - <label label={label} halign={CENTER} hexpand /> - </button> - ))} - </box>} - </box> - </eventbox> -} diff --git a/examples/js/notifications/notifications/NotificationPopups.tsx b/examples/js/notifications/notifications/NotificationPopups.tsx deleted file mode 100644 index 13fdd88..0000000 --- a/examples/js/notifications/notifications/NotificationPopups.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { Astal, Gtk, Gdk } from "astal/gtk3" -import Notifd from "gi://AstalNotifd" -import Notification from "./Notification" -import { type Subscribable } from "astal/binding" -import { Variable, bind, timeout } from "astal" - -// see comment below in constructor -const TIMEOUT_DELAY = 5000 - -// The purpose if this class is to replace Variable<Array<Widget>> -// with a Map<number, Widget> type in order to track notification widgets -// by their id, while making it conviniently bindable as an array -class NotifiationMap implements Subscribable { - // the underlying map to keep track of id widget pairs - private map: Map<number, Gtk.Widget> = new Map() - - // it makes sense to use a Variable under the hood and use its - // reactivity implementation instead of keeping track of subscribers ourselves - private var: Variable<Array<Gtk.Widget>> = Variable([]) - - // notify subscribers to rerender when state changes - private notifiy() { - this.var.set([...this.map.values()].reverse()) - } - - constructor() { - const notifd = Notifd.get_default() - - /** - * uncomment this if you want to - * ignore timeout by senders and enforce our own timeout - * note that if the notification has any actions - * they might not work, since the sender already treats them as resolved - */ - // notifd.ignoreTimeout = true - - notifd.connect("notified", (_, id) => { - this.set(id, Notification({ - notification: notifd.get_notification(id)!, - - // once hovering over the notification is done - // destroy the widget without calling notification.dismiss() - // so that it acts as a "popup" and we can still display it - // in a notification center like widget - // but clicking on the close button will close it - onHoverLost: () => this.delete(id), - - // notifd by default does not close notifications - // until user input or the timeout specified by sender - // which we set to ignore above - setup: () => timeout(TIMEOUT_DELAY, () => { - /** - * uncomment this if you want to "hide" the notifications - * after TIMEOUT_DELAY - */ - // this.delete(id) - }) - })) - }) - - // notifications can be closed by the outside before - // any user input, which have to be handled too - notifd.connect("resolved", (_, id) => { - this.delete(id) - }) - } - - private set(key: number, value: Gtk.Widget) { - // in case of replacecment destroy previous widget - this.map.get(key)?.destroy() - this.map.set(key, value) - this.notifiy() - } - - private delete(key: number) { - this.map.get(key)?.destroy() - this.map.delete(key) - this.notifiy() - } - - // needed by the Subscribable interface - get() { - return this.var.get() - } - - // needed by the Subscribable interface - subscribe(callback: (list: Array<Gtk.Widget>) => void) { - return this.var.subscribe(callback) - } -} - -export default function NotificationPopups(gdkmonitor: Gdk.Monitor) { - const { TOP, RIGHT } = Astal.WindowAnchor - const notifs = new NotifiationMap() - - return <window - className="NotificationPopups" - gdkmonitor={gdkmonitor} - exclusivity={Astal.Exclusivity.EXCLUSIVE} - anchor={TOP | RIGHT}> - <box vertical noImplicitDestroy> - {bind(notifs)} - </box> - </window> -} diff --git a/examples/js/notifications/style.scss b/examples/js/notifications/style.scss deleted file mode 100644 index 7ef0168..0000000 --- a/examples/js/notifications/style.scss +++ /dev/null @@ -1 +0,0 @@ -@use "./notifications/Notification.scss"; |