Source: xxe/control/LengthyRemoteCommand.js

class WaitScreen extends XUI.Dialog {
    constructor(message, ownerCmd) {
        super({ title: null, movable: true, resizable: false, closeable: false,
                template: WaitScreen.TEMPLATE, buttons: null });

        this._ownerCmd = ownerCmd;
        
        let pane = this.contentPane.firstElementChild;
        let icon = pane.firstElementChild;
        // With the default xui-alert-icon color.
        icon.textContent = XUI.StockIcon["hourglass"]; 
        
        let msg = pane.lastElementChild;
        if (message.startsWith("<html>")) {
            message = message.substring(6);
        } else {
            message = XUI.Util.escapeHTML(message);
            if (message.indexOf('\n') >= 0) {
                message = message.replaceAll('\n', "<br>");
            }
        }
        msg.innerHTML = message;
    }
    
    open(position, reference) {
        const dialog = super.open(position, reference);
        // Prevent pressing "Escape" from closing this modal splashscreen.
        dialog.removeEventListener("keydown", XUI.Dialogs.onKeydownDialog);
        return dialog;
    }
    
    dialogClosed(result) {
        // Do not attempt to close if already closed.
        this._ownerCmd._waitScreen = null;
    }
}

WaitScreen.TEMPLATE = document.createElement("template");
WaitScreen.TEMPLATE.innerHTML = `
<div class="xui-alert-pane">
  <div class="xui-alert-icon"></div>
  <div class="xui-alert-message"></div>
</div>
`;

/**
 * A {@link RemoteCommand} displaying a <b>Wait</b> modal splashscreen during
 * the execution of a possibly lengthy remote command.
 */
class LengthyRemoteCommand extends RemoteCommand {
    constructor(commandName, waitMessage=null) {
        super(commandName);
        if (!waitMessage) {
            waitMessage = `Executing command "${commandName}".\nPlease wait...`;
        }
        this._waitMessage = waitMessage;
        this._waitScreen = null;
    }
    
    execute(mode, docView, params, event=null) {
        this.stopWaiting();
        
        if (mode === EXECUTE_TEST) {
            return super.execute(mode, docView, params, event);
        }
        
        Command.consumeEvent(event);
        
        this._waitScreen = new WaitScreen(this._waitMessage, this);
        this._waitScreen.open("center", docView);

        let startWaiting = new Promise((resolve, reject) => {
            setTimeout(() => { resolve(true); }, 1000 /*ms*/);
        });

        return startWaiting
            .then((done) => {
                return super.execute(mode, docView, params, event);
            });
            // No need to catch errors here. At worst, RemoteCommand.execute
            // will return a null Promise.
    }
    
    commandExecuted(mode, docView, params, result) {
        this.stopWaiting();
        return super.commandExecuted(mode, docView, params, result);
    }

    stopWaiting() {
        if (this._waitScreen !== null) {
            this._waitScreen.close();
            this._waitScreen = null;
        }
    }
}