mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-03 11:19:10 +08:00
fix: cannot paste images when mentioned visual models (#7817)
* refactor(paste): 优化粘贴功能逻辑,移除模型类型依赖 重构粘贴服务处理逻辑,将文件类型支持判断移至组件层 简化handlePaste接口,移除isVisionModel和isGenerateImageModel参数 * fix(MessageEditor): 支持生成图片模型的视觉消息检查 * refactor(Inputbar): 移除调试用的console.log语句 * refactor(PasteService): 移除调试用的console.log语句
This commit is contained in:
parent
6a4468193b
commit
1493132974
@ -521,8 +521,6 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
async (event: ClipboardEvent) => {
|
||||
return await PasteService.handlePaste(
|
||||
event,
|
||||
isVisionModel(model),
|
||||
isGenerateImageModel(model),
|
||||
supportedExts,
|
||||
setFiles,
|
||||
setText,
|
||||
@ -533,7 +531,7 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
t
|
||||
)
|
||||
},
|
||||
[model, pasteLongTextAsFile, pasteLongTextThreshold, resizeTextArea, supportedExts, t, text]
|
||||
[pasteLongTextAsFile, pasteLongTextThreshold, resizeTextArea, supportedExts, t, text]
|
||||
)
|
||||
|
||||
const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
|
||||
|
||||
@ -41,14 +41,58 @@ const MessageBlockEditor: FC<Props> = ({ message, topicId, onSave, onResend, onC
|
||||
const [isFileDragging, setIsFileDragging] = useState(false)
|
||||
const { assistant } = useAssistant(message.assistantId)
|
||||
const model = assistant.model || assistant.defaultModel
|
||||
const isVision = useMemo(() => isVisionModel(model), [model])
|
||||
const supportExts = useMemo(() => [...textExts, ...documentExts, ...(isVision ? imageExts : [])], [isVision])
|
||||
const { pasteLongTextThreshold, fontSize, sendMessageShortcut, enableSpellCheck } = useSettings()
|
||||
const { t } = useTranslation()
|
||||
const textareaRef = useRef<TextAreaRef>(null)
|
||||
const attachmentButtonRef = useRef<AttachmentButtonRef>(null)
|
||||
const isUserMessage = message.role === 'user'
|
||||
|
||||
const topicMessages = useAppSelector((state) => selectMessagesForTopic(state, topicId))
|
||||
|
||||
const couldAddImageFile = useMemo(() => {
|
||||
const relatedAssistantMessages = topicMessages.filter((m) => m.askId === message.id && m.role === 'assistant')
|
||||
if (relatedAssistantMessages.length === 0) {
|
||||
// 无关联消息时fallback到助手模型
|
||||
return isVisionModel(model)
|
||||
}
|
||||
return relatedAssistantMessages.every((m) => {
|
||||
if (m.model) {
|
||||
return isVisionModel(m.model) || isGenerateImageModel(m.model)
|
||||
} else {
|
||||
// 若消息关联不存在的模型,视为其支持视觉
|
||||
return true
|
||||
}
|
||||
})
|
||||
}, [message.id, model, topicMessages])
|
||||
|
||||
const couldAddTextFile = useMemo(() => {
|
||||
const relatedAssistantMessages = topicMessages.filter((m) => m.askId === message.id && m.role === 'assistant')
|
||||
if (relatedAssistantMessages.length === 0) {
|
||||
// 无关联消息时fallback到助手模型
|
||||
return isVisionModel(model) || (!isVisionModel(model) && !isGenerateImageModel(model))
|
||||
}
|
||||
return relatedAssistantMessages.every((m) => {
|
||||
if (m.model) {
|
||||
return isVisionModel(m.model) || (!isVisionModel(m.model) && !isGenerateImageModel(m.model))
|
||||
} else {
|
||||
// 若消息关联不存在的模型,视为其支持文本
|
||||
return true
|
||||
}
|
||||
})
|
||||
}, [message.id, model, topicMessages])
|
||||
|
||||
const extensions = useMemo(() => {
|
||||
if (couldAddImageFile && couldAddTextFile) {
|
||||
return [...imageExts, ...documentExts, ...textExts]
|
||||
} else if (couldAddImageFile) {
|
||||
return [...imageExts]
|
||||
} else if (couldAddTextFile) {
|
||||
return [...documentExts, ...textExts]
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}, [couldAddImageFile, couldAddTextFile])
|
||||
|
||||
const resizeTextArea = useCallback(() => {
|
||||
const textArea = textareaRef.current?.resizableTextArea?.textArea
|
||||
if (textArea) {
|
||||
@ -70,9 +114,7 @@ const MessageBlockEditor: FC<Props> = ({ message, topicId, onSave, onResend, onC
|
||||
async (event: ClipboardEvent) => {
|
||||
return await PasteService.handlePaste(
|
||||
event,
|
||||
isVisionModel(model),
|
||||
isGenerateImageModel(model),
|
||||
supportExts,
|
||||
extensions,
|
||||
setFiles,
|
||||
undefined, // 不需要setText
|
||||
false, // 不需要 pasteLongTextAsFile
|
||||
@ -82,7 +124,7 @@ const MessageBlockEditor: FC<Props> = ({ message, topicId, onSave, onResend, onC
|
||||
t
|
||||
)
|
||||
},
|
||||
[model, pasteLongTextThreshold, resizeTextArea, supportExts, t]
|
||||
[extensions, pasteLongTextThreshold, resizeTextArea, t]
|
||||
)
|
||||
|
||||
// 添加全局粘贴事件处理
|
||||
@ -125,7 +167,7 @@ const MessageBlockEditor: FC<Props> = ({ message, topicId, onSave, onResend, onC
|
||||
if (files) {
|
||||
let supportedFiles = 0
|
||||
files.forEach((file) => {
|
||||
if (supportExts.includes(getFileExtension(file.path))) {
|
||||
if (extensions.includes(getFileExtension(file.path))) {
|
||||
setFiles((prevFiles) => [...prevFiles, file])
|
||||
supportedFiles++
|
||||
}
|
||||
@ -209,52 +251,6 @@ const MessageBlockEditor: FC<Props> = ({ message, topicId, onSave, onResend, onC
|
||||
}
|
||||
}
|
||||
|
||||
const topicMessages = useAppSelector((state) => selectMessagesForTopic(state, topicId))
|
||||
|
||||
const couldAddImageFile = useMemo(() => {
|
||||
const relatedAssistantMessages = topicMessages.filter((m) => m.askId === message.id && m.role === 'assistant')
|
||||
if (relatedAssistantMessages.length === 0) {
|
||||
// 无关联消息时fallback到助手模型
|
||||
return isVisionModel(model)
|
||||
}
|
||||
return relatedAssistantMessages.every((m) => {
|
||||
if (m.model) {
|
||||
return isVisionModel(m.model)
|
||||
} else {
|
||||
// 若消息关联不存在的模型,视为其支持视觉
|
||||
return true
|
||||
}
|
||||
})
|
||||
}, [message.id, model, topicMessages])
|
||||
|
||||
const couldAddTextFile = useMemo(() => {
|
||||
const relatedAssistantMessages = topicMessages.filter((m) => m.askId === message.id && m.role === 'assistant')
|
||||
if (relatedAssistantMessages.length === 0) {
|
||||
// 无关联消息时fallback到助手模型
|
||||
return isVisionModel(model) || (!isVisionModel(model) && !isGenerateImageModel(model))
|
||||
}
|
||||
return relatedAssistantMessages.every((m) => {
|
||||
if (m.model) {
|
||||
return isVisionModel(m.model) || (!isVisionModel(m.model) && !isGenerateImageModel(m.model))
|
||||
} else {
|
||||
// 若消息关联不存在的模型,视为其支持文本
|
||||
return true
|
||||
}
|
||||
})
|
||||
}, [message.id, model, topicMessages])
|
||||
|
||||
const extensions = useMemo(() => {
|
||||
if (couldAddImageFile && couldAddTextFile) {
|
||||
return [...imageExts, ...documentExts, ...textExts]
|
||||
} else if (couldAddImageFile) {
|
||||
return [...imageExts]
|
||||
} else if (couldAddTextFile) {
|
||||
return [...documentExts, ...textExts]
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}, [couldAddImageFile, couldAddTextFile])
|
||||
|
||||
return (
|
||||
<>
|
||||
<EditorContainer className="message-editor" onDragOver={(e) => e.preventDefault()} onDrop={handleDrop}>
|
||||
|
||||
@ -24,8 +24,6 @@ let isInitialized = false
|
||||
*/
|
||||
export const handlePaste = async (
|
||||
event: ClipboardEvent,
|
||||
isVisionModel: boolean,
|
||||
isGenerateImageModel: boolean,
|
||||
supportExts: string[],
|
||||
setFiles: (updater: (prevFiles: FileMetadata[]) => FileMetadata[]) => void,
|
||||
setText?: (text: string) => void,
|
||||
@ -57,7 +55,6 @@ export const handlePaste = async (
|
||||
// 短文本走默认粘贴行为,直接返回
|
||||
return false
|
||||
}
|
||||
|
||||
// 2. 文件/图片粘贴(仅在无文本时处理)
|
||||
if (event.clipboardData?.files && event.clipboardData.files.length > 0) {
|
||||
event.preventDefault()
|
||||
@ -69,7 +66,7 @@ export const handlePaste = async (
|
||||
// 如果没有路径,可能是剪贴板中的图像数据
|
||||
if (!filePath) {
|
||||
// 图像生成也支持图像编辑
|
||||
if (file.type.startsWith('image/') && (isVisionModel || isGenerateImageModel)) {
|
||||
if (file.type.startsWith('image/') && supportExts.includes(getFileExtension(file.name))) {
|
||||
const tempFilePath = await window.api.file.createTempFile(file.name)
|
||||
const arrayBuffer = await file.arrayBuffer()
|
||||
const uint8Array = new Uint8Array(arrayBuffer)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user