Vmeda.Online/src/core/classes/ion-loading.ts

168 lines
4.4 KiB
TypeScript

// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { CoreUtils } from '@services/utils/utils';
import { LoadingController } from '@singletons';
/**
* Dismiss listener.
*/
export type CoreIonLoadingElementDismissListener = () => unknown;
/**
* Class to improve the behaviour of HTMLIonLoadingElement.
*
* In addition to present/dismiss, this loader can also be paused/resumed in order to allow stacking
* modals in top of one another without interfering. Conceptually, a paused loader is still
* active but will not be shown in the UI.
*/
export class CoreIonLoadingElement {
protected scheduled = false;
protected paused = false;
protected listeners: CoreIonLoadingElementDismissListener[] = [];
protected asyncLoadingElement?: Promise<HTMLIonLoadingElement>;
constructor(protected text?: string) { }
/**
* Dismiss the loading element.
*
* @param data Dismiss data.
* @param role Dismiss role.
*/
async dismiss(data?: unknown, role?: string): Promise<void> {
if (this.paused) {
this.paused = false;
this.listeners.forEach(listener => listener());
return;
}
if (!this.asyncLoadingElement) {
if (this.scheduled) {
this.scheduled = false;
this.listeners.forEach(listener => listener());
}
return;
}
const asyncLoadingElement = this.asyncLoadingElement;
delete this.asyncLoadingElement;
const loadingElement = await asyncLoadingElement;
await loadingElement.dismiss(data, role);
this.listeners.forEach(listener => listener());
}
/**
* Register dismiss listener.
*
* @param listener Listener.
*/
onDismiss(listener: CoreIonLoadingElementDismissListener): void {
this.listeners.push(listener);
}
/**
* Hide the loading element.
*/
async pause(): Promise<void> {
if (!this.asyncLoadingElement) {
return;
}
this.paused = true;
const asyncLoadingElement = this.asyncLoadingElement;
delete this.asyncLoadingElement;
const loadingElement = await asyncLoadingElement;
loadingElement.dismiss();
}
/**
* Present the loading element.
*/
async present(): Promise<void> {
if (this.paused || this.scheduled || this.asyncLoadingElement) {
return;
}
// Wait a bit before presenting the modal, to prevent it being displayed if dismiss is called fast.
this.scheduled = true;
await CoreUtils.wait(40);
if (!this.scheduled) {
return;
}
// Present modal.
this.scheduled = false;
await this.presentLoadingElement();
}
/**
* Show loading element.
*/
async resume(): Promise<void> {
if (!this.paused) {
return;
}
this.paused = false;
await this.presentLoadingElement();
}
/**
* Update text in the loading element.
*
* @param text Text.
*/
async updateText(text: string): Promise<void> {
this.text = text;
if (!this.asyncLoadingElement) {
return;
}
const loadingElement = await this.asyncLoadingElement;
const contentElement = loadingElement.querySelector('.loading-content');
if (contentElement) {
contentElement.innerHTML = text;
}
}
/**
* Create and present the loading element.
*/
private async presentLoadingElement(): Promise<void> {
let resolveLoadingElement!: ((loadingElement: HTMLIonLoadingElement) => void);
this.asyncLoadingElement = new Promise(resolve => resolveLoadingElement = resolve);
const loadingElement = await LoadingController.create({ message: this.text });
await loadingElement.present();
resolveLoadingElement(loadingElement);
}
}