ensure deferred js is executed on the correct page

setHtml() and deferred js now share a single queue, to ensure that js
calls are delivered to the correct page

also remove the onLoadFinished hook, which is no longer used
This commit is contained in:
Damien Elmes 2017-08-07 16:01:35 +10:00
parent 9c63714e80
commit 538119201c

View File

@ -76,7 +76,7 @@ class AnkiWebView(QWebEngineView):
self._page = AnkiWebPage(self._onBridgeCmd) self._page = AnkiWebPage(self._onBridgeCmd)
self._domDone = True self._domDone = True
self._pendingJS = [] self._pendingActions = []
self.setPage(self._page) self.setPage(self._page)
self._page.profile().setHttpCacheType(QWebEngineProfile.NoCache) self._page.profile().setHttpCacheType(QWebEngineProfile.NoCache)
@ -140,17 +140,12 @@ class AnkiWebView(QWebEngineView):
pass pass
def setHtml(self, html): def setHtml(self, html):
if not self._domDone or self._pendingJS: self._queueAction("setHtml", html)
# defer update until previous page has initialized
if devMode: def _setHtml(self, html):
print("deferring setHtml() until page is ready")
from aqt import mw
mw.progress.timer(25, lambda: self.setHtml(html), False)
return
app = QApplication.instance() app = QApplication.instance()
oldFocus = app.focusWidget() oldFocus = app.focusWidget()
self._domDone = False self._domDone = False
self._pendingJS = []
self._page.setHtml(html) self._page.setHtml(html)
# work around webengine stealing focus on setHtml() # work around webengine stealing focus on setHtml()
if oldFocus: if oldFocus:
@ -214,13 +209,28 @@ body { zoom: %f; %s }
self.evalWithCallback(js, None) self.evalWithCallback(js, None)
def evalWithCallback(self, js, cb): def evalWithCallback(self, js, cb):
if self._domDone: self._queueAction("eval", js, cb)
if cb:
self.page().runJavaScript(js, cb) def _evalWithCallback(self, js, cb):
else: if cb:
self.page().runJavaScript(js) self.page().runJavaScript(js, cb)
else: else:
self._pendingJS.append([js, cb]) self.page().runJavaScript(js)
def _queueAction(self, name, *args):
self._pendingActions.append((name, args))
self._maybeRunActions()
def _maybeRunActions(self):
while self._pendingActions and self._domDone:
name, args = self._pendingActions.pop(0)
if name == "eval":
self._evalWithCallback(*args)
elif name == "setHtml":
self._setHtml(*args)
else:
raise Exception("unknown action: {}".format(name))
def _openLinksExternally(self, url): def _openLinksExternally(self, url):
openLink(url) openLink(url)
@ -233,23 +243,15 @@ body { zoom: %f; %s }
if cmd == "domDone": if cmd == "domDone":
self._domDone = True self._domDone = True
# run through any pending js calls self._maybeRunActions()
for js, cb in self._pendingJS:
self.evalWithCallback(js, cb)
self._pendingJS = []
self.onLoadFinished()
else: else:
self.onBridgeCmd(cmd) self.onBridgeCmd(cmd)
def defaultOnBridgeCmd(self, cmd): def defaultOnBridgeCmd(self, cmd):
print("unhandled bridge cmd:", cmd) print("unhandled bridge cmd:", cmd)
def defaultOnLoadFinished(self):
pass
def resetHandlers(self): def resetHandlers(self):
self.onBridgeCmd = self.defaultOnBridgeCmd self.onBridgeCmd = self.defaultOnBridgeCmd
self.onLoadFinished = self.defaultOnLoadFinished
def adjustHeightToFit(self): def adjustHeightToFit(self):
self.evalWithCallback("$(document.body).height()", self._onHeight) self.evalWithCallback("$(document.body).height()", self._onHeight)