[AGS] GTK 4 Migration: Done, Start adding QuickActions
Probably gonna abandon the QuickActions, as that is just way too much effort for what it does. Will be providing keybinds for doing what I wanted to do there in Hyprland
This commit is contained in:
		| @@ -7,7 +7,7 @@ | ||||
| * | ||||
| */ | ||||
|  | ||||
| import { Astal, Gdk } from "astal/gtk4" | ||||
| import { App, Astal, Gdk } from "astal/gtk4" | ||||
| import Notifd from "gi://AstalNotifd"; | ||||
| import Notification from "./notifications"; | ||||
| import { timeout, Variable } from "astal" | ||||
| @@ -31,8 +31,7 @@ interface NotificationDetails { | ||||
| //          │                   Handler                     │ | ||||
| //          ╰───────────────────────────────────────────────╯ | ||||
| // ─────────────────────────────────────────────────────────────────── | ||||
| let ShownNotifications: number[] = []; | ||||
| const ShownNotificationsCount: Variable<number> = Variable( 0 ); | ||||
| let ShownNotifications: Variable<number[]> = Variable( [] ); | ||||
| let Notifications: NotificationDetails[] = []; | ||||
|  | ||||
| const notifd = Notifd.get_default(); | ||||
| @@ -46,6 +45,9 @@ notifd.ignoreTimeout = true; | ||||
| const deleteNotification = ( index: number ): void => { | ||||
|     hideNotification( index ); | ||||
|     Notifications.splice( index, 1 ); | ||||
|     if ( Notifications.length === 0 ) { | ||||
|         notificationMenuOpen = false; | ||||
|     } | ||||
| } | ||||
|  | ||||
| // ─────────────────────────────────────────────────────────────────── | ||||
| @@ -133,9 +135,9 @@ const hookToNotificationDaemon = (): void => { | ||||
|  */ | ||||
| const showNotification = ( id: number, removeAgain: boolean = true ) => { | ||||
|     // Add notification to UI for display | ||||
|     ShownNotifications.reverse().push( id ); | ||||
|     ShownNotifications.reverse(); | ||||
|     ShownNotificationsCount.set( ShownNotifications.length ); | ||||
|     const not = [...ShownNotifications.get()].reverse(); | ||||
|     not.push( id ); | ||||
|     ShownNotifications.set( not.reverse() ); | ||||
|  | ||||
|     // Set delay to remove the notification again | ||||
|     if ( removeAgain && Notifications[ id ].notification.get_urgency() !== Notifd.Urgency.CRITICAL ) { | ||||
| @@ -154,7 +156,9 @@ const showNotification = ( id: number, removeAgain: boolean = true ) => { | ||||
|  */ | ||||
| const hideNotification = ( id: number ) => { | ||||
|     if ( !notificationMenuOpen ) { | ||||
|         ShownNotifications.splice( ShownNotifications.indexOf( id ), 1 ); | ||||
|         const not = [...ShownNotifications.get()]; | ||||
|         not.splice( not.indexOf( id ), 1 ); | ||||
|         ShownNotifications.set( not ); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -167,10 +171,11 @@ const hideNotification = ( id: number ) => { | ||||
| const openNotificationMenu = () => { | ||||
|     // Simply show all notifications | ||||
|     notificationMenuOpen = true; | ||||
|     const ShownNotifications = []; | ||||
|     const not = []; | ||||
|     for (let index = 0; index < Notifications.length; index++) { | ||||
|         ShownNotifications.push( index ); | ||||
|         not.push( index ); | ||||
|     } | ||||
|     ShownNotifications.set( not.reverse() ); | ||||
| } | ||||
|  | ||||
| // ─────────────────────────────────────────────────────────────────── | ||||
| @@ -182,9 +187,7 @@ const openNotificationMenu = () => { | ||||
| const closeNotificationMenu = () => { | ||||
|     // Hide all notifications | ||||
|     notificationMenuOpen = true; | ||||
|  | ||||
|     ShownNotifications = []; | ||||
|     ShownNotificationsCount.set( 0 ); | ||||
|     ShownNotifications.set( [] ); | ||||
| } | ||||
|  | ||||
| // ─────────────────────────────────────────────────────────────────── | ||||
| @@ -193,11 +196,13 @@ const closeNotificationMenu = () => { | ||||
| /** | ||||
|  * Toggle the notification menu (i.e. show all notifications) | ||||
|  */ | ||||
| const toggleNotificationMenu = () => { | ||||
| const toggleNotificationMenu = (): string => { | ||||
|     if ( notificationMenuOpen ) { | ||||
|         closeNotificationMenu(); | ||||
|         return 'Toggle notification menu closed'; | ||||
|     } else { | ||||
|         openNotificationMenu(); | ||||
|         return 'Toggled notification menu open'; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -209,8 +214,9 @@ const toggleNotificationMenu = () => { | ||||
|  */ | ||||
| const clearAllNotifications = () => { | ||||
|     Notifications = []; | ||||
|     ShownNotifications = []; | ||||
|     ShownNotificationsCount.set( 0 ); | ||||
|     ShownNotifications.set( [] ); | ||||
|     // TODO: Hiding for each individual deleteNotification | ||||
|     notificationMenuOpen = false; | ||||
| } | ||||
|  | ||||
| // ─────────────────────────────────────────────────────────────────── | ||||
| @@ -220,7 +226,9 @@ const clearAllNotifications = () => { | ||||
|  * Delete the newest notifications | ||||
|  */ | ||||
| const clearNewestNotifications = () => { | ||||
|     ShownNotifications.splice( 0, 1 ); | ||||
|     const not = [...ShownNotifications.get()]; | ||||
|     not.splice( 0, 1 ); | ||||
|     ShownNotifications.set( not ); | ||||
|  | ||||
|     Notifications.splice( Notifications.length - 1, 1 ); | ||||
| } | ||||
| @@ -236,16 +244,16 @@ const startNotificationHandler = (gdkmonitor: Gdk.Monitor) => { | ||||
|     const { TOP, RIGHT } = Astal.WindowAnchor | ||||
|  | ||||
|     hookToNotificationDaemon(); | ||||
|     const range = (n: number) => [...Array(n).keys()]; | ||||
|  | ||||
|     return <window | ||||
|         cssClasses={["NotificationHandler"]} | ||||
|         gdkmonitor={gdkmonitor} | ||||
|         exclusivity={Astal.Exclusivity.EXCLUSIVE} | ||||
|         anchor={TOP | RIGHT}> | ||||
|         <box vertical noImplicitDestroy> | ||||
|             {ShownNotificationsCount( n => range( n ).map( i => { | ||||
|                 print( 'Rendering' ); | ||||
|         anchor={TOP | RIGHT} | ||||
|         visible={ShownNotifications( list => list.length > 0 )} | ||||
|         application={App}> | ||||
|         <box vertical> | ||||
|             {ShownNotifications( list => list.map( i => { | ||||
|                 // i is index in ShownNotifications array | ||||
|                 return <Notification id={i} delete={deleteNotification} notification={Notifications[ i ].notification}></Notification> | ||||
|             } ) ) } | ||||
| @@ -267,8 +275,19 @@ const cliHandler = ( args: string[] ): string => { | ||||
|         clearNewestNotifications(); | ||||
|         return 'Cleared newest notification'; | ||||
|     } else if ( args[ 1 ] == 'toggle' ) { | ||||
|         toggleNotificationMenu(); | ||||
|         return 'Toggled notifications'; | ||||
|         return toggleNotificationMenu(); | ||||
|     } else if ( args[ 1 ] == 'list' ){ | ||||
|         if ( Notifications.length > 0 ) { | ||||
|             let list = 'Currently unviewed notifications: '; | ||||
|             for (let index = 0; index < Notifications.length; index++) { | ||||
|                 const element = Notifications[index]; | ||||
|                  | ||||
|                 list += `\n - (${element.notifdID}) ${element.notification.get_app_name()}: ${element.notification.get_summary()}`; | ||||
|             } | ||||
|             return list; | ||||
|         } else { | ||||
|             return 'No currently unviewed notifications' | ||||
|         } | ||||
|     } else { | ||||
|         return 'Unknown command!'; | ||||
|     } | ||||
|   | ||||
| @@ -14,22 +14,25 @@ window.NotificationHandler { | ||||
| } | ||||
|  | ||||
| box.Notification { | ||||
|     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); | ||||
|  | ||||
|     &:first-child>box { | ||||
|     &:first-child { | ||||
|         margin-top: 1rem; | ||||
|     } | ||||
|  | ||||
|     &:last-child>box { | ||||
|     &:last-child { | ||||
|         margin-bottom: 1rem; | ||||
|     } | ||||
|  | ||||
|     &.critical>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 { | ||||
|         border: 1pt solid gtkalpha($error, .4); | ||||
|  | ||||
|         .header { | ||||
|   | ||||
| @@ -24,9 +24,9 @@ const urgency = (n: Notifd.Notification) => { | ||||
| } | ||||
|  | ||||
| type Props = { | ||||
|     delete( id: number ): void | ||||
|     delete: ( id: number ) => void; | ||||
|     notification: Notifd.Notification | ||||
|     id: number | ||||
|     id: number, | ||||
| } | ||||
|  | ||||
| export default function Notification(props: Props) { | ||||
| @@ -34,54 +34,54 @@ export default function Notification(props: Props) { | ||||
|     const { START, CENTER, END } = Gtk.Align | ||||
|  | ||||
|     return <box vertical | ||||
|         cssClasses={['Notification', urgency(n)]}> | ||||
|         <box cssName="header"> | ||||
|         cssClasses={['Notification', `${urgency(n)}`]}> | ||||
|         <box cssClasses={["header"]}> | ||||
|             {(n.appIcon || n.desktopEntry) ? <Gtk.Image | ||||
|                 cssName="app-icon" | ||||
|                 cssClasses={["app-icon"]} | ||||
|                 visible={Boolean(n.appIcon || n.desktopEntry)} | ||||
|                 iconName={n.appIcon || n.desktopEntry} | ||||
|             /> : <Gtk.Image iconName={'window-close-symbolic'}></Gtk.Image>} | ||||
|             /> : <image iconName={'window-close-symbolic'}></image>} | ||||
|             <label | ||||
|                 cssName="app-name" | ||||
|                 cssClasses={["app-name"]} | ||||
|                 halign={START} | ||||
|                 // ellipsize={Pango.EllipsizeMode.END} | ||||
|                 label={n.appName || "Unknown"} | ||||
|             /> | ||||
|             <label | ||||
|                 cssName="time" | ||||
|                 cssClasses={["time"]} | ||||
|                 hexpand | ||||
|                 halign={END} | ||||
|                 label={time(n.time)} | ||||
|             /> | ||||
|             <button onClicked={() => del( id )}> | ||||
|                 <Gtk.Image iconName="window-close-symbolic" /> | ||||
|             <button onClicked={() => { del( id ) }}> | ||||
|                 <image iconName="window-close-symbolic" /> | ||||
|             </button> | ||||
|         </box> | ||||
|         <Gtk.Separator visible /> | ||||
|         <box cssName="content"> | ||||
|         <box cssClasses={["content"]}> | ||||
|             {n.image && fileExists(n.image) ? <box | ||||
|                 valign={START} | ||||
|                 cssName="image"> | ||||
|                 <Gtk.Image file={n.image}></Gtk.Image> | ||||
|                 cssClasses={["image"]}> | ||||
|                 <image file={n.image}></image> | ||||
|             </box> | ||||
|                 : <box></box>} | ||||
|             {n.image ? <box | ||||
|                 expand={false} | ||||
|                 valign={START} | ||||
|                 className="icon-image"> | ||||
|                 <Gtk.Image iconName={n.image} expand halign={CENTER} valign={CENTER} /> | ||||
|                 cssClasses={["icon-image"]}> | ||||
|                 <image iconName={n.image} expand halign={CENTER} valign={CENTER} /> | ||||
|             </box> | ||||
|                 : <box></box>} | ||||
|             <box vertical> | ||||
|                 <Gtk.Label | ||||
|                     cssName="summary" | ||||
|                 <label | ||||
|                     cssClasses={["summary"]} | ||||
|                     halign={START} | ||||
|                     xalign={0} | ||||
|                     label={n.summary} | ||||
|                     // ellipsize={Pango.EllipsizeMode.END} | ||||
|                 /> | ||||
|                 {n.body ? <label | ||||
|                     cssName="body" | ||||
|                     cssClasses={["body"]} | ||||
|                     wrap | ||||
|                     useMarkup | ||||
|                     halign={START} | ||||
| @@ -90,7 +90,7 @@ export default function Notification(props: Props) { | ||||
|                 /> : <label></label>} | ||||
|             </box> | ||||
|         </box> | ||||
|         {n.get_actions().length > 0 ? <box cssName="actions"> | ||||
|         {n.get_actions().length > 0 ? <box cssClasses={["actions"]}> | ||||
|             {n.get_actions().map(({ label, id }) => ( | ||||
|                 <button | ||||
|                     hexpand | ||||
|   | ||||
		Reference in New Issue
	
	Block a user