123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- import type { Body, Meta, UppyFile } from '@uppy/utils/lib/UppyFile'
- import type { I18n } from '@uppy/utils/lib/Translator'
- import type { Uppy, State } from '@uppy/core/lib/Uppy'
- import { h } from 'preact'
- import classNames from 'classnames'
- import statusBarStates from './StatusBarStates.ts'
- import calculateProcessingProgress from './calculateProcessingProgress.ts'
- import {
- UploadBtn,
- RetryBtn,
- CancelBtn,
- PauseResumeButton,
- DoneBtn,
- ProgressBarProcessing,
- ProgressBarError,
- ProgressBarUploading,
- ProgressBarComplete,
- } from './Components.tsx'
- const {
- STATE_ERROR,
- STATE_WAITING,
- STATE_PREPROCESSING,
- STATE_UPLOADING,
- STATE_POSTPROCESSING,
- STATE_COMPLETE,
- } = statusBarStates
- export interface StatusBarUIProps<M extends Meta, B extends Body> {
- newFiles: number
- allowNewUpload: boolean
- isUploadInProgress: boolean
- isAllPaused: boolean
- resumableUploads: boolean
- error: any
- hideUploadButton?: boolean
- hidePauseResumeButton?: boolean
- hideCancelButton?: boolean
- hideRetryButton?: boolean
- recoveredState: State<M, B>['recoveredState']
- uploadState: (typeof statusBarStates)[keyof typeof statusBarStates]
- totalProgress: number
- files: Record<string, UppyFile<M, B>>
- supportsUploadProgress: boolean
- hideAfterFinish?: boolean
- isSomeGhost: boolean
- doneButtonHandler?: (() => void) | null
- isUploadStarted: boolean
- i18n: I18n
- startUpload: () => void
- uppy: Uppy<M, B>
- isAllComplete: boolean
- showProgressDetails?: boolean
- numUploads: number
- complete: number
- totalSize: number
- totalETA: number
- totalUploadedSize: number
- }
- // TODO: rename the function to StatusBarUI on the next major.
- export default function StatusBar<M extends Meta, B extends Body>(
- props: StatusBarUIProps<M, B>,
- ): JSX.Element {
- const {
- newFiles,
- allowNewUpload,
- isUploadInProgress,
- isAllPaused,
- resumableUploads,
- error,
- hideUploadButton,
- hidePauseResumeButton,
- hideCancelButton,
- hideRetryButton,
- recoveredState,
- uploadState,
- totalProgress,
- files,
- supportsUploadProgress,
- hideAfterFinish,
- isSomeGhost,
- doneButtonHandler,
- isUploadStarted,
- i18n,
- startUpload,
- uppy,
- isAllComplete,
- showProgressDetails,
- numUploads,
- complete,
- totalSize,
- totalETA,
- totalUploadedSize,
- } = props
- function getProgressValue(): number | null {
- switch (uploadState) {
- case STATE_POSTPROCESSING:
- case STATE_PREPROCESSING: {
- const progress = calculateProcessingProgress(files)
- 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
- }
- }
- function getIsIndeterminate(): boolean {
- 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
- }
- }
- function getIsHidden(): boolean | undefined {
- if (recoveredState) {
- return false
- }
- switch (uploadState) {
- case STATE_WAITING:
- return hideUploadButton || newFiles === 0
- case STATE_COMPLETE:
- return hideAfterFinish
- default:
- return false
- }
- }
- const progressValue = getProgressValue()
- const isHidden = getIsHidden()
- const width = progressValue ?? 100
- const showUploadBtn =
- !error &&
- newFiles &&
- !isUploadInProgress &&
- !isAllPaused &&
- allowNewUpload &&
- !hideUploadButton
- const showCancelBtn =
- !hideCancelButton &&
- uploadState !== STATE_WAITING &&
- uploadState !== STATE_COMPLETE
- const showPauseResumeBtn =
- resumableUploads &&
- !hidePauseResumeButton &&
- uploadState === STATE_UPLOADING
- const showRetryBtn = error && !isAllComplete && !hideRetryButton
- const showDoneBtn = doneButtonHandler && uploadState === STATE_COMPLETE
- const progressClassNames = classNames('uppy-StatusBar-progress', {
- 'is-indeterminate': getIsIndeterminate(),
- })
- const statusBarClassNames = classNames(
- 'uppy-StatusBar',
- `is-${uploadState}`,
- { 'has-ghosts': isSomeGhost },
- )
- return (
- <div className={statusBarClassNames} aria-hidden={isHidden}>
- <div
- className={progressClassNames}
- style={{ width: `${width}%` }}
- role="progressbar"
- aria-label={`${width}%`}
- aria-valuetext={`${width}%`}
- aria-valuemin={0}
- aria-valuemax={100}
- aria-valuenow={progressValue!}
- />
- {((): JSX.Element | null => {
- switch (uploadState) {
- case STATE_PREPROCESSING:
- case STATE_POSTPROCESSING:
- return (
- <ProgressBarProcessing
- progress={calculateProcessingProgress(files)}
- />
- )
- case STATE_COMPLETE:
- return <ProgressBarComplete i18n={i18n} />
- case STATE_ERROR:
- return (
- <ProgressBarError
- error={error}
- i18n={i18n}
- numUploads={numUploads}
- complete={complete}
- />
- )
- case STATE_UPLOADING:
- return (
- <ProgressBarUploading
- i18n={i18n}
- supportsUploadProgress={supportsUploadProgress}
- totalProgress={totalProgress}
- showProgressDetails={showProgressDetails}
- isUploadStarted={isUploadStarted}
- isAllComplete={isAllComplete}
- isAllPaused={isAllPaused}
- newFiles={newFiles}
- numUploads={numUploads}
- complete={complete}
- totalUploadedSize={totalUploadedSize}
- totalSize={totalSize}
- totalETA={totalETA}
- startUpload={startUpload}
- />
- )
- default:
- return null
- }
- })()}
- <div className="uppy-StatusBar-actions">
- {recoveredState || showUploadBtn ?
- <UploadBtn
- newFiles={newFiles}
- isUploadStarted={isUploadStarted}
- recoveredState={recoveredState}
- i18n={i18n}
- isSomeGhost={isSomeGhost}
- startUpload={startUpload}
- uploadState={uploadState}
- />
- : null}
- {showRetryBtn ?
- <RetryBtn i18n={i18n} uppy={uppy} />
- : null}
- {showPauseResumeBtn ?
- <PauseResumeButton
- isAllPaused={isAllPaused}
- i18n={i18n}
- isAllComplete={isAllComplete}
- resumableUploads={resumableUploads}
- uppy={uppy}
- />
- : null}
- {showCancelBtn ?
- <CancelBtn i18n={i18n} uppy={uppy} />
- : null}
- {showDoneBtn ?
- <DoneBtn i18n={i18n} doneButtonHandler={doneButtonHandler} />
- : null}
- </div>
- </div>
- )
- }
- StatusBar.defaultProps = {
- doneButtonHandler: undefined,
- hideAfterFinish: false,
- hideCancelButton: false,
- hidePauseResumeButton: false,
- hideRetryButton: false,
- hideUploadButton: undefined,
- showProgressDetails: undefined,
- }
|