common-ui/src/lib/loading/loading.service.ts
2022-06-28 16:46:33 +03:00

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);
}
}