import type Uppy from '@uppy/core' import type { Body, Meta, State, UppyFile } from '@uppy/core' import type { I18n } from '@uppy/utils' import classNames from 'classnames' // biome-ignore lint/style/useImportType: h is not a type import { Component, type ComponentChild, h } from 'preact' import { shallowEqualObjects } from 'shallow-equal' import type { DashboardState } from '../../Dashboard.js' import Buttons from './Buttons/index.js' import FileInfo from './FileInfo/index.js' import FilePreviewAndLink from './FilePreviewAndLink/index.js' import FileProgress from './FileProgress/index.js' type Props = { file: UppyFile handleRequestThumbnail: (file: UppyFile) => void handleCancelThumbnail: (file: UppyFile) => void individualCancellation: boolean showRemoveButtonAfterComplete: boolean recoveredState: State['recoveredState'] resumableUploads: boolean i18n: I18n role: string showLinkToFileUploadResult: boolean toggleFileCard: (show: boolean, fileId: string) => void metaFields: DashboardState['metaFields'] id: string containerWidth: number containerHeight: number toggleAddFilesPanel: (show: boolean) => void isSingleFile: boolean hideRetryButton: boolean hideCancelButton: boolean hidePauseResumeButton: boolean canEditFile: (file: UppyFile) => boolean openFileEditor: (file: UppyFile) => void uppy: Uppy } export default class FileItem extends Component< Props > { componentDidMount(): void { const { file } = this.props if (!file.preview) { this.props.handleRequestThumbnail(file) } } shouldComponentUpdate(nextProps: Props): boolean { return !shallowEqualObjects(this.props, nextProps) } // VirtualList mounts FileItems again and they emit `thumbnail:request` // Otherwise thumbnails are broken or missing after Golden Retriever restores files componentDidUpdate(): void { const { file } = this.props if (!file.preview) { this.props.handleRequestThumbnail(file) } } componentWillUnmount(): void { const { file } = this.props if (!file.preview) { this.props.handleCancelThumbnail(file) } } render(): ComponentChild { const { file } = this.props const isProcessing = file.progress.preprocess || file.progress.postprocess const isUploaded = !!file.progress.uploadComplete && !isProcessing && !file.error const uploadInProgressOrComplete = !!file.progress.uploadStarted || !!isProcessing const uploadInProgress = (file.progress.uploadStarted && !file.progress.uploadComplete) || isProcessing const error = file.error || false // File that Golden Retriever was able to partly restore (only meta, not blob), // users still need to re-add it, so it’s a ghost const { isGhost } = file let showRemoveButton = this.props.individualCancellation ? !isUploaded : !uploadInProgress && !isUploaded if (isUploaded && this.props.showRemoveButtonAfterComplete) { showRemoveButton = true } const dashboardItemClass = classNames({ 'uppy-Dashboard-Item': true, 'is-inprogress': uploadInProgress && !this.props.recoveredState, 'is-processing': isProcessing, 'is-complete': isUploaded, 'is-error': !!error, 'is-resumable': this.props.resumableUploads, 'is-noIndividualCancellation': !this.props.individualCancellation, 'is-ghost': isGhost, }) return (
uppy={this.props.uppy} file={file} error={error} isUploaded={isUploaded} hideRetryButton={this.props.hideRetryButton} hideCancelButton={this.props.hideCancelButton} hidePauseResumeButton={this.props.hidePauseResumeButton} recoveredState={this.props.recoveredState} resumableUploads={this.props.resumableUploads} individualCancellation={this.props.individualCancellation} i18n={this.props.i18n} />
) } }