diff --git a/web/app/components/base/file-uploader/file-uploader-in-attachment/file-in-attachment-item.tsx b/web/app/components/base/file-uploader/file-uploader-in-attachment/file-item.tsx similarity index 58% rename from web/app/components/base/file-uploader/file-uploader-in-attachment/file-in-attachment-item.tsx rename to web/app/components/base/file-uploader/file-uploader-in-attachment/file-item.tsx index 621fbca6c0..00fbf402dc 100644 --- a/web/app/components/base/file-uploader/file-uploader-in-attachment/file-in-attachment-item.tsx +++ b/web/app/components/base/file-uploader/file-uploader-in-attachment/file-item.tsx @@ -1,8 +1,9 @@ import { memo } from 'react' -import { RiDeleteBinLine } from '@remixicon/react' +import { + RiDeleteBinLine, + RiDownloadLine, +} from '@remixicon/react' import FileTypeIcon from '../file-type-icon' -import type { FileEntity } from '../types' -import { useFile } from '../hooks' import { getFileAppearanceType, getFileExtension, @@ -16,35 +17,46 @@ import cn from '@/utils/classnames' import { ReplayLine } from '@/app/components/base/icons/src/vender/other' type FileInAttachmentItemProps = { - file: FileEntity + fileId: string + file: File + imageUrl?: string + progress?: number + showDeleteAction?: boolean + showDownloadAction?: boolean + onRemove?: (fileId: string) => void + onReUpload?: (fileId: string) => void } const FileInAttachmentItem = ({ + fileId, file, + imageUrl, + progress = 0, + showDeleteAction, + showDownloadAction = true, + onRemove, + onReUpload, }: FileInAttachmentItemProps) => { - const { - handleRemoveFile, - handleReUploadFile, - } = useFile() - const ext = getFileExtension(file.file) + const isImageFile = isImage(file) + const ext = getFileExtension(file) return (
{ - isImage(file?.file) && ( + isImageFile && ( ) } { - !isImage(file.file) && ( + !isImageFile && ( ) @@ -53,9 +65,9 @@ const FileInAttachmentItem = ({
- {file.file?.name} + {file.name}
{ @@ -64,31 +76,44 @@ const FileInAttachmentItem = ({ ) } - {formatFileSize(file.file?.size || 0)} + {formatFileSize(file.size || 0)}
{ - file.progress >= 0 && file.progress < 100 && ( + progress > 0 && progress < 100 && ( ) } { - file.progress === -1 && ( + progress === -1 && ( handleReUploadFile(file.id)} + onClick={() => onReUpload?.(fileId)} > ) } - handleRemoveFile(file.id)}> - - + { + showDeleteAction && ( + onRemove?.(fileId)}> + + + ) + } + { + showDownloadAction && ( + + + + ) + }
) diff --git a/web/app/components/base/file-uploader/file-uploader-in-attachment/index.tsx b/web/app/components/base/file-uploader/file-uploader-in-attachment/index.tsx index 494a1101ae..c451746f06 100644 --- a/web/app/components/base/file-uploader/file-uploader-in-attachment/index.tsx +++ b/web/app/components/base/file-uploader/file-uploader-in-attachment/index.tsx @@ -13,7 +13,8 @@ import { } from '../store' import type { FileEntity } from '../types' import FileInput from '../file-input' -import FileInAttachmentItem from './file-in-attachment-item' +import { useFile } from '../hooks' +import FileItem from './file-item' import Button from '@/app/components/base/button' import cn from '@/utils/classnames' @@ -25,6 +26,10 @@ type Option = { const FileUploaderInAttachment = () => { const { t } = useTranslation() const files = useStore(s => s.files) + const { + handleRemoveFile, + handleReUploadFile, + } = useFile() const options = [ { value: 'local', @@ -81,9 +86,16 @@ const FileUploaderInAttachment = () => {
{ files.map(file => ( - handleRemoveFile(file.fileId)} + onReUpload={() => handleReUploadFile(file.fileId)} /> )) } diff --git a/web/app/components/base/file-uploader/file-uploader-in-chat-input/file-image-item.tsx b/web/app/components/base/file-uploader/file-uploader-in-chat-input/file-image-item.tsx index 2b0a86120d..a1095fefe7 100644 --- a/web/app/components/base/file-uploader/file-uploader-in-chat-input/file-image-item.tsx +++ b/web/app/components/base/file-uploader/file-uploader-in-chat-input/file-image-item.tsx @@ -1,37 +1,46 @@ import { RiCloseLine } from '@remixicon/react' import FileImageRender from '../file-image-render' -import type { FileEntity } from '../types' -import { useFile } from '../hooks' import Button from '@/app/components/base/button' import ProgressCircle from '@/app/components/base/progress-bar/progress-circle' import { ReplayLine } from '@/app/components/base/icons/src/vender/other' type FileImageItemProps = { - file: FileEntity - className?: string + fileId: string + imageUrl?: string + progress?: number + showDeleteAction?: boolean + onRemove?: (fileId: string) => void + onReUpload?: (fileId: string) => void } const FileImageItem = ({ - file, + fileId, + imageUrl, + progress = 0, + showDeleteAction, + onRemove, + onReUpload, }: FileImageItemProps) => { - const { handleRemoveFile } = useFile() - return (
- + { + showDeleteAction && ( + + ) + } { - file.progress > 0 && file.progress < 100 && ( + progress > 0 && progress < 100 && (
- + onReUpload?.(fileId)} + />
) } diff --git a/web/app/components/base/file-uploader/file-uploader-in-chat-input/file-item.tsx b/web/app/components/base/file-uploader/file-uploader-in-chat-input/file-item.tsx index 853f618587..38af9d0136 100644 --- a/web/app/components/base/file-uploader/file-uploader-in-chat-input/file-item.tsx +++ b/web/app/components/base/file-uploader/file-uploader-in-chat-input/file-item.tsx @@ -2,12 +2,10 @@ import { RiCloseLine, RiDownloadLine, } from '@remixicon/react' -import type { FileEntity } from '../types' import { getFileAppearanceType, getFileExtension, } from '../utils' -import { useFile } from '../hooks' import FileTypeIcon from '../file-type-icon' import cn from '@/utils/classnames' import { formatFileSize } from '@/utils/format' @@ -17,17 +15,25 @@ import ActionButton from '@/app/components/base/action-button' import Button from '@/app/components/base/button' type FileItemProps = { - file: FileEntity - showDownload?: boolean - className?: string + fileId: string + file: File + progress?: number + showDeleteAction?: boolean + showDownloadAction?: boolean + onRemove?: (fileId: string) => void + onReUpload?: (fileId: string) => void } const FileItem = ({ + fileId, file, - showDownload, + progress = 0, + showDeleteAction, + showDownloadAction = true, + onRemove, + onReUpload, }: FileItemProps) => { - const { handleRemoveFile } = useFile() - const ext = getFileExtension(file.file) - const uploadError = file.progress === -1 + const ext = getFileExtension(file) + const uploadError = progress === -1 return (
- + { + showDeleteAction && ( + + ) + }
- {file.file?.name} + {file.name}
{ @@ -62,10 +72,10 @@ const FileItem = ({ ) } - {formatFileSize(file.file?.size || 0)} + {formatFileSize(file.size || 0)}
{ - showDownload && ( + showDownloadAction && ( @@ -74,17 +84,18 @@ const FileItem = ({ ) } { - file.progress > 0 && file.progress < 100 && ( + progress > 0 && progress < 100 && ( ) } { - file.progress === -1 && ( + uploadError && ( onReUpload?.(fileId)} /> ) } diff --git a/web/app/components/base/file-uploader/file-uploader-in-chat-input/file-list.tsx b/web/app/components/base/file-uploader/file-uploader-in-chat-input/file-list.tsx index 33fd4443e8..870de729dc 100644 --- a/web/app/components/base/file-uploader/file-uploader-in-chat-input/file-list.tsx +++ b/web/app/components/base/file-uploader/file-uploader-in-chat-input/file-list.tsx @@ -1,10 +1,15 @@ import { isImage } from '../utils' +import { useFile } from '../hooks' import { useStore } from '../store' import FileImageItem from './file-image-item' import FileItem from './file-item' const FileList = () => { const files = useStore(s => s.files) + const { + handleRemoveFile, + handleReUploadFile, + } = useFile() return (
@@ -13,16 +18,27 @@ const FileList = () => { if (isImage(file.file)) { return ( ) } return ( ) }) diff --git a/web/app/components/base/file-uploader/hooks.ts b/web/app/components/base/file-uploader/hooks.ts index 1be14aaccd..1bec18265c 100644 --- a/web/app/components/base/file-uploader/hooks.ts +++ b/web/app/components/base/file-uploader/hooks.ts @@ -25,7 +25,7 @@ export const useFile = () => { } = fileStore.getState() const newFiles = produce(files, (draft) => { - const index = draft.findIndex(file => file.id === newFile.id) + const index = draft.findIndex(file => file.fileId === newFile.fileId) if (index > -1) draft[index] = newFile @@ -41,7 +41,7 @@ export const useFile = () => { setFiles, } = fileStore.getState() - const newFiles = files.filter(file => file.id !== fileId) + const newFiles = files.filter(file => file.fileId !== fileId) setFiles(newFiles) }, [fileStore]) @@ -50,7 +50,7 @@ export const useFile = () => { files, setFiles, } = fileStore.getState() - const index = files.findIndex(file => file.id === fileId) + const index = files.findIndex(file => file.fileId === fileId) if (index > -1) { const uploadingFile = files[index] @@ -94,7 +94,7 @@ export const useFile = () => { 'load', () => { const uploadingFile = { - id: uuid4(), + fileId: uuid4(), file, url: '', progress: 0, @@ -107,7 +107,7 @@ export const useFile = () => { handleAddOrUpdateFiles({ ...uploadingFile, progress }) }, onSuccessCallback: (res) => { - handleAddOrUpdateFiles({ ...uploadingFile, fileId: res.id, progress: 100 }) + handleAddOrUpdateFiles({ ...uploadingFile, fileStorageId: res.id, progress: 100 }) }, onErrorCallback: () => { notify({ type: 'error', message: t('common.imageUploader.uploadFromComputerUploadError') }) diff --git a/web/app/components/base/file-uploader/index.ts b/web/app/components/base/file-uploader/index.ts index 8d95504bf1..1c599cd4b0 100644 --- a/web/app/components/base/file-uploader/index.ts +++ b/web/app/components/base/file-uploader/index.ts @@ -1,4 +1,6 @@ export { default as FileUploaderInAttachmentWrapper } from './file-uploader-in-attachment' +export { default as FileItemInAttachment } from './file-uploader-in-attachment/file-item' export { default as FileUploaderInChatInput } from './file-uploader-in-chat-input' export { default as FileTypeIcon } from './file-type-icon' export { default as FileListInChatInput } from './file-uploader-in-chat-input/file-list' +export { default as FileItemInChatInput } from './file-uploader-in-chat-input/file-list' diff --git a/web/app/components/base/file-uploader/types.ts b/web/app/components/base/file-uploader/types.ts index 237f444501..217959433b 100644 --- a/web/app/components/base/file-uploader/types.ts +++ b/web/app/components/base/file-uploader/types.ts @@ -16,9 +16,9 @@ export enum FileAppearanceTypeEnum { export type FileAppearanceType = keyof typeof FileAppearanceTypeEnum export type FileEntity = { - id: string - file?: File - fileId?: string + fileId: string + file: File + fileStorageId?: string progress: number url?: string base64Url?: string