diff --git a/ags/widget/AskPopup.tsx b/ags/widget/AskPopup.tsx index bf92b87..0f2bb66 100644 --- a/ags/widget/AskPopup.tsx +++ b/ags/widget/AskPopup.tsx @@ -23,14 +23,9 @@ export type AskPopupProps = { export function AskPopup(props: AskPopupProps): Astal.Window { let accepted: boolean = false; - return !accepted && props.onCancel?.()} - options={[ + return !accepted && props.onCancel?.()} options={[ { text: props.cancelText ?? tr("cancel") }, { text: props.acceptText ?? tr("accept"), diff --git a/ags/widget/CustomDialog.tsx b/ags/widget/CustomDialog.tsx index 6afef16..784b0c8 100644 --- a/ags/widget/CustomDialog.tsx +++ b/ags/widget/CustomDialog.tsx @@ -4,7 +4,7 @@ import { PopupWindow } from "./PopupWindow"; import { Separator } from "./Separator"; import { tr } from "../i18n/intl"; import { Accessor, For, With } from "ags"; -import { variableToBoolean, WidgetNodeType } from "../scripts/utils"; +import { transformWidget, variableToBoolean, WidgetNodeType } from "../scripts/utils"; export type CustomDialogProps = { @@ -28,61 +28,58 @@ export interface CustomDialogOption { closeOnClick?: boolean | Accessor; } -function CustomDialogOption(props: CustomDialogOption & { dialog: Astal.Window }) { +function CustomDialogOption({closeOnClick = true, ...props}: CustomDialogOption & { dialog: Astal.Window }) { function onClicked() { props.onClick?.(); - props.closeOnClick && props.dialog.close(); + closeOnClick && + props.dialog?.close(); } - return } export function CustomDialog({ options = [{ text: tr("accept") }], ...props}: CustomDialogProps) { - let dialog: Astal.Window; - return Windows.getDefault().createWindowForFocusedMonitor((mon: number) => - + dialog = self}> - - - - - + onDestroy={props.onFinish} $={(self) => self.set_child( - { - (props.children instanceof Accessor) ? - (Array.isArray(props.children) ? - >}> - {(widget) => widget && widget} - - : }> - {(widget) => widget && widget} - ) - : (Array.isArray(props.children) ? - props.children.map(widget => widget && widget).filter(w => w) - : props.children) - } - - 0} - spacing={8} orientation={Gtk.Orientation.VERTICAL} /> + - {( - { - (options instanceof Accessor) ? - - {(option) => } - - : options.map(option => - ) - } - )} - - )(); + + + + { + (props.children instanceof Accessor) ? + (Array.isArray(props.children) ? + >}> + {(widget) => widget && widget} + + : }> + {(widget) => widget && widget} + ) + : (Array.isArray(props.children) ? + props.children.map(widget => widget && widget).filter(w => w) + : props.children) + } + + 0} + spacing={8} orientation={Gtk.Orientation.VERTICAL} /> + + + + {transformWidget(options, (props) => )} + + as Gtk.Box + )} + /> as Astal.Window + )(); } diff --git a/ags/widget/Notification.tsx b/ags/widget/Notification.tsx index 55e131e..33d5a04 100644 --- a/ags/widget/Notification.tsx +++ b/ags/widget/Notification.tsx @@ -2,11 +2,14 @@ import { Gdk, Gtk } from "ags/gtk4"; import { Separator } from "./Separator"; import { HistoryNotification, Notifications } from "../scripts/notifications"; import { getAppIcon, getSymbolicIcon } from "../scripts/apps"; +import { onCleanup } from "ags"; import AstalNotifd from "gi://AstalNotifd"; import Pango from "gi://Pango?version=1.0"; import GLib from "gi://GLib?version=2.0"; import GObject from "gi://GObject?version=2.0"; +import { escapeUnintendedMarkup, pathToURI } from "../scripts/utils"; + function getNotificationImage(notif: AstalNotifd.Notification|HistoryNotification): (string|undefined) { const img = notif.image || notif.appIcon; @@ -14,16 +17,7 @@ function getNotificationImage(notif: AstalNotifd.Notification|HistoryNotificatio if(!img || !img.includes('/')) return undefined; - switch(true) { - case /^[/]/.test(img): - return `file://${img}`; - - case /^[~]/.test(img): - case /^file:\/\/[~]/i.test(img): - return `file://${GLib.get_home_dir()}/${img.replace(/^(file\:\/\/|[~]|file\:\/\[~])/i, "")}`; - } - - return img; + return pathToURI(img); } export function NotificationWidget({ notification, actionClicked, holdOnHover, showTime, actionClose }: { @@ -40,6 +34,9 @@ export function NotificationWidget({ notification, actionClicked, holdOnHover, s const conns: Map> = new Map(); + onCleanup(() => + conns.forEach((ids, obj) => ids.forEach(id => obj.disconnect(id)))); + return holdOnHover && Notifications.getDefault().holdNotification(notification.id)), eventControllerMotion.connect("leave", () => - holdOnHover && Notifications.getDefault().removeNotification(notification.id)) + holdOnHover && notification && Notifications.getDefault().removeNotification(notification.id)) ]); conns.set(gestureClick, [ @@ -63,12 +60,10 @@ export function NotificationWidget({ notification, actionClicked, holdOnHover, s actionClicked?.(notification); }) ]); - }} onDestroy={(_) => { - conns.forEach((ids, obj) => ids.forEach(id => obj.disconnect(id))); }}> - { + { const icon = getSymbolicIcon(notification.appIcon ?? notification.appName) ?? getSymbolicIcon(notification.appName) ?? getAppIcon(notification.appName); @@ -86,32 +81,31 @@ export function NotificationWidget({ notification, actionClicked, holdOnHover, s label={GLib.DateTime.new_from_unix_local(notification.time).format("%H:%M") ?? ""} /> + class={"close"} onClicked={() => actionClose?.(notification)}/> - { - const image = getNotificationImage(notification); - - image && - self.prepend(Gtk.Picture.new_for_filename(image)); - }}> - + + {getNotificationImage(notification) && + + } - - - action.label.toLowerCase() !== "view").length > 0) }> diff --git a/ags/widget/bar/Clock.tsx b/ags/widget/bar/Clock.tsx index 2ad44ac..bec076d 100644 --- a/ags/widget/bar/Clock.tsx +++ b/ags/widget/bar/Clock.tsx @@ -6,7 +6,7 @@ import { Config } from "../../scripts/config"; export const Clock = () => - `clock ${Object.hasOwn(wins, "center-window") ? "open" : ""}`)} + `clock ${wins.includes("center-window") ? "open" : ""}`)} $={(self) => { const conns: Array = [ self.connect("clicked", (_) => Windows.getDefault().toggle("center-window")), diff --git a/ags/widget/runner/ResultWidget.tsx b/ags/widget/runner/ResultWidget.tsx deleted file mode 100644 index 045a9a3..0000000 --- a/ags/widget/runner/ResultWidget.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { Accessor, With } from "ags"; -import { register } from "ags/gobject"; -import { Gtk } from "ags/gtk4"; -import Pango from "gi://Pango?version=1.0"; -import { variableToBoolean } from "../../scripts/utils"; - -export { ResultWidget, ResultWidgetProps }; - -type ResultWidgetProps = { - icon?: string | Accessor | JSX.Element | Accessor; - title: string | Accessor; - description?: string | Accessor; - closeOnClick?: boolean; - setup?: () => void; - onClick?: () => void; -}; - -@register({ GTypeName: "ResultWidget" }) -class ResultWidget extends Gtk.Box { - - public readonly onClick: () => void; - public readonly setup?: () => void; - public icon?: (string | Accessor | JSX.Element | Accessor); - public closeOnClick: boolean = true; - - - constructor(props: ResultWidgetProps) { - super({ - cssClasses: ["result"], - hexpand: true - }); - - this.icon = props.icon; - this.setup = props.setup; - this.closeOnClick = props.closeOnClick ?? true; - this.onClick = () => props.onClick?.(); - - if(this.icon !== undefined) { - if(this.icon instanceof Accessor) { - if(typeof this.icon.get() === "string") { - this.prepend( - } /> as Gtk.Image); - } else { - this.prepend( - }> - {(widget) => widget} - - as Gtk.Box); - } - } else { - if(typeof this.icon === "string") - this.prepend( as Gtk.Image); - else - this.prepend(this.icon as Gtk.Widget); - } - } - - this.append( - - - - as Gtk.Box); - } -}