Text scanner refactor (#771)
* Create searchAt wrappers * Add optional support for searching on the click event * Update QueryParser to use TextScanner's searchOnClick functionality * Move/rename searchAt * Move pendingLookup checks * Add 'searched' event to TextScanner * Use common searched event for Frontend and QueryParser * Move functions, make private
This commit is contained in:
parent
dd8e32e7c4
commit
2f8408ffcc
@ -36,15 +36,18 @@ class QueryParser extends EventDispatcher {
|
|||||||
node: this._queryParser,
|
node: this._queryParser,
|
||||||
ignoreElements: () => [],
|
ignoreElements: () => [],
|
||||||
ignorePoint: null,
|
ignorePoint: null,
|
||||||
search: this._search.bind(this),
|
getOptionsContext,
|
||||||
documentUtil
|
documentUtil,
|
||||||
|
searchTerms: true,
|
||||||
|
searchKanji: false,
|
||||||
|
searchOnClick: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async prepare() {
|
async prepare() {
|
||||||
await this._queryParserGenerator.prepare();
|
await this._queryParserGenerator.prepare();
|
||||||
this._textScanner.prepare();
|
this._textScanner.prepare();
|
||||||
this._queryParser.addEventListener('click', this._onClick.bind(this));
|
this._textScanner.on('searched', this._onSearched.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
setOptions({selectedParser, termSpacing, scanning}) {
|
setOptions({selectedParser, termSpacing, scanning}) {
|
||||||
@ -76,18 +79,12 @@ class QueryParser extends EventDispatcher {
|
|||||||
|
|
||||||
// Private
|
// Private
|
||||||
|
|
||||||
_onClick(e) {
|
_onSearched({type, definitions, sentence, cause, textSource, optionsContext, error}) {
|
||||||
this._textScanner.searchAt(e.clientX, e.clientY, 'click');
|
if (error !== null) {
|
||||||
}
|
yomichan.logError(error);
|
||||||
|
return;
|
||||||
async _search(textSource, cause) {
|
}
|
||||||
if (textSource === null) { return null; }
|
if (type === null) { return; }
|
||||||
|
|
||||||
const optionsContext = this._getOptionsContext();
|
|
||||||
const results = await this._textScanner.findTerms(textSource, optionsContext);
|
|
||||||
if (results === null) { return null; }
|
|
||||||
|
|
||||||
const {definitions, sentence, type} = results;
|
|
||||||
|
|
||||||
this.trigger('searched', {
|
this.trigger('searched', {
|
||||||
type,
|
type,
|
||||||
@ -97,8 +94,6 @@ class QueryParser extends EventDispatcher {
|
|||||||
textSource,
|
textSource,
|
||||||
optionsContext
|
optionsContext
|
||||||
});
|
});
|
||||||
|
|
||||||
return {definitions, type};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_onParserChange(e) {
|
_onParserChange(e) {
|
||||||
|
@ -47,8 +47,10 @@ class Frontend {
|
|||||||
node: window,
|
node: window,
|
||||||
ignoreElements: this._ignoreElements.bind(this),
|
ignoreElements: this._ignoreElements.bind(this),
|
||||||
ignorePoint: this._ignorePoint.bind(this),
|
ignorePoint: this._ignorePoint.bind(this),
|
||||||
search: this._search.bind(this),
|
getOptionsContext: this._getUpToDateOptionsContext.bind(this),
|
||||||
documentUtil: this._documentUtil
|
documentUtil: this._documentUtil,
|
||||||
|
searchTerms: true,
|
||||||
|
searchKanji: true
|
||||||
});
|
});
|
||||||
this._parentPopupId = parentPopupId;
|
this._parentPopupId = parentPopupId;
|
||||||
this._parentFrameId = parentFrameId;
|
this._parentFrameId = parentFrameId;
|
||||||
@ -105,6 +107,7 @@ class Frontend {
|
|||||||
|
|
||||||
this._textScanner.on('clearSelection', this._onClearSelection.bind(this));
|
this._textScanner.on('clearSelection', this._onClearSelection.bind(this));
|
||||||
this._textScanner.on('activeModifiersChanged', this._onActiveModifiersChanged.bind(this));
|
this._textScanner.on('activeModifiersChanged', this._onActiveModifiersChanged.bind(this));
|
||||||
|
this._textScanner.on('searched', this._onSearched.bind(this));
|
||||||
|
|
||||||
api.crossFrame.registerHandlers([
|
api.crossFrame.registerHandlers([
|
||||||
['getUrl', {async: false, handler: this._onApiGetUrl.bind(this)}],
|
['getUrl', {async: false, handler: this._onApiGetUrl.bind(this)}],
|
||||||
@ -126,8 +129,7 @@ class Frontend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async setTextSource(textSource) {
|
async setTextSource(textSource) {
|
||||||
await this._search(textSource, 'script');
|
await this._textScanner.search(textSource, 'script');
|
||||||
this._textScanner.setCurrentTextSource(textSource);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getOptionsContext() {
|
async getOptionsContext() {
|
||||||
@ -247,6 +249,27 @@ class Frontend {
|
|||||||
await this.updateOptions();
|
await this.updateOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onSearched({textScanner, type, definitions, sentence, cause, textSource, optionsContext, error}) {
|
||||||
|
if (error !== null) {
|
||||||
|
if (yomichan.isExtensionUnloaded) {
|
||||||
|
if (textSource !== null && this._options.scanning.modifier !== 'none') {
|
||||||
|
this._showExtensionUnloaded(textSource);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
yomichan.logError(error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (type !== null) {
|
||||||
|
const focus = (cause === 'mouse');
|
||||||
|
this._showContent(textSource, focus, definitions, type, sentence, optionsContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === null && this._options.scanning.autoHideResults) {
|
||||||
|
textScanner.clearSelection(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async _updateOptionsInternal() {
|
async _updateOptionsInternal() {
|
||||||
const optionsContext = await this.getOptionsContext();
|
const optionsContext = await this.getOptionsContext();
|
||||||
const options = await api.optionsGet(optionsContext);
|
const options = await api.optionsGet(optionsContext);
|
||||||
@ -279,7 +302,7 @@ class Frontend {
|
|||||||
const textSourceCurrent = this._textScanner.getCurrentTextSource();
|
const textSourceCurrent = this._textScanner.getCurrentTextSource();
|
||||||
const causeCurrent = this._textScanner.causeCurrent;
|
const causeCurrent = this._textScanner.causeCurrent;
|
||||||
if (textSourceCurrent !== null && causeCurrent !== null) {
|
if (textSourceCurrent !== null && causeCurrent !== null) {
|
||||||
await this._search(textSourceCurrent, causeCurrent);
|
await this._textScanner.search(textSourceCurrent, causeCurrent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,44 +425,6 @@ class Frontend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async _search(textSource, cause) {
|
|
||||||
if (this._popup === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
await this._updatePendingOptions();
|
|
||||||
|
|
||||||
let results = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (textSource !== null) {
|
|
||||||
const optionsContext = await this.getOptionsContext();
|
|
||||||
results = (
|
|
||||||
await this._textScanner.findTerms(textSource, optionsContext) ||
|
|
||||||
await this._textScanner.findKanji(textSource, optionsContext)
|
|
||||||
);
|
|
||||||
if (results !== null) {
|
|
||||||
const focus = (cause === 'mouse');
|
|
||||||
this._showContent(textSource, focus, results.definitions, results.type, optionsContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
if (yomichan.isExtensionUnloaded) {
|
|
||||||
if (textSource !== null && this._options.scanning.modifier !== 'none') {
|
|
||||||
this._showExtensionUnloaded(textSource);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
yomichan.logError(e);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (results === null && this._options.scanning.autoHideResults) {
|
|
||||||
this._textScanner.clearSelection(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
async _showExtensionUnloaded(textSource) {
|
async _showExtensionUnloaded(textSource) {
|
||||||
if (textSource === null) {
|
if (textSource === null) {
|
||||||
textSource = this._textScanner.getCurrentTextSource();
|
textSource = this._textScanner.getCurrentTextSource();
|
||||||
@ -448,11 +433,8 @@ class Frontend {
|
|||||||
this._showPopupContent(textSource, await this.getOptionsContext());
|
this._showPopupContent(textSource, await this.getOptionsContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
_showContent(textSource, focus, definitions, type, optionsContext) {
|
_showContent(textSource, focus, definitions, type, sentence, optionsContext) {
|
||||||
const {url} = optionsContext;
|
const {url} = optionsContext;
|
||||||
const sentenceExtent = this._options.anki.sentenceExt;
|
|
||||||
const layoutAwareScan = this._options.scanning.layoutAwareScan;
|
|
||||||
const sentence = this._documentUtil.extractSentence(textSource, sentenceExtent, layoutAwareScan);
|
|
||||||
const query = textSource.text();
|
const query = textSource.text();
|
||||||
const details = {
|
const details = {
|
||||||
focus,
|
focus,
|
||||||
@ -571,4 +553,9 @@ class Frontend {
|
|||||||
api.broadcastTab('requestFrontendReadyBroadcast', {frameId: this._frameId});
|
api.broadcastTab('requestFrontendReadyBroadcast', {frameId: this._frameId});
|
||||||
await promise;
|
await promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _getUpToDateOptionsContext() {
|
||||||
|
await this._updatePendingOptions();
|
||||||
|
return await this.getOptionsContext();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,13 +21,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class TextScanner extends EventDispatcher {
|
class TextScanner extends EventDispatcher {
|
||||||
constructor({node, ignoreElements, ignorePoint, search, documentUtil}) {
|
constructor({node, ignoreElements, ignorePoint, documentUtil, getOptionsContext, searchTerms=false, searchKanji=false, searchOnClick=false}) {
|
||||||
super();
|
super();
|
||||||
this._node = node;
|
this._node = node;
|
||||||
this._ignoreElements = ignoreElements;
|
this._ignoreElements = ignoreElements;
|
||||||
this._ignorePoint = ignorePoint;
|
this._ignorePoint = ignorePoint;
|
||||||
this._search = search;
|
|
||||||
this._documentUtil = documentUtil;
|
this._documentUtil = documentUtil;
|
||||||
|
this._getOptionsContext = getOptionsContext;
|
||||||
|
this._searchTerms = searchTerms;
|
||||||
|
this._searchKanji = searchKanji;
|
||||||
|
this._searchOnClick = searchOnClick;
|
||||||
|
|
||||||
this._isPrepared = false;
|
this._isPrepared = false;
|
||||||
this._ignoreNodes = null;
|
this._ignoreNodes = null;
|
||||||
@ -125,41 +128,6 @@ class TextScanner extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async searchAt(x, y, cause) {
|
|
||||||
try {
|
|
||||||
this._scanTimerClear();
|
|
||||||
|
|
||||||
if (this._pendingLookup) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof this._ignorePoint === 'function' && await this._ignorePoint(x, y)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const textSource = this._documentUtil.getRangeFromPoint(x, y, this._deepContentScan);
|
|
||||||
try {
|
|
||||||
if (this._textSourceCurrent !== null && this._textSourceCurrent.equals(textSource)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._pendingLookup = true;
|
|
||||||
const result = await this._search(textSource, cause);
|
|
||||||
if (result !== null) {
|
|
||||||
this._causeCurrent = cause;
|
|
||||||
this.setCurrentTextSource(textSource);
|
|
||||||
}
|
|
||||||
this._pendingLookup = false;
|
|
||||||
} finally {
|
|
||||||
if (textSource !== null) {
|
|
||||||
textSource.cleanup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
yomichan.logError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getTextSourceContent(textSource, length, layoutAwareScan) {
|
getTextSourceContent(textSource, length, layoutAwareScan) {
|
||||||
const clonedTextSource = textSource.clone();
|
const clonedTextSource = textSource.clone();
|
||||||
|
|
||||||
@ -206,35 +174,44 @@ class TextScanner extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async findTerms(textSource, optionsContext) {
|
async search(textSource, cause) {
|
||||||
const scanLength = this._scanLength;
|
let definitions = null;
|
||||||
const sentenceExtent = this._sentenceExtent;
|
let sentence = null;
|
||||||
const layoutAwareScan = this._layoutAwareScan;
|
let type = null;
|
||||||
const searchText = this.getTextSourceContent(textSource, scanLength, layoutAwareScan);
|
let error = null;
|
||||||
if (searchText.length === 0) { return null; }
|
let searched = false;
|
||||||
|
let optionsContext = null;
|
||||||
|
|
||||||
const {definitions, length} = await api.termsFind(searchText, {}, optionsContext);
|
try {
|
||||||
if (definitions.length === 0) { return null; }
|
if (this._textSourceCurrent !== null && this._textSourceCurrent.equals(textSource)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
textSource.setEndOffset(length, layoutAwareScan);
|
optionsContext = await this._getOptionsContext();
|
||||||
const sentence = this._documentUtil.extractSentence(textSource, sentenceExtent, layoutAwareScan);
|
searched = true;
|
||||||
|
|
||||||
return {definitions, sentence, type: 'terms'};
|
const result = await this._findDefinitions(textSource, cause);
|
||||||
}
|
if (result !== null) {
|
||||||
|
({definitions, sentence, type} = result);
|
||||||
|
this._causeCurrent = cause;
|
||||||
|
this.setCurrentTextSource(textSource);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
async findKanji(textSource, optionsContext) {
|
if (!searched) { return; }
|
||||||
const sentenceExtent = this._sentenceExtent;
|
|
||||||
const layoutAwareScan = this._layoutAwareScan;
|
|
||||||
const searchText = this.getTextSourceContent(textSource, 1, layoutAwareScan);
|
|
||||||
if (searchText.length === 0) { return null; }
|
|
||||||
|
|
||||||
const definitions = await api.kanjiFind(searchText, optionsContext);
|
this.trigger('searched', {
|
||||||
if (definitions.length === 0) { return null; }
|
textScanner: this,
|
||||||
|
type,
|
||||||
textSource.setEndOffset(1, layoutAwareScan);
|
definitions,
|
||||||
const sentence = this._documentUtil.extractSentence(textSource, sentenceExtent, layoutAwareScan);
|
sentence,
|
||||||
|
cause,
|
||||||
return {definitions, sentence, type: 'kanji'};
|
textSource,
|
||||||
|
optionsContext,
|
||||||
|
error
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private
|
// Private
|
||||||
@ -248,7 +225,7 @@ class TextScanner extends EventDispatcher {
|
|||||||
_onMouseMove(e) {
|
_onMouseMove(e) {
|
||||||
this._scanTimerClear();
|
this._scanTimerClear();
|
||||||
|
|
||||||
if (this._pendingLookup || DocumentUtil.isMouseButtonDown(e, 'primary')) {
|
if (DocumentUtil.isMouseButtonDown(e, 'primary')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,18 +239,7 @@ class TextScanner extends EventDispatcher {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const search = async () => {
|
this._searchAtFromMouse(e.clientX, e.clientY);
|
||||||
if (this._modifier === 'none') {
|
|
||||||
if (!await this._scanTimerWait()) {
|
|
||||||
// Aborted
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.searchAt(e.clientX, e.clientY, 'mouse');
|
|
||||||
};
|
|
||||||
|
|
||||||
search();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_onMouseDown(e) {
|
_onMouseDown(e) {
|
||||||
@ -296,6 +262,10 @@ class TextScanner extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_onClick(e) {
|
_onClick(e) {
|
||||||
|
if (this._searchOnClick) {
|
||||||
|
this._searchAt(e.clientX, e.clientY, 'click');
|
||||||
|
}
|
||||||
|
|
||||||
if (this._preventNextClick) {
|
if (this._preventNextClick) {
|
||||||
this._preventNextClick = false;
|
this._preventNextClick = false;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -334,25 +304,7 @@ class TextScanner extends EventDispatcher {
|
|||||||
|
|
||||||
this._primaryTouchIdentifier = primaryTouch.identifier;
|
this._primaryTouchIdentifier = primaryTouch.identifier;
|
||||||
|
|
||||||
if (this._pendingLookup) {
|
this._searchAtFromTouchStart(primaryTouch.clientX, primaryTouch.clientY);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const textSourceCurrentPrevious = this._textSourceCurrent !== null ? this._textSourceCurrent.clone() : null;
|
|
||||||
|
|
||||||
this.searchAt(primaryTouch.clientX, primaryTouch.clientY, 'touchStart')
|
|
||||||
.then(() => {
|
|
||||||
if (
|
|
||||||
this._textSourceCurrent === null ||
|
|
||||||
this._textSourceCurrent.equals(textSourceCurrentPrevious)
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._preventScroll = true;
|
|
||||||
this._preventNextContextMenu = true;
|
|
||||||
this._preventNextMouseDown = true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_onTouchEnd(e) {
|
_onTouchEnd(e) {
|
||||||
@ -384,7 +336,7 @@ class TextScanner extends EventDispatcher {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.searchAt(primaryTouch.clientX, primaryTouch.clientY, 'touchMove');
|
this._searchAt(primaryTouch.clientX, primaryTouch.clientY, 'touchMove');
|
||||||
|
|
||||||
e.preventDefault(); // Disable scroll
|
e.preventDefault(); // Disable scroll
|
||||||
}
|
}
|
||||||
@ -425,13 +377,13 @@ class TextScanner extends EventDispatcher {
|
|||||||
[this._node, 'mousedown', this._onMouseDown.bind(this)],
|
[this._node, 'mousedown', this._onMouseDown.bind(this)],
|
||||||
[this._node, 'mousemove', this._onMouseMove.bind(this)],
|
[this._node, 'mousemove', this._onMouseMove.bind(this)],
|
||||||
[this._node, 'mouseover', this._onMouseOver.bind(this)],
|
[this._node, 'mouseover', this._onMouseOver.bind(this)],
|
||||||
[this._node, 'mouseout', this._onMouseOut.bind(this)]
|
[this._node, 'mouseout', this._onMouseOut.bind(this)],
|
||||||
|
[this._node, 'click', this._onClick.bind(this)]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
_getTouchEventListeners() {
|
_getTouchEventListeners() {
|
||||||
return [
|
return [
|
||||||
[this._node, 'click', this._onClick.bind(this)],
|
|
||||||
[this._node, 'auxclick', this._onAuxClick.bind(this)],
|
[this._node, 'auxclick', this._onAuxClick.bind(this)],
|
||||||
[this._node, 'touchstart', this._onTouchStart.bind(this)],
|
[this._node, 'touchstart', this._onTouchStart.bind(this)],
|
||||||
[this._node, 'touchend', this._onTouchEnd.bind(this)],
|
[this._node, 'touchend', this._onTouchEnd.bind(this)],
|
||||||
@ -460,4 +412,106 @@ class TextScanner extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _findDefinitions(textSource, optionsContext) {
|
||||||
|
if (textSource === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (this._searchTerms) {
|
||||||
|
const results = await this._findTerms(textSource, optionsContext);
|
||||||
|
if (results !== null) { return results; }
|
||||||
|
}
|
||||||
|
if (this._searchKanji) {
|
||||||
|
const results = await this._findKanji(textSource, optionsContext);
|
||||||
|
if (results !== null) { return results; }
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async _findTerms(textSource, optionsContext) {
|
||||||
|
const scanLength = this._scanLength;
|
||||||
|
const sentenceExtent = this._sentenceExtent;
|
||||||
|
const layoutAwareScan = this._layoutAwareScan;
|
||||||
|
const searchText = this.getTextSourceContent(textSource, scanLength, layoutAwareScan);
|
||||||
|
if (searchText.length === 0) { return null; }
|
||||||
|
|
||||||
|
const {definitions, length} = await api.termsFind(searchText, {}, optionsContext);
|
||||||
|
if (definitions.length === 0) { return null; }
|
||||||
|
|
||||||
|
textSource.setEndOffset(length, layoutAwareScan);
|
||||||
|
const sentence = this._documentUtil.extractSentence(textSource, sentenceExtent, layoutAwareScan);
|
||||||
|
|
||||||
|
return {definitions, sentence, type: 'terms'};
|
||||||
|
}
|
||||||
|
|
||||||
|
async _findKanji(textSource, optionsContext) {
|
||||||
|
const sentenceExtent = this._sentenceExtent;
|
||||||
|
const layoutAwareScan = this._layoutAwareScan;
|
||||||
|
const searchText = this.getTextSourceContent(textSource, 1, layoutAwareScan);
|
||||||
|
if (searchText.length === 0) { return null; }
|
||||||
|
|
||||||
|
const definitions = await api.kanjiFind(searchText, optionsContext);
|
||||||
|
if (definitions.length === 0) { return null; }
|
||||||
|
|
||||||
|
textSource.setEndOffset(1, layoutAwareScan);
|
||||||
|
const sentence = this._documentUtil.extractSentence(textSource, sentenceExtent, layoutAwareScan);
|
||||||
|
|
||||||
|
return {definitions, sentence, type: 'kanji'};
|
||||||
|
}
|
||||||
|
|
||||||
|
async _searchAt(x, y, cause) {
|
||||||
|
if (this._pendingLookup) { return; }
|
||||||
|
|
||||||
|
try {
|
||||||
|
this._pendingLookup = true;
|
||||||
|
this._scanTimerClear();
|
||||||
|
|
||||||
|
if (typeof this._ignorePoint === 'function' && await this._ignorePoint(x, y)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const textSource = this._documentUtil.getRangeFromPoint(x, y, this._deepContentScan);
|
||||||
|
try {
|
||||||
|
await this.search(textSource, cause);
|
||||||
|
} finally {
|
||||||
|
if (textSource !== null) {
|
||||||
|
textSource.cleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
yomichan.logError(e);
|
||||||
|
} finally {
|
||||||
|
this._pendingLookup = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async _searchAtFromMouse(x, y) {
|
||||||
|
if (this._pendingLookup) { return; }
|
||||||
|
|
||||||
|
if (this._modifier === 'none') {
|
||||||
|
if (!await this._scanTimerWait()) {
|
||||||
|
// Aborted
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await this._searchAt(x, y, 'mouse');
|
||||||
|
}
|
||||||
|
|
||||||
|
async _searchAtFromTouchStart(x, y) {
|
||||||
|
if (this._pendingLookup) { return; }
|
||||||
|
|
||||||
|
const textSourceCurrentPrevious = this._textSourceCurrent !== null ? this._textSourceCurrent.clone() : null;
|
||||||
|
|
||||||
|
await this._searchAt(x, y, 'touchStart');
|
||||||
|
|
||||||
|
if (
|
||||||
|
this._textSourceCurrent !== null &&
|
||||||
|
!this._textSourceCurrent.equals(textSourceCurrentPrevious)
|
||||||
|
) {
|
||||||
|
this._preventScroll = true;
|
||||||
|
this._preventNextContextMenu = true;
|
||||||
|
this._preventNextMouseDown = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user