From 8ece95fd2f3336261150b20891fda26d3972913b Mon Sep 17 00:00:00 2001 From: Jannik Stehle Date: Tue, 7 Jun 2022 16:38:23 +0200 Subject: [PATCH] Implement an upload progress estimation --- .../web-runtime/src/components/UploadInfo.vue | 89 +++++++++++++++++-- .../web-runtime/src/services/uppyService.ts | 4 + 2 files changed, 84 insertions(+), 9 deletions(-) diff --git a/packages/web-runtime/src/components/UploadInfo.vue b/packages/web-runtime/src/components/UploadInfo.vue index 19fa25120c6..b57574df2d4 100644 --- a/packages/web-runtime/src/components/UploadInfo.vue +++ b/packages/web-runtime/src/components/UploadInfo.vue @@ -18,14 +18,11 @@ -
- +
+
+ + +
{ this.runningUploads -= 1 + + if (!this.runningUploads) { + this.resetProgress() + } }) this.$uppyService.subscribe('progress', (value) => { this.totalProgress = value }) + this.$uppyService.subscribe('upload-progress', ({ file, progress }) => { + if (!Object.keys(this.filesInEstimation).length) { + this.timeStarted = new Date() + this.remainingTime = this.$gettext('Calculating estimated time...') + } + + if (this.filesInEstimation[file.meta.uploadId] === undefined) { + this.filesInEstimation[file.meta.uploadId] = 0 + this.bytesTotal += progress.bytesTotal + } + + const byteIncrease = progress.bytesUploaded - this.filesInEstimation[file.meta.uploadId] + this.bytesUploaded += byteIncrease + this.filesInEstimation[file.meta.uploadId] = progress.bytesUploaded + + const timeElapsed = new Date() - this.timeStarted + const progressPercent = (100 * this.bytesUploaded) / this.bytesTotal + const totalTimeNeededInMilliseconds = (timeElapsed / progressPercent) * 100 + const remainingMilliseconds = totalTimeNeededInMilliseconds - timeElapsed + + this.remainingTime = this.getRemainingTime(remainingMilliseconds) + }) this.$uppyService.subscribe('uploadError', (file) => { if (this.errors.includes(file.meta.uploadId)) { return @@ -301,6 +330,38 @@ export default { }) }, methods: { + getRemainingTime(remainingMilliseconds) { + const roundedRemainingSeconds = Math.round(remainingMilliseconds / 1000) + if (roundedRemainingSeconds >= 30 && roundedRemainingSeconds < 60) { + return this.$gettext('1 minute left') + } + + const roundedRemainingMinutes = Math.round(remainingMilliseconds / 1000 / 60) + if (roundedRemainingMinutes >= 1 && roundedRemainingMinutes < 60) { + return this.$gettextInterpolate( + this.$ngettext( + '%{ roundedRemainingMinutes } minute left', + '%{ roundedRemainingMinutes } minutes left', + roundedRemainingMinutes + ), + { roundedRemainingMinutes } + ) + } + + const roundedRemainingHours = Math.round(remainingMilliseconds / 1000 / 60 / 60) + if (roundedRemainingHours > 0) { + return this.$gettextInterpolate( + this.$ngettext( + '%{ roundedRemainingHours } hour left', + '%{ roundedRemainingHours } hours left', + roundedRemainingHours + ), + { roundedRemainingHours } + ) + } + + return this.$gettext('Few seconds left') + }, handleTopLevelFolderUpdate(file, status) { const topLevelFolder = this.uploads[file.meta.topLevelFolderId] if (status === 'success') { @@ -318,6 +379,7 @@ export default { this.showInfo = false this.infoExpanded = false this.cleanOverlay() + this.resetProgress() }, cleanOverlay() { this.uploadsCancelled = false @@ -327,6 +389,14 @@ export default { this.filesInProgressCount = 0 this.runningUploads = 0 }, + resetProgress() { + this.bytesTotal = 0 + this.bytesUploaded = 0 + this.filesInEstimation = {} + this.estimatedTime = 0 + this.timeStarted = null + this.remainingTime = undefined + }, displayFileAsResource(file) { return !!file.targetRoute }, @@ -402,6 +472,7 @@ export default { this.uploadsCancelled = true this.filesInProgressCount = 0 this.runningUploads = 0 + this.resetProgress() this.$uppyService.cancelAllUploads() const runningUploads = Object.values(this.uploads).filter( (u) => u.status !== 'success' && u.status !== 'error' diff --git a/packages/web-runtime/src/services/uppyService.ts b/packages/web-runtime/src/services/uppyService.ts index 219edf37fa8..535c8196f57 100644 --- a/packages/web-runtime/src/services/uppyService.ts +++ b/packages/web-runtime/src/services/uppyService.ts @@ -17,6 +17,7 @@ type UppyServiceTopics = | 'filesSelected' | 'progress' | 'addedForUpload' + | 'upload-progress' export class UppyService { uppy: Uppy @@ -137,6 +138,9 @@ export class UppyService { this.uppy.on('progress', (value) => { this.publish('progress', value) }) + this.uppy.on('upload-progress', (file, progress) => { + this.publish('upload-progress', { file, progress }) + }) this.uppy.on('cancel-all', () => { this.publish('uploadCancelled') })