import { ComponentPropsWithoutRef, CSSProperties, memo, ReactElement, useMemo, useState, } from 'react'; import {AnimatePresence, m} from 'framer-motion'; import {FileTypeIcon} from '@common/uploads/file-type-icon/file-type-icon'; import {prettyBytes} from '@common/uploads/utils/pretty-bytes'; import {IconButton} from '@common/ui/buttons/icon-button'; import {CloseIcon} from '@common/icons/material/Close'; import {ProgressCircle} from '@common/ui/progress/progress-circle'; import {CheckCircleIcon} from '@common/icons/material/CheckCircle'; import {UploadedFile} from '@common/uploads/uploaded-file'; import {useFileUploadStore} from '@common/uploads/uploader/file-upload-provider'; import {Trans} from '@common/i18n/trans'; import {MixedText} from '@common/i18n/mixed-text'; import {Tooltip} from '@common/ui/tooltip/tooltip'; import {ErrorIcon} from '@common/icons/material/Error'; import {WarningIcon} from '@common/icons/material/Warning'; import {message} from '@common/i18n/message'; interface UploadQueueProps { file: UploadedFile; style: CSSProperties; } export const UploadQueueItem = memo(({file, style}: UploadQueueProps) => { return (
{file.name}
); }); interface SizeInfoProps { file: UploadedFile; } function SizeInfo({file}: SizeInfoProps) { const fileUpload = useFileUploadStore(s => s.fileUploads.get(file.id)); const bytesUploaded = fileUpload?.bytesUploaded || 0; const totalBytes = useMemo(() => prettyBytes(file.size), [file]); const uploadedBytes = useMemo( () => prettyBytes(bytesUploaded), [bytesUploaded] ); let statusMessage: ReactElement; if (fileUpload?.status === 'completed') { statusMessage = ; } else if (fileUpload?.status === 'aborted') { statusMessage = ; } else if (fileUpload?.status === 'failed') { statusMessage = ; } else { statusMessage = ( ); } return
{statusMessage}
; } interface FileStatusProps { file: UploadedFile; } function FileStatus({file}: FileStatusProps) { const fileUpload = useFileUploadStore(s => s.fileUploads.get(file.id)); const abortUpload = useFileUploadStore(s => s.abortUpload); const percentage = fileUpload?.percentage || 0; const status = fileUpload?.status; const errorMessage = fileUpload?.errorMessage; const [isHovered, setIsHovered] = useState(false); const abortButton = ( { abortUpload(file.id); }} > ); const progressButton = ( ); let statusButton: ReactElement; if (status === 'failed') { const errMessage = errorMessage || message('This file could not be uploaded'); statusButton = ( }> ); } else if (status === 'aborted') { statusButton = ( ); } else if (status === 'completed') { statusButton = ( ); } else { statusButton = ( { if (e.pointerType === 'mouse') { setIsHovered(true); } }} onPointerLeave={e => { if (e.pointerType === 'mouse') { setIsHovered(false); } }} > {isHovered ? abortButton : progressButton} ); } return {statusButton}; } interface AnimatedStatusProps extends Omit< ComponentPropsWithoutRef<'div'>, 'onAnimationStart' | 'onDragStart' | 'onDragEnd' | 'onDrag' > { children: ReactElement; } function AnimatedStatus({children, ...domProps}: AnimatedStatusProps) { return ( {children} ); }