From a4e7ec15c6e3c16a4e9f0b8d13ffc1fae399a3b3 Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Thu, 3 Mar 2022 18:25:05 +0000 Subject: [PATCH 1/7] Load notifications more efficiently in a separate thread --- src/Indicator.vala | 51 ++++++++++++++++++------------ src/Services/Session.vala | 22 ++++++++++--- src/Widgets/NotificationsList.vala | 4 +-- 3 files changed, 50 insertions(+), 27 deletions(-) diff --git a/src/Indicator.vala b/src/Indicator.vala index 0f23a457..502b1285 100644 --- a/src/Indicator.vala +++ b/src/Indicator.vala @@ -49,11 +49,7 @@ public class Notifications.Indicator : Wingpanel.Indicator { dynamic_icon.active = true; nlist = new NotificationsList (); - - var previous_session = Session.get_instance ().get_session_notifications (); - previous_session.foreach ((notification) => { - nlist.add_entry (notification); - }); + get_session_notifications.begin (); Gtk.IconTheme.get_default ().add_resource_path ("/io/elementary/wingpanel/notifications"); @@ -68,28 +64,43 @@ public class Notifications.Indicator : Wingpanel.Indicator { monitor.notification_received.connect (on_notification_received); monitor.notification_closed.connect (on_notification_closed); - dynamic_icon.button_press_event.connect ((e) => { - if (e.button == Gdk.BUTTON_MIDDLE) { - notify_settings.set_boolean ("do-not-disturb", !notify_settings.get_boolean ("do-not-disturb")); - return Gdk.EVENT_STOP; - } - - return Gdk.EVENT_PROPAGATE; - }); - notify_settings.changed["do-not-disturb"].connect (() => { set_display_icon_name (); }); - - nlist.add.connect (set_display_icon_name); - nlist.remove.connect (set_display_icon_name); - - set_display_icon_name (); } return dynamic_icon; } + private async void get_session_notifications () throws ThreadError { + dynamic_icon.tooltip_markup = _("Updating session notifications. Please wait"); + dynamic_icon.get_style_context ().add_class ("disabled"); + + SourceFunc callback = get_session_notifications.callback; + ThreadFunc run = () => { + var previous_session = Session.get_instance ().get_session_notifications (); + previous_session.foreach ((notification) => { + nlist.add_entry (notification, false); // Do not need to write back to file + }); + Idle.add ((owned)callback); + return true; + }; + new Thread ("load-notifications", (owned)run); + yield; + + nlist.add.connect (set_display_icon_name); + nlist.remove.connect (set_display_icon_name); + dynamic_icon.button_press_event.connect ((e) => { + if (e.button == Gdk.BUTTON_MIDDLE) { + notify_settings.set_boolean ("do-not-disturb", !notify_settings.get_boolean ("do-not-disturb")); + return Gdk.EVENT_STOP; + } + + return Gdk.EVENT_PROPAGATE; + }); + set_display_icon_name (); + } + public override Gtk.Widget? get_widget () { if (main_box == null) { var not_disturb_switch = new Granite.SwitchModelButton (_("Do Not Disturb")); @@ -216,7 +227,7 @@ public class Notifications.Indicator : Wingpanel.Indicator { } private void update_tooltip () { - uint number_of_notifications = Session.get_instance ().get_session_notifications ().length (); + uint number_of_notifications = Session.get_instance ().count_notifications (); int number_of_apps = nlist.app_entries.size; string description; diff --git a/src/Services/Session.vala b/src/Services/Session.vala index 053b7d41..22e90ac0 100644 --- a/src/Services/Session.vala +++ b/src/Services/Session.vala @@ -78,7 +78,7 @@ public class Notifications.Session : GLib.Object { key.get_string (group, SENDER_KEY), key.get_boolean (group, HAS_TEMP_FILE_KEY) ); - list.append (notification); + list.prepend (notification); } } catch (KeyFileError e) { warning (e.message); @@ -86,10 +86,20 @@ public class Notifications.Session : GLib.Object { warning (e.message); } + list.reverse (); return list; } - public void add_notification (Notification notification) { + public uint count_notifications () { + uint count = 0; + foreach (unowned string group in key.get_groups ()) { + count++; + } + + return count; + } + + public void add_notification (Notification notification, bool write_file = true) { string id = notification.id.to_string (); key.set_int64 (id, UNIX_TIME_KEY, notification.timestamp.to_unix ()); key.set_string (id, APP_ICON_KEY, notification.app_icon); @@ -103,10 +113,12 @@ public class Notifications.Session : GLib.Object { key.set_uint64 (id, REPLACES_ID_KEY, notification.replaces_id); key.set_boolean (id, HAS_TEMP_FILE_KEY, notification.has_temp_file); - write_contents (); + if (write_file) { + write_contents (); + } } - public void remove_notification (Notification notification) { + public void remove_notification (Notification notification, bool write_file = true) { try { if (notification.has_temp_file) { var file = File.new_for_path (notification.image_path); @@ -126,7 +138,7 @@ public class Notifications.Session : GLib.Object { public void remove_notifications (Notification[] notifications) { foreach (unowned var notification in notifications) { - remove_notification (notification); + remove_notification (notification, false); } write_contents (); diff --git a/src/Widgets/NotificationsList.vala b/src/Widgets/NotificationsList.vala index f1f8a04a..0b452096 100644 --- a/src/Widgets/NotificationsList.vala +++ b/src/Widgets/NotificationsList.vala @@ -46,7 +46,7 @@ public class Notifications.NotificationsList : Gtk.ListBox { row_activated.connect (on_row_activated); } - public void add_entry (Notification notification) { + public void add_entry (Notification notification, bool write_file = true) { var entry = new NotificationEntry (notification); if (app_entries[notification.desktop_id] != null) { @@ -71,7 +71,7 @@ public class Notifications.NotificationsList : Gtk.ListBox { show_all (); - Session.get_instance ().add_notification (notification); + Session.get_instance ().add_notification (notification, write_file); } public void clear_all () { From 639498eb3b9e7ac19c7d476986f41616769d5508 Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Sun, 6 Mar 2022 16:31:49 +0000 Subject: [PATCH 2/7] Add session notifications in Idle loop instead of thread --- src/Indicator.vala | 51 ++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/src/Indicator.vala b/src/Indicator.vala index 502b1285..ca89f785 100644 --- a/src/Indicator.vala +++ b/src/Indicator.vala @@ -49,7 +49,6 @@ public class Notifications.Indicator : Wingpanel.Indicator { dynamic_icon.active = true; nlist = new NotificationsList (); - get_session_notifications.begin (); Gtk.IconTheme.get_default ().add_resource_path ("/io/elementary/wingpanel/notifications"); @@ -67,38 +66,43 @@ public class Notifications.Indicator : Wingpanel.Indicator { notify_settings.changed["do-not-disturb"].connect (() => { set_display_icon_name (); }); + + dynamic_icon.button_press_event.connect ((e) => { + if (e.button == Gdk.BUTTON_MIDDLE) { + notify_settings.set_boolean ("do-not-disturb", !notify_settings.get_boolean ("do-not-disturb")); + return Gdk.EVENT_STOP; + } + + return Gdk.EVENT_PROPAGATE; + }); + + + get_session_notifications (); } return dynamic_icon; } - private async void get_session_notifications () throws ThreadError { + private List previous_session = null; + private void get_session_notifications () { dynamic_icon.tooltip_markup = _("Updating session notifications. Please wait"); dynamic_icon.get_style_context ().add_class ("disabled"); - - SourceFunc callback = get_session_notifications.callback; - ThreadFunc run = () => { - var previous_session = Session.get_instance ().get_session_notifications (); - previous_session.foreach ((notification) => { + previous_session = Session.get_instance ().get_session_notifications (); + unowned var list = previous_session; + Idle.add (() => { + if (list != null && list.data != null) { + var notification = list.data; nlist.add_entry (notification, false); // Do not need to write back to file - }); - Idle.add ((owned)callback); - return true; - }; - new Thread ("load-notifications", (owned)run); - yield; - - nlist.add.connect (set_display_icon_name); - nlist.remove.connect (set_display_icon_name); - dynamic_icon.button_press_event.connect ((e) => { - if (e.button == Gdk.BUTTON_MIDDLE) { - notify_settings.set_boolean ("do-not-disturb", !notify_settings.get_boolean ("do-not-disturb")); - return Gdk.EVENT_STOP; + list = list.next; + return Source.CONTINUE; + } else { + nlist.add.connect (set_display_icon_name); + nlist.remove.connect (set_display_icon_name); + set_display_icon_name (); + previous_session = null; + return Source.REMOVE; } - - return Gdk.EVENT_PROPAGATE; }); - set_display_icon_name (); } public override Gtk.Widget? get_widget () { @@ -229,7 +233,6 @@ public class Notifications.Indicator : Wingpanel.Indicator { private void update_tooltip () { uint number_of_notifications = Session.get_instance ().count_notifications (); int number_of_apps = nlist.app_entries.size; - string description; string accel_label; From 051cd8b18e7ebf56edded955cb4482ff059e03ae Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Mon, 7 Mar 2022 15:08:13 +0000 Subject: [PATCH 3/7] Add appdata for next release --- data/notifications.appdata.xml.in | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/data/notifications.appdata.xml.in b/data/notifications.appdata.xml.in index 741a8ca8..c6f5eff0 100644 --- a/data/notifications.appdata.xml.in +++ b/data/notifications.appdata.xml.in @@ -7,6 +7,18 @@ See missed notifications in the panel preferences-system-notifications + + +

Fixes:

+
    +
  • Reduce delay in initially showing wingpanel when there is a large number of notifications
  • +
+

Minor updates:

+
    +
  • Updated translations
  • +
+
+

Fixes:

From 49403cb9e41aba917bf5da5d942cd7ab81947139 Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Tue, 7 Jun 2022 17:35:06 +0100 Subject: [PATCH 4/7] Load and add notifications async; throttle writes --- src/Indicator.vala | 44 ++++++++++++------------------ src/Services/Session.vala | 18 +++++++++--- src/Widgets/NotificationsList.vala | 9 ++++-- 3 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/Indicator.vala b/src/Indicator.vala index ca89f785..5319fde2 100644 --- a/src/Indicator.vala +++ b/src/Indicator.vala @@ -27,6 +27,7 @@ public class Notifications.Indicator : Wingpanel.Indicator { private Gtk.ModelButton clear_all_btn; private Gtk.Spinner? dynamic_icon = null; private NotificationsList nlist; + private List previous_session = null; public Indicator () { Object ( @@ -55,10 +56,6 @@ public class Notifications.Indicator : Wingpanel.Indicator { var provider = new Gtk.CssProvider (); provider.load_from_resource ("io/elementary/wingpanel/notifications/indicator.css"); - unowned var dynamic_icon_style_context = dynamic_icon.get_style_context (); - dynamic_icon_style_context.add_class ("notification-icon"); - dynamic_icon_style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - var monitor = NotificationMonitor.get_instance (); monitor.notification_received.connect (on_notification_received); monitor.notification_closed.connect (on_notification_closed); @@ -76,33 +73,28 @@ public class Notifications.Indicator : Wingpanel.Indicator { return Gdk.EVENT_PROPAGATE; }); + dynamic_icon.tooltip_markup = _("Updating session notifications. Please wait"); + dynamic_icon.get_style_context ().add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + previous_session = Session.get_instance ().get_session_notifications (); + Timeout.add (2000, () => { // Do not block animated drawing of wingpanel + load_session_notifications.begin (() => { // load asynchromously so spinner continues to rotate + dynamic_icon.get_style_context ().add_class ("notification-icon"); + set_display_icon_name (); + nlist.add.connect (set_display_icon_name); + nlist.remove.connect (set_display_icon_name); + }); - get_session_notifications (); + return Source.REMOVE; + }); } return dynamic_icon; } - private List previous_session = null; - private void get_session_notifications () { - dynamic_icon.tooltip_markup = _("Updating session notifications. Please wait"); - dynamic_icon.get_style_context ().add_class ("disabled"); - previous_session = Session.get_instance ().get_session_notifications (); - unowned var list = previous_session; - Idle.add (() => { - if (list != null && list.data != null) { - var notification = list.data; - nlist.add_entry (notification, false); // Do not need to write back to file - list = list.next; - return Source.CONTINUE; - } else { - nlist.add.connect (set_display_icon_name); - nlist.remove.connect (set_display_icon_name); - set_display_icon_name (); - previous_session = null; - return Source.REMOVE; - } - }); + private async void load_session_notifications () { + foreach (var notification in previous_session) { + yield nlist.add_entry (notification, false); // This is slow as NotificationEntry is complex + } } public override Gtk.Widget? get_widget () { @@ -185,7 +177,7 @@ public class Notifications.Indicator : Wingpanel.Indicator { } if (app_settings == null || app_settings.get_boolean (REMEMBER_KEY)) { - nlist.add_entry (notification); + nlist.add_entry.begin (notification, true); } set_display_icon_name (); diff --git a/src/Services/Session.vala b/src/Services/Session.vala index c55b4dd6..57bd5e5d 100644 --- a/src/Services/Session.vala +++ b/src/Services/Session.vala @@ -162,11 +162,21 @@ public class Notifications.Session : GLib.Object { } } + private uint write_timeout_id = 0; private void write_contents () { - try { - FileUtils.set_contents (session_file.get_path (), key.to_data ()); - } catch (FileError e) { - warning (e.message); + if (write_timeout_id > 0) { + Source.remove (write_timeout_id); } + + write_timeout_id = Timeout.add (1000, () => { + write_timeout_id = 0; + try { + FileUtils.set_contents (session_file.get_path (), key.to_data ()); + } catch (FileError e) { + warning (e.message); + } + + return Source.REMOVE; + }); } } diff --git a/src/Widgets/NotificationsList.vala b/src/Widgets/NotificationsList.vala index beef513d..58a824ef 100644 --- a/src/Widgets/NotificationsList.vala +++ b/src/Widgets/NotificationsList.vala @@ -46,7 +46,7 @@ public class Notifications.NotificationsList : Gtk.ListBox { row_activated.connect (on_row_activated); } - public void add_entry (Notification notification, bool write_file = true) { + public async void add_entry (Notification notification, bool add_to_session = true, bool write_file = true) { var entry = new NotificationEntry (notification); if (app_entries[notification.desktop_id] != null) { @@ -71,7 +71,12 @@ public class Notifications.NotificationsList : Gtk.ListBox { show_all (); - Session.get_instance ().add_notification (notification, write_file); + Idle.add (add_entry.callback); + yield; + + if (add_to_session) { // If notification was obtained from session do not write it back + Session.get_instance ().add_notification (notification); + } } public void clear_all () { From 9c2a9e68950593e271894380de43346afab8c96b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Wed, 8 Jun 2022 09:21:06 -0700 Subject: [PATCH 5/7] Update Indicator.vala --- src/Indicator.vala | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Indicator.vala b/src/Indicator.vala index 5319fde2..a17ca53e 100644 --- a/src/Indicator.vala +++ b/src/Indicator.vala @@ -46,16 +46,19 @@ public class Notifications.Indicator : Wingpanel.Indicator { public override Gtk.Widget get_display_widget () { if (dynamic_icon == null) { - dynamic_icon = new Gtk.Spinner (); - dynamic_icon.active = true; - - nlist = new NotificationsList (); - Gtk.IconTheme.get_default ().add_resource_path ("/io/elementary/wingpanel/notifications"); var provider = new Gtk.CssProvider (); provider.load_from_resource ("io/elementary/wingpanel/notifications/indicator.css"); + dynamic_icon = new Gtk.Spinner () { + active = true, + tooltip_markup = _("Updating notifications…") + }; + dynamic_icon.get_style_context ().add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + + nlist = new NotificationsList (); + var monitor = NotificationMonitor.get_instance (); monitor.notification_received.connect (on_notification_received); monitor.notification_closed.connect (on_notification_closed); @@ -73,8 +76,6 @@ public class Notifications.Indicator : Wingpanel.Indicator { return Gdk.EVENT_PROPAGATE; }); - dynamic_icon.tooltip_markup = _("Updating session notifications. Please wait"); - dynamic_icon.get_style_context ().add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); previous_session = Session.get_instance ().get_session_notifications (); Timeout.add (2000, () => { // Do not block animated drawing of wingpanel load_session_notifications.begin (() => { // load asynchromously so spinner continues to rotate From 11e0f4006851c15e80a6dfbab1b4d02be0bf0d52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Wed, 8 Jun 2022 09:23:10 -0700 Subject: [PATCH 6/7] Update Indicator.vala --- src/Indicator.vala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Indicator.vala b/src/Indicator.vala index a17ca53e..12c899dc 100644 --- a/src/Indicator.vala +++ b/src/Indicator.vala @@ -55,7 +55,10 @@ public class Notifications.Indicator : Wingpanel.Indicator { active = true, tooltip_markup = _("Updating notifications…") }; - dynamic_icon.get_style_context ().add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + + unowned var dynamic_icon_context = dynamic_icon.get_style_context (); + dynamic_icon_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + dynamic_icon_context.add_class ("notification-icon"); nlist = new NotificationsList (); @@ -79,7 +82,6 @@ public class Notifications.Indicator : Wingpanel.Indicator { previous_session = Session.get_instance ().get_session_notifications (); Timeout.add (2000, () => { // Do not block animated drawing of wingpanel load_session_notifications.begin (() => { // load asynchromously so spinner continues to rotate - dynamic_icon.get_style_context ().add_class ("notification-icon"); set_display_icon_name (); nlist.add.connect (set_display_icon_name); nlist.remove.connect (set_display_icon_name); From 9152c4d65d17d47bbffbf4e8370d187f79a4456f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Wed, 8 Jun 2022 09:23:41 -0700 Subject: [PATCH 7/7] Update Indicator.vala --- src/Indicator.vala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Indicator.vala b/src/Indicator.vala index 12c899dc..073785eb 100644 --- a/src/Indicator.vala +++ b/src/Indicator.vala @@ -56,9 +56,9 @@ public class Notifications.Indicator : Wingpanel.Indicator { tooltip_markup = _("Updating notifications…") }; - unowned var dynamic_icon_context = dynamic_icon.get_style_context (); - dynamic_icon_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - dynamic_icon_context.add_class ("notification-icon"); + unowned var dynamic_icon_style_context = dynamic_icon.get_style_context (); + dynamic_icon_style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + dynamic_icon_style_context.add_class ("notification-icon"); nlist = new NotificationsList ();