refactor(ags): typecheck notif logic
This commit is contained in:
parent
f7ced94c21
commit
42a168762f
10 changed files with 236 additions and 149 deletions
|
@ -9,7 +9,10 @@ import { Box, Entry, Icon, Label, ListBox, Revealer, Scrollable } from 'resource
|
|||
import PopupWindow from '../misc/popup.js';
|
||||
import AppItem from './app-item.js';
|
||||
|
||||
/** @typedef {import('types/service/applications.js').Application} App */
|
||||
/**
|
||||
* @typedef {import('types/service/applications.js').Application} App
|
||||
* @typedef {typeof imports.gi.Gtk.ListBoxRow} ListBoxRow
|
||||
*/
|
||||
|
||||
|
||||
const Applauncher = ({ window_name = 'applauncher' } = {}) => {
|
||||
|
@ -32,17 +35,23 @@ const Applauncher = ({ window_name = 'applauncher' } = {}) => {
|
|||
|
||||
fzfResults = fzf.find(text);
|
||||
// @ts-expect-error
|
||||
list.set_sort_func((a, b) => {
|
||||
const row1 = a.get_children()[0]?.attribute.app.name;
|
||||
const row2 = b.get_children()[0]?.attribute.app.name;
|
||||
list.set_sort_func(
|
||||
/**
|
||||
* @param {ListBoxRow} a
|
||||
* @param {ListBoxRow} b
|
||||
*/
|
||||
(a, b) => {
|
||||
const row1 = a.get_children()[0]?.attribute.app.name;
|
||||
const row2 = b.get_children()[0]?.attribute.app.name;
|
||||
|
||||
if (!row1 || !row2) {
|
||||
return 0;
|
||||
}
|
||||
if (!row1 || !row2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return fzfResults.indexOf(row1) -
|
||||
return fzfResults.indexOf(row1) -
|
||||
fzfResults.indexOf(row1) || 0;
|
||||
});
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
const makeNewChildren = () => {
|
||||
|
@ -96,7 +105,7 @@ const Applauncher = ({ window_name = 'applauncher' } = {}) => {
|
|||
setSort(text);
|
||||
let visibleApps = 0;
|
||||
|
||||
/** @type Array<typeof imports.gi.Gtk.ListBoxRow> */
|
||||
/** @type Array<ListBoxRow> */
|
||||
// @ts-expect-error
|
||||
const rows = list.get_children();
|
||||
|
||||
|
|
|
@ -135,6 +135,7 @@ export default () => {
|
|||
const updateWorkspaces = () => {
|
||||
Hyprland.workspaces.forEach((ws) => {
|
||||
const currentWs = self.children.find((ch) => {
|
||||
// @ts-expect-error
|
||||
return ch.attribute.id === ws.id;
|
||||
});
|
||||
|
||||
|
|
|
@ -9,12 +9,13 @@ const ANIM_DURATION = 500;
|
|||
const TRANSITION = `transition: margin ${ANIM_DURATION}ms ease,
|
||||
opacity ${ANIM_DURATION}ms ease;`;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {import('types/widgets/overlay').OverlayProps} OverlayProps
|
||||
* @typedef {import('types/widgets/overlay').default} Overlay
|
||||
*
|
||||
* @param {OverlayProps & {
|
||||
*/
|
||||
|
||||
|
||||
/** @param {OverlayProps & {
|
||||
* setup?: function(Overlay):void
|
||||
* }} o
|
||||
*/
|
||||
|
|
|
@ -4,12 +4,13 @@ import { EventBox } from 'resource:///com/github/Aylur/ags/widget.js';
|
|||
|
||||
const { Gtk } = imports.gi;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {import('types/widgets/eventbox').EventBoxProps} EventBoxProps
|
||||
* @typedef {import('types/widgets/eventbox').default} EventBox
|
||||
*
|
||||
* @param {EventBoxProps & {
|
||||
*/
|
||||
|
||||
|
||||
/** @param {EventBoxProps & {
|
||||
* on_primary_click_release?: function(EventBox):void
|
||||
* }} o
|
||||
*/
|
||||
|
@ -23,7 +24,7 @@ export default ({
|
|||
const CanRun = Variable(true);
|
||||
const Disabled = Variable(false);
|
||||
|
||||
let widget; // eslint-disable-line
|
||||
let widget = EventBox();
|
||||
|
||||
const wrapper = EventBox({
|
||||
cursor: 'pointer',
|
||||
|
@ -35,7 +36,7 @@ export default ({
|
|||
|
||||
get_child: () => widget.child,
|
||||
|
||||
/** @param {import('types/widget').Widget} new_child */
|
||||
/** @param {import('types/widgets/box').default} new_child */
|
||||
set_child: (new_child) => {
|
||||
widget.child = new_child;
|
||||
},
|
||||
|
|
|
@ -23,8 +23,8 @@ import { timeout } from 'resource:///com/github/Aylur/ags/utils.js';
|
|||
export default ({
|
||||
transition = 'slide_down',
|
||||
transition_duration = 500,
|
||||
onOpen = () => { /**/ },
|
||||
onClose = () => { /**/ },
|
||||
onOpen = () => {/**/},
|
||||
onClose = () => {/**/},
|
||||
|
||||
// Window props
|
||||
name,
|
||||
|
@ -42,8 +42,12 @@ export default ({
|
|||
...props,
|
||||
|
||||
attribute: {
|
||||
/**
|
||||
* @param {typeof imports.gi.Gtk.Allocation} alloc
|
||||
* @param {'left'|'right'} side
|
||||
*/
|
||||
set_x_pos: (
|
||||
alloc = {},
|
||||
alloc,
|
||||
side = 'right',
|
||||
) => {
|
||||
const width = window.get_display()
|
||||
|
|
|
@ -8,28 +8,35 @@ import { lookUpIcon } from 'resource:///com/github/Aylur/ags/utils.js';
|
|||
|
||||
const { GLib } = imports.gi;
|
||||
|
||||
/** @typedef {import('types/service/notifications').Notification} Notification */
|
||||
|
||||
/** @param {number} time */
|
||||
const setTime = (time) => {
|
||||
return GLib.DateTime
|
||||
.new_from_unix_local(time)
|
||||
.format('%H:%M');
|
||||
};
|
||||
|
||||
const getDragState = (box) => box.get_parent().get_parent()
|
||||
.get_parent().get_parent().get_parent()._dragging;
|
||||
/** @param {import('types/widgets/eventbox').default} box */
|
||||
const getDragState = (box) => box.get_parent()?.get_parent()
|
||||
// @ts-expect-error
|
||||
?.get_parent()?.get_parent()?.get_parent()?.attribute.dragging;
|
||||
|
||||
import Gesture from './gesture.js';
|
||||
import CursorBox from '../misc/cursorbox.js';
|
||||
|
||||
|
||||
/** @param {Notification} notif */
|
||||
const NotificationIcon = (notif) => {
|
||||
let iconCmd = () => { /**/ };
|
||||
/** @type function(import('types/widgets/eventbox').default):void */
|
||||
let iconCmd = () => {/**/};
|
||||
|
||||
if (Applications.query(notif.appEntry).length > 0) {
|
||||
const app = Applications.query(notif.appEntry)[0];
|
||||
if (notif._appEntry && Applications.query(notif._appEntry).length > 0) {
|
||||
const app = Applications.query(notif._appEntry)[0];
|
||||
|
||||
let wmClass = app.app.get_string('StartupWMClass');
|
||||
|
||||
if (app.app.get_filename().includes('discord')) {
|
||||
if (app.app?.get_filename()?.includes('discord')) {
|
||||
wmClass = 'discord';
|
||||
}
|
||||
|
||||
|
@ -45,17 +52,19 @@ const NotificationIcon = (notif) => {
|
|||
'togglespecialworkspace spot');
|
||||
}
|
||||
else {
|
||||
Hyprland.sendMessage('j/clients').then((out) => {
|
||||
out = JSON.parse(out);
|
||||
Hyprland.sendMessage('j/clients').then((msg) => {
|
||||
/** @type {Array<import('types/service/hyprland').Client>} */
|
||||
const clients = JSON.parse(msg);
|
||||
|
||||
const classes = [];
|
||||
|
||||
for (const key of out) {
|
||||
for (const key of clients) {
|
||||
if (key.class) {
|
||||
classes.push(key.class);
|
||||
}
|
||||
}
|
||||
|
||||
if (classes.includes(wmClass)) {
|
||||
if (wmClass && classes.includes(wmClass)) {
|
||||
Hyprland.sendMessage('dispatch ' +
|
||||
`focuswindow ^(${wmClass})`);
|
||||
}
|
||||
|
@ -81,7 +90,7 @@ const NotificationIcon = (notif) => {
|
|||
child: Box({
|
||||
vpack: 'start',
|
||||
hexpand: false,
|
||||
className: 'icon img',
|
||||
class_name: 'icon img',
|
||||
css: `
|
||||
background-image: url("${notif.image}");
|
||||
background-size: contain;
|
||||
|
@ -96,13 +105,13 @@ const NotificationIcon = (notif) => {
|
|||
|
||||
let icon = 'dialog-information-symbolic';
|
||||
|
||||
if (lookUpIcon(notif.appIcon)) {
|
||||
icon = notif.appIcon;
|
||||
if (lookUpIcon(notif._appIcon)) {
|
||||
icon = notif._appIcon;
|
||||
}
|
||||
|
||||
|
||||
if (lookUpIcon(notif.appEntry)) {
|
||||
icon = notif.appEntry;
|
||||
if (notif._appEntry && lookUpIcon(notif._appEntry)) {
|
||||
icon = notif._appEntry;
|
||||
}
|
||||
|
||||
|
||||
|
@ -112,7 +121,7 @@ const NotificationIcon = (notif) => {
|
|||
child: Box({
|
||||
vpack: 'start',
|
||||
hexpand: false,
|
||||
className: 'icon',
|
||||
class_name: 'icon',
|
||||
css: `
|
||||
min-width: 78px;
|
||||
min-height: 78px;
|
||||
|
@ -132,11 +141,18 @@ const NotificationIcon = (notif) => {
|
|||
// to know when there are notifs or not
|
||||
export const HasNotifs = Variable(false);
|
||||
|
||||
/**
|
||||
* @param {{
|
||||
* notif: Notification
|
||||
* slideIn?: 'Left'|'Right'
|
||||
* command?: () => void
|
||||
* }} o
|
||||
*/
|
||||
export const Notification = ({
|
||||
notif,
|
||||
slideIn = 'Left',
|
||||
command = () => { /**/ },
|
||||
} = {}) => {
|
||||
}) => {
|
||||
if (!notif) {
|
||||
return;
|
||||
}
|
||||
|
@ -145,7 +161,7 @@ export const Notification = ({
|
|||
'Spotify',
|
||||
];
|
||||
|
||||
if (BlockedApps.find((app) => app === notif.appName)) {
|
||||
if (BlockedApps.find((app) => app === notif._appName)) {
|
||||
notif.close();
|
||||
|
||||
return;
|
||||
|
@ -161,8 +177,9 @@ export const Notification = ({
|
|||
});
|
||||
|
||||
// Add body to notif
|
||||
// @ts-expect-error
|
||||
notifWidget.child.add(Box({
|
||||
className: `notification ${notif.urgency}`,
|
||||
class_name: `notification ${notif.urgency}`,
|
||||
vexpand: false,
|
||||
|
||||
// Notification
|
||||
|
@ -174,6 +191,7 @@ export const Notification = ({
|
|||
Box({
|
||||
children: [
|
||||
NotificationIcon(notif),
|
||||
|
||||
Box({
|
||||
hexpand: true,
|
||||
vertical: true,
|
||||
|
@ -185,21 +203,21 @@ export const Notification = ({
|
|||
|
||||
// Title
|
||||
Label({
|
||||
className: 'title',
|
||||
class_name: 'title',
|
||||
xalign: 0,
|
||||
justification: 'left',
|
||||
hexpand: true,
|
||||
maxWidthChars: 24,
|
||||
max_width_chars: 24,
|
||||
truncate: 'end',
|
||||
wrap: true,
|
||||
label: notif.summary,
|
||||
useMarkup: notif.summary
|
||||
use_markup: notif.summary
|
||||
.startsWith('<'),
|
||||
}),
|
||||
|
||||
// Time
|
||||
Label({
|
||||
className: 'time',
|
||||
class_name: 'time',
|
||||
vpack: 'start',
|
||||
label: setTime(notif.time),
|
||||
}),
|
||||
|
@ -207,9 +225,12 @@ export const Notification = ({
|
|||
// Close button
|
||||
CursorBox({
|
||||
child: Button({
|
||||
className: 'close-button',
|
||||
class_name: 'close-button',
|
||||
vpack: 'start',
|
||||
onClicked: () => notif.close(),
|
||||
|
||||
on_primary_click_release: () =>
|
||||
notif.close(),
|
||||
|
||||
child: Icon('window-close' +
|
||||
'-symbolic'),
|
||||
}),
|
||||
|
@ -219,9 +240,9 @@ export const Notification = ({
|
|||
|
||||
// Description
|
||||
Label({
|
||||
className: 'description',
|
||||
class_name: 'description',
|
||||
hexpand: true,
|
||||
useMarkup: true,
|
||||
use_markup: true,
|
||||
xalign: 0,
|
||||
justification: 'left',
|
||||
label: notif.body,
|
||||
|
@ -234,11 +255,13 @@ export const Notification = ({
|
|||
|
||||
// Actions
|
||||
Box({
|
||||
className: 'actions',
|
||||
class_name: 'actions',
|
||||
children: notif.actions.map((action) => Button({
|
||||
className: 'action-button',
|
||||
onClicked: () => notif.invoke(action.id),
|
||||
class_name: 'action-button',
|
||||
hexpand: true,
|
||||
|
||||
on_primary_click_release: () => notif.invoke(action.id),
|
||||
|
||||
child: Label(action.label),
|
||||
})),
|
||||
}),
|
||||
|
|
|
@ -7,7 +7,16 @@ import { timeout } from 'resource:///com/github/Aylur/ags/utils.js';
|
|||
import { Notification, HasNotifs } from './base.js';
|
||||
import CursorBox from '../misc/cursorbox.js';
|
||||
|
||||
/**
|
||||
* @typedef {import('types/service/notifications').Notification} NotifObj
|
||||
* @typedef {import('types/widgets/box').default} Box
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @param {Box} box
|
||||
* @param {NotifObj} notif
|
||||
*/
|
||||
const addNotif = (box, notif) => {
|
||||
if (notif) {
|
||||
const NewNotif = Notification({
|
||||
|
@ -27,7 +36,7 @@ const NotificationList = () => Box({
|
|||
vertical: true,
|
||||
vexpand: true,
|
||||
vpack: 'start',
|
||||
binds: [['visible', HasNotifs]],
|
||||
visible: HasNotifs.bind(),
|
||||
|
||||
setup: (self) => {
|
||||
self
|
||||
|
@ -40,31 +49,42 @@ const NotificationList = () => Box({
|
|||
}
|
||||
|
||||
else if (id) {
|
||||
addNotif(box, Notifications.getNotification(id));
|
||||
const notifObj = Notifications.getNotification(id);
|
||||
|
||||
if (notifObj) {
|
||||
addNotif(box, notifObj);
|
||||
}
|
||||
}
|
||||
}, 'notified')
|
||||
|
||||
.hook(Notifications, (box, id) => {
|
||||
const notif = box.children.find((ch) => ch._id === id);
|
||||
// @ts-expect-error
|
||||
const notif = box.children.find((ch) => ch.attribute.id === id);
|
||||
|
||||
if (notif?.sensitive) {
|
||||
notif.slideAway('Right');
|
||||
// @ts-expect-error
|
||||
notif.attribute.slideAway('Right');
|
||||
}
|
||||
}, 'closed');
|
||||
},
|
||||
});
|
||||
|
||||
// TODO: use cursorbox feature for this
|
||||
// Needs to be wrapped to still have onHover when disabled
|
||||
const ClearButton = () => CursorBox({
|
||||
child: Button({
|
||||
onPrimaryClickRelease: () => {
|
||||
sensitive: HasNotifs.bind(),
|
||||
|
||||
on_primary_click_release: () => {
|
||||
Notifications.clear();
|
||||
timeout(1000, () => App.closeWindow('notification-center'));
|
||||
},
|
||||
binds: [['sensitive', HasNotifs]],
|
||||
|
||||
child: Box({
|
||||
|
||||
children: [
|
||||
Label('Clear '),
|
||||
|
||||
Icon({
|
||||
setup: (self) => {
|
||||
self.hook(Notifications, () => {
|
||||
|
@ -80,7 +100,7 @@ const ClearButton = () => CursorBox({
|
|||
});
|
||||
|
||||
const Header = () => Box({
|
||||
className: 'header',
|
||||
class_name: 'header',
|
||||
children: [
|
||||
Label({
|
||||
label: 'Notifications',
|
||||
|
@ -93,14 +113,17 @@ const Header = () => Box({
|
|||
|
||||
const Placeholder = () => Revealer({
|
||||
transition: 'crossfade',
|
||||
binds: [['revealChild', HasNotifs, 'value', (value) => !value]],
|
||||
reveal_child: HasNotifs.bind()
|
||||
.transform((v) => !v),
|
||||
|
||||
child: Box({
|
||||
className: 'placeholder',
|
||||
class_name: 'placeholder',
|
||||
vertical: true,
|
||||
vpack: 'center',
|
||||
hpack: 'center',
|
||||
vexpand: true,
|
||||
hexpand: true,
|
||||
|
||||
children: [
|
||||
Icon('notification-disabled-symbolic'),
|
||||
Label('Your inbox is empty'),
|
||||
|
@ -109,22 +132,27 @@ const Placeholder = () => Revealer({
|
|||
});
|
||||
|
||||
export default () => Box({
|
||||
className: 'notification-center',
|
||||
class_name: 'notification-center',
|
||||
vertical: true,
|
||||
children: [
|
||||
Header(),
|
||||
|
||||
Box({
|
||||
className: 'notification-wallpaper-box',
|
||||
class_name: 'notification-wallpaper-box',
|
||||
|
||||
children: [
|
||||
Scrollable({
|
||||
className: 'notification-list-box',
|
||||
class_name: 'notification-list-box',
|
||||
hscroll: 'never',
|
||||
vscroll: 'automatic',
|
||||
|
||||
child: Box({
|
||||
className: 'notification-list',
|
||||
class_name: 'notification-list',
|
||||
vertical: true,
|
||||
|
||||
children: [
|
||||
NotificationList(),
|
||||
|
||||
Placeholder(),
|
||||
],
|
||||
}),
|
||||
|
|
|
@ -5,90 +5,97 @@ import { timeout } from 'resource:///com/github/Aylur/ags/utils.js';
|
|||
|
||||
import { HasNotifs } from './base.js';
|
||||
|
||||
import Gtk from 'gi://Gtk';
|
||||
const { Gtk } = imports.gi;
|
||||
|
||||
const MAX_OFFSET = 200;
|
||||
const OFFSCREEN = 300;
|
||||
const ANIM_DURATION = 500;
|
||||
const SLIDE_MIN_THRESHOLD = 10;
|
||||
const TRANSITION = 'transition: margin 0.5s ease, opacity 0.5s ease;';
|
||||
const SQUEEZED = 'margin-bottom: -70px; margin-top: -70px;';
|
||||
const MAX_LEFT = `
|
||||
margin-left: -${Number(MAX_OFFSET + OFFSCREEN)}px;
|
||||
margin-right: ${Number(MAX_OFFSET + OFFSCREEN)}px;
|
||||
`;
|
||||
const MAX_RIGHT = `
|
||||
margin-left: ${Number(MAX_OFFSET + OFFSCREEN)}px;
|
||||
margin-right: -${Number(MAX_OFFSET + OFFSCREEN)}px;
|
||||
`;
|
||||
|
||||
const slideLeft = `${TRANSITION} ${MAX_LEFT}
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
opacity: 0;`;
|
||||
const squeezeLeft = `${TRANSITION} ${MAX_LEFT} ${SQUEEZED} opacity: 0;`;
|
||||
|
||||
const slideRight = `${TRANSITION} ${MAX_RIGHT}
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
opacity: 0;`;
|
||||
const squeezeRight = `${TRANSITION} ${MAX_RIGHT} ${SQUEEZED} opacity: 0;`;
|
||||
|
||||
const defaultStyle = `${TRANSITION} margin: unset; opacity: 1;`;
|
||||
|
||||
|
||||
export default ({
|
||||
id,
|
||||
slideIn = 'Left',
|
||||
command = () => { /**/ },
|
||||
command = () => {/**/},
|
||||
...props
|
||||
}) => {
|
||||
const widget = EventBox({
|
||||
...props,
|
||||
cursor: 'grab',
|
||||
onHover: (self) => {
|
||||
if (!self._hovered) {
|
||||
self._hovered = true;
|
||||
on_hover: (self) => {
|
||||
if (!self.attribute.hovered) {
|
||||
self.attribute.hovered = true;
|
||||
}
|
||||
},
|
||||
onHoverLost: (self) => {
|
||||
if (self._hovered) {
|
||||
self._hovered = false;
|
||||
on_hover_lost: (self) => {
|
||||
if (self.attribute.hovered) {
|
||||
self.attribute.hovered = false;
|
||||
}
|
||||
},
|
||||
|
||||
attribute: {
|
||||
dragging: false,
|
||||
hovered: false,
|
||||
ready: false,
|
||||
id,
|
||||
|
||||
/** @param {'Left'|'Right'} side */
|
||||
slideAway: (side) => {
|
||||
// Slide away
|
||||
// @ts-expect-error
|
||||
widget.child.setCss(side === 'Left' ? slideLeft : slideRight);
|
||||
|
||||
// Make it uninteractable
|
||||
widget.sensitive = false;
|
||||
|
||||
timeout(ANIM_DURATION - 100, () => {
|
||||
// Reduce height after sliding away
|
||||
// @ts-expect-error
|
||||
widget.child?.setCss(side === 'Left' ?
|
||||
squeezeLeft :
|
||||
squeezeRight);
|
||||
|
||||
timeout(ANIM_DURATION, () => {
|
||||
// Kill notif and update HasNotifs after anim is done
|
||||
command();
|
||||
|
||||
HasNotifs.value = Notifications
|
||||
.notifications.length > 0;
|
||||
|
||||
// @ts-expect-error
|
||||
widget.get_parent()?.remove;
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Properties
|
||||
widget._dragging = false;
|
||||
widget._hovered = false;
|
||||
widget._id = id;
|
||||
widget.ready = false;
|
||||
|
||||
const gesture = Gtk.GestureDrag.new(widget);
|
||||
|
||||
const TRANSITION = 'transition: margin 0.5s ease, opacity 0.5s ease;';
|
||||
const SQUEEZED = 'margin-bottom: -70px; margin-top: -70px;';
|
||||
const MAX_LEFT = `
|
||||
margin-left: -${Number(MAX_OFFSET + OFFSCREEN)}px;
|
||||
margin-right: ${Number(MAX_OFFSET + OFFSCREEN)}px;
|
||||
`;
|
||||
const MAX_RIGHT = `
|
||||
margin-left: ${Number(MAX_OFFSET + OFFSCREEN)}px;
|
||||
margin-right: -${Number(MAX_OFFSET + OFFSCREEN)}px;
|
||||
`;
|
||||
|
||||
const slideLeft = `${TRANSITION} ${MAX_LEFT}
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
opacity: 0;`;
|
||||
const squeezeLeft = `${TRANSITION} ${MAX_LEFT} ${SQUEEZED} opacity: 0;`;
|
||||
|
||||
const slideRight = `${TRANSITION} ${MAX_RIGHT}
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
opacity: 0;`;
|
||||
const squeezeRight = `${TRANSITION} ${MAX_RIGHT} ${SQUEEZED} opacity: 0;`;
|
||||
|
||||
const defaultStyle = `${TRANSITION} margin: unset; opacity: 1;`;
|
||||
|
||||
|
||||
// Notif methods
|
||||
widget.slideAway = (side) => {
|
||||
// Slide away
|
||||
widget.child.setCss(side === 'Left' ? slideLeft : slideRight);
|
||||
|
||||
// Makie it uninteractable
|
||||
widget.sensitive = false;
|
||||
|
||||
timeout(ANIM_DURATION - 100, () => {
|
||||
// Reduce height after sliding away
|
||||
widget.child?.setCss(side === 'Left' ? squeezeLeft : squeezeRight);
|
||||
|
||||
timeout(ANIM_DURATION, () => {
|
||||
// Kill notif and update HasNotifs after anim is done
|
||||
command();
|
||||
HasNotifs.value = Notifications.notifications.length > 0;
|
||||
widget.get_parent()?.remove(widget);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
widget.add(Box({
|
||||
css: squeezeLeft,
|
||||
setup: (self) => {
|
||||
|
@ -123,14 +130,16 @@ export default ({
|
|||
}
|
||||
|
||||
// Put a threshold on if a click is actually dragging
|
||||
widget._dragging = Math.abs(offset) > SLIDE_MIN_THRESHOLD;
|
||||
widget.attribute.dragging =
|
||||
Math.abs(offset) > SLIDE_MIN_THRESHOLD;
|
||||
|
||||
widget.cursor = 'grabbing';
|
||||
}, 'drag-update')
|
||||
|
||||
// On drag end
|
||||
.hook(gesture, () => {
|
||||
// Make it slide in on init
|
||||
if (!widget.ready) {
|
||||
if (!widget.attribute.ready) {
|
||||
// Reverse of slideAway, so it started at squeeze, then we go to slide
|
||||
self.setCss(slideIn === 'Left' ?
|
||||
slideLeft :
|
||||
|
@ -140,7 +149,7 @@ export default ({
|
|||
// Then we go to center
|
||||
self.setCss(defaultStyle);
|
||||
timeout(ANIM_DURATION, () => {
|
||||
widget.ready = true;
|
||||
widget.attribute.ready = true;
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -152,16 +161,16 @@ export default ({
|
|||
// If crosses threshold after letting go, slide away
|
||||
if (Math.abs(offset) > MAX_OFFSET) {
|
||||
if (offset > 0) {
|
||||
widget.slideAway('Right');
|
||||
widget.attribute.slideAway('Right');
|
||||
}
|
||||
else {
|
||||
widget.slideAway('Left');
|
||||
widget.attribute.slideAway('Left');
|
||||
}
|
||||
}
|
||||
else {
|
||||
self.setCss(defaultStyle);
|
||||
widget.cursor = 'grab';
|
||||
widget._dragging = false;
|
||||
widget.attribute.dragging = false;
|
||||
}
|
||||
}, 'drag-end');
|
||||
},
|
||||
|
|
|
@ -16,7 +16,6 @@ export const NotifPopups = () => PopupWindow({
|
|||
|
||||
const TOP_MARGIN = 6;
|
||||
|
||||
// FIXME: opens at wrong place
|
||||
export const NotifCenter = () => PopupWindow({
|
||||
name: 'notification-center',
|
||||
anchor: ['top', 'right'],
|
||||
|
|
|
@ -14,6 +14,7 @@ export default () => Box({
|
|||
vertical: true,
|
||||
|
||||
setup: (self) => {
|
||||
/** @param {number} id */
|
||||
const addPopup = (id) => {
|
||||
if (!id) {
|
||||
return;
|
||||
|
@ -21,38 +22,49 @@ export default () => Box({
|
|||
|
||||
const notif = Notifications.getNotification(id);
|
||||
|
||||
const NewNotif = Notification({
|
||||
notif,
|
||||
command: () => notif.dismiss(),
|
||||
});
|
||||
if (notif) {
|
||||
const NewNotif = Notification({
|
||||
notif,
|
||||
command: () => notif.dismiss(),
|
||||
});
|
||||
|
||||
if (NewNotif) {
|
||||
// Use this instead of add to put it at the top
|
||||
self.pack_end(NewNotif, false, false, 0);
|
||||
self.show_all();
|
||||
if (NewNotif) {
|
||||
// Use this instead of add to put it at the top
|
||||
self.pack_end(NewNotif, false, false, 0);
|
||||
self.show_all();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} id
|
||||
* @param {boolean} force
|
||||
*/
|
||||
const handleDismiss = (id, force = false) => {
|
||||
const notif = self.children.find((ch) => ch._id === id);
|
||||
// @ts-expect-error
|
||||
const notif = self.children.find((ch) => ch.attribute.id === id);
|
||||
|
||||
if (!notif) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If notif isn't hovered or was closed, slide away
|
||||
if (!notif._hovered || force) {
|
||||
notif.slideAway('Left');
|
||||
// @ts-expect-error
|
||||
if (!notif.attribute.hovered || force) {
|
||||
// @ts-expect-error
|
||||
notif.attribute.slideAway('Left');
|
||||
}
|
||||
|
||||
// If notif is hovered, delay close
|
||||
else if (notif._hovered) {
|
||||
notif.interval = interval(DELAY, () => {
|
||||
if (!notif._hovered && notif.interval) {
|
||||
notif.slideAway('Left');
|
||||
// @ts-expect-error
|
||||
else if (notif.attribute.hovered) {
|
||||
const intervalId = interval(DELAY, () => {
|
||||
// @ts-expect-error
|
||||
if (!notif.attribute.hovered && intervalId) {
|
||||
// @ts-expect-error
|
||||
notif.attribute.slideAway('Left');
|
||||
|
||||
GLib.source_remove(notif.interval);
|
||||
notif.interval = null;
|
||||
GLib.source_remove(intervalId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue