[geary/wip/766133-gnotification: 13/15] Implement application actions for notifications



commit bb1fe538fd20a4d91ede043f484f9236361d521e
Author: Michael Gratton <mike vee net>
Date:   Sun Apr 14 20:59:22 2019 +1000

    Implement application actions for notifications
    
    Adds show-email and show-folder folder actions to allow default actions
    for notifications to reveal new email in main windows.

 src/client/application/geary-application.vala     | 58 ++++++++++++++++++++++
 src/client/components/main-window.vala            | 24 +++++++++
 src/client/notification/notification-desktop.vala | 60 +++++++++++++++--------
 3 files changed, 122 insertions(+), 20 deletions(-)
---
diff --git a/src/client/application/geary-application.vala b/src/client/application/geary-application.vala
index 5638da87..37ed88b8 100644
--- a/src/client/application/geary-application.vala
+++ b/src/client/application/geary-application.vala
@@ -60,6 +60,8 @@ public class GearyApplication : Gtk.Application {
     public const string ACTION_HELP = "help";
     public const string ACTION_MAILTO = "mailto";
     public const string ACTION_PREFERENCES = "preferences";
+    public const string ACTION_SHOW_EMAIL = "show-email";
+    public const string ACTION_SHOW_FOLDER = "show-folder";
     public const string ACTION_QUIT = "quit";
 
     // Local-only command line options
@@ -89,6 +91,8 @@ public class GearyApplication : Gtk.Application {
         {ACTION_MAILTO, on_activate_mailto, "s"},
         {ACTION_PREFERENCES, on_activate_preferences},
         {ACTION_QUIT, on_activate_quit},
+        {ACTION_SHOW_EMAIL, on_activate_show_email, "(svv)"},
+        {ACTION_SHOW_FOLDER, on_activate_show_folder, "(sv)"}
     };
 
     // This is also the order in which they are presented to the user,
@@ -727,6 +731,25 @@ public class GearyApplication : Gtk.Application {
         }
     }
 
+    private Geary.Folder? get_folder_from_action_target(GLib.Variant target) {
+        Geary.Folder? folder = null;
+        string account_id = (string) target.get_child_value(0);
+        try {
+            Geary.AccountInformation? account_config =
+                this.engine.get_account(account_id);
+            Geary.Account? account =
+                this.engine.get_account_instance(account_config);
+            Geary.FolderPath? path =
+                account.to_folder_path(
+                    target.get_child_value(1).get_variant()
+                );
+            folder = account.get_folder(path);
+        } catch (GLib.Error err) {
+            debug("Could not find account/folder %s", err.message);
+        }
+        return folder;
+    }
+
     private void on_activate_about() {
         Gtk.show_about_dialog(get_active_window(),
             "program-name", NAME,
@@ -783,6 +806,41 @@ public class GearyApplication : Gtk.Application {
         exit();
     }
 
+    private void on_activate_show_email(GLib.SimpleAction action,
+                                        GLib.Variant? target) {
+        if (target != null) {
+            // Target is a (account_id,folder_path,email_id) tuple
+            Geary.Folder? folder = get_folder_from_action_target(target);
+            Geary.EmailIdentifier? email_id = null;
+            if (folder != null) {
+                try {
+                    email_id = folder.account.to_email_identifier(
+                        target.get_child_value(2).get_variant()
+                    );
+                } catch (GLib.Error err) {
+                    debug("Could not find email id: %s", err.message);
+                }
+
+                if (email_id != null) {
+                    this.controller.main_window.present();
+                    this.controller.main_window.show_email(folder, email_id);
+                }
+            }
+        }
+    }
+
+    private void on_activate_show_folder(GLib.SimpleAction action,
+                                        GLib.Variant? target) {
+        if (target != null) {
+            // Target is a (account_id,folder_path) tuple
+            Geary.Folder? folder = get_folder_from_action_target(target);
+            if (folder != null) {
+                this.controller.main_window.present();
+                this.controller.main_window.show_folder(folder);
+            }
+        }
+    }
+
     private void on_activate_help() {
         try {
             if (is_installed()) {
diff --git a/src/client/components/main-window.vala b/src/client/components/main-window.vala
index 4b53422e..db91981e 100644
--- a/src/client/components/main-window.vala
+++ b/src/client/components/main-window.vala
@@ -174,6 +174,30 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
         update_infobar_frame();
     }
 
+    /** Selects the given account and folder. */
+    public void show_folder(Geary.Folder folder) {
+        this.folder_list.select_folder(folder);
+    }
+
+    /** Selects the given account, folder and email. */
+    public void show_email(Geary.Folder folder, Geary.EmailIdentifier id) {
+        // XXX this is broken in the case of the email's folder not
+        // being currently selected and loaded, since changing folders
+        // and loading the email in the conversation monitor won't
+        // have completed until well after is it obtained
+        // below. However, it should work in the only case where this
+        // currently used, that is when a user clicks on a
+        // notification for new mail in the current folder.
+        show_folder(folder);
+        Geary.App.ConversationMonitor? conversations =
+            this.application.controller.current_conversations;
+        Geary.App.Conversation? conversation =
+            conversations.get_by_email_identifier(id);
+        if (conversation != null) {
+            this.conversation_list_view.select_conversation(conversation);
+        }
+    }
+
     /** Displays and focuses the search bar for the window. */
     public void show_search_bar(string? text = null) {
         this.search_bar.give_search_focus();
diff --git a/src/client/notification/notification-desktop.vala 
b/src/client/notification/notification-desktop.vala
index 961fcd21..356a6010 100644
--- a/src/client/notification/notification-desktop.vala
+++ b/src/client/notification/notification-desktop.vala
@@ -18,10 +18,8 @@ public class Notification.Desktop : Geary.BaseObject {
 
     private weak NewMessagesMonitor monitor;
     private weak GearyApplication application;
-    private GLib.Notification? current_notification = null;
+    private GLib.Notification? arrived_notification = null;
     private GLib.Notification? error_notification = null;
-    private Geary.Folder? folder = null;
-    private Geary.Email? email = null;
     private GLib.Cancellable load_cancellable;
 
 
@@ -43,7 +41,7 @@ public class Notification.Desktop : Geary.BaseObject {
 
     public void clear_arrived_notification() {
         this.application.withdraw_notification(ARRIVED_ID);
-        this.current_notification = null;
+        this.arrived_notification = null;
     }
 
     public void set_error_notification(string summary, string body) {
@@ -52,7 +50,7 @@ public class Notification.Desktop : Geary.BaseObject {
         // but it means in the future, a more robust system will be needed.)
         if (this.error_notification == null) {
             this.error_notification = issue_notification(
-                ERROR_ID, summary, body
+                ERROR_ID, summary, body, null, null
             );
         }
     }
@@ -79,10 +77,6 @@ public class Notification.Desktop : Geary.BaseObject {
     }
 
     private void notify_new_mail(Geary.Folder folder, int added) {
-        // don't pass email if invoked
-        this.folder = null;
-        this.email = null;
-
         if (this.application.config.show_notifications &&
             this.monitor.should_notify_new_messages(folder)) {
             string body = ngettext(
@@ -101,8 +95,8 @@ public class Notification.Desktop : Geary.BaseObject {
                 ).printf(body, total);
             }
 
-            issue_current_notification(
-                this.folder.account.information.display_name, body
+            issue_arrived_notification(
+                folder.account.information.display_name, body, folder, null
             );
         }
     }
@@ -111,10 +105,6 @@ public class Notification.Desktop : Geary.BaseObject {
                                           Geary.Email email,
                                           GLib.Cancellable? cancellable)
         throws GLib.Error {
-        // used if notification is invoked
-        this.folder = folder;
-        this.email = email;
-
         Geary.RFC822.MailboxAddress? originator =
             Util.Email.get_primary_originator(email);
         if (this.application.config.show_notifications &&
@@ -140,32 +130,62 @@ public class Notification.Desktop : Geary.BaseObject {
                     );
             }
 
-            issue_current_notification(
+            issue_arrived_notification(
                 contact.is_trusted
                     ? contact.display_name : originator.to_short_display(),
-                body
+                body,
+                folder,
+                email.id
             );
         } else {
             notify_new_mail(folder, 1);
         }
     }
 
-    private void issue_current_notification(string summary, string body) {
+    private void issue_arrived_notification(string summary,
+                                            string body,
+                                            Geary.Folder folder,
+                                            Geary.EmailIdentifier? id) {
         // only one outstanding notification at a time
         clear_arrived_notification();
+
+        string? action = null;
+        GLib.Variant[] target_param = new GLib.Variant[] {
+            folder.account.information.id,
+            new GLib.Variant.variant(folder.path.to_variant())
+        };
+
+        if (id == null) {
+            action = GearyApplication.ACTION_SHOW_FOLDER;
+        } else {
+            action = GearyApplication.ACTION_SHOW_EMAIL;
+            target_param += new GLib.Variant.variant(id.to_variant());
+        }
+
         this.arrived_notification = issue_notification(
-            ARRIVED_ID, summary, body
+            ARRIVED_ID,
+            summary,
+            body,
+            "app." + action,
+            new GLib.Variant.tuple(target_param)
         );
     }
 
     private GLib.Notification issue_notification(string id,
                                                  string summary,
-                                                 string body) {
+                                                 string body,
+                                                 string? action,
+                                                 GLib.Variant? action_target) {
         GLib.Notification notification = new GLib.Notification(summary);
         notification.set_body(body);
         notification.set_icon(
             new GLib.ThemedIcon("%s-symbolic".printf(GearyApplication.APP_ID))
         );
+        if (action != null) {
+            notification.set_default_action_and_target_value(
+                action, action_target
+            );
+        }
         this.application.send_notification(id, notification);
         return notification;
     }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]