Search decouple (#1369)

* Update how query post-processing is implemented

* Update DisplaySearch to not subclass Display

* Update display construction

* Make display initialization consistent

* Remove unused

* Fix wanakana binding

* Use own frame/tab ID

* DisplaySearch => SearchDisplayController

* Fix globals
This commit is contained in:
toasted-nutbread 2021-02-11 22:57:38 -05:00 committed by GitHub
parent 94db6c69fa
commit 1c5e3e6d39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 80 additions and 66 deletions

View File

@ -17,22 +17,23 @@
/* global /* global
* ClipboardMonitor * ClipboardMonitor
* Display
* api * api
* wanakana * wanakana
*/ */
class DisplaySearch extends Display { class SearchDisplayController {
constructor(tabId, frameId, japaneseUtil, documentFocusController, hotkeyHandler) { constructor(tabId, frameId, display, japaneseUtil) {
super(tabId, frameId, 'search', japaneseUtil, documentFocusController, hotkeyHandler); this._tabId = tabId;
this._frameId = frameId;
this._display = display;
this._searchButton = document.querySelector('#search-button'); this._searchButton = document.querySelector('#search-button');
this._queryInput = document.querySelector('#search-textbox'); this._queryInput = document.querySelector('#search-textbox');
this._introElement = document.querySelector('#intro'); this._introElement = document.querySelector('#intro');
this._clipboardMonitorEnableCheckbox = document.querySelector('#clipboard-monitor-enable'); this._clipboardMonitorEnableCheckbox = document.querySelector('#clipboard-monitor-enable');
this._wanakanaEnableCheckbox = document.querySelector('#wanakana-enable'); this._wanakanaEnableCheckbox = document.querySelector('#wanakana-enable');
this._queryInputEvents = new EventListenerCollection(); this._queryInputEvents = new EventListenerCollection();
this._queryInputEventsSetup = false;
this._wanakanaEnabled = false; this._wanakanaEnabled = false;
this._isPrepared = false;
this._introVisible = true; this._introVisible = true;
this._introAnimationTimer = null; this._introAnimationTimer = null;
this._clipboardMonitorEnabled = false; this._clipboardMonitorEnabled = false;
@ -42,57 +43,38 @@ class DisplaySearch extends Display {
getText: async () => (await api.clipboardGet()) getText: async () => (await api.clipboardGet())
} }
}); });
this.autoPlayAudioDelay = 0;
this.hotkeyHandler.registerActions([
['focusSearchBox', this._onActionFocusSearchBox.bind(this)]
]);
} }
async prepare() { async prepare() {
await super.prepare(); await this._display.updateOptions();
await this.updateOptions();
yomichan.on('optionsUpdated', this._onOptionsUpdated.bind(this)); yomichan.on('optionsUpdated', this._onOptionsUpdated.bind(this));
this.on('optionsUpdated', this._onDisplayOptionsUpdated.bind(this)); this._display.on('optionsUpdated', this._onDisplayOptionsUpdated.bind(this));
this.on('contentUpdating', this._onContentUpdating.bind(this)); this._display.on('contentUpdating', this._onContentUpdating.bind(this));
this.on('modeChange', this._onModeChange.bind(this)); this._display.on('modeChange', this._onModeChange.bind(this));
this.registerMessageHandlers([ this._display.hotkeyHandler.registerActions([
['focusSearchBox', this._onActionFocusSearchBox.bind(this)]
]);
this._display.registerMessageHandlers([
['updateSearchQuery', {async: false, handler: this._onExternalSearchUpdate.bind(this)}] ['updateSearchQuery', {async: false, handler: this._onExternalSearchUpdate.bind(this)}]
]); ]);
this.queryParserVisible = true; this._display.autoPlayAudioDelay = 0;
this.setHistorySettings({useBrowserHistory: true}); this._display.queryParserVisible = true;
this._display.setHistorySettings({useBrowserHistory: true});
const enableWanakana = !!this.getOptions().general.enableWanakana; this._display.setQueryPostProcessor(this._postProcessQuery.bind(this));
this._wanakanaEnableCheckbox.checked = enableWanakana;
this._setWanakanaEnabled(enableWanakana);
this._searchButton.addEventListener('click', this._onSearch.bind(this), false); this._searchButton.addEventListener('click', this._onSearch.bind(this), false);
this._wanakanaEnableCheckbox.addEventListener('change', this._onWanakanaEnableChange.bind(this)); this._wanakanaEnableCheckbox.addEventListener('change', this._onWanakanaEnableChange.bind(this));
window.addEventListener('copy', this._onCopy.bind(this)); window.addEventListener('copy', this._onCopy.bind(this));
this._clipboardMonitor.on('change', this._onExternalSearchUpdate.bind(this)); this._clipboardMonitor.on('change', this._onExternalSearchUpdate.bind(this));
this._clipboardMonitorEnableCheckbox.addEventListener('change', this._onClipboardMonitorEnableChange.bind(this)); this._clipboardMonitorEnableCheckbox.addEventListener('change', this._onClipboardMonitorEnableChange.bind(this));
this.hotkeyHandler.on('keydownNonHotkey', this._onKeyDown.bind(this)); this._display.hotkeyHandler.on('keydownNonHotkey', this._onKeyDown.bind(this));
this._onModeChange(); this._onModeChange();
this._onDisplayOptionsUpdated({options: this.getOptions()}); this._onDisplayOptionsUpdated({options: this._display.getOptions()});
this.initializeState();
this._isPrepared = true;
}
postProcessQuery(query) {
if (this._wanakanaEnabled) {
try {
query = this._japaneseUtil.convertToKana(query);
} catch (e) {
// NOP
}
}
return query;
} }
// Actions // Actions
@ -118,16 +100,20 @@ class DisplaySearch extends Display {
} }
async _onOptionsUpdated() { async _onOptionsUpdated() {
await this.updateOptions(); await this._display.updateOptions();
const query = this._queryInput.value; const query = this._queryInput.value;
if (query) { if (query) {
this.searchLast(); this._display.searchLast();
} }
} }
_onDisplayOptionsUpdated({options}) { _onDisplayOptionsUpdated({options}) {
this._clipboardMonitorEnabled = options.clipboard.enableSearchPageMonitor; this._clipboardMonitorEnabled = options.clipboard.enableSearchPageMonitor;
this._updateClipboardMonitorEnabled(); this._updateClipboardMonitorEnabled();
const enableWanakana = !!this._display.getOptions().general.enableWanakana;
this._wanakanaEnableCheckbox.checked = enableWanakana;
this._setWanakanaEnabled(enableWanakana);
} }
_onContentUpdating({type, content, source}) { _onContentUpdating({type, content, source}) {
@ -138,7 +124,7 @@ class DisplaySearch extends Display {
case 'kanji': case 'kanji':
animate = !!content.animate; animate = !!content.animate;
valid = (typeof source === 'string' && source.length > 0); valid = (typeof source === 'string' && source.length > 0);
this.blurElement(this._queryInput); this._display.blurElement(this._queryInput);
break; break;
case 'clear': case 'clear':
valid = false; valid = false;
@ -167,7 +153,7 @@ class DisplaySearch extends Display {
// Search // Search
e.preventDefault(); e.preventDefault();
e.stopImmediatePropagation(); e.stopImmediatePropagation();
this.blurElement(e.currentTarget); this._display.blurElement(e.currentTarget);
this._search(true, true, true); this._search(true, true, true);
} }
@ -182,7 +168,7 @@ class DisplaySearch extends Display {
} }
_onExternalSearchUpdate({text, animate=true}) { _onExternalSearchUpdate({text, animate=true}) {
const {clipboard: {autoSearchContent, maximumSearchLength}} = this.getOptions(); const {clipboard: {autoSearchContent, maximumSearchLength}} = this._display.getOptions();
if (text.length > maximumSearchLength) { if (text.length > maximumSearchLength) {
text = text.substring(0, maximumSearchLength); text = text.substring(0, maximumSearchLength);
} }
@ -199,7 +185,7 @@ class DisplaySearch extends Display {
path: 'general.enableWanakana', path: 'general.enableWanakana',
value, value,
scope: 'profile', scope: 'profile',
optionsContext: this.getOptionsContext() optionsContext: this._display.getOptionsContext()
}], 'search'); }], 'search');
} }
@ -209,28 +195,28 @@ class DisplaySearch extends Display {
} }
_onModeChange() { _onModeChange() {
let mode = this.mode; let mode = this._display.mode;
if (mode === null) { mode = ''; } if (mode === null) { mode = ''; }
document.documentElement.dataset.searchMode = mode; document.documentElement.dataset.searchMode = mode;
this._updateClipboardMonitorEnabled(); this._updateClipboardMonitorEnabled();
} }
_setWanakanaEnabled(enabled) { _setWanakanaEnabled(enabled) {
if (this._queryInputEventsSetup && this._wanakanaEnabled === enabled) { return; }
const input = this._queryInput; const input = this._queryInput;
this._queryInputEvents.removeAllEventListeners(); this._queryInputEvents.removeAllEventListeners();
this._queryInputEvents.addEventListener(input, 'keydown', this._onSearchKeydown.bind(this), false); this._queryInputEvents.addEventListener(input, 'keydown', this._onSearchKeydown.bind(this), false);
if (this._wanakanaEnabled !== enabled) {
this._wanakanaEnabled = enabled; this._wanakanaEnabled = enabled;
if (enabled) { if (enabled) {
wanakana.bind(input); wanakana.bind(input);
} else { } else {
wanakana.unbind(input); wanakana.unbind(input);
} }
}
this._queryInputEvents.addEventListener(input, 'input', this._onSearchInput.bind(this), false); this._queryInputEvents.addEventListener(input, 'input', this._onSearchInput.bind(this), false);
this._queryInputEventsSetup = true;
} }
_setIntroVisible(visible, animate) { _setIntroVisible(visible, animate) {
@ -306,12 +292,12 @@ class DisplaySearch extends Display {
path: 'clipboard.enableSearchPageMonitor', path: 'clipboard.enableSearchPageMonitor',
value, value,
scope: 'profile', scope: 'profile',
optionsContext: this.getOptionsContext() optionsContext: this._display.getOptionsContext()
}], 'search'); }], 'search');
} }
_updateClipboardMonitorEnabled() { _updateClipboardMonitorEnabled() {
const mode = this.mode; const mode = this._display.mode;
const enabled = this._clipboardMonitorEnabled; const enabled = this._clipboardMonitorEnabled;
this._clipboardMonitorEnableCheckbox.checked = enabled; this._clipboardMonitorEnableCheckbox.checked = enabled;
if (enabled && mode !== 'popup') { if (enabled && mode !== 'popup') {
@ -335,7 +321,7 @@ class DisplaySearch extends Display {
_search(animate, history, lookup) { _search(animate, history, lookup) {
const query = this._queryInput.value; const query = this._queryInput.value;
const depth = this.depth; const depth = this._display.depth;
const url = window.location.href; const url = window.location.href;
const documentTitle = document.title; const documentTitle = document.title;
const details = { const details = {
@ -361,7 +347,7 @@ class DisplaySearch extends Display {
} }
}; };
if (!lookup) { details.params.lookup = 'false'; } if (!lookup) { details.params.lookup = 'false'; }
this.setContent(details); this._display.setContent(details);
} }
_updateSearchHeight(shrink) { _updateSearchHeight(shrink) {
@ -375,4 +361,15 @@ class DisplaySearch extends Display {
node.style.height = `${scrollHeight}px`; node.style.height = `${scrollHeight}px`;
} }
} }
_postProcessQuery(query) {
if (this._wanakanaEnabled) {
try {
query = this._japaneseUtil.convertToKana(query);
} catch (e) {
// NOP
}
}
return query;
}
} }

View File

@ -16,10 +16,11 @@
*/ */
/* global /* global
* DisplaySearch * Display
* DocumentFocusController * DocumentFocusController
* HotkeyHandler * HotkeyHandler
* JapaneseUtil * JapaneseUtil
* SearchDisplayController
* api * api
* wanakana * wanakana
*/ */
@ -39,10 +40,16 @@
const hotkeyHandler = new HotkeyHandler(); const hotkeyHandler = new HotkeyHandler();
hotkeyHandler.prepare(); hotkeyHandler.prepare();
const displaySearch = new DisplaySearch(tabId, frameId, japaneseUtil, documentFocusController, hotkeyHandler); const display = new Display(tabId, frameId, 'search', japaneseUtil, documentFocusController, hotkeyHandler);
await displaySearch.prepare(); await display.prepare();
const searchDisplayController = new SearchDisplayController(tabId, frameId, display, japaneseUtil);
await searchDisplayController.prepare();
display.initializeState();
document.documentElement.dataset.loaded = 'true'; document.documentElement.dataset.loaded = 'true';
yomichan.ready(); yomichan.ready();
} catch (e) { } catch (e) {
yomichan.logError(e); yomichan.logError(e);

View File

@ -109,7 +109,7 @@
<script src="/bg/js/query-parser.js"></script> <script src="/bg/js/query-parser.js"></script>
<script src="/bg/js/clipboard-monitor.js"></script> <script src="/bg/js/clipboard-monitor.js"></script>
<script src="/bg/js/search.js"></script> <script src="/bg/js/search-display-controller.js"></script>
<script src="/bg/js/search-main.js"></script> <script src="/bg/js/search-main.js"></script>

View File

@ -41,10 +41,14 @@
const display = new Display(tabId, frameId, 'popup', japaneseUtil, documentFocusController, hotkeyHandler); const display = new Display(tabId, frameId, 'popup', japaneseUtil, documentFocusController, hotkeyHandler);
await display.prepare(); await display.prepare();
const displayProfileSelection = new DisplayProfileSelection(display); const displayProfileSelection = new DisplayProfileSelection(display);
displayProfileSelection.prepare(); displayProfileSelection.prepare();
display.initializeState(); display.initializeState();
document.documentElement.dataset.loaded = 'true';
yomichan.ready(); yomichan.ready();
} catch (e) { } catch (e) {
yomichan.logError(e); yomichan.logError(e);

View File

@ -117,6 +117,7 @@ class Display extends EventDispatcher {
this._displayAudio = new DisplayAudio(this); this._displayAudio = new DisplayAudio(this);
this._ankiNoteNotification = null; this._ankiNoteNotification = null;
this._ankiNoteNotificationEventListeners = null; this._ankiNoteNotificationEventListeners = null;
this._queryPostProcessor = null;
this._hotkeyHandler.registerActions([ this._hotkeyHandler.registerActions([
['close', () => { this._onHotkeyClose(); }], ['close', () => { this._onHotkeyClose(); }],
@ -405,8 +406,8 @@ class Display extends EventDispatcher {
return data.data; return data.data;
} }
postProcessQuery(query) { setQueryPostProcessor(func) {
return query; this._queryPostProcessor = func;
} }
close() { close() {
@ -573,10 +574,10 @@ class Display extends EventDispatcher {
this._query = query; this._query = query;
clear = false; clear = false;
const isTerms = (type === 'terms'); const isTerms = (type === 'terms');
query = this.postProcessQuery(query); query = this._postProcessQuery(query);
this._rawQuery = query; this._rawQuery = query;
let queryFull = urlSearchParams.get('full'); let queryFull = urlSearchParams.get('full');
queryFull = (queryFull !== null ? this.postProcessQuery(queryFull) : query); queryFull = (queryFull !== null ? this._postProcessQuery(queryFull) : query);
const wildcardsEnabled = (urlSearchParams.get('wildcards') !== 'off'); const wildcardsEnabled = (urlSearchParams.get('wildcards') !== 'off');
const lookup = (urlSearchParams.get('lookup') !== 'false'); const lookup = (urlSearchParams.get('lookup') !== 'false');
await this._setContentTermsOrKanji(token, isTerms, query, queryFull, lookup, wildcardsEnabled, eventArgs); await this._setContentTermsOrKanji(token, isTerms, query, queryFull, lookup, wildcardsEnabled, eventArgs);
@ -1930,4 +1931,9 @@ class Display extends EventDispatcher {
} }
return false; return false;
} }
_postProcessQuery(query) {
const queryPostProcessor = this._queryPostProcessor;
return typeof queryPostProcessor === 'function' ? queryPostProcessor(query) : query;
}
} }