fix: harden notification application rule integration
This commit is contained in:
@@ -52,13 +52,21 @@ Singleton {
|
||||
return stored && typeof stored === "object" && !Array.isArray(stored) ? stored : {};
|
||||
}
|
||||
|
||||
// The schema change is the persistence boundary. This branch keeps a
|
||||
// session fallback only so it remains usable while that companion change
|
||||
// is being integrated; it intentionally makes no restart guarantee then.
|
||||
readonly property bool appRulesSchemaAvailable: PreferenceSchema.has("notificationAppRules")
|
||||
|
||||
readonly property var appRules: Object.assign({}, root.persistedAppRules, root.fallbackAppRules)
|
||||
|
||||
readonly property var applications: {
|
||||
// byId()/heuristicLookup() do not make a binding by themselves. This
|
||||
// read updates persisted app labels once DesktopEntries finishes scan.
|
||||
const entries = DesktopEntries.applications.values;
|
||||
const remembered = root.rememberedApplications;
|
||||
return Object.keys(root.appRules).map(appId => ({
|
||||
id: appId,
|
||||
name: remembered[appId]?.name || appId
|
||||
name: root.applicationLabel(appId, entries, remembered)
|
||||
})).sort((a, b) => a.name.localeCompare(b.name));
|
||||
}
|
||||
|
||||
@@ -74,11 +82,16 @@ Singleton {
|
||||
|
||||
readonly property bool hasNotifications: root.history.length > 0
|
||||
|
||||
function notificationAppId(notification: Notification): string {
|
||||
function notificationAppId(notification: var): string {
|
||||
const desktopEntry = String(notification.desktopEntry ?? "").trim();
|
||||
return desktopEntry || String(notification.appName ?? "").trim() || "Notifications";
|
||||
}
|
||||
|
||||
function applicationLabel(appId: string, entries: var, remembered: var): string {
|
||||
const entry = DesktopEntries.byId(appId) || DesktopEntries.heuristicLookup(appId);
|
||||
return entry?.name || remembered[appId]?.name || appId;
|
||||
}
|
||||
|
||||
function normalizedAppRule(rule: var): var {
|
||||
const source = rule && typeof rule === "object" && !Array.isArray(rule) ? rule : {};
|
||||
return {
|
||||
@@ -106,14 +119,14 @@ Singleton {
|
||||
showContentOnLockScreen: patch.showContentOnLockScreen === undefined ? current.showContentOnLockScreen : patch.showContentOnLockScreen === true
|
||||
};
|
||||
|
||||
if (DesktopPreferences.set("notificationAppRules", next))
|
||||
if (root.appRulesSchemaAvailable && DesktopPreferences.set("notificationAppRules", next))
|
||||
root.fallbackAppRules = {};
|
||||
else
|
||||
root.fallbackAppRules = next;
|
||||
return true;
|
||||
}
|
||||
|
||||
function rememberApplication(notification: Notification): string {
|
||||
function rememberApplication(notification: var): string {
|
||||
const appId = root.notificationAppId(notification);
|
||||
const next = Object.assign({}, root.rememberedApplications);
|
||||
next[appId] = {
|
||||
@@ -128,12 +141,12 @@ Singleton {
|
||||
|
||||
// These policy getters deliberately accept Notification objects, so a lock
|
||||
// screen can use the same source of truth without duplicating app matching.
|
||||
function shouldShowOnLockScreen(notification: Notification): bool {
|
||||
function shouldShowOnLockScreen(notification: var): bool {
|
||||
const rule = root.appRule(root.notificationAppId(notification));
|
||||
return rule.enabled && rule.showOnLockScreen;
|
||||
}
|
||||
|
||||
function shouldShowContentOnLockScreen(notification: Notification): bool {
|
||||
function shouldShowContentOnLockScreen(notification: var): bool {
|
||||
const rule = root.appRule(root.notificationAppId(notification));
|
||||
return rule.enabled && rule.showOnLockScreen && rule.showContentOnLockScreen;
|
||||
}
|
||||
@@ -174,7 +187,10 @@ Singleton {
|
||||
actionIconsSupported: true
|
||||
inlineReplySupported: true
|
||||
|
||||
onNotification: notification => {
|
||||
onNotification: notification => root.handleNotification(notification)
|
||||
}
|
||||
|
||||
function handleNotification(notification: var): void {
|
||||
// Replayed from before a shell reload. Letting these through would
|
||||
// re-toast and re-list everything on every edit, so they are left
|
||||
// untracked and allowed to die.
|
||||
@@ -201,12 +217,11 @@ Singleton {
|
||||
|
||||
if (!root.doNotDisturb)
|
||||
root.popups = [notification].concat(root.popups);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Mutation ────────────────────────────────────────────────────────────
|
||||
|
||||
function pushHistory(n: Notification): void {
|
||||
function pushHistory(n: var): void {
|
||||
const next = [n].concat(root.history);
|
||||
|
||||
// Anything past the cap is released, otherwise it stays tracked
|
||||
@@ -259,7 +274,7 @@ Singleton {
|
||||
|
||||
// Called from the `closed` signal — the object is on its way out, so this
|
||||
// only ever removes references, never touches the notification.
|
||||
function forget(n: Notification): void {
|
||||
function forget(n: var): void {
|
||||
delete root.arrivals[n.id];
|
||||
if (root.history.indexOf(n) !== -1)
|
||||
root.history = root.history.filter(x => x !== n);
|
||||
|
||||
Reference in New Issue
Block a user