aboutsummaryrefslogtreecommitdiff
path: root/ext/js
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2021-10-03 16:46:15 -0400
committerGitHub <noreply@github.com>2021-10-03 16:46:15 -0400
commitbe8ef53e90c3893dc2696b846dadb185be8c4514 (patch)
tree93b75d0f2f974e12a2a3d33dc9b51dc674a43504 /ext/js
parentd14268eb574d39b5ecc1e83302d45d5933770a73 (diff)
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
Diffstat (limited to 'ext/js')
-rw-r--r--ext/js/display/display-anki.js58
-rw-r--r--ext/js/display/display-audio.js108
-rw-r--r--ext/js/display/display.js199
-rw-r--r--ext/js/display/popup-main.js8
-rw-r--r--ext/js/display/search-display-controller.js19
-rw-r--r--ext/js/display/search-main.js10
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();