file uploader

This commit is contained in:
StyleZhang 2024-08-13 15:24:09 +08:00
parent 57f178902f
commit d7c8bced9b
7 changed files with 95 additions and 79 deletions

View File

@ -16,7 +16,8 @@ import type { Theme } from '../../embedded-chatbot/theme/theme-context'
import { useTextAreaHeight } from './hooks'
import Operation from './operation'
import cn from '@/utils/classnames'
// import { FileListFlexOperation } from '@/app/components/base/file-uploader'
import { FileListFlexOperation } from '@/app/components/base/file-uploader'
import { FileContextProvider } from '@/app/components/base/file-uploader/store'
import VoiceInput from '@/app/components/base/voice-input'
import { useToastContext } from '@/app/components/base/toast'
@ -92,58 +93,60 @@ const ChatInputArea = ({
)
return (
<div
className={cn(
'py-[9px] bg-components-panel-bg-blur border border-components-chat-input-border rounded-xl shadow-md',
)}
>
<div className='relative px-[9px] max-h-[158px] overflow-x-hidden overflow-y-auto'>
{/* <FileListFlexOperation /> */}
<div
ref={wrapperRef}
className='flex items-center justify-between'
>
<div className='flex items-center relative grow w-full'>
<div
ref={textValueRef}
className='absolute w-auto h-auto p-1 leading-6 body-lg-regular pointer-events-none whitespace-pre invisible'
>
{query}
<FileContextProvider>
<div
className={cn(
'py-[9px] bg-components-panel-bg-blur border border-components-chat-input-border rounded-xl shadow-md',
)}
>
<div className='relative px-[9px] max-h-[158px] overflow-x-hidden overflow-y-auto'>
<FileListFlexOperation />
<div
ref={wrapperRef}
className='flex items-center justify-between'
>
<div className='flex items-center relative grow w-full'>
<div
ref={textValueRef}
className='absolute w-auto h-auto p-1 leading-6 body-lg-regular pointer-events-none whitespace-pre invisible'
>
{query}
</div>
<Textarea
ref={textareaRef}
className='p-1 w-full leading-6 body-lg-regular text-text-tertiary outline-none'
placeholder='Enter message...'
autoSize={{ minRows: 1 }}
onResize={handleTextareaResize}
value={query}
onChange={(e) => {
setQuery(e.target.value)
handleTextareaResize()
}}
onKeyUp={handleKeyUp}
onKeyDown={handleKeyDown}
/>
</div>
<Textarea
ref={textareaRef}
className='p-1 w-full leading-6 body-lg-regular text-text-tertiary outline-none'
placeholder='Enter message...'
autoSize={{ minRows: 1 }}
onResize={handleTextareaResize}
value={query}
onChange={(e) => {
setQuery(e.target.value)
handleTextareaResize()
}}
onKeyUp={handleKeyUp}
onKeyDown={handleKeyDown}
/>
{
!isMultipleLine && operation
}
</div>
{
!isMultipleLine && operation
showVoiceInput && (
<VoiceInput
onCancel={() => setShowVoiceInput(false)}
onConverted={text => setQuery(text)}
/>
)
}
</div>
{
showVoiceInput && (
<VoiceInput
onCancel={() => setShowVoiceInput(false)}
onConverted={text => setQuery(text)}
/>
isMultipleLine && (
<div className='px-[9px]'>{operation}</div>
)
}
</div>
{
isMultipleLine && (
<div className='px-[9px]'>{operation}</div>
)
}
</div>
</FileContextProvider>
)
}

View File

@ -8,7 +8,7 @@ type FileListItemProps = {
isFile?: boolean
className?: string
}
const FileListItem = ({
const FileListFlexItem = ({
isFile,
className,
}: FileListItemProps) => {
@ -48,4 +48,4 @@ const FileListItem = ({
)
}
export default memo(FileListItem)
export default memo(FileListFlexItem)

View File

@ -3,33 +3,31 @@ import {
memo,
} from 'react'
import { RiCloseLine } from '@remixicon/react'
import FileListItem from './file-list-item'
import { useStore } from '../store'
import FileListItem from './file-list-flex-item'
import Button from '@/app/components/base/button'
const FileListFlexOperation = forwardRef<HTMLDivElement>((_, ref) => {
const files = useStore(s => s.files)
return (
<div
ref={ref}
className='flex flex-wrap gap-2'
>
<div className='relative'>
<Button className='absolute -right-1.5 -top-1.5 p-0 w-5 h-5 rounded-full'>
<RiCloseLine className='w-4 h-4 text-components-button-secondary-text' />
</Button>
<FileListItem />
</div>
<div className='relative'>
<Button className='absolute -right-1.5 -top-1.5 p-0 w-5 h-5 rounded-full'>
<RiCloseLine className='w-4 h-4 text-components-button-secondary-text' />
</Button>
<FileListItem />
</div>
<div className='relative'>
<Button className='absolute -right-1.5 -top-1.5 p-0 w-5 h-5 rounded-full'>
<RiCloseLine className='w-4 h-4 text-components-button-secondary-text' />
</Button>
<FileListItem isFile />
</div>
{
files.map(file => (
<div
key={file._id}
className='relative'
>
<Button className='absolute -right-1.5 -top-1.5 p-0 w-5 h-5 rounded-full'>
<RiCloseLine className='w-4 h-4 text-components-button-secondary-text' />
</Button>
<FileListItem />
</div>
))
}
</div>
)
})

View File

@ -2,7 +2,7 @@ import {
forwardRef,
memo,
} from 'react'
import FileListItem from './file-list-item'
import FileListFlexItem from './file-list-flex-item'
const FileListFlexPreview = forwardRef<HTMLDivElement>((_, ref) => {
return (
@ -10,10 +10,10 @@ const FileListFlexPreview = forwardRef<HTMLDivElement>((_, ref) => {
ref={ref}
className='flex flex-wrap gap-2'
>
<FileListItem />
<FileListItem />
<FileListItem isFile />
<FileListItem isFile />
<FileListFlexItem />
<FileListFlexItem />
<FileListFlexItem isFile />
<FileListFlexItem isFile />
</div>
)
})

View File

@ -1,5 +1,4 @@
import {
memo,
useCallback,
} from 'react'
import {
@ -8,6 +7,10 @@ import {
} from '@remixicon/react'
import { useTranslation } from 'react-i18next'
import FileFromLinkOrLocal from '../file-from-link-or-local'
import {
FileContextProvider,
useStore,
} from '../store'
import FileInAttachmentItem from './file-in-attachment-item'
import Button from '@/app/components/base/button'
import cn from '@/utils/classnames'
@ -19,6 +22,7 @@ type Option = {
}
const FileUploaderInAttachment = () => {
const { t } = useTranslation()
const files = useStore(s => s.files)
const options = [
{
value: 'local',
@ -68,11 +72,24 @@ const FileUploaderInAttachment = () => {
{options.map(renderOption)}
</div>
<div className='mt-1 space-y-1'>
<FileInAttachmentItem />
<FileInAttachmentItem />
{
files.map(file => (
<FileInAttachmentItem
key={file._id}
/>
))
}
</div>
</div>
)
}
export default memo(FileUploaderInAttachment)
const FileUploaderInAttachmentWrapper = () => {
return (
<FileContextProvider>
<FileUploaderInAttachment />
</FileContextProvider>
)
}
export default FileUploaderInAttachmentWrapper

View File

@ -1,4 +1,4 @@
export { default as FileUploaderInAttachment } from './file-uploader-in-attachment'
export { default as FileUploaderInAttachmentWrapper } from './file-uploader-in-attachment'
export { default as FileUploaderInChatInput } from './file-uploader-in-chat-input'
export { default as FileTypeIcon } from './file-type-icon'
export { default as FileListFlexOperation } from './file-list-flex/file-list-flex-operation'

View File

@ -12,8 +12,7 @@ import Textarea from '@/app/components/base/textarea'
import { DEFAULT_VALUE_MAX_LEN } from '@/config'
import TextGenerationImageUploader from '@/app/components/base/image-uploader/text-generation-image-uploader'
import type { VisionFile, VisionSettings } from '@/types/app'
import ChatInputArea from '@/app/components/base/chat/chat/chat-input-area'
import { FileUploaderInAttachment } from '@/app/components/base/file-uploader'
import { FileUploaderInAttachmentWrapper } from '@/app/components/base/file-uploader'
export type IRunOnceProps = {
siteInfo: SiteInfo
@ -115,8 +114,7 @@ const RunOnce: FC<IRunOnceProps> = ({
</div>
)
}
<ChatInputArea />
<FileUploaderInAttachment />
<FileUploaderInAttachmentWrapper />
{promptConfig.prompt_variables.length > 0 && (
<div className='mt-4 h-[1px] bg-gray-100'></div>
)}