diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ecc5149f..ce19bc48 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -26,8 +26,8 @@ variables: glib2-devel gmime-devel gnome-online-accounts-devel gtk3-devel iso-codes-devel json-glib-devel itstool libcanberra-devel libgee-devel libhandy-devel - libnotify-devel libsecret-devel libunwind-devel - libxml2-devel libytnef-devel sqlite-devel webkitgtk4-devel + libsecret-devel libunwind-devel libxml2-devel + libytnef-devel sqlite-devel webkitgtk4-devel FEDORA_TEST_DEPS: Xvfb tar xz # Ubuntu packages @@ -37,9 +37,9 @@ variables: libgcr-3-dev libgee-0.8-dev libglib2.0-dev libgmime-2.6-dev libgoa-1.0-dev libgtk-3-dev libhandy-0.0-dev libjson-glib-dev libmessaging-menu-dev - libnotify-dev libsecret-1-dev libsqlite3-dev - libunity-dev libunwind-dev libwebkit2gtk-4.0-dev - libxml2-dev libytnef0-dev + libsecret-1-dev libsqlite3-dev libunity-dev + libunwind-dev libwebkit2gtk-4.0-dev libxml2-dev + libytnef0-dev UBUNTU_TEST_DEPS: xauth xvfb fedora: diff --git a/INSTALL b/INSTALL index 6d322f32..57582719 100644 --- a/INSTALL +++ b/INSTALL @@ -44,9 +44,8 @@ Install them by running this command: desktop-file-utils enchant2-devel folks-devel gcr-devel \ glib2-devel gmime-devel gnome-online-accounts-devel gtk3-devel \ iso-codes-devel json-glib-devel libcanberra-devel \ - libgee-devel libhandy-devel libnotify-devel libsecret-devel \ - libunwind-devel libxml2-devel libytnef-devel sqlite-devel \ - webkitgtk4-devel + libgee-devel libhandy-devel libsecret-devel libunwind-devel \ + libxml2-devel libytnef-devel sqlite-devel webkitgtk4-devel Installing dependencies on Ubuntu/Debian ---------------------------------------- @@ -57,9 +56,8 @@ Install them by running this command: desktop-file-utils iso-codes gettext libcanberra-dev \ libenchant-dev libfolks-dev libgcr-3-dev libgee-0.8-dev \ libglib2.0-dev libgmime-2.6-dev libgoa-1.0-dev libgtk-3-dev \ - libjson-glib-dev libhandy-dev libnotify-dev libsecret-1-dev \ - libsqlite3-dev libunwind-dev libwebkit2gtk-4.0-dev \ - libxml2-dev libytnef0-dev + libjson-glib-dev libhandy-dev libsecret-1-dev libsqlite3-dev \ + libunwind-dev libwebkit2gtk-4.0-dev libxml2-dev libytnef0-dev And for Ubuntu Unity integration: diff --git a/bindings/vapi/libnotify.vapi b/bindings/vapi/libnotify.vapi deleted file mode 100644 index 163cff16..00000000 --- a/bindings/vapi/libnotify.vapi +++ /dev/null @@ -1,73 +0,0 @@ -/* libnotify.vapi generated by vapigen, do not modify. */ - -namespace Notify { - [CCode (cheader_filename = "libnotify/notify.h")] - public class Notification : GLib.Object { - [CCode (has_construct_function = false)] - public Notification (string summary, string? body, string? icon); - public void add_action (string action, string label, owned Notify.ActionCallback callback); - public void clear_actions (); - public void clear_hints (); - public bool close () throws GLib.Error; - public int get_closed_reason (); - public void set_app_name (string app_name); - public void set_category (string category); - public void set_hint (string key, GLib.Variant value); - public void set_hint_byte (string key, uchar value); - public void set_hint_byte_array (string key, uchar[] value, size_t len); - public void set_hint_double (string key, double value); - public void set_hint_int32 (string key, int value); - public void set_hint_string (string key, string value); - public void set_hint_uint32 (string key, uint value); - public void set_icon_from_pixbuf (Gdk.Pixbuf icon); - public void set_image_from_pixbuf (Gdk.Pixbuf pixbuf); - public void set_timeout (int timeout); - public void set_urgency (Notify.Urgency urgency); - public bool show () throws GLib.Error; - public bool update (string summary, string body, string icon); - [NoAccessorMethod] - public string app_name { owned get; set; } - [NoAccessorMethod] - public string body { owned get; set construct; } - public int closed_reason { get; } - [NoAccessorMethod] - public string icon_name { owned get; set construct; } - [NoAccessorMethod] - public int id { get; set construct; } - [NoAccessorMethod] - public string summary { owned get; set construct; } - public virtual signal void closed (); - } - [CCode (cheader_filename = "libnotify/notify.h", cprefix = "NOTIFY_URGENCY_")] - public enum Urgency { - LOW, - NORMAL, - CRITICAL - } - [CCode (cheader_filename = "libnotify/notify.h")] - public delegate void ActionCallback (Notify.Notification notification, string action); - [CCode (cheader_filename = "libnotify/notify.h")] - public const int EXPIRES_DEFAULT; - [CCode (cheader_filename = "libnotify/notify.h")] - public const int EXPIRES_NEVER; - [CCode (cheader_filename = "libnotify/notify.h")] - public const int VERSION_MAJOR; - [CCode (cheader_filename = "libnotify/notify.h")] - public const int VERSION_MICRO; - [CCode (cheader_filename = "libnotify/notify.h")] - public const int VERSION_MINOR; - [CCode (cheader_filename = "libnotify/notify.h")] - public static unowned string get_app_name (); - [CCode (cheader_filename = "libnotify/notify.h")] - public static GLib.List? get_server_caps (); - [CCode (cheader_filename = "libnotify/notify.h")] - public static bool get_server_info (out unowned string ret_name, out unowned string ret_vendor, out unowned string ret_version, out unowned string ret_spec_version); - [CCode (cheader_filename = "libnotify/notify.h")] - public static bool init (string app_name); - [CCode (cheader_filename = "libnotify/notify.h")] - public static bool is_initted (); - [CCode (cheader_filename = "libnotify/notify.h")] - public static void set_app_name (string app_name); - [CCode (cheader_filename = "libnotify/notify.h")] - public static void uninit (); -} diff --git a/meson.build b/meson.build index 81fabb7a..23162d87 100644 --- a/meson.build +++ b/meson.build @@ -69,7 +69,6 @@ json_glib = dependency('json-glib-1.0', version: '>= 1.0') libcanberra = dependency('libcanberra', version: '>= 0.28') libhandy = dependency('libhandy-0.0', version: '>= 0.0.9') libmath = cc.find_library('m') -libnotify = dependency('libnotify', version: '>= 0.7.5') libsecret = dependency('libsecret-1', version: '>= 0.11') libsoup = dependency('libsoup-2.4', version: '>= 2.48') libunwind_dep = dependency( diff --git a/po/POTFILES.in b/po/POTFILES.in index 69c71b39..6025091a 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -80,7 +80,7 @@ src/client/folder-list/folder-list-special-grouping.vala src/client/folder-list/folder-list-tree.vala src/client/notification/in-app-notification.vala src/client/notification/libmessagingmenu.vala -src/client/notification/libnotify.vala +src/client/notification/glib-notification.vala src/client/notification/new-messages-indicator.vala src/client/notification/new-messages-monitor.vala src/client/notification/null-indicator.vala diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala index e9104451..21c5fad7 100644 --- a/src/client/application/geary-controller.vala +++ b/src/client/application/geary-controller.vala @@ -157,7 +157,7 @@ public class GearyController : Geary.BaseObject { private NewMessagesMonitor? new_messages_monitor = null; private NewMessagesIndicator? new_messages_indicator = null; private UnityLauncher? unity_launcher = null; - private Libnotify? libnotify = null; + private GLibNotification? gLibNotification = null; private uint select_folder_timeout_id = 0; private int64 next_folder_select_allowed_usec = 0; private Geary.Nonblocking.Mutex select_folder_mutex = new Geary.Nonblocking.Mutex(); @@ -328,8 +328,7 @@ public class GearyController : Geary.BaseObject { unity_launcher = new UnityLauncher(new_messages_monitor); - this.libnotify = new Libnotify(this.new_messages_monitor); - this.libnotify.invoked.connect(on_libnotify_invoked); + gLibNotification = new GLibNotification(new_messages_monitor); this.main_window.conversation_list_view.grab_focus(); @@ -443,7 +442,7 @@ public class GearyController : Geary.BaseObject { } // Release monitoring early so held resources can be freed up - this.libnotify = null; + this.gLibNotification = null; this.new_messages_indicator = null; this.unity_launcher = null; this.new_messages_monitor.clear_folders(); @@ -703,6 +702,15 @@ public class GearyController : Geary.BaseObject { info_bar.retry.connect(on_retry_problem); this.main_window.show_infobar(info_bar); } + + Geary.ServiceProblemReport? service_report = + report as Geary.ServiceProblemReport; + if (service_report != null && service_report.service.protocol == SMTP) { + gLibNotification.set_error_notification( + _("Error sending email"), + _("Geary encountered an error sending an email. If the problem persists, please manually delete the email from your Outbox folder.") + ); + } } private void update_account_status() { @@ -897,7 +905,7 @@ public class GearyController : Geary.BaseObject { if (folder.special_folder_type == Geary.SpecialFolderType.OUTBOX) { main_window.status_bar.deactivate_message(StatusBar.Message.OUTBOX_SEND_FAILURE); main_window.status_bar.deactivate_message(StatusBar.Message.OUTBOX_SAVE_SENT_MAIL_FAILED); - libnotify.clear_error_notification(); + gLibNotification.clear_error_notification(); } } @@ -1266,18 +1274,6 @@ public class GearyController : Geary.BaseObject { } } - private void on_libnotify_invoked(Geary.Folder? folder, Geary.Email? email) { - new_messages_monitor.clear_all_new_messages(); - - if (folder == null || email == null || !can_switch_conversation_view()) - return; - - main_window.folder_list.select_folder(folder); - Geary.App.Conversation? conversation = current_conversations.get_by_email_identifier(email.id); - if (conversation != null) - main_window.conversation_list_view.select_conversation(conversation); - } - private void on_indicator_activated_application(uint32 timestamp) { this.application.present(); } @@ -2617,7 +2613,7 @@ public class GearyController : Geary.BaseObject { ).printf(Util.Email.to_short_recipient_display(rfc822.to)); InAppNotification notification = new InAppNotification(message); this.main_window.add_notification(notification); - Libnotify.play_sound("message-sent-email"); + GLibNotification.play_sound("message-sent-email"); } private void on_conversation_view_added(ConversationListBox list) { @@ -2949,6 +2945,7 @@ public class GearyController : Geary.BaseObject { case Geary.Protocol.SMTP: context.account.outgoing.restart.begin(context.cancellable); + gLibNotification.clear_error_notification(); break; } } diff --git a/src/client/meson.build b/src/client/meson.build index 0770c20e..52740edb 100644 --- a/src/client/meson.build +++ b/src/client/meson.build @@ -81,9 +81,9 @@ geary_client_vala_sources = files( 'folder-list/folder-list-search-branch.vala', 'folder-list/folder-list-special-grouping.vala', + 'notification/glib-notification.vala', 'notification/in-app-notification.vala', 'notification/libmessagingmenu.vala', - 'notification/libnotify.vala', 'notification/new-messages-indicator.vala', 'notification/new-messages-monitor.vala', 'notification/null-indicator.vala', @@ -125,7 +125,6 @@ geary_client_dependencies = [ json_glib, libcanberra, libhandy, - libnotify, libsecret, libsoup, gmime, diff --git a/src/client/notification/libnotify.vala b/src/client/notification/glib-notification.vala similarity index 64% rename from src/client/notification/libnotify.vala rename to src/client/notification/glib-notification.vala index 93a2ad99..ca1d8b32 100644 --- a/src/client/notification/libnotify.vala +++ b/src/client/notification/glib-notification.vala @@ -4,38 +4,30 @@ * (version 2.1 or later). See the COPYING file in this distribution. */ -// Displays a notification via libnotify -public class Libnotify : Geary.BaseObject { +// Displays a notification via GLibNotification +public class GLibNotification : Geary.BaseObject { public const Geary.Email.Field REQUIRED_FIELDS = Geary.Email.Field.ORIGINATORS | Geary.Email.Field.SUBJECT; private static Canberra.Context? sound_context = null; private weak NewMessagesMonitor monitor; - private Notify.Notification? current_notification = null; - private Notify.Notification? error_notification = null; + private GLib.Notification? current_notification = null; + private GLib.Notification? error_notification = null; private Geary.Folder? folder = null; private Geary.Email? email = null; - private List? caps = null; - public signal void invoked(Geary.Folder? folder, Geary.Email? email); - public Libnotify(NewMessagesMonitor monitor) { + public GLibNotification(NewMessagesMonitor monitor) { this.monitor = monitor; - - monitor.add_required_fields(REQUIRED_FIELDS); - - if (!Notify.is_initted()) { - if (!Notify.init(Environment.get_prgname())) - message("Failed to initialize libnotify."); - } - init_sound(); - // This will return null if no notification server is present - this.caps = Notify.get_server_caps(); + this.monitor.add_required_fields(REQUIRED_FIELDS); + this.monitor.new_messages_arrived.connect(on_new_messages_arrived); + } - monitor.new_messages_arrived.connect(on_new_messages_arrived); + ~GLibNotification() { + this.monitor.new_messages_arrived.disconnect(on_new_messages_arrived); } private static void init_sound() { @@ -56,11 +48,6 @@ public class Libnotify : Geary.BaseObject { } } - private void on_default_action(Notify.Notification notification, string action) { - invoked(folder, email); - GearyApplication.instance.activate(); - } - private void notify_new_mail(Geary.Folder folder, int added) { // don't pass email if invoked this.folder = null; @@ -135,12 +122,7 @@ public class Libnotify : Geary.BaseObject { private void issue_current_notification(string summary, string body, Gdk.Pixbuf? icon) { // only one outstanding notification at a time if (current_notification != null) { - try { - current_notification.close(); - } catch (Error err) { - debug("Unable to close current libnotify notification: %s", err.message); - } - + GearyApplication.instance.withdraw_notification("email.arrived"); current_notification = null; } @@ -148,39 +130,20 @@ public class Libnotify : Geary.BaseObject { } - private Notify.Notification? issue_notification(string category, string summary, - string body, Gdk.Pixbuf? icon, string? sound) { - if (this.caps == null) - return null; - - // Avoid constructor due to ABI change - Notify.Notification notification = (Notify.Notification) GLib.Object.new( - typeof (Notify.Notification), - "icon-name", "org.gnome.Geary", - "summary", GLib.Environment.get_application_name()); - notification.set_hint_string("desktop-entry", "org.gnome.Geary"); - if (caps.find_custom("actions", GLib.strcmp) != null) - notification.add_action("default", _("Open"), on_default_action); - - notification.set_category(category); - notification.set("summary", summary); - notification.set("body", body); + private GLib.Notification issue_notification(string id, string summary, string body, + Gdk.Pixbuf? icon, string? sound) { + GLib.Notification notification = new GLib.Notification(summary); + notification.set_body(body); + //notification.set_default_action("app.activate"); if (icon != null) - notification.set_image_from_pixbuf(icon); + notification.set_icon(icon); if (sound != null) { - if (caps.find("sound") != null) - notification.set_hint_string("sound-name", sound); - else - play_sound(sound); + play_sound(sound); } - try { - notification.show(); - } catch (Error err) { - message("Unable to show notification: %s", err.message); - } + GearyApplication.instance.send_notification(id, notification); return notification; } @@ -200,19 +163,11 @@ public class Libnotify : Geary.BaseObject { if (error_notification != null) return; - error_notification = issue_notification("email", summary, body, null, null); + error_notification = issue_notification("error", summary, body, null, null); } public void clear_error_notification() { - if (error_notification != null) { - try { - error_notification.close(); - } catch (Error err) { - debug("Unable to close libnotify error notification: %s", err.message); - } - - error_notification = null; - } + GearyApplication.instance.withdraw_notification("error"); + error_notification = null; } } - diff --git a/src/client/notification/new-messages-monitor.vala b/src/client/notification/new-messages-monitor.vala index 71c2e807..85ea6c6d 100644 --- a/src/client/notification/new-messages-monitor.vala +++ b/src/client/notification/new-messages-monitor.vala @@ -5,7 +5,7 @@ */ // NewMessagesMonitor is a central data store for new message information that the various -// notification methods (libnotify, libunity, etc.) can monitor to do their thing. +// notification methods (GLibNotification, libunity, etc.) can monitor to do their thing. // Subclasses should trap the "notify::count" signal and use that to perform whatever magic // they need for their implementation, or trap "new-messages" to receive notifications of the emails // themselves as they're added. In the latter case, subscribers should add required Email.Field