feat(agsV2): make popups disappear after time
All checks were successful
Discord / discord commits (push) Has been skipped

This commit is contained in:
matt1432 2024-10-16 12:04:15 -04:00
parent 2ee60de237
commit 8ee3530330
5 changed files with 134 additions and 6 deletions

View file

@ -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 = (
<box
className="background"
hexpand
vexpand
halign={Gtk.Align.FILL}
valign={Gtk.Align.FILL}
/>
);
const progress = (
<box
className="progress"
vexpand
valign={Gtk.Align.FILL}
css={bind(this, 'fraction').as((fraction) => {
return `
transition: margin-right ${this.transition_duration} linear;
margin-right: ${
Math.abs(fraction - 1) * background.get_allocated_width()
}px;
`;
})}
/>
);
this.add((
<overlay overlay={progress}>
{background}
</overlay>
));
this.show_all();
}
}
export default (props?: SmoothProgressProps) => new SmoothProgress(props);

View file

@ -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(

View file

@ -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<typeof NotifGestureWrapper> | 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 (
<NotifGestureWrapper id={id}>
<NotifGestureWrapper
id={id}
popup_timer={popup_timer}
setup_notif={(self) => {
self.connect('notify::popup-timer', () => {
progress.fraction = self.popup_timer / 5;
});
}}
>
<box vertical className={`notification ${notifObj.urgency} widget`}>
{/* Content */}
<box>
@ -165,6 +179,8 @@ export const Notification = ({
</box>
</box>
{progress}
{/* Actions */}
<box className="actions">
{notifObj.get_actions().map((action) => (

View file

@ -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

View file

@ -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;
}
}
}