diff --git a/.eslintrc.js b/.eslintrc.js
index 950799469f..27f2f42a47 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -85,7 +85,7 @@ module.exports = {
'no-param-reassign': ['warn'],
'no-redeclare': ['warn'],
'no-shadow': ['warn'],
- 'no-use-before-define': ['warn'],
+ 'no-use-before-define': ['warn', { 'functions': false }],
'radix': ['warn'],
'react/button-has-type': 'error',
'react/destructuring-assignment': ['warn'],
diff --git a/BACKLOG.md b/BACKLOG.md
index e73cf9a67c..7387eba168 100644
--- a/BACKLOG.md
+++ b/BACKLOG.md
@@ -50,7 +50,6 @@ PRs are welcome! Please do open an issue to discuss first if it's a big feature,
- [ ] Display data like image resolution on file cards. should be done by thumbnail generator maybe #783
- [ ] Possibility to edit/delete more than one file at once. example: add copyrigh info to 1000 files #118, #97
- [ ] Possibility to work on already uploaded / in progress files. We'll just provide the `fileId` to the `file-edit-complete` event so that folks can more easily roll out custom code for this themselves #112, #113, #2063
-- [ ] Show upload speed too if `showProgressDetails: true`. Maybe have separate options for which things are displayed, or at least have css-classes that can be hidden with `display: none` #766
- [ ] Focus jumps weirdly if you remove a file https://github.com/transloadit/uppy/pull/2161#issuecomment-613565486
- [ ] A mini UI that features drop & progress (may involve a `mini: true` options for dashboard, may involve drop+progress or new plugin) (@arturi)
- [ ] Add a Load More button so you don't have to TAB endlessly to get to the upload button (https://github.com/transloadit/uppy/issues/1419)
diff --git a/packages/@uppy/dashboard/src/style.scss b/packages/@uppy/dashboard/src/style.scss
index c2d62b197a..c6466a36e8 100644
--- a/packages/@uppy/dashboard/src/style.scss
+++ b/packages/@uppy/dashboard/src/style.scss
@@ -705,11 +705,6 @@
height: 100%;
}
-// Do not show progress details in the StatusBar if we do not have space.
-.uppy-Dashboard:not(.uppy-size--md) .uppy-StatusBar-additionalInfo {
- display: none;
-}
-
.uppy-Dashboard-filesContainer {
@include clearfix;
diff --git a/packages/@uppy/status-bar/src/Components.js b/packages/@uppy/status-bar/src/Components.js
new file mode 100644
index 0000000000..24b8902be5
--- /dev/null
+++ b/packages/@uppy/status-bar/src/Components.js
@@ -0,0 +1,446 @@
+const classNames = require('classnames')
+const throttle = require('lodash.throttle')
+const prettierBytes = require('@transloadit/prettier-bytes')
+const prettyETA = require('@uppy/utils/lib/prettyETA')
+const { h } = require('preact')
+
+const statusBarStates = require('./StatusBarStates')
+
+const DOT = `\u00B7`
+const renderDot = () => ` ${DOT} `
+
+function UploadBtn (props) {
+ const {
+ newFiles,
+ isUploadStarted,
+ recoveredState,
+ i18n,
+ uploadState,
+ isSomeGhost,
+ startUpload,
+ } = props
+
+ const uploadBtnClassNames = classNames(
+ 'uppy-u-reset',
+ 'uppy-c-btn',
+ 'uppy-StatusBar-actionBtn',
+ 'uppy-StatusBar-actionBtn--upload',
+ {
+ 'uppy-c-btn-primary': uploadState === statusBarStates.STATE_WAITING,
+ },
+ { 'uppy-StatusBar-actionBtn--disabled': isSomeGhost }
+ )
+
+ const uploadBtnText
+ = newFiles && isUploadStarted && !recoveredState
+ ? i18n('uploadXNewFiles', { smart_count: newFiles })
+ : i18n('uploadXFiles', { smart_count: newFiles })
+
+ return (
+
+ )
+}
+
+function RetryBtn (props) {
+ const { i18n, uppy } = props
+
+ return (
+
+ )
+}
+
+function CancelBtn (props) {
+ const { i18n, uppy } = props
+
+ return (
+
+ )
+}
+
+function PauseResumeButton (props) {
+ const { isAllPaused, i18n, isAllComplete, resumableUploads, uppy } = props
+ const title = isAllPaused ? i18n('resume') : i18n('pause')
+
+ function togglePauseResume () {
+ if (isAllComplete) return null
+
+ if (!resumableUploads) {
+ return uppy.cancelAll()
+ }
+
+ if (isAllPaused) {
+ return uppy.resumeAll()
+ }
+
+ return uppy.pauseAll()
+ }
+
+ return (
+
+ )
+}
+
+function DoneBtn (props) {
+ const { i18n, doneButtonHandler } = props
+
+ return (
+
+ )
+}
+
+function LoadingSpinner () {
+ return (
+
+ )
+}
+
+function ProgressBarProcessing (props) {
+ const { value, mode, message } = props
+ const roundedValue = Math.round(value * 100)
+ const dot = `\u00B7`
+
+ return (
+
+
+ {mode === 'determinate' ? `${roundedValue}% ${dot} ` : ''}
+ {message}
+
+ )
+}
+
+function ProgressDetails (props) {
+ const {
+ numUploads,
+ complete,
+ totalUploadedSize,
+ totalSize,
+ totalETA,
+ i18n,
+ } = props
+
+ const ifShowFilesUploadedOfTotal = numUploads > 1
+
+ return (
+
+ {ifShowFilesUploadedOfTotal
+ && i18n('filesUploadedOfTotal', {
+ complete,
+ smart_count: numUploads,
+ })}
+
+ {/* When should we render this dot?
+ 1. .-additionalInfo is shown (happens only on desktops)
+ 2. AND 'filesUploadedOfTotal' was shown
+ */}
+ {ifShowFilesUploadedOfTotal && renderDot()}
+
+ {i18n('dataUploadedOfTotal', {
+ complete: prettierBytes(totalUploadedSize),
+ total: prettierBytes(totalSize),
+ })}
+
+ {renderDot()}
+
+ {i18n('xTimeLeft', {
+ time: prettyETA(totalETA),
+ })}
+
+
+ )
+}
+
+function UnknownProgressDetails (props) {
+ const { i18n, complete, numUploads } = props
+
+ return (
+
+ {i18n('filesUploadedOfTotal', { complete, smart_count: numUploads })}
+
+ )
+}
+
+function UploadNewlyAddedFiles (props) {
+ const { i18n, newFiles, startUpload } = props
+ const uploadBtnClassNames = classNames(
+ 'uppy-u-reset',
+ 'uppy-c-btn',
+ 'uppy-StatusBar-actionBtn',
+ 'uppy-StatusBar-actionBtn--uploadNewlyAdded'
+ )
+
+ return (
+
+
+ {i18n('xMoreFilesAdded', { smart_count: newFiles })}
+
+
+
+ )
+}
+
+const ThrottledProgressDetails = throttle(ProgressDetails, 500, {
+ leading: true,
+ trailing: true,
+})
+
+function ProgressBarUploading (props) {
+ const {
+ i18n,
+ supportsUploadProgress,
+ totalProgress,
+ showProgressDetails,
+ isUploadStarted,
+ isAllComplete,
+ isAllPaused,
+ newFiles,
+ numUploads,
+ complete,
+ totalUploadedSize,
+ totalSize,
+ totalETA,
+ startUpload,
+ } = props
+ const showUploadNewlyAddedFiles = newFiles && isUploadStarted
+
+ if (!isUploadStarted || isAllComplete) {
+ return null
+ }
+
+ const title = isAllPaused ? i18n('paused') : i18n('uploading')
+
+ function renderProgressDetails () {
+ if (!isAllPaused && !showUploadNewlyAddedFiles && showProgressDetails) {
+ if (supportsUploadProgress) {
+ return (
+
+ )
+ }
+ return (
+
+ )
+ }
+ return null
+ }
+
+ return (
+
+ {!isAllPaused ?
: null}
+
+
+ {supportsUploadProgress ? `${title}: ${totalProgress}%` : title}
+
+
+ {renderProgressDetails()}
+
+ {showUploadNewlyAddedFiles ? (
+
+ ) : null}
+
+
+ )
+}
+
+function ProgressBarComplete (props) {
+ const { i18n } = props
+
+ return (
+
+
+
+
+ {i18n('complete')}
+
+
+
+ )
+}
+
+function ProgressBarError (props) {
+ const { error, i18n } = props
+
+ function displayErrorAlert () {
+ const errorMessage = `${i18n('uploadFailed')} \n\n ${error}`
+ // eslint-disable-next-line no-alert
+ alert(errorMessage) // TODO: move to custom alert implementation
+ }
+
+ return (
+
+
+
+
+ {i18n('uploadFailed')}
+
+
+
+
+ )
+}
+
+module.exports = {
+ UploadBtn,
+ RetryBtn,
+ CancelBtn,
+ PauseResumeButton,
+ DoneBtn,
+ LoadingSpinner,
+ ProgressDetails,
+ ProgressBarProcessing,
+ ProgressBarError,
+ ProgressBarUploading,
+ ProgressBarComplete,
+}
diff --git a/packages/@uppy/status-bar/src/StatusBar.js b/packages/@uppy/status-bar/src/StatusBar.js
index d87ae6d3d5..bbd412d4bc 100644
--- a/packages/@uppy/status-bar/src/StatusBar.js
+++ b/packages/@uppy/status-bar/src/StatusBar.js
@@ -1,57 +1,32 @@
-const throttle = require('lodash.throttle')
-const classNames = require('classnames')
-const prettierBytes = require('@transloadit/prettier-bytes')
-const prettyETA = require('@uppy/utils/lib/prettyETA')
const { h } = require('preact')
+const classNames = require('classnames')
const statusBarStates = require('./StatusBarStates')
-
-function calculateProcessingProgress (files) {
- // Collect pre or postprocessing progress states.
- const progresses = []
- Object.keys(files).forEach((fileID) => {
- const { progress } = files[fileID]
- if (progress.preprocess) {
- progresses.push(progress.preprocess)
- }
- if (progress.postprocess) {
- progresses.push(progress.postprocess)
- }
- })
-
- // In the future we should probably do this differently. For now we'll take the
- // mode and message from the first file…
- const { mode, message } = progresses[0]
- const value = progresses.filter(isDeterminate).reduce((total, progress, index, all) => {
- return total + progress.value / all.length
- }, 0)
- function isDeterminate (progress) {
- return progress.mode === 'determinate'
- }
-
- return {
- mode,
- message,
- value,
- }
-}
-
-function togglePauseResume (props) {
- if (props.isAllComplete) return
-
- if (!props.resumableUploads) {
- return props.uppy.cancelAll()
- }
-
- if (props.isAllPaused) {
- return props.uppy.resumeAll()
- }
-
- return props.uppy.pauseAll()
-}
-
-module.exports = (props) => {
- props = props || {}
-
+const calculateProcessingProgress = require('./calculateProcessingProgress')
+
+const {
+ UploadBtn,
+ RetryBtn,
+ CancelBtn,
+ PauseResumeButton,
+ DoneBtn,
+ ProgressBarProcessing,
+ ProgressBarError,
+ ProgressBarUploading,
+ ProgressBarComplete,
+} = require('./Components')
+
+const {
+ STATE_ERROR,
+ STATE_WAITING,
+ STATE_PREPROCESSING,
+ STATE_UPLOADING,
+ STATE_POSTPROCESSING,
+ STATE_COMPLETE,
+} = statusBarStates
+
+module.exports = StatusBar
+
+function StatusBar (props) {
const {
newFiles,
allowNewUpload,
@@ -64,68 +39,122 @@ module.exports = (props) => {
hideCancelButton,
hideRetryButton,
recoveredState,
+ uploadState,
+ totalProgress,
+ files,
+ supportsUploadProgress,
+ hideAfterFinish,
+ isSomeGhost,
+ isTargetDOMEl,
+ doneButtonHandler,
+ isUploadStarted,
+ i18n,
+ startUpload,
+ uppy,
+ isAllComplete,
+ showProgressDetails,
+ numUploads,
+ complete,
+ totalSize,
+ totalETA,
+ totalUploadedSize,
} = props
- const { uploadState } = props
+ function getProgressValue () {
+ switch (uploadState) {
+ case STATE_POSTPROCESSING:
+ case STATE_PREPROCESSING: {
+ const progress = calculateProcessingProgress(files)
- let progressValue = props.totalProgress
- let progressMode
- let progressBarContent
+ if (progress.mode === 'determinate') {
+ return progress.value * 100
+ }
+ return totalProgress
+ }
+ case STATE_ERROR: {
+ return null
+ }
+ case STATE_UPLOADING: {
+ if (!supportsUploadProgress) {
+ return null
+ }
+ return totalProgress
+ }
+ default:
+ return totalProgress
+ }
+ }
- if (uploadState === statusBarStates.STATE_PREPROCESSING || uploadState === statusBarStates.STATE_POSTPROCESSING) {
- const progress = calculateProcessingProgress(props.files)
- progressMode = progress.mode
- if (progressMode === 'determinate') {
- progressValue = progress.value * 100
+ function getIsIndeterminate () {
+ switch (uploadState) {
+ case STATE_POSTPROCESSING:
+ case STATE_PREPROCESSING: {
+ const { mode } = calculateProcessingProgress(files)
+ return mode === 'indeterminate'
+ }
+ case STATE_UPLOADING: {
+ if (!supportsUploadProgress) {
+ return true
+ }
+ return false
+ }
+ default:
+ return false
}
+ }
- progressBarContent = ProgressBarProcessing(progress)
- } else if (uploadState === statusBarStates.STATE_COMPLETE) {
- progressBarContent = ProgressBarComplete(props)
- } else if (uploadState === statusBarStates.STATE_UPLOADING) {
- if (!props.supportsUploadProgress) {
- progressMode = 'indeterminate'
- progressValue = null
+ function getIsHidden () {
+ if (recoveredState) {
+ return false
}
- progressBarContent = ProgressBarUploading(props)
- } else if (uploadState === statusBarStates.STATE_ERROR) {
- progressValue = undefined
- progressBarContent = ProgressBarError(props)
+ switch (uploadState) {
+ case STATE_WAITING:
+ return hideUploadButton || newFiles === 0
+ case STATE_COMPLETE:
+ return hideAfterFinish
+ default:
+ return false
+ }
}
- const width = typeof progressValue === 'number' ? progressValue : 100
- let isHidden = (uploadState === statusBarStates.STATE_WAITING && props.hideUploadButton)
- || (uploadState === statusBarStates.STATE_WAITING && !props.newFiles > 0)
- || (uploadState === statusBarStates.STATE_COMPLETE && props.hideAfterFinish)
+ const progressValue = getProgressValue()
- let showUploadBtn = !error && newFiles
- && !isUploadInProgress && !isAllPaused
- && allowNewUpload && !hideUploadButton
+ const isHidden = getIsHidden()
- if (recoveredState) {
- isHidden = false
- showUploadBtn = true
- }
+ const width = progressValue ?? 100
+
+ const showUploadBtn
+ = !error
+ && newFiles
+ && !isUploadInProgress
+ && !isAllPaused
+ && allowNewUpload
+ && !hideUploadButton
- const showCancelBtn = !hideCancelButton
- && uploadState !== statusBarStates.STATE_WAITING
- && uploadState !== statusBarStates.STATE_COMPLETE
- const showPauseResumeBtn = resumableUploads && !hidePauseResumeButton
- && uploadState === statusBarStates.STATE_UPLOADING
+ const showCancelBtn
+ = !hideCancelButton
+ && uploadState !== STATE_WAITING
+ && uploadState !== STATE_COMPLETE
+
+ const showPauseResumeBtn
+ = resumableUploads
+ && !hidePauseResumeButton
+ && uploadState === STATE_UPLOADING
const showRetryBtn = error && !hideRetryButton
- const showDoneBtn = props.doneButtonHandler && uploadState === statusBarStates.STATE_COMPLETE
+ const showDoneBtn = doneButtonHandler && uploadState === STATE_COMPLETE
- const progressClassNames = `uppy-StatusBar-progress
- ${progressMode ? `is-${progressMode}` : ''}`
+ const progressClassNames = classNames('uppy-StatusBar-progress', {
+ 'is-indeterminate': getIsIndeterminate(),
+ })
const statusBarClassNames = classNames(
- { 'uppy-Root': props.isTargetDOMEl },
+ { 'uppy-Root': isTargetDOMEl },
'uppy-StatusBar',
`is-${uploadState}`,
- { 'has-ghosts': props.isSomeGhost }
+ { 'has-ghosts': isSomeGhost }
)
return (
@@ -140,291 +169,75 @@ module.exports = (props) => {
aria-valuemax="100"
aria-valuenow={progressValue}
/>
- {progressBarContent}
-
- {showUploadBtn ?
: null}
- {showRetryBtn ?
: null}
- {showPauseResumeBtn ?
: null}
- {showCancelBtn ?
: null}
- {showDoneBtn ?
: null}
-
-
- )
-}
-
-const UploadBtn = (props) => {
- const uploadBtnClassNames = classNames(
- 'uppy-u-reset',
- 'uppy-c-btn',
- 'uppy-StatusBar-actionBtn',
- 'uppy-StatusBar-actionBtn--upload',
- { 'uppy-c-btn-primary': props.uploadState === statusBarStates.STATE_WAITING },
- { 'uppy-StatusBar-actionBtn--disabled': props.isSomeGhost }
- )
-
- const uploadBtnText = props.newFiles && props.isUploadStarted && !props.recoveredState
- ? props.i18n('uploadXNewFiles', { smart_count: props.newFiles })
- : props.i18n('uploadXFiles', { smart_count: props.newFiles })
-
- return (
-
- )
-}
-
-const RetryBtn = (props) => {
- return (
-
- )
-}
-const CancelBtn = (props) => {
- return (
-
- )
-}
-
-const PauseResumeButton = (props) => {
- const { isAllPaused, i18n } = props
- const title = isAllPaused ? i18n('resume') : i18n('pause')
-
- return (
-
- )
-}
-
-const DoneBtn = (props) => {
- const { i18n } = props
- return (
-
- )
-}
-
-const LoadingSpinner = () => {
- return (
-
- )
-}
-
-const ProgressBarProcessing = (props) => {
- const value = Math.round(props.value * 100)
-
- return (
-
-
- {props.mode === 'determinate' ? `${value}% \u00B7 ` : ''}
- {props.message}
-
- )
-}
-
-const renderDot = () => ' \u00B7 '
-
-const ProgressDetails = (props) => {
- const ifShowFilesUploadedOfTotal = props.numUploads > 1
-
- return (
-
- {
- ifShowFilesUploadedOfTotal
- && props.i18n('filesUploadedOfTotal', {
- complete: props.complete,
- smart_count: props.numUploads,
- })
- }
-
- {/* When should we render this dot?
- 1. .-additionalInfo is shown (happens only on desktops)
- 2. AND 'filesUploadedOfTotal' was shown
- */}
- {ifShowFilesUploadedOfTotal && renderDot()}
-
- {
- props.i18n('dataUploadedOfTotal', {
- complete: prettierBytes(props.totalUploadedSize),
- total: prettierBytes(props.totalSize),
- })
+ {(() => {
+ switch (uploadState) {
+ case STATE_PREPROCESSING:
+ case STATE_POSTPROCESSING:
+ return (
+
+ )
+ case STATE_COMPLETE:
+ return
+ case STATE_ERROR:
+ return
+ case STATE_UPLOADING:
+ return (
+
+ )
+ default:
+ return null
}
+ })()}
- {renderDot()}
-
- {
- props.i18n('xTimeLeft', {
- time: prettyETA(props.totalETA),
- })
- }
-
-
- )
-}
-
-const UnknownProgressDetails = (props) => {
- return (
-
- {props.i18n('filesUploadedOfTotal', { complete: props.complete, smart_count: props.numUploads })}
-
- )
-}
-
-const UploadNewlyAddedFiles = (props) => {
- const uploadBtnClassNames = classNames(
- 'uppy-u-reset',
- 'uppy-c-btn',
- 'uppy-StatusBar-actionBtn',
- 'uppy-StatusBar-actionBtn--uploadNewlyAdded'
- )
-
- return (
-
-
- {props.i18n('xMoreFilesAdded', { smart_count: props.newFiles })}
-
-
-
- )
-}
-
-const ThrottledProgressDetails = throttle(ProgressDetails, 500, { leading: true, trailing: true })
-
-const ProgressBarUploading = (props) => {
- if (!props.isUploadStarted || props.isAllComplete) {
- return null
- }
-
- const title = props.isAllPaused ? props.i18n('paused') : props.i18n('uploading')
- const showUploadNewlyAddedFiles = props.newFiles && props.isUploadStarted
-
- return (
-
- {!props.isAllPaused ?
: null}
-
-
- {props.supportsUploadProgress ? `${title}: ${props.totalProgress}%` : title}
-
- {/* eslint-disable-next-line no-nested-ternary */}
- {!props.isAllPaused && !showUploadNewlyAddedFiles && props.showProgressDetails
- ? (props.supportsUploadProgress ?
:
)
- : null}
- {showUploadNewlyAddedFiles ?
: null}
-
-
- )
-}
-
-const ProgressBarComplete = ({ i18n }) => {
- return (
-
-
-
-
- {i18n('complete')}
-
-
-
- )
-}
-
-const ProgressBarError = ({ error, i18n }) => {
- function displayErrorAlert () {
- const errorMessage = `${i18n('uploadFailed')} \n\n ${error}`
- // eslint-disable-next-line no-alert
- alert(errorMessage) // TODO: move to custom alert implementation
- }
-
- return (
-
-
-
-
- {i18n('uploadFailed')}
-
+
+ {(recoveredState || showUploadBtn) ? (
+
+ ) : null}
+
+ {showRetryBtn ?
: null}
+
+ {showPauseResumeBtn ? (
+
+ ) : null}
+
+ {showCancelBtn ?
: null}
+
+ {showDoneBtn ? (
+
+ ) : null}
-
)
}
diff --git a/packages/@uppy/status-bar/src/calculateProcessingProgress.js b/packages/@uppy/status-bar/src/calculateProcessingProgress.js
new file mode 100644
index 0000000000..2864022fbf
--- /dev/null
+++ b/packages/@uppy/status-bar/src/calculateProcessingProgress.js
@@ -0,0 +1,26 @@
+module.export = function calculateProcessingProgress (files) {
+ const values = []
+ let mode
+ let message
+
+ for (const { progress } of Object.values(files)) {
+ const { preprocess, postprocess } = progress
+ // In the future we should probably do this differently. For now we'll take the
+ // mode and message from the first file…
+ if (message == null && (preprocess || postprocess)) {
+ ({ mode, message } = preprocess || postprocess)
+ }
+ if (preprocess?.mode === 'determinate') values.push(preprocess.value)
+ if (postprocess?.mode === 'determinate') values.push(postprocess.value)
+ }
+
+ const value = values.reduce((total, progressValue) => {
+ return total + progressValue / values.length
+ }, 0)
+
+ return {
+ mode,
+ message,
+ value,
+ }
+}
diff --git a/packages/@uppy/status-bar/src/index.js b/packages/@uppy/status-bar/src/index.js
index a52b47a66e..30ca006ec5 100644
--- a/packages/@uppy/status-bar/src/index.js
+++ b/packages/@uppy/status-bar/src/index.js
@@ -10,7 +10,8 @@ const StatusBarUI = require('./StatusBar')
* progress percentage and time remaining.
*/
module.exports = class StatusBar extends UIPlugin {
- static VERSION = require('../package.json').version
+ // eslint-disable-next-line global-require
+ static VERSION = require('../package.json').version;
constructor (uppy, opts) {
super(uppy, opts)
@@ -72,74 +73,18 @@ module.exports = class StatusBar extends UIPlugin {
this.install = this.install.bind(this)
}
- getTotalSpeed (files) {
- let totalSpeed = 0
- files.forEach((file) => {
- totalSpeed += getSpeed(file.progress)
- })
- return totalSpeed
- }
-
- getTotalETA (files) {
- const totalSpeed = this.getTotalSpeed(files)
- if (totalSpeed === 0) {
- return 0
- }
-
- const totalBytesRemaining = files.reduce((total, file) => {
- return total + getBytesRemaining(file.progress)
- }, 0)
-
- return Math.round(totalBytesRemaining / totalSpeed * 10) / 10
- }
-
startUpload = () => {
const { recoveredState } = this.uppy.getState()
+
if (recoveredState) {
this.uppy.emit('restore-confirmed')
- return
+ return undefined
}
+
return this.uppy.upload().catch(() => {
// Error logged in Core
})
- }
-
- getUploadingState (isAllErrored, isAllComplete, recoveredState, files) {
- if (isAllErrored) {
- return statusBarStates.STATE_ERROR
- }
-
- if (isAllComplete) {
- return statusBarStates.STATE_COMPLETE
- }
-
- if (recoveredState) {
- return statusBarStates.STATE_WAITING
- }
-
- let state = statusBarStates.STATE_WAITING
- const fileIDs = Object.keys(files)
- for (let i = 0; i < fileIDs.length; i++) {
- const { progress } = files[fileIDs[i]]
- // If ANY files are being uploaded right now, show the uploading state.
- if (progress.uploadStarted && !progress.uploadComplete) {
- return statusBarStates.STATE_UPLOADING
- }
- // If files are being preprocessed AND postprocessed at this time, we show the
- // preprocess state. If any files are being uploaded we show uploading.
- if (progress.preprocess && state !== statusBarStates.STATE_UPLOADING) {
- state = statusBarStates.STATE_PREPROCESSING
- }
- // If NO files are being preprocessed or uploaded right now, but some files are
- // being postprocessed, show the postprocess state.
- if (progress.postprocess
- && state !== statusBarStates.STATE_UPLOADING
- && state !== statusBarStates.STATE_PREPROCESSING) {
- state = statusBarStates.STATE_POSTPROCESSING
- }
- }
- return state
- }
+ };
render (state) {
const {
@@ -168,8 +113,10 @@ module.exports = class StatusBar extends UIPlugin {
// If some state was recovered, we want to show Upload button/counter
// for all the files, because in this case it’s not an Upload button,
// but “Confirm Restore Button”
- const newFilesOrRecovered = recoveredState ? Object.values(files) : newFiles
- const totalETA = this.getTotalETA(inProgressNotPausedFiles)
+ const newFilesOrRecovered = recoveredState
+ ? Object.values(files)
+ : newFiles
+ const totalETA = getTotalETA(inProgressNotPausedFiles)
const resumableUploads = !!capabilities.resumableUploads
const supportsUploadProgress = capabilities.uploadProgress !== false
@@ -177,18 +124,23 @@ module.exports = class StatusBar extends UIPlugin {
let totalUploadedSize = 0
startedFiles.forEach((file) => {
- totalSize += (file.progress.bytesTotal || 0)
- totalUploadedSize += (file.progress.bytesUploaded || 0)
+ totalSize += file.progress.bytesTotal || 0
+ totalUploadedSize += file.progress.bytesUploaded || 0
})
return StatusBarUI({
error,
- uploadState: this.getUploadingState(isAllErrored, isAllComplete, recoveredState, state.files || {}),
+ uploadState: getUploadingState(
+ isAllErrored,
+ isAllComplete,
+ recoveredState,
+ state.files || {}
+ ),
allowNewUpload,
totalProgress,
totalSize,
totalUploadedSize,
- isAllComplete,
+ isAllComplete: false,
isAllPaused,
isAllErrored,
isUploadStarted,
@@ -236,3 +188,63 @@ module.exports = class StatusBar extends UIPlugin {
this.unmount()
}
}
+
+function getTotalSpeed (files) {
+ let totalSpeed = 0
+ files.forEach((file) => {
+ totalSpeed += getSpeed(file.progress)
+ })
+ return totalSpeed
+}
+
+function getTotalETA (files) {
+ const totalSpeed = getTotalSpeed(files)
+ if (totalSpeed === 0) {
+ return 0
+ }
+
+ const totalBytesRemaining = files.reduce((total, file) => {
+ return total + getBytesRemaining(file.progress)
+ }, 0)
+
+ return Math.round((totalBytesRemaining / totalSpeed) * 10) / 10
+}
+
+function getUploadingState (isAllErrored, isAllComplete, recoveredState, files) {
+ if (isAllErrored) {
+ return statusBarStates.STATE_ERROR
+ }
+
+ if (isAllComplete) {
+ return statusBarStates.STATE_COMPLETE
+ }
+
+ if (recoveredState) {
+ return statusBarStates.STATE_WAITING
+ }
+
+ let state = statusBarStates.STATE_WAITING
+ const fileIDs = Object.keys(files)
+ for (let i = 0; i < fileIDs.length; i++) {
+ const { progress } = files[fileIDs[i]]
+ // If ANY files are being uploaded right now, show the uploading state.
+ if (progress.uploadStarted && !progress.uploadComplete) {
+ return statusBarStates.STATE_UPLOADING
+ }
+ // If files are being preprocessed AND postprocessed at this time, we show the
+ // preprocess state. If any files are being uploaded we show uploading.
+ if (progress.preprocess && state !== statusBarStates.STATE_UPLOADING) {
+ state = statusBarStates.STATE_PREPROCESSING
+ }
+ // If NO files are being preprocessed or uploaded right now, but some files are
+ // being postprocessed, show the postprocess state.
+ if (
+ progress.postprocess
+ && state !== statusBarStates.STATE_UPLOADING
+ && state !== statusBarStates.STATE_PREPROCESSING
+ ) {
+ state = statusBarStates.STATE_POSTPROCESSING
+ }
+ }
+ return state
+}
diff --git a/packages/@uppy/status-bar/src/style.scss b/packages/@uppy/status-bar/src/style.scss
index ece3152fb2..eea2c756e8 100644
--- a/packages/@uppy/status-bar/src/style.scss
+++ b/packages/@uppy/status-bar/src/style.scss
@@ -6,7 +6,7 @@
position: relative;
z-index: $zIndex-2;
display: flex;
- height: 40px;
+ height: 46px;
color: $white;
font-weight: 400;
font-size: 12px;
@@ -14,10 +14,6 @@
background-color: $white;
transition: height 0.2s;
- .uppy-size--md & {
- height: 46px;
- }
-
[data-uppy-theme="dark"] & {
background-color: $gray-900;
}