mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-07 05:55:37 -05:00
172 lines
4.5 KiB
QML
172 lines
4.5 KiB
QML
import QtQuick
|
|
import Quickshell
|
|
import qs.Common
|
|
import qs.Services
|
|
|
|
QtObject {
|
|
id: manager
|
|
|
|
property var popupLoaders: []
|
|
property int maxTargetNotifications: 3
|
|
property int baseNotificationHeight: 132
|
|
property bool dismissalInProgress: false
|
|
|
|
property Timer dismissalTimer: Timer {
|
|
interval: 200
|
|
repeat: false
|
|
onTriggered: dismissNextOldest()
|
|
}
|
|
|
|
property Component popupLoaderComponent: Component {
|
|
Loader {
|
|
id: popupLoader
|
|
|
|
property var notifWrapper
|
|
|
|
active: false
|
|
asynchronous: true
|
|
|
|
sourceComponent: NotificationPopup {
|
|
id: popup
|
|
|
|
notificationData: popupLoader.notifWrapper
|
|
notificationId: popupLoader.notifWrapper ? popupLoader.notifWrapper.notification.id : ""
|
|
onEntered: manager._onPopupEntered(popupLoader)
|
|
onSlideOutChanged: {
|
|
if (slideOut) {
|
|
manager._onPopupExitStarted(popupLoader);
|
|
}
|
|
}
|
|
onExitFinished: manager._onPopupExitFinished(popupLoader)
|
|
}
|
|
}
|
|
}
|
|
|
|
property Connections notificationConnections: Connections {
|
|
function onVisibleNotificationsChanged() {
|
|
syncPopupsWithQueue(NotificationService.visibleNotifications);
|
|
}
|
|
|
|
target: NotificationService
|
|
}
|
|
|
|
function _createPopupLoader(notifWrapper) {
|
|
const L = popupLoaderComponent.createObject(manager, {
|
|
"notifWrapper": notifWrapper
|
|
});
|
|
popupLoaders.push(L);
|
|
return L;
|
|
}
|
|
|
|
function _destroyPopupLoader(L) {
|
|
const i = popupLoaders.indexOf(L);
|
|
if (i !== -1) {
|
|
popupLoaders.splice(i, 1);
|
|
popupLoaders = popupLoaders.slice();
|
|
}
|
|
L.active = false;
|
|
L.sourceComponent = null;
|
|
}
|
|
|
|
function _activeItems() {
|
|
return popupLoaders.filter((L) => {
|
|
return L.item && L.item.notificationData && L.item.notificationData.popup;
|
|
});
|
|
}
|
|
|
|
function _stableItems() {
|
|
return _activeItems().filter((L) => {
|
|
return !L.item.entering;
|
|
});
|
|
}
|
|
|
|
function repositionAll() {
|
|
const stable = _stableItems();
|
|
for (let i = 0; i < stable.length; ++i) {
|
|
const it = stable[i].item;
|
|
if (it)
|
|
it.verticalOffset = i * baseNotificationHeight;
|
|
|
|
}
|
|
}
|
|
|
|
function syncPopupsWithQueue(newWrappers) {
|
|
for (let w of newWrappers) {
|
|
if (!popupLoaders.some((L) => {
|
|
return L.notifWrapper === w;
|
|
})) {
|
|
const L = _createPopupLoader(w);
|
|
const actives = _activeItems().length;
|
|
w.initialOffset = actives * baseNotificationHeight;
|
|
L.active = true;
|
|
}
|
|
}
|
|
for (let L of popupLoaders.slice()) {
|
|
if (newWrappers.indexOf(L.notifWrapper) === -1)
|
|
_destroyPopupLoader(L);
|
|
|
|
}
|
|
repositionAll();
|
|
}
|
|
|
|
function _onPopupEntered(L) {
|
|
repositionAll();
|
|
maybeStartOverflow();
|
|
}
|
|
|
|
function _onPopupExitStarted(L) {
|
|
const it = L.item;
|
|
if (!it)
|
|
return ;
|
|
|
|
if (it.shadowLayers) {
|
|
for (let layer of it.shadowLayers) {
|
|
if (layer)
|
|
layer.visible = false;
|
|
|
|
}
|
|
}
|
|
if (it.iconContainer && it.iconContainer.iconImage) {
|
|
it.iconContainer.iconImage.source = "";
|
|
}
|
|
}
|
|
|
|
function _onPopupExitFinished(L) {
|
|
NotificationService.releaseWrapper(L.notifWrapper);
|
|
_destroyPopupLoader(L);
|
|
repositionAll();
|
|
maybeStartOverflow();
|
|
}
|
|
|
|
function maybeStartOverflow() {
|
|
const active = _activeItems();
|
|
if (dismissalInProgress)
|
|
return ;
|
|
|
|
if (active.length > maxTargetNotifications)
|
|
startSequentialDismissal();
|
|
|
|
}
|
|
|
|
function startSequentialDismissal() {
|
|
dismissalInProgress = true;
|
|
dismissNextOldest();
|
|
}
|
|
|
|
function dismissNextOldest() {
|
|
const active = _activeItems();
|
|
if (active.length <= maxTargetNotifications) {
|
|
dismissalInProgress = false;
|
|
return ;
|
|
}
|
|
const oldest = active[0].item;
|
|
if (oldest) {
|
|
oldest.notificationData.removedByLimit = true;
|
|
oldest.notificationData.popup = false;
|
|
dismissalTimer.restart();
|
|
}
|
|
}
|
|
|
|
|
|
}
|