1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-04-03 20:32:07 -04:00

fix(notifications): Allow duplicate history entry management w/unique IDs & source tracking

This commit is contained in:
purian23
2026-03-01 19:39:00 -05:00
parent 39a43f4de5
commit 1bf66ee482

View File

@@ -19,6 +19,7 @@ Singleton {
readonly property string historyFile: Paths.strip(Paths.cache) + "/notification_history.json" readonly property string historyFile: Paths.strip(Paths.cache) + "/notification_history.json"
readonly property string imageCacheDir: Paths.strip(Paths.cache) + "/notification_images" readonly property string imageCacheDir: Paths.strip(Paths.cache) + "/notification_images"
property bool historyLoaded: false property bool historyLoaded: false
property int historyEntryCounter: 0
property list<NotifWrapper> notificationQueue: [] property list<NotifWrapper> notificationQueue: []
property list<NotifWrapper> visibleNotifications: [] property list<NotifWrapper> visibleNotifications: []
@@ -73,6 +74,12 @@ Singleton {
onTriggered: root.performSaveHistory() onTriggered: root.performSaveHistory()
} }
function _makeHistoryEntryId(sourceId, timestamp) {
historyEntryCounter += 1;
const safeSource = sourceId && sourceId !== "" ? sourceId : "notification";
return safeSource + "_" + (timestamp || Date.now()) + "_" + historyEntryCounter;
}
function getImageCachePath(wrapper) { function getImageCachePath(wrapper) {
const ts = wrapper.time ? wrapper.time.getTime() : Date.now(); const ts = wrapper.time ? wrapper.time.getTime() : Date.now();
const id = wrapper.notification?.id?.toString() || "0"; const id = wrapper.notification?.id?.toString() || "0";
@@ -80,12 +87,13 @@ Singleton {
} }
function updateHistoryImage(wrapperId, imagePath) { function updateHistoryImage(wrapperId, imagePath) {
const idx = historyList.findIndex(n => n.id === wrapperId); const idx = historyList.findIndex(n => n.sourceNotificationId === wrapperId || n.id === wrapperId);
if (idx < 0) if (idx < 0)
return; return;
const item = historyList[idx]; const item = historyList[idx];
const updated = { const updated = {
id: item.id, id: item.id,
sourceNotificationId: item.sourceNotificationId || item.id,
summary: item.summary, summary: item.summary,
body: item.body, body: item.body,
htmlBody: item.htmlBody, htmlBody: item.htmlBody,
@@ -113,8 +121,11 @@ Singleton {
} else if (imageUrl && !imageUrl.startsWith("image://qsimage/")) { } else if (imageUrl && !imageUrl.startsWith("image://qsimage/")) {
persistableImage = imageUrl; persistableImage = imageUrl;
} }
const sourceNotificationId = wrapper.notification?.id?.toString() || "";
const timestamp = wrapper.time.getTime();
const data = { const data = {
id: wrapper.notification?.id?.toString() || Date.now().toString(), id: _makeHistoryEntryId(sourceNotificationId, timestamp),
sourceNotificationId: sourceNotificationId,
summary: wrapper.summary || "", summary: wrapper.summary || "",
body: wrapper.body || "", body: wrapper.body || "",
htmlBody: wrapper.htmlBody || wrapper.body || "", htmlBody: wrapper.htmlBody || wrapper.body || "",
@@ -122,7 +133,7 @@ Singleton {
appIcon: wrapper.appIcon || "", appIcon: wrapper.appIcon || "",
image: persistableImage, image: persistableImage,
urgency: urg, urgency: urg,
timestamp: wrapper.time.getTime(), timestamp: timestamp,
desktopEntry: wrapper.desktopEntry || "" desktopEntry: wrapper.desktopEntry || ""
}; };
let newList = [data, ...historyList]; let newList = [data, ...historyList];
@@ -152,6 +163,8 @@ Singleton {
const now = Date.now(); const now = Date.now();
const maxAgeMs = maxAgeDays > 0 ? maxAgeDays * 24 * 60 * 60 * 1000 : 0; const maxAgeMs = maxAgeDays > 0 ? maxAgeDays * 24 * 60 * 60 * 1000 : 0;
const loaded = []; const loaded = [];
const seenIds = {};
let needsRewrite = false;
for (const item of historyAdapter.notifications || []) { for (const item of historyAdapter.notifications || []) {
if (maxAgeMs > 0 && (now - item.timestamp) > maxAgeMs) if (maxAgeMs > 0 && (now - item.timestamp) > maxAgeMs)
@@ -162,8 +175,18 @@ Singleton {
if (htmlBody) { if (htmlBody) {
htmlBody = htmlBody.replace(/<img\b[^>]*>/gi, ""); htmlBody = htmlBody.replace(/<img\b[^>]*>/gi, "");
} }
const sourceNotificationId = (item.sourceNotificationId || item.id || "").toString();
let historyId = (item.id || "").toString();
if (!historyId || seenIds[historyId]) {
historyId = _makeHistoryEntryId(sourceNotificationId, item.timestamp || now);
needsRewrite = true;
}
if (!item.sourceNotificationId)
needsRewrite = true;
seenIds[historyId] = true;
loaded.push({ loaded.push({
id: item.id || "", id: historyId,
sourceNotificationId: sourceNotificationId,
summary: item.summary || "", summary: item.summary || "",
body: body, body: body,
htmlBody: htmlBody, htmlBody: htmlBody,
@@ -177,7 +200,7 @@ Singleton {
} }
historyList = loaded; historyList = loaded;
historyLoaded = true; historyLoaded = true;
if (maxAgeMs > 0 && loaded.length !== (historyAdapter.notifications || []).length) if ((maxAgeMs > 0 && loaded.length !== (historyAdapter.notifications || []).length) || needsRewrite)
saveHistory(); saveHistory();
} catch (e) { } catch (e) {
console.warn("NotificationService: load history failed:", e); console.warn("NotificationService: load history failed:", e);