[AGS] Bar: BT, Audio, SysInfo, Brightness
This commit is contained in:
@@ -91,7 +91,6 @@ const findNotificationByNotificationID = ( id: number ): number => {
|
||||
* @param id The notifd ID of the notification
|
||||
*/
|
||||
const addNotification = ( id: number ): void => {
|
||||
print( '[ Notifications ] Notification with id ' + id + ' added.' );
|
||||
const currIndex = Notifications.length;
|
||||
Notifications.push( {
|
||||
notifdID: id,
|
||||
|
12
config/astal/components/notifications/helper.ts
Normal file
12
config/astal/components/notifications/helper.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Gtk, Gdk } from "astal/gtk4";
|
||||
import { GLib } from "astal";
|
||||
|
||||
export const isIcon = (icon: string) => {
|
||||
const display = Gdk.Display.get_default();
|
||||
if (!display) return false;
|
||||
const iconTheme = Gtk.IconTheme.get_for_display(display);
|
||||
return iconTheme.has_icon(icon);
|
||||
};
|
||||
|
||||
export const fileExists = (path: string) =>
|
||||
GLib.file_test(path, GLib.FileTest.EXISTS);
|
24
config/astal/components/notifications/icon.tsx
Normal file
24
config/astal/components/notifications/icon.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Gtk } from "astal/gtk4";
|
||||
import Notifd from "gi://AstalNotifd";
|
||||
import { fileExists, isIcon } from "./helper";
|
||||
|
||||
|
||||
export function NotificationIcon(notification: Notifd.Notification) {
|
||||
if ( notification.image || notification.appIcon || notification.desktopEntry) {
|
||||
const icon = notification.image || notification.appIcon || notification.desktopEntry;
|
||||
if (fileExists(icon)) {
|
||||
return (
|
||||
<box expand={false} valign={Gtk.Align.CENTER}>
|
||||
<image file={icon} />
|
||||
</box>
|
||||
);
|
||||
} else if (isIcon(icon)) {
|
||||
return (
|
||||
<box expand={false} valign={Gtk.Align.CENTER}>
|
||||
<image iconName={icon} />
|
||||
</box>
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
@@ -13,7 +13,7 @@ window.NotificationHandler {
|
||||
all: unset;
|
||||
}
|
||||
|
||||
box.Notification {
|
||||
box.notification {
|
||||
|
||||
&:first-child {
|
||||
margin-top: 1rem;
|
||||
|
@@ -1,103 +1,113 @@
|
||||
// From astal examples
|
||||
// From astal examples
|
||||
|
||||
import { GLib } from "astal"
|
||||
import { Gtk } from "astal/gtk4"
|
||||
import Notifd from "gi://AstalNotifd"
|
||||
import { bind, GLib } from "astal";
|
||||
import { Gtk } from "astal/gtk4";
|
||||
import Notifd from "gi://AstalNotifd";
|
||||
import { NotificationIcon } from "./icon";
|
||||
// import Pango from "gi://Pango?version=1.0"
|
||||
|
||||
const fileExists = (path: string) =>
|
||||
GLib.file_test(path, GLib.FileTest.EXISTS)
|
||||
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 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
|
||||
const { LOW, NORMAL, CRITICAL } = Notifd.Urgency;
|
||||
// match operator when?
|
||||
switch (n.urgency) {
|
||||
case LOW: return "low"
|
||||
case CRITICAL: return "critical"
|
||||
case LOW:
|
||||
return "low";
|
||||
case CRITICAL:
|
||||
return "critical";
|
||||
case NORMAL:
|
||||
default: return "normal"
|
||||
default:
|
||||
return "normal";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
type Props = {
|
||||
delete: ( id: number ) => void;
|
||||
notification: Notifd.Notification
|
||||
id: number,
|
||||
}
|
||||
delete: (id: number) => void;
|
||||
notification: Notifd.Notification;
|
||||
id: number;
|
||||
};
|
||||
|
||||
export default function Notification(props: Props) {
|
||||
const { notification: n, id: id, delete: del } = props
|
||||
const { START, CENTER, END } = Gtk.Align
|
||||
const { notification: n, id: id, delete: del } = props;
|
||||
const { START, CENTER, END } = Gtk.Align;
|
||||
|
||||
return <box vertical
|
||||
cssClasses={['Notification', `${urgency(n)}`]}>
|
||||
<box cssClasses={["header"]}>
|
||||
{(n.appIcon || n.desktopEntry) ? <Gtk.Image
|
||||
cssClasses={["app-icon"]}
|
||||
visible={Boolean(n.appIcon || n.desktopEntry)}
|
||||
iconName={n.appIcon || n.desktopEntry}
|
||||
/> : <image iconName={'window-close-symbolic'}></image>}
|
||||
<label
|
||||
cssClasses={["app-name"]}
|
||||
halign={START}
|
||||
// ellipsize={Pango.EllipsizeMode.END}
|
||||
label={n.appName || "Unknown"}
|
||||
/>
|
||||
<label
|
||||
cssClasses={["time"]}
|
||||
hexpand
|
||||
halign={END}
|
||||
label={time(n.time)}
|
||||
/>
|
||||
<button onClicked={() => { del( id ) }}>
|
||||
<image iconName="window-close-symbolic" />
|
||||
</button>
|
||||
</box>
|
||||
<Gtk.Separator visible />
|
||||
<box cssClasses={["content"]}>
|
||||
{n.image && fileExists(n.image) ? <box
|
||||
valign={START}
|
||||
cssClasses={["image"]}>
|
||||
<image file={n.image}></image>
|
||||
</box>
|
||||
: <box></box>}
|
||||
{n.image ? <box
|
||||
expand={false}
|
||||
valign={START}
|
||||
cssClasses={["icon-image"]}>
|
||||
<image iconName={n.image} expand halign={CENTER} valign={CENTER} />
|
||||
</box>
|
||||
: <box></box>}
|
||||
<box vertical>
|
||||
return (
|
||||
<box vertical cssClasses={["notification", `${urgency(n)}`]}>
|
||||
<box cssClasses={["header"]}>
|
||||
{n.appIcon || n.desktopEntry ? (
|
||||
<Gtk.Image
|
||||
cssClasses={["app-icon"]}
|
||||
visible={Boolean(n.appIcon || n.desktopEntry)}
|
||||
iconName={n.appIcon || n.desktopEntry}
|
||||
/>
|
||||
) : (
|
||||
<image iconName={"window-close-symbolic"}></image>
|
||||
)}
|
||||
<label
|
||||
cssClasses={["summary"]}
|
||||
cssClasses={["app-name"]}
|
||||
halign={START}
|
||||
xalign={0}
|
||||
label={n.summary}
|
||||
// ellipsize={Pango.EllipsizeMode.END}
|
||||
label={n.appName || "Unknown"}
|
||||
/>
|
||||
{n.body ? <label
|
||||
cssClasses={["body"]}
|
||||
wrap
|
||||
useMarkup
|
||||
halign={START}
|
||||
xalign={0}
|
||||
label={n.body}
|
||||
/> : <label></label>}
|
||||
</box>
|
||||
</box>
|
||||
{n.get_actions().length > 0 ? <box cssClasses={["actions"]}>
|
||||
{n.get_actions().map(({ label, id }) => (
|
||||
<button
|
||||
<label
|
||||
cssClasses={["time"]}
|
||||
hexpand
|
||||
onClicked={() => n.invoke(id)}>
|
||||
<label label={label} halign={CENTER} hexpand />
|
||||
</button>
|
||||
))}
|
||||
</box> : <box></box>}
|
||||
</box>
|
||||
halign={END}
|
||||
label={time(n.time)}
|
||||
/>
|
||||
<button
|
||||
onClicked={() => {
|
||||
del(id);
|
||||
}}
|
||||
child={<image iconName="window-close-symbolic" />}
|
||||
></button>
|
||||
</box>
|
||||
<Gtk.Separator visible />
|
||||
<box cssClasses={["content"]}>
|
||||
<box
|
||||
cssClasses={["image"]}
|
||||
visible={Boolean(NotificationIcon(n))}
|
||||
halign={CENTER}
|
||||
valign={CENTER}
|
||||
vexpand={true}
|
||||
>
|
||||
{NotificationIcon(n)}
|
||||
</box>
|
||||
<box vertical>
|
||||
<label
|
||||
cssClasses={["summary"]}
|
||||
halign={START}
|
||||
xalign={0}
|
||||
useMarkup
|
||||
label={bind(n, "summary")}
|
||||
// ellipsize={Pango.EllipsizeMode.END}
|
||||
/>
|
||||
{n.body && (
|
||||
<label
|
||||
cssClasses={["body"]}
|
||||
valign={CENTER}
|
||||
wrap={true}
|
||||
maxWidthChars={50}
|
||||
label={bind(n, "body")}
|
||||
/>
|
||||
)}
|
||||
</box>
|
||||
</box>
|
||||
{n.get_actions().length > 0 ? (
|
||||
<box cssClasses={["actions"]}>
|
||||
{n.get_actions().map(({ label, id }) => (
|
||||
<button hexpand onClicked={() => n.invoke(id)}>
|
||||
<label label={label} halign={CENTER} hexpand />
|
||||
</button>
|
||||
))}
|
||||
</box>
|
||||
) : (
|
||||
<box></box>
|
||||
)}
|
||||
</box>
|
||||
);
|
||||
}
|
||||
|
Reference in New Issue
Block a user