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
This commit is contained in:
parent
d14268eb57
commit
be8ef53e90
@ -23,8 +23,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class DisplayAnki {
|
class DisplayAnki {
|
||||||
constructor(display, japaneseUtil) {
|
constructor(display, displayAudio, japaneseUtil) {
|
||||||
this._display = display;
|
this._display = display;
|
||||||
|
this._displayAudio = displayAudio;
|
||||||
this._ankiFieldTemplates = null;
|
this._ankiFieldTemplates = null;
|
||||||
this._ankiFieldTemplatesDefault = null;
|
this._ankiFieldTemplatesDefault = null;
|
||||||
this._ankiNoteBuilder = new AnkiNoteBuilder({japaneseUtil});
|
this._ankiNoteBuilder = new AnkiNoteBuilder({japaneseUtil});
|
||||||
@ -70,28 +71,11 @@ class DisplayAnki {
|
|||||||
['viewNote', this._viewNoteForSelectedEntry.bind(this)]
|
['viewNote', this._viewNoteForSelectedEntry.bind(this)]
|
||||||
]);
|
]);
|
||||||
this._display.on('optionsUpdated', this._onOptionsUpdated.bind(this));
|
this._display.on('optionsUpdated', this._onOptionsUpdated.bind(this));
|
||||||
}
|
this._display.on('contentClear', this._onContentClear.bind(this));
|
||||||
|
this._display.on('contentUpdateStart', this._onContentUpdateStart.bind(this));
|
||||||
cleanupEntries() {
|
this._display.on('contentUpdateEntry', this._onContentUpdateEntry.bind(this));
|
||||||
this._updateDictionaryEntryDetailsToken = null;
|
this._display.on('contentUpdateComplete', this._onContentUpdateComplete.bind(this));
|
||||||
this._dictionaryEntryDetails = null;
|
this._display.on('logDictionaryEntryData', this._onLogDictionaryEntryData.bind(this));
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getLogData(dictionaryEntry) {
|
async getLogData(dictionaryEntry) {
|
||||||
@ -173,6 +157,32 @@ class DisplayAnki {
|
|||||||
this._updateAnkiFieldTemplates(options);
|
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) {
|
_onNoteAdd(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const node = e.currentTarget;
|
const node = e.currentTarget;
|
||||||
@ -526,7 +536,7 @@ class DisplayAnki {
|
|||||||
const fields = Object.entries(modeOptions.fields);
|
const fields = Object.entries(modeOptions.fields);
|
||||||
const contentOrigin = this._display.getContentOrigin();
|
const contentOrigin = this._display.getContentOrigin();
|
||||||
const details = this._ankiNoteBuilder.getDictionaryEntryDetailsForNote(dictionaryEntry);
|
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 optionsContext = this._display.getOptionsContext();
|
||||||
|
|
||||||
const {note, errors, requirements: outputRequirements} = await this._ankiNoteBuilder.createNote({
|
const {note, errors, requirements: outputRequirements} = await this._ankiNoteBuilder.createNote({
|
||||||
|
@ -56,49 +56,21 @@ class DisplayAudio {
|
|||||||
|
|
||||||
prepare() {
|
prepare() {
|
||||||
this._audioSystem.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('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()});
|
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() {
|
clearAutoPlayTimer() {
|
||||||
if (this._autoPlayAudioTimer === null) { return; }
|
if (this._autoPlayAudioTimer === null) { return; }
|
||||||
clearTimeout(this._autoPlayAudioTimer);
|
clearTimeout(this._autoPlayAudioTimer);
|
||||||
@ -171,6 +143,64 @@ class DisplayAudio {
|
|||||||
this._cache.clear();
|
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) {
|
_addAudioSourceInfo(type, url, voice, isInOptions, nameMap) {
|
||||||
const index = this._audioSources.length;
|
const index = this._audioSources.length;
|
||||||
const downloadable = this._sourceIsDownloadable(type);
|
const downloadable = this._sourceIsDownloadable(type);
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* global
|
/* global
|
||||||
* DisplayAnki
|
|
||||||
* DisplayAudio
|
|
||||||
* DisplayGenerator
|
* DisplayGenerator
|
||||||
* DisplayHistory
|
* DisplayHistory
|
||||||
* DisplayNotification
|
* DisplayNotification
|
||||||
@ -106,10 +104,8 @@ class Display extends EventDispatcher {
|
|||||||
this._contentTextScanner = null;
|
this._contentTextScanner = null;
|
||||||
this._tagNotification = null;
|
this._tagNotification = null;
|
||||||
this._footerNotificationContainer = document.querySelector('#content-footer');
|
this._footerNotificationContainer = document.querySelector('#content-footer');
|
||||||
this._displayAudio = new DisplayAudio(this);
|
|
||||||
this._optionToggleHotkeyHandler = new OptionToggleHotkeyHandler(this);
|
this._optionToggleHotkeyHandler = new OptionToggleHotkeyHandler(this);
|
||||||
this._elementOverflowController = new ElementOverflowController();
|
this._elementOverflowController = new ElementOverflowController();
|
||||||
this._displayAnki = new DisplayAnki(this, japaneseUtil);
|
|
||||||
this._frameVisible = (pageType === 'search');
|
this._frameVisible = (pageType === 'search');
|
||||||
|
|
||||||
this._hotkeyHandler.registerActions([
|
this._hotkeyHandler.registerActions([
|
||||||
@ -120,8 +116,6 @@ class Display extends EventDispatcher {
|
|||||||
['firstEntry', () => { this._focusEntry(0, 0, true); }],
|
['firstEntry', () => { this._focusEntry(0, 0, true); }],
|
||||||
['historyBackward', () => { this._sourceTermView(); }],
|
['historyBackward', () => { this._sourceTermView(); }],
|
||||||
['historyForward', () => { this._nextTermView(); }],
|
['historyForward', () => { this._nextTermView(); }],
|
||||||
['playAudio', () => { this._playAudioCurrent(); }],
|
|
||||||
['playAudioFromSource', this._onHotkeyActionPlayAudioFromSource.bind(this)],
|
|
||||||
['copyHostSelection', () => this._copyHostSelection()],
|
['copyHostSelection', () => this._copyHostSelection()],
|
||||||
['nextEntryDifferentDictionary', () => { this._focusEntryWithDifferentDictionary(1, true); }],
|
['nextEntryDifferentDictionary', () => { this._focusEntryWithDifferentDictionary(1, true); }],
|
||||||
['previousEntryDifferentDictionary', () => { this._focusEntryWithDifferentDictionary(-1, true); }]
|
['previousEntryDifferentDictionary', () => { this._focusEntryWithDifferentDictionary(-1, true); }]
|
||||||
@ -129,7 +123,6 @@ class Display extends EventDispatcher {
|
|||||||
this.registerDirectMessageHandlers([
|
this.registerDirectMessageHandlers([
|
||||||
['setOptionsContext', {async: false, handler: this._onMessageSetOptionsContext.bind(this)}],
|
['setOptionsContext', {async: false, handler: this._onMessageSetOptionsContext.bind(this)}],
|
||||||
['setContent', {async: false, handler: this._onMessageSetContent.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)}],
|
['setCustomCss', {async: false, handler: this._onMessageSetCustomCss.bind(this)}],
|
||||||
['setContentScale', {async: false, handler: this._onMessageSetContentScale.bind(this)}],
|
['setContentScale', {async: false, handler: this._onMessageSetContentScale.bind(this)}],
|
||||||
['configure', {async: true, handler: this._onMessageConfigure.bind(this)}],
|
['configure', {async: true, handler: this._onMessageConfigure.bind(this)}],
|
||||||
@ -144,14 +137,6 @@ class Display extends EventDispatcher {
|
|||||||
return this._displayGenerator;
|
return this._displayGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
get autoPlayAudioDelay() {
|
|
||||||
return this._displayAudio.autoPlayAudioDelay;
|
|
||||||
}
|
|
||||||
|
|
||||||
set autoPlayAudioDelay(value) {
|
|
||||||
this._displayAudio.autoPlayAudioDelay = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
get queryParserVisible() {
|
get queryParserVisible() {
|
||||||
return this._queryParserVisible;
|
return this._queryParserVisible;
|
||||||
}
|
}
|
||||||
@ -230,8 +215,6 @@ class Display extends EventDispatcher {
|
|||||||
// Prepare
|
// Prepare
|
||||||
await this._hotkeyHelpController.prepare();
|
await this._hotkeyHelpController.prepare();
|
||||||
await this._displayGenerator.prepare();
|
await this._displayGenerator.prepare();
|
||||||
this._displayAudio.prepare();
|
|
||||||
this._displayAnki.prepare();
|
|
||||||
this._queryParser.prepare();
|
this._queryParser.prepare();
|
||||||
this._history.prepare();
|
this._history.prepare();
|
||||||
this._optionToggleHotkeyHandler.prepare();
|
this._optionToggleHotkeyHandler.prepare();
|
||||||
@ -345,10 +328,6 @@ class Display extends EventDispatcher {
|
|||||||
this.trigger('optionsUpdated', {options});
|
this.trigger('optionsUpdated', {options});
|
||||||
}
|
}
|
||||||
|
|
||||||
clearAutoPlayTimer() {
|
|
||||||
this._displayAudio.clearAutoPlayTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
setContent(details) {
|
setContent(details) {
|
||||||
const {focus, params, state, content} = details;
|
const {focus, params, state, content} = details;
|
||||||
const historyMode = this._historyHasChanged ? details.historyMode : 'clear';
|
const historyMode = this._historyHasChanged ? details.historyMode : 'clear';
|
||||||
@ -468,10 +447,6 @@ class Display extends EventDispatcher {
|
|||||||
return Number.isFinite(index) ? index : -1;
|
return Number.isFinite(index) ? index : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
getAnkiNoteMediaAudioDetails(term, reading) {
|
|
||||||
return this._displayAudio.getAnkiNoteMediaAudioDetails(term, reading);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Message handlers
|
// Message handlers
|
||||||
|
|
||||||
_onDirectMessage(data) {
|
_onDirectMessage(data) {
|
||||||
@ -511,10 +486,6 @@ class Display extends EventDispatcher {
|
|||||||
this.setContent(details);
|
this.setContent(details);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onMessageClearAutoPlayTimer() {
|
|
||||||
this.clearAutoPlayTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
_onMessageSetCustomCss({css}) {
|
_onMessageSetCustomCss({css}) {
|
||||||
this.setCustomCss(css);
|
this.setCustomCss(css);
|
||||||
}
|
}
|
||||||
@ -534,10 +505,7 @@ class Display extends EventDispatcher {
|
|||||||
|
|
||||||
_onMessageVisibilityChanged({value}) {
|
_onMessageVisibilityChanged({value}) {
|
||||||
this._frameVisible = value;
|
this._frameVisible = value;
|
||||||
if (!value) {
|
this.trigger('frameVisibilityChange', {value});
|
||||||
this._displayAudio.clearAutoPlayTimer();
|
|
||||||
this._displayAudio.stopAudio();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_onMessageExtensionUnloaded() {
|
_onMessageExtensionUnloaded() {
|
||||||
@ -568,9 +536,8 @@ class Display extends EventDispatcher {
|
|||||||
this._closeAllPopupMenus();
|
this._closeAllPopupMenus();
|
||||||
this._eventListeners.removeAllEventListeners();
|
this._eventListeners.removeAllEventListeners();
|
||||||
this._mediaLoader.unloadAll();
|
this._mediaLoader.unloadAll();
|
||||||
this._displayAudio.cleanupEntries();
|
|
||||||
this._displayAnki.cleanupEntries();
|
|
||||||
this._hideTagNotification(false);
|
this._hideTagNotification(false);
|
||||||
|
this._triggerContentClear();
|
||||||
this._dictionaryEntries = [];
|
this._dictionaryEntries = [];
|
||||||
this._dictionaryEntryNodes = [];
|
this._dictionaryEntryNodes = [];
|
||||||
this._elementOverflowController.clearElements();
|
this._elementOverflowController.clearElements();
|
||||||
@ -582,62 +549,25 @@ class Display extends EventDispatcher {
|
|||||||
|
|
||||||
const fullVisible = urlSearchParams.get('full-visible');
|
const fullVisible = urlSearchParams.get('full-visible');
|
||||||
this._queryParserVisibleOverride = (fullVisible === null ? null : (fullVisible !== 'false'));
|
this._queryParserVisibleOverride = (fullVisible === null ? null : (fullVisible !== 'false'));
|
||||||
this._updateQueryParser();
|
|
||||||
|
|
||||||
let clear = true;
|
|
||||||
this._historyHasChanged = true;
|
this._historyHasChanged = true;
|
||||||
this._contentType = type;
|
this._contentType = type;
|
||||||
this._query = '';
|
|
||||||
const eventArgs = {type, urlSearchParams, token};
|
|
||||||
|
|
||||||
// Set content
|
// Set content
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'terms':
|
case 'terms':
|
||||||
case 'kanji':
|
case 'kanji':
|
||||||
{
|
await this._setContentTermsOrKanji(type, urlSearchParams, token);
|
||||||
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);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'unloaded':
|
case 'unloaded':
|
||||||
{
|
this._setContentExtensionUnloaded();
|
||||||
clear = false;
|
break;
|
||||||
const {content} = this._history;
|
default:
|
||||||
eventArgs.content = content;
|
type = 'clear';
|
||||||
this.trigger('contentUpdating', eventArgs);
|
this._contentType = type;
|
||||||
this._setContentExtensionUnloaded();
|
this._clearContent();
|
||||||
}
|
|
||||||
break;
|
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) {
|
} catch (e) {
|
||||||
this.onError(e);
|
this.onError(e);
|
||||||
}
|
}
|
||||||
@ -874,8 +804,11 @@ class Display extends EventDispatcher {
|
|||||||
document.documentElement.dataset.theme = themeName;
|
document.documentElement.dataset.theme = themeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _findDictionaryEntries(isTerms, source, wildcardsEnabled, optionsContext) {
|
async _findDictionaryEntries(isKanji, source, wildcardsEnabled, optionsContext) {
|
||||||
if (isTerms) {
|
if (isKanji) {
|
||||||
|
const dictionaryEntries = await yomichan.api.kanjiFind(source, optionsContext);
|
||||||
|
return dictionaryEntries;
|
||||||
|
} else {
|
||||||
const findDetails = {};
|
const findDetails = {};
|
||||||
if (wildcardsEnabled) {
|
if (wildcardsEnabled) {
|
||||||
const match = /^([*\uff0a]*)([\w\W]*?)([*\uff0a]*)$/.exec(source);
|
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);
|
const {dictionaryEntries} = await yomichan.api.termsFind(source, findDetails, optionsContext);
|
||||||
return dictionaryEntries;
|
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 {state, content} = this._history;
|
||||||
let changeHistory = false;
|
let changeHistory = false;
|
||||||
if (!isObject(content)) {
|
if (!isObject(content)) {
|
||||||
@ -909,12 +853,7 @@ class Display extends EventDispatcher {
|
|||||||
changeHistory = true;
|
changeHistory = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let {
|
let {focusEntry, scrollX, scrollY, optionsContext} = state;
|
||||||
focusEntry=null,
|
|
||||||
scrollX=null,
|
|
||||||
scrollY=null,
|
|
||||||
optionsContext=null
|
|
||||||
} = state;
|
|
||||||
if (typeof focusEntry !== 'number') { focusEntry = 0; }
|
if (typeof focusEntry !== 'number') { focusEntry = 0; }
|
||||||
if (!(typeof optionsContext === 'object' && optionsContext !== null)) {
|
if (!(typeof optionsContext === 'object' && optionsContext !== null)) {
|
||||||
optionsContext = this.getOptionsContext();
|
optionsContext = this.getOptionsContext();
|
||||||
@ -922,16 +861,9 @@ class Display extends EventDispatcher {
|
|||||||
changeHistory = true;
|
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;
|
let {dictionaryEntries} = content;
|
||||||
if (!Array.isArray(dictionaryEntries)) {
|
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; }
|
if (this._setContentToken !== token) { return; }
|
||||||
content.dictionaryEntries = dictionaryEntries;
|
content.dictionaryEntries = dictionaryEntries;
|
||||||
changeHistory = true;
|
changeHistory = true;
|
||||||
@ -964,10 +896,6 @@ class Display extends EventDispatcher {
|
|||||||
this._replaceHistoryStateNoNavigate(state, content);
|
this._replaceHistoryStateNoNavigate(state, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
eventArgs.source = query;
|
|
||||||
eventArgs.content = content;
|
|
||||||
this.trigger('contentUpdating', eventArgs);
|
|
||||||
|
|
||||||
this._dictionaryEntries = dictionaryEntries;
|
this._dictionaryEntries = dictionaryEntries;
|
||||||
|
|
||||||
this._updateNavigation(this._history.hasPrevious(), this._history.hasNext());
|
this._updateNavigation(this._history.hasPrevious(), this._history.hasNext());
|
||||||
@ -976,7 +904,7 @@ class Display extends EventDispatcher {
|
|||||||
const container = this._container;
|
const container = this._container;
|
||||||
container.textContent = '';
|
container.textContent = '';
|
||||||
|
|
||||||
this._displayAnki.setupEntriesBegin();
|
this._triggerContentUpdateStart();
|
||||||
|
|
||||||
for (let i = 0, ii = dictionaryEntries.length; i < ii; ++i) {
|
for (let i = 0, ii = dictionaryEntries.length; i < ii; ++i) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
@ -986,15 +914,14 @@ class Display extends EventDispatcher {
|
|||||||
|
|
||||||
const dictionaryEntry = dictionaryEntries[i];
|
const dictionaryEntry = dictionaryEntries[i];
|
||||||
const entry = (
|
const entry = (
|
||||||
isTerms ?
|
dictionaryEntry.type === 'term' ?
|
||||||
this._displayGenerator.createTermEntry(dictionaryEntry) :
|
this._displayGenerator.createTermEntry(dictionaryEntry) :
|
||||||
this._displayGenerator.createKanjiEntry(dictionaryEntry)
|
this._displayGenerator.createKanjiEntry(dictionaryEntry)
|
||||||
);
|
);
|
||||||
entry.dataset.index = `${i}`;
|
entry.dataset.index = `${i}`;
|
||||||
this._dictionaryEntryNodes.push(entry);
|
this._dictionaryEntryNodes.push(entry);
|
||||||
this._addEntryEventListeners(entry);
|
this._addEntryEventListeners(entry);
|
||||||
this._displayAudio.setupEntry(entry, i);
|
this._triggerContentUpdateEntry(dictionaryEntry, entry, i);
|
||||||
this._displayAnki.setupEntry(entry, i);
|
|
||||||
container.appendChild(entry);
|
container.appendChild(entry);
|
||||||
if (focusEntry === i) {
|
if (focusEntry === i) {
|
||||||
this._focusEntry(i, 0, false);
|
this._focusEntry(i, 0, false);
|
||||||
@ -1011,8 +938,7 @@ class Display extends EventDispatcher {
|
|||||||
this._windowScroll.to(x, y);
|
this._windowScroll.to(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._displayAudio.setupEntriesComplete();
|
this._triggerContentUpdateComplete();
|
||||||
this._displayAnki.setupEntriesComplete();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_setContentExtensionUnloaded() {
|
_setContentExtensionUnloaded() {
|
||||||
@ -1028,14 +954,18 @@ class Display extends EventDispatcher {
|
|||||||
|
|
||||||
this._updateNavigation(false, false);
|
this._updateNavigation(false, false);
|
||||||
this._setNoContentVisible(false);
|
this._setNoContentVisible(false);
|
||||||
this._setTitleText('');
|
this._setQuery('', '', 0);
|
||||||
this._setFullQuery('', 0);
|
|
||||||
|
this._triggerContentUpdateStart();
|
||||||
|
this._triggerContentUpdateComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
_clearContent() {
|
_clearContent() {
|
||||||
this._container.textContent = '';
|
this._container.textContent = '';
|
||||||
this._setTitleText('');
|
this._setQuery('', '', 0);
|
||||||
this._setFullQuery('', 0);
|
|
||||||
|
this._triggerContentUpdateStart();
|
||||||
|
this._triggerContentUpdateComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
_setNoContentVisible(visible) {
|
_setNoContentVisible(visible) {
|
||||||
@ -1046,10 +976,12 @@ class Display extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_setFullQuery(text, offset) {
|
_setQuery(query, fullQuery, queryOffset) {
|
||||||
this._fullQuery = text;
|
this._query = query;
|
||||||
this._queryOffset = offset;
|
this._fullQuery = fullQuery;
|
||||||
|
this._queryOffset = queryOffset;
|
||||||
this._updateQueryParser();
|
this._updateQueryParser();
|
||||||
|
this._setTitleText(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateQueryParser() {
|
_updateQueryParser() {
|
||||||
@ -1219,10 +1151,6 @@ class Display extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async _playAudioCurrent() {
|
|
||||||
await this._displayAudio.playAudio(this._index, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
_getEntry(index) {
|
_getEntry(index) {
|
||||||
const entries = this._dictionaryEntryNodes;
|
const entries = this._dictionaryEntryNodes;
|
||||||
return index >= 0 && index < entries.length ? entries[index] : null;
|
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);
|
this._focusEntry(this._index + count * sign, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onHotkeyActionPlayAudioFromSource(source) {
|
|
||||||
this._displayAudio.playAudio(this._index, 0, source);
|
|
||||||
}
|
|
||||||
|
|
||||||
_closeAllPopupMenus() {
|
_closeAllPopupMenus() {
|
||||||
for (const popupMenu of PopupMenu.openMenus) {
|
for (const popupMenu of PopupMenu.openMenus) {
|
||||||
popupMenu.close();
|
popupMenu.close();
|
||||||
@ -1598,9 +1522,32 @@ class Display extends EventDispatcher {
|
|||||||
const dictionaryEntry = this._dictionaryEntries[index];
|
const dictionaryEntry = this._dictionaryEntries[index];
|
||||||
const result = {dictionaryEntry};
|
const result = {dictionaryEntry};
|
||||||
|
|
||||||
const result2 = await this._displayAnki.getLogData(dictionaryEntry);
|
const promises = [];
|
||||||
Object.assign(result, result2);
|
this.trigger('logDictionaryEntryData', {dictionaryEntry, promises});
|
||||||
|
if (promises.length > 0) {
|
||||||
|
for (const result2 of await Promise.all(promises)) {
|
||||||
|
Object.assign(result, result2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
console.log(result);
|
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});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
/* global
|
/* global
|
||||||
* Display
|
* Display
|
||||||
|
* DisplayAnki
|
||||||
|
* DisplayAudio
|
||||||
* DisplayProfileSelection
|
* DisplayProfileSelection
|
||||||
* DisplayResizer
|
* DisplayResizer
|
||||||
* DocumentFocusController
|
* DocumentFocusController
|
||||||
@ -41,6 +43,12 @@
|
|||||||
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 displayAudio = new DisplayAudio(display);
|
||||||
|
displayAudio.prepare();
|
||||||
|
|
||||||
|
const displayAnki = new DisplayAnki(display, displayAudio, japaneseUtil);
|
||||||
|
displayAnki.prepare();
|
||||||
|
|
||||||
const displayProfileSelection = new DisplayProfileSelection(display);
|
const displayProfileSelection = new DisplayProfileSelection(display);
|
||||||
displayProfileSelection.prepare();
|
displayProfileSelection.prepare();
|
||||||
|
|
||||||
|
@ -21,10 +21,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class SearchDisplayController {
|
class SearchDisplayController {
|
||||||
constructor(tabId, frameId, display, japaneseUtil, searchPersistentStateController) {
|
constructor(tabId, frameId, display, displayAudio, japaneseUtil, searchPersistentStateController) {
|
||||||
this._tabId = tabId;
|
this._tabId = tabId;
|
||||||
this._frameId = frameId;
|
this._frameId = frameId;
|
||||||
this._display = display;
|
this._display = display;
|
||||||
|
this._displayAudio = displayAudio;
|
||||||
this._searchPersistentStateController = searchPersistentStateController;
|
this._searchPersistentStateController = searchPersistentStateController;
|
||||||
this._searchButton = document.querySelector('#search-button');
|
this._searchButton = document.querySelector('#search-button');
|
||||||
this._queryInput = document.querySelector('#search-textbox');
|
this._queryInput = document.querySelector('#search-textbox');
|
||||||
@ -56,7 +57,7 @@ class SearchDisplayController {
|
|||||||
yomichan.on('optionsUpdated', this._onOptionsUpdated.bind(this));
|
yomichan.on('optionsUpdated', this._onOptionsUpdated.bind(this));
|
||||||
|
|
||||||
this._display.on('optionsUpdated', this._onDisplayOptionsUpdated.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([
|
this._display.hotkeyHandler.registerActions([
|
||||||
['focusSearchBox', this._onActionFocusSearchBox.bind(this)]
|
['focusSearchBox', this._onActionFocusSearchBox.bind(this)]
|
||||||
@ -69,7 +70,7 @@ class SearchDisplayController {
|
|||||||
|
|
||||||
this._updateClipboardMonitorEnabled();
|
this._updateClipboardMonitorEnabled();
|
||||||
|
|
||||||
this._display.autoPlayAudioDelay = 0;
|
this._displayAudio.autoPlayAudioDelay = 0;
|
||||||
this._display.queryParserVisible = true;
|
this._display.queryParserVisible = true;
|
||||||
this._display.setHistorySettings({useBrowserHistory: true});
|
this._display.setHistorySettings({useBrowserHistory: true});
|
||||||
|
|
||||||
@ -145,27 +146,27 @@ class SearchDisplayController {
|
|||||||
this._setWanakanaEnabled(enableWanakana);
|
this._setWanakanaEnabled(enableWanakana);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onContentUpdating({type, content, source}) {
|
_onContentUpdateStart({type, query, content}) {
|
||||||
let animate = false;
|
let animate = false;
|
||||||
let valid = false;
|
let valid = false;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'terms':
|
case 'terms':
|
||||||
case 'kanji':
|
case 'kanji':
|
||||||
animate = !!content.animate;
|
animate = !!content.animate;
|
||||||
valid = (typeof source === 'string' && source.length > 0);
|
valid = (typeof query === 'string' && query.length > 0);
|
||||||
this._display.blurElement(this._queryInput);
|
this._display.blurElement(this._queryInput);
|
||||||
break;
|
break;
|
||||||
case 'clear':
|
case 'clear':
|
||||||
valid = false;
|
valid = false;
|
||||||
animate = true;
|
animate = true;
|
||||||
source = '';
|
query = '';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof source !== 'string') { source = ''; }
|
if (typeof query !== 'string') { query = ''; }
|
||||||
|
|
||||||
if (this._queryInput.value !== source) {
|
if (this._queryInput.value !== query) {
|
||||||
this._queryInput.value = source;
|
this._queryInput.value = query;
|
||||||
this._updateSearchHeight(true);
|
this._updateSearchHeight(true);
|
||||||
}
|
}
|
||||||
this._setIntroVisible(!valid, animate);
|
this._setIntroVisible(!valid, animate);
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
/* global
|
/* global
|
||||||
* Display
|
* Display
|
||||||
|
* DisplayAnki
|
||||||
|
* DisplayAudio
|
||||||
* DocumentFocusController
|
* DocumentFocusController
|
||||||
* HotkeyHandler
|
* HotkeyHandler
|
||||||
* JapaneseUtil
|
* JapaneseUtil
|
||||||
@ -49,7 +51,13 @@
|
|||||||
const display = new Display(tabId, frameId, 'search', japaneseUtil, documentFocusController, hotkeyHandler);
|
const display = new Display(tabId, frameId, 'search', japaneseUtil, documentFocusController, hotkeyHandler);
|
||||||
await display.prepare();
|
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();
|
await searchDisplayController.prepare();
|
||||||
|
|
||||||
display.initializeState();
|
display.initializeState();
|
||||||
|
Loading…
Reference in New Issue
Block a user