[geary/wip/135-contact-popovers: 5/26] Implement New Conversation action



commit b9d6c26af81f94ada119895e9868162b7b98715c
Author: Michael Gratton <mike vee net>
Date:   Thu Mar 14 18:57:47 2019 +1100

    Implement New Conversation action
    
    Move some of the main-window-specific composer infrastructure from
    GearyController to MainWindow. Add a method for showing a new composer
    for a mailbox to the window. Create composer using full mailbox, not
    just the email address, so the contact's display name is included.

 src/client/application/geary-controller.vala       | 40 +++++++++++-----------
 src/client/components/main-window.vala             | 35 +++++++++++++++++++
 .../conversation-viewer/conversation-list-box.vala |  5 +++
 .../conversation-viewer/conversation-message.vala  | 23 ++++++++++---
 4 files changed, 79 insertions(+), 24 deletions(-)
---
diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala
index 3b5cc495..f8b793b3 100644
--- a/src/client/application/geary-controller.vala
+++ b/src/client/application/geary-controller.vala
@@ -124,6 +124,10 @@ public class GearyController : Geary.BaseObject {
         get; private set; default = null;
     }
 
+    public ContactListStoreCache contact_list_store_cache {
+        get; private set; default = new ContactListStoreCache();
+    }
+
     private Geary.Account? current_account = null;
     private Gee.Map<Geary.AccountInformation,AccountContext> accounts =
         new Gee.HashMap<Geary.AccountInformation,AccountContext>();
@@ -137,7 +141,6 @@ public class GearyController : Geary.BaseObject {
     private Cancellable cancellable_search = new Cancellable();
     private Cancellable cancellable_open_account = new Cancellable();
     private Cancellable cancellable_context_dependent_buttons = new Cancellable();
-    private ContactListStoreCache contact_list_store_cache = new ContactListStoreCache();
     private Gee.Set<Geary.App.Conversation> selected_conversations = new 
Gee.HashSet<Geary.App.Conversation>();
     private Geary.App.Conversation? last_deleted_conversation = null;
     private Gee.LinkedList<ComposerWidget> composer_widgets = new Gee.LinkedList<ComposerWidget>();
@@ -571,6 +574,14 @@ public class GearyController : Geary.BaseObject {
         }
     }
 
+    /** Adds a new composer to be kept track of. */
+    public void add_composer(ComposerWidget widget) {
+        debug(@"Added composer of type $(widget.compose_type); $(this.composer_widgets.size) composers 
total");
+        widget.destroy.connect(this.on_composer_widget_destroy);
+        widget.link_activated.connect((uri) => { open_uri(uri); });
+        this.composer_widgets.add(widget);
+    }
+
     /** Expunges removed accounts while the controller remains open. */
     internal async void expunge_accounts() {
         try {
@@ -2138,28 +2149,17 @@ public class GearyController : Geary.BaseObject {
         } else {
             widget = new ComposerWidget(current_account, contact_list_store_cache, compose_type, 
application.config);
         }
-        widget.destroy.connect(on_composer_widget_destroy);
-        widget.link_activated.connect((uri) => { open_uri(uri); });
 
-        // We want to keep track of the open composer windows, so we can allow the user to cancel
-        // an exit without losing their data.
-        composer_widgets.add(widget);
-        debug(@"Creating composer of type $(widget.compose_type); $(composer_widgets.size) composers total");
+        add_composer(widget);
 
-        if (inline) {
-            if (widget.state == ComposerWidget.ComposerState.PANED) {
-                main_window.conversation_viewer.do_compose(widget);
-                get_window_action(ACTION_FIND_IN_CONVERSATION).set_enabled(false);
-            } else {
-                main_window.conversation_viewer.do_compose_embedded(
-                    widget,
-                    referred,
-                    is_draft
-                );
-            }
+        if (widget.state == INLINE || widget.state == INLINE_COMPACT) {
+            this.main_window.conversation_viewer.do_compose_embedded(
+                widget,
+                referred,
+                is_draft
+            );
         } else {
-            new ComposerWindow(widget);
-            widget.state = ComposerWidget.ComposerState.DETACHED;
+            this.main_window.show_composer(widget);
         }
 
         // Load the widget's content
diff --git a/src/client/components/main-window.vala b/src/client/components/main-window.vala
index c6826e76..39f15911 100644
--- a/src/client/components/main-window.vala
+++ b/src/client/components/main-window.vala
@@ -125,6 +125,20 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
         base_unref();
     }
 
+    public void open_composer_for_mailbox(Geary.RFC822.MailboxAddress to) {
+        GearyController controller = this.application.controller;
+        ComposerWidget composer = new ComposerWidget(
+            this.current_folder.account,
+            controller.contact_list_store_cache,
+            NEW_MESSAGE,
+            this.application.config
+        );
+        composer.to = to.to_full_display();
+        controller.add_composer(composer);
+        show_composer(composer);
+        composer.load.begin(null, null, false);
+    }
+
     /** Updates the window's account status info bars. */
     public void update_account_status(Geary.Account.Status status,
                                       bool has_auth_error,
@@ -174,6 +188,23 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
         this.info_bar_frame.show();
     }
 
+    /** Displays a composer in the window if possible, else in a new window. */
+    public void show_composer(ComposerWidget composer) {
+        bool has_composer = (
+            this.conversation_viewer.is_composer_visible ||
+            (this.conversation_viewer.current_list != null &&
+             this.conversation_viewer.current_list.has_composer)
+        );
+
+        if (has_composer) {
+            composer.state = ComposerWidget.ComposerState.DETACHED;
+            new ComposerWindow(composer);
+        } else {
+            this.conversation_viewer.do_compose(composer);
+            get_action(GearyController.ACTION_FIND_IN_CONVERSATION).set_enabled(false);
+        }
+    }
+
     private void load_config(Configuration config) {
         // This code both loads AND saves the pane positions with live updating. This is more
         // resilient against crashes because the value in dconf changes *immediately*, and
@@ -583,6 +614,10 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
         return service;
     }
 
+    private SimpleAction get_action(string name) {
+        return (SimpleAction) lookup_action(name);
+    }
+
     [GtkCallback]
     private void on_map() {
         this.update_ui_timeout.start();
diff --git a/src/client/conversation-viewer/conversation-list-box.vala 
b/src/client/conversation-viewer/conversation-list-box.vala
index 571a6c2a..9799d97e 100644
--- a/src/client/conversation-viewer/conversation-list-box.vala
+++ b/src/client/conversation-viewer/conversation-list-box.vala
@@ -465,6 +465,9 @@ public class ConversationListBox : Gtk.ListBox, Geary.BaseInterface {
     /** Search manager for highlighting search terms in this list. */
     public SearchManager search { get; private set; }
 
+    /** Specifies if this list box currently has an embedded composer. */
+    public bool has_composer { get; private set; default = false; }
+
     // Used to load messages in conversation.
     private Geary.App.EmailStore email_store;
 
@@ -712,9 +715,11 @@ public class ConversationListBox : Gtk.ListBox, Geary.BaseInterface {
         // circular ref.
         row.should_scroll.connect((row) => { scroll_to(row); });
         add(row);
+        this.has_composer = true;
 
         embed.composer.draft_id_changed.connect((id) => { this.draft_id = id; });
         embed.vanished.connect(() => {
+                this.has_composer = false;
                 this.draft_id = null;
                 remove(row);
                 if (is_draft &&
diff --git a/src/client/conversation-viewer/conversation-message.vala 
b/src/client/conversation-viewer/conversation-message.vala
index b04d8aca..cdb492c2 100644
--- a/src/client/conversation-viewer/conversation-message.vala
+++ b/src/client/conversation-viewer/conversation-message.vala
@@ -152,6 +152,8 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
     }
 
 
+    private static GLib.VariantType MAILBOX_TYPE = new GLib.VariantType("(ss)");
+
 
     /** Box containing the preview and full header widgets.  */
     [GtkChild]
@@ -363,14 +365,13 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
         add_action(ACTION_CONTACT_OPEN, true, VariantType.STRING)
             // XXX
             ;
-        add_action(ACTION_CONTACT_SAVE, true, new VariantType("(ss)"))
+        add_action(ACTION_CONTACT_SAVE, true, ConversationMessage.MAILBOX_TYPE)
             // XXX
             ;
         add_action(ACTION_CONTACT_SHOW_CONVERSATIONS, true, VariantType.STRING)
             .activate.connect(on_contact_show_conversations);
-        add_action(ACTION_CONVERSATION_NEW, true, new VariantType("(ss)"))
-            // XXX
-            ;
+        add_action(ACTION_CONVERSATION_NEW, true, ConversationMessage.MAILBOX_TYPE)
+            .activate.connect(on_new_conversation);
         add_action(ACTION_COPY_EMAIL, true, VariantType.STRING)
             .activate.connect(on_copy_email_address);
         add_action(ACTION_COPY_LINK, true, VariantType.STRING)
@@ -1151,6 +1152,20 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
         }
     }
 
+    private void on_new_conversation(Variant? param) {
+        MainWindow? main = this.get_toplevel() as MainWindow;
+        if (main != null &&
+            param.get_type().equal(ConversationMessage.MAILBOX_TYPE)) {
+            string? name = (string) param.get_child_value(0);
+            Geary.RFC822.MailboxAddress mailbox = new Geary.RFC822.MailboxAddress(
+                Geary.String.is_empty_or_whitespace(name) ? null : name,
+                (string) param.get_child_value(1)
+            );
+
+            main.open_composer_for_mailbox(mailbox);
+        }
+    }
+
     private void on_copy_link(Variant? param) {
         Gtk.Clipboard clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD);
         clipboard.set_text(param.get_string(), -1);


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