Refactor Popup.complete to async

This commit is contained in:
Wolfsblvt 2024-06-30 20:44:29 +02:00
parent aff4138263
commit da968e127b
4 changed files with 38 additions and 30 deletions

View File

@ -641,14 +641,14 @@ async function showExtensionsDetails() {
action: async () => {
requiresReload = true;
await autoUpdateExtensions(true);
popup.complete(POPUP_RESULT.AFFIRMATIVE);
await popup.complete(POPUP_RESULT.AFFIRMATIVE);
},
};
// If we are updating an extension, the "old" popup is still active. We should close that.
const oldPopup = Popup.util.popups.find(popup => popup.content.querySelector('.extensions_info'));
if (oldPopup) {
oldPopup.complete(POPUP_RESULT.CANCELLED);
await oldPopup.complete(POPUP_RESULT.CANCELLED);
}
const popup = new Popup(`<div class="extensions_info">${html}</div>`, POPUP_TYPE.TEXT, '', { okButton: 'Close', wide: true, large: true, customButtons: [updateAllButton], allowVerticalScrolling: true });

View File

@ -6,7 +6,7 @@ const ELEMENT_ID = 'loader';
let loaderPopup;
export function showLoader() {
// Two loaders don't make sense
// Two loaders don't make sense. Don't await, we can overlay the old loader while it closes
if (loaderPopup) loaderPopup.complete(POPUP_RESULT.CANCELLED);
loaderPopup = new Popup(`
@ -23,24 +23,28 @@ export function showLoader() {
export async function hideLoader() {
if (!loaderPopup) {
console.warn('There is no loader showing to hide');
return;
return Promise.resolve();
}
//Sets up a 2-step animation. Spinner blurs/fades out, and then the loader shadow does the same.
$('#load-spinner').on('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function () {
$(`#${ELEMENT_ID}`)
//only fade out the spinner and replace with login screen
.animate({ opacity: 0 }, 300, function () {
$(`#${ELEMENT_ID}`).remove();
loaderPopup.complete(POPUP_RESULT.AFFIRMATIVE);
loaderPopup = null;
});
});
$('#load-spinner')
.css({
'filter': 'blur(15px)',
'opacity': '0',
return new Promise((resolve) => {
//Sets up a 2-step animation. Spinner blurs/fades out, and then the loader shadow does the same.
$('#load-spinner').on('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function () {
$(`#${ELEMENT_ID}`)
//only fade out the spinner and replace with login screen
.animate({ opacity: 0 }, 300, function () {
$(`#${ELEMENT_ID}`).remove();
loaderPopup.complete(POPUP_RESULT.AFFIRMATIVE).then(() => {
loaderPopup = null;
resolve();
});
});
});
$('#load-spinner')
.css({
'filter': 'blur(15px)',
'opacity': '0',
});
});
}

View File

@ -98,7 +98,7 @@ const showPopupHelper = {
const result = await popup.show();
if (typeof result === 'string' || typeof result === 'boolean') throw new Error(`Invalid popup result. CONFIRM popups only support numbers, or null. Result: ${result}`);
return result;
}
},
};
export class Popup {
@ -210,7 +210,7 @@ export class Popup {
this.customInputs = customInputs;
this.customInputs?.forEach(input => {
if (!input.id || !(typeof input.id === 'string')) {
console.warn('Given custom input does not have a valid id set')
console.warn('Given custom input does not have a valid id set');
return;
}
@ -318,20 +318,20 @@ export class Popup {
if (String(undefined) === String(resultControl.dataset.result)) return;
if (isNaN(result)) throw new Error('Invalid result control. Result must be a number. ' + resultControl.dataset.result);
const type = resultControl.dataset.resultEvent || 'click';
resultControl.addEventListener(type, () => this.complete(result));
resultControl.addEventListener(type, async () => await this.complete(result));
});
// Bind dialog listeners manually, so we can be sure context is preserved
const cancelListener = (evt) => {
this.complete(POPUP_RESULT.CANCELLED);
const cancelListener = async (evt) => {
evt.preventDefault();
evt.stopPropagation();
await this.complete(POPUP_RESULT.CANCELLED);
window.removeEventListener('cancel', cancelListenerBound);
};
const cancelListenerBound = cancelListener.bind(this);
this.dlg.addEventListener('cancel', cancelListenerBound);
const keyListener = (evt) => {
const keyListener = async (evt) => {
switch (evt.key) {
case 'Enter': {
// CTRL+Enter counts as a closing action, but all other modifiers (ALT, SHIFT) should not trigger this
@ -347,10 +347,10 @@ export class Popup {
if (!resultControl)
return;
const result = Number(document.activeElement.getAttribute('data-result') ?? this.defaultResult);
this.complete(result);
evt.preventDefault();
evt.stopPropagation();
const result = Number(document.activeElement.getAttribute('data-result') ?? this.defaultResult);
await this.complete(result);
window.removeEventListener('keydown', keyListenerBound);
break;
@ -430,8 +430,10 @@ export class Popup {
* - All other will return the result value as provided as `POPUP_RESULT` or a custom number value
*
* @param {POPUP_RESULT|number} result - The result of the popup (either an existing `POPUP_RESULT` or a custom result value)
*
* @returns {Promise<string|number|boolean?>} A promise that resolves with the value of the popup when it is completed.
*/
complete(result) {
async complete(result) {
// In all cases besides INPUT the popup value should be the result
/** @type {POPUP_RESULT|number|boolean|string?} */
let value = result;
@ -468,6 +470,8 @@ export class Popup {
Popup.util.lastResult = { value, result, inputResults: this.inputResults };
this.#hide();
return this.#promise;
}
/**

View File

@ -1653,8 +1653,8 @@ async function buttonsCallback(args, text) {
const buttonElement = document.createElement('div');
buttonElement.classList.add('menu_button', 'result-control', 'wide100p');
buttonElement.dataset.result = String(result);
buttonElement.addEventListener('click', () => {
popup?.complete(result);
buttonElement.addEventListener('click', async () => {
await popup.complete(result);
});
buttonElement.innerText = button;
buttonContainer.appendChild(buttonElement);