From 612dcc693f96ffcf7d0b8cd451c55ffed4c950c9 Mon Sep 17 00:00:00 2001 From: retrozinndev Date: Wed, 23 Jul 2025 20:51:02 -0300 Subject: [PATCH] :sparkles: feat(notifications): retrieve history from astal's notifd file in XDG_STATE_HOME --- ags/scripts/apps.ts | 9 ++++ ags/scripts/notifications.ts | 93 +++++++++++++++++++++++++----------- ags/scripts/stylesheet.ts | 30 +++++------- 3 files changed, 88 insertions(+), 44 deletions(-) diff --git a/ags/scripts/apps.ts b/ags/scripts/apps.ts index bde7719..971bac4 100644 --- a/ags/scripts/apps.ts +++ b/ags/scripts/apps.ts @@ -61,6 +61,15 @@ export function getIconByAppName(appName: string): (string|undefined) { return appName.toLowerCase(); const nameReverseDNS = appName.split('.'); + const lastItem = nameReverseDNS[nameReverseDNS.length - 1]; + const lastPretty = `${lastItem.charAt(0).toUpperCase()}${lastItem.substring(1, lastItem.length)}`; + + const uppercaseRDNS = nameReverseDNS.slice(0, nameReverseDNS.length - 1) + .concat(lastPretty).join('.'); + + if(lookupIcon(uppercaseRDNS)) + return uppercaseRDNS; + if(lookupIcon(nameReverseDNS[nameReverseDNS.length - 1])) return nameReverseDNS[nameReverseDNS.length - 1]; diff --git a/ags/scripts/notifications.ts b/ags/scripts/notifications.ts index 07d9f77..2a81ebd 100644 --- a/ags/scripts/notifications.ts +++ b/ags/scripts/notifications.ts @@ -4,8 +4,11 @@ import { execAsync } from "ags/process"; import GObject, { getter, property, register, signal } from "ags/gobject"; import AstalNotifd from "gi://AstalNotifd"; -import Gio from "gi://Gio?version=2.0"; import AstalIO from "gi://AstalIO"; +import { onCleanup } from "ags"; +import Gio from "gi://Gio?version=2.0"; +import GLib from "gi://GLib?version=2.0"; +import { readFile } from "ags/file"; export interface HistoryNotification { @@ -95,11 +98,12 @@ class Notifications extends GObject.Object { }) ); - this.run_dispose = () => { - super.run_dispose(); - this.#connections.map((id: number) => + this.retrieveHistoryFromFile(); + + onCleanup(() => { + this.#connections.map(id => AstalNotifd.get_default().disconnect(id)); - }; + }); } public static getDefault(): Notifications { @@ -109,23 +113,59 @@ class Notifications extends GObject.Object { return this.instance; } + private retrieveHistoryFromFile(): void { + const historyFile = Gio.File.new_for_path(`${GLib.get_user_state_dir()}/astal/notifd/notifications.json`); + if(!historyFile.query_exists(null)) return; + + let content: string; + console.log("Notifications: History file found! Trying to retrieve history from JSON"); + + try { + content = readFile(historyFile.get_path()!); + } catch(e: any) { + console.error(`Notifications: An error occurred while trying to read the history file. Stderr:\n${ + (e as Error).message}\n${(e as Error).stack}`); + + return; + } + + try { + const historyJSON = JSON.parse(content); + + (historyJSON["notifications"] as Array).reverse() + .forEach(n => this.addHistory(n)); + } catch(e: any) { + if(e instanceof SyntaxError) { + console.error(`Notifications: Couldn't parse history JSON because of a SyntaxError:\n${e.message + }\n${e.stack}`); + + return; + } + + console.error(`Notifications: An error occurred while parsing the history JSON file. Stderr:\n${ + e.message}\n${e.stack}`); + + return; + } + } + public async sendNotification(props: { - urgency?: AstalNotifd.Urgency; - appName?: string; - image?: string; - summary: string; - body?: string; - replaceId?: number; - actions?: Array<{ - id?: (string|number); - text: string; - onAction?: () => void - }> - }): Promise<{ - id?: (string|number); - text: string; - onAction?: () => void - }|null|void> { + urgency?: AstalNotifd.Urgency; + appName?: string; + image?: string; + summary: string; + body?: string; + replaceId?: number; + actions?: Array<{ + id?: (string|number); + text: string; + onAction?: () => void + }> + }): Promise<{ + id?: (string|number); + text: string; + onAction?: () => void + }|null|void> { return await execAsync([ "notify-send", @@ -155,7 +195,7 @@ class Notifications extends GObject.Object { return action ?? undefined; } - }).catch((err: Gio.IOErrorEnum) => { + }).catch((err: Error) => { console.error(`Notifications: Couldn't send notification! Is the daemon running? Stderr:\n${ err.message ? `${err.message}\n` : ""}Stack: ${err.stack}`); }); @@ -185,11 +225,11 @@ class Notifications extends GObject.Object { this.#history.unshift({ id: notif.id, - appName: notif.appName, + appName: notif.app_name, body: notif.body, summary: notif.summary, urgency: notif.urgency, - appIcon: notif.appIcon, + appIcon: notif.app_icon, time: notif.time, image: notif.image ? notif.image : undefined } as HistoryNotification); @@ -236,10 +276,9 @@ class Notifications extends GObject.Object { public removeNotification(notif: (AstalNotifd.Notification|number)): void { const notificationId = (notif instanceof AstalNotifd.Notification) ? notif.id : notif; - this.#notificationsOnHold.has(notificationId) && - this.#notificationsOnHold.delete(notificationId); + this.#notificationsOnHold.delete(notificationId); - this.#notifications = this.#notifications.filter((item: AstalNotifd.Notification) => + this.#notifications = this.#notifications.filter((item) => item.id !== notificationId); AstalNotifd.get_default().get_notification(notificationId)?.dismiss(); diff --git a/ags/scripts/stylesheet.ts b/ags/scripts/stylesheet.ts index fea0c09..d86b5cd 100644 --- a/ags/scripts/stylesheet.ts +++ b/ags/scripts/stylesheet.ts @@ -13,10 +13,7 @@ export class Stylesheet { private static instance: Stylesheet; #watchDelay: (AstalIO.Time|undefined); #outputPath = Gio.File.new_for_path(`${GLib.get_user_state_dir()}/ags/style`); - #styles = [ - "./style", - "./style.scss" - ]; + #styles = [ "./style", "./style.scss" ]; public async compileSass(): Promise { console.log("Stylesheet: Compiling Sass"); @@ -30,7 +27,7 @@ export class Stylesheet { const content = readFile(cssFilePath); - if(content) { + if(content?.trim()) { App.reset_css(); App.apply_css(content); @@ -43,10 +40,12 @@ export class Stylesheet { } public async compileApply(): Promise { - await this.compileSass().catch((err: Gio.IOErrorEnum) => - console.error(`Stylesheet: An Error occurred and Sass couldn't be compiled. Stderr:\n${err.message ? - `\t${err.message}\n` : ""}${err.stack}\n`) - ).then(() => this.reapply(this.#outputPath.get_path()! + "/style.css")); + await this.compileSass().then(() => + this.reapply(this.#outputPath.get_path()! + "/style.css") + ).catch((err: Error) => + console.error(`Stylesheet: An error occurred and Sass couldn't be compiled. Stderr:\n${ + err.message}\n${err.stack}`) + ); } public static getDefault(): Stylesheet { @@ -77,13 +76,10 @@ export class Stylesheet { ) ) - monitorFile( - `${GLib.get_user_cache_dir()}/wal/colors.scss`, - (file: string) => { - execAsync(`bash -c "cp -f ${file} ./style/_wal.scss"`).catch(r => { - console.error(`Stylesheet: Failed to copy pywal stylesheet to style dir. Stderr: ${r}`); - }); - } - ); + monitorFile(`${GLib.get_user_cache_dir()}/wal/colors.scss`, (file: string) => { + execAsync(`bash -c "cp -f ${file} ./style/_wal.scss"`).catch(r => { + console.error(`Stylesheet: Failed to copy pywal stylesheet to style dir. Stderr: ${r}`); + }); + }); } }