From 3a80bbd70349c3392ef211ad5b0bd232d35703a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Wed, 26 Aug 2026 12:46:14 -0700 Subject: [PATCH 1/7] AppEntry: don't call clear all twice --- src/Widgets/AppEntry.vala | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Widgets/AppEntry.vala b/src/Widgets/AppEntry.vala index ef115638..d41dbcd9 100644 --- a/src/Widgets/AppEntry.vala +++ b/src/Widgets/AppEntry.vala @@ -107,7 +107,6 @@ public class Notifications.AppEntry : Gtk.ListBoxRow { clear_btn_entry.clicked.connect (() => { clear_btn_image.add_css_class ("active"); - clear_all_notification_entries (); GLib.Timeout.add (600, () => { clear (); // Causes notification list to destroy this app entry after clearing its notification entries return GLib.Source.REMOVE; From 6a235dd10e1fc41ed61522dabbf2378370bc3455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Wed, 26 Aug 2026 13:24:41 -0700 Subject: [PATCH 2/7] Rest of the owl --- src/Indicator.vala | 14 ++++------- src/Widgets/AppEntry.vala | 37 +-------------------------- src/Widgets/NotificationsList.vala | 40 +++++++++++++++++++++++++++--- 3 files changed, 43 insertions(+), 48 deletions(-) diff --git a/src/Indicator.vala b/src/Indicator.vala index fa4c8820..d633aa3c 100644 --- a/src/Indicator.vala +++ b/src/Indicator.vala @@ -173,15 +173,11 @@ public class Notifications.Indicator : Wingpanel.Indicator { } private void on_notification_closed (uint32 id, Notification.CloseReason reason) { - SearchFunc find_entry = (e, i) => { - return i == e.notification.server_id ? 0 : i > e.notification.server_id ? 1 : -1; - }; - - foreach (var app_entry in nlist.app_entries.values) { - unowned var node = app_entry.app_notifications.search (id, find_entry); - if (node != null) { - node.data.notification.server_id = 0; // Notification is now outdated - node.data.clear (); + for (int i = 0; i < nlist.list_store.n_items; i++) { + var entry = (NotificationEntry) nlist.list_store.get_item (i); + if (id == entry.notification.server_id) { + entry.notification.server_id = 0; // Notification is now outdated + entry.clear (); return; } } diff --git a/src/Widgets/AppEntry.vala b/src/Widgets/AppEntry.vala index d41dbcd9..558745b9 100644 --- a/src/Widgets/AppEntry.vala +++ b/src/Widgets/AppEntry.vala @@ -20,13 +20,12 @@ public class Notifications.AppEntry : Gtk.ListBoxRow { public string app_id { get; private set; } public AppInfo? app_info { get; construct; default = null; } - public List app_notifications; private static Gtk.CssProvider provider; private static Settings settings; private static HashTable headers; - private Gtk.ToggleButton expander; + public Gtk.ToggleButton expander { get; private set; } static construct { provider = new Gtk.CssProvider (); @@ -46,8 +45,6 @@ public class Notifications.AppEntry : Gtk.ListBoxRow { } construct { - app_notifications = new List (); - unowned string name; if (app_info != null) { app_id = app_info.get_id (); @@ -118,36 +115,4 @@ public class Notifications.AppEntry : Gtk.ListBoxRow { return true; }); } - - public void add_notification_entry (NotificationEntry entry) { - app_notifications.prepend (entry); - entry.clear.connect (remove_notification_entry); - - expander.bind_property ("active", entry.revealer, "reveal-child", SYNC_CREATE); - } - - public void remove_notification_entry (NotificationEntry entry) { - app_notifications.remove (entry); - entry.dismiss (); - - Session.get_instance ().remove_notification (entry.notification); - if (app_notifications.length () == 0) { - if (headers.remove (app_id)) { - settings.set_value ("headers", headers); - } - - clear (); - } - } - - public void clear_all_notification_entries () { - Notification[] to_remove = {}; - app_notifications.@foreach ((entry) => { - entry.dismiss (); - to_remove += entry.notification; - }); - - app_notifications = new List (); - Session.get_instance ().remove_notifications (to_remove); - } } diff --git a/src/Widgets/NotificationsList.vala b/src/Widgets/NotificationsList.vala index 4f60b7b2..77836a08 100644 --- a/src/Widgets/NotificationsList.vala +++ b/src/Widgets/NotificationsList.vala @@ -25,7 +25,7 @@ public class Notifications.NotificationsList : Granite.Bin { private GLib.HashTable app_datetime; public Gee.HashMap app_entries { get; private set; } - private ListStore list_store; + public ListStore list_store { get; private set; } construct { app_entries = new Gee.HashMap (); @@ -107,13 +107,31 @@ public class Notifications.NotificationsList : Granite.Bin { app_entries[row_app_id] = app_entry; } - app_entry.add_notification_entry (row_entry); + app_entry.expander.bind_property ("active", row_entry.revealer, "reveal-child", SYNC_CREATE); + row_entry.clear.connect (() => { + int nofication_entries = 0; + for (int i = 0; i < list_store.n_items; i++) { + var entry = (NotificationEntry) list_store.get_item (i); + if (entry.notification.desktop_id == row_app_id) { + nofication_entries++; + } + } + + if (nofication_entries == 0) { + clear_app_entry (app_entry); + } + }); row.set_header (app_entries[row_app_id]); } public async void add_entry (Notification notification) { var entry = new NotificationEntry (notification); + entry.clear.connect (() => { + entry.dismiss (); + Session.get_instance ().remove_notification (notification); + }); + list_store.insert_sorted (entry, sort_func); unowned GLib.DateTime? time = app_datetime[notification.desktop_id]; @@ -145,7 +163,23 @@ public class Notifications.NotificationsList : Granite.Bin { private void clear_app_entry (AppEntry app_entry) { app_entry.clear.disconnect (clear_app_entry); app_entries.unset (app_entry.app_id); - app_entry.clear_all_notification_entries (); + + var settings = new Settings ("io.elementary.panel.notifications"); + var headers = (HashTable) settings.get_value ("headers"); + if (headers.remove (app_entry.app_id)) { + settings.set_value ("headers", headers); + } + + Notification[] to_remove = {}; + for (int i = 0; i < list_store.n_items; i++) { + var entry = (NotificationEntry) list_store.get_item (i); + if (entry.notification.desktop_id == app_entry.app_id) { + entry.dismiss (); + to_remove += entry.notification; + } + } + + Session.get_instance ().remove_notifications (to_remove); if (app_entries.size == 0) { Session.get_instance ().clear (); From 346dea6e4b94d0df943d2158f812b50639507b04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Wed, 26 Aug 2026 13:30:23 -0700 Subject: [PATCH 3/7] fix typo --- src/Widgets/NotificationsList.vala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Widgets/NotificationsList.vala b/src/Widgets/NotificationsList.vala index 77836a08..dfa6d7e6 100644 --- a/src/Widgets/NotificationsList.vala +++ b/src/Widgets/NotificationsList.vala @@ -110,15 +110,15 @@ public class Notifications.NotificationsList : Granite.Bin { app_entry.expander.bind_property ("active", row_entry.revealer, "reveal-child", SYNC_CREATE); row_entry.clear.connect (() => { - int nofication_entries = 0; + int entries = 0; for (int i = 0; i < list_store.n_items; i++) { var entry = (NotificationEntry) list_store.get_item (i); if (entry.notification.desktop_id == row_app_id) { - nofication_entries++; + entries++; } } - if (nofication_entries == 0) { + if (entries == 0) { clear_app_entry (app_entry); } }); From dd3c02ee2c8bf9920723bcfb11cb9c87d08e8ac7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Fri, 28 Aug 2026 11:01:19 -0700 Subject: [PATCH 4/7] Remove expander bind --- src/Widgets/AppEntry.vala | 2 +- src/Widgets/NotificationsList.vala | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Widgets/AppEntry.vala b/src/Widgets/AppEntry.vala index 558745b9..d475fd88 100644 --- a/src/Widgets/AppEntry.vala +++ b/src/Widgets/AppEntry.vala @@ -25,7 +25,7 @@ public class Notifications.AppEntry : Gtk.ListBoxRow { private static Settings settings; private static HashTable headers; - public Gtk.ToggleButton expander { get; private set; } + private Gtk.ToggleButton expander; static construct { provider = new Gtk.CssProvider (); diff --git a/src/Widgets/NotificationsList.vala b/src/Widgets/NotificationsList.vala index 04762e97..6df9868c 100644 --- a/src/Widgets/NotificationsList.vala +++ b/src/Widgets/NotificationsList.vala @@ -112,8 +112,6 @@ public class Notifications.NotificationsList : Granite.Bin { app_entries[row_app_id] = app_entry; } - app_entry.expander.bind_property ("active", row_entry.revealer, "reveal-child", SYNC_CREATE); - row_entry.clear.connect (() => { int entries = 0; for (int i = 0; i < list_store.n_items; i++) { From 7106db61999968088dc6e57fec2b6b527e491f0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Fri, 28 Aug 2026 11:07:59 -0700 Subject: [PATCH 5/7] handle clear app entry in clear --- src/Widgets/NotificationsList.vala | 42 ++++++++++++++++++------------ 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/Widgets/NotificationsList.vala b/src/Widgets/NotificationsList.vala index 6df9868c..954735c0 100644 --- a/src/Widgets/NotificationsList.vala +++ b/src/Widgets/NotificationsList.vala @@ -112,28 +112,12 @@ public class Notifications.NotificationsList : Granite.Bin { app_entries[row_app_id] = app_entry; } - row_entry.clear.connect (() => { - int entries = 0; - for (int i = 0; i < list_store.n_items; i++) { - var entry = (NotificationEntry) list_store.get_item (i); - if (entry.notification.desktop_id == row_app_id) { - entries++; - } - } - - if (entries == 0) { - clear_app_entry (app_entry); - } - }); row.set_header (app_entries[row_app_id]); } public async void add_entry (Notification notification) { var entry = new NotificationEntry (notification); - entry.clear.connect (() => { - entry.dismiss (); - Session.get_instance ().remove_notification (notification); - }); + entry.clear.connect (clear_notification_entry); list_store.insert_sorted (entry, sort_func); @@ -184,6 +168,30 @@ public class Notifications.NotificationsList : Granite.Bin { } } + private void clear_notification_entry (NotificationEntry entry) { + entry.dismiss (); + Session.get_instance ().remove_notification (entry.notification); + + int entries = 0; + for (int i = 0; i < list_store.n_items; i++) { + var notification_entry = (NotificationEntry) list_store.get_item (i); + if (notification_entry.notification.desktop_id == entry.notification.desktop_id) { + entries++; + } + } + + if (entries == 0) { + var iter = app_entries.map_iterator (); + while (iter.next ()) { + var app_entry = iter.get_value (); + if (app_entry.app_id == entry.notification.desktop_id) { + clear_app_entry (app_entry); + return; + } + } + } + } + private void on_row_activated (Gtk.ListBoxRow row) { if (row is NotificationEntry) { unowned var notification_entry = (NotificationEntry) row; From e6ac8d45cef603062a865c3e792bf159224532fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Fri, 28 Aug 2026 11:14:10 -0700 Subject: [PATCH 6/7] this is a map lol --- src/Widgets/NotificationsList.vala | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/Widgets/NotificationsList.vala b/src/Widgets/NotificationsList.vala index 954735c0..9fbff276 100644 --- a/src/Widgets/NotificationsList.vala +++ b/src/Widgets/NotificationsList.vala @@ -180,15 +180,8 @@ public class Notifications.NotificationsList : Granite.Bin { } } - if (entries == 0) { - var iter = app_entries.map_iterator (); - while (iter.next ()) { - var app_entry = iter.get_value (); - if (app_entry.app_id == entry.notification.desktop_id) { - clear_app_entry (app_entry); - return; - } - } + if (entries == 0 && app_entries[entry.notification.desktop_id] != null) { + clear_app_entry (app_entries[entry.notification.desktop_id]); } } From df4ae72a29973045bc28c61c285176de0755fe6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Fri, 28 Aug 2026 12:10:23 -0700 Subject: [PATCH 7/7] handle app_entry unparent internally --- src/Widgets/AppEntry.vala | 12 ++++++++++++ src/Widgets/NotificationsList.vala | 12 ------------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Widgets/AppEntry.vala b/src/Widgets/AppEntry.vala index d475fd88..77c87c98 100644 --- a/src/Widgets/AppEntry.vala +++ b/src/Widgets/AppEntry.vala @@ -114,5 +114,17 @@ public class Notifications.AppEntry : Gtk.ListBoxRow { targetval = (bool) srcval ? _("Show less") : _("Show more"); return true; }); + + notify["parent"].connect (() => { + if (parent != null) { + return; + } + + if (headers.remove (app_id)) { + settings.set_value ("headers", headers); + } + + clear (); + }); } } diff --git a/src/Widgets/NotificationsList.vala b/src/Widgets/NotificationsList.vala index 9fbff276..ab99c14e 100644 --- a/src/Widgets/NotificationsList.vala +++ b/src/Widgets/NotificationsList.vala @@ -171,18 +171,6 @@ public class Notifications.NotificationsList : Granite.Bin { private void clear_notification_entry (NotificationEntry entry) { entry.dismiss (); Session.get_instance ().remove_notification (entry.notification); - - int entries = 0; - for (int i = 0; i < list_store.n_items; i++) { - var notification_entry = (NotificationEntry) list_store.get_item (i); - if (notification_entry.notification.desktop_id == entry.notification.desktop_id) { - entries++; - } - } - - if (entries == 0 && app_entries[entry.notification.desktop_id] != null) { - clear_app_entry (app_entries[entry.notification.desktop_id]); - } } private void on_row_activated (Gtk.ListBoxRow row) {