import { HttpEvent } from "@angular/common/http"; import { Observable } from "rxjs"; import { distinctUntilChanged, scan } from "rxjs/operators"; import { isHttpProgressEvent, isHttpResponse } from "./http"; export interface Upload { progress: number; state: "PENDING" | "IN_PROGRESS" | "DONE"; } export function upload(): ( source: Observable<HttpEvent<unknown>> ) => Observable<Upload> { const initialState: Upload = { state: "PENDING", progress: 0 }; const reduceState = (state: Upload, event: HttpEvent<unknown>): Upload => { if (isHttpProgressEvent(event)) { return { progress: event.total ? Math.round((100 * event.loaded) / event.total) : state.progress, state: "IN_PROGRESS", }; } if (isHttpResponse(event)) { return { progress: 100, state: "DONE", }; } return state; }; return (source) => source.pipe( scan(reduceState, initialState), distinctUntilChanged( (a, b) => a.state === b.state && a.progress === b.progress ) ); }