From e87cc5c37d6ae2f845af7bd28720cb47372589bc Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 9 Aug 2020 13:19:42 -0400 Subject: [PATCH] Query parser text scanner options refactor (#717) * Add _setSelectedParser helper * Update TextScanner internal options representation * Update QueryParser internal options representation --- ext/bg/js/query-parser.js | 66 ++++++++++++++++++++++-------------- ext/fg/js/frontend.js | 13 +++++-- ext/mixed/js/display.js | 28 ++++++++++++--- ext/mixed/js/text-scanner.js | 45 +++++++++++++++++------- 4 files changed, 108 insertions(+), 44 deletions(-) diff --git a/ext/bg/js/query-parser.js b/ext/bg/js/query-parser.js index 88c40c93..6ca09a82 100644 --- a/ext/bg/js/query-parser.js +++ b/ext/bg/js/query-parser.js @@ -25,9 +25,12 @@ class QueryParser extends EventDispatcher { constructor({getOptionsContext, setSpinnerVisible}) { super(); - this._options = null; this._getOptionsContext = getOptionsContext; this._setSpinnerVisible = setSpinnerVisible; + this._selectedParser = null; + this._scanLength = 1; + this._sentenceExtent = 1; + this._layoutAwareScan = false; this._parseResults = []; this._queryParser = document.querySelector('#query-parser-content'); this._queryParserSelect = document.querySelector('#query-parser-select-container'); @@ -46,11 +49,26 @@ class QueryParser extends EventDispatcher { this._queryParser.addEventListener('click', this._onClick.bind(this)); } - setOptions(options) { - this._options = options; - this._textScanner.setOptions(options); + setOptions({selectedParser, scanLength, sentenceExtent, layoutAwareScan, termSpacing, scanning}) { + if (selectedParser === null || typeof selectedParser === 'string') { + this._selectedParser = selectedParser; + } + if (typeof scanLength === 'number') { + this._scanLength = scanLength; + } + if (typeof sentenceExtent === 'number') { + this._sentenceExtent = sentenceExtent; + } + if (typeof layoutAwareScan === 'boolean') { + this._layoutAwareScan = layoutAwareScan; + } + if (typeof termSpacing === 'boolean') { + this._queryParser.dataset.termSpacing = `${termSpacing}`; + } + if (scanning !== null && typeof scanning === 'object') { + this._textScanner.setOptions(scanning); + } this._textScanner.setEnabled(true); - this._queryParser.dataset.termSpacing = `${options.parsing.termSpacing}`; } async setText(text) { @@ -76,7 +94,9 @@ class QueryParser extends EventDispatcher { async _search(textSource, cause) { if (textSource === null) { return null; } - const {length: scanLength, layoutAwareScan} = this._options.scanning; + const scanLength = this._scanLength; + const sentenceExtent = this._sentenceExtent; + const layoutAwareScan = this._layoutAwareScan; const searchText = this._textScanner.getTextSourceContent(textSource, scanLength, layoutAwareScan); if (searchText.length === 0) { return null; } @@ -84,7 +104,6 @@ class QueryParser extends EventDispatcher { const {definitions, length} = await api.termsFind(searchText, {}, optionsContext); if (definitions.length === 0) { return null; } - const sentenceExtent = this._options.anki.sentenceExt; const sentence = docSentenceExtract(textSource, sentenceExtent, layoutAwareScan); textSource.setEndOffset(length, layoutAwareScan); @@ -103,32 +122,29 @@ class QueryParser extends EventDispatcher { _onParserChange(e) { const value = e.target.value; + this._setSelectedParser(value); + } + + _refreshSelectedParser() { + if (this._parseResults.length > 0 && !this._getParseResult()) { + const value = this._parseResults[0].id; + this._setSelectedParser(value); + } + } + + _setSelectedParser(value) { + const optionsContext = this._getOptionsContext(); api.modifySettings([{ action: 'set', path: 'parsing.selectedParser', value, scope: 'profile', - optionsContext: this._getOptionsContext() + optionsContext }], 'search'); } - _refreshSelectedParser() { - if (this._parseResults.length > 0) { - if (!this._getParseResult()) { - const value = this._parseResults[0].id; - api.modifySettings([{ - action: 'set', - path: 'parsing.selectedParser', - value, - scope: 'profile', - optionsContext: this._getOptionsContext() - }], 'search'); - } - } - } - _getParseResult() { - const {selectedParser} = this._options.parsing; + const selectedParser = this._selectedParser; return this._parseResults.find((r) => r.id === selectedParser); } @@ -145,7 +161,7 @@ class QueryParser extends EventDispatcher { _renderParserSelect() { this._queryParserSelect.textContent = ''; if (this._parseResults.length > 1) { - const {selectedParser} = this._options.parsing; + const selectedParser = this._selectedParser; const select = this._queryParserGenerator.createParserSelect(this._parseResults, selectedParser); select.addEventListener('change', this._onParserChange.bind(this)); this._queryParserSelect.appendChild(select); diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 685dbd28..1214e74b 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -233,11 +233,20 @@ class Frontend { async _updateOptionsInternal() { const optionsContext = await this.getOptionsContext(); - this._options = await api.optionsGet(optionsContext); + const options = await api.optionsGet(optionsContext); + const scanningOptions = options.scanning; + this._options = options; await this._updatePopup(); - this._textScanner.setOptions(this._options); + this._textScanner.setOptions({ + deepContentScan: scanningOptions.deepDomScan, + selectText: scanningOptions.selectText, + modifier: scanningOptions.modifier, + useMiddleMouse: scanningOptions.middleMouse, + delay: scanningOptions.delay, + touchInputEnabled: scanningOptions.touchInputEnabled + }); this._updateTextScannerEnabled(); const ignoreNodes = ['.scan-disable', '.scan-disable *']; diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 418707ca..927c2c2c 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -218,11 +218,29 @@ class Display extends EventDispatcher { } async updateOptions() { - this._options = await api.optionsGet(this.getOptionsContext()); - this._updateDocumentOptions(this._options); - this._updateTheme(this._options.general.popupTheme); - this.setCustomCss(this._options.general.customPopupCss); - this._queryParser.setOptions(this._options); + const options = await api.optionsGet(this.getOptionsContext()); + const scanning = options.scanning; + this._options = options; + + this._updateDocumentOptions(options); + this._updateTheme(options.general.popupTheme); + this.setCustomCss(options.general.customPopupCss); + + this._queryParser.setOptions({ + selectedParser: options.parsing.selectedParser, + scanLength: scanning.length, + sentenceExtent: options.anki.sentenceExt, + layoutAwareScan: scanning.layoutAwareScan, + termSpacing: options.parsing.termSpacing, + scanning: { + deepContentScan: scanning.deepDomScan, + selectText: scanning.selectText, + modifier: scanning.modifier, + useMiddleMouse: scanning.middleMouse, + delay: scanning.delay, + touchInputEnabled: scanning.touchInputEnabled + } + }); } addMultipleEventListeners(selector, type, listener, options) { diff --git a/ext/mixed/js/text-scanner.js b/ext/mixed/js/text-scanner.js index 7c705fc8..61e9256d 100644 --- a/ext/mixed/js/text-scanner.js +++ b/ext/mixed/js/text-scanner.js @@ -36,7 +36,13 @@ class TextScanner extends EventDispatcher { this._textSourceCurrent = null; this._textSourceCurrentSelected = false; this._pendingLookup = false; - this._options = null; + + this._deepContentScan = false; + this._selectText = false; + this._modifier = 'none'; + this._useMiddleMouse = false; + this._delay = 0; + this._touchInputEnabled = false; this._enabled = false; this._eventListeners = new EventListenerCollection(); @@ -85,8 +91,25 @@ class TextScanner extends EventDispatcher { } } - setOptions(options) { - this._options = options; + setOptions({deepContentScan, selectText, modifier, useMiddleMouse, delay, touchInputEnabled}) { + if (typeof deepContentScan === 'boolean') { + this._deepContentScan = deepContentScan; + } + if (typeof selectText === 'boolean') { + this._selectText = selectText; + } + if (typeof modifier === 'string') { + this._modifier = modifier; + } + if (typeof useMiddleMouse === 'boolean') { + this._useMiddleMouse = useMiddleMouse; + } + if (typeof delay === 'number') { + this._delay = delay; + } + if (typeof touchInputEnabled === 'boolean') { + this._touchInputEnabled = false; + } } async searchAt(x, y, cause) { @@ -101,7 +124,7 @@ class TextScanner extends EventDispatcher { return; } - const textSource = docRangeFromPoint(x, y, this._options.scanning.deepDomScan); + const textSource = docRangeFromPoint(x, y, this._deepContentScan); try { if (this._textSourceCurrent !== null && this._textSourceCurrent.equals(textSource)) { return; @@ -162,7 +185,7 @@ class TextScanner extends EventDispatcher { setCurrentTextSource(textSource) { this._textSourceCurrent = textSource; - if (this._options.scanning.selectText) { + if (this._selectText) { this._textSourceCurrent.select(); this._textSourceCurrentSelected = true; } else { @@ -188,17 +211,15 @@ class TextScanner extends EventDispatcher { const modifiers = DOM.getActiveModifiers(e); this.trigger('activeModifiersChanged', {modifiers}); - const scanningOptions = this._options.scanning; - const scanningModifier = scanningOptions.modifier; if (!( - this._isScanningModifierPressed(scanningModifier, e) || - (scanningOptions.middleMouse && DOM.isMouseButtonDown(e, 'auxiliary')) + this._isScanningModifierPressed(this._modifier, e) || + (this._useMiddleMouse && DOM.isMouseButtonDown(e, 'auxiliary')) )) { return; } const search = async () => { - if (scanningModifier === 'none') { + if (this._modifier === 'none') { if (!await this._scanTimerWait()) { // Aborted return; @@ -325,7 +346,7 @@ class TextScanner extends EventDispatcher { } async _scanTimerWait() { - const delay = this._options.scanning.delay; + const delay = this._delay; const promise = promiseTimeout(delay, true); this._scanTimerPromise = promise; try { @@ -346,7 +367,7 @@ class TextScanner extends EventDispatcher { _hookEvents() { const eventListenerInfos = this._getMouseEventListeners(); - if (this._options.scanning.touchInputEnabled) { + if (this._touchInputEnabled) { eventListenerInfos.push(...this._getTouchEventListeners()); }