Skip to content

Commit 46888b9

Browse files
fix(frontend): show feedback and restrict types for prompt file uploads
1 parent 906e3c4 commit 46888b9

1 file changed

Lines changed: 19 additions & 27 deletions

File tree

frontend/src/components/message/PromptInput.tsx

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { AgentQuickSelect } from '@/components/agent/AgentQuickSelect'
2929
import { VoiceStatusOverlay, type VoiceStatusOverlayState } from './VoiceStatusOverlay'
3030
import { detectMentionTrigger, parsePromptToParts, getFilename, filterAgentsByQuery } from '@/lib/promptParser'
3131
import { randomId } from '@/lib/utils'
32+
import { showToast } from '@/lib/toast'
3233
import { formatModelName, getProviders } from '@/api/providers'
3334
import { useQuery } from '@tanstack/react-query'
3435

@@ -812,6 +813,14 @@ export const PromptInput = memo(forwardRef<PromptInputHandle, PromptInputProps>(
812813
})
813814
}
814815

816+
const addFileAttachment = (file: File) => {
817+
if (ACCEPTED_FILE_TYPES.includes(file.type)) {
818+
addImageAttachment(file)
819+
} else {
820+
showToast.error(`Only images and PDFs can be attached (${file.name})`)
821+
}
822+
}
823+
815824
const handlePaste = async (event: React.ClipboardEvent<HTMLTextAreaElement>) => {
816825
const clipboardData = event.clipboardData
817826
if (!clipboardData) return
@@ -839,7 +848,7 @@ if (isIOS && isSecureContext && navigator.clipboard && navigator.clipboard.read)
839848
try {
840849
const blob = await item.getType(type)
841850
const file = new File([blob], `pasted-${Date.now()}.${type.split('/')[1]}`, { type })
842-
addImageAttachment(file)
851+
addFileAttachment(file)
843852
} catch (err) {
844853
console.error('Failed to read clipboard item type:', err)
845854
}
@@ -853,30 +862,15 @@ if (isIOS && isSecureContext && navigator.clipboard && navigator.clipboard.read)
853862
}
854863

855864
const items = Array.from(clipboardData.items)
856-
857-
const imageItems = items.filter((item) => {
858-
if (item.kind !== 'file') return false
859-
860-
const hasKnownType = ACCEPTED_FILE_TYPES.includes(item.type)
861-
const isLikelyImage = item.type.startsWith('image/')
862-
const hasNoType = !item.type || item.type === ''
863-
864-
return hasKnownType || isLikelyImage || hasNoType
865-
})
866865

867-
if (imageItems.length > 0) {
866+
const fileItems = items.filter((item) => item.kind === 'file')
867+
868+
if (fileItems.length > 0) {
868869
event.preventDefault()
869-
for (const item of imageItems) {
870+
for (const item of fileItems) {
870871
const file = item.getAsFile()
871872
if (file) {
872-
const isValidImageFile =
873-
ACCEPTED_FILE_TYPES.includes(file.type) ||
874-
file.type.startsWith('image/') ||
875-
file.size > 0
876-
877-
if (isValidImageFile) {
878-
addImageAttachment(file)
879-
}
873+
addFileAttachment(file)
880874
}
881875
}
882876
}
@@ -904,17 +898,15 @@ if (isIOS && isSecureContext && navigator.clipboard && navigator.clipboard.read)
904898
const files = event.dataTransfer?.files
905899
if (files) {
906900
for (const file of Array.from(files)) {
907-
if (ACCEPTED_FILE_TYPES.includes(file.type)) {
908-
addImageAttachment(file)
909-
}
901+
addFileAttachment(file)
910902
}
911903
}
912904
}
913905

914906
const handleFileInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
915907
const file = event.currentTarget.files?.[0]
916-
if (file && ACCEPTED_FILE_TYPES.includes(file.type)) {
917-
addImageAttachment(file)
908+
if (file) {
909+
addFileAttachment(file)
918910
}
919911
event.currentTarget.value = ''
920912
}
@@ -1368,7 +1360,7 @@ return (
13681360
<input
13691361
ref={fileInputRef}
13701362
type="file"
1371-
accept="*/*"
1363+
accept={ACCEPTED_FILE_TYPES.join(',')}
13721364
className="hidden"
13731365
onChange={handleFileInputChange}
13741366
/>

0 commit comments

Comments
 (0)