[geary/wip/135-contact-popovers: 56/56] Implement spoofed email address UI for ContactsPopover



commit 6536e2cc07712390402b759e64155f058c8c329c
Author: Michael Gratton <mike vee net>
Date:   Wed Mar 27 17:07:28 2019 +1100

    Implement spoofed email address UI for ContactsPopover

 .../conversation-contact-popover.vala              |  84 ++--
 .../conversation-viewer/conversation-message.vala  |   7 +-
 ui/conversation-contact-popover.ui                 | 431 ++++++++++++++-------
 ui/geary.css                                       |   4 +
 4 files changed, 345 insertions(+), 181 deletions(-)
---
diff --git a/src/client/conversation-viewer/conversation-contact-popover.vala 
b/src/client/conversation-viewer/conversation-contact-popover.vala
index f7a95523..3f2dc10c 100644
--- a/src/client/conversation-viewer/conversation-contact-popover.vala
+++ b/src/client/conversation-viewer/conversation-contact-popover.vala
@@ -41,6 +41,9 @@ public class Conversation.ContactPopover : Gtk.Popover {
 
     private GLib.Cancellable load_cancellable = new GLib.Cancellable();
 
+    [GtkChild]
+    private Gtk.Grid contact_pane;
+
     [GtkChild]
     private Gtk.Image avatar;
 
@@ -65,6 +68,15 @@ public class Conversation.ContactPopover : Gtk.Popover {
     [GtkChild]
     private Gtk.ModelButton load_remote_button;
 
+    [GtkChild]
+    private Gtk.Grid deceptive_pane;
+
+    [GtkChild]
+    private Gtk.Label forged_email_label;
+
+    [GtkChild]
+    private Gtk.Label actual_email_label;
+
     private GLib.SimpleActionGroup actions = new GLib.SimpleActionGroup();
 
 
@@ -125,40 +137,52 @@ public class Conversation.ContactPopover : Gtk.Popover {
     }
 
     private void update() {
-        string display_name = this.contact.display_name;
-        this.contact_name.set_text(display_name);
+        if (!this.mailbox.is_spoofed()) {
+            this.contact_pane.show();
+            this.deceptive_pane.hide();
+
+            string display_name = this.contact.display_name;
+            this.contact_name.set_text(display_name);
+
+            if (!this.contact.display_name_is_email) {
+                this.contact_address.set_text(this.mailbox.address);
+            } else {
+                this.contact_name.vexpand = true;
+                this.contact_name.valign = FILL;
+                this.contact_address.hide();
+            }
 
-        if (!this.contact.display_name_is_email) {
-            this.contact_address.set_text(this.mailbox.address);
-        } else {
-            this.contact_name.vexpand = true;
-            this.contact_name.valign = FILL;
-            this.contact_address.hide();
-        }
+            bool is_desktop = this.contact.is_desktop_contact;
 
-        bool is_desktop = this.contact.is_desktop_contact;
+            bool starred = false;
+            bool unstarred = false;
+            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
+                )
+            );
+        } else {
+            this.deceptive_pane.show();
+            this.contact_pane.hide();
 
-        bool starred = false;
-        bool unstarred = false;
-        if (is_desktop) {
-            starred = this.contact.is_favourite;
-            unstarred = !this.contact.is_favourite;
+            this.forged_email_label.label = Geary.String.reduce_whitespace(
+                this.mailbox.name
+            );
+            this.actual_email_label.label = this.mailbox.address;
         }
-        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 open() {
diff --git a/src/client/conversation-viewer/conversation-message.vala 
b/src/client/conversation-viewer/conversation-message.vala
index ce8588d0..d423ba55 100644
--- a/src/client/conversation-viewer/conversation-message.vala
+++ b/src/client/conversation-viewer/conversation-message.vala
@@ -146,9 +146,10 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
                 // reduce the chance of the user of being tricked by
                 // malware.
                 primary.set_text(display_address);
-                this.displayed = new Geary.RFC822.MailboxAddress(
-                    null, this.source.address
-                );
+                // Use the source as the displayed address so that the
+                // contact popover uses the spoofed mailbox and
+                // displays it as being spoofed.
+                this.displayed = this.source;
             } else if (this.contact.is_trusted) {
                 // The contact's name can be trusted, so no need to
                 // display the email address
diff --git a/ui/conversation-contact-popover.ui b/ui/conversation-contact-popover.ui
index ca98a8fc..c899fb09 100644
--- a/ui/conversation-contact-popover.ui
+++ b/ui/conversation-contact-popover.ui
@@ -9,82 +9,248 @@
       <object class="GtkGrid">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
-        <property name="margin_left">10</property>
-        <property name="margin_right">10</property>
-        <property name="margin_top">10</property>
-        <property name="margin_bottom">10</property>
         <property name="orientation">vertical</property>
         <child>
-          <object class="GtkGrid">
+          <object class="GtkGrid" id="contact_pane">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
-            <property name="margin_bottom">6</property>
-            <property name="column_spacing">12</property>
+            <property name="margin_left">10</property>
+            <property name="margin_right">10</property>
+            <property name="margin_top">10</property>
+            <property name="margin_bottom">10</property>
+            <property name="orientation">vertical</property>
             <child>
-              <object class="GtkButton" id="unstarred_button">
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="halign">end</property>
-                <property name="valign">center</property>
-                <property name="action_name">con.star</property>
-                <property name="relief">none</property>
+              <object class="GtkGrid">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_bottom">6</property>
+                <property name="column_spacing">12</property>
                 <child>
-                  <object class="GtkImage">
+                  <object class="GtkButton" id="unstarred_button">
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="halign">end</property>
+                    <property name="valign">center</property>
+                    <property name="action_name">con.star</property>
+                    <property name="relief">none</property>
+                    <child>
+                      <object class="GtkImage">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="icon_name">non-starred-symbolic</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="top_attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="starred_button">
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="halign">end</property>
+                    <property name="valign">center</property>
+                    <property name="action_name">con.unstar</property>
+                    <property name="relief">none</property>
+                    <child>
+                      <object class="GtkImage">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="icon_name">starred-symbolic</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">3</property>
+                    <property name="top_attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkImage" id="avatar">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="pixel_size">48</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkGrid">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="icon_name">non-starred-symbolic</property>
+                    <property name="orientation">vertical</property>
+                    <child>
+                      <object class="GtkLabel" id="contact_name">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="halign">start</property>
+                        <property name="valign">end</property>
+                        <property name="vexpand">True</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="contact_address">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="halign">start</property>
+                        <property name="valign">start</property>
+                        <property name="margin_top">2</property>
+                        <property name="hexpand">False</property>
+                        <property name="vexpand">True</property>
+                        <property name="ellipsize">middle</property>
+                        <style>
+                          <class name="dim-label"/>
+                        </style>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">1</property>
+                      </packing>
+                    </child>
                   </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">0</property>
+                  </packing>
                 </child>
               </object>
               <packing>
-                <property name="left_attach">2</property>
+                <property name="left_attach">0</property>
                 <property name="top_attach">0</property>
               </packing>
             </child>
             <child>
-              <object class="GtkButton" id="starred_button">
+              <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="halign">end</property>
-                <property name="valign">center</property>
-                <property name="action_name">con.unstar</property>
-                <property name="relief">none</property>
-                <child>
-                  <object class="GtkImage">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="icon_name">starred-symbolic</property>
-                  </object>
-                </child>
+                <property name="action_name">con.new-conversation</property>
+                <property name="text" translatable="yes">New Conversation…</property>
               </object>
               <packing>
-                <property name="left_attach">3</property>
-                <property name="top_attach">0</property>
+                <property name="left_attach">0</property>
+                <property name="top_attach">2</property>
               </packing>
             </child>
             <child>
-              <object class="GtkImage" id="avatar">
+              <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>
-                <property name="pixel_size">48</property>
               </object>
               <packing>
                 <property name="left_attach">0</property>
-                <property name="top_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>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkGrid" id="deceptive_pane">
+            <property name="can_focus">False</property>
+            <property name="margin_left">10</property>
+            <property name="margin_right">10</property>
+            <property name="margin_top">10</property>
+            <property name="margin_bottom">10</property>
+            <property name="orientation">vertical</property>
+            <property name="row_spacing">6</property>
             <child>
               <object class="GtkGrid">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="orientation">vertical</property>
+                <property name="column_spacing">12</property>
                 <child>
-                  <object class="GtkLabel" id="contact_name">
+                  <object class="GtkImage">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="halign">start</property>
-                    <property name="valign">end</property>
-                    <property name="vexpand">True</property>
+                    <property name="pixel_size">36</property>
+                    <property name="icon_name">dialog-warning-symbolic</property>
                   </object>
                   <packing>
                     <property name="left_attach">0</property>
@@ -92,134 +258,103 @@
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkLabel" id="contact_address">
+                  <object class="GtkLabel">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="halign">start</property>
-                    <property name="valign">start</property>
-                    <property name="margin_top">2</property>
-                    <property name="hexpand">False</property>
-                    <property name="vexpand">True</property>
-                    <property name="ellipsize">middle</property>
+                    <property name="label" translatable="yes" comments="Title label on contact 
popover">Deceptive email address</property>
                     <style>
-                      <class name="dim-label"/>
+                      <class name="title"/>
                     </style>
                   </object>
                   <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">1</property>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">0</property>
                   </packing>
                 </child>
               </object>
               <packing>
-                <property name="left_attach">1</property>
+                <property name="left_attach">0</property>
                 <property name="top_attach">0</property>
               </packing>
             </child>
-          </object>
-          <packing>
-            <property name="left_attach">0</property>
-            <property name="top_attach">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkSeparator">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
+            <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="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes" comments="Contact popover label">This email 
address is:</property>
+                <property name="xalign">0</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="actual_email_label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <style>
+                  <class name="geary-deceptive"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">3</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes" comments="Contact popover label">But was forged 
as:</property>
+                <property name="xalign">0</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">4</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="forged_email_label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <style>
+                  <class name="geary-deceptive"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">5</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes" comments="Contact popover label">The sender may 
not be trustworthy</property>
+                <property name="xalign">0</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">6</property>
+              </packing>
+            </child>
           </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/geary.css b/ui/geary.css
index b7c061b4..10507392 100644
--- a/ui/geary.css
+++ b/ui/geary.css
@@ -180,6 +180,10 @@ grid.geary-message-summary {
   font-size: 80%;
 }
 
+.geary-contact-popover .geary-deceptive {
+  font-weight: bold;
+}
+
 /* Composer */
 
 .geary-composer-embed headerbar {


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