Unverified Commit cfbfd59b authored by zxhlyh's avatar zxhlyh Committed by GitHub

fix: upload image (#1522)

parent d9336d9a
...@@ -161,7 +161,7 @@ const PromptValuePanel: FC<IPromptValuePanelProps> = ({ ...@@ -161,7 +161,7 @@ const PromptValuePanel: FC<IPromptValuePanelProps> = ({
{ {
appType === AppType.completion && visionConfig?.enabled && ( appType === AppType.completion && visionConfig?.enabled && (
<div className="mt-3 xl:flex justify-between"> <div className="mt-3 xl:flex justify-between">
<div className="mr-1 py-2 shrink-0 w-[120px] text-sm text-gray-900">Image Upload</div> <div className="mr-1 py-2 shrink-0 w-[120px] text-sm text-gray-900">{t('common.imageUploader.imageUpload')}</div>
<div className='grow'> <div className='grow'>
<TextGenerationImageUploader <TextGenerationImageUploader
settings={visionConfig} settings={visionConfig}
......
import { useState } from 'react' import { useMemo, useRef, useState } from 'react'
import { useParams } from 'next/navigation' import { useParams } from 'next/navigation'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { imageUpload } from './utils' import { imageUpload } from './utils'
...@@ -10,38 +10,59 @@ export const useImageFiles = () => { ...@@ -10,38 +10,59 @@ export const useImageFiles = () => {
const { t } = useTranslation() const { t } = useTranslation()
const { notify } = useToastContext() const { notify } = useToastContext()
const [files, setFiles] = useState<ImageFile[]>([]) const [files, setFiles] = useState<ImageFile[]>([])
const filesRef = useRef<ImageFile[]>([])
const handleUpload = (imageFile: ImageFile) => { const handleUpload = (imageFile: ImageFile) => {
const files = filesRef.current
const index = files.findIndex(file => file._id === imageFile._id)
if (index > -1) {
const currentFile = files[index]
const newFiles = [...files.slice(0, index), { ...currentFile, ...imageFile }, ...files.slice(index + 1)]
setFiles(newFiles)
filesRef.current = newFiles
}
else {
const newFiles = [...files, imageFile] const newFiles = [...files, imageFile]
setFiles(newFiles) setFiles(newFiles)
filesRef.current = newFiles
}
} }
const handleRemove = (imageFileId: string) => { const handleRemove = (imageFileId: string) => {
const files = filesRef.current
const index = files.findIndex(file => file._id === imageFileId) const index = files.findIndex(file => file._id === imageFileId)
if (index > -1) { if (index > -1) {
const newFiles = [...files.slice(0, index), ...files.slice(index + 1)] const currentFile = files[index]
const newFiles = [...files.slice(0, index), { ...currentFile, deleted: true }, ...files.slice(index + 1)]
setFiles(newFiles) setFiles(newFiles)
filesRef.current = newFiles
} }
} }
const handleImageLinkLoadError = (imageFileId: string) => { const handleImageLinkLoadError = (imageFileId: string) => {
const files = filesRef.current
const index = files.findIndex(file => file._id === imageFileId) const index = files.findIndex(file => file._id === imageFileId)
if (index > -1) { if (index > -1) {
const currentFile = files[index] const currentFile = files[index]
const newFiles = [...files.slice(0, index), { ...currentFile, progress: -1 }, ...files.slice(index + 1)] const newFiles = [...files.slice(0, index), { ...currentFile, progress: -1 }, ...files.slice(index + 1)]
filesRef.current = newFiles
setFiles(newFiles) setFiles(newFiles)
} }
} }
const handleImageLinkLoadSuccess = (imageFileId: string) => { const handleImageLinkLoadSuccess = (imageFileId: string) => {
const files = filesRef.current
const index = files.findIndex(file => file._id === imageFileId) const index = files.findIndex(file => file._id === imageFileId)
if (index > -1) { if (index > -1) {
const currentImageFile = files[index] const currentImageFile = files[index]
const newFiles = [...files.slice(0, index), { ...currentImageFile, progress: 100 }, ...files.slice(index + 1)] const newFiles = [...files.slice(0, index), { ...currentImageFile, progress: 100 }, ...files.slice(index + 1)]
filesRef.current = newFiles
setFiles(newFiles) setFiles(newFiles)
} }
} }
const handleReUpload = (imageFileId: string) => { const handleReUpload = (imageFileId: string) => {
const files = filesRef.current
const index = files.findIndex(file => file._id === imageFileId) const index = files.findIndex(file => file._id === imageFileId)
if (index > -1) { if (index > -1) {
...@@ -50,15 +71,18 @@ export const useImageFiles = () => { ...@@ -50,15 +71,18 @@ export const useImageFiles = () => {
file: currentImageFile.file!, file: currentImageFile.file!,
onProgressCallback: (progress) => { onProgressCallback: (progress) => {
const newFiles = [...files.slice(0, index), { ...currentImageFile, progress }, ...files.slice(index + 1)] const newFiles = [...files.slice(0, index), { ...currentImageFile, progress }, ...files.slice(index + 1)]
filesRef.current = newFiles
setFiles(newFiles) setFiles(newFiles)
}, },
onSuccessCallback: (res) => { onSuccessCallback: (res) => {
const newFiles = [...files.slice(0, index), { ...currentImageFile, fileId: res.id, progress: 100 }, ...files.slice(index + 1)] const newFiles = [...files.slice(0, index), { ...currentImageFile, fileId: res.id, progress: 100 }, ...files.slice(index + 1)]
filesRef.current = newFiles
setFiles(newFiles) setFiles(newFiles)
}, },
onErrorCallback: () => { onErrorCallback: () => {
notify({ type: 'error', message: t('common.imageUploader.uploadFromComputerUploadError') }) notify({ type: 'error', message: t('common.imageUploader.uploadFromComputerUploadError') })
const newFiles = [...files.slice(0, index), { ...currentImageFile, progress: -1 }, ...files.slice(index + 1)] const newFiles = [...files.slice(0, index), { ...currentImageFile, progress: -1 }, ...files.slice(index + 1)]
filesRef.current = newFiles
setFiles(newFiles) setFiles(newFiles)
}, },
}, !!params.token) }, !!params.token)
...@@ -67,10 +91,15 @@ export const useImageFiles = () => { ...@@ -67,10 +91,15 @@ export const useImageFiles = () => {
const handleClear = () => { const handleClear = () => {
setFiles([]) setFiles([])
filesRef.current = []
} }
const filteredFiles = useMemo(() => {
return files.filter(file => !file.deleted)
}, [files])
return { return {
files, files: filteredFiles,
onUpload: handleUpload, onUpload: handleUpload,
onRemove: handleRemove, onRemove: handleRemove,
onImageLinkLoadError: handleImageLinkLoadError, onImageLinkLoadError: handleImageLinkLoadError,
......
...@@ -88,6 +88,7 @@ const Uploader: FC<UploaderProps> = ({ ...@@ -88,6 +88,7 @@ const Uploader: FC<UploaderProps> = ({
absolute block inset-0 opacity-0 text-[0] absolute block inset-0 opacity-0 text-[0]
${disabled ? 'cursor-not-allowed' : 'cursor-pointer'} ${disabled ? 'cursor-not-allowed' : 'cursor-pointer'}
`} `}
onClick={e => (e.target as HTMLInputElement).value = ''}
type='file' type='file'
accept='.png, .jpg, .jpeg, .webp, .gif' accept='.png, .jpg, .jpeg, .webp, .gif'
onChange={handleChange} onChange={handleChange}
......
...@@ -82,7 +82,7 @@ const RunOnce: FC<IRunOnceProps> = ({ ...@@ -82,7 +82,7 @@ const RunOnce: FC<IRunOnceProps> = ({
{ {
visionConfig?.enabled && ( visionConfig?.enabled && (
<div className="w-full mt-4"> <div className="w-full mt-4">
<div className="text-gray-900 text-sm font-medium">Image Upload</div> <div className="text-gray-900 text-sm font-medium">{t('common.imageUploader.imageUpload')}</div>
<div className='mt-2'> <div className='mt-2'>
<TextGenerationImageUploader <TextGenerationImageUploader
settings={visionConfig} settings={visionConfig}
......
...@@ -438,6 +438,7 @@ const translation = { ...@@ -438,6 +438,7 @@ const translation = {
pasteImageLink: 'Paste image link', pasteImageLink: 'Paste image link',
pasteImageLinkInputPlaceholder: 'Paste image link here', pasteImageLinkInputPlaceholder: 'Paste image link here',
pasteImageLinkInvalid: 'Invalid image link', pasteImageLinkInvalid: 'Invalid image link',
imageUpload: 'Image Upload',
}, },
} }
......
...@@ -438,6 +438,7 @@ const translation = { ...@@ -438,6 +438,7 @@ const translation = {
pasteImageLink: '粘贴图片链接', pasteImageLink: '粘贴图片链接',
pasteImageLinkInputPlaceholder: '将图像链接粘贴到此处', pasteImageLinkInputPlaceholder: '将图像链接粘贴到此处',
pasteImageLinkInvalid: '图片链接无效', pasteImageLinkInvalid: '图片链接无效',
imageUpload: '图片上传',
}, },
} }
......
...@@ -301,6 +301,7 @@ export type ImageFile = { ...@@ -301,6 +301,7 @@ export type ImageFile = {
progress: number progress: number
url: string url: string
base64Url?: string base64Url?: string
deleted?: boolean
} }
export type VisionFile = { export type VisionFile = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment