feat(agsV2): make popups disappear after time
All checks were successful
Discord / discord commits (push) Has been skipped
All checks were successful
Discord / discord commits (push) Has been skipped
This commit is contained in:
parent
2ee60de237
commit
8ee3530330
5 changed files with 134 additions and 6 deletions
60
nixosModules/ags/v2/widgets/misc/smooth-progress.tsx
Normal file
60
nixosModules/ags/v2/widgets/misc/smooth-progress.tsx
Normal 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);
|
|
@ -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(
|
||||
|
|
|
@ -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) => (
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue