[geary] Fix messages with search hits in bodies not being expanded. Bug 778033.



commit ae3374593f9d89f54e4bf40fd128dd3f6792e458
Author: Michael James Gratton <mike vee net>
Date:   Thu Feb 23 10:40:31 2017 +1100

    Fix messages with search hits in bodies not being expanded. Bug 778033.
    
    * src/client/conversation-viewer/conversation-web-view.vala
      (ConversationWebView): Add async ::highlight_search_terms with hacks to
      make WK2 find API work a bit more like the WK1 API.  Add
      ::unmark_search_terms method for consistency.
    
    * src/client/conversation-viewer/conversation-list-box.vala
      (ConversationListBox): Keep track of total number of search terms
      found, so we can notify the viewer and update to deal with heasrch
      highlighting now being async. Rename ::search_matches_found to
      ::search_matches_updated and add a count param, update call sites and
      handlers.
    
    * src/client/conversation-viewer/conversation-message.vala
      (ConversationMessage): Use search term highlighting on
      ConversationWebView rather than WebKit's API directly.
    
    * src/client/conversation-viewer/conversation-viewer.vala
      (ConversationViewer): Update find entry's primary icon to reflect
      whether any matches were found.

 .../conversation-viewer/conversation-list-box.vala |   50 ++++++++++---------
 .../conversation-viewer/conversation-message.vala  |   18 ++-----
 .../conversation-viewer/conversation-viewer.vala   |   12 ++++-
 .../conversation-viewer/conversation-web-view.vala |   49 +++++++++++++++++++
 4 files changed, 90 insertions(+), 39 deletions(-)
---
diff --git a/src/client/conversation-viewer/conversation-list-box.vala 
b/src/client/conversation-viewer/conversation-list-box.vala
index 97dffba..3073105 100644
--- a/src/client/conversation-viewer/conversation-list-box.vala
+++ b/src/client/conversation-viewer/conversation-list-box.vala
@@ -344,7 +344,10 @@ public class ConversationListBox : Gtk.ListBox {
     private ConversationRow? last_row = null;
 
     // Cached search terms to apply to new messages
-    private Gee.Set<string>? ordered_search_terms = null;
+    private Gee.Set<string>? search_terms = null;
+
+    // Total number of search matches found
+    private uint search_matches_found = 0;
 
     private uint loading_timeout_id = 0;
 
@@ -400,7 +403,7 @@ public class ConversationListBox : Gtk.ListBox {
         Geary.EmailFlags? flags_to_add, Geary.EmailFlags? flags_to_remove);
 
     /** Fired when an email that matches the current search terms is found. */
-    public signal void search_matches_found();
+    public signal void search_matches_updated(uint matches);
 
 
     /**
@@ -664,6 +667,7 @@ public class ConversationListBox : Gtk.ListBox {
                 if (!Geary.String.is_empty_or_whitespace(word))
                     search_matches.add(word);
             }
+
             if (!this.cancellable.is_cancelled()) {
                 highlight_search_terms(search_matches);
             }
@@ -675,16 +679,9 @@ public class ConversationListBox : Gtk.ListBox {
      *
      * Returns true if any were found, else returns false.
      */
-    public void highlight_search_terms(Gee.Set<string> search_matches) {
-        // Webkit's highlighting is ... weird.  In order to actually
-        // see all the highlighting you're applying, it seems
-        // necessary to start with the shortest string and work up.
-        // If you don't, it seems that shorter strings will overwrite
-        // longer ones, and you're left with incomplete highlighting.
-        Gee.TreeSet<string> ordered_matches =
-            new Gee.TreeSet<string>((a, b) => a.length - b.length);
-        ordered_matches.add_all(search_matches);
-        this.ordered_search_terms = ordered_matches;
+    public void highlight_search_terms(Gee.Set<string> terms) {
+        this.search_terms = terms;
+        this.search_matches_found = 0;
         foreach (Gtk.Widget child in get_children()) {
             EmailRow? row = child as EmailRow;
             if (row != null) {
@@ -697,7 +694,9 @@ public class ConversationListBox : Gtk.ListBox {
      * Removes search term highlighting from all messages.
      */
     public void unmark_search_terms() {
-        this.ordered_search_terms = null;
+        this.search_terms = null;
+        this.search_matches_found = 0;
+
         this.foreach((child) => {
                 EmailRow? row = child as EmailRow;
                 if (row != null) {
@@ -709,6 +708,7 @@ public class ConversationListBox : Gtk.ListBox {
                     }
                 }
             });
+        search_matches_updated(this.search_matches_found);
     }
 
     /**
@@ -830,7 +830,7 @@ public class ConversationListBox : Gtk.ListBox {
         }
 
         // Apply any existing search terms to the new row
-        if (this.ordered_search_terms != null) {
+        if (this.search_terms != null) {
             apply_search_terms(row);
         }
 
@@ -958,27 +958,29 @@ public class ConversationListBox : Gtk.ListBox {
     }
 
     private void apply_search_terms(EmailRow row) {
+        // Message bodies need to be loaded to be able to search for
+        // them?
         if (row.view.message_bodies_loaded) {
-            apply_search_terms_impl(row);
+            this.apply_search_terms_impl.begin(row);
         } else {
             row.view.notify["message-bodies-loaded"].connect(() => {
-                    apply_search_terms_impl(row);
+                    this.apply_search_terms_impl.begin(row);
                 });
         }
     }
 
-    private inline void apply_search_terms_impl(EmailRow row) {
+    // This should only be called from apply_search_terms above
+    private async void apply_search_terms_impl(EmailRow row) {
         bool found = false;
         foreach (ConversationMessage view in row.view) {
-                if (view.highlight_search_terms(this.ordered_search_terms) > 0) {
-                    found = true;
-                    break;
-                }
-        }
-        if (found) {
-            search_matches_found();
+            uint count = yield view.highlight_search_terms(this.search_terms);
+            if (count > 0) {
+                found = true;
+            }
+            this.search_matches_found += count;
         }
         row.is_search_match = found;
+        search_matches_updated(this.search_matches_found);
     }
 
     /**
diff --git a/src/client/conversation-viewer/conversation-message.vala 
b/src/client/conversation-viewer/conversation-message.vala
index f8e9c35..e6a1361 100644
--- a/src/client/conversation-viewer/conversation-message.vala
+++ b/src/client/conversation-viewer/conversation-message.vala
@@ -483,10 +483,11 @@ public class ConversationMessage : Gtk.Grid {
 
     /**
      * Highlights user search terms in the message view.
-     &
-     * Returns the number of matching search terms.
+     *
+     * Highlighting includes both in the message headers, and the
+     * mesage body. returns the number of matching search terms.
      */
-    public uint highlight_search_terms(Gee.Set<string> search_matches) {
+    public async uint highlight_search_terms(Gee.Set<string> search_matches) {
         // Remove existing highlights
         this.web_view.get_find_controller().search_finish();
 
@@ -502,16 +503,9 @@ public class ConversationMessage : Gtk.Grid {
                     ++headers_found;
                 }
             }
-
-            // XXX WK2
-            //webkit_found += this.web_view.mark_text_matches(raw_match, false, 0);
-            this.web_view.get_find_controller().search(
-                raw_match,
-                WebKit.FindOptions.CASE_INSENSITIVE,
-                1024
-            );
         }
 
+        webkit_found += yield this.web_view.highlight_search_terms(search_matches);
         return headers_found + webkit_found;
     }
 
@@ -522,7 +516,7 @@ public class ConversationMessage : Gtk.Grid {
         foreach (AddressFlowBoxChild address in this.searchable_addresses) {
             address.unmark_search_terms();
         }
-        web_view.get_find_controller().search_finish();
+        this.web_view.unmark_search_terms();
     }
 
     private SimpleAction add_action(string name, bool enabled, VariantType? type = null) {
diff --git a/src/client/conversation-viewer/conversation-viewer.vala 
b/src/client/conversation-viewer/conversation-viewer.vala
index 61dd49a..d18284c 100644
--- a/src/client/conversation-viewer/conversation-viewer.vala
+++ b/src/client/conversation-viewer/conversation-viewer.vala
@@ -204,9 +204,15 @@ public class ConversationViewer : Gtk.Stack {
         // are expanded and highlighted as they are added.
         this.conversation_find_next.set_sensitive(false);
         this.conversation_find_prev.set_sensitive(false);
-        new_list.search_matches_found.connect(() => {
-                this.conversation_find_next.set_sensitive(true);
-                this.conversation_find_prev.set_sensitive(true);
+        new_list.search_matches_updated.connect((count) => {
+                bool found = count > 0;
+                this.conversation_find_entry.set_icon_from_icon_name(
+                    Gtk.EntryIconPosition.PRIMARY,
+                    found || Geary.String.is_empty(this.conversation_find_entry.text)
+                    ? "edit-find-symbolic" : "computer-fail-symbolic"
+                );
+                this.conversation_find_next.set_sensitive(found);
+                this.conversation_find_prev.set_sensitive(found);
             });
         Gee.Set<string>? find_terms = get_find_search_terms();
         if (find_terms != null) {
diff --git a/src/client/conversation-viewer/conversation-web-view.vala 
b/src/client/conversation-viewer/conversation-web-view.vala
index 5ebfb61..588d39b 100644
--- a/src/client/conversation-viewer/conversation-web-view.vala
+++ b/src/client/conversation-viewer/conversation-web-view.vala
@@ -94,6 +94,55 @@ public class ConversationWebView : ClientWebView {
         return WebKitUtil.to_string(result);
     }
 
+    /**
+     * Highlights user search terms in the message view.
+     *
+     * Returns the number of matching search terms.
+     */
+    public async uint highlight_search_terms(Gee.Collection<string> search_matches) {
+        // XXX WK2 doesn't deal with the multiple highlighting
+        // required by search folder matches, only single highlighting
+        // for a fine-like interface. For now, just highlight the
+        // first term
+
+        uint found = 0;
+
+        WebKit.FindController controller = get_find_controller();
+        SourceFunc callback = this.highlight_search_terms.callback;
+        ulong found_handler = 0;
+        ulong not_found_handler = 0;
+
+        found_handler = controller.found_text.connect((count) => {
+                found = count;
+                controller.disconnect(found_handler);
+                controller.disconnect(not_found_handler);
+                callback();
+            });
+        not_found_handler = controller.failed_to_find_text.connect(() => {
+                controller.disconnect(found_handler);
+                controller.disconnect(not_found_handler);
+                callback();
+            });
+
+        controller.search(
+            Geary.Collection.get_first(search_matches),
+            WebKit.FindOptions.CASE_INSENSITIVE |
+            WebKit.FindOptions.WRAP_AROUND,
+            128
+        );
+
+        yield;
+
+        return found;
+    }
+
+    /**
+     * Unmarks any search terms highlighted in the message view.
+     */
+    public void unmark_search_terms() {
+        get_find_controller().search_finish();
+    }
+
     public override bool key_press_event(Gdk.EventKey event) {
         // WebView consumes a number of key presses for scrolling
         // itself internally, but we want them to navigate around in


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