Merge pull request #2281 from ayagmar/fix/notification-window-focus

fix(notifications): prefer default actions for window focus
This commit is contained in:
Lysec
2026-03-23 23:40:45 +01:00
committed by GitHub
3 changed files with 38 additions and 19 deletions
+10 -7
View File
@@ -350,12 +350,13 @@ Variants {
function runAction(actionId, isDismissed) {
if (!isDismissed) {
NotificationService.focusSenderWindow(model.appName);
NotificationService.invokeActionAndSuppressClose(notificationId, actionId);
} else if (Settings.data.notifications.clearDismissed) {
NotificationService.removeFromHistory(notificationId);
if (NotificationService.invokeActionAndSuppressClose(notificationId, actionId))
card.animateOut();
} else {
if (Settings.data.notifications.clearDismissed)
NotificationService.removeFromHistory(notificationId);
card.animateOut();
}
card.animateOut();
}
Timer {
@@ -527,9 +528,11 @@ Variants {
var hasDefault = actions.some(function (a) {
return a.identifier === "default";
});
if (hasDefault) {
card.runAction("default", false);
if (hasDefault && NotificationService.invokeActionAndSuppressClose(notificationId, "default")) {
card.animateOut();
} else {
// Without a default action, or if invoking it fails,
// the best fallback is focusing the sender window by app identity.
NotificationService.focusSenderWindow(model.appName);
card.animateOut();
}
@@ -171,7 +171,8 @@ SmartPanel {
if (actionIndex >= 0) {
var actions = parseActions(item.actionsJson);
if (actionIndex < actions.length) {
NotificationService.invokeAction(item.id, actions[actionIndex].identifier);
if (NotificationService.invokeAction(item.id, actions[actionIndex].identifier))
root.close();
}
} else {
var delegate = notificationColumn.children[focusIndex];
@@ -791,18 +792,18 @@ SmartPanel {
return;
}
// Focus sender window (and invoke default action if available)
// Without a default action, or if invoking it fails,
// fall back to focusing the sender window by app identity.
var actions = notificationDelegate.actionsList;
var hasDefault = actions.some(function (a) {
return a.identifier === "default";
});
if (hasDefault) {
NotificationService.focusSenderWindow(notificationDelegate.appName);
NotificationService.invokeAction(notificationDelegate.notificationId, "default");
if (hasDefault && NotificationService.invokeAction(notificationDelegate.notificationId, "default")) {
root.close();
} else {
NotificationService.focusSenderWindow(notificationDelegate.appName);
root.close();
}
root.close();
}
onCanceled: {
notificationDelegate.isSwiping = false;
@@ -960,9 +961,8 @@ SmartPanel {
// Capture modelData in a property to avoid reference errors
property var actionData: modelData
onClicked: {
NotificationService.focusSenderWindow(notificationDelegate.appName);
root.close();
NotificationService.invokeAction(notificationDelegate.notificationId, actionData.identifier);
if (NotificationService.invokeAction(notificationDelegate.notificationId, actionData.identifier))
root.close();
}
}
}
+19 -3
View File
@@ -921,13 +921,29 @@ Singleton {
function invokeActionAndSuppressClose(id, actionId) {
const notifData = popupState[id];
if (notifData && notifData.notification && notifData.onClosed) {
const notification = notifData?.notification;
const onClosed = notifData?.onClosed;
let restoreClosedHandler = false;
if (notification && onClosed) {
try {
notifData.notification.closed.disconnect(notifData.onClosed);
// A successful action may synchronously close the notification. Disconnect
// our close handler first so the popup is only dismissed by the action path.
notification.closed.disconnect(onClosed);
restoreClosedHandler = true;
} catch (e) {}
}
return invokeAction(id, actionId);
const invoked = invokeAction(id, actionId);
if (!invoked && restoreClosedHandler && notification && onClosed) {
try {
// If invoking the action failed, restore normal close handling for this popup.
notification.closed.connect(onClosed);
} catch (e) {}
}
return invoked;
}
function invokeAction(id, actionId) {