* 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.
96 lines
3.3 KiB
JavaScript
96 lines
3.3 KiB
JavaScript
/*
|
|
* Copyright 2016 Michael Gratton <mike@vee.net>
|
|
*
|
|
* This software is licensed under the GNU Lesser General Public License
|
|
* (version 2.1 or later). See the COPYING file in this distribution.
|
|
*/
|
|
|
|
/**
|
|
* Application logic for ClientWebView and subclasses.
|
|
*/
|
|
|
|
let PageState = function() {
|
|
this.init.apply(this, arguments);
|
|
};
|
|
PageState.prototype = {
|
|
init: function() {
|
|
this.allowRemoteImages = false;
|
|
this.isLoaded = false;
|
|
this.hasSelection = false;
|
|
this.lastPreferredHeight = 0;
|
|
|
|
let state = this;
|
|
|
|
// 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);
|
|
}
|
|
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;
|
|
},
|
|
loaded: function() {
|
|
this.isLoaded = true;
|
|
},
|
|
loadRemoteImages: function() {
|
|
this.allowRemoteImages = true;
|
|
let images = document.getElementsByTagName("IMG");
|
|
for (let i = 0; i < images.length; i++) {
|
|
let img = images.item(i);
|
|
let src = img.src;
|
|
img.src = "";
|
|
img.src = src;
|
|
}
|
|
},
|
|
remoteImageLoadBlocked: function() {
|
|
window.webkit.messageHandlers.remoteImageLoadBlocked.postMessage(null);
|
|
},
|
|
/**
|
|
* Sends "preferredHeightChanged" message if it has changed.
|
|
*/
|
|
updatePreferredHeight: function() {
|
|
let updated = false;
|
|
let height = this.getPreferredHeight();
|
|
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;
|
|
if (this.hasSelection != hasSelection) {
|
|
this.hasSelection = hasSelection;
|
|
window.webkit.messageHandlers.selectionChanged.postMessage(hasSelection);
|
|
}
|
|
}
|
|
};
|