62 lines
1.7 KiB
TypeScript
62 lines
1.7 KiB
TypeScript
import { Injectable } from '@angular/core';
|
|
import { BehaviorSubject } from 'rxjs';
|
|
|
|
const MIN_LOADING_TIME = 300;
|
|
|
|
export interface ILoadingConfig {
|
|
readonly type: 'spinner' | 'progress-bar';
|
|
readonly title?: string;
|
|
readonly value?: number;
|
|
readonly remainingTime?: string;
|
|
}
|
|
|
|
@Injectable({ providedIn: 'root' })
|
|
export class LoadingService {
|
|
readonly #loadingEvent$ = new BehaviorSubject<ILoadingConfig | undefined>(undefined);
|
|
readonly isLoading$ = this.#loadingEvent$.asObservable();
|
|
#loadingStarted = 0;
|
|
#timeout?: number;
|
|
|
|
start(config: ILoadingConfig = { type: 'spinner' }): void {
|
|
if (this.#timeout) {
|
|
clearTimeout(this.#timeout);
|
|
this.#timeout = undefined;
|
|
}
|
|
setTimeout(() => {
|
|
this.#loadingEvent$.next(config);
|
|
this.#loadingStarted = new Date().getTime();
|
|
});
|
|
}
|
|
|
|
update(config: ILoadingConfig): void {
|
|
if (!this.#loadingEvent$.value) {
|
|
return this.start(config);
|
|
}
|
|
this.#loadingEvent$.next(config);
|
|
}
|
|
|
|
stop(): void {
|
|
const timeSinceStarted = new Date().getTime() - this.#loadingStarted;
|
|
const remainingLoadingTime = MIN_LOADING_TIME - timeSinceStarted;
|
|
|
|
return remainingLoadingTime > 0 ? this._stopAfter(remainingLoadingTime) : this._stop();
|
|
}
|
|
|
|
loadWhile(func: Promise<unknown>): void {
|
|
this.start();
|
|
|
|
func.then(
|
|
() => this.stop(),
|
|
() => this.stop(),
|
|
);
|
|
}
|
|
|
|
private _stop(): void {
|
|
setTimeout(() => this.#loadingEvent$.next(undefined));
|
|
}
|
|
|
|
private _stopAfter(timeout: number): void {
|
|
this.#timeout = window.setTimeout(() => this._stop(), timeout);
|
|
}
|
|
}
|