[geary/mjog/mail-merge-plugin: 26/72] Application.Controller: Rework composer life-cycle, again
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/mjog/mail-merge-plugin: 26/72] Application.Controller: Rework composer life-cycle, again
- Date: Tue, 18 Aug 2020 06:32:45 +0000 (UTC)
commit c57ae854bd00cc4c5f003ff16285c0e12766273e
Author: Michael Gratton <mike vee net>
Date: Fri Jul 3 15:12:27 2020 +1000
Application.Controller: Rework composer life-cycle, again
Since plugins especially require the ability to customise a composer
ideally before presenting it, split up composer construction into two
phases: `compose_blah` methods that find a matching composer or
constructa new one, then `present_composer` to present it.
Add `composer_registered` and `composer_deregistered` signals, fired
as appropriate so other code paths (again, plugins in particular) can
hook into composer lifecycles.
Update call sites for new API and to explicitly present new composers.
src/client/application/application-client.vala | 21 ++-
src/client/application/application-controller.vala | 146 +++++++++++----------
.../application/application-main-window.vala | 48 ++++---
3 files changed, 127 insertions(+), 88 deletions(-)
---
diff --git a/src/client/application/application-client.vala b/src/client/application/application-client.vala
index b8c041e83..75b82c80f 100644
--- a/src/client/application/application-client.vala
+++ b/src/client/application/application-client.vala
@@ -726,8 +726,25 @@ public class Application.Client : Gtk.Application {
}
public async void new_composer(Geary.RFC822.MailboxAddress? to = null) {
- yield this.present();
- yield this.controller.compose_new_email(to);
+ MainWindow main = yield this.present();
+ AccountContext? account = null;
+ if (main.selected_account == null) {
+ account = this.controller.get_context_for_account(
+ main.selected_account.information
+ );
+ }
+ if (account == null) {
+ account = Geary.Collection.first(
+ this.controller.get_account_contexts()
+ );
+ }
+ if (account != null) {
+ Composer.Widget composer = yield this.controller.compose_blank(
+ account,
+ to
+ );
+ this.controller.present_composer(composer);
+ }
}
public async void new_composer_mailto(string? mailto) {
diff --git a/src/client/application/application-controller.vala
b/src/client/application/application-controller.vala
index 3755e3a0a..147c5efeb 100644
--- a/src/client/application/application-controller.vala
+++ b/src/client/application/application-controller.vala
@@ -100,6 +100,22 @@ internal class Application.Controller :
private GLib.Cancellable? storage_cleanup_cancellable;
+ /**
+ * Emitted when a composer is registered.
+ *
+ * This will be emitted after a composer is constructed, but
+ * before it is shown.
+ */
+ public signal void composer_registered(Composer.Widget widget);
+
+ /**
+ * Emitted when a composer is deregistered.
+ *
+ * This will be emitted when a composer has been closed and is
+ * about to be destroyed.
+ */
+ public signal void composer_deregistered(Composer.Widget widget);
+
/**
* Constructs a new instance of the controller.
*/
@@ -312,37 +328,26 @@ internal class Application.Controller :
/**
* Opens a composer for writing a new, blank message.
*/
- public async Composer.Widget? compose_new_email(Geary.RFC822.MailboxAddress? to = null,
- Geary.Folder? save_to = null) {
- // If there's already an empty composer open, just use that
+ public async Composer.Widget compose_blank(AccountContext send_context,
+ Geary.RFC822.MailboxAddress? to = null) {
MainWindow main = this.application.get_active_main_window();
- Composer.Widget existing = main.conversation_viewer.current_composer;
- if (existing != null &&
- existing.current_mode == PANED &&
- existing.is_blank) {
- existing.present();
- existing.set_focus();
- return existing;
- }
-
- var context = this.accounts.get(
- this.application.get_active_main_window().selected_account.information
- );
- Composer.Widget? composer = null;
- if (context != null) {
+ Composer.Widget composer = main.conversation_viewer.current_composer;
+ if (composer == null ||
+ composer.current_mode != PANED ||
+ !composer.is_blank ||
+ composer.sender_context != send_context) {
composer = new Composer.Widget(
this,
this.application.config,
context,
- save_to
+ null
);
register_composer(composer);
- show_composer(composer);
- try {
- yield composer.load_empty_body(to);
- } catch (GLib.Error err) {
- report_problem(new Geary.ProblemReport(err));
- }
+ }
+ try {
+ yield composer.load_empty_body(to);
+ } catch (GLib.Error err) {
+ report_problem(new Geary.ProblemReport(err));
}
return composer;
}
@@ -354,39 +359,44 @@ internal class Application.Controller :
* the context is loaded to be edited (e.g. for drafts, templates,
* sending again. Otherwise the context is treated as the email to
* be replied to, etc.
+ *
+ * Returns null if there is an existing composer open and the
+ * prompt to close it was declined.
*/
- public async Composer.Widget? compose_with_context_email(Composer.Widget.ContextType type,
- Geary.Email context,
- string? quote,
- Geary.Folder? save_to = null) {
- MainWindow show_on = this.application.get_active_main_window();
+ public async Composer.Widget? compose_with_context(AccountContext send_context,
+ Composer.Widget.ContextType type,
+ Geary.Email context,
+ string? quote) {
+ MainWindow main = this.application.get_active_main_window();
+ Composer.Widget? composer = null;
if (type == EDIT) {
// Check all known composers since the context may be open
// an existing composer already.
- foreach (Composer.Widget composer in this.composer_widgets) {
- if (composer.current_mode != NONE &&
- composer.current_mode != CLOSED &&
- composer.saved_id != null &&
- composer.saved_id.equal_to(context.id)) {
- composer.present();
- composer.set_focus();
- return composer;
+ foreach (var existing in this.composer_widgets) {
+ if (existing.current_mode != NONE &&
+ existing.current_mode != CLOSED &&
+ composer.sender_context == send_context &&
+ existing.saved_id != null &&
+ existing.saved_id.equal_to(context.id)) {
+ composer = existing;
+ break;
}
}
} else {
// See whether there is already an inline message in the
// current window that is either a reply/forward for that
// message, or there is a quote to insert into it.
- foreach (Composer.Widget existing in this.composer_widgets) {
- if (existing.get_toplevel() == show_on &&
+ foreach (var existing in this.composer_widgets) {
+ if (existing.get_toplevel() == main &&
(existing.current_mode == INLINE ||
existing.current_mode == INLINE_COMPACT) &&
+ existing.sender_context == send_context &&
(context.id in existing.get_referred_ids() ||
quote != null)) {
try {
existing.append_to_email(context, quote, type);
- existing.present();
- return existing;
+ composer = existing;
+ break;
} catch (Geary.EngineError error) {
report_problem(new Geary.ProblemReport(error));
}
@@ -397,21 +407,19 @@ internal class Application.Controller :
// new one. Replies must open inline in the main window,
// so we need to ensure there are no composers open there
// first.
- if (!show_on.close_composer(true)) {
+ if (composer == null && !main.close_composer(true)) {
+ // Prompt to close the existing composer was declined,
+ // so bail out
return null;
}
}
- var account = this.accounts.get(
- this.application.get_active_main_window().selected_account.information
- );
- Composer.Widget? composer = null;
- if (account != null) {
+ if (composer == null) {
composer = new Composer.Widget(
this,
this.application.config,
account,
- save_to
+ null
);
register_composer(composer);
@@ -420,12 +428,6 @@ internal class Application.Controller :
} catch (GLib.Error err) {
report_problem(new Geary.ProblemReport(err));
}
-
- // Have to load the body before showing the composer
- // because we need to know what other messages the context
- // message refers to, so it can be displayed as an inline
- // composer if appropriate.
- show_composer(composer);
}
return composer;
}
@@ -444,7 +446,7 @@ internal class Application.Controller :
context
);
register_composer(composer);
- show_composer(composer);
+ present_composer(composer);
try {
yield composer.load_mailto(mailto);
@@ -1381,7 +1383,7 @@ internal class Application.Controller :
/** Clears new message counts in notification plugin contexts. */
internal void clear_new_messages(Geary.Folder source,
- Gee.Set<Geary.App.Conversation> visible) {
+ Gee.Set<Geary.App.Conversation> visible) {
foreach (MainWindow window in this.application.get_main_windows()) {
window.folder_list.set_has_new(source, false);
}
@@ -1429,11 +1431,15 @@ internal class Application.Controller :
this.all_windows_backgrounded_timeout.start();
}
- /** Displays a composer on the last active main window. */
- internal void show_composer(Composer.Widget composer) {
- var target = this.application.get_active_main_window();
- target.show_composer(composer);
+ /** Attempts to make the composer visible on the active monitor. */
+ internal void present_composer(Composer.Widget composer) {
+ if (composer.current_mode == CLOSED ||
+ composer.current_mode == NONE) {
+ var target = this.application.get_active_main_window();
+ target.show_composer(composer);
+ }
composer.set_focus();
+ composer.present();
}
internal bool check_open_composers() {
@@ -1448,17 +1454,21 @@ internal class Application.Controller :
}
internal void register_composer(Composer.Widget widget) {
- debug(@"Registered composer of type $(widget.context_type); $(this.composer_widgets.size) composers
total");
- widget.destroy.connect_after(this.on_composer_widget_destroy);
- this.composer_widgets.add(widget);
+ if (!(widget in this.composer_widgets)) {
+ debug(@"Registered composer of type $(widget.context_type); " +
+ @"$(this.composer_widgets.size) composers total");
+ widget.destroy.connect_after(this.on_composer_widget_destroy);
+ this.composer_widgets.add(widget);
+ composer_registered(widget);
+ }
}
private void on_composer_widget_destroy(Gtk.Widget sender) {
Composer.Widget? composer = sender as Composer.Widget;
- if (composer != null) {
- composer_widgets.remove((Composer.Widget) sender);
+ if (composer != null && composer_widgets.remove(composer)) {
debug(@"Composer type $(composer.context_type) destroyed; " +
@"$(this.composer_widgets.size) composers remaining");
+ composer_deregistered(composer);
}
}
@@ -2518,7 +2528,7 @@ private class Application.SendComposerCommand : ComposerCommand {
this.saved = null;
this.composer.set_enabled(true);
- this.application.controller.show_composer(this.composer);
+ this.application.controller.present_composer(this.composer);
clear_composer();
}
@@ -2572,7 +2582,7 @@ private class Application.SaveComposerCommand : ComposerCommand {
if (this.composer != null) {
this.destroy_timer.reset();
this.composer.set_enabled(true);
- this.controller.show_composer(this.composer);
+ this.controller.present_composer(this.composer);
clear_composer();
} else {
/// Translators: A label for an in-app notification.
@@ -2630,7 +2640,7 @@ private class Application.DiscardComposerCommand : ComposerCommand {
if (this.composer != null) {
this.destroy_timer.reset();
this.composer.set_enabled(true);
- this.controller.show_composer(this.composer);
+ this.controller.present_composer(this.composer);
clear_composer();
} else {
/// Translators: A label for an in-app notification.
diff --git a/src/client/application/application-main-window.vala
b/src/client/application/application-main-window.vala
index 86cd97aae..645fd7290 100644
--- a/src/client/application/application-main-window.vala
+++ b/src/client/application/application-main-window.vala
@@ -1556,7 +1556,20 @@ public class Application.MainWindow :
);
}
- private void create_composer_from_viewer(Composer.Widget.ContextType type) {
+ private async void create_composer(Geary.Account send_context,
+ Composer.Widget.ContextType type,
+ Geary.Email context,
+ string? quote) {
+ var composer = yield this.controller.compose_with_context(
+ this.controller.get_context_for_account(send_context.information),
+ type,
+ context,
+ quote ?? ""
+ );
+ this.controller.present_composer(composer);
+ }
+
+ private async void create_composer_from_viewer(Composer.Widget.ContextType type) {
Geary.Account? account = this.selected_account;
ConversationEmail? email_view = null;
ConversationListBox? list_view = this.conversation_viewer.current_list;
@@ -1564,12 +1577,8 @@ public class Application.MainWindow :
email_view = list_view.get_reply_target();
}
if (account != null && email_view != null) {
- email_view.get_selection_for_quoting.begin((obj, res) => {
- string? quote = email_view.get_selection_for_quoting.end(res);
- this.controller.compose_with_context_email.begin(
- type, email_view.email, quote ?? ""
- );
- });
+ string? quote = yield email_view.get_selection_for_quoting();
+ yield create_composer(account, type, email_view.email, quote);
}
}
@@ -2105,8 +2114,11 @@ public class Application.MainWindow :
// TODO: Determine how to map between conversations
// and drafts correctly.
Geary.Email draft = activated.get_latest_recv_email(IN_FOLDER);
- this.controller.compose_with_context_email.begin(
- EDIT, draft, null
+ this.create_composer.begin(
+ this.selected_folder.account,
+ EDIT,
+ draft,
+ null
);
}
}
@@ -2134,15 +2146,15 @@ public class Application.MainWindow :
}
private void on_reply_conversation() {
- create_composer_from_viewer(REPLY_SENDER);
+ this.create_composer_from_viewer.begin(REPLY_SENDER);
}
private void on_reply_all_conversation() {
- create_composer_from_viewer(REPLY_ALL);
+ this.create_composer_from_viewer.begin(REPLY_ALL);
}
private void on_forward_conversation() {
- create_composer_from_viewer(FORWARD);
+ this.create_composer_from_viewer.begin(FORWARD);
}
private void on_show_copy_menu() {
@@ -2458,24 +2470,24 @@ public class Application.MainWindow :
private void on_email_reply_to_sender(Geary.Email target, string? quote) {
if (this.selected_account != null) {
- this.controller.compose_with_context_email.begin(
- REPLY_SENDER, target, quote
+ this.create_composer.begin(
+ this.selected_account, REPLY_SENDER, target, quote
);
}
}
private void on_email_reply_to_all(Geary.Email target, string? quote) {
if (this.selected_account != null) {
- this.controller.compose_with_context_email.begin(
- REPLY_ALL, target, quote
+ this.create_composer.begin(
+ this.selected_account, REPLY_ALL, target, quote
);
}
}
private void on_email_forward(Geary.Email target, string? quote) {
if (this.selected_account != null) {
- this.controller.compose_with_context_email.begin(
- FORWARD, target, quote
+ this.create_composer.begin(
+ this.selected_account, FORWARD, target, quote
);
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]