From 1c5e3e6d397f22de99494e147cc53b106e1d16b4 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Thu, 11 Feb 2021 22:57:38 -0500 Subject: [PATCH] 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 --- ...search.js => search-display-controller.js} | 113 +++++++++--------- ext/bg/js/search-main.js | 13 +- ext/bg/search.html | 2 +- ext/fg/js/float-main.js | 4 + ext/mixed/js/display.js | 14 ++- 5 files changed, 80 insertions(+), 66 deletions(-) rename ext/bg/js/{search.js => search-display-controller.js} (84%) diff --git a/ext/bg/js/search.js b/ext/bg/js/search-display-controller.js similarity index 84% rename from ext/bg/js/search.js rename to ext/bg/js/search-display-controller.js index a786b0bf..b8ad2d52 100644 --- a/ext/bg/js/search.js +++ b/ext/bg/js/search-display-controller.js @@ -17,22 +17,23 @@ /* global * ClipboardMonitor - * Display * api * wanakana */ -class DisplaySearch extends Display { - constructor(tabId, frameId, japaneseUtil, documentFocusController, hotkeyHandler) { - super(tabId, frameId, 'search', japaneseUtil, documentFocusController, hotkeyHandler); +class SearchDisplayController { + constructor(tabId, frameId, display, japaneseUtil) { + this._tabId = tabId; + this._frameId = frameId; + this._display = display; this._searchButton = document.querySelector('#search-button'); this._queryInput = document.querySelector('#search-textbox'); this._introElement = document.querySelector('#intro'); this._clipboardMonitorEnableCheckbox = document.querySelector('#clipboard-monitor-enable'); this._wanakanaEnableCheckbox = document.querySelector('#wanakana-enable'); this._queryInputEvents = new EventListenerCollection(); + this._queryInputEventsSetup = false; this._wanakanaEnabled = false; - this._isPrepared = false; this._introVisible = true; this._introAnimationTimer = null; this._clipboardMonitorEnabled = false; @@ -42,57 +43,38 @@ class DisplaySearch extends Display { getText: async () => (await api.clipboardGet()) } }); - this.autoPlayAudioDelay = 0; - - this.hotkeyHandler.registerActions([ - ['focusSearchBox', this._onActionFocusSearchBox.bind(this)] - ]); } async prepare() { - await super.prepare(); - await this.updateOptions(); + await this._display.updateOptions(); + yomichan.on('optionsUpdated', this._onOptionsUpdated.bind(this)); - this.on('optionsUpdated', this._onDisplayOptionsUpdated.bind(this)); - this.on('contentUpdating', this._onContentUpdating.bind(this)); - this.on('modeChange', this._onModeChange.bind(this)); + this._display.on('optionsUpdated', this._onDisplayOptionsUpdated.bind(this)); + this._display.on('contentUpdating', this._onContentUpdating.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)}] ]); - this.queryParserVisible = true; - this.setHistorySettings({useBrowserHistory: true}); - - const enableWanakana = !!this.getOptions().general.enableWanakana; - this._wanakanaEnableCheckbox.checked = enableWanakana; - this._setWanakanaEnabled(enableWanakana); + this._display.autoPlayAudioDelay = 0; + this._display.queryParserVisible = true; + this._display.setHistorySettings({useBrowserHistory: true}); + this._display.setQueryPostProcessor(this._postProcessQuery.bind(this)); this._searchButton.addEventListener('click', this._onSearch.bind(this), false); this._wanakanaEnableCheckbox.addEventListener('change', this._onWanakanaEnableChange.bind(this)); window.addEventListener('copy', this._onCopy.bind(this)); this._clipboardMonitor.on('change', this._onExternalSearchUpdate.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._onDisplayOptionsUpdated({options: this.getOptions()}); - - this.initializeState(); - - this._isPrepared = true; - } - - postProcessQuery(query) { - if (this._wanakanaEnabled) { - try { - query = this._japaneseUtil.convertToKana(query); - } catch (e) { - // NOP - } - } - return query; + this._onDisplayOptionsUpdated({options: this._display.getOptions()}); } // Actions @@ -118,16 +100,20 @@ class DisplaySearch extends Display { } async _onOptionsUpdated() { - await this.updateOptions(); + await this._display.updateOptions(); const query = this._queryInput.value; if (query) { - this.searchLast(); + this._display.searchLast(); } } _onDisplayOptionsUpdated({options}) { this._clipboardMonitorEnabled = options.clipboard.enableSearchPageMonitor; this._updateClipboardMonitorEnabled(); + + const enableWanakana = !!this._display.getOptions().general.enableWanakana; + this._wanakanaEnableCheckbox.checked = enableWanakana; + this._setWanakanaEnabled(enableWanakana); } _onContentUpdating({type, content, source}) { @@ -138,7 +124,7 @@ class DisplaySearch extends Display { case 'kanji': animate = !!content.animate; valid = (typeof source === 'string' && source.length > 0); - this.blurElement(this._queryInput); + this._display.blurElement(this._queryInput); break; case 'clear': valid = false; @@ -167,7 +153,7 @@ class DisplaySearch extends Display { // Search e.preventDefault(); e.stopImmediatePropagation(); - this.blurElement(e.currentTarget); + this._display.blurElement(e.currentTarget); this._search(true, true, true); } @@ -182,7 +168,7 @@ class DisplaySearch extends Display { } _onExternalSearchUpdate({text, animate=true}) { - const {clipboard: {autoSearchContent, maximumSearchLength}} = this.getOptions(); + const {clipboard: {autoSearchContent, maximumSearchLength}} = this._display.getOptions(); if (text.length > maximumSearchLength) { text = text.substring(0, maximumSearchLength); } @@ -199,7 +185,7 @@ class DisplaySearch extends Display { path: 'general.enableWanakana', value, scope: 'profile', - optionsContext: this.getOptionsContext() + optionsContext: this._display.getOptionsContext() }], 'search'); } @@ -209,28 +195,28 @@ class DisplaySearch extends Display { } _onModeChange() { - let mode = this.mode; + let mode = this._display.mode; if (mode === null) { mode = ''; } document.documentElement.dataset.searchMode = mode; this._updateClipboardMonitorEnabled(); } _setWanakanaEnabled(enabled) { + if (this._queryInputEventsSetup && this._wanakanaEnabled === enabled) { return; } + const input = this._queryInput; this._queryInputEvents.removeAllEventListeners(); - this._queryInputEvents.addEventListener(input, 'keydown', this._onSearchKeydown.bind(this), false); - if (this._wanakanaEnabled !== enabled) { - this._wanakanaEnabled = enabled; - if (enabled) { - wanakana.bind(input); - } else { - wanakana.unbind(input); - } + this._wanakanaEnabled = enabled; + if (enabled) { + wanakana.bind(input); + } else { + wanakana.unbind(input); } this._queryInputEvents.addEventListener(input, 'input', this._onSearchInput.bind(this), false); + this._queryInputEventsSetup = true; } _setIntroVisible(visible, animate) { @@ -306,12 +292,12 @@ class DisplaySearch extends Display { path: 'clipboard.enableSearchPageMonitor', value, scope: 'profile', - optionsContext: this.getOptionsContext() + optionsContext: this._display.getOptionsContext() }], 'search'); } _updateClipboardMonitorEnabled() { - const mode = this.mode; + const mode = this._display.mode; const enabled = this._clipboardMonitorEnabled; this._clipboardMonitorEnableCheckbox.checked = enabled; if (enabled && mode !== 'popup') { @@ -335,7 +321,7 @@ class DisplaySearch extends Display { _search(animate, history, lookup) { const query = this._queryInput.value; - const depth = this.depth; + const depth = this._display.depth; const url = window.location.href; const documentTitle = document.title; const details = { @@ -361,7 +347,7 @@ class DisplaySearch extends Display { } }; if (!lookup) { details.params.lookup = 'false'; } - this.setContent(details); + this._display.setContent(details); } _updateSearchHeight(shrink) { @@ -375,4 +361,15 @@ class DisplaySearch extends Display { node.style.height = `${scrollHeight}px`; } } + + _postProcessQuery(query) { + if (this._wanakanaEnabled) { + try { + query = this._japaneseUtil.convertToKana(query); + } catch (e) { + // NOP + } + } + return query; + } } diff --git a/ext/bg/js/search-main.js b/ext/bg/js/search-main.js index f6abdfc8..c7ec595a 100644 --- a/ext/bg/js/search-main.js +++ b/ext/bg/js/search-main.js @@ -16,10 +16,11 @@ */ /* global - * DisplaySearch + * Display * DocumentFocusController * HotkeyHandler * JapaneseUtil + * SearchDisplayController * api * wanakana */ @@ -39,10 +40,16 @@ const hotkeyHandler = new HotkeyHandler(); hotkeyHandler.prepare(); - const displaySearch = new DisplaySearch(tabId, frameId, japaneseUtil, documentFocusController, hotkeyHandler); - await displaySearch.prepare(); + const display = new Display(tabId, frameId, 'search', japaneseUtil, documentFocusController, hotkeyHandler); + await display.prepare(); + + const searchDisplayController = new SearchDisplayController(tabId, frameId, display, japaneseUtil); + await searchDisplayController.prepare(); + + display.initializeState(); document.documentElement.dataset.loaded = 'true'; + yomichan.ready(); } catch (e) { yomichan.logError(e); diff --git a/ext/bg/search.html b/ext/bg/search.html index 40c1ef45..e5690c8d 100644 --- a/ext/bg/search.html +++ b/ext/bg/search.html @@ -109,7 +109,7 @@ - + diff --git a/ext/fg/js/float-main.js b/ext/fg/js/float-main.js index efc012d7..7c048b62 100644 --- a/ext/fg/js/float-main.js +++ b/ext/fg/js/float-main.js @@ -41,10 +41,14 @@ const display = new Display(tabId, frameId, 'popup', japaneseUtil, documentFocusController, hotkeyHandler); await display.prepare(); + const displayProfileSelection = new DisplayProfileSelection(display); displayProfileSelection.prepare(); + display.initializeState(); + document.documentElement.dataset.loaded = 'true'; + yomichan.ready(); } catch (e) { yomichan.logError(e); diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index c8b7b14b..2acc0d3f 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -117,6 +117,7 @@ class Display extends EventDispatcher { this._displayAudio = new DisplayAudio(this); this._ankiNoteNotification = null; this._ankiNoteNotificationEventListeners = null; + this._queryPostProcessor = null; this._hotkeyHandler.registerActions([ ['close', () => { this._onHotkeyClose(); }], @@ -405,8 +406,8 @@ class Display extends EventDispatcher { return data.data; } - postProcessQuery(query) { - return query; + setQueryPostProcessor(func) { + this._queryPostProcessor = func; } close() { @@ -573,10 +574,10 @@ class Display extends EventDispatcher { this._query = query; clear = false; const isTerms = (type === 'terms'); - query = this.postProcessQuery(query); + query = this._postProcessQuery(query); this._rawQuery = query; 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 lookup = (urlSearchParams.get('lookup') !== 'false'); await this._setContentTermsOrKanji(token, isTerms, query, queryFull, lookup, wildcardsEnabled, eventArgs); @@ -1930,4 +1931,9 @@ class Display extends EventDispatcher { } return false; } + + _postProcessQuery(query) { + const queryPostProcessor = this._queryPostProcessor; + return typeof queryPostProcessor === 'function' ? queryPostProcessor(query) : query; + } }