extract ClipboardMonitor from DisplaySearch
This commit is contained in:
parent
37a922adc0
commit
c685fd0e5f
78
ext/bg/js/clipboard-monitor.js
Normal file
78
ext/bg/js/clipboard-monitor.js
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Alex Yatskov <alex@foosoft.net>
|
||||
* Author: Alex Yatskov <alex@foosoft.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
class ClipboardMonitor {
|
||||
constructor() {
|
||||
this.timerId = null;
|
||||
this.timerToken = null;
|
||||
this.interval = 250;
|
||||
this.previousText = null;
|
||||
}
|
||||
|
||||
onClipboardText(_text) {
|
||||
throw new Error('Override me');
|
||||
}
|
||||
|
||||
start() {
|
||||
// The token below is used as a unique identifier to ensure that a new clipboard monitor
|
||||
// hasn't been started during the await call. The check below the await apiClipboardGet()
|
||||
// call will exit early if the reference has changed.
|
||||
const token = {};
|
||||
const intervalCallback = async () => {
|
||||
this.timerId = null;
|
||||
|
||||
let text = null;
|
||||
try {
|
||||
text = await apiClipboardGet();
|
||||
} catch (e) {
|
||||
// NOP
|
||||
}
|
||||
if (this.timerToken !== token) { return; }
|
||||
|
||||
if (
|
||||
typeof text === 'string' &&
|
||||
(text = text.trim()).length > 0 &&
|
||||
text !== this.previousText
|
||||
) {
|
||||
this.previousText = text;
|
||||
if (jpIsStringPartiallyJapanese(text)) {
|
||||
this.onClipboardText(text);
|
||||
}
|
||||
}
|
||||
|
||||
this.timerId = setTimeout(intervalCallback, this.interval);
|
||||
};
|
||||
|
||||
this.timerToken = token;
|
||||
|
||||
intervalCallback();
|
||||
}
|
||||
|
||||
stop() {
|
||||
this.timerToken = null;
|
||||
if (this.timerId !== null) {
|
||||
clearTimeout(this.timerId);
|
||||
this.timerId = null;
|
||||
}
|
||||
}
|
||||
|
||||
setPreviousText(text) {
|
||||
this.previousText = text;
|
||||
}
|
||||
}
|
@ -36,10 +36,7 @@ class DisplaySearch extends Display {
|
||||
this.introVisible = true;
|
||||
this.introAnimationTimer = null;
|
||||
|
||||
this.clipboardMonitorTimerId = null;
|
||||
this.clipboardMonitorTimerToken = null;
|
||||
this.clipboardInterval = 250;
|
||||
this.clipboardPreviousText = null;
|
||||
this.clipboardMonitor = new ClipboardMonitor();
|
||||
}
|
||||
|
||||
static create() {
|
||||
@ -93,7 +90,7 @@ class DisplaySearch extends Display {
|
||||
if (this.clipboardMonitorEnable !== null) {
|
||||
if (this.options.general.enableClipboardMonitor === true) {
|
||||
this.clipboardMonitorEnable.checked = true;
|
||||
this.startClipboardMonitor();
|
||||
this.clipboardMonitor.start();
|
||||
} else {
|
||||
this.clipboardMonitorEnable.checked = false;
|
||||
}
|
||||
@ -103,7 +100,7 @@ class DisplaySearch extends Display {
|
||||
{permissions: ['clipboardRead']},
|
||||
(granted) => {
|
||||
if (granted) {
|
||||
this.startClipboardMonitor();
|
||||
this.clipboardMonitor.start();
|
||||
apiOptionsSet({general: {enableClipboardMonitor: true}}, this.getOptionsContext());
|
||||
} else {
|
||||
e.target.checked = false;
|
||||
@ -111,16 +108,18 @@ class DisplaySearch extends Display {
|
||||
}
|
||||
);
|
||||
} else {
|
||||
this.stopClipboardMonitor();
|
||||
this.clipboardMonitor.stop();
|
||||
apiOptionsSet({general: {enableClipboardMonitor: false}}, this.getOptionsContext());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener('popstate', (e) => this.onPopState(e));
|
||||
window.addEventListener('copy', (e) => this.onCopy(e));
|
||||
|
||||
this.clipboardMonitor.onClipboardText = (text) => this.onClipboardText(text);
|
||||
|
||||
this.updateSearchButton();
|
||||
this.initClipboardMonitor();
|
||||
} catch (e) {
|
||||
this.onError(e);
|
||||
}
|
||||
@ -199,6 +198,17 @@ class DisplaySearch extends Display {
|
||||
}
|
||||
}
|
||||
|
||||
onCopy() {
|
||||
// ignore copy from search page
|
||||
this.clipboardMonitor.setPreviousText(document.getSelection().toString().trim());
|
||||
}
|
||||
|
||||
onClipboardText(text) {
|
||||
this.setQuery(this.isWanakanaEnabled() ? window.wanakana.toKana(text) : text);
|
||||
window.history.pushState(null, '', `${window.location.pathname}?query=${encodeURIComponent(text)}`);
|
||||
this.onSearchQueryUpdated(this.query.value, true);
|
||||
}
|
||||
|
||||
async onSearchQueryUpdated(query, animate) {
|
||||
try {
|
||||
const details = {};
|
||||
@ -238,58 +248,6 @@ class DisplaySearch extends Display {
|
||||
this.queryParser.setOptions(this.options);
|
||||
}
|
||||
|
||||
initClipboardMonitor() {
|
||||
// ignore copy from search page
|
||||
window.addEventListener('copy', () => {
|
||||
this.clipboardPreviousText = document.getSelection().toString().trim();
|
||||
});
|
||||
}
|
||||
|
||||
startClipboardMonitor() {
|
||||
// The token below is used as a unique identifier to ensure that a new clipboard monitor
|
||||
// hasn't been started during the await call. The check below the await apiClipboardGet()
|
||||
// call will exit early if the reference has changed.
|
||||
const token = {};
|
||||
const intervalCallback = async () => {
|
||||
this.clipboardMonitorTimerId = null;
|
||||
|
||||
let text = null;
|
||||
try {
|
||||
text = await apiClipboardGet();
|
||||
} catch (e) {
|
||||
// NOP
|
||||
}
|
||||
if (this.clipboardMonitorTimerToken !== token) { return; }
|
||||
|
||||
if (
|
||||
typeof text === 'string' &&
|
||||
(text = text.trim()).length > 0 &&
|
||||
text !== this.clipboardPreviousText
|
||||
) {
|
||||
this.clipboardPreviousText = text;
|
||||
if (jpIsStringPartiallyJapanese(text)) {
|
||||
this.setQuery(this.isWanakanaEnabled() ? window.wanakana.toKana(text) : text);
|
||||
window.history.pushState(null, '', `${window.location.pathname}?query=${encodeURIComponent(text)}`);
|
||||
this.onSearchQueryUpdated(this.query.value, true);
|
||||
}
|
||||
}
|
||||
|
||||
this.clipboardMonitorTimerId = setTimeout(intervalCallback, this.clipboardInterval);
|
||||
};
|
||||
|
||||
this.clipboardMonitorTimerToken = token;
|
||||
|
||||
intervalCallback();
|
||||
}
|
||||
|
||||
stopClipboardMonitor() {
|
||||
this.clipboardMonitorTimerToken = null;
|
||||
if (this.clipboardMonitorTimerId !== null) {
|
||||
clearTimeout(this.clipboardMonitorTimerId);
|
||||
this.clipboardMonitorTimerId = null;
|
||||
}
|
||||
}
|
||||
|
||||
isWanakanaEnabled() {
|
||||
return this.wanakanaEnable !== null && this.wanakanaEnable.checked;
|
||||
}
|
||||
|
@ -87,6 +87,7 @@
|
||||
<script src="/mixed/js/text-scanner.js"></script>
|
||||
|
||||
<script src="/bg/js/search-query-parser.js"></script>
|
||||
<script src="/bg/js/clipboard-monitor.js"></script>
|
||||
<script src="/bg/js/search.js"></script>
|
||||
<script src="/bg/js/search-frontend.js"></script>
|
||||
</body>
|
||||
|
Loading…
Reference in New Issue
Block a user