diff options
| -rw-r--r-- | ext/bg/js/search-frontend.js | 7 | ||||
| -rw-r--r-- | ext/bg/js/search-query-parser.js | 48 | ||||
| -rw-r--r-- | ext/bg/js/search.js | 27 | ||||
| -rw-r--r-- | ext/fg/js/float.js | 17 | ||||
| -rw-r--r-- | ext/fg/js/frontend-initialize.js | 4 | ||||
| -rw-r--r-- | ext/fg/js/frontend.js | 18 | ||||
| -rw-r--r-- | ext/fg/js/popup-nested.js | 7 | ||||
| -rw-r--r-- | ext/fg/js/popup-proxy-host.js | 3 | ||||
| -rw-r--r-- | ext/fg/js/popup-proxy.js | 4 | ||||
| -rw-r--r-- | ext/fg/js/popup.js | 34 | ||||
| -rw-r--r-- | ext/mixed/js/display.js | 16 | ||||
| -rw-r--r-- | ext/mixed/js/text-scanner.js | 7 | 
12 files changed, 101 insertions, 91 deletions
| 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..9f59f2e5 100644 --- a/ext/bg/js/search-query-parser.js +++ b/ext/bg/js/search-query-parser.js @@ -27,12 +27,14 @@   */  class QueryParser extends TextScanner { -    constructor(search) { -        super(document.querySelector('#query-parser-content'), [], [], []); -        this.search = search; +    constructor({getOptionsContext, setContent, setSpinnerVisible}) { +        super(document.querySelector('#query-parser-content'), [], []); + +        this.getOptionsContext = getOptionsContext; +        this.setContent = setContent; +        this.setSpinnerVisible = setSpinnerVisible;          this.parseResults = []; -        this.selectedParser = null;          this.queryParser = document.querySelector('#query-parser-content');          this.queryParserSelect = document.querySelector('#query-parser-select-container'); @@ -56,18 +58,18 @@ class QueryParser extends TextScanner {      async onSearchSource(textSource, cause) {          if (textSource === null) { return null; } -        this.setTextSourceScanLength(textSource, this.search.options.scanning.length); +        this.setTextSourceScanLength(textSource, this.options.scanning.length);          const searchText = textSource.text();          if (searchText.length === 0) { return; } -        const {definitions, length} = await apiTermsFind(searchText, {}, this.search.getOptionsContext()); +        const {definitions, length} = await apiTermsFind(searchText, {}, this.getOptionsContext());          if (definitions.length === 0) { return null; } -        const sentence = docSentenceExtract(textSource, this.search.options.anki.sentenceExt); +        const sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt);          textSource.setEndOffset(length); -        this.search.setContent('terms', {definitions, context: { +        this.setContent('terms', {definitions, context: {              focus: false,              disableHistory: cause === 'mouse',              sentence, @@ -79,9 +81,7 @@ class QueryParser extends TextScanner {      onParserChange(e) {          const selectedParser = e.target.value; -        this.selectedParser = selectedParser; -        apiOptionsSet({parsing: {selectedParser}}, this.search.getOptionsContext()); -        this.renderParseResult(); +        apiOptionsSet({parsing: {selectedParser}}, this.getOptionsContext());      }      getMouseEventListeners() { @@ -112,23 +112,20 @@ 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()); +                apiOptionsSet({parsing: {selectedParser}}, this.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) { -        this.search.setSpinnerVisible(true); +        this.setSpinnerVisible(true);          this.setPreview(text); @@ -138,20 +135,20 @@ class QueryParser extends TextScanner {          this.renderParserSelect();          this.renderParseResult(); -        this.search.setSpinnerVisible(false); +        this.setSpinnerVisible(false);      }      async parseText(text) {          const results = []; -        if (this.search.options.parsing.enableScanningParser) { +        if (this.options.parsing.enableScanningParser) {              results.push({                  name: 'Scanning parser',                  id: 'scan', -                parsedText: await apiTextParse(text, this.search.getOptionsContext()) +                parsedText: await apiTextParse(text, this.getOptionsContext())              });          } -        if (this.search.options.parsing.enableMecabParser) { -            const mecabResults = await apiTextParseMecab(text, this.search.getOptionsContext()); +        if (this.options.parsing.enableMecabParser) { +            const mecabResults = await apiTextParseMecab(text, this.getOptionsContext());              for (const [mecabDictName, mecabDictResults] of mecabResults) {                  results.push({                      name: `MeCab: ${mecabDictName}`, @@ -176,7 +173,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..9250fdde 100644 --- a/ext/bg/js/search.js +++ b/ext/bg/js/search.js @@ -29,12 +29,18 @@ class DisplaySearch extends Display {      constructor() {          super(document.querySelector('#spinner'), document.querySelector('#content')); +        this._isPrepared = false; +          this.optionsContext = {              depth: 0,              url: window.location.href          }; -        this.queryParser = new QueryParser(this); +        this.queryParser = new QueryParser({ +            getOptionsContext: this.getOptionsContext.bind(this), +            setContent: this.setContent.bind(this), +            setSpinnerVisible: this.setSpinnerVisible.bind(this) +        });          this.search = document.querySelector('#search');          this.query = document.querySelector('#query'); @@ -112,6 +118,8 @@ class DisplaySearch extends Display {              this.clipboardMonitor.on('change', this.onExternalSearchUpdate.bind(this));              this.updateSearchButton(); + +            this._isPrepared = true;          } catch (e) {              this.onError(e);          } @@ -247,15 +255,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 +283,21 @@ class DisplaySearch extends Display {          }      } -    async updateOptions(options) { -        await super.updateOptions(options); +    async updateOptions() { +        await super.updateOptions();          this.queryParser.setOptions(this.options); +        if (!this._isPrepared) { return; } +        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..d6c5eac6 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 (typeof targetPopupId !== 'undefined' && 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-host.js b/ext/fg/js/popup-proxy-host.js index 793d3949..6f1c13c6 100644 --- a/ext/fg/js/popup-proxy-host.js +++ b/ext/fg/js/popup-proxy-host.js @@ -25,7 +25,6 @@  class PopupProxyHost {      constructor() {          this._popups = new Map(); -        this._nextId = 0;          this._apiReceiver = null;          this._frameIdPromise = null;      } @@ -76,7 +75,7 @@ class PopupProxyHost {          // New unique id          if (id === null) { -            id = this._nextId++; +            id = yomichan.generateId(16);          }          // Create new popup 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..6898a6eb 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); 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(); |