Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load notifications without blocking #241

Merged
merged 9 commits into from
Jun 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions data/notifications.appdata.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@
<summary>See missed notifications in the panel</summary>
<icon type="stock">preferences-system-notifications</icon>
<releases>
<release version="6.0.5" date="2021-12-17" urgency="medium">
<description>
<p>Fixes:</p>
<ul>
<li>Reduce delay in initially showing wingpanel when there is a large number of notifications</li>
</ul>
<p>Minor updates:</p>
<ul>
<li>Updated translations</li>
</ul>
</description>
</release>
<release version="6.0.4" date="2021-12-17" urgency="medium">
<description>
<p>Fixes:</p>
Expand Down
51 changes: 30 additions & 21 deletions src/Indicator.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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<Notification> previous_session = null;

public Indicator () {
Object (
Expand All @@ -45,29 +46,30 @@ 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 ();

var previous_session = Session.get_instance ().get_session_notifications ();
previous_session.foreach ((notification) => {
nlist.add_entry (notification, false);
});

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…")
};

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);
dynamic_icon_style_context.add_class ("notification-icon");

nlist = new NotificationsList ();

var monitor = NotificationMonitor.get_instance ();
monitor.notification_received.connect (on_notification_received);
monitor.notification_closed.connect (on_notification_closed);

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"));
Expand All @@ -77,19 +79,27 @@ public class Notifications.Indicator : Wingpanel.Indicator {
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);
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
set_display_icon_name ();
nlist.add.connect (set_display_icon_name);
nlist.remove.connect (set_display_icon_name);
});

set_display_icon_name ();
return Source.REMOVE;
});
}

return dynamic_icon;
}

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 () {
if (main_box == null) {
var not_disturb_switch = new Granite.SwitchModelButton (_("Do Not Disturb"));
Expand Down Expand Up @@ -170,7 +180,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 ();
Expand Down Expand Up @@ -216,9 +226,8 @@ 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;
string accel_label;

Expand Down
30 changes: 25 additions & 5 deletions src/Services/Session.vala
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,27 @@ 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);
} catch (FileError e) {
warning (e.message);
}

list.reverse ();
return list;
}

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 ());
Expand Down Expand Up @@ -152,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;
});
}
}
9 changes: 7 additions & 2 deletions src/Widgets/NotificationsList.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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 () {
Expand Down