diff --git a/ext/bg/js/search-frontend.js b/ext/bg/js/search-frontend.js index a470e873..2d2aa8d4 100644 --- a/ext/bg/js/search-frontend.js +++ b/ext/bg/js/search-frontend.js @@ -30,12 +30,7 @@ async function searchFrontendSetup() { const options = await apiOptionsGet(optionsContext); if (!options.scanning.enableOnSearchPage) { return; } - const ignoreNodes = ['.scan-disable', '.scan-disable *']; - if (!options.scanning.enableOnPopupExpressions) { - ignoreNodes.push('.source-text', '.source-text *'); - } - - window.frontendInitializationData = {depth: 1, ignoreNodes, proxy: false}; + window.frontendInitializationData = {depth: 1, proxy: false}; const scriptSrcs = [ '/mixed/js/text-scanner.js', diff --git a/ext/bg/js/search-query-parser.js b/ext/bg/js/search-query-parser.js index 06316ce2..6e18073b 100644 --- a/ext/bg/js/search-query-parser.js +++ b/ext/bg/js/search-query-parser.js @@ -28,11 +28,10 @@ class QueryParser extends TextScanner { constructor(search) { - super(document.querySelector('#query-parser-content'), [], [], []); + super(document.querySelector('#query-parser-content'), [], []); this.search = search; this.parseResults = []; - this.selectedParser = null; this.queryParser = document.querySelector('#query-parser-content'); this.queryParserSelect = document.querySelector('#query-parser-select-container'); @@ -79,9 +78,7 @@ class QueryParser extends TextScanner { onParserChange(e) { const selectedParser = e.target.value; - this.selectedParser = selectedParser; apiOptionsSet({parsing: {selectedParser}}, this.search.getOptionsContext()); - this.renderParseResult(); } getMouseEventListeners() { @@ -112,19 +109,16 @@ class QueryParser extends TextScanner { refreshSelectedParser() { if (this.parseResults.length > 0) { - if (this.selectedParser === null) { - this.selectedParser = this.search.options.parsing.selectedParser; - } - if (this.selectedParser === null || !this.getParseResult()) { + if (!this.getParseResult()) { const selectedParser = this.parseResults[0].id; - this.selectedParser = selectedParser; apiOptionsSet({parsing: {selectedParser}}, this.search.getOptionsContext()); } } } getParseResult() { - return this.parseResults.find((r) => r.id === this.selectedParser); + const {selectedParser} = this.options.parsing; + return this.parseResults.find((r) => r.id === selectedParser); } async setText(text) { @@ -176,7 +170,8 @@ class QueryParser extends TextScanner { renderParserSelect() { this.queryParserSelect.textContent = ''; if (this.parseResults.length > 1) { - const select = this.queryParserGenerator.createParserSelect(this.parseResults, this.selectedParser); + const {selectedParser} = this.options.parsing; + const select = this.queryParserGenerator.createParserSelect(this.parseResults, selectedParser); select.addEventListener('change', this.onParserChange.bind(this)); this.queryParserSelect.appendChild(select); } diff --git a/ext/bg/js/search.js b/ext/bg/js/search.js index e2bdff73..8b8ee55e 100644 --- a/ext/bg/js/search.js +++ b/ext/bg/js/search.js @@ -247,15 +247,12 @@ class DisplaySearch extends Display { } onWanakanaEnableChange(e) { - const {queryParams: {query=''}} = parseUrl(window.location.href); const enableWanakana = e.target.checked; if (enableWanakana) { window.wanakana.bind(this.query); } else { window.wanakana.unbind(this.query); } - this.setQuery(query); - this.onSearchQueryUpdated(this.query.value, false); apiOptionsSet({general: {enableWanakana}}, this.getOptionsContext()); } @@ -278,19 +275,20 @@ class DisplaySearch extends Display { } } - async updateOptions(options) { - await super.updateOptions(options); + async updateOptions() { + await super.updateOptions(); this.queryParser.setOptions(this.options); + const query = this.query.value; + if (query) { + this.setQuery(query); + this.onSearchQueryUpdated(query, false); + } } isWanakanaEnabled() { return this.wanakanaEnable !== null && this.wanakanaEnable.checked; } - getOptionsContext() { - return this.optionsContext; - } - setQuery(query) { const interpretedQuery = this.isWanakanaEnabled() ? window.wanakana.toKana(query) : query; this.query.value = interpretedQuery; diff --git a/ext/fg/js/float.js b/ext/fg/js/float.js index 393c2719..9b720ebe 100644 --- a/ext/fg/js/float.js +++ b/ext/fg/js/float.js @@ -28,6 +28,8 @@ class DisplayFloat extends Display { super(document.querySelector('#spinner'), document.querySelector('#definitions')); this.autoPlayAudioTimer = null; + this._popupId = null; + this.optionsContext = { depth: 0, url: window.location.href @@ -53,7 +55,7 @@ class DisplayFloat extends Display { ['setContent', ({type, details}) => this.setContent(type, details)], ['clearAutoPlayTimer', () => this.clearAutoPlayTimer()], ['setCustomCss', ({css}) => this.setCustomCss(css)], - ['prepare', ({options, popupInfo, url, childrenSupported, scale, uniqueId}) => this.prepare(options, popupInfo, url, childrenSupported, scale, uniqueId)], + ['prepare', ({popupInfo, url, childrenSupported, scale}) => this.prepare(popupInfo, url, childrenSupported, scale)], ['setContentScale', ({scale}) => this.setContentScale(scale)] ]); @@ -61,23 +63,24 @@ class DisplayFloat extends Display { window.addEventListener('message', this.onMessage.bind(this), false); } - async prepare(options, popupInfo, url, childrenSupported, scale, uniqueId) { + async prepare(popupInfo, url, childrenSupported, scale) { if (this._prepareInvoked) { return; } this._prepareInvoked = true; - await super.prepare(options); - const {id, depth, parentFrameId} = popupInfo; + this._popupId = id; this.optionsContext.depth = depth; this.optionsContext.url = url; + await super.prepare(); + if (childrenSupported) { popupNestedInitialize(id, depth, parentFrameId, url); } this.setContentScale(scale); - apiForward('popupPrepareCompleted', {uniqueId}); + apiForward('popupPrepareCompleted', {targetPopupId: this._popupId}); } onError(error) { @@ -144,10 +147,6 @@ class DisplayFloat extends Display { handler(params); } - getOptionsContext() { - return this.optionsContext; - } - autoPlayAudio() { this.clearAutoPlayTimer(); this.autoPlayAudioTimer = window.setTimeout(() => super.autoPlayAudio(), 400); diff --git a/ext/fg/js/frontend-initialize.js b/ext/fg/js/frontend-initialize.js index 8424b21d..3a191247 100644 --- a/ext/fg/js/frontend-initialize.js +++ b/ext/fg/js/frontend-initialize.js @@ -26,7 +26,7 @@ async function main() { await yomichan.prepare(); const data = window.frontendInitializationData || {}; - const {id, depth=0, parentFrameId, ignoreNodes, url, proxy=false} = data; + const {id, depth=0, parentFrameId, url, proxy=false} = data; let popup; if (proxy) { @@ -38,7 +38,7 @@ async function main() { popup = popupHost.getOrCreatePopup(null, null, depth); } - const frontend = new Frontend(popup, ignoreNodes); + const frontend = new Frontend(popup); await frontend.prepare(); } diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 768b9326..d7bc02cc 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -26,10 +26,9 @@ */ class Frontend extends TextScanner { - constructor(popup, ignoreNodes) { + constructor(popup) { super( window, - ignoreNodes, popup.isProxy() ? [] : [popup.getContainer()], [(x, y) => this.popup.containsPoint(x, y)] ); @@ -95,6 +94,9 @@ class Frontend extends TextScanner { } onRuntimeMessage({action, params}, sender, callback) { + const {targetPopupId} = params || {}; + if (targetPopupId !== 'all' && targetPopupId !== this.popup.id) { return; } + const handler = this._runtimeMessageHandlers.get(action); if (typeof handler !== 'function') { return false; } @@ -129,8 +131,20 @@ class Frontend extends TextScanner { async updateOptions() { this.setOptions(await apiOptionsGet(this.getOptionsContext())); + + const ignoreNodes = ['.scan-disable', '.scan-disable *']; + if (!this.options.scanning.enableOnPopupExpressions) { + ignoreNodes.push('.source-text', '.source-text *'); + } + this.ignoreNodes = ignoreNodes.join(','); + await this.popup.setOptions(this.options); + this._updateContentScale(); + + if (this.textSourceCurrent !== null && this.causeCurrent !== null) { + await this.onSearchSource(this.textSourceCurrent, this.causeCurrent); + } } async onSearchSource(textSource, cause) { diff --git a/ext/fg/js/popup-nested.js b/ext/fg/js/popup-nested.js index 06f8fc4b..39d91fd8 100644 --- a/ext/fg/js/popup-nested.js +++ b/ext/fg/js/popup-nested.js @@ -36,12 +36,7 @@ async function popupNestedInitialize(id, depth, parentFrameId, url) { return; } - const ignoreNodes = ['.scan-disable', '.scan-disable *']; - if (!options.scanning.enableOnPopupExpressions) { - ignoreNodes.push('.source-text', '.source-text *'); - } - - window.frontendInitializationData = {id, depth, parentFrameId, ignoreNodes, url, proxy: true}; + window.frontendInitializationData = {id, depth, parentFrameId, url, proxy: true}; const scriptSrcs = [ '/mixed/js/text-scanner.js', diff --git a/ext/fg/js/popup-proxy.js b/ext/fg/js/popup-proxy.js index f7cef214..997b1317 100644 --- a/ext/fg/js/popup-proxy.js +++ b/ext/fg/js/popup-proxy.js @@ -33,6 +33,10 @@ class PopupProxy { // Public properties + get id() { + return this._id; + } + get parent() { return null; } diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index d752812e..e6e93a76 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -210,11 +210,9 @@ class Popup { const parentFrameId = (typeof this._frameId === 'number' ? this._frameId : null); this._container.setAttribute('src', chrome.runtime.getURL('/fg/float.html')); this._container.addEventListener('load', () => { - const uniqueId = yomichan.generateId(32); - Popup._listenForDisplayPrepareCompleted(uniqueId, resolve); + this._listenForDisplayPrepareCompleted(resolve); this._invokeApi('prepare', { - options: this._options, popupInfo: { id: this._id, depth: this._depth, @@ -222,8 +220,7 @@ class Popup { }, url: this.url, childrenSupported: this._childrenSupported, - scale: this._contentScale, - uniqueId + scale: this._contentScale }); }); this._observeFullscreen(true); @@ -364,23 +361,12 @@ class Popup { contentWindow.postMessage({action, params, token}, this._targetOrigin); } - static _getFullscreenElement() { - return ( - document.fullscreenElement || - document.msFullscreenElement || - document.mozFullScreenElement || - document.webkitFullscreenElement || - null - ); - } - - static _listenForDisplayPrepareCompleted(uniqueId, resolve) { + _listenForDisplayPrepareCompleted(resolve) { const runtimeMessageCallback = ({action, params}, sender, callback) => { if ( action === 'popupPrepareCompleted' && - typeof params === 'object' && - params !== null && - params.uniqueId === uniqueId + isObject(params) && + params.targetPopupId === this._id ) { chrome.runtime.onMessage.removeListener(runtimeMessageCallback); callback(); @@ -391,6 +377,16 @@ class Popup { chrome.runtime.onMessage.addListener(runtimeMessageCallback); } + static _getFullscreenElement() { + return ( + document.fullscreenElement || + document.msFullscreenElement || + document.mozFullScreenElement || + document.webkitFullscreenElement || + null + ); + } + static _getPositionForHorizontalText(elementRect, width, height, viewport, offsetScale, optionsGeneral) { const preferBelow = (optionsGeneral.popupHorizontalTextPosition === 'below'); const horizontalOffset = optionsGeneral.popupHorizontalOffset * offsetScale; diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 515e28a7..9a7a91f3 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -40,6 +40,7 @@ class Display { this.spinner = spinner; this.container = container; this.definitions = []; + this.optionsContext = null; this.options = null; this.context = null; this.index = 0; @@ -165,12 +166,11 @@ class Display { this.setInteractive(true); } - async prepare(options=null) { + async prepare() { await yomichan.prepare(); - const displayGeneratorPromise = this.displayGenerator.prepare(); - const updateOptionsPromise = this.updateOptions(options); - await Promise.all([displayGeneratorPromise, updateOptionsPromise]); - yomichan.on('optionsUpdated', () => this.updateOptions(null)); + await this.displayGenerator.prepare(); + await this.updateOptions(); + yomichan.on('optionsUpdated', () => this.updateOptions()); } onError(_error) { @@ -369,11 +369,11 @@ class Display { } getOptionsContext() { - throw new Error('Override me'); + return this.optionsContext; } - async updateOptions(options) { - this.options = options ? options : await apiOptionsGet(this.getOptionsContext()); + async updateOptions() { + this.options = await apiOptionsGet(this.getOptionsContext()); this.updateDocumentOptions(this.options); this.updateTheme(this.options.general.popupTheme); this.setCustomCss(this.options.general.customPopupCss); @@ -851,7 +851,7 @@ class Display { } setPopupVisibleOverride(visible) { - return apiForward('popupSetVisibleOverride', {visible}); + return apiForward('popupSetVisibleOverride', {visible, targetPopupId: 'all'}); } setSpinnerVisible(visible) { diff --git a/ext/mixed/js/text-scanner.js b/ext/mixed/js/text-scanner.js index a08e09fb..b8156c01 100644 --- a/ext/mixed/js/text-scanner.js +++ b/ext/mixed/js/text-scanner.js @@ -23,13 +23,15 @@ */ class TextScanner { - constructor(node, ignoreNodes, ignoreElements, ignorePoints) { + constructor(node, ignoreElements, ignorePoints) { this.node = node; - this.ignoreNodes = (Array.isArray(ignoreNodes) && ignoreNodes.length > 0 ? ignoreNodes.join(',') : null); this.ignoreElements = ignoreElements; this.ignorePoints = ignorePoints; + this.ignoreNodes = null; + this.scanTimerPromise = null; + this.causeCurrent = null; this.textSourceCurrent = null; this.pendingLookup = false; this.options = null; @@ -298,6 +300,7 @@ class TextScanner { this.pendingLookup = true; const result = await this.onSearchSource(textSource, cause); if (result !== null) { + this.causeCurrent = cause; this.textSourceCurrent = textSource; if (this.options.scanning.selectText) { textSource.select();