[geary] Fix messages with search hits in bodies not being expanded. Bug 778033.
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary] Fix messages with search hits in bodies not being expanded. Bug 778033.
- Date: Thu, 23 Feb 2017 00:33:53 +0000 (UTC)
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]