forked from u14app/gemini-next-chat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFileUploader.tsx
108 lines (93 loc) · 3.24 KB
/
FileUploader.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
'use client'
import { useRef, useMemo, memo, useCallback } from 'react'
import { Paperclip, ImagePlus } from 'lucide-react'
import { useToast } from '@/components/ui/use-toast'
import type { FileManagerOptions } from '@/utils/FileManager'
import { encodeToken } from '@/utils/signature'
import { fileUpload, imageUpload } from '@/utils/upload'
import { useSettingStore, useEnvStore } from '@/store/setting'
import { useAttachmentStore } from '@/store/attachment'
import { GEMINI_API_BASE_URL } from '@/constant/urls'
import { OldVisionModel } from '@/constant/model'
import mimeType, { imageMimeType } from '@/constant/attachment'
import { isFunction } from 'lodash-es'
type Props = {
beforeUpload?: () => void
afterUpload?: () => void
}
function FileUploader({ beforeUpload, afterUpload }: Props) {
const { toast } = useToast()
const attachmentRef = useRef<HTMLInputElement>(null)
const imageRef = useRef<HTMLInputElement>(null)
const settingStore = useSettingStore()
const isOldVisionModel = useMemo(() => {
return OldVisionModel.includes(settingStore.model)
}, [settingStore.model])
const handleError = useCallback(
(err: string) => {
toast({ description: err })
},
[toast],
)
const handleFileUpload = useCallback(
async (files: FileList | null) => {
if (isFunction(beforeUpload)) beforeUpload()
const { apiKey, apiProxy, password } = useSettingStore.getState()
const { uploadLimit } = useEnvStore.getState()
const options: FileManagerOptions =
apiKey !== '' ? { apiKey, baseUrl: apiProxy || GEMINI_API_BASE_URL } : { token: encodeToken(password) }
const { add: addAttachment, update: updateAttachment } = useAttachmentStore.getState()
await fileUpload({
files,
uploadLimit,
fileManagerOptions: options,
addAttachment,
updateAttachment,
onError: handleError,
})
if (attachmentRef.current && attachmentRef.current.value) {
attachmentRef.current.value = ''
}
if (isFunction(afterUpload)) afterUpload()
},
[handleError, beforeUpload, afterUpload],
)
const handleImageUpload = useCallback(
async (files: FileList | null) => {
if (isFunction(beforeUpload)) beforeUpload()
const { add: addAttachment, update: updateAttachment } = useAttachmentStore.getState()
await imageUpload({ files, addAttachment, updateAttachment, onError: handleError })
if (imageRef.current && imageRef.current.value) {
imageRef.current.value = ''
}
if (isFunction(afterUpload)) afterUpload()
},
[handleError, beforeUpload, afterUpload],
)
return (
<>
<input
ref={attachmentRef}
type="file"
accept={mimeType.join(',')}
multiple
hidden
onChange={(ev) => handleFileUpload(ev.target.files)}
/>
<input
ref={imageRef}
type="file"
accept={imageMimeType.join(',')}
multiple
hidden
onChange={(ev) => handleImageUpload(ev.target.files)}
/>
{isOldVisionModel ? (
<ImagePlus onClick={() => imageRef.current?.click()} />
) : (
<Paperclip onClick={() => attachmentRef.current?.click()} />
)}
</>
)
}
export default memo(FileUploader)