[geary/bug/728002-webkit2: 107/140] Update how ClientWebView HTML preferred size changes are sent to the app.
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/bug/728002-webkit2: 107/140] Update how ClientWebView HTML preferred size changes are sent to the app.
- Date: Tue, 31 Jan 2017 23:07:32 +0000 (UTC)
commit 5dfcfe4c8ea43dc66502964afefa443083da440a
Author: Michael James Gratton <mike vee net>
Date: Tue Jan 24 19:30:12 2017 +1100
Update how ClientWebView HTML preferred size changes are sent to the app.
* ui/client-web-view.js (PageState): Use event listeners to send
coalesced preferred height changes, rather than using polling. Call
::load on DOM loaded, not on complete page loaded, so in-place
mutations take affect ASAP. Replace ::preferredHeightChanged with
::updatePreferredHeight method that checks that the height has changed
before sending the message to the app.
* ui/composer-web-view.js: Remove loaded event handler, it's managed by
the base class now.
* ui/conversation-web-view.js (ConversationPageState): Rename
::updatePreferredHeight to ::pollPreferredHeightUpdate to avoid name
clash with parent class. Stop polling if no change has occurred after a
number of repeated checks. Remove loaded event handler, it's managed by
the base class now.
(ComposerPageState::createControllableQuotes): Don't update preferred
height at the end of the call since it will be handled by the DOM load
event handler.
ui/client-web-view.js | 47 ++++++++++++++++++++++++++++++++++++------
ui/composer-web-view.js | 6 +----
ui/conversation-web-view.js | 26 ++++++++---------------
3 files changed, 50 insertions(+), 29 deletions(-)
---
diff --git a/ui/client-web-view.js b/ui/client-web-view.js
index ba224ae..4c11d39 100644
--- a/ui/client-web-view.js
+++ b/ui/client-web-view.js
@@ -17,14 +17,40 @@ PageState.prototype = {
this.allowRemoteImages = false;
this.isLoaded = false;
this.hasSelection = false;
+ this.lastPreferredHeight = 0;
let state = this;
- let timeoutId = window.setInterval(function() {
- state.preferredHeightChanged();
- if (state.isLoaded) {
- window.clearTimeout(timeoutId);
+
+ // Coalesce multiple calls to updatePreferredHeight using a
+ // timeout to avoid the overhead of multiple JS messages sent
+ // to the app and hence view multiple resizes being queued.
+ let queueTimeout = null;
+ let queuePreferredHeightUpdate = function() {
+ if (queueTimeout != null) {
+ clearTimeout(queueTimeout);
}
- }, 50);
+ queueTimeout = setTimeout(
+ function() { state.updatePreferredHeight(); }, 10
+ );
+ };
+
+ // Queues an update after the DOM has been initially loaded
+ // and had any changes made to it by derived classes.
+ document.addEventListener("DOMContentLoaded", function(e) {
+ state.loaded();
+ queuePreferredHeightUpdate();
+ });
+ // Queues updates for not only the complete document, but also
+ // for any IMG elements loaded, hence handles resizing when
+ // the user later requests remote images loading.
+ //
+ // Note also that the delay introduced here by the last call
+ // to queuePreferredHeightUpdate when the complete document is
+ // loaded seems to be important to get an acurate idea of the
+ // final document size.
+ document.addEventListener("load", function(e) {
+ queuePreferredHeightUpdate();
+ }, true);
},
getPreferredHeight: function() {
return window.document.documentElement.offsetHeight;
@@ -45,13 +71,20 @@ PageState.prototype = {
remoteImageLoadBlocked: function() {
window.webkit.messageHandlers.remoteImageLoadBlocked.postMessage(null);
},
- preferredHeightChanged: function() {
+ /**
+ * Sends "preferredHeightChanged" message if it has changed.
+ */
+ updatePreferredHeight: function() {
+ let updated = false;
let height = this.getPreferredHeight();
- if (height > 0) {
+ if (height > 0 && height != this.lastPreferredHeight) {
+ updated = true;
+ this.lastPreferredHeight = height;
window.webkit.messageHandlers.preferredHeightChanged.postMessage(
height
);
}
+ return updated;
},
selectionChanged: function() {
let hasSelection = !window.getSelection().isCollapsed;
diff --git a/ui/composer-web-view.js b/ui/composer-web-view.js
index 7aefa15..a81cd6f 100644
--- a/ui/composer-web-view.js
+++ b/ui/composer-web-view.js
@@ -102,8 +102,7 @@ ComposerPageState.prototype = {
};
this.bodyObserver.observe(this.messageBody, config);
- // Chain up here so we continue to a preferred size update
- // after munging the HTML above.
+ // Chain up
PageState.prototype.loaded.apply(this, []);
},
undo: function() {
@@ -434,6 +433,3 @@ let SelectionUtil = {
var geary = new ComposerPageState();
-window.onload = function() {
- geary.loaded();
-};
diff --git a/ui/conversation-web-view.js b/ui/conversation-web-view.js
index 3fd6fc7..e1727e7 100644
--- a/ui/conversation-web-view.js
+++ b/ui/conversation-web-view.js
@@ -33,14 +33,11 @@ ConversationPageState.prototype = {
e.preventDefault();
}
}, true);
-
},
loaded: function() {
this.updateDirection();
this.createControllableQuotes();
this.wrapSignature();
- // Chain up here so we continue to a preferred size update
- // after munging the HTML above.
PageState.prototype.loaded.apply(this, []);
},
/**
@@ -55,18 +52,18 @@ ConversationPageState.prototype = {
}
},
/**
- * Starts looking for changes to the page's height.
+ * Polls for a change in the page's preferred height.
*/
- updatePreferredHeight: function() {
- let height = this.getPreferredHeight();
+ pollPreferredHeightUpdate: function() {
let state = this;
+ let count = 0;
let timeoutId = window.setInterval(function() {
- let newHeight = state.getPreferredHeight();
- if (height != newHeight) {
- state.preferredHeightChanged();
+ if (state.updatePreferredHeight() || ++count >= 10) {
+ // Cancel polling when height actually changes or if
+ // no change was found after a long enough period
window.clearTimeout(timeoutId);
}
- }, 50);
+ }, 10);
},
/**
* Add top level blockquotes to hide/show container.
@@ -94,7 +91,7 @@ ConversationPageState.prototype = {
);
}
- let script = this;
+ let state = this;
function newControllerButton(styleClass, text) {
let button = document.createElement("BUTTON");
button.classList.add("geary-button");
@@ -103,7 +100,7 @@ ConversationPageState.prototype = {
quoteContainer.classList.toggle(
ConversationPageState.QUOTE_HIDE_CLASS
);
- script.updatePreferredHeight();
+ state.pollPreferredHeightUpdate();
};
button.appendChild(document.createTextNode(text));
@@ -127,8 +124,6 @@ ConversationPageState.prototype = {
quoteContainer.appendChild(quoteDiv);
parent.insertBefore(quoteContainer, nextSibling);
-
- this.updatePreferredHeight();
}
}
},
@@ -316,6 +311,3 @@ ConversationPageState.isDescendantOf = function(node, ancestorTag) {
};
var geary = new ConversationPageState();
-window.onload = function() {
- geary.loaded();
-};
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]