61 lines
1.6 KiB
TypeScript
61 lines
1.6 KiB
TypeScript
import { Injectable, signal } from '@angular/core';
|
|
|
|
const MIN_LOADING_TIME = 300;
|
|
|
|
export interface ILoadingConfig {
|
|
readonly type: 'spinner' | 'progress-bar';
|
|
readonly title?: string;
|
|
readonly value?: number;
|
|
readonly remainingTime?: string;
|
|
}
|
|
|
|
@Injectable()
|
|
export class LoadingService {
|
|
readonly #loading = signal<ILoadingConfig | undefined>(undefined);
|
|
readonly isLoading = this.#loading.asReadonly();
|
|
#loadingStarted = 0;
|
|
#stopTimeout: NodeJS.Timeout | undefined;
|
|
|
|
start(config: ILoadingConfig = { type: 'spinner' }): void {
|
|
if (this.#stopTimeout) {
|
|
clearTimeout(this.#stopTimeout);
|
|
this.#stopTimeout = undefined;
|
|
}
|
|
setTimeout(() => {
|
|
this.#loading.set(config);
|
|
this.#loadingStarted = Date.now();
|
|
});
|
|
}
|
|
|
|
update(config: ILoadingConfig): void {
|
|
if (!this.isLoading()) {
|
|
return this.start(config);
|
|
}
|
|
this.#loading.set(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(),
|
|
);
|
|
}
|
|
|
|
#stop(): void {
|
|
setTimeout(() => this.#loading.set(undefined));
|
|
}
|
|
|
|
#stopAfter(clearAfter: number): void {
|
|
this.#stopTimeout = setTimeout(() => this.#stop(), clearAfter);
|
|
}
|
|
}
|