diff options
Diffstat (limited to 'home-configuration/config/quickshell/modules/notifications/NotificationFocus.qml')
| -rw-r--r-- | home-configuration/config/quickshell/modules/notifications/NotificationFocus.qml | 228 |
1 files changed, 172 insertions, 56 deletions
diff --git a/home-configuration/config/quickshell/modules/notifications/NotificationFocus.qml b/home-configuration/config/quickshell/modules/notifications/NotificationFocus.qml index af52eaa..ce59b2a 100644 --- a/home-configuration/config/quickshell/modules/notifications/NotificationFocus.qml +++ b/home-configuration/config/quickshell/modules/notifications/NotificationFocus.qml @@ -1,13 +1,120 @@ import QtQuick import Quickshell import Quickshell.Io -import "../../config.js" as Config Item { id: root property string pendingApp: "" + function normalize(value) { + if (!value) + return "" + + var result = String(value).toLowerCase().trim() + + result = result.replace(/^org\./, "") + result = result.replace(/^com\./, "") + result = result.replace(/^net\./, "") + result = result.replace(/^app\./, "") + + result = result.replace(/\.desktop$/, "") + result = result.replace(/\.desktop$/i, "") + + result = result.replace(/[^a-z0-9]+/g, "") + + return result + } + + function candidates(value) { + var result = [] + var raw = String(value || "").toLowerCase().trim() + + function add(candidate) { + if (!candidate) + return + + candidate = normalize(candidate) + + if (candidate && result.indexOf(candidate) === -1) + result.push(candidate) + } + + add(raw) + + if (raw.indexOf(".") !== -1) { + var parts = raw.split(".") + + add(parts[parts.length - 1]) + + for (var i = 0; i < parts.length; i++) + add(parts[i]) + } + + if (raw.indexOf("/") !== -1) + add(raw.split("/").pop()) + + if (raw.indexOf("-") !== -1) { + var dashParts = raw.split("-") + + for (var j = 0; j < dashParts.length; j++) + add(dashParts[j]) + } + + if (raw.indexOf("_") !== -1) { + var underscoreParts = raw.split("_") + + for (var k = 0; k < underscoreParts.length; k++) + add(underscoreParts[k]) + } + + return result + } + + function matchScore(notificationApp, windowAppId, windowTitle) { + var notificationCandidates = candidates(notificationApp) + var windowCandidates = candidates(windowAppId) + + var best = 0 + + for (var i = 0; i < notificationCandidates.length; i++) { + var notificationCandidate = notificationCandidates[i] + + for (var j = 0; j < windowCandidates.length; j++) { + var windowCandidate = windowCandidates[j] + + if (notificationCandidate === windowCandidate) + best = Math.max(best, 100) + + else if ( + notificationCandidate.length >= 4 && + windowCandidate.length >= 4 && + ( + notificationCandidate.indexOf(windowCandidate) !== -1 || + windowCandidate.indexOf(notificationCandidate) !== -1 + ) + ) { + best = Math.max(best, 60) + } + } + } + + var titleCandidates = candidates(windowTitle) + + for (var n = 0; n < notificationCandidates.length; n++) { + for (var t = 0; t < titleCandidates.length; t++) { + if ( + notificationCandidates[n].length >= 4 && + notificationCandidates[n] === titleCandidates[t] + ) { + best = Math.max(best, 30) + } + } + } + + return best + } + Process { id: windowsProcess @@ -23,7 +130,7 @@ Item { windows = JSON.parse(this.text) } catch (error) { console.error( - "Failed to parse niri windows:", + "Failed to parse Niri windows:", error ) @@ -31,74 +138,74 @@ Item { return } - var app = root.pendingApp.toLowerCase() + var notificationApp = root.pendingApp root.pendingApp = "" - if (Config.notificationVesktopNames.indexOf(app) !== -1) { - for (var i = 0; i < windows.length; i++) { - var niriWindow = windows[i] - var appId = (niriWindow.app_id || "").toLowerCase() - - if (appId === Config.notificationVesktopAppId) { - console.log( - "FOCUSING VESKTOP WINDOW:", - niriWindow.id, - niriWindow.title - ) - - focusProcess.exec([ - "niri", - "msg", - "action", - "focus-window", - "--id", - String(niriWindow.id) - ]) - - return - } - } + if (!notificationApp) { + console.warn("Notification focus: empty app name") + return + } - console.log( - "No matching Niri window found for:", - app + if (!Array.isArray(windows)) { + console.error( + "Niri windows response is not an array" ) - return } - for (var j = 0; j < windows.length; j++) { - var window = windows[j] - var windowAppId = (window.app_id || "").toLowerCase() + var bestWindow = null + var bestScore = 0 + + for (var i = 0; i < windows.length; i++) { + var window = windows[i] - if ( - windowAppId === app || - windowAppId === app + ".desktop" - ) { - console.log( - "FOCUSING WINDOW:", - window.id, - window.app_id, - window.title - ) + if (!window || window.id === undefined) + continue - focusProcess.exec([ - "niri", - "msg", - "action", - "focus-window", - "--id", - String(window.id) - ]) + var appId = window.app_id || "" + var title = window.title || "" - return + var score = matchScore( + notificationApp, + appId, + title + ) + + if (score > bestScore) { + bestScore = score + bestWindow = window } } + if (!bestWindow) { + console.log( + "No matching Niri window found:", + notificationApp + ) + return + } + console.log( - "No matching Niri window found for:", - app + "FOCUSING WINDOW:", + bestWindow.id, + "notification app:", + notificationApp, + "app_id:", + bestWindow.app_id, + "title:", + bestWindow.title, + "score:", + bestScore ) + + focusProcess.exec([ + "niri", + "msg", + "action", + "focus-window", + "--id", + String(bestWindow.id) + ]) } } } @@ -111,7 +218,16 @@ Item { if (!notification) return - root.pendingApp = notification.appName + var app = notification.appName || "" + + if (!app) { + console.warn( + "Notification has no application name" + ) + return + } + + root.pendingApp = app windowsProcess.exec([ "niri", |
