Files

238 lines
6.9 KiB
QML

import QtQuick
import qs.Common
import qs.Services
import qs.Widgets
DankPopout {
id: root
layerNamespace: "dms:notification-center-popout"
fullHeightSurface: true
property bool notificationHistoryVisible: false
property var triggerScreen: null
property real stablePopupHeight: 400
property real _lastAlignedContentHeight: -1
property bool _pendingSizedOpen: false
property bool _heightUpdatePending: false
function updateStablePopupHeight() {
const item = contentLoader.item;
if (item && !root.shouldBeVisible) {
const notificationList = findChild(item, "notificationList");
if (notificationList && typeof notificationList.forceLayout === "function") {
notificationList.forceLayout();
}
}
const target = item ? Theme.px(item.implicitHeight, dpr) : 400;
if (Math.abs(target - _lastAlignedContentHeight) < 0.5)
return;
_lastAlignedContentHeight = target;
stablePopupHeight = target;
}
function queueStablePopupHeightUpdate() {
if (_heightUpdatePending)
return;
_heightUpdatePending = true;
Qt.callLater(() => {
_heightUpdatePending = false;
updateStablePopupHeight();
});
}
NotificationKeyboardController {
id: keyboardController
listView: null
isOpen: root.shouldBeVisible
onClose: () => {
notificationHistoryVisible = false;
}
}
popupWidth: 400 + Theme.spacingL
popupHeight: stablePopupHeight
positioning: ""
suspendShadowWhileResizing: false
screen: triggerScreen
function toggle() {
notificationHistoryVisible = !notificationHistoryVisible;
}
// Re-open without toggling the flag (used when retargeting to another monitor).
function present() {
openSized();
}
function openSized() {
if (!notificationHistoryVisible)
return;
primeContent();
if (contentLoader.item) {
updateStablePopupHeight();
_pendingSizedOpen = false;
Qt.callLater(() => {
if (!notificationHistoryVisible)
return;
updateStablePopupHeight();
open();
clearPrimedContent();
});
return;
}
_pendingSizedOpen = true;
}
onBackgroundClicked: {
notificationHistoryVisible = false;
}
onNotificationHistoryVisibleChanged: {
if (notificationHistoryVisible) {
openSized();
} else {
_pendingSizedOpen = false;
clearPrimedContent();
close();
}
}
function setupKeyboardNavigation() {
if (!contentLoader.item)
return;
contentLoader.item.externalKeyboardController = keyboardController;
const notificationList = findChild(contentLoader.item, "notificationList");
const notificationHeader = findChild(contentLoader.item, "notificationHeader");
if (notificationList) {
keyboardController.listView = notificationList;
notificationList.keyboardController = keyboardController;
}
if (notificationHeader) {
notificationHeader.keyboardController = keyboardController;
}
keyboardController.reset();
keyboardController.rebuildFlatNavigation();
}
Connections {
target: contentLoader
function onLoaded() {
root.updateStablePopupHeight();
if (root._pendingSizedOpen && root.notificationHistoryVisible) {
Qt.callLater(() => {
if (!root._pendingSizedOpen || !root.notificationHistoryVisible)
return;
root.updateStablePopupHeight();
root._pendingSizedOpen = false;
root.open();
root.clearPrimedContent();
});
return;
}
if (root.shouldBeVisible)
Qt.callLater(root.setupKeyboardNavigation);
}
}
Connections {
target: contentLoader.item
function onImplicitHeightChanged() {
root.queueStablePopupHeightUpdate();
}
}
onDprChanged: updateStablePopupHeight()
onShouldBeVisibleChanged: {
notificationHistoryVisible = shouldBeVisible;
if (shouldBeVisible) {
NotificationService.onOverlayOpen();
updateStablePopupHeight();
if (contentLoader.item)
Qt.callLater(setupKeyboardNavigation);
} else {
NotificationService.onOverlayClose();
keyboardController.keyboardNavigationActive = false;
NotificationService.expandedGroups = {};
NotificationService.expandedMessages = {};
}
}
function findChild(parent, objectName) {
if (parent.objectName === objectName) {
return parent;
}
for (let i = 0; i < parent.children.length; i++) {
const child = parent.children[i];
const result = findChild(child, objectName);
if (result) {
return result;
}
}
return null;
}
content: Component {
Item {
id: notificationContent
property alias externalKeyboardController: body.externalKeyboardController
implicitHeight: body.implicitHeight
focus: true
Component.onCompleted: {
if (root.shouldBeVisible)
forceActiveFocus();
}
Keys.onPressed: event => body.handleKey(event)
Connections {
target: root
function onShouldBeVisibleChanged() {
if (root.shouldBeVisible) {
Qt.callLater(() => notificationContent.forceActiveFocus());
return;
}
notificationContent.focus = false;
}
}
QtObject {
id: popoutHost
readonly property bool shouldBeVisible: root.shouldBeVisible
readonly property var screen: root.screen
readonly property var transientSurfaceTracker: root.transientSurfaceTracker
readonly property real maxContentHeight: (root.screen?.height ?? 1080) * 0.8
function close() {
root.notificationHistoryVisible = false;
}
function requestSettings() {
root.notificationHistoryVisible = false;
PopoutService.openSettingsWithTab("notifications", root, () => root.open());
}
}
NotificationCenterContent {
id: body
anchors.fill: parent
host: popoutHost
}
}
}
}