mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
839bf63b9f
Test Plan: SaaS CI Reviewers: paulfitz Reviewed By: paulfitz Differential Revision: https://phab.getgrist.com/D4351
58 lines
2.4 KiB
TypeScript
58 lines
2.4 KiB
TypeScript
import {IProgress} from 'app/client/models/NotifyModel';
|
|
import {Disposable} from 'grainjs';
|
|
|
|
export class ImportProgress extends Disposable {
|
|
// Import does upload first, then import. We show a single indicator, estimating which fraction
|
|
// of the time should be given to upload (whose progress we can report well), and which to the
|
|
// subsequent import (whose progress indicator is mostly faked).
|
|
private _uploadFraction: number;
|
|
private _estImportSeconds: number;
|
|
|
|
private _importTimer: null | ReturnType<typeof setInterval> = null;
|
|
private _importStart: number = 0;
|
|
|
|
constructor(private _progressUI: IProgress, file: File) {
|
|
super();
|
|
// We'll assume that for .grist files, the upload takes 90% of the total time, and for other
|
|
// files, 40%.
|
|
this._uploadFraction = file.name.endsWith(".grist") ? 0.9 : 0.4;
|
|
|
|
// TODO: Import step should include a progress callback, to be combined with upload progress.
|
|
// Without it, we estimate import to take 2s per MB (non-scientific unreliable estimate), and
|
|
// use an asymptotic indicator which keeps moving without ever finishing. Not terribly useful,
|
|
// but does slow down for larger files, and is more comforting than a stuck indicator.
|
|
this._estImportSeconds = file.size / 1024 / 1024 * 2;
|
|
|
|
this._progressUI.setProgress(0);
|
|
this.onDispose(() => this._importTimer && clearInterval(this._importTimer));
|
|
}
|
|
|
|
// Once this reaches 100, the import stage begins.
|
|
public setUploadProgress(percentage: number) {
|
|
this._progressUI.setProgress(percentage * this._uploadFraction);
|
|
if (percentage >= 100 && !this._importTimer) {
|
|
this._importStart = Date.now();
|
|
this._importTimer = setInterval(() => this._onImportTimer(), 100);
|
|
}
|
|
}
|
|
|
|
public finish() {
|
|
if (this._importTimer) {
|
|
clearInterval(this._importTimer);
|
|
}
|
|
this._progressUI.setProgress(100);
|
|
}
|
|
|
|
/**
|
|
* Calls _progressUI.setProgress(percent) with percentage increasing from 0 and asymptotically
|
|
* approaching 100, reaching 50% after estSeconds. It's intended to look reasonable when the
|
|
* estimate is good, and to keep showing slowing progress even if it's not.
|
|
*/
|
|
private _onImportTimer() {
|
|
const elapsedSeconds = (Date.now() - this._importStart) / 1000;
|
|
const importProgress = elapsedSeconds / (elapsedSeconds + this._estImportSeconds);
|
|
const progress = this._uploadFraction + importProgress * (1 - this._uploadFraction);
|
|
this._progressUI.setProgress(100 * progress);
|
|
}
|
|
}
|