From 8ee353033086c5f4472db487a8e6828f19883107 Mon Sep 17 00:00:00 2001 From: matt1432 Date: Wed, 16 Oct 2024 12:04:15 -0400 Subject: [PATCH] feat(agsV2): make popups disappear after time --- .../ags/v2/widgets/misc/smooth-progress.tsx | 60 +++++++++++++++++++ .../ags/v2/widgets/notifs/gesture.tsx | 43 ++++++++++++- .../ags/v2/widgets/notifs/notification.tsx | 20 ++++++- nixosModules/ags/v2/widgets/notifs/popups.tsx | 2 +- nixosModules/ags/v2/widgets/notifs/style.scss | 15 +++++ 5 files changed, 134 insertions(+), 6 deletions(-) create mode 100644 nixosModules/ags/v2/widgets/misc/smooth-progress.tsx diff --git a/nixosModules/ags/v2/widgets/misc/smooth-progress.tsx b/nixosModules/ags/v2/widgets/misc/smooth-progress.tsx new file mode 100644 index 00000000..13821043 --- /dev/null +++ b/nixosModules/ags/v2/widgets/misc/smooth-progress.tsx @@ -0,0 +1,60 @@ +import { bind } from 'astal'; +import { Gtk, Widget } from 'astal/gtk3'; +import { register, property } from 'astal/gobject'; + +type SmoothProgressProps = Widget.BoxProps & { + transition_duration?: string +}; + + +@register() +class SmoothProgress extends Widget.Box { + @property(Number) + declare fraction: number; + + @property(String) + declare transition_duration: string; + + constructor({ + transition_duration = '1s', + ...rest + }: SmoothProgressProps = {}) { + super(rest); + this.transition_duration = transition_duration; + + const background = ( + + ); + + const progress = ( + { + return ` + transition: margin-right ${this.transition_duration} linear; + margin-right: ${ + Math.abs(fraction - 1) * background.get_allocated_width() + }px; + `; + })} + /> + ); + + this.add(( + + {background} + + )); + this.show_all(); + } +} + +export default (props?: SmoothProgressProps) => new SmoothProgress(props); diff --git a/nixosModules/ags/v2/widgets/notifs/gesture.tsx b/nixosModules/ags/v2/widgets/notifs/gesture.tsx index 89c4691e..bec34a90 100644 --- a/nixosModules/ags/v2/widgets/notifs/gesture.tsx +++ b/nixosModules/ags/v2/widgets/notifs/gesture.tsx @@ -1,6 +1,8 @@ import { Gdk, Gtk, Widget } from 'astal/gtk3'; import { register, property } from 'astal/gobject'; -import { idle } from 'astal'; +import { idle, interval } from 'astal'; + +import AstalIO from 'gi://AstalIO?version=0.1'; import AstalNotifd from 'gi://AstalNotifd?version=0.1'; const Notifications = AstalNotifd.get_default(); @@ -61,6 +63,8 @@ const defaultStyle = `${TRANSITION} margin: unset; opacity: 1;`; type NotifGestureWrapperProps = Widget.BoxProps & { id: number slide_in_from?: 'Left' | 'Right' + popup_timer?: number + setup_notif?: (self: NotifGestureWrapper) => void }; @register() @@ -71,6 +75,11 @@ export class NotifGestureWrapper extends Widget.EventBox { readonly slide_in_from: 'Left' | 'Right'; + private timer_object: AstalIO.Time | undefined; + + @property(Number) + declare popup_timer: number; + @property(Boolean) declare dragging: boolean; @@ -125,11 +134,19 @@ export class NotifGestureWrapper extends Widget.EventBox { (this.get_child() as Widget.Revealer).revealChild = false; setTimeout(() => { - // Kill notif and update HasNotifs after anim is done + // Kill notif if specified if (force) { Notifications.get_notification(this.id)?.dismiss(); } + + // Make sure we cleanup any references to this instance + this.timer_object?.cancel(); + NotifGestureWrapper.popups.delete(this.id); + + // Update HasNotifs HasNotifs.set(Notifications.get_notifications().length > 0); + + // Get rid of disappeared widget this.destroy(); }, ANIM_DURATION); }, ANIM_DURATION - 100); @@ -138,12 +155,18 @@ export class NotifGestureWrapper extends Widget.EventBox { constructor({ id, slide_in_from = 'Left', + popup_timer = 0, + setup_notif = () => { /**/ }, ...rest }: NotifGestureWrapperProps) { super(); + + setup_notif(this); + this.id = id; - this.dragging = false; this.slide_in_from = slide_in_from; + this.popup_timer = popup_timer; + this.dragging = false; // OnClick this.connect('button-press-event', () => { @@ -189,6 +212,20 @@ export class NotifGestureWrapper extends Widget.EventBox { )); }); + // Handle timeout before sliding away if it is a popup + if (this.popup_timer !== 0) { + this.timer_object = interval(1000, () => { + if (!this.hovered) { + if (this.popup_timer === 0) { + this.slideAway('Left'); + } + else { + this.popup_timer--; + } + } + }); + } + const gesture = Gtk.GestureDrag.new(this); this.add( diff --git a/nixosModules/ags/v2/widgets/notifs/notification.tsx b/nixosModules/ags/v2/widgets/notifs/notification.tsx index f39bc4c9..db964993 100644 --- a/nixosModules/ags/v2/widgets/notifs/notification.tsx +++ b/nixosModules/ags/v2/widgets/notifs/notification.tsx @@ -10,6 +10,7 @@ import AstalNotifd from 'gi://AstalNotifd?version=0.1'; const Notifications = AstalNotifd.get_default(); import NotifGestureWrapper from './gesture'; +import SmoothProgress from '../misc/smooth-progress'; // Make a variable to connect to for Widgets @@ -22,7 +23,9 @@ const setTime = (time: number): string => { .format('%H:%M') ?? ''; }; -const NotifIcon = ({ notifObj }: { notifObj: AstalNotifd.Notification }) => { +const NotifIcon = ({ notifObj }: { + notifObj: AstalNotifd.Notification +}) => { let icon: string; if (notifObj.get_image() !== '') { @@ -89,6 +92,7 @@ const BlockedApps = [ export const Notification = ({ id = 0, + popup_timer = 0, }): ReturnType | undefined => { const notifObj = Notifications.get_notification(id); @@ -104,8 +108,18 @@ export const Notification = ({ HasNotifs.set(Notifications.get_notifications().length > 0); + const progress = SmoothProgress({ className: 'smooth-progress' }); + return ( - + { + self.connect('notify::popup-timer', () => { + progress.fraction = self.popup_timer / 5; + }); + }} + > {/* Content */} @@ -165,6 +179,8 @@ export const Notification = ({ + {progress} + {/* Actions */} {notifObj.get_actions().map((action) => ( diff --git a/nixosModules/ags/v2/widgets/notifs/popups.tsx b/nixosModules/ags/v2/widgets/notifs/popups.tsx index 3134111e..ddd4433d 100644 --- a/nixosModules/ags/v2/widgets/notifs/popups.tsx +++ b/nixosModules/ags/v2/widgets/notifs/popups.tsx @@ -17,7 +17,7 @@ export default () => ( return; } - const NewNotif = Notification({ id }); + const NewNotif = Notification({ id, popup_timer: 5 }); if (NewNotif) { // Use this instead of add to put it at the top diff --git a/nixosModules/ags/v2/widgets/notifs/style.scss b/nixosModules/ags/v2/widgets/notifs/style.scss index c8d595be..0a8f88dc 100644 --- a/nixosModules/ags/v2/widgets/notifs/style.scss +++ b/nixosModules/ags/v2/widgets/notifs/style.scss @@ -29,4 +29,19 @@ .action-button {} } + + .smooth-progress { + min-height: 7px; + margin: 3px; + + .background { + background-color: darken($window_bg_color, 3%); + border-radius: 3px; + } + + .progress { + background-color: $accent-color; + border-radius: 3px; + } + } }