feat: refactor notification system to manage hover states centrally and auto close

This commit is contained in:
Hannes
2026-09-02 00:16:15 +02:00
parent b59eb012ba
commit 27401c25a0
5 changed files with 129 additions and 25 deletions
+72 -8
View File
@@ -31,8 +31,7 @@ PanelWindow {
property var grouped: {
const vals = NotificationS.trackedNotifications.values
const len = vals.length
if (len < 0) return []
if (!vals || vals.length === 0) return []
let map = {}
for (let i = 0; i < vals.length; ++i) {
const n = vals[i]
@@ -65,21 +64,86 @@ PanelWindow {
expandedGroups = ({})
}
function closeNHistory() {
// Centralized close via singleton signal fixes previous ReferenceError
// where this file tried to access notifificationHistoryLoader.id directly
// (that id lives in NotificationHistoryLoader.qml and is not in scope here).
console.log("[NotificationHistory] closeNHistory() requested")
NotificationS.historyHovered = false
NotificationS.closeHistoryRequested()
}
// ── Hover tracking via NotificationServer ──
// History reports its hover state to the singleton; button does the same.
// Timer auto-closes when neither is hovered for historyAutoCloseDelay ms.
property bool _allowAutoClose: false
HoverHandler {
id: historyHoverHandler
onHoveredChanged: NotificationS.historyHovered = hovered
}
// Fallback MouseArea that doesn't steal clicks (acceptedButtons: NoButton)
// Ensures hover is detected even if HoverHandler is missed on PanelWindow boundaries.
// Placed with high z but NoButton so it doesn't block inner MouseAreas.
MouseArea {
id: historyHoverMouseArea
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.NoButton
propagateComposedEvents: true
onContainsMouseChanged: NotificationS.historyHovered = containsMouse
}
// Grace timer: don't allow auto-close immediately after opening,
// giving keyboard users time to move mouse to history.
Timer {
id: graceTimer
interval: 500
running: root.visible && !_allowAutoClose
repeat: false
onTriggered: _allowAutoClose = true
}
Timer {
id: hoverCloseTimer
interval: NotificationS.historyAutoCloseDelay
// Only run when panel is visible, grace passed, and neither element is hovered
running: root.visible && _allowAutoClose && !NotificationS.historyHovered && !NotificationS.buttonHovered
repeat: false
onTriggered: {
if (!NotificationS.historyHovered && !NotificationS.buttonHovered) {
console.log("[NotificationHistory] Auto-closing after hover timeout (" + interval + "ms)")
root.closeNHistory()
}
}
}
// Ensure hover state is cleared when window hides/destroys
onVisibleChanged: {
if (!visible) {
NotificationS.historyHovered = false
_allowAutoClose = false
}
}
Component.onDestruction: NotificationS.historyHovered = false
FocusScope {
id: nHistoryScope
anchors.fill: parent
focus: true
Keys.onReleased: function(event) {
if (event.key === Qt.Key_Escape) {
console.log("Pressed Escape, closing JLearner")
notifificationHistoryLoader.active = false
console.log("Pressed Escape, closing NotificationHistory")
root.closeNHistory()
}
}
Rectangle {
anchors.fill: parent
color: "lightblue"
visible: false // debug helper, keep hidden in normal use
}
}
@@ -154,7 +218,7 @@ PanelWindow {
spacing: Config.screen_spacing_fun(screen.height)
Text{
text: NotificationS.soundEnabled ? "󰂚" : "󰂛"
text: NotificationS.notificationPopupEnabled ? "󰂚" : "󰂛"
font.family: Config.font
font.pixelSize: topBar.height*0.75
color: textColor
@@ -166,7 +230,7 @@ PanelWindow {
implicitWidth: notificationVolumeSwitch.height*2
implicitHeight: topBar.height*0.75
anchors.verticalCenter: parent.verticalCenter
checked: NotificationS.soundEnabled
checked: NotificationS.notificationPopupEnabled
indicator: Rectangle {
implicitWidth: notificationVolumeSwitch.width
@@ -203,8 +267,8 @@ PanelWindow {
}
onCheckedChanged: {
NotificationS.soundEnabled = notificationVolumeSwitch.checked
console.log("NotificationS.soundEnabled:", NotificationS.soundEnabled)
NotificationS.notificationPopupEnabled = notificationVolumeSwitch.checked
console.log("NotificationS.notificationPopupEnabled:", NotificationS.notificationPopupEnabled)
}
}