177 lines
6.3 KiB
JavaScript

// This file is for the notification list on the sidebar
// For the popup notifications, see onscreendisplay.js
// The actual widget for each single notification is in ags/modules/.commonwidgets/notification.js
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
import Notifications from 'resource:///com/github/Aylur/ags/service/notifications.js';
const { Box, Button, Label, Revealer, Scrollable, Stack } = Widget;
import { MaterialIcon } from '../../.commonwidgets/materialicon.js';
import { setupCursorHover } from '../../.widgetutils/cursorhover.js';
import Notification from '../../.commonwidgets/notification.js';
import { ConfigToggle } from '../../.commonwidgets/configwidgets.js';
export default (props) => {
const notifEmptyContent = Box({
homogeneous: true,
children: [Box({
vertical: true,
vpack: 'center',
className: 'txt spacing-v-10',
children: [
Box({
vertical: true,
className: 'spacing-v-5 txt-subtext',
children: [
MaterialIcon('notifications_active', 'gigantic'),
Label({ label: 'No notifications', className: 'txt-small' }),
]
}),
]
})]
});
const notificationList = Box({
vertical: true,
vpack: 'start',
className: 'spacing-v-5-revealer',
setup: (self) => self
.hook(Notifications, (box, id) => {
if (box.get_children().length == 0) { // On init there's no notif, or 1st notif
Notifications.notifications
.forEach(n => {
box.pack_end(Notification({
notifObject: n,
isPopup: false,
}), false, false, 0)
});
box.show_all();
return;
}
// 2nd or later notif
const notif = Notifications.getNotification(id);
const NewNotif = Notification({
notifObject: notif,
isPopup: false,
});
if (NewNotif) {
box.pack_end(NewNotif, false, false, 0);
box.show_all();
}
}, 'notified')
.hook(Notifications, (box, id) => {
if (!id) return;
for (const ch of box.children) {
if (ch._id === id) {
ch.attribute.destroyWithAnims();
}
}
}, 'closed')
,
});
const ListActionButton = (icon, name, action) => Button({
className: 'sidebar-centermodules-bottombar-button',
onClicked: action,
child: Box({
hpack: 'center',
className: 'spacing-h-5',
children: [
MaterialIcon(icon, 'norm'),
Label({
className: 'txt-small',
label: name,
})
]
}),
setup: setupCursorHover,
});
const silenceButton = ListActionButton('notifications_paused', 'Silence', (self) => {
Notifications.dnd = !Notifications.dnd;
self.toggleClassName('notif-listaction-btn-enabled', Notifications.dnd);
});
// const silenceToggle = ConfigToggle({
// expandWidget: false,
// icon: 'do_not_disturb_on',
// name: 'Do Not Disturb',
// initValue: false,
// onChange: (self, newValue) => {
// Notifications.dnd = newValue;
// },
// })
const clearButton = Revealer({
transition: 'slide_right',
transitionDuration: userOptions.animations.durationSmall,
setup: (self) => self.hook(Notifications, (self) => {
self.revealChild = Notifications.notifications.length > 0;
}),
child: ListActionButton('clear_all', 'Clear', () => {
Notifications.clear();
const kids = notificationList.get_children();
for (let i = 0; i < kids.length; i++) {
const kid = kids[i];
Utils.timeout(userOptions.animations.choreographyDelay * i, () => kid.attribute.destroyWithAnims());
}
})
})
const notifCount = Label({
attribute: {
updateCount: (self) => {
const count = Notifications.notifications.length;
if (count > 0) self.label = `${count} notifications`;
else self.label = '';
},
},
hexpand: true,
xalign: 0,
className: 'txt-small margin-left-10',
label: `${Notifications.notifications.length}`,
setup: (self) => self
.hook(Notifications, (box, id) => self.attribute.updateCount(self), 'notified')
.hook(Notifications, (box, id) => self.attribute.updateCount(self), 'dismissed')
.hook(Notifications, (box, id) => self.attribute.updateCount(self), 'closed')
,
});
const listTitle = Box({
vpack: 'start',
className: 'txt spacing-h-5',
children: [
notifCount,
silenceButton,
// silenceToggle,
// Box({ hexpand: true }),
clearButton,
]
});
const notifList = Scrollable({
hexpand: true,
hscroll: 'never',
vscroll: 'automatic',
child: Box({
vexpand: true,
homogeneous: true,
children: [notificationList],
}),
setup: (self) => {
const vScrollbar = self.get_vscrollbar();
vScrollbar.get_style_context().add_class('sidebar-scrollbar');
}
});
const listContents = Stack({
transition: 'crossfade',
transitionDuration: userOptions.animations.durationLarge,
children: {
'empty': notifEmptyContent,
'list': notifList,
},
setup: (self) => self.hook(Notifications, (self) => {
self.shown = (Notifications.notifications.length > 0 ? 'list' : 'empty')
}),
});
return Box({
...props,
className: 'spacing-v-5',
vertical: true,
children: [
listContents,
listTitle,
]
});
}