[california] Hit link attendee email address when showing events: Bug #740092



commit 00c999454072c72a494fc406bb3ea309dae30109
Author: Jim Nelson <jim yorba org>
Date:   Thu Nov 13 17:24:07 2014 -0800

    Hit link attendee email address when showing events: Bug #740092
    
    This moves some of the code out of util/util-uri.vala into a new
    email utility file, since the code was not entirely related to URIs.

 src/Makefile.am                     |    1 +
 src/component/component-person.vala |    5 +++-
 src/host/host-attendees-editor.vala |    6 ++--
 src/host/host-show-event.vala       |   18 ++++++++++---
 src/rc/show-event.ui                |    2 +
 src/util/util-email.vala            |   47 +++++++++++++++++++++++++++++++++++
 src/util/util-uri.vala              |   28 --------------------
 src/util/util.vala                  |    4 +-
 8 files changed, 73 insertions(+), 38 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index f5fc807..2dd4438 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -150,6 +150,7 @@ california_VALASOURCES = \
        toolkit/toolkit-stack-model.vala \
        \
        util/util.vala \
+       util/util-email.vala \
        util/util-gfx.vala \
        util/util-markup.vala \
        util/util-memory.vala \
diff --git a/src/component/component-person.vala b/src/component/component-person.vala
index d38554d..5c92f68 100644
--- a/src/component/component-person.vala
+++ b/src/component/component-person.vala
@@ -42,6 +42,9 @@ public class Person : BaseObject, Gee.Hashable<Person>, Gee.Comparable<Person> {
     
     /**
      * The CN (common name) for the { link Person}.
+     *
+     * Note that it's common for agents to use the { link mailbox} for the common name if a name
+     * is not given when producing the component.
      */
     public string? common_name { get; private set; default = null; }
     
@@ -171,7 +174,7 @@ public class Person : BaseObject, Gee.Hashable<Person>, Gee.Comparable<Person> {
     }
     
     private static void validate_mailto(Soup.URI uri) throws ComponentError {
-        if (!String.ci_equal(uri.scheme, "mailto") || String.is_empty(uri.path) || 
!URI.is_valid_mailbox(uri.path))
+        if (!String.ci_equal(uri.scheme, "mailto") || String.is_empty(uri.path) || 
!Email.is_valid_mailbox(uri.path))
             throw new ComponentError.INVALID("Invalid mailto: %s", uri.to_string(false));
     }
     
diff --git a/src/host/host-attendees-editor.vala b/src/host/host-attendees-editor.vala
index 51a12db..74d465b 100644
--- a/src/host/host-attendees-editor.vala
+++ b/src/host/host-attendees-editor.vala
@@ -47,7 +47,7 @@ public class AttendeesEditor : Gtk.Box, Toolkit.Card {
     
     private bool transform_add_guest_text_to_button(Binding binding, Value source_value,
         ref Value target_value) {
-        target_value = URI.is_valid_mailbox(add_guest_entry.text);
+        target_value = Email.is_valid_mailbox(add_guest_entry.text);
         
         return true;
     }
@@ -91,13 +91,13 @@ public class AttendeesEditor : Gtk.Box, Toolkit.Card {
     [GtkCallback]
     private void on_add_guest_button_clicked() {
         string mailbox = add_guest_entry.text.strip();
-        if (!URI.is_valid_mailbox(mailbox))
+        if (!Email.is_valid_mailbox(mailbox))
             return;
         
         try {
             // add to model (which adds to listbox) and clear entry
             guest_model.add(new Component.Person(Component.Person.Relationship.ATTENDEE,
-                URI.generate_mailto(mailbox)));
+                Email.generate_mailto_uri(mailbox)));
             add_guest_entry.text = "";
         } catch (Error err) {
             debug("Unable to generate mailto from \"%s\": %s", mailbox, err.message);
diff --git a/src/host/host-show-event.vala b/src/host/host-show-event.vala
index 8511eaa..721156d 100644
--- a/src/host/host-show-event.vala
+++ b/src/host/host-show-event.vala
@@ -170,7 +170,7 @@ public class ShowEvent : Gtk.Grid, Toolkit.Card {
         // organizers as a sorted LF-delimited string
         string organizers = traverse<Component.Person>(event.organizers)
             .sort()
-            .to_string(stringify_person) ?? "";
+            .to_string(stringify_person_markup) ?? "";
         organizers_label.label = ngettext("Organizer", "Organizers", event.organizers.size);
         set_label(organizers_label, organizers_text, organizers);
         
@@ -178,7 +178,7 @@ public class ShowEvent : Gtk.Grid, Toolkit.Card {
         string attendees = traverse<Component.Person>(event.attendees)
             .filter(person => !event.organizers.contains(person))
             .sort()
-            .to_string(stringify_person) ?? "";
+            .to_string(stringify_person_markup) ?? "";
         int attendee_count = traverse<Component.Person>(event.attendees)
             .filter(person => !event.organizers.contains(person))
             .count();
@@ -227,8 +227,18 @@ public class ShowEvent : Gtk.Grid, Toolkit.Card {
         return true;
     }
     
-    private string? stringify_person(Component.Person person, bool is_first, bool is_last) {
-        return "%s%s".printf(person.full_mailbox, is_last ? "" : "\n");
+    private string? stringify_person_markup(Component.Person person, bool is_first, bool is_last) {
+        // keep adding linefeeds until the last address
+        unowned string suffix = is_last ? "" : "\n";
+        
+        // more complicated if full name available: link only the email address inside the brackets
+        if (!String.is_empty(person.common_name) && !String.ci_equal(person.common_name, person.mailbox)) {
+            return "%s &lt;<a href=\"%s\">%s</a>&gt;%s".printf(escape(person.common_name), 
person.mailto_text,
+                escape(person.mailbox), suffix);
+        }
+        
+        // otherwise, only the email address
+        return "<a href=\"%s\">%s</a>%s".printf(person.mailto_text, escape(person.mailbox), suffix);
     }
     
     // Note that text is not escaped, up to caller to determine if necessary or not.
diff --git a/src/rc/show-event.ui b/src/rc/show-event.ui
index 450532f..53a14ee 100644
--- a/src/rc/show-event.ui
+++ b/src/rc/show-event.ui
@@ -156,6 +156,7 @@
             <property name="xalign">0</property>
             <property name="yalign">0</property>
             <property name="label">(empty)</property>
+            <property name="use_markup">True</property>
             <property name="selectable">True</property>
             <property name="ellipsize">end</property>
           </object>
@@ -216,6 +217,7 @@
             <property name="xalign">0</property>
             <property name="yalign">0</property>
             <property name="label">(empty)</property>
+            <property name="use_markup">True</property>
             <property name="selectable">True</property>
           </object>
           <packing>
diff --git a/src/util/util-email.vala b/src/util/util-email.vala
new file mode 100644
index 0000000..e6539b7
--- /dev/null
+++ b/src/util/util-email.vala
@@ -0,0 +1,47 @@
+/* Copyright 2014 Yorba Foundation
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later).  See the COPYING file in this distribution.
+ */
+
+namespace California.Email {
+
+private Regex email_regex;
+
+internal void init() throws Error {
+    // http://www.regular-expressions.info/email.html
+    // matches john dep aol museum not john aol   com
+    email_regex = new Regex("[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,5}", RegexCompileFlags.CASELESS);
+}
+
+internal void terminate() {
+    email_regex = null;
+}
+
+/**
+ * Validates a string as a valid RFC822 mailbox (i.e. email) address.
+ */
+public bool is_valid_mailbox(string str) {
+    return email_regex.match(str);
+}
+
+/**
+ * Generates a valid mailto: as a text string.
+ *
+ * No validity checking is done here on the mailbox; use { link is_valid_mailbox}.
+ */
+public string generate_mailto_text(string mailbox) {
+    return "mailto:%s".printf(GLib.Uri.escape_string(mailbox, "@"));
+}
+
+/**
+ * Generates a valid mailto: Soup.URI given a mailbox (i.e. email) address.
+ *
+ * No validity checking is done here on the mailbox; use { link is_valid_mailbox}.
+ */
+public Soup.URI generate_mailto_uri(string mailbox) throws Error {
+    return URI.parse(generate_mailto_text(mailbox));
+}
+
+}
+
diff --git a/src/util/util-uri.vala b/src/util/util-uri.vala
index cd92c53..83390ed 100644
--- a/src/util/util-uri.vala
+++ b/src/util/util-uri.vala
@@ -14,18 +14,6 @@ errordomain URIError {
 
 namespace California.URI {
 
-private Regex email_regex;
-
-internal void init() throws Error {
-    // http://www.regular-expressions.info/email.html
-    // matches john dep aol museum not john aol   com
-    email_regex = new Regex("[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,5}", RegexCompileFlags.CASELESS);
-}
-
-internal void terminate() {
-    email_regex = null;
-}
-
 /**
  * Basic validation of a string intended to be parsed as an absolute URI.
  *
@@ -69,21 +57,5 @@ public Soup.URI parse(string uri) throws Error {
     return parsed;
 }
 
-/**
- * Validates a string as a valid RFC822 mailbox (i.e. email) address.
- */
-public bool is_valid_mailbox(string str) {
-    return email_regex.match(str);
-}
-
-/**
- * Generates a valid mailto: Soup.URI given a mailbox (i.e. email) address.
- *
- * No validity checking is done here on the mailbox; use { link is_valid_mailbox}.
- */
-public Soup.URI generate_mailto(string mailbox) throws Error {
-    return parse("mailto:%s".printf(GLib.Uri.escape_string(mailbox, "@")));
-}
-
 }
 
diff --git a/src/util/util.vala b/src/util/util.vala
index 66337b3..bece1fd 100644
--- a/src/util/util.vala
+++ b/src/util/util.vala
@@ -14,14 +14,14 @@ public void init() throws Error {
     
     // internal init
     Markup.init();
-    URI.init();
+    Email.init();
 }
 
 public void terminate() {
     if (!Unit.do_terminate(ref init_count))
         return;
     
-    URI.terminate();
+    Email.terminate();
     Markup.terminate();
 }
 


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