Merge pull request #411 from siikamiika/apply-all-options-profile-change

apply all options on profile change
This commit is contained in:
siikamiika 2020-03-21 22:29:07 +02:00 committed by GitHub
commit 08d38d8db2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 101 additions and 91 deletions

View File

@ -30,12 +30,7 @@ async function searchFrontendSetup() {
const options = await apiOptionsGet(optionsContext); const options = await apiOptionsGet(optionsContext);
if (!options.scanning.enableOnSearchPage) { return; } if (!options.scanning.enableOnSearchPage) { return; }
const ignoreNodes = ['.scan-disable', '.scan-disable *']; window.frontendInitializationData = {depth: 1, proxy: false};
if (!options.scanning.enableOnPopupExpressions) {
ignoreNodes.push('.source-text', '.source-text *');
}
window.frontendInitializationData = {depth: 1, ignoreNodes, proxy: false};
const scriptSrcs = [ const scriptSrcs = [
'/mixed/js/text-scanner.js', '/mixed/js/text-scanner.js',

View File

@ -27,12 +27,14 @@
*/ */
class QueryParser extends TextScanner { class QueryParser extends TextScanner {
constructor(search) { constructor({getOptionsContext, setContent, setSpinnerVisible}) {
super(document.querySelector('#query-parser-content'), [], [], []); super(document.querySelector('#query-parser-content'), [], []);
this.search = search;
this.getOptionsContext = getOptionsContext;
this.setContent = setContent;
this.setSpinnerVisible = setSpinnerVisible;
this.parseResults = []; this.parseResults = [];
this.selectedParser = null;
this.queryParser = document.querySelector('#query-parser-content'); this.queryParser = document.querySelector('#query-parser-content');
this.queryParserSelect = document.querySelector('#query-parser-select-container'); this.queryParserSelect = document.querySelector('#query-parser-select-container');
@ -56,18 +58,18 @@ class QueryParser extends TextScanner {
async onSearchSource(textSource, cause) { async onSearchSource(textSource, cause) {
if (textSource === null) { return null; } if (textSource === null) { return null; }
this.setTextSourceScanLength(textSource, this.search.options.scanning.length); this.setTextSourceScanLength(textSource, this.options.scanning.length);
const searchText = textSource.text(); const searchText = textSource.text();
if (searchText.length === 0) { return; } if (searchText.length === 0) { return; }
const {definitions, length} = await apiTermsFind(searchText, {}, this.search.getOptionsContext()); const {definitions, length} = await apiTermsFind(searchText, {}, this.getOptionsContext());
if (definitions.length === 0) { return null; } if (definitions.length === 0) { return null; }
const sentence = docSentenceExtract(textSource, this.search.options.anki.sentenceExt); const sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt);
textSource.setEndOffset(length); textSource.setEndOffset(length);
this.search.setContent('terms', {definitions, context: { this.setContent('terms', {definitions, context: {
focus: false, focus: false,
disableHistory: cause === 'mouse', disableHistory: cause === 'mouse',
sentence, sentence,
@ -79,9 +81,7 @@ class QueryParser extends TextScanner {
onParserChange(e) { onParserChange(e) {
const selectedParser = e.target.value; const selectedParser = e.target.value;
this.selectedParser = selectedParser; apiOptionsSet({parsing: {selectedParser}}, this.getOptionsContext());
apiOptionsSet({parsing: {selectedParser}}, this.search.getOptionsContext());
this.renderParseResult();
} }
getMouseEventListeners() { getMouseEventListeners() {
@ -112,23 +112,20 @@ class QueryParser extends TextScanner {
refreshSelectedParser() { refreshSelectedParser() {
if (this.parseResults.length > 0) { if (this.parseResults.length > 0) {
if (this.selectedParser === null) { if (!this.getParseResult()) {
this.selectedParser = this.search.options.parsing.selectedParser;
}
if (this.selectedParser === null || !this.getParseResult()) {
const selectedParser = this.parseResults[0].id; const selectedParser = this.parseResults[0].id;
this.selectedParser = selectedParser; apiOptionsSet({parsing: {selectedParser}}, this.getOptionsContext());
apiOptionsSet({parsing: {selectedParser}}, this.search.getOptionsContext());
} }
} }
} }
getParseResult() { getParseResult() {
return this.parseResults.find((r) => r.id === this.selectedParser); const {selectedParser} = this.options.parsing;
return this.parseResults.find((r) => r.id === selectedParser);
} }
async setText(text) { async setText(text) {
this.search.setSpinnerVisible(true); this.setSpinnerVisible(true);
this.setPreview(text); this.setPreview(text);
@ -138,20 +135,20 @@ class QueryParser extends TextScanner {
this.renderParserSelect(); this.renderParserSelect();
this.renderParseResult(); this.renderParseResult();
this.search.setSpinnerVisible(false); this.setSpinnerVisible(false);
} }
async parseText(text) { async parseText(text) {
const results = []; const results = [];
if (this.search.options.parsing.enableScanningParser) { if (this.options.parsing.enableScanningParser) {
results.push({ results.push({
name: 'Scanning parser', name: 'Scanning parser',
id: 'scan', id: 'scan',
parsedText: await apiTextParse(text, this.search.getOptionsContext()) parsedText: await apiTextParse(text, this.getOptionsContext())
}); });
} }
if (this.search.options.parsing.enableMecabParser) { if (this.options.parsing.enableMecabParser) {
const mecabResults = await apiTextParseMecab(text, this.search.getOptionsContext()); const mecabResults = await apiTextParseMecab(text, this.getOptionsContext());
for (const [mecabDictName, mecabDictResults] of mecabResults) { for (const [mecabDictName, mecabDictResults] of mecabResults) {
results.push({ results.push({
name: `MeCab: ${mecabDictName}`, name: `MeCab: ${mecabDictName}`,
@ -176,7 +173,8 @@ class QueryParser extends TextScanner {
renderParserSelect() { renderParserSelect() {
this.queryParserSelect.textContent = ''; this.queryParserSelect.textContent = '';
if (this.parseResults.length > 1) { if (this.parseResults.length > 1) {
const select = this.queryParserGenerator.createParserSelect(this.parseResults, this.selectedParser); const {selectedParser} = this.options.parsing;
const select = this.queryParserGenerator.createParserSelect(this.parseResults, selectedParser);
select.addEventListener('change', this.onParserChange.bind(this)); select.addEventListener('change', this.onParserChange.bind(this));
this.queryParserSelect.appendChild(select); this.queryParserSelect.appendChild(select);
} }

View File

@ -29,12 +29,18 @@ class DisplaySearch extends Display {
constructor() { constructor() {
super(document.querySelector('#spinner'), document.querySelector('#content')); super(document.querySelector('#spinner'), document.querySelector('#content'));
this._isPrepared = false;
this.optionsContext = { this.optionsContext = {
depth: 0, depth: 0,
url: window.location.href url: window.location.href
}; };
this.queryParser = new QueryParser(this); this.queryParser = new QueryParser({
getOptionsContext: this.getOptionsContext.bind(this),
setContent: this.setContent.bind(this),
setSpinnerVisible: this.setSpinnerVisible.bind(this)
});
this.search = document.querySelector('#search'); this.search = document.querySelector('#search');
this.query = document.querySelector('#query'); this.query = document.querySelector('#query');
@ -112,6 +118,8 @@ class DisplaySearch extends Display {
this.clipboardMonitor.on('change', this.onExternalSearchUpdate.bind(this)); this.clipboardMonitor.on('change', this.onExternalSearchUpdate.bind(this));
this.updateSearchButton(); this.updateSearchButton();
this._isPrepared = true;
} catch (e) { } catch (e) {
this.onError(e); this.onError(e);
} }
@ -247,15 +255,12 @@ class DisplaySearch extends Display {
} }
onWanakanaEnableChange(e) { onWanakanaEnableChange(e) {
const {queryParams: {query=''}} = parseUrl(window.location.href);
const enableWanakana = e.target.checked; const enableWanakana = e.target.checked;
if (enableWanakana) { if (enableWanakana) {
window.wanakana.bind(this.query); window.wanakana.bind(this.query);
} else { } else {
window.wanakana.unbind(this.query); window.wanakana.unbind(this.query);
} }
this.setQuery(query);
this.onSearchQueryUpdated(this.query.value, false);
apiOptionsSet({general: {enableWanakana}}, this.getOptionsContext()); apiOptionsSet({general: {enableWanakana}}, this.getOptionsContext());
} }
@ -278,19 +283,21 @@ class DisplaySearch extends Display {
} }
} }
async updateOptions(options) { async updateOptions() {
await super.updateOptions(options); await super.updateOptions();
this.queryParser.setOptions(this.options); this.queryParser.setOptions(this.options);
if (!this._isPrepared) { return; }
const query = this.query.value;
if (query) {
this.setQuery(query);
this.onSearchQueryUpdated(query, false);
}
} }
isWanakanaEnabled() { isWanakanaEnabled() {
return this.wanakanaEnable !== null && this.wanakanaEnable.checked; return this.wanakanaEnable !== null && this.wanakanaEnable.checked;
} }
getOptionsContext() {
return this.optionsContext;
}
setQuery(query) { setQuery(query) {
const interpretedQuery = this.isWanakanaEnabled() ? window.wanakana.toKana(query) : query; const interpretedQuery = this.isWanakanaEnabled() ? window.wanakana.toKana(query) : query;
this.query.value = interpretedQuery; this.query.value = interpretedQuery;

View File

@ -28,6 +28,8 @@ class DisplayFloat extends Display {
super(document.querySelector('#spinner'), document.querySelector('#definitions')); super(document.querySelector('#spinner'), document.querySelector('#definitions'));
this.autoPlayAudioTimer = null; this.autoPlayAudioTimer = null;
this._popupId = null;
this.optionsContext = { this.optionsContext = {
depth: 0, depth: 0,
url: window.location.href url: window.location.href
@ -53,7 +55,7 @@ class DisplayFloat extends Display {
['setContent', ({type, details}) => this.setContent(type, details)], ['setContent', ({type, details}) => this.setContent(type, details)],
['clearAutoPlayTimer', () => this.clearAutoPlayTimer()], ['clearAutoPlayTimer', () => this.clearAutoPlayTimer()],
['setCustomCss', ({css}) => this.setCustomCss(css)], ['setCustomCss', ({css}) => this.setCustomCss(css)],
['prepare', ({options, popupInfo, url, childrenSupported, scale, uniqueId}) => this.prepare(options, popupInfo, url, childrenSupported, scale, uniqueId)], ['prepare', ({popupInfo, url, childrenSupported, scale}) => this.prepare(popupInfo, url, childrenSupported, scale)],
['setContentScale', ({scale}) => this.setContentScale(scale)] ['setContentScale', ({scale}) => this.setContentScale(scale)]
]); ]);
@ -61,23 +63,24 @@ class DisplayFloat extends Display {
window.addEventListener('message', this.onMessage.bind(this), false); window.addEventListener('message', this.onMessage.bind(this), false);
} }
async prepare(options, popupInfo, url, childrenSupported, scale, uniqueId) { async prepare(popupInfo, url, childrenSupported, scale) {
if (this._prepareInvoked) { return; } if (this._prepareInvoked) { return; }
this._prepareInvoked = true; this._prepareInvoked = true;
await super.prepare(options);
const {id, depth, parentFrameId} = popupInfo; const {id, depth, parentFrameId} = popupInfo;
this._popupId = id;
this.optionsContext.depth = depth; this.optionsContext.depth = depth;
this.optionsContext.url = url; this.optionsContext.url = url;
await super.prepare();
if (childrenSupported) { if (childrenSupported) {
popupNestedInitialize(id, depth, parentFrameId, url); popupNestedInitialize(id, depth, parentFrameId, url);
} }
this.setContentScale(scale); this.setContentScale(scale);
apiForward('popupPrepareCompleted', {uniqueId}); apiForward('popupPrepareCompleted', {targetPopupId: this._popupId});
} }
onError(error) { onError(error) {
@ -144,10 +147,6 @@ class DisplayFloat extends Display {
handler(params); handler(params);
} }
getOptionsContext() {
return this.optionsContext;
}
autoPlayAudio() { autoPlayAudio() {
this.clearAutoPlayTimer(); this.clearAutoPlayTimer();
this.autoPlayAudioTimer = window.setTimeout(() => super.autoPlayAudio(), 400); this.autoPlayAudioTimer = window.setTimeout(() => super.autoPlayAudio(), 400);

View File

@ -26,7 +26,7 @@ async function main() {
await yomichan.prepare(); await yomichan.prepare();
const data = window.frontendInitializationData || {}; const data = window.frontendInitializationData || {};
const {id, depth=0, parentFrameId, ignoreNodes, url, proxy=false} = data; const {id, depth=0, parentFrameId, url, proxy=false} = data;
let popup; let popup;
if (proxy) { if (proxy) {
@ -38,7 +38,7 @@ async function main() {
popup = popupHost.getOrCreatePopup(null, null, depth); popup = popupHost.getOrCreatePopup(null, null, depth);
} }
const frontend = new Frontend(popup, ignoreNodes); const frontend = new Frontend(popup);
await frontend.prepare(); await frontend.prepare();
} }

View File

@ -26,10 +26,9 @@
*/ */
class Frontend extends TextScanner { class Frontend extends TextScanner {
constructor(popup, ignoreNodes) { constructor(popup) {
super( super(
window, window,
ignoreNodes,
popup.isProxy() ? [] : [popup.getContainer()], popup.isProxy() ? [] : [popup.getContainer()],
[(x, y) => this.popup.containsPoint(x, y)] [(x, y) => this.popup.containsPoint(x, y)]
); );
@ -95,6 +94,9 @@ class Frontend extends TextScanner {
} }
onRuntimeMessage({action, params}, sender, callback) { onRuntimeMessage({action, params}, sender, callback) {
const {targetPopupId} = params || {};
if (typeof targetPopupId !== 'undefined' && targetPopupId !== this.popup.id) { return; }
const handler = this._runtimeMessageHandlers.get(action); const handler = this._runtimeMessageHandlers.get(action);
if (typeof handler !== 'function') { return false; } if (typeof handler !== 'function') { return false; }
@ -129,8 +131,20 @@ class Frontend extends TextScanner {
async updateOptions() { async updateOptions() {
this.setOptions(await apiOptionsGet(this.getOptionsContext())); this.setOptions(await apiOptionsGet(this.getOptionsContext()));
const ignoreNodes = ['.scan-disable', '.scan-disable *'];
if (!this.options.scanning.enableOnPopupExpressions) {
ignoreNodes.push('.source-text', '.source-text *');
}
this.ignoreNodes = ignoreNodes.join(',');
await this.popup.setOptions(this.options); await this.popup.setOptions(this.options);
this._updateContentScale(); this._updateContentScale();
if (this.textSourceCurrent !== null && this.causeCurrent !== null) {
await this.onSearchSource(this.textSourceCurrent, this.causeCurrent);
}
} }
async onSearchSource(textSource, cause) { async onSearchSource(textSource, cause) {

View File

@ -36,12 +36,7 @@ async function popupNestedInitialize(id, depth, parentFrameId, url) {
return; return;
} }
const ignoreNodes = ['.scan-disable', '.scan-disable *']; window.frontendInitializationData = {id, depth, parentFrameId, url, proxy: true};
if (!options.scanning.enableOnPopupExpressions) {
ignoreNodes.push('.source-text', '.source-text *');
}
window.frontendInitializationData = {id, depth, parentFrameId, ignoreNodes, url, proxy: true};
const scriptSrcs = [ const scriptSrcs = [
'/mixed/js/text-scanner.js', '/mixed/js/text-scanner.js',

View File

@ -25,7 +25,6 @@
class PopupProxyHost { class PopupProxyHost {
constructor() { constructor() {
this._popups = new Map(); this._popups = new Map();
this._nextId = 0;
this._apiReceiver = null; this._apiReceiver = null;
this._frameIdPromise = null; this._frameIdPromise = null;
} }
@ -76,7 +75,7 @@ class PopupProxyHost {
// New unique id // New unique id
if (id === null) { if (id === null) {
id = this._nextId++; id = yomichan.generateId(16);
} }
// Create new popup // Create new popup

View File

@ -33,6 +33,10 @@ class PopupProxy {
// Public properties // Public properties
get id() {
return this._id;
}
get parent() { get parent() {
return null; return null;
} }

View File

@ -210,11 +210,9 @@ class Popup {
const parentFrameId = (typeof this._frameId === 'number' ? this._frameId : null); const parentFrameId = (typeof this._frameId === 'number' ? this._frameId : null);
this._container.setAttribute('src', chrome.runtime.getURL('/fg/float.html')); this._container.setAttribute('src', chrome.runtime.getURL('/fg/float.html'));
this._container.addEventListener('load', () => { this._container.addEventListener('load', () => {
const uniqueId = yomichan.generateId(32); this._listenForDisplayPrepareCompleted(resolve);
Popup._listenForDisplayPrepareCompleted(uniqueId, resolve);
this._invokeApi('prepare', { this._invokeApi('prepare', {
options: this._options,
popupInfo: { popupInfo: {
id: this._id, id: this._id,
depth: this._depth, depth: this._depth,
@ -222,8 +220,7 @@ class Popup {
}, },
url: this.url, url: this.url,
childrenSupported: this._childrenSupported, childrenSupported: this._childrenSupported,
scale: this._contentScale, scale: this._contentScale
uniqueId
}); });
}); });
this._observeFullscreen(true); this._observeFullscreen(true);
@ -364,23 +361,12 @@ class Popup {
contentWindow.postMessage({action, params, token}, this._targetOrigin); contentWindow.postMessage({action, params, token}, this._targetOrigin);
} }
static _getFullscreenElement() { _listenForDisplayPrepareCompleted(resolve) {
return (
document.fullscreenElement ||
document.msFullscreenElement ||
document.mozFullScreenElement ||
document.webkitFullscreenElement ||
null
);
}
static _listenForDisplayPrepareCompleted(uniqueId, resolve) {
const runtimeMessageCallback = ({action, params}, sender, callback) => { const runtimeMessageCallback = ({action, params}, sender, callback) => {
if ( if (
action === 'popupPrepareCompleted' && action === 'popupPrepareCompleted' &&
typeof params === 'object' && isObject(params) &&
params !== null && params.targetPopupId === this._id
params.uniqueId === uniqueId
) { ) {
chrome.runtime.onMessage.removeListener(runtimeMessageCallback); chrome.runtime.onMessage.removeListener(runtimeMessageCallback);
callback(); callback();
@ -391,6 +377,16 @@ class Popup {
chrome.runtime.onMessage.addListener(runtimeMessageCallback); chrome.runtime.onMessage.addListener(runtimeMessageCallback);
} }
static _getFullscreenElement() {
return (
document.fullscreenElement ||
document.msFullscreenElement ||
document.mozFullScreenElement ||
document.webkitFullscreenElement ||
null
);
}
static _getPositionForHorizontalText(elementRect, width, height, viewport, offsetScale, optionsGeneral) { static _getPositionForHorizontalText(elementRect, width, height, viewport, offsetScale, optionsGeneral) {
const preferBelow = (optionsGeneral.popupHorizontalTextPosition === 'below'); const preferBelow = (optionsGeneral.popupHorizontalTextPosition === 'below');
const horizontalOffset = optionsGeneral.popupHorizontalOffset * offsetScale; const horizontalOffset = optionsGeneral.popupHorizontalOffset * offsetScale;

View File

@ -40,6 +40,7 @@ class Display {
this.spinner = spinner; this.spinner = spinner;
this.container = container; this.container = container;
this.definitions = []; this.definitions = [];
this.optionsContext = null;
this.options = null; this.options = null;
this.context = null; this.context = null;
this.index = 0; this.index = 0;
@ -165,12 +166,11 @@ class Display {
this.setInteractive(true); this.setInteractive(true);
} }
async prepare(options=null) { async prepare() {
await yomichan.prepare(); await yomichan.prepare();
const displayGeneratorPromise = this.displayGenerator.prepare(); await this.displayGenerator.prepare();
const updateOptionsPromise = this.updateOptions(options); await this.updateOptions();
await Promise.all([displayGeneratorPromise, updateOptionsPromise]); yomichan.on('optionsUpdated', () => this.updateOptions());
yomichan.on('optionsUpdated', () => this.updateOptions(null));
} }
onError(_error) { onError(_error) {
@ -369,11 +369,11 @@ class Display {
} }
getOptionsContext() { getOptionsContext() {
throw new Error('Override me'); return this.optionsContext;
} }
async updateOptions(options) { async updateOptions() {
this.options = options ? options : await apiOptionsGet(this.getOptionsContext()); this.options = await apiOptionsGet(this.getOptionsContext());
this.updateDocumentOptions(this.options); this.updateDocumentOptions(this.options);
this.updateTheme(this.options.general.popupTheme); this.updateTheme(this.options.general.popupTheme);
this.setCustomCss(this.options.general.customPopupCss); this.setCustomCss(this.options.general.customPopupCss);

View File

@ -23,13 +23,15 @@
*/ */
class TextScanner { class TextScanner {
constructor(node, ignoreNodes, ignoreElements, ignorePoints) { constructor(node, ignoreElements, ignorePoints) {
this.node = node; this.node = node;
this.ignoreNodes = (Array.isArray(ignoreNodes) && ignoreNodes.length > 0 ? ignoreNodes.join(',') : null);
this.ignoreElements = ignoreElements; this.ignoreElements = ignoreElements;
this.ignorePoints = ignorePoints; this.ignorePoints = ignorePoints;
this.ignoreNodes = null;
this.scanTimerPromise = null; this.scanTimerPromise = null;
this.causeCurrent = null;
this.textSourceCurrent = null; this.textSourceCurrent = null;
this.pendingLookup = false; this.pendingLookup = false;
this.options = null; this.options = null;
@ -298,6 +300,7 @@ class TextScanner {
this.pendingLookup = true; this.pendingLookup = true;
const result = await this.onSearchSource(textSource, cause); const result = await this.onSearchSource(textSource, cause);
if (result !== null) { if (result !== null) {
this.causeCurrent = cause;
this.textSourceCurrent = textSource; this.textSourceCurrent = textSource;
if (this.options.scanning.selectText) { if (this.options.scanning.selectText) {
textSource.select(); textSource.select();