From be8ef53e90c3893dc2696b846dadb185be8c4514 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 3 Oct 2021 16:46:15 -0400 Subject: [PATCH] Display refactoring (#1978) * Refactor _setContentTermsOrKanji * Update query assignment * Simplify * Remove redundant _updateQueryParser * Reorder query assignment * Remove isTerms, replace with isKanji * Simplify defaults * Refactor events * Update DisplayAnki to use events * Simplify * Update DisplayAudio to use events * Simplify * Move audio hotkeys * Add frameVisibilityChange event * Fix name * Add logDictionaryEntryData event * Move clearAutoPlayTimer handler * Fix call * Externalize DisplayAnki and DisplayAudio from Display * Simplify clear --- ext/js/display/display-anki.js | 58 +++--- ext/js/display/display-audio.js | 108 +++++++---- ext/js/display/display.js | 199 +++++++------------- ext/js/display/popup-main.js | 8 + ext/js/display/search-display-controller.js | 19 +- ext/js/display/search-main.js | 10 +- 6 files changed, 203 insertions(+), 199 deletions(-) diff --git a/ext/js/display/display-anki.js b/ext/js/display/display-anki.js index 216e3108..46e88ae0 100644 --- a/ext/js/display/display-anki.js +++ b/ext/js/display/display-anki.js @@ -23,8 +23,9 @@ */ class DisplayAnki { - constructor(display, japaneseUtil) { + constructor(display, displayAudio, japaneseUtil) { this._display = display; + this._displayAudio = displayAudio; this._ankiFieldTemplates = null; this._ankiFieldTemplatesDefault = null; this._ankiNoteBuilder = new AnkiNoteBuilder({japaneseUtil}); @@ -70,28 +71,11 @@ class DisplayAnki { ['viewNote', this._viewNoteForSelectedEntry.bind(this)] ]); this._display.on('optionsUpdated', this._onOptionsUpdated.bind(this)); - } - - cleanupEntries() { - this._updateDictionaryEntryDetailsToken = null; - this._dictionaryEntryDetails = null; - this._hideAnkiNoteErrors(false); - } - - setupEntriesBegin() { - this._noteContext = this._getNoteContext(); - } - - setupEntry(entry) { - this._addMultipleEventListeners(entry, '.action-view-tags', 'click', this._onShowTagsBind); - this._addMultipleEventListeners(entry, '.action-add-note', 'click', this._onNoteAddBind); - this._addMultipleEventListeners(entry, '.action-view-note', 'click', this._onViewNoteButtonClickBind); - this._addMultipleEventListeners(entry, '.action-view-note', 'contextmenu', this._onViewNoteButtonContextMenuBind); - this._addMultipleEventListeners(entry, '.action-view-note', 'menuClose', this._onViewNoteButtonMenuCloseBind); - } - - setupEntriesComplete() { - this._updateDictionaryEntryDetails(); + this._display.on('contentClear', this._onContentClear.bind(this)); + this._display.on('contentUpdateStart', this._onContentUpdateStart.bind(this)); + this._display.on('contentUpdateEntry', this._onContentUpdateEntry.bind(this)); + this._display.on('contentUpdateComplete', this._onContentUpdateComplete.bind(this)); + this._display.on('logDictionaryEntryData', this._onLogDictionaryEntryData.bind(this)); } async getLogData(dictionaryEntry) { @@ -173,6 +157,32 @@ class DisplayAnki { this._updateAnkiFieldTemplates(options); } + _onContentClear() { + this._updateDictionaryEntryDetailsToken = null; + this._dictionaryEntryDetails = null; + this._hideAnkiNoteErrors(false); + } + + _onContentUpdateStart() { + this._noteContext = this._getNoteContext(); + } + + _onContentUpdateEntry({element}) { + this._addMultipleEventListeners(element, '.action-view-tags', 'click', this._onShowTagsBind); + this._addMultipleEventListeners(element, '.action-add-note', 'click', this._onNoteAddBind); + this._addMultipleEventListeners(element, '.action-view-note', 'click', this._onViewNoteButtonClickBind); + this._addMultipleEventListeners(element, '.action-view-note', 'contextmenu', this._onViewNoteButtonContextMenuBind); + this._addMultipleEventListeners(element, '.action-view-note', 'menuClose', this._onViewNoteButtonMenuCloseBind); + } + + _onContentUpdateComplete() { + this._updateDictionaryEntryDetails(); + } + + _onLogDictionaryEntryData({dictionaryEntry, promises}) { + promises.push(this.getLogData(dictionaryEntry)); + } + _onNoteAdd(e) { e.preventDefault(); const node = e.currentTarget; @@ -526,7 +536,7 @@ class DisplayAnki { const fields = Object.entries(modeOptions.fields); const contentOrigin = this._display.getContentOrigin(); const details = this._ankiNoteBuilder.getDictionaryEntryDetailsForNote(dictionaryEntry); - const audioDetails = (details.type === 'term' ? this._display.getAnkiNoteMediaAudioDetails(details.term, details.reading) : null); + const audioDetails = (details.type === 'term' ? this._displayAudio.getAnkiNoteMediaAudioDetails(details.term, details.reading) : null); const optionsContext = this._display.getOptionsContext(); const {note, errors, requirements: outputRequirements} = await this._ankiNoteBuilder.createNote({ diff --git a/ext/js/display/display-audio.js b/ext/js/display/display-audio.js index 3a6b7a50..0bc95abb 100644 --- a/ext/js/display/display-audio.js +++ b/ext/js/display/display-audio.js @@ -56,49 +56,21 @@ class DisplayAudio { prepare() { this._audioSystem.prepare(); + this._display.hotkeyHandler.registerActions([ + ['playAudio', this._onHotkeyActionPlayAudio.bind(this)], + ['playAudioFromSource', this._onHotkeyActionPlayAudioFromSource.bind(this)] + ]); + this._display.registerDirectMessageHandlers([ + ['clearAutoPlayTimer', {async: false, handler: this._onMessageClearAutoPlayTimer.bind(this)}] + ]); this._display.on('optionsUpdated', this._onOptionsUpdated.bind(this)); + this._display.on('contentClear', this._onContentClear.bind(this)); + this._display.on('contentUpdateEntry', this._onContentUpdateEntry.bind(this)); + this._display.on('contentUpdateComplete', this._onContentUpdateComplete.bind(this)); + this._display.on('frameVisibilityChange', this._onFrameVisibilityChange.bind(this)); this._onOptionsUpdated({options: this._display.getOptions()}); } - cleanupEntries() { - this._entriesToken = {}; - this._cache.clear(); - this.clearAutoPlayTimer(); - this._eventListeners.removeAllEventListeners(); - } - - setupEntry(entry, dictionaryEntryIndex) { - for (const button of entry.querySelectorAll('.action-play-audio')) { - const headwordIndex = this._getAudioPlayButtonHeadwordIndex(button); - this._eventListeners.addEventListener(button, 'click', this._onAudioPlayButtonClick.bind(this, dictionaryEntryIndex, headwordIndex), false); - this._eventListeners.addEventListener(button, 'contextmenu', this._onAudioPlayButtonContextMenu.bind(this, dictionaryEntryIndex, headwordIndex), false); - this._eventListeners.addEventListener(button, 'menuClose', this._onAudioPlayMenuCloseClick.bind(this, dictionaryEntryIndex, headwordIndex), false); - } - } - - setupEntriesComplete() { - if (!this._autoPlay || !this._display.frameVisible) { return; } - - this.clearAutoPlayTimer(); - - const {dictionaryEntries} = this._display; - if (dictionaryEntries.length === 0) { return; } - - const firstDictionaryEntries = dictionaryEntries[0]; - if (firstDictionaryEntries.type === 'kanji') { return; } - - const callback = () => { - this._autoPlayAudioTimer = null; - this.playAudio(0, 0); - }; - - if (this._autoPlayAudioDelay > 0) { - this._autoPlayAudioTimer = setTimeout(callback, this._autoPlayAudioDelay); - } else { - callback(); - } - } - clearAutoPlayTimer() { if (this._autoPlayAudioTimer === null) { return; } clearTimeout(this._autoPlayAudioTimer); @@ -171,6 +143,64 @@ class DisplayAudio { this._cache.clear(); } + _onContentClear() { + this._entriesToken = {}; + this._cache.clear(); + this.clearAutoPlayTimer(); + this._eventListeners.removeAllEventListeners(); + } + + _onContentUpdateEntry({element, index}) { + for (const button of element.querySelectorAll('.action-play-audio')) { + const headwordIndex = this._getAudioPlayButtonHeadwordIndex(button); + this._eventListeners.addEventListener(button, 'click', this._onAudioPlayButtonClick.bind(this, index, headwordIndex), false); + this._eventListeners.addEventListener(button, 'contextmenu', this._onAudioPlayButtonContextMenu.bind(this, index, headwordIndex), false); + this._eventListeners.addEventListener(button, 'menuClose', this._onAudioPlayMenuCloseClick.bind(this, index, headwordIndex), false); + } + } + + _onContentUpdateComplete() { + if (!this._autoPlay || !this._display.frameVisible) { return; } + + this.clearAutoPlayTimer(); + + const {dictionaryEntries} = this._display; + if (dictionaryEntries.length === 0) { return; } + + const firstDictionaryEntries = dictionaryEntries[0]; + if (firstDictionaryEntries.type === 'kanji') { return; } + + const callback = () => { + this._autoPlayAudioTimer = null; + this.playAudio(0, 0); + }; + + if (this._autoPlayAudioDelay > 0) { + this._autoPlayAudioTimer = setTimeout(callback, this._autoPlayAudioDelay); + } else { + callback(); + } + } + + _onFrameVisibilityChange({value}) { + if (!value) { + this.clearAutoPlayTimer(); + this.stopAudio(); + } + } + + _onHotkeyActionPlayAudio() { + this.playAudio(this._display.selectedIndex, 0); + } + + _onHotkeyActionPlayAudioFromSource(source) { + this.playAudio(this._display.selectedIndex, 0, source); + } + + _onMessageClearAutoPlayTimer() { + this.clearAutoPlayTimer(); + } + _addAudioSourceInfo(type, url, voice, isInOptions, nameMap) { const index = this._audioSources.length; const downloadable = this._sourceIsDownloadable(type); diff --git a/ext/js/display/display.js b/ext/js/display/display.js index 5e35a9de..ed1af17e 100644 --- a/ext/js/display/display.js +++ b/ext/js/display/display.js @@ -16,8 +16,6 @@ */ /* global - * DisplayAnki - * DisplayAudio * DisplayGenerator * DisplayHistory * DisplayNotification @@ -106,10 +104,8 @@ class Display extends EventDispatcher { this._contentTextScanner = null; this._tagNotification = null; this._footerNotificationContainer = document.querySelector('#content-footer'); - this._displayAudio = new DisplayAudio(this); this._optionToggleHotkeyHandler = new OptionToggleHotkeyHandler(this); this._elementOverflowController = new ElementOverflowController(); - this._displayAnki = new DisplayAnki(this, japaneseUtil); this._frameVisible = (pageType === 'search'); this._hotkeyHandler.registerActions([ @@ -120,8 +116,6 @@ class Display extends EventDispatcher { ['firstEntry', () => { this._focusEntry(0, 0, true); }], ['historyBackward', () => { this._sourceTermView(); }], ['historyForward', () => { this._nextTermView(); }], - ['playAudio', () => { this._playAudioCurrent(); }], - ['playAudioFromSource', this._onHotkeyActionPlayAudioFromSource.bind(this)], ['copyHostSelection', () => this._copyHostSelection()], ['nextEntryDifferentDictionary', () => { this._focusEntryWithDifferentDictionary(1, true); }], ['previousEntryDifferentDictionary', () => { this._focusEntryWithDifferentDictionary(-1, true); }] @@ -129,7 +123,6 @@ class Display extends EventDispatcher { this.registerDirectMessageHandlers([ ['setOptionsContext', {async: false, handler: this._onMessageSetOptionsContext.bind(this)}], ['setContent', {async: false, handler: this._onMessageSetContent.bind(this)}], - ['clearAutoPlayTimer', {async: false, handler: this._onMessageClearAutoPlayTimer.bind(this)}], ['setCustomCss', {async: false, handler: this._onMessageSetCustomCss.bind(this)}], ['setContentScale', {async: false, handler: this._onMessageSetContentScale.bind(this)}], ['configure', {async: true, handler: this._onMessageConfigure.bind(this)}], @@ -144,14 +137,6 @@ class Display extends EventDispatcher { return this._displayGenerator; } - get autoPlayAudioDelay() { - return this._displayAudio.autoPlayAudioDelay; - } - - set autoPlayAudioDelay(value) { - this._displayAudio.autoPlayAudioDelay = value; - } - get queryParserVisible() { return this._queryParserVisible; } @@ -230,8 +215,6 @@ class Display extends EventDispatcher { // Prepare await this._hotkeyHelpController.prepare(); await this._displayGenerator.prepare(); - this._displayAudio.prepare(); - this._displayAnki.prepare(); this._queryParser.prepare(); this._history.prepare(); this._optionToggleHotkeyHandler.prepare(); @@ -345,10 +328,6 @@ class Display extends EventDispatcher { this.trigger('optionsUpdated', {options}); } - clearAutoPlayTimer() { - this._displayAudio.clearAutoPlayTimer(); - } - setContent(details) { const {focus, params, state, content} = details; const historyMode = this._historyHasChanged ? details.historyMode : 'clear'; @@ -468,10 +447,6 @@ class Display extends EventDispatcher { return Number.isFinite(index) ? index : -1; } - getAnkiNoteMediaAudioDetails(term, reading) { - return this._displayAudio.getAnkiNoteMediaAudioDetails(term, reading); - } - // Message handlers _onDirectMessage(data) { @@ -511,10 +486,6 @@ class Display extends EventDispatcher { this.setContent(details); } - _onMessageClearAutoPlayTimer() { - this.clearAutoPlayTimer(); - } - _onMessageSetCustomCss({css}) { this.setCustomCss(css); } @@ -534,10 +505,7 @@ class Display extends EventDispatcher { _onMessageVisibilityChanged({value}) { this._frameVisible = value; - if (!value) { - this._displayAudio.clearAutoPlayTimer(); - this._displayAudio.stopAudio(); - } + this.trigger('frameVisibilityChange', {value}); } _onMessageExtensionUnloaded() { @@ -568,9 +536,8 @@ class Display extends EventDispatcher { this._closeAllPopupMenus(); this._eventListeners.removeAllEventListeners(); this._mediaLoader.unloadAll(); - this._displayAudio.cleanupEntries(); - this._displayAnki.cleanupEntries(); this._hideTagNotification(false); + this._triggerContentClear(); this._dictionaryEntries = []; this._dictionaryEntryNodes = []; this._elementOverflowController.clearElements(); @@ -582,62 +549,25 @@ class Display extends EventDispatcher { const fullVisible = urlSearchParams.get('full-visible'); this._queryParserVisibleOverride = (fullVisible === null ? null : (fullVisible !== 'false')); - this._updateQueryParser(); - let clear = true; this._historyHasChanged = true; this._contentType = type; - this._query = ''; - const eventArgs = {type, urlSearchParams, token}; // Set content switch (type) { case 'terms': case 'kanji': - { - const query = urlSearchParams.get('query'); - if (query === null) { break; } - - this._query = query; - clear = false; - const isTerms = (type === 'terms'); - let queryFull = urlSearchParams.get('full'); - queryFull = (queryFull !== null ? queryFull : query); - let queryOffset = urlSearchParams.get('offset'); - if (queryOffset !== null) { - queryOffset = Number.parseInt(queryOffset, 10); - if (!Number.isFinite(queryOffset)) { queryOffset = null; } - } - const wildcardsEnabled = (urlSearchParams.get('wildcards') !== 'off'); - const lookup = (urlSearchParams.get('lookup') !== 'false'); - await this._setContentTermsOrKanji(token, isTerms, query, queryFull, queryOffset, lookup, wildcardsEnabled, eventArgs); - } + await this._setContentTermsOrKanji(type, urlSearchParams, token); break; case 'unloaded': - { - clear = false; - const {content} = this._history; - eventArgs.content = content; - this.trigger('contentUpdating', eventArgs); - this._setContentExtensionUnloaded(); - } + this._setContentExtensionUnloaded(); + break; + default: + type = 'clear'; + this._contentType = type; + this._clearContent(); break; } - - // Clear - if (clear) { - type = 'clear'; - this._contentType = type; - const {content} = this._history; - eventArgs.type = type; - eventArgs.content = content; - this.trigger('contentUpdating', eventArgs); - this._clearContent(); - } - - const stale = (this._setContentToken !== token); - eventArgs.stale = stale; - this.trigger('contentUpdated', eventArgs); } catch (e) { this.onError(e); } @@ -874,8 +804,11 @@ class Display extends EventDispatcher { document.documentElement.dataset.theme = themeName; } - async _findDictionaryEntries(isTerms, source, wildcardsEnabled, optionsContext) { - if (isTerms) { + async _findDictionaryEntries(isKanji, source, wildcardsEnabled, optionsContext) { + if (isKanji) { + const dictionaryEntries = await yomichan.api.kanjiFind(source, optionsContext); + return dictionaryEntries; + } else { const findDetails = {}; if (wildcardsEnabled) { const match = /^([*\uff0a]*)([\w\W]*?)([*\uff0a]*)$/.exec(source); @@ -891,13 +824,24 @@ class Display extends EventDispatcher { const {dictionaryEntries} = await yomichan.api.termsFind(source, findDetails, optionsContext); return dictionaryEntries; - } else { - const dictionaryEntries = await yomichan.api.kanjiFind(source, optionsContext); - return dictionaryEntries; } } - async _setContentTermsOrKanji(token, isTerms, query, queryFull, queryOffset, lookup, wildcardsEnabled, eventArgs) { + async _setContentTermsOrKanji(type, urlSearchParams, token) { + const lookup = (urlSearchParams.get('lookup') !== 'false'); + const wildcardsEnabled = (urlSearchParams.get('wildcards') !== 'off'); + + // Set query + const query = urlSearchParams.get('query'); + let queryFull = urlSearchParams.get('full'); + queryFull = (queryFull !== null ? queryFull : query); + let queryOffset = urlSearchParams.get('offset'); + if (queryOffset !== null) { + queryOffset = Number.parseInt(queryOffset, 10); + queryOffset = Number.isFinite(queryOffset) ? Math.max(0, Math.min(queryFull.length - query.length, queryOffset)) : null; + } + this._setQuery(query, queryFull, queryOffset); + let {state, content} = this._history; let changeHistory = false; if (!isObject(content)) { @@ -909,12 +853,7 @@ class Display extends EventDispatcher { changeHistory = true; } - let { - focusEntry=null, - scrollX=null, - scrollY=null, - optionsContext=null - } = state; + let {focusEntry, scrollX, scrollY, optionsContext} = state; if (typeof focusEntry !== 'number') { focusEntry = 0; } if (!(typeof optionsContext === 'object' && optionsContext !== null)) { optionsContext = this.getOptionsContext(); @@ -922,16 +861,9 @@ class Display extends EventDispatcher { changeHistory = true; } - if (queryOffset !== null) { - queryOffset = Math.max(0, Math.min(queryFull.length - query.length, queryOffset)); - } - - this._setFullQuery(queryFull, queryOffset); - this._setTitleText(query); - let {dictionaryEntries} = content; if (!Array.isArray(dictionaryEntries)) { - dictionaryEntries = lookup && query.length > 0 ? await this._findDictionaryEntries(isTerms, query, wildcardsEnabled, optionsContext) : []; + dictionaryEntries = lookup && query.length > 0 ? await this._findDictionaryEntries(type === 'kanji', query, wildcardsEnabled, optionsContext) : []; if (this._setContentToken !== token) { return; } content.dictionaryEntries = dictionaryEntries; changeHistory = true; @@ -964,10 +896,6 @@ class Display extends EventDispatcher { this._replaceHistoryStateNoNavigate(state, content); } - eventArgs.source = query; - eventArgs.content = content; - this.trigger('contentUpdating', eventArgs); - this._dictionaryEntries = dictionaryEntries; this._updateNavigation(this._history.hasPrevious(), this._history.hasNext()); @@ -976,7 +904,7 @@ class Display extends EventDispatcher { const container = this._container; container.textContent = ''; - this._displayAnki.setupEntriesBegin(); + this._triggerContentUpdateStart(); for (let i = 0, ii = dictionaryEntries.length; i < ii; ++i) { if (i > 0) { @@ -986,15 +914,14 @@ class Display extends EventDispatcher { const dictionaryEntry = dictionaryEntries[i]; const entry = ( - isTerms ? + dictionaryEntry.type === 'term' ? this._displayGenerator.createTermEntry(dictionaryEntry) : this._displayGenerator.createKanjiEntry(dictionaryEntry) ); entry.dataset.index = `${i}`; this._dictionaryEntryNodes.push(entry); this._addEntryEventListeners(entry); - this._displayAudio.setupEntry(entry, i); - this._displayAnki.setupEntry(entry, i); + this._triggerContentUpdateEntry(dictionaryEntry, entry, i); container.appendChild(entry); if (focusEntry === i) { this._focusEntry(i, 0, false); @@ -1011,8 +938,7 @@ class Display extends EventDispatcher { this._windowScroll.to(x, y); } - this._displayAudio.setupEntriesComplete(); - this._displayAnki.setupEntriesComplete(); + this._triggerContentUpdateComplete(); } _setContentExtensionUnloaded() { @@ -1028,14 +954,18 @@ class Display extends EventDispatcher { this._updateNavigation(false, false); this._setNoContentVisible(false); - this._setTitleText(''); - this._setFullQuery('', 0); + this._setQuery('', '', 0); + + this._triggerContentUpdateStart(); + this._triggerContentUpdateComplete(); } _clearContent() { this._container.textContent = ''; - this._setTitleText(''); - this._setFullQuery('', 0); + this._setQuery('', '', 0); + + this._triggerContentUpdateStart(); + this._triggerContentUpdateComplete(); } _setNoContentVisible(visible) { @@ -1046,10 +976,12 @@ class Display extends EventDispatcher { } } - _setFullQuery(text, offset) { - this._fullQuery = text; - this._queryOffset = offset; + _setQuery(query, fullQuery, queryOffset) { + this._query = query; + this._fullQuery = fullQuery; + this._queryOffset = queryOffset; this._updateQueryParser(); + this._setTitleText(query); } _updateQueryParser() { @@ -1219,10 +1151,6 @@ class Display extends EventDispatcher { } } - async _playAudioCurrent() { - await this._displayAudio.playAudio(this._index, 0); - } - _getEntry(index) { const entries = this._dictionaryEntryNodes; return index >= 0 && index < entries.length ? entries[index] : null; @@ -1575,10 +1503,6 @@ class Display extends EventDispatcher { this._focusEntry(this._index + count * sign, 0, true); } - _onHotkeyActionPlayAudioFromSource(source) { - this._displayAudio.playAudio(this._index, 0, source); - } - _closeAllPopupMenus() { for (const popupMenu of PopupMenu.openMenus) { popupMenu.close(); @@ -1598,9 +1522,32 @@ class Display extends EventDispatcher { const dictionaryEntry = this._dictionaryEntries[index]; const result = {dictionaryEntry}; - const result2 = await this._displayAnki.getLogData(dictionaryEntry); - Object.assign(result, result2); + const promises = []; + this.trigger('logDictionaryEntryData', {dictionaryEntry, promises}); + if (promises.length > 0) { + for (const result2 of await Promise.all(promises)) { + Object.assign(result, result2); + } + } console.log(result); } + + _triggerContentClear() { + this.trigger('contentClear', {}); + } + + _triggerContentUpdateStart() { + let {content} = this._history; + if (typeof content !== 'object' || content === null) { content = {}; } + this.trigger('contentUpdateStart', {type: this._contentType, query: this._query, content}); + } + + _triggerContentUpdateEntry(dictionaryEntry, element, index) { + this.trigger('contentUpdateEntry', {dictionaryEntry, element, index}); + } + + _triggerContentUpdateComplete() { + this.trigger('contentUpdateComplete', {type: this._contentType}); + } } diff --git a/ext/js/display/popup-main.js b/ext/js/display/popup-main.js index 0b5e338d..8621e200 100644 --- a/ext/js/display/popup-main.js +++ b/ext/js/display/popup-main.js @@ -17,6 +17,8 @@ /* global * Display + * DisplayAnki + * DisplayAudio * DisplayProfileSelection * DisplayResizer * DocumentFocusController @@ -41,6 +43,12 @@ const display = new Display(tabId, frameId, 'popup', japaneseUtil, documentFocusController, hotkeyHandler); await display.prepare(); + const displayAudio = new DisplayAudio(display); + displayAudio.prepare(); + + const displayAnki = new DisplayAnki(display, displayAudio, japaneseUtil); + displayAnki.prepare(); + const displayProfileSelection = new DisplayProfileSelection(display); displayProfileSelection.prepare(); diff --git a/ext/js/display/search-display-controller.js b/ext/js/display/search-display-controller.js index 489a9fa3..2b97479e 100644 --- a/ext/js/display/search-display-controller.js +++ b/ext/js/display/search-display-controller.js @@ -21,10 +21,11 @@ */ class SearchDisplayController { - constructor(tabId, frameId, display, japaneseUtil, searchPersistentStateController) { + constructor(tabId, frameId, display, displayAudio, japaneseUtil, searchPersistentStateController) { this._tabId = tabId; this._frameId = frameId; this._display = display; + this._displayAudio = displayAudio; this._searchPersistentStateController = searchPersistentStateController; this._searchButton = document.querySelector('#search-button'); this._queryInput = document.querySelector('#search-textbox'); @@ -56,7 +57,7 @@ class SearchDisplayController { yomichan.on('optionsUpdated', this._onOptionsUpdated.bind(this)); this._display.on('optionsUpdated', this._onDisplayOptionsUpdated.bind(this)); - this._display.on('contentUpdating', this._onContentUpdating.bind(this)); + this._display.on('contentUpdateStart', this._onContentUpdateStart.bind(this)); this._display.hotkeyHandler.registerActions([ ['focusSearchBox', this._onActionFocusSearchBox.bind(this)] @@ -69,7 +70,7 @@ class SearchDisplayController { this._updateClipboardMonitorEnabled(); - this._display.autoPlayAudioDelay = 0; + this._displayAudio.autoPlayAudioDelay = 0; this._display.queryParserVisible = true; this._display.setHistorySettings({useBrowserHistory: true}); @@ -145,27 +146,27 @@ class SearchDisplayController { this._setWanakanaEnabled(enableWanakana); } - _onContentUpdating({type, content, source}) { + _onContentUpdateStart({type, query, content}) { let animate = false; let valid = false; switch (type) { case 'terms': case 'kanji': animate = !!content.animate; - valid = (typeof source === 'string' && source.length > 0); + valid = (typeof query === 'string' && query.length > 0); this._display.blurElement(this._queryInput); break; case 'clear': valid = false; animate = true; - source = ''; + query = ''; break; } - if (typeof source !== 'string') { source = ''; } + if (typeof query !== 'string') { query = ''; } - if (this._queryInput.value !== source) { - this._queryInput.value = source; + if (this._queryInput.value !== query) { + this._queryInput.value = query; this._updateSearchHeight(true); } this._setIntroVisible(!valid, animate); diff --git a/ext/js/display/search-main.js b/ext/js/display/search-main.js index 7d39b3b7..a6479c86 100644 --- a/ext/js/display/search-main.js +++ b/ext/js/display/search-main.js @@ -17,6 +17,8 @@ /* global * Display + * DisplayAnki + * DisplayAudio * DocumentFocusController * HotkeyHandler * JapaneseUtil @@ -49,7 +51,13 @@ const display = new Display(tabId, frameId, 'search', japaneseUtil, documentFocusController, hotkeyHandler); await display.prepare(); - const searchDisplayController = new SearchDisplayController(tabId, frameId, display, japaneseUtil, searchPersistentStateController); + const displayAudio = new DisplayAudio(display); + displayAudio.prepare(); + + const displayAnki = new DisplayAnki(display, displayAudio, japaneseUtil); + displayAnki.prepare(); + + const searchDisplayController = new SearchDisplayController(tabId, frameId, display, displayAudio, japaneseUtil, searchPersistentStateController); await searchDisplayController.prepare(); display.initializeState();