[geary/wip/765516-gtk-widget-conversation-viewer: 45/80] Ensure message are marked ready when their message bodies are visible.
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/765516-gtk-widget-conversation-viewer: 45/80] Ensure message are marked ready when their message bodies are visible.
- Date: Thu, 16 Jun 2016 04:16:36 +0000 (UTC)
commit a14d2937b9323681595380e22be8e704f876ccdd
Author: Michael James Gratton <mike vee net>
Date: Sat Apr 16 18:10:49 2016 +1000
Ensure message are marked ready when their message bodies are visible.
* src/client/conversation-viewer/conversation-message.vala: Keep track of
the web_view's allocation so we can work out if it is visible, and the
loading state of the web_view so we know if it should be considered or
not.
(ConversationMessage::load_message_body): Rearranged a bit so only one
web_view.load_status signal handler is needed and there isn't a race
between loading completion and showing remote images. Also set the new
is_loading_complete property.
* src/client/conversation-viewer/conversation-viewer.vala
(check_mark_read): Reimplement using widget coordinates rather than
HTML coordinates.
.../conversation-viewer/conversation-message.vala | 57 ++++++++++++------
.../conversation-viewer/conversation-viewer.vala | 62 +++++++++++++------
2 files changed, 80 insertions(+), 39 deletions(-)
---
diff --git a/src/client/conversation-viewer/conversation-message.vala
b/src/client/conversation-viewer/conversation-message.vala
index afc42d4..941fa86 100644
--- a/src/client/conversation-viewer/conversation-message.vala
+++ b/src/client/conversation-viewer/conversation-message.vala
@@ -54,6 +54,12 @@ public class ConversationMessage : Gtk.Box {
// The HTML viewer to view the emails.
public ConversationWebView web_view { get; private set; }
+ // The allocation for the web view
+ public Gdk.Rectangle web_view_allocation { get; private set; }
+
+ // Has the message body been been fully loaded?
+ public bool is_loading_complete = false;
+
[GtkChild]
private Gtk.Image avatar_image;
@@ -180,8 +186,9 @@ public class ConversationMessage : Gtk.Box {
// web_view.context_menu.connect(() => { return true; }); // Suppress default context menu.
// web_view.realize.connect( () => { web_view.get_vadjustment().value_changed.connect(mark_read); });
// web_view.size_allocate.connect(mark_read);
- web_view.realize.connect(() => { debug("web_view: realised"); });
- web_view.size_allocate.connect(() => { debug("web_view: allocated"); });
+ web_view.size_allocate.connect((widget, allocation) => {
+ web_view_allocation = allocation;
+ });
body_box.set_has_tooltip(true);
web_view.hovering_over_link.connect(on_hovering_over_link);
@@ -372,6 +379,10 @@ public class ConversationMessage : Gtk.Box {
return menu;
}
+ public bool is_manual_read() {
+ return get_style_context().has_class("geary_manual_read");
+ }
+
public void update_flags(Geary.Email email) {
Geary.EmailFlags flags = email.email_flags;
Gtk.StyleContext style = get_style_context();
@@ -404,17 +415,35 @@ public class ConversationMessage : Gtk.Box {
private void load_message_body() {
bool remote_images = false;
+ bool load_images = false;
string body_text = "";
try {
- body_text = message.get_body(Geary.RFC822.TextFormat.HTML, inline_image_replacer) ?? "";
+ body_text = message.get_body(
+ Geary.RFC822.TextFormat.HTML, inline_image_replacer
+ ) ?? "";
} catch (Error err) {
debug("Could not get message text. %s", err.message);
}
body_text = clean_html_markup(body_text, message, out remote_images);
+ if (remote_images) {
+ Geary.Contact contact =
+ containing_folder.account.get_contact_store().get_by_rfc822(
+ email.get_primary_originator()
+ );
+ bool always_load = contact != null && contact.always_load_remote_images();
+ if (always_load || email.load_remote_images().is_certain()) {
+ load_images = true;
+ } else {
+ remote_images_infobar.show();
+ }
+ }
web_view.notify["load-status"].connect((source, param) => {
if (web_view.load_status == WebKit.LoadStatus.FINISHED) {
+ if (load_images) {
+ show_images(false);
+ }
WebKit.DOM.HTMLElement html = (
web_view.get_dom_document().document_element as
WebKit.DOM.HTMLElement
@@ -433,25 +462,15 @@ public class ConversationMessage : Gtk.Box {
(Callback) on_show_quote_clicked, this);
bind_event(web_view, ".quote_container > .hider", "click",
(Callback) on_hide_quote_clicked, this);
+
+ // XXX Not actually true since remote images will
+ // still be loading.
+ is_loading_complete = true;
}
});
- web_view.load_string(body_text, "text/html", "UTF8", "");
- if (remote_images) {
- Geary.Contact contact = containing_folder.account.get_contact_store().get_by_rfc822(
- email.get_primary_originator());
- bool always_load = contact != null && contact.always_load_remote_images();
-
- if (always_load || email.load_remote_images().is_certain()) {
- web_view.notify["load-status"].connect((source, param) => {
- if (web_view.load_status == WebKit.LoadStatus.FINISHED) {
- show_images(false);
- }
- });
- } else {
- remote_images_infobar.show();
- }
- }
+ // Only load it after we've hooked up the load-status signal above
+ web_view.load_string(body_text, "text/html", "UTF8", "");
}
// This delegate is called from within Geary.RFC822.Message.get_body while assembling the plain
diff --git a/src/client/conversation-viewer/conversation-viewer.vala
b/src/client/conversation-viewer/conversation-viewer.vala
index 73a56e8..5ab12ba 100644
--- a/src/client/conversation-viewer/conversation-viewer.vala
+++ b/src/client/conversation-viewer/conversation-viewer.vala
@@ -151,6 +151,11 @@ public class ConversationViewer : Gtk.Stack {
toggle_show_message(row);
}
});
+ conversation_listbox.realize.connect(() => {
+ conversation_page.get_vadjustment()
+ .value_changed.connect(check_mark_read);
+ });
+ conversation_listbox.size_allocate.connect(check_mark_read);
// Setup state machine for search/find states.
Geary.State.Mapping[] mappings = {
@@ -201,26 +206,43 @@ public class ConversationViewer : Gtk.Stack {
}
public void check_mark_read() {
- Gee.ArrayList<Geary.EmailIdentifier> emails = new Gee.ArrayList<Geary.EmailIdentifier>();
- // foreach (Geary.Email message in messages) {
- // try {
- // if (message.email_flags.is_unread()) {
- // ConversationMessage row = conversation_message_for_id(message.id);
- // if (!row.is_manual_read() &&
- // body.offset_top + body.offset_height > scroll_top &&
- // body.offset_top + 28 < scroll_top + scroll_height) { // 28 = 15 padding + 13 first
line of text
- // emails.add(message.id);
-
- // // since it can take some time for the new flags
- // // to round-trip back to ConversationViewer's
- // // signal handlers, mark as manually read here
- // mark_manual_read(message.id);
- // }
- // }
- // } catch (Error error) {
- // debug("Problem checking email class: %s", error.message);
- // }
- // }
+ Gee.ArrayList<Geary.EmailIdentifier> emails =
+ new Gee.ArrayList<Geary.EmailIdentifier>();
+
+ Gtk.Adjustment adj = conversation_page.vadjustment;
+ int top_bound = (int) adj.value;
+ int bottom_bound = top_bound + (int) adj.page_size;
+
+ const int TEXT_PADDING = 50;
+ foreach (Geary.Email message in messages) {
+ ConversationMessage row = conversation_message_for_id(message.id);
+ // Don't bother with not-yet-loaded messages since the
+ // size of the body will be off, affecting the visibility
+ // of messages further down the conversation.
+ if (message.email_flags.is_unread() &&
+ row.is_loading_complete &&
+ !row.is_manual_read()) {
+ int body_top = 0;
+ int body_left = 0;
+ row.web_view.translate_coordinates(
+ conversation_listbox,
+ 0, 0,
+ out body_left, out body_top
+ );
+ int body_bottom = body_top + row.web_view_allocation.height;
+
+ // Only mark the message as read if it's actually visible
+ if (body_bottom > top_bound &&
+ body_top + TEXT_PADDING < bottom_bound) {
+ emails.add(message.id);
+
+ // Since it can take some time for the new flags
+ // to round-trip back to ConversationViewer's
+ // signal handlers, mark as manually read here
+ row.mark_manual_read();
+ }
+ }
+ }
if (emails.size > 0) {
Geary.EmailFlags flags = new Geary.EmailFlags();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]