summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2020-05-02 12:47:15 -0400
committerGitHub <noreply@github.com>2020-05-02 12:47:15 -0400
commit08ada6844af424e8ff28e592fc6b9dbc1a9a97eb (patch)
tree1c025f5522b76aa9dbb534b3328f96a5afb9125b
parentce861ce079f8588b12e7b6d6208dee817b09bafa (diff)
Remove Frontend inheritance (#486)
* Make Frontend use composition instead of inheritance for TextScanner * Use push instead of concat * Update setOptions and setEnabled APIs * Update how onWindowMessage event listener is added/removed * Rename options to _options * Use bind instead of arrow function * Fix selection being cleared due to settings changes
-rw-r--r--ext/bg/js/search-query-parser.js1
-rw-r--r--ext/bg/js/settings/popup-preview-frame.js9
-rw-r--r--ext/fg/js/frontend.js94
-rw-r--r--ext/mixed/js/text-scanner.js22
4 files changed, 77 insertions, 49 deletions
diff --git a/ext/bg/js/search-query-parser.js b/ext/bg/js/search-query-parser.js
index 3215f8e4..137234e8 100644
--- a/ext/bg/js/search-query-parser.js
+++ b/ext/bg/js/search-query-parser.js
@@ -86,6 +86,7 @@ class QueryParser extends TextScanner {
setOptions(options) {
super.setOptions(options);
+ super.setEnabled(true);
this.queryParser.dataset.termSpacing = `${options.parsing.termSpacing}`;
}
diff --git a/ext/bg/js/settings/popup-preview-frame.js b/ext/bg/js/settings/popup-preview-frame.js
index e73c04a0..cb548ed7 100644
--- a/ext/bg/js/settings/popup-preview-frame.js
+++ b/ext/bg/js/settings/popup-preview-frame.js
@@ -66,12 +66,10 @@ class SettingsPopupPreview {
this.popup.setCustomOuterCss = this.popupSetCustomOuterCss.bind(this);
this.frontend = new Frontend(this.popup);
-
this.frontend.getOptionsContext = async () => this.optionsContext;
- this.frontend.setEnabled = () => {};
- this.frontend.clearSelection = () => {};
-
await this.frontend.prepare();
+ this.frontend.setDisabledOverride(true);
+ this.frontend.canClearSelection = false;
// Update search
this.updateSearch();
@@ -169,8 +167,7 @@ class SettingsPopupPreview {
const source = new TextSourceRange(range, range.toString(), null, null);
try {
- await this.frontend.onSearchSource(source, 'script');
- this.frontend.setCurrentTextSource(source);
+ await this.frontend.setTextSource(source);
} finally {
source.cleanup();
}
diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js
index 50f52724..76ad27e0 100644
--- a/ext/fg/js/frontend.js
+++ b/ext/fg/js/frontend.js
@@ -25,14 +25,8 @@
* docSentenceExtract
*/
-class Frontend extends TextScanner {
+class Frontend {
constructor(popup, getUrl=null) {
- super(
- window,
- () => this.popup.isProxy() ? [] : [this.popup.getContainer()],
- [(x, y) => this.popup.containsPoint(x, y)]
- );
-
this._id = yomichan.generateId(16);
this.popup = popup;
@@ -41,15 +35,23 @@ class Frontend extends TextScanner {
this._disabledOverride = false;
- this.options = null;
+ this._options = null;
this._pageZoomFactor = 1.0;
this._contentScale = 1.0;
this._orphaned = false;
this._lastShowPromise = Promise.resolve();
+ this._enabledEventListeners = new EventListenerCollection();
+ this._textScanner = new TextScanner(
+ window,
+ () => this.popup.isProxy() ? [] : [this.popup.getContainer()],
+ [(x, y) => this.popup.containsPoint(x, y)]
+ );
+ this._textScanner.onSearchSource = this.onSearchSource.bind(this);
+
this._windowMessageHandlers = new Map([
- ['popupClose', () => this.clearSelection(false)],
+ ['popupClose', () => this._textScanner.clearSelection(false)],
['selectionCopy', () => document.execCommand('copy')]
]);
@@ -60,6 +62,14 @@ class Frontend extends TextScanner {
]);
}
+ get canClearSelection() {
+ return this._textScanner.canClearSelection;
+ }
+
+ set canClearSelection(value) {
+ this._textScanner.canClearSelection = value;
+ }
+
async prepare() {
try {
await this.updateOptions();
@@ -79,7 +89,7 @@ class Frontend extends TextScanner {
yomichan.on('zoomChanged', this.onZoomChanged.bind(this));
chrome.runtime.onMessage.addListener(this.onRuntimeMessage.bind(this));
- this.on('clearSelection', this.onClearSelection.bind(this));
+ this._textScanner.on('clearSelection', this.onClearSelection.bind(this));
this._updateContentScale();
this._broadcastRootPopupInformation();
@@ -129,44 +139,45 @@ class Frontend extends TextScanner {
this._updateContentScale();
}
- getMouseEventListeners() {
- return [
- ...super.getMouseEventListeners(),
- [window, 'message', this.onWindowMessage.bind(this)]
- ];
- }
-
setDisabledOverride(disabled) {
this._disabledOverride = disabled;
- this.setEnabled(this.options.general.enable, this._canEnable());
+ this._updateTextScannerEnabled();
}
async setPopup(popup) {
- this.clearSelection(true);
+ this._textScanner.clearSelection(true);
this.popup = popup;
await popup.setOptionsContext(await this.getOptionsContext(), this._id);
}
async updateOptions() {
const optionsContext = await this.getOptionsContext();
- this.options = await apiOptionsGet(optionsContext);
- this.setOptions(this.options, this._canEnable());
+ this._options = await apiOptionsGet(optionsContext);
+ this._textScanner.setOptions(this._options);
+ this._updateTextScannerEnabled();
const ignoreNodes = ['.scan-disable', '.scan-disable *'];
- if (!this.options.scanning.enableOnPopupExpressions) {
+ if (!this._options.scanning.enableOnPopupExpressions) {
ignoreNodes.push('.source-text', '.source-text *');
}
- this.ignoreNodes = ignoreNodes.join(',');
+ this._textScanner.ignoreNodes = ignoreNodes.join(',');
await this.popup.setOptionsContext(optionsContext, this._id);
this._updateContentScale();
- if (this.textSourceCurrent !== null && this.causeCurrent !== null) {
- await this.onSearchSource(this.textSourceCurrent, this.causeCurrent);
+ const textSourceCurrent = this._textScanner.getCurrentTextSource();
+ const causeCurrent = this._textScanner.causeCurrent;
+ if (textSourceCurrent !== null && causeCurrent !== null) {
+ await this.onSearchSource(textSourceCurrent, causeCurrent);
}
}
+ async setTextSource(textSource) {
+ await this.onSearchSource(textSource, 'script');
+ this._textScanner.setCurrentTextSource(textSource);
+ }
+
async onSearchSource(textSource, cause) {
let results = null;
@@ -184,15 +195,15 @@ class Frontend extends TextScanner {
}
} catch (e) {
if (this._orphaned) {
- if (textSource !== null && this.options.scanning.modifier !== 'none') {
+ if (textSource !== null && this._options.scanning.modifier !== 'none') {
this._showPopupContent(textSource, await this.getOptionsContext(), 'orphaned');
}
} else {
yomichan.logError(e);
}
} finally {
- if (results === null && this.options.scanning.autoHideResults) {
- this.clearSelection(false);
+ if (results === null && this._options.scanning.autoHideResults) {
+ this._textScanner.clearSelection(false);
}
}
@@ -201,7 +212,7 @@ class Frontend extends TextScanner {
showContent(textSource, focus, definitions, type, optionsContext) {
const {url} = optionsContext;
- const sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt);
+ const sentence = docSentenceExtract(textSource, this._options.anki.sentenceExt);
this._showPopupContent(
textSource,
optionsContext,
@@ -215,7 +226,7 @@ class Frontend extends TextScanner {
}
async findTerms(textSource, optionsContext) {
- this.setTextSourceScanLength(textSource, this.options.scanning.length);
+ this._textScanner.setTextSourceScanLength(textSource, this._options.scanning.length);
const searchText = textSource.text();
if (searchText.length === 0) { return null; }
@@ -229,7 +240,7 @@ class Frontend extends TextScanner {
}
async findKanji(textSource, optionsContext) {
- this.setTextSourceScanLength(textSource, 1);
+ this._textScanner.setTextSourceScanLength(textSource, 1);
const searchText = textSource.text();
if (searchText.length === 0) { return null; }
@@ -263,8 +274,21 @@ class Frontend extends TextScanner {
return this._lastShowPromise;
}
+ _updateTextScannerEnabled() {
+ const enabled = (
+ this._options.general.enable &&
+ this.popup.depth <= this._options.scanning.popupNestingMaxDepth &&
+ !this._disabledOverride
+ );
+ this._enabledEventListeners.removeAllEventListeners();
+ this._textScanner.setEnabled(enabled);
+ if (enabled) {
+ this._enabledEventListeners.addEventListener(window, 'message', this.onWindowMessage.bind(this));
+ }
+ }
+
_updateContentScale() {
- const {popupScalingFactor, popupScaleRelativeToPageZoom, popupScaleRelativeToVisualViewport} = this.options.general;
+ const {popupScalingFactor, popupScaleRelativeToPageZoom, popupScaleRelativeToVisualViewport} = this._options.general;
let contentScale = popupScalingFactor;
if (popupScaleRelativeToPageZoom) {
contentScale /= this._pageZoomFactor;
@@ -295,12 +319,8 @@ class Frontend extends TextScanner {
});
}
- _canEnable() {
- return this.popup.depth <= this.options.scanning.popupNestingMaxDepth && !this._disabledOverride;
- }
-
async _updatePopupPosition() {
- const textSource = this.getCurrentTextSource();
+ const textSource = this._textScanner.getCurrentTextSource();
if (textSource !== null && await this.popup.isVisible()) {
this._showPopupContent(textSource, await this.getOptionsContext());
}
diff --git a/ext/mixed/js/text-scanner.js b/ext/mixed/js/text-scanner.js
index c582ccd8..774eef44 100644
--- a/ext/mixed/js/text-scanner.js
+++ b/ext/mixed/js/text-scanner.js
@@ -45,6 +45,16 @@ class TextScanner extends EventDispatcher {
this.preventNextMouseDown = false;
this.preventNextClick = false;
this.preventScroll = false;
+
+ this._canClearSelection = true;
+ }
+
+ get canClearSelection() {
+ return this._canClearSelection;
+ }
+
+ set canClearSelection(value) {
+ this._canClearSelection = value;
}
onMouseOver(e) {
@@ -222,9 +232,9 @@ class TextScanner extends EventDispatcher {
}
}
- setEnabled(enabled, canEnable) {
+ setEnabled(enabled) {
this.eventListeners.removeAllEventListeners();
- this.enabled = enabled && canEnable;
+ this.enabled = enabled;
if (this.enabled) {
this.hookEvents();
} else {
@@ -233,9 +243,9 @@ class TextScanner extends EventDispatcher {
}
hookEvents() {
- let eventListenerInfos = this.getMouseEventListeners();
+ const eventListenerInfos = this.getMouseEventListeners();
if (this.options.scanning.touchInputEnabled) {
- eventListenerInfos = eventListenerInfos.concat(this.getTouchEventListeners());
+ eventListenerInfos.push(...this.getTouchEventListeners());
}
for (const [node, type, listener, options] of eventListenerInfos) {
@@ -264,9 +274,8 @@ class TextScanner extends EventDispatcher {
];
}
- setOptions(options, canEnable=true) {
+ setOptions(options) {
this.options = options;
- this.setEnabled(this.options.general.enable, canEnable);
}
async searchAt(x, y, cause) {
@@ -324,6 +333,7 @@ class TextScanner extends EventDispatcher {
}
clearSelection(passive) {
+ if (!this._canClearSelection) { return; }
if (this.textSourceCurrent !== null) {
if (this.textSourceCurrentSelected) {
this.textSourceCurrent.deselect();