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.
This commit is contained in:
Michael Gratton 2019-04-14 20:59:22 +10:00 committed by Michael James Gratton
parent f7488453d0
commit bb1fe538fd
3 changed files with 122 additions and 20 deletions

View file

@ -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()) {

View file

@ -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();

View file

@ -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;
}