From fc4bc926c3faa5400e57249c1cf79deeb5c19dfe Mon Sep 17 00:00:00 2001 From: Michael Gratton Date: Sun, 19 Apr 2020 16:29:53 +1000 Subject: [PATCH] Composer.Widget: Convert to using AccountContext objects Use AccountContext objects so the composer can access the account's cancellable, contacts, etc. Simplify cancellable handling as a result. --- .../application-account-context.vala | 2 +- .../application/application-controller.vala | 138 ++++++++-------- src/client/composer/composer-widget.vala | 147 +++++++++--------- 3 files changed, 145 insertions(+), 142 deletions(-) diff --git a/src/client/application/application-account-context.vala b/src/client/application/application-account-context.vala index 45ec9970..ada24c0e 100644 --- a/src/client/application/application-account-context.vala +++ b/src/client/application/application-account-context.vala @@ -9,7 +9,7 @@ /** * Collects application state related to a single open account. */ -internal class Application.AccountContext : Geary.BaseObject { +public class Application.AccountContext : Geary.BaseObject { /** The account for this context. */ public Geary.Account account { get; private set; } diff --git a/src/client/application/application-controller.vala b/src/client/application/application-controller.vala index 530dec32..c039eac1 100644 --- a/src/client/application/application-controller.vala +++ b/src/client/application/application-controller.vala @@ -335,16 +335,22 @@ internal class Application.Controller : Geary.BaseObject { } } - var composer = new Composer.Widget( - this.application, - this.application.get_active_main_window().selected_account + var context = this.accounts.get( + this.application.get_active_main_window().selected_account.information ); - register_composer(composer); - show_composer(composer, null); - try { - yield composer.load_empty_body(to); - } catch (GLib.Error err) { - report_problem(new Geary.ProblemReport(err)); + if (context != null) { + var composer = new Composer.Widget( + this.application, + context, + this.accounts.values.read_only_view + ); + register_composer(composer); + show_composer(composer, null); + try { + yield composer.load_empty_body(to); + } catch (GLib.Error err) { + report_problem(new Geary.ProblemReport(err)); + } } } @@ -354,16 +360,21 @@ internal class Application.Controller : Geary.BaseObject { public async void compose_mailto(string mailto) { MainWindow? window = this.application.last_active_main_window; if (window != null && window.selected_account != null) { - var composer = new Composer.Widget( - this.application, window.selected_account - ); - register_composer(composer); - show_composer(composer, null); + var context = this.accounts.get(window.selected_account.information); + if (context != null) { + var composer = new Composer.Widget( + this.application, + context, + this.accounts.values.read_only_view + ); + register_composer(composer); + show_composer(composer, null); - try { - yield composer.load_mailto(mailto); - } catch (GLib.Error err) { - report_problem(new Geary.ProblemReport(err)); + try { + yield composer.load_mailto(mailto); + } catch (GLib.Error err) { + report_problem(new Geary.ProblemReport(err)); + } } } else { // Schedule the send for after we have an account open. @@ -423,17 +434,23 @@ internal class Application.Controller : Geary.BaseObject { } } - var composer = new Composer.Widget( - this.application, - this.application.get_active_main_window().selected_account + var account = this.accounts.get( + this.application.get_active_main_window().selected_account.information ); - register_composer(composer); - show_composer(composer, Geary.Collection.single(context.id)); + if (account != null) { + var composer = new Composer.Widget( + this.application, + account, + this.accounts.values.read_only_view + ); + register_composer(composer); + show_composer(composer, Geary.Collection.single(context.id)); - try { - yield composer.load_context(type, context, quote); - } catch (GLib.Error err) { - report_problem(new Geary.ProblemReport(err)); + try { + yield composer.load_context(type, context, quote); + } catch (GLib.Error err) { + report_problem(new Geary.ProblemReport(err)); + } } } @@ -462,13 +479,6 @@ internal class Application.Controller : Geary.BaseObject { } } - /** Returns the contact store for an account, if any. */ - public Application.ContactStore? - get_contact_store_for_account(Geary.Account target) { - AccountContext? context = this.accounts.get(target.information); - return (context != null) ? context.contacts : null; - } - /** * Updates flags for a collection of conversations. * @@ -881,18 +891,14 @@ internal class Application.Controller : Geary.BaseObject { /** Queues the email in a composer for delivery. */ internal async void send_composed_email(Composer.Widget composer) { - AccountContext? context = this.accounts.get( - composer.account.information - ); - if (context != null) { - try { - yield context.commands.execute( - new SendComposerCommand(this.application, context, composer), - context.cancellable - ); - } catch (GLib.Error err) { - report_problem(new Geary.ProblemReport(err)); - } + AccountContext context = composer.sender_context; + try { + yield context.commands.execute( + new SendComposerCommand(this.application, context, composer), + context.cancellable + ); + } catch (GLib.Error err) { + report_problem(new Geary.ProblemReport(err)); } } @@ -902,35 +908,27 @@ internal class Application.Controller : Geary.BaseObject { // the composer's draft manager is already saving drafts on // the server. Until we get that saving local-only, this will // only be around for pushing the composer onto the undo stack - AccountContext? context = this.accounts.get( - composer.account.information - ); - if (context != null) { - try { - yield context.commands.execute( - new SaveComposerCommand(this, composer), - context.cancellable - ); - } catch (GLib.Error err) { - report_problem(new Geary.ProblemReport(err)); - } + AccountContext context = composer.sender_context; + try { + yield context.commands.execute( + new SaveComposerCommand(this, composer), + context.cancellable + ); + } catch (GLib.Error err) { + report_problem(new Geary.ProblemReport(err)); } } /** Queues a composer to be discarded. */ internal async void discard_composed_email(Composer.Widget composer) { - AccountContext? context = this.accounts.get( - composer.account.information - ); - if (context != null) { - try { - yield context.commands.execute( - new DiscardComposerCommand(this, composer), - context.cancellable - ); - } catch (GLib.Error err) { - report_problem(new Geary.ProblemReport(err)); - } + AccountContext context = composer.sender_context; + try { + yield context.commands.execute( + new DiscardComposerCommand(this, composer), + context.cancellable + ); + } catch (GLib.Error err) { + report_problem(new Geary.ProblemReport(err)); } } diff --git a/src/client/composer/composer-widget.vala b/src/client/composer/composer-widget.vala index ee169448..dddce3a7 100644 --- a/src/client/composer/composer-widget.vala +++ b/src/client/composer/composer-widget.vala @@ -116,11 +116,12 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { private class FromAddressMap { - public Geary.Account account; + public Application.AccountContext account; public Geary.RFC822.MailboxAddresses from; - public FromAddressMap(Geary.Account a, Geary.RFC822.MailboxAddresses f) { - account = a; - from = f; + public FromAddressMap(Application.AccountContext account, + Geary.RFC822.MailboxAddresses from) { + this.account = account; + this.from = from; } } @@ -256,7 +257,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { /** The account the email is being sent from. */ - public Geary.Account account { get; private set; } + public Application.AccountContext sender_context { get; private set; } /** The identifier of the saved email this composer holds, if any. */ public Geary.EmailIdentifier? saved_id { @@ -290,7 +291,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { get { return ( this.accounts.size > 1 || - this.account.information.has_sender_aliases + this.sender_context.account.information.has_sender_aliases ); } } @@ -445,7 +446,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { } } - private Gee.Collection accounts; + private Gee.Collection accounts; private string? pointer_url = null; private string? cursor_url = null; @@ -502,17 +503,13 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { public Widget(Application.Client application, - Geary.Account initial_account) { + Application.AccountContext initial_account, + Gee.Collection all_accounts) { components_reflow_box_get_type(); base_ref(); this.application = application; - this.account = initial_account; - - try { - this.accounts = this.application.engine.get_accounts(); - } catch (GLib.Error e) { - warning("Could not fetch account info: %s", e.message); - } + this.sender_context = initial_account; + this.accounts = all_accounts; this.header = new Headerbar(application.config); this.header.expand_composer.connect(on_expand_compact_headers); @@ -595,7 +592,9 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { // TODO: also listen for account updates to allow adding identities while writing an email - this.from = new Geary.RFC822.MailboxAddresses.single(account.information.primary_mailbox); + this.from = new Geary.RFC822.MailboxAddresses.single( + this.sender_context.account.information.primary_mailbox + ); this.draft_timer = new Geary.TimeoutManager.seconds( 10, on_draft_timeout @@ -659,7 +658,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { if (to != null) { this.to = to.to_full_display(); } - yield finish_loading("", "", false, null); + yield finish_loading("", "", false); } public async void load_mailto(string mailto) @@ -716,7 +715,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { attachment_failed(err.message); } } - yield finish_loading(body, "", false, null); + yield finish_loading(body, "", false); } } @@ -784,7 +783,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { break; } - yield finish_loading(body, complete_quote, (type == EDIT), null); + yield finish_loading(body, complete_quote, (type == EDIT)); } /** @@ -942,11 +941,11 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { } try { - yield close_draft_manager(KEEP, null); + yield close_draft_manager(KEEP); } catch (GLib.Error error) { this.application.controller.report_problem( new Geary.AccountProblemReport( - this.account.information, error + this.sender_context.account.information, error ) ); } @@ -1001,10 +1000,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { * Loads and sets contact auto-complete data for the current account. */ private void load_entry_completions() { - Application.ContactStore contacts = - this.application.controller.get_contact_store_for_account( - this.account - ); + Application.ContactStore contacts = this.sender_context.contacts; this.to_entry.completion = new ContactEntryCompletion(contacts); this.cc_entry.completion = new ContactEntryCompletion(contacts); this.bcc_entry.completion = new ContactEntryCompletion(contacts); @@ -1018,13 +1014,22 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { bool first_email = true; foreach (Geary.RFC822.MessageID mid in this.in_reply_to) { - Gee.MultiMap? email_map; + Gee.MultiMap? email_map = null; try { - email_map = - yield this.account.local_search_message_id_async(mid, Geary.Email.Field.ENVELOPE, - true, null, new Geary.EmailFlags.with(Geary.EmailFlags.DRAFT)); // TODO: Folder blacklist - } catch (Error error) { - continue; + // TODO: Folder blacklist + email_map = yield this.sender_context.account + .local_search_message_id_async( + mid, + ENVELOPE, + true, + null, + new Geary.EmailFlags.with(Geary.EmailFlags.DRAFT) + ); + } catch (GLib.Error error) { + warning( + "Error restoring edited message state from In-Reply-To: %s", + error.message + ); } if (email_map == null) continue; @@ -1394,7 +1399,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { Geary.Email referred, bool modify_headers = true) { Gee.List sender_addresses = - account.information.sender_mailboxes; + this.sender_context.account.information.sender_mailboxes; // Set the preferred from address. New messages should retain // the account default and drafts should retain the draft's @@ -1510,8 +1515,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { private async void finish_loading(string body, string quote, - bool is_body_complete, - GLib.Cancellable? cancellable) { + bool is_body_complete) { update_attachments_view(); update_pending_attachments(this.pending_include, true); @@ -1523,7 +1527,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { ); try { - yield open_draft_manager(this.saved_id, cancellable); + yield open_draft_manager(this.saved_id); } catch (Error e) { debug("Could not open draft manager: %s", e.message); } @@ -1581,7 +1585,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { try { yield this.editor.clean_content(); yield this.application.controller.send_composed_email(this); - yield close_draft_manager(DISCARD, null); + yield close_draft_manager(DISCARD); if (this.container != null) { this.container.close(); @@ -1589,7 +1593,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { } catch (GLib.Error error) { this.application.controller.report_problem( new Geary.AccountProblemReport( - this.account.information, error + this.sender_context.account.information, error ) ); } @@ -1598,10 +1602,9 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { /** * Creates and opens the composer's draft manager. */ - private async void open_draft_manager(Geary.EmailIdentifier? editing_draft_id, - GLib.Cancellable? cancellable) + private async void open_draft_manager(Geary.EmailIdentifier? editing_draft_id) throws GLib.Error { - if (!this.account.information.save_drafts) { + if (!this.sender_context.account.information.save_drafts) { this.header.show_save_and_close = false; return; } @@ -1612,14 +1615,14 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { } GLib.Cancellable internal_cancellable = new GLib.Cancellable(); - if (cancellable != null) { - cancellable.cancelled.connect( - () => { internal_cancellable.cancel(); } - ); - } + this.sender_context.cancellable.cancelled.connect( + () => { internal_cancellable.cancel(); } + ); this.draft_manager_opening = internal_cancellable; - Geary.App.DraftManager new_manager = new Geary.App.DraftManager(account); + Geary.App.DraftManager new_manager = new Geary.App.DraftManager( + this.sender_context.account + ); try { yield new_manager.open_async(editing_draft_id, internal_cancellable); debug("Draft manager opened"); @@ -1645,17 +1648,16 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { /** * Closes current draft manager, if any, then opens a new one. */ - private async void reopen_draft_manager(GLib.Cancellable? cancellable) + private async void reopen_draft_manager() throws GLib.Error { // Discard the draft, if any, since it may be on a different // account - yield close_draft_manager(DISCARD, cancellable); - yield open_draft_manager(null, cancellable); + yield close_draft_manager(DISCARD); + yield open_draft_manager(null); yield save_draft(); } - private async void close_draft_manager(DraftPolicy draft_policy, - GLib.Cancellable? cancellable) + private async void close_draft_manager(DraftPolicy draft_policy) throws GLib.Error { var old_manager = this.draft_manager; if (old_manager != null) { @@ -1676,7 +1678,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { yield old_manager.discard(null); } - yield old_manager.close_async(cancellable); + yield old_manager.close_async(null); debug("Draft manager closed"); } } @@ -1745,7 +1747,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { } catch (GLib.Error error) { this.application.controller.report_problem( new Geary.AccountProblemReport( - this.account.information, error + this.sender_context.account.information, error ) ); } @@ -1763,11 +1765,11 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { set_enabled(false); try { - yield close_draft_manager(DISCARD, null); + yield close_draft_manager(DISCARD); } catch (GLib.Error error) { this.application.controller.report_problem( new Geary.AccountProblemReport( - this.account.information, error + this.sender_context.account.information, error ) ); } @@ -2465,10 +2467,13 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { return action as SimpleAction; } - private bool add_account_emails_to_from_list(Geary.Account other_account, bool set_active = false) { + private bool add_account_emails_to_from_list( + Application.AccountContext other_account, + bool set_active = false + ) { bool is_primary = true; - foreach (Geary.RFC822.MailboxAddress mailbox in - other_account.information.sender_mailboxes) { + Geary.AccountInformation info = other_account.account.information; + foreach (Geary.RFC822.MailboxAddress mailbox in info.sender_mailboxes) { Geary.RFC822.MailboxAddresses addresses = new Geary.RFC822.MailboxAddresses.single(mailbox); @@ -2479,9 +2484,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { // printf argument will be the alternate email address, // and the second will be the account's primary email // address. - display = _("%1$s via %2$s").printf( - display, other_account.information.display_name - ); + display = _("%1$s via %2$s").printf(display, info.display_name); } is_primary = false; @@ -2527,7 +2530,8 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { // show nothing. if (this.accounts.size < 1 || (this.accounts.size == 1 && - !Geary.traverse(this.accounts).first().information.has_sender_aliases)) { + !Geary.Collection.first(this.accounts) + .account.information.has_sender_aliases)) { return false; } @@ -2541,9 +2545,9 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { // Always add at least the current account. The var set_active // is set to true if the current message's from address has // been set in the ComboBox. - bool set_active = add_account_emails_to_from_list(this.account); + bool set_active = add_account_emails_to_from_list(this.sender_context); foreach (var account in this.accounts) { - if (account != this.account) { + if (account != this.sender_context) { set_active = add_account_emails_to_from_list( account, set_active ); @@ -2567,14 +2571,13 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { FromAddressMap selected = this.from_list.get(index); this.from = selected.from; - if (selected.account != this.account) { - this.account = selected.account; + if (selected.account != this.sender_context) { + this.sender_context = selected.account; this.update_signature.begin(null); load_entry_completions(); - var current_account = this.account; + var current_account = this.sender_context.account; this.reopen_draft_manager.begin( - null, (obj, res) => { try { this.reopen_draft_manager.end(res); @@ -2593,8 +2596,10 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { private async void update_signature(Cancellable? cancellable = null) { string sig = ""; - if (this.account.information.use_signature) { - sig = account.information.signature; + Geary.AccountInformation account = + this.sender_context.account.information; + if (account.use_signature) { + sig = account.signature; if (Geary.String.is_empty_or_whitespace(sig)) { // No signature is specified in the settings, so use // ~/.signature @@ -2912,7 +2917,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface { } private void on_draft_timeout() { - var current_account = this.account; + var current_account = this.sender_context.account; this.save_draft.begin( (obj, res) => { try {