From 7234cce4ae528db3e6177da1dbd499abd3c83837 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 22 Nov 2020 11:19:21 -0500 Subject: [PATCH] Refactor nested popup/frontend setup (#1052) --- ext/bg/js/search.js | 31 +--------- ext/fg/js/float.js | 60 +----------------- ext/fg/js/frontend.js | 10 +-- ext/fg/js/popup.js | 9 +-- ext/mixed/js/display.js | 134 +++++++++++++++++++++++++++++----------- 5 files changed, 105 insertions(+), 139 deletions(-) diff --git a/ext/bg/js/search.js b/ext/bg/js/search.js index 1dda0f43..e68dccfd 100644 --- a/ext/bg/js/search.js +++ b/ext/bg/js/search.js @@ -25,7 +25,7 @@ class DisplaySearch extends Display { constructor() { - super(); + super('search'); this._searchButton = document.querySelector('#search-button'); this._queryInput = document.querySelector('#search-textbox'); this._introElement = document.querySelector('#intro'); @@ -85,8 +85,6 @@ class DisplaySearch extends Display { this._onModeChange(); - await this._prepareNestedPopups(); - this.initializeState(); this._isPrepared = true; @@ -319,33 +317,6 @@ class DisplaySearch extends Display { this._introElement.style.height = '0'; } - async _prepareNestedPopups() { - let complete = false; - - const onOptionsUpdated = async () => { - const optionsContext = this.getOptionsContext(); - const options = await api.optionsGet(optionsContext); - if (!options.scanning.enableOnSearchPage || complete) { return; } - - complete = true; - yomichan.off('optionsUpdated', onOptionsUpdated); - - try { - await this.setupNestedPopups({ - depth: 1, - useProxyPopup: false, - pageType: 'search' - }); - } catch (e) { - yomichan.logError(e); - } - }; - - yomichan.on('optionsUpdated', onOptionsUpdated); - - await onOptionsUpdated(); - } - async _setClipboardMonitorEnabled(value) { let modify = true; if (value) { diff --git a/ext/fg/js/float.js b/ext/fg/js/float.js index bc555ffd..195861a3 100644 --- a/ext/fg/js/float.js +++ b/ext/fg/js/float.js @@ -23,8 +23,7 @@ class DisplayFloat extends Display { constructor() { - super(); - this._nestedPopupsPrepared = false; + super('popup'); this._frameEndpoint = new FrameEndpoint(); this._windowMessageHandlers = new Map([ ['extensionUnloaded', {async: false, handler: this._onMessageExtensionUnloaded.bind(this)}] @@ -48,10 +47,6 @@ class DisplayFloat extends Display { const {browser} = await api.getEnvironmentInfo(); this._browser = browser; - this.registerDirectMessageHandlers([ - ['configure', {async: true, handler: this._onMessageConfigure.bind(this)}], - ['setContentScale', {async: false, handler: this._onMessageSetContentScale.bind(this)}] - ]); window.addEventListener('message', this._onWindowMessage.bind(this), false); document.documentElement.addEventListener('mouseup', this._onMouseUp.bind(this), false); document.documentElement.addEventListener('click', this._onClick.bind(this), false); @@ -101,23 +96,6 @@ class DisplayFloat extends Display { yomichan.invokeMessageHandler(messageHandler, params, callback); } - async _onMessageConfigure({frameId, ownerFrameId, popupId, optionsContext, childrenSupported, scale}) { - this.ownerFrameId = ownerFrameId; - await this.setOptionsContext(optionsContext); - - if (childrenSupported && !this._nestedPopupsPrepared) { - const {depth} = optionsContext; - this._prepareNestedPopups(depth + 1, popupId, frameId); - this._nestedPopupsPrepared = true; - } - - this._setContentScale(scale); - } - - _onMessageSetContentScale({scale}) { - this._setContentScale(scale); - } - _onMessageExtensionUnloaded() { if (yomichan.isExtensionUnloaded) { return; } yomichan.triggerExtensionUnloaded(); @@ -200,42 +178,6 @@ class DisplayFloat extends Display { parent.removeChild(textarea); } - _setContentScale(scale) { - const body = document.body; - if (body === null) { return; } - body.style.fontSize = `${scale}em`; - } - - async _prepareNestedPopups(depth, parentPopupId, parentFrameId) { - let complete = false; - - const onOptionsUpdated = async () => { - const optionsContext = this.getOptionsContext(); - const options = await api.optionsGet(optionsContext); - const maxPopupDepthExceeded = !(typeof depth === 'number' && depth <= options.scanning.popupNestingMaxDepth); - if (maxPopupDepthExceeded || complete) { return; } - - complete = true; - yomichan.off('optionsUpdated', onOptionsUpdated); - - try { - await this.setupNestedPopups({ - depth, - parentPopupId, - parentFrameId, - useProxyPopup: true, - pageType: 'popup' - }); - } catch (e) { - yomichan.logError(e); - } - }; - - yomichan.on('optionsUpdated', onOptionsUpdated); - - await onOptionsUpdated(); - } - _invokeOwner(action, params={}) { return api.crossFrame.invoke(this.ownerFrameId, action, params); } diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 2ee9b4a1..e4c6342e 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -379,10 +379,6 @@ class Frontend { } if (this._updatePopupToken !== token) { return; } - if (this._pageType === 'search') { - this.setDisabledOverride(!this._options.scanning.enableOnSearchPage); - } - this._clearSelection(true); this._popupEventListeners.removeAllEventListeners(); this._popup = popup; @@ -525,11 +521,7 @@ class Frontend { } _updateTextScannerEnabled() { - const enabled = ( - this._options.general.enable && - this._depth <= this._options.scanning.popupNestingMaxDepth && - !this._disabledOverride - ); + const enabled = (this._options.general.enable && !this._disabledOverride); this._textScanner.setEnabled(enabled); } diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 826457c1..2feb220d 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -255,12 +255,13 @@ class Popup extends EventDispatcher { // Configure await this._invokeSafe('configure', { - frameId: this._frameId, + depth: this._depth, + parentPopupId: this._id, + parentFrameId: this._frameId, ownerFrameId: this._ownerFrameId, - popupId: this._id, - optionsContext: this._optionsContext, childrenSupported: this._childrenSupported, - scale: this._contentScale + scale: this._contentScale, + optionsContext: this._optionsContext }); } diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 19df9a61..ba1f3758 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -32,8 +32,9 @@ */ class Display extends EventDispatcher { - constructor() { + constructor(pageType) { super(); + this._pageType = pageType; this._container = document.querySelector('#definitions'); this._definitions = []; this._optionsContext = {depth: 0, url: window.location.href}; @@ -79,7 +80,6 @@ class Display extends EventDispatcher { documentUtil: this._documentUtil }); this._mode = null; - this._ownerFrameId = null; this._defaultAnkiFieldTemplates = null; this._defaultAnkiFieldTemplatesPromise = null; this._templateRenderer = new TemplateRendererProxy(); @@ -95,6 +95,13 @@ class Display extends EventDispatcher { this._closeButton = document.querySelector('#close-button'); this._navigationPreviousButton = document.querySelector('#navigate-previous-button'); this._navigationNextButton = document.querySelector('#navigate-next-button'); + this._frontend = null; + this._frontendSetupPromise = null; + this._depth = 0; + this._parentPopupId = null; + this._parentFrameId = null; + this._ownerFrameId = null; + this._childrenSupported = true; this.registerActions([ ['close', () => { this.onEscape(); }], @@ -135,7 +142,9 @@ class Display extends EventDispatcher { ['setOptionsContext', {async: false, handler: this._onMessageSetOptionsContext.bind(this)}], ['setContent', {async: false, handler: this._onMessageSetContent.bind(this)}], ['clearAutoPlayTimer', {async: false, handler: this._onMessageClearAutoPlayTimer.bind(this)}], - ['setCustomCss', {async: false, handler: this._onMessageSetCustomCss.bind(this)}] + ['setCustomCss', {async: false, handler: this._onMessageSetCustomCss.bind(this)}], + ['setContentScale', {async: false, handler: this._onMessageSetContentScale.bind(this)}], + ['configure', {async: true, handler: this._onMessageConfigure.bind(this)}] ]); } @@ -164,10 +173,6 @@ class Display extends EventDispatcher { return this._ownerFrameId; } - set ownerFrameId(value) { - this._ownerFrameId = value; - } - async prepare() { this._audioSystem.prepare(); this._updateMode(); @@ -268,6 +273,8 @@ class Display extends EventDispatcher { preventMiddleMouse: scanning.preventMiddleMouse.onSearchQuery } }); + + this._updateNestedFrontend(options); } addMultipleEventListeners(selector, type, listener, options) { @@ -365,36 +372,6 @@ class Display extends EventDispatcher { } } - async setupNestedPopups({depth, parentPopupId, parentFrameId, useProxyPopup, pageType}) { - await dynamicLoader.loadScripts([ - '/mixed/js/text-scanner.js', - '/mixed/js/frame-client.js', - '/fg/js/popup.js', - '/fg/js/popup-proxy.js', - '/fg/js/popup-window.js', - '/fg/js/popup-factory.js', - '/fg/js/frame-offset-forwarder.js', - '/fg/js/frontend.js' - ]); - - const {frameId} = await api.frameInformationGet(); - - const popupFactory = new PopupFactory(frameId); - popupFactory.prepare(); - - const frontend = new Frontend({ - frameId, - popupFactory, - depth, - parentPopupId, - parentFrameId, - useProxyPopup, - pageType, - allowRootFramePopupProxy: true - }); - await frontend.prepare(); - } - authenticateMessageData(data) { return data; } @@ -453,6 +430,20 @@ class Display extends EventDispatcher { this.setCustomCss(css); } + _onMessageSetContentScale({scale}) { + this._setContentScale(scale); + } + + async _onMessageConfigure({depth, parentPopupId, parentFrameId, ownerFrameId, childrenSupported, scale, optionsContext}) { + this._depth = depth; + this._parentPopupId = parentPopupId; + this._parentFrameId = parentFrameId; + this._ownerFrameId = ownerFrameId; + this._childrenSupported = childrenSupported; + this._setContentScale(scale); + await this.setOptionsContext(optionsContext); + } + // Private async _onStateChanged() { @@ -1568,4 +1559,73 @@ class Display extends EventDispatcher { target.focus({preventScroll: true}); } } + + _setContentScale(scale) { + const body = document.body; + if (body === null) { return; } + body.style.fontSize = `${scale}em`; + } + + async _updateNestedFrontend(options) { + const isSearchPage = (this._pageType === 'search'); + const isEnabled = this._childrenSupported && ( + (isSearchPage) ? + (options.scanning.enableOnSearchPage) : + (this._depth < options.scanning.popupNestingMaxDepth) + ); + + if (this._frontend === null) { + if (!isEnabled) { return; } + + try { + if (this._frontendSetupPromise === null) { + this._frontendSetupPromise = this._setupNestedFrontend(isSearchPage); + } + await this._frontendSetupPromise; + } catch (e) { + yomichan.logError(e); + return; + } finally { + this._frontendSetupPromise = null; + } + } + + this._frontend.setDisabledOverride(!isEnabled); + } + + async _setupNestedFrontend(isSearchPage) { + const setupNestedPopupsOptions = ( + (isSearchPage) ? + {useProxyPopup: false} : + {useProxyPopup: true, parentPopupId: this._parentPopupId, parentFrameId: this._parentFrameId} + ); + + const {frameId} = await api.frameInformationGet(); + + await dynamicLoader.loadScripts([ + '/mixed/js/text-scanner.js', + '/mixed/js/frame-client.js', + '/fg/js/popup.js', + '/fg/js/popup-proxy.js', + '/fg/js/popup-window.js', + '/fg/js/popup-factory.js', + '/fg/js/frame-offset-forwarder.js', + '/fg/js/frontend.js' + ]); + + const popupFactory = new PopupFactory(frameId); + popupFactory.prepare(); + + Object.assign(setupNestedPopupsOptions, { + depth: this._depth + 1, + frameId, + popupFactory, + pageType: this._pageType, + allowRootFramePopupProxy: true + }); + + const frontend = new Frontend(setupNestedPopupsOptions); + this._frontend = frontend; + await frontend.prepare(); + } }