Display updates (#1057)

* Fix history assignment on the search page

* Use clear instead of assigned

* Simplify definitions assignment

* Organize

* Fix query not being cleared

* Fix media loading

* Fix potential issue with options not being assigned

* Catch error when frameId is null, causing infinite loop

* Fix frontend construction parameters
This commit is contained in:
toasted-nutbread 2020-11-24 11:54:08 -05:00 committed by GitHub
parent 068b1eef71
commit de299c64ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 67 additions and 57 deletions

View File

@ -143,7 +143,7 @@ class DisplaySearch extends Display {
await this.updateOptions(); await this.updateOptions();
const query = this._queryInput.value; const query = this._queryInput.value;
if (query) { if (query) {
this._search(false); this._search(false, false);
} }
} }
@ -153,7 +153,7 @@ class DisplaySearch extends Display {
switch (type) { switch (type) {
case 'terms': case 'terms':
case 'kanji': case 'kanji':
animate = content.animate; animate = !!content.animate;
valid = content.definitions.length > 0; valid = content.definitions.length > 0;
this.blurElement(this._queryInput); this.blurElement(this._queryInput);
break; break;
@ -182,12 +182,12 @@ class DisplaySearch extends Display {
e.preventDefault(); e.preventDefault();
e.stopImmediatePropagation(); e.stopImmediatePropagation();
this.blurElement(e.currentTarget); this.blurElement(e.currentTarget);
this._search(true); this._search(true, true);
} }
_onSearch(e) { _onSearch(e) {
e.preventDefault(); e.preventDefault();
this._search(true); this._search(true, true);
} }
_onCopy() { _onCopy() {
@ -197,7 +197,7 @@ class DisplaySearch extends Display {
_onExternalSearchUpdate({text, animate=true}) { _onExternalSearchUpdate({text, animate=true}) {
this._queryInput.value = text; this._queryInput.value = text;
this._search(animate); this._search(animate, false);
} }
_onWanakanaEnableChange(e) { _onWanakanaEnableChange(e) {
@ -342,11 +342,11 @@ class DisplaySearch extends Display {
}); });
} }
_search(animate) { _search(animate, history) {
const query = this._queryInput.value; const query = this._queryInput.value;
const details = { const details = {
focus: false, focus: false,
history: false, history,
params: { params: {
query query
}, },

View File

@ -114,7 +114,7 @@ class PopupFactory {
const popup = new Popup({ const popup = new Popup({
id, id,
depth, depth,
frameId, frameId: this._frameId,
ownerFrameId, ownerFrameId,
childrenSupported childrenSupported
}); });
@ -129,6 +129,9 @@ class PopupFactory {
popup.prepare(); popup.prepare();
return popup; return popup;
} else { } else {
if (frameId === null) {
throw new Error('Invalid frameId');
}
const useFrameOffsetForwarder = (parentPopupId === null); const useFrameOffsetForwarder = (parentPopupId === null);
({id, depth, frameId} = await api.crossFrame.invoke(frameId, 'getOrCreatePopup', { ({id, depth, frameId} = await api.crossFrame.invoke(frameId, 'getOrCreatePopup', {
id, id,

View File

@ -522,6 +522,12 @@ class Display extends EventDispatcher {
const token = {}; // Unique identifier token const token = {}; // Unique identifier token
this._setContentToken = token; this._setContentToken = token;
try { try {
// Clear
this._closePopups();
this._eventListeners.removeAllEventListeners();
this._mediaLoader.unloadAll();
// Prepare
const urlSearchParams = new URLSearchParams(location.search); const urlSearchParams = new URLSearchParams(location.search);
let type = urlSearchParams.get('type'); let type = urlSearchParams.get('type');
if (type === null) { type = 'terms'; } if (type === null) { type = 'terms'; }
@ -530,46 +536,51 @@ class Display extends EventDispatcher {
this._queryParserVisibleOverride = (fullVisible === null ? null : (fullVisible !== 'false')); this._queryParserVisibleOverride = (fullVisible === null ? null : (fullVisible !== 'false'));
this._updateQueryParser(); this._updateQueryParser();
this._closePopups(); let clear = true;
this._eventListeners.removeAllEventListeners();
let assigned = false;
const eventArgs = {type, urlSearchParams, token};
this._historyHasChanged = true; this._historyHasChanged = true;
this._contentType = type; this._contentType = type;
this._mediaLoader.unloadAll(); const eventArgs = {type, urlSearchParams, token};
// Set content
switch (type) { switch (type) {
case 'terms': case 'terms':
case 'kanji': case 'kanji':
{ {
let query = urlSearchParams.get('query');
if (!query) { break; }
clear = false;
const isTerms = (type === 'terms'); const isTerms = (type === 'terms');
assigned = await this._setContentTermsOrKanji(token, isTerms, urlSearchParams, eventArgs); query = this.postProcessQuery(query);
let queryFull = urlSearchParams.get('full');
queryFull = (queryFull !== null ? this.postProcessQuery(queryFull) : query);
const wildcardsEnabled = (urlSearchParams.get('wildcards') !== 'off');
await this._setContentTermsOrKanji(token, isTerms, query, queryFull, wildcardsEnabled, eventArgs);
} }
break; break;
case 'unloaded': case 'unloaded':
{ {
clear = false;
const {content} = this._history; const {content} = this._history;
eventArgs.content = content; eventArgs.content = content;
this.trigger('contentUpdating', eventArgs); this.trigger('contentUpdating', eventArgs);
this._setContentExtensionUnloaded(); this._setContentExtensionUnloaded();
assigned = true;
} }
break; break;
} }
const stale = (this._setContentToken !== token); // Clear
if (!stale) { if (clear) {
if (!assigned) { type = 'clear';
type = 'clear'; this._contentType = type;
this._contentType = type; const {content} = this._history;
const {content} = this._history; eventArgs.type = type;
eventArgs.type = type; eventArgs.content = content;
eventArgs.content = content; this.trigger('contentUpdating', eventArgs);
this.trigger('contentUpdating', eventArgs); this._clearContent();
this._clearContent();
}
} }
const stale = (this._setContentToken !== token);
eventArgs.stale = stale; eventArgs.stale = stale;
this.trigger('contentUpdated', eventArgs); this.trigger('contentUpdated', eventArgs);
} catch (e) { } catch (e) {
@ -788,10 +799,10 @@ class Display extends EventDispatcher {
document.documentElement.dataset.yomichanTheme = themeName; document.documentElement.dataset.yomichanTheme = themeName;
} }
async _findDefinitions(isTerms, source, urlSearchParams, optionsContext) { async _findDefinitions(isTerms, source, wildcardsEnabled, optionsContext) {
if (isTerms) { if (isTerms) {
const findDetails = {}; const findDetails = {};
if (urlSearchParams.get('wildcards') !== 'off') { if (wildcardsEnabled) {
const match = /^([*\uff0a]*)([\w\W]*?)([*\uff0a]*)$/.exec(source); const match = /^([*\uff0a]*)([\w\W]*?)([*\uff0a]*)$/.exec(source);
if (match !== null) { if (match !== null) {
if (match[1]) { if (match[1]) {
@ -811,13 +822,7 @@ class Display extends EventDispatcher {
} }
} }
async _setContentTermsOrKanji(token, isTerms, urlSearchParams, eventArgs) { async _setContentTermsOrKanji(token, isTerms, query, queryFull, wildcardsEnabled, eventArgs) {
let source = urlSearchParams.get('query');
if (!source) {
this._setFullQuery('');
return false;
}
let {state, content} = this._history; let {state, content} = this._history;
let changeHistory = false; let changeHistory = false;
if (!isObject(content)) { if (!isObject(content)) {
@ -839,28 +844,30 @@ class Display extends EventDispatcher {
if (typeof url !== 'string') { url = window.location.href; } if (typeof url !== 'string') { url = window.location.href; }
sentence = this._getValidSentenceData(sentence); sentence = this._getValidSentenceData(sentence);
source = this.postProcessQuery(source); this._setFullQuery(queryFull);
let full = urlSearchParams.get('full'); this._setTitleText(query);
full = (full === null ? source : this.postProcessQuery(full));
this._setFullQuery(full);
this._setTitleText(source);
let {definitions} = content; let {definitions} = content;
if (!Array.isArray(definitions)) { if (!Array.isArray(definitions)) {
definitions = await this._findDefinitions(isTerms, source, urlSearchParams, optionsContext); definitions = await this._findDefinitions(isTerms, query, wildcardsEnabled, optionsContext);
if (this._setContentToken !== token) { return true; } if (this._setContentToken !== token) { return; }
content.definitions = definitions; content.definitions = definitions;
changeHistory = true; changeHistory = true;
} }
await this._setOptionsContextIfDifferent(optionsContext); await this._setOptionsContextIfDifferent(optionsContext);
if (this._setContentToken !== token) { return true; } if (this._setContentToken !== token) { return; }
if (this._options === null) {
await this.updateOptions();
if (this._setContentToken !== token) { return; }
}
if (changeHistory) { if (changeHistory) {
this._replaceHistoryStateNoNavigate(state, content); this._replaceHistoryStateNoNavigate(state, content);
} }
eventArgs.source = source; eventArgs.source = query;
eventArgs.content = content; eventArgs.content = content;
this.trigger('contentUpdating', eventArgs); this.trigger('contentUpdating', eventArgs);
@ -880,7 +887,7 @@ class Display extends EventDispatcher {
for (let i = 0, ii = definitions.length; i < ii; ++i) { for (let i = 0, ii = definitions.length; i < ii; ++i) {
if (i > 0) { if (i > 0) {
await promiseTimeout(1); await promiseTimeout(1);
if (this._setContentToken !== token) { return true; } if (this._setContentToken !== token) { return; }
} }
const definition = definitions[i]; const definition = definitions[i];
@ -912,8 +919,6 @@ class Display extends EventDispatcher {
} }
this._updateAdderButtons(token, isTerms, definitions); this._updateAdderButtons(token, isTerms, definitions);
return true;
} }
_setContentExtensionUnloaded() { _setContentExtensionUnloaded() {
@ -930,11 +935,13 @@ class Display extends EventDispatcher {
this._updateNavigation(false, false); this._updateNavigation(false, false);
this._setNoContentVisible(false); this._setNoContentVisible(false);
this._setTitleText(''); this._setTitleText('');
this._setFullQuery('');
} }
_clearContent() { _clearContent() {
this._container.textContent = ''; this._container.textContent = '';
this._setTitleText(''); this._setTitleText('');
this._setFullQuery('');
} }
_setNoContentVisible(visible) { _setNoContentVisible(visible) {
@ -1566,7 +1573,7 @@ class Display extends EventDispatcher {
try { try {
if (this._frontendSetupPromise === null) { if (this._frontendSetupPromise === null) {
this._frontendSetupPromise = this._setupNestedFrontend(isSearchPage); this._frontendSetupPromise = this._setupNestedFrontend();
} }
await this._frontendSetupPromise; await this._frontendSetupPromise;
} catch (e) { } catch (e) {
@ -1580,12 +1587,12 @@ class Display extends EventDispatcher {
this._frontend.setDisabledOverride(!isEnabled); this._frontend.setDisabledOverride(!isEnabled);
} }
async _setupNestedFrontend(isSearchPage) { async _setupNestedFrontend() {
const setupNestedPopupsOptions = ( const setupNestedPopupsOptions = {
(isSearchPage) ? useProxyPopup: this._parentFrameId !== null,
{useProxyPopup: false} : parentPopupId: this._parentPopupId,
{useProxyPopup: true, parentPopupId: this._parentPopupId, parentFrameId: this._parentFrameId} parentFrameId: this._parentFrameId
); };
const {frameId} = await api.frameInformationGet(); const {frameId} = await api.frameInformationGet();

View File

@ -27,13 +27,13 @@ class MediaLoader {
} }
async loadMedia(path, dictionaryName, onLoad, onUnload) { async loadMedia(path, dictionaryName, onLoad, onUnload) {
const token = this.token; const token = this._token;
const data = {onUnload, loaded: false}; const data = {onUnload, loaded: false};
this._loadMediaData.push(data); this._loadMediaData.push(data);
const media = await this.getMedia(path, dictionaryName); const media = await this.getMedia(path, dictionaryName);
if (token !== this.token) { return; } if (token !== this._token) { return; }
onLoad(media.url); onLoad(media.url);
data.loaded = true; data.loaded = true;