common-ui/src/lib/loading/loading.service.ts

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