scan decoupling
This commit is contained in:
parent
02a34bb4bc
commit
e5be42d3de
@ -20,7 +20,14 @@
|
|||||||
class Frontend {
|
class Frontend {
|
||||||
constructor(popup, ignoreNodes) {
|
constructor(popup, ignoreNodes) {
|
||||||
this.popup = popup;
|
this.popup = popup;
|
||||||
this.textScanner = new TextScanner(window, ignoreNodes, this.popup, this.searchSource.bind(this));
|
this.textScanner = new TextScanner(
|
||||||
|
window,
|
||||||
|
ignoreNodes,
|
||||||
|
[this.popup.container],
|
||||||
|
[(x, y) => this.popup.containsPoint(x, y)]
|
||||||
|
);
|
||||||
|
this.textScanner.subscribe('textSearch', ({textSource, cause}) => this.searchSource(textSource, cause));
|
||||||
|
this.textScanner.subscribe('searchClear', () => this.searchClear(true));
|
||||||
this.options = null;
|
this.options = null;
|
||||||
|
|
||||||
this.optionsContext = {
|
this.optionsContext = {
|
||||||
@ -138,7 +145,6 @@ class Frontend {
|
|||||||
let results = null;
|
let results = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.textScanner.pendingLookup = true;
|
|
||||||
if (textSource !== null) {
|
if (textSource !== null) {
|
||||||
results = (
|
results = (
|
||||||
await this.findTerms(textSource) ||
|
await this.findTerms(textSource) ||
|
||||||
@ -165,8 +171,6 @@ class Frontend {
|
|||||||
if (results === null && this.options.scanning.autoHideResults) {
|
if (results === null && this.options.scanning.autoHideResults) {
|
||||||
this.searchClear(true);
|
this.searchClear(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.textScanner.pendingLookup = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
@ -182,7 +186,6 @@ class Frontend {
|
|||||||
{definitions, context: {sentence, url, focus, disableHistory: true}}
|
{definitions, context: {sentence, url, focus, disableHistory: true}}
|
||||||
);
|
);
|
||||||
|
|
||||||
this.textScanner.setCurrentTextSource(textSource);
|
|
||||||
if (this.options.scanning.selectText) {
|
if (this.options.scanning.selectText) {
|
||||||
textSource.select();
|
textSource.select();
|
||||||
}
|
}
|
||||||
|
@ -18,19 +18,23 @@
|
|||||||
|
|
||||||
|
|
||||||
class TextScanner {
|
class TextScanner {
|
||||||
constructor(node, ignoreNodes, popup, onTextSearch) {
|
constructor(node, ignoreNodes, ignoreElements, ignorePoints) {
|
||||||
this.node = node;
|
this.node = node;
|
||||||
this.ignoreNodes = (Array.isArray(ignoreNodes) && ignoreNodes.length > 0 ? ignoreNodes.join(',') : null);
|
this.ignoreNodes = (Array.isArray(ignoreNodes) && ignoreNodes.length > 0 ? ignoreNodes.join(',') : null);
|
||||||
this.popup = popup;
|
this.ignoreElements = ignoreElements;
|
||||||
this.onTextSearch = onTextSearch;
|
this.ignorePoints = ignorePoints;
|
||||||
|
|
||||||
this.popupTimerPromise = null;
|
this.scanTimerPromise = null;
|
||||||
this.textSourceCurrent = null;
|
this.textSourceCurrent = null;
|
||||||
this.pendingLookup = false;
|
this.pendingLookup = false;
|
||||||
this.options = null;
|
this.options = null;
|
||||||
|
|
||||||
this.enabled = false;
|
this.enabled = false;
|
||||||
this.eventListeners = [];
|
this.eventListeners = [];
|
||||||
|
this.subscribers = {
|
||||||
|
searchClear: [],
|
||||||
|
textSearch: []
|
||||||
|
};
|
||||||
|
|
||||||
this.primaryTouchIdentifier = null;
|
this.primaryTouchIdentifier = null;
|
||||||
this.preventNextContextMenu = false;
|
this.preventNextContextMenu = false;
|
||||||
@ -40,13 +44,13 @@ class TextScanner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMouseOver(e) {
|
onMouseOver(e) {
|
||||||
if (this.popup && e.target === this.popup.container) {
|
if (this.ignoreElements.includes(e.target)) {
|
||||||
this.popupTimerClear();
|
this.scanTimerClear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseMove(e) {
|
onMouseMove(e) {
|
||||||
this.popupTimerClear();
|
this.scanTimerClear();
|
||||||
|
|
||||||
if (this.pendingLookup || DOM.isMouseButtonDown(e, 'primary')) {
|
if (this.pendingLookup || DOM.isMouseButtonDown(e, 'primary')) {
|
||||||
return;
|
return;
|
||||||
@ -63,7 +67,7 @@ class TextScanner {
|
|||||||
|
|
||||||
const search = async () => {
|
const search = async () => {
|
||||||
if (scanningModifier === 'none') {
|
if (scanningModifier === 'none') {
|
||||||
if (!await this.popupTimerWait()) {
|
if (!await this.scanTimerWait()) {
|
||||||
// Aborted
|
// Aborted
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -84,14 +88,14 @@ class TextScanner {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DOM.isMouseButtonPressed(e, 'primary')) {
|
if (DOM.isMouseButtonDown(e, 'primary')) {
|
||||||
this.popupTimerClear();
|
this.scanTimerClear();
|
||||||
this.searchClear();
|
this.onSearchClear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseOut() {
|
onMouseOut() {
|
||||||
this.popupTimerClear();
|
this.scanTimerClear();
|
||||||
}
|
}
|
||||||
|
|
||||||
onClick(e) {
|
onClick(e) {
|
||||||
@ -192,23 +196,55 @@ class TextScanner {
|
|||||||
e.preventDefault(); // Disable scroll
|
e.preventDefault(); // Disable scroll
|
||||||
}
|
}
|
||||||
|
|
||||||
async popupTimerWait() {
|
async onSearchClear() {
|
||||||
|
this.searchClear();
|
||||||
|
await this.publish('searchClear', {});
|
||||||
|
}
|
||||||
|
|
||||||
|
async onTextSearch(textSource, cause) {
|
||||||
|
this.pendingLookup = true;
|
||||||
|
const results = await this.publish('textSearch', {textSource, cause});
|
||||||
|
if (results.some((r) => r)) {
|
||||||
|
this.textSourceCurrent = textSource;
|
||||||
|
}
|
||||||
|
this.pendingLookup = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
onError(error) {
|
||||||
|
logError(error, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribe(eventName, subscriber) {
|
||||||
|
if (this.subscribers[eventName].includes(subscriber)) { return; }
|
||||||
|
this.subscribers[eventName].push(subscriber);
|
||||||
|
}
|
||||||
|
|
||||||
|
async publish(eventName, data) {
|
||||||
|
const results = [];
|
||||||
|
for (const subscriber of this.subscribers[eventName]) {
|
||||||
|
const result = await subscriber(data);
|
||||||
|
results.push(result);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
async scanTimerWait() {
|
||||||
const delay = this.options.scanning.delay;
|
const delay = this.options.scanning.delay;
|
||||||
const promise = promiseTimeout(delay, true);
|
const promise = promiseTimeout(delay, true);
|
||||||
this.popupTimerPromise = promise;
|
this.scanTimerPromise = promise;
|
||||||
try {
|
try {
|
||||||
return await promise;
|
return await promise;
|
||||||
} finally {
|
} finally {
|
||||||
if (this.popupTimerPromise === promise) {
|
if (this.scanTimerPromise === promise) {
|
||||||
this.popupTimerPromise = null;
|
this.scanTimerPromise = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
popupTimerClear() {
|
scanTimerClear() {
|
||||||
if (this.popupTimerPromise !== null) {
|
if (this.scanTimerPromise !== null) {
|
||||||
this.popupTimerPromise.resolve(false);
|
this.scanTimerPromise.resolve(false);
|
||||||
this.popupTimerPromise = null;
|
this.scanTimerPromise = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,7 +259,7 @@ class TextScanner {
|
|||||||
this.clearEventListeners();
|
this.clearEventListeners();
|
||||||
this.enabled = false;
|
this.enabled = false;
|
||||||
}
|
}
|
||||||
this.searchClear();
|
this.onSearchClear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,12 +298,18 @@ class TextScanner {
|
|||||||
|
|
||||||
async searchAt(x, y, cause) {
|
async searchAt(x, y, cause) {
|
||||||
try {
|
try {
|
||||||
this.popupTimerClear();
|
this.scanTimerClear();
|
||||||
|
|
||||||
if (this.pendingLookup || (this.popup && await this.popup.containsPoint(x, y))) {
|
if (this.pendingLookup) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const ignorePointFn of this.ignorePoints) {
|
||||||
|
if (await ignorePointFn(x, y)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const textSource = docRangeFromPoint(x, y, this.options);
|
const textSource = docRangeFromPoint(x, y, this.options);
|
||||||
if (this.textSourceCurrent !== null && this.textSourceCurrent.equals(textSource)) {
|
if (this.textSourceCurrent !== null && this.textSourceCurrent.equals(textSource)) {
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user