|
import { |
|
useCallback, |
|
} from 'react' |
|
import { |
|
RiLink, |
|
RiUploadCloud2Line, |
|
} from '@remixicon/react' |
|
import { useTranslation } from 'react-i18next' |
|
import FileFromLinkOrLocal from '../file-from-link-or-local' |
|
import { |
|
FileContextProvider, |
|
useStore, |
|
} from '../store' |
|
import type { FileEntity } from '../types' |
|
import FileInput from '../file-input' |
|
import { useFile } from '../hooks' |
|
import FileItem from './file-item' |
|
import Button from '@/app/components/base/button' |
|
import cn from '@/utils/classnames' |
|
import type { FileUpload } from '@/app/components/base/features/types' |
|
import { TransferMethod } from '@/types/app' |
|
|
|
type Option = { |
|
value: string |
|
label: string |
|
icon: JSX.Element |
|
} |
|
type FileUploaderInAttachmentProps = { |
|
fileConfig: FileUpload |
|
} |
|
const FileUploaderInAttachment = ({ |
|
fileConfig, |
|
}: FileUploaderInAttachmentProps) => { |
|
const { t } = useTranslation() |
|
const files = useStore(s => s.files) |
|
const { |
|
handleRemoveFile, |
|
handleReUploadFile, |
|
} = useFile(fileConfig) |
|
const options = [ |
|
{ |
|
value: TransferMethod.local_file, |
|
label: t('common.fileUploader.uploadFromComputer'), |
|
icon: <RiUploadCloud2Line className='w-4 h-4' />, |
|
}, |
|
{ |
|
value: TransferMethod.remote_url, |
|
label: t('common.fileUploader.pasteFileLink'), |
|
icon: <RiLink className='w-4 h-4' />, |
|
}, |
|
] |
|
|
|
const renderButton = useCallback((option: Option, open?: boolean) => { |
|
return ( |
|
<Button |
|
key={option.value} |
|
variant='tertiary' |
|
className={cn('grow relative', open && 'bg-components-button-tertiary-bg-hover')} |
|
disabled={!!(fileConfig.number_limits && files.length >= fileConfig.number_limits)} |
|
> |
|
{option.icon} |
|
<span className='ml-1'>{option.label}</span> |
|
{ |
|
option.value === TransferMethod.local_file && ( |
|
<FileInput fileConfig={fileConfig} /> |
|
) |
|
} |
|
</Button> |
|
) |
|
}, [fileConfig, files.length]) |
|
const renderTrigger = useCallback((option: Option) => { |
|
return (open: boolean) => renderButton(option, open) |
|
}, [renderButton]) |
|
const renderOption = useCallback((option: Option) => { |
|
if (option.value === TransferMethod.local_file && fileConfig?.allowed_file_upload_methods?.includes(TransferMethod.local_file)) |
|
return renderButton(option) |
|
|
|
if (option.value === TransferMethod.remote_url && fileConfig?.allowed_file_upload_methods?.includes(TransferMethod.remote_url)) { |
|
return ( |
|
<FileFromLinkOrLocal |
|
key={option.value} |
|
showFromLocal={false} |
|
trigger={renderTrigger(option)} |
|
fileConfig={fileConfig} |
|
/> |
|
) |
|
} |
|
}, [renderButton, renderTrigger, fileConfig]) |
|
|
|
return ( |
|
<div> |
|
<div className='flex items-center space-x-1'> |
|
{options.map(renderOption)} |
|
</div> |
|
<div className='mt-1 space-y-1'> |
|
{ |
|
files.map(file => ( |
|
<FileItem |
|
key={file.id} |
|
file={file} |
|
showDeleteAction |
|
showDownloadAction={false} |
|
onRemove={() => handleRemoveFile(file.id)} |
|
onReUpload={() => handleReUploadFile(file.id)} |
|
/> |
|
)) |
|
} |
|
</div> |
|
</div> |
|
) |
|
} |
|
|
|
type FileUploaderInAttachmentWrapperProps = { |
|
value?: FileEntity[] |
|
onChange: (files: FileEntity[]) => void |
|
fileConfig: FileUpload |
|
} |
|
const FileUploaderInAttachmentWrapper = ({ |
|
value, |
|
onChange, |
|
fileConfig, |
|
}: FileUploaderInAttachmentWrapperProps) => { |
|
return ( |
|
<FileContextProvider |
|
value={value} |
|
onChange={onChange} |
|
> |
|
<FileUploaderInAttachment fileConfig={fileConfig} /> |
|
</FileContextProvider> |
|
) |
|
} |
|
|
|
export default FileUploaderInAttachmentWrapper |
|
|