[geary/wip/728002-webkit2: 68/96] Add an OSD prgress bar for remote image loading.
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/728002-webkit2: 68/96] Add an OSD prgress bar for remote image loading.
- Date: Sat, 14 Jan 2017 12:17:32 +0000 (UTC)
commit c669d2d6177dd1e6447a78a90fd468b6b17ac888
Author: Michael James Gratton <mike vee net>
Date: Tue Jan 3 20:30:49 2017 +1100
Add an OSD prgress bar for remote image loading.
* src/client/conversation-viewer/conversation-message.vala
(ConversationMessage): Chase body container type and name change,
update call sites. Add in a Progress bar and update it using callbacks
from the web view, handling both initial load and the user subsequently
giving permission to load remote images.
* src/client/components/client-web-view.vala (ClientWebView): Provide a
form of the internal URL scheme prefix.
* ui/conversation-message.ui: Convert body container from being a GtkBox
to a GtkGrid, add in a GtkProgressBar.
src/client/components/client-web-view.vala | 8 ++-
.../conversation-viewer/conversation-email.vala | 6 +-
.../conversation-viewer/conversation-list-box.vala | 2 +-
.../conversation-viewer/conversation-message.vala | 79 ++++++++++++++++++--
ui/conversation-message.ui | 51 ++++++++++---
5 files changed, 120 insertions(+), 26 deletions(-)
---
diff --git a/src/client/components/client-web-view.vala b/src/client/components/client-web-view.vala
index 6723578..60313ff 100644
--- a/src/client/components/client-web-view.vala
+++ b/src/client/components/client-web-view.vala
@@ -17,11 +17,15 @@
public class ClientWebView : WebKit.WebView {
+ /** URI Scheme and delimiter for internal resource loads. */
+ public const string INTERNAL_URL_PREFIX = "geary:";
+
+ /** URI for internal message body page loads. */
+ public const string INTERNAL_URL_BODY = INTERNAL_URL_PREFIX + "body";
+
/** URI Scheme and delimiter for images loaded by Content-ID. */
public const string CID_URL_PREFIX = "cid:";
- private const string INTERNAL_URL_BODY = "geary:body";
-
private const string PREFERRED_HEIGHT_MESSAGE = "preferredHeightChanged";
private const string REMOTE_IMAGE_LOAD_BLOCKED_MESSAGE = "remoteImageLoadBlocked";
private const string SELECTION_CHANGED_MESSAGE = "selectionChanged";
diff --git a/src/client/conversation-viewer/conversation-email.vala
b/src/client/conversation-viewer/conversation-email.vala
index b588a4d..7ee1e71 100644
--- a/src/client/conversation-viewer/conversation-email.vala
+++ b/src/client/conversation-viewer/conversation-email.vala
@@ -488,9 +488,7 @@ public class ConversationEmail : Gtk.Box {
Gee.List<Geary.RFC822.Message> sub_messages = message.get_sub_messages();
if (sub_messages.size > 0) {
- this.primary_message.body.pack_start(
- this.sub_messages, false, false, 0
- );
+ this.primary_message.body_container.add(this.sub_messages);
}
foreach (Geary.RFC822.Message sub_message in sub_messages) {
ConversationMessage attached_message =
@@ -714,7 +712,7 @@ public class ConversationEmail : Gtk.Box {
if (!this.displayed_attachments.is_empty) {
this.attachments_button.show();
this.attachments_button.set_sensitive(!this.is_collapsed);
- this.primary_message.body.add(this.attachments);
+ this.primary_message.body_container.add(this.attachments);
if (this.displayed_attachments.size > 1) {
this.select_all_attachments.show();
diff --git a/src/client/conversation-viewer/conversation-list-box.vala
b/src/client/conversation-viewer/conversation-list-box.vala
index 2625d94..3ad1bfb 100644
--- a/src/client/conversation-viewer/conversation-list-box.vala
+++ b/src/client/conversation-viewer/conversation-list-box.vala
@@ -778,7 +778,7 @@ public class ConversationListBox : Gtk.ListBox {
});
ConversationMessage conversation_message = view.primary_message;
- conversation_message.body.button_release_event.connect_after((event) => {
+ conversation_message.body_container.button_release_event.connect_after((event) => {
// Consume all non-consumed clicks so the row is not
// inadvertently activated after clicking on the
// email body.
diff --git a/src/client/conversation-viewer/conversation-message.vala
b/src/client/conversation-viewer/conversation-message.vala
index ff7f236..09a4ac5 100644
--- a/src/client/conversation-viewer/conversation-message.vala
+++ b/src/client/conversation-viewer/conversation-message.vala
@@ -204,7 +204,9 @@ public class ConversationMessage : Gtk.Grid {
[GtkChild]
private Gtk.Revealer body_revealer;
[GtkChild]
- public Gtk.Box body; // WebKit.WebView crashes when added to a Grid
+ public Gtk.Grid body_container;
+ [GtkChild]
+ public Gtk.ProgressBar body_progress;
[GtkChild]
private Gtk.Popover link_popover;
@@ -240,6 +242,16 @@ public class ConversationMessage : Gtk.Grid {
private int next_replaced_buffer_number = 0;
+ // Is the view set to allow remote image loads?
+ private bool is_loading_images;
+
+ private int remote_resources_requested = 0;
+
+ private int remote_resources_loaded = 0;
+
+ // Timer for hiding the progress bar when complete
+ private Geary.TimeoutManager body_progress_timer = null;
+
/** Fired when the user clicks a link in the email. */
public signal void link_activated(string link);
@@ -268,6 +280,7 @@ public class ConversationMessage : Gtk.Grid {
Configuration config,
bool load_remote_images) {
this.message = message;
+ this.is_loading_images = load_remote_images;
#if !GTK_3_20
// GTK < 3.20+ style workarounds. Keep this in sync with
@@ -372,21 +385,29 @@ public class ConversationMessage : Gtk.Grid {
this.web_view.link_activated.connect((link) => {
link_activated(link);
});
+ this.web_view.load_changed.connect(on_load_changed);
this.web_view.mouse_target_changed.connect(on_mouse_target_changed);
- this.web_view.resource_load_started.connect((view, res, req) => {
- this.resources[res.get_uri()] = res;
+ this.web_view.notify["estimated-load-progress"].connect(() => {
+ this.body_progress.set_fraction(this.web_view.estimated_load_progress);
});
+ this.web_view.resource_load_started.connect(on_resource_load_started);
this.web_view.remote_image_load_blocked.connect(() => {
this.remote_images_infobar.show();
});
this.web_view.selection_changed.connect(on_selection_changed);
+ this.web_view.set_hexpand(true);
+ this.web_view.set_vexpand(true);
this.web_view.show();
- this.body.set_has_tooltip(true); // Used to show link URLs
- this.body.pack_start(this.web_view, true, true, 0);
+ this.body_container.set_has_tooltip(true); // Used to show link URLs
+ this.body_container.add(this.web_view);
+ this.body_progress_timer = new Geary.TimeoutManager.seconds(
+ 1, () => { this.body_progress.hide(); }
+ );
}
public override void destroy() {
+ this.body_progress_timer.reset();
this.resources.clear();
this.searchable_addresses.clear();
base.destroy();
@@ -696,6 +717,7 @@ public class ConversationMessage : Gtk.Grid {
}
private void show_images(bool remember) {
+ this.is_loading_images = true;
this.web_view.load_remote_images();
if (remember) {
flag_remote_images();
@@ -782,6 +804,49 @@ public class ConversationMessage : Gtk.Grid {
revealer.set_transition_type(transition);
}
+ private void on_load_changed(WebKit.LoadEvent load_event) {
+ if (load_event != WebKit.LoadEvent.FINISHED) {
+ this.body_progress_timer.reset();
+ this.body_progress.pulse();
+ } else {
+ this.body_progress_timer.start();
+ }
+ }
+
+ private void on_resource_load_started(WebKit.WebView view,
+ WebKit.WebResource res,
+ WebKit.URIRequest req) {
+ // We only want to show the body loading progress meter if we
+ // are loading images, so do it here rather than
+ // on_load_changed.
+ if (this.is_loading_images &&
+ !res.get_uri().has_prefix(ClientWebView.INTERNAL_URL_PREFIX)) {
+ this.body_progress.show();
+ this.body_progress.pulse();
+ if (!this.web_view.is_loading) {
+ // The initial page load has finished, so we must be
+ // loading a remote image, but can't rely on the
+ // load_changed signal to stop the timer or
+ // estimated-load-progress changing. So manually
+ // manage it here.
+ this.remote_resources_requested++;
+ res.finished.connect(() => {
+ this.remote_resources_loaded++;
+ this.body_progress.set_fraction(
+ (this.remote_resources_loaded /
+ this.remote_resources_requested) +
+ this.body_progress.get_pulse_step()
+ );
+ if (this.remote_resources_loaded >=
+ this.remote_resources_requested) {
+ this.body_progress_timer.start();
+ }
+ });
+ }
+ this.resources[res.get_uri()] = res;
+ }
+ }
+
[GtkCallback]
private void on_address_box_child_activated(Gtk.FlowBox box,
Gtk.FlowBoxChild child) {
@@ -863,8 +928,8 @@ public class ConversationMessage : Gtk.Grid {
WebKit.HitTestResult hit_test,
uint modifiers) {
if (hit_test.context_is_link()) {
- this.body.set_tooltip_text(hit_test.get_link_uri());
- this.body.trigger_tooltip_query();
+ this.body_container.set_tooltip_text(hit_test.get_link_uri());
+ this.body_container.trigger_tooltip_query();
}
}
diff --git a/ui/conversation-message.ui b/ui/conversation-message.ui
index cf65392..d635b08 100644
--- a/ui/conversation-message.ui
+++ b/ui/conversation-message.ui
@@ -5,7 +5,6 @@
<template class="ConversationMessage" parent="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="hexpand">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkGrid" id="summary">
@@ -475,13 +474,10 @@
<object class="GtkRevealer" id="body_revealer">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="hexpand">True</property>
<child>
- <object class="GtkBox" id="body">
+ <object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="hexpand">True</property>
- <property name="orientation">vertical</property>
<child>
<object class="GtkGrid" id="infobars">
<property name="visible">True</property>
@@ -582,6 +578,9 @@
<action-widget response="1">button1</action-widget>
<action-widget response="2">button2</action-widget>
</action-widgets>
+ <child>
+ <placeholder/>
+ </child>
</object>
<packing>
<property name="left_attach">0</property>
@@ -590,14 +589,42 @@
</child>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkOverlay">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkGrid" id="body_container">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <style>
+ <class name="geary-message-body"/>
+ </style>
+ </object>
+ <packing>
+ <property name="index">-1</property>
+ </packing>
+ </child>
+ <child type="overlay">
+ <object class="GtkProgressBar" id="body_progress">
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <style>
+ <class name="osd"/>
+ <class name="top"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
</packing>
</child>
- <style>
- <class name="geary-message-body"/>
- </style>
</object>
</child>
</object>
@@ -612,7 +639,7 @@
</template>
<object class="GtkPopover" id="link_popover">
<property name="can_focus">False</property>
- <property name="relative_to">body</property>
+ <property name="relative_to">body_container</property>
<property name="position">bottom</property>
<child>
<object class="GtkGrid">
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]