[geary/wip/135-contact-popovers: 16/26] Separate and implement contact popover action from conversation message
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/135-contact-popovers: 16/26] Separate and implement contact popover action from conversation message
- Date: Mon, 8 Apr 2019 00:28:19 +0000 (UTC)
commit 68b2da17c574486107d25f123fae0a2bad594ec8
Author: Michael Gratton <mike vee net>
Date: Sat Mar 16 19:56:33 2019 +1100
Separate and implement contact popover action from conversation message
This leads to a minor bit of UI string and code duplication, but
substantially reduces the complexity of implementing the popover's
actions. Hook up all remaining actions except open and save.
.../conversation-contact-popover.vala | 146 ++++++++++++++++-----
.../conversation-viewer/conversation-message.vala | 75 ++---------
ui/conversation-contact-popover.ui | 105 ++++++++++++++-
ui/conversation-message-menus.ui | 24 ----
4 files changed, 228 insertions(+), 122 deletions(-)
---
diff --git a/src/client/conversation-viewer/conversation-contact-popover.vala
b/src/client/conversation-viewer/conversation-contact-popover.vala
index 640bb015..75386fa3 100644
--- a/src/client/conversation-viewer/conversation-contact-popover.vala
+++ b/src/client/conversation-viewer/conversation-contact-popover.vala
@@ -12,15 +12,35 @@
public class Conversation.ContactPopover : Gtk.Popover {
+ private const string ACTION_COPY_EMAIL= "copy-email";
+ private const string ACTION_LOAD_REMOTE = "load-remote";
+ private const string ACTION_NEW_CONVERSATION = "new-conversation";
+ private const string ACTION_OPEN = "open";
+ private const string ACTION_SAVE = "save";
+ private const string ACTION_SHOW_CONVERSATIONS = "show-conversations";
+ private const string ACTION_STAR = "star";
+ private const string ACTION_UNSTAR = "unstar";
+
+ private const string ACTION_GROUP = "con";
+
+ private const GLib.ActionEntry[] ACTION_ENTRIES = {
+ {ACTION_COPY_EMAIL, on_copy_email, },
+ {ACTION_LOAD_REMOTE, on_load_remote, null, "false" },
+ {ACTION_NEW_CONVERSATION, on_new_conversation },
+ {ACTION_OPEN, on_open },
+ {ACTION_SAVE, on_save },
+ {ACTION_SHOW_CONVERSATIONS, on_show_conversations },
+ {ACTION_STAR, on_star, },
+ {ACTION_UNSTAR, on_unstar, },
+ };
+
+
public Application.Contact contact { get; private set; }
public Geary.RFC822.MailboxAddress mailbox { get; private set; }
private GLib.Cancellable load_cancellable = new GLib.Cancellable();
- [GtkChild]
- private Gtk.Grid container;
-
[GtkChild]
private Gtk.Image avatar;
@@ -36,45 +56,35 @@ public class Conversation.ContactPopover : Gtk.Popover {
[GtkChild]
private Gtk.Button unstarred_button;
+ [GtkChild]
+ private Gtk.ModelButton open_button;
+
+ [GtkChild]
+ private Gtk.ModelButton save_button;
+
+ [GtkChild]
+ private Gtk.ModelButton load_remote_button;
+
+ private GLib.SimpleActionGroup actions = new GLib.SimpleActionGroup();
+
public ContactPopover(Gtk.Widget relative_to,
Application.Contact contact,
Geary.RFC822.MailboxAddress mailbox) {
+
this.relative_to = relative_to;
this.contact = contact;
this.mailbox = mailbox;
+ this.load_remote_button.role = CHECK;
+
+ this.actions.add_action_entries(ACTION_ENTRIES, this);
+ insert_action_group(ACTION_GROUP, this.actions);
+
contact.changed.connect(this.on_contact_changed);
update();
}
- public void add_section(GLib.MenuModel section,
- Gee.Map<string,GLib.Variant> values) {
- Gtk.Separator separator = new Gtk.Separator(Gtk.Orientation.HORIZONTAL);
- separator.show();
- this.container.add(separator);
- for (int i = 0; i < section.get_n_items(); i++) {
- GLib.MenuItem item = new MenuItem.from_model(section, i);
- string action_fq = (string) item.get_attribute_value(
- Menu.ATTRIBUTE_ACTION, VariantType.STRING
- );
-
- string action_name = action_fq.substring(action_fq.index_of(".") + 1);
-
- Gtk.ModelButton button = new Gtk.ModelButton();
- button.text = (string) item.get_attribute_value(
- Menu.ATTRIBUTE_LABEL, VariantType.STRING
- );
- button.action_name = (string) item.get_attribute_value(
- Menu.ATTRIBUTE_ACTION, VariantType.STRING
- );
- button.action_target = values[action_name];
- button.show();
-
- this.container.add(button);
- }
- }
-
/**
* Starts loading the avatar for the message's sender.
*/
@@ -121,20 +131,94 @@ public class Conversation.ContactPopover : Gtk.Popover {
this.contact_address.hide();
}
+ bool is_desktop = this.contact.is_desktop_contact;
+
bool starred = false;
bool unstarred = false;
- if (this.contact.is_desktop_contact) {
+ if (is_desktop) {
starred = this.contact.is_favourite;
unstarred = !this.contact.is_favourite;
}
this.starred_button.set_visible(starred);
this.unstarred_button.set_visible(unstarred);
+
+
+ this.open_button.set_visible(is_desktop);
+ this.save_button.set_visible(!is_desktop);
+ this.load_remote_button.set_visible(!is_desktop);
+
+ GLib.SimpleAction load_remote = (GLib.SimpleAction)
+ actions.lookup_action(ACTION_LOAD_REMOTE);
+ load_remote.set_state(
+ new GLib.Variant.boolean(
+ is_desktop || this.contact.load_remote_resources
+ )
+ );
+ }
+
+ private async void set_load_remote_resources(bool enabled) {
+ try {
+ yield this.contact.set_remote_resource_loading(enabled, null);
+ } catch (GLib.Error err) {
+ debug("Failed to set load remote resources for contact %s:, %s",
+ this.contact.to_string(), err.message);
+ }
+ }
+
+ private async void set_favourite(bool enabled) {
+ try {
+ yield this.contact.set_favourite(enabled, null);
+ } catch (GLib.Error err) {
+ debug("Failed to set enabled state for contact %s:, %s",
+ this.contact.to_string(), err.message);
+ }
}
private void on_contact_changed() {
update();
}
+ private void on_copy_email() {
+ Gtk.Clipboard clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD);
+ clipboard.set_text(this.mailbox.to_full_display(), -1);
+ clipboard.store();
+ }
+
+ private void on_load_remote(GLib.SimpleAction action) {
+ bool state = !action.get_state().get_boolean();
+ this.set_load_remote_resources.begin(state);
+ }
+
+ private void on_new_conversation() {
+ MainWindow? main = this.get_toplevel() as MainWindow;
+ if (main != null) {
+ main.open_composer_for_mailbox(this.mailbox);
+ }
+ }
+
+ private void on_open() {
+
+ }
+
+ private void on_save() {
+
+ }
+
+ private void on_show_conversations() {
+ MainWindow? main = this.get_toplevel() as MainWindow;
+ if (main != null) {
+ main.show_search_bar("from:%s".printf(this.mailbox.address));
+ }
+ }
+
+ private void on_star() {
+ this.set_favourite.begin(true);
+ }
+
+ private void on_unstar() {
+ this.set_favourite.begin(false);
+ }
+
[GtkCallback]
private void after_closed() {
GLib.Idle.add(() => {
diff --git a/src/client/conversation-viewer/conversation-message.vala
b/src/client/conversation-viewer/conversation-message.vala
index 47941785..e7daec28 100644
--- a/src/client/conversation-viewer/conversation-message.vala
+++ b/src/client/conversation-viewer/conversation-message.vala
@@ -32,11 +32,6 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
private const int MAX_INLINE_IMAGE_MAJOR_DIM = 1024;
- private const string ACTION_CONTACT_LOAD_IMAGES = "contact-load-images";
- private const string ACTION_CONTACT_OPEN = "contact-open";
- private const string ACTION_CONTACT_SAVE = "contact-save";
- private const string ACTION_CONTACT_SHOW_CONVERSATIONS =
- "contact-show-conversations";
private const string ACTION_CONVERSATION_NEW = "conversation-new";
private const string ACTION_COPY_EMAIL = "copy-email";
private const string ACTION_COPY_LINK = "copy-link";
@@ -203,9 +198,6 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
}
- private static GLib.VariantType MAILBOX_TYPE = new GLib.VariantType("(ss)");
-
-
/** Contact for the primary originator, if any. */
internal Application.Contact? primary_contact {
get; private set;
@@ -305,8 +297,6 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
private MenuModel context_menu_email;
private MenuModel context_menu_image;
private MenuModel context_menu_main;
- private MenuModel context_menu_known_contact;
- private MenuModel context_menu_unknown_contact;
private MenuModel? context_menu_inspector = null;
// Address fields that can be search through
@@ -406,18 +396,7 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
// Actions
- add_action(ACTION_CONTACT_LOAD_IMAGES, true, VariantType.BOOLEAN)
- // XXX
- ;
- add_action(ACTION_CONTACT_OPEN, true, VariantType.STRING)
- // XXX
- ;
- 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, ConversationMessage.MAILBOX_TYPE)
+ add_action(ACTION_CONVERSATION_NEW, true, VariantType.STRING)
.activate.connect(on_new_conversation);
add_action(ACTION_COPY_EMAIL, true, VariantType.STRING)
.activate.connect(on_copy_email_address);
@@ -447,12 +426,6 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
context_menu_email = (MenuModel) builder.get_object("context_menu_email");
context_menu_image = (MenuModel) builder.get_object("context_menu_image");
context_menu_main = (MenuModel) builder.get_object("context_menu_main");
- this.context_menu_known_contact = (MenuModel) builder.get_object(
- "context_menu_known_contact"
- );
- this.context_menu_unknown_contact = (MenuModel) builder.get_object(
- "context_menu_unknown_contact"
- );
if (Args.inspector) {
context_menu_inspector =
(MenuModel) builder.get_object("context_menu_inspector");
@@ -1080,17 +1053,6 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
Gee.Map<string,GLib.Variant> values =
new Gee.HashMap<string,GLib.Variant>();
-
- GLib.Variant mailbox_var = new GLib.Variant.tuple(
- new GLib.Variant[] {
- address.name ?? "",
- address.address
- });
- values[ACTION_CONTACT_OPEN] = "not yet defined";
- values[ACTION_CONTACT_SAVE] = mailbox_var;
- values[ACTION_CONTACT_SHOW_CONVERSATIONS] = address.address;
- values[ACTION_CONTACT_LOAD_IMAGES] = false;
- values[ACTION_CONVERSATION_NEW] = mailbox_var;
values[ACTION_COPY_EMAIL] = address.to_full_display();
Conversation.ContactPopover popover = new Conversation.ContactPopover(
@@ -1099,13 +1061,6 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
address
);
popover.load_avatar.begin();
- popover.add_section(this.context_menu_email, values);
- popover.add_section(
- address_child.contact.is_desktop_contact
- ? this.context_menu_known_contact
- : this.context_menu_unknown_contact,
- values
- );
popover.set_position(Gtk.PositionType.BOTTOM);
popover.closed.connect(() => {
address_child.unset_state_flags(Gtk.StateFlags.ACTIVE);
@@ -1245,34 +1200,28 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
remote_images_infobar.hide();
}
- private void on_contact_show_conversations(Variant? param) {
- string email = param as string;
- MainWindow? main = this.get_toplevel() as MainWindow;
- if (main != null && email != null) {
- main.show_search_bar("from:%s".printf(email));
- }
+ private void on_copy_link(Variant? param) {
+ Gtk.Clipboard clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD);
+ clipboard.set_text(param.get_string(), -1);
+ clipboard.store();
}
private void on_new_conversation(Variant? param) {
+ string value = param.get_string();
+ if (value.has_prefix(Geary.ComposedEmail.MAILTO_SCHEME)) {
+ value = value.substring(Geary.ComposedEmail.MAILTO_SCHEME.length, -1);
+ }
+
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.is_valid_address(value)) {
Geary.RFC822.MailboxAddress mailbox = new Geary.RFC822.MailboxAddress(
- Geary.String.is_empty_or_whitespace(name) ? null : name,
- (string) param.get_child_value(1)
+ null, value
);
-
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);
- clipboard.store();
- }
-
private void on_copy_email_address(Variant? param) {
string value = param.get_string();
if (value.has_prefix(Geary.ComposedEmail.MAILTO_SCHEME)) {
diff --git a/ui/conversation-contact-popover.ui b/ui/conversation-contact-popover.ui
index b533f3d0..ca98a8fc 100644
--- a/ui/conversation-contact-popover.ui
+++ b/ui/conversation-contact-popover.ui
@@ -6,7 +6,7 @@
<property name="can_focus">False</property>
<signal name="closed" handler="after_closed" after="yes" swapped="no"/>
<child>
- <object class="GtkGrid" id="container">
+ <object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">10</property>
@@ -14,7 +14,6 @@
<property name="margin_top">10</property>
<property name="margin_bottom">10</property>
<property name="orientation">vertical</property>
- <property name="row_spacing">2</property>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
@@ -27,7 +26,7 @@
<property name="receives_default">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
- <property name="action_name">msg.contact-star</property>
+ <property name="action_name">con.star</property>
<property name="relief">none</property>
<child>
<object class="GtkImage">
@@ -48,7 +47,7 @@
<property name="receives_default">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
- <property name="action_name">msg.contact-star</property>
+ <property name="action_name">con.unstar</property>
<property name="relief">none</property>
<child>
<object class="GtkImage">
@@ -123,6 +122,104 @@
<property name="top_attach">0</property>
</packing>
</child>
+ <child>
+ <object class="GtkSeparator">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkModelButton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="action_name">con.new-conversation</property>
+ <property name="text" translatable="yes">_New Conversation…</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkModelButton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="action_name">con.copy-email</property>
+ <property name="text" translatable="yes">Copy Email _Address</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparator">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkModelButton" id="save_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="action_name">con.save</property>
+ <property name="text" translatable="yes">Save in Contacts…</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkModelButton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="action_name">con.show-conversations</property>
+ <property name="text" translatable="yes">Show Conversations</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkModelButton" id="open_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="action_name">con.open</property>
+ <property name="text" translatable="yes">Open in Contacts</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkModelButton" id="load_remote_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="action_name">con.load-remote</property>
+ <property name="text" translatable="yes">Always Load Remote Images</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">8</property>
+ </packing>
+ </child>
</object>
</child>
<style>
diff --git a/ui/conversation-message-menus.ui b/ui/conversation-message-menus.ui
index 27d70c6d..32d0be1c 100644
--- a/ui/conversation-message-menus.ui
+++ b/ui/conversation-message-menus.ui
@@ -38,30 +38,6 @@
<attribute name="action">msg.copy-selection</attribute>
</item>
</section>
- <section id="context_menu_known_contact">
- <item>
- <attribute name="label" translatable="yes">Sho_w Conversations</attribute>
- <attribute name="action">msg.contact-show-conversations</attribute>
- </item>
- <item>
- <attribute name="label" translatable="yes">_Open in Contacts…</attribute>
- <attribute name="action">msg.contact-save</attribute>
- </item>
- </section>
- <section id="context_menu_unknown_contact">
- <item>
- <attribute name="label" translatable="yes">Sho_w Conversations</attribute>
- <attribute name="action">msg.contact-show-conversations</attribute>
- </item>
- <item>
- <attribute name="label" translatable="yes">Save in Con_tacts…</attribute>
- <attribute name="action">msg.contact-save</attribute>
- </item>
- <item>
- <attribute name="label" translatable="yes">Always Load Remote Images</attribute>
- <attribute name="action">msg.contact-load-images</attribute>
- </item>
- </section>
<section id="context_menu_inspector">
<item>
<attribute name="label" translatable="yes">_Inspect…</attribute>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]