mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-05 12:29:44 +08:00
refactor(PasteService): 优化粘贴服务逻辑并移除不必要的翻译依赖
将`t`参数改为布尔类型的`showMessage`参数,简化消息显示逻辑 添加默认的粘贴文本长度阈值 使文件扩展名检查变为可选参数 更新相关调用处的参数传递
This commit is contained in:
parent
38a8a9d535
commit
07c7ecd0cf
@ -552,10 +552,10 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
|||||||
pasteLongTextThreshold,
|
pasteLongTextThreshold,
|
||||||
text,
|
text,
|
||||||
resizeTextArea,
|
resizeTextArea,
|
||||||
t
|
true
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
[pasteLongTextAsFile, pasteLongTextThreshold, resizeTextArea, supportedExts, t, text]
|
[pasteLongTextAsFile, pasteLongTextThreshold, resizeTextArea, supportedExts, text]
|
||||||
)
|
)
|
||||||
|
|
||||||
const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
|
const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
|
||||||
|
|||||||
@ -130,10 +130,10 @@ const MessageBlockEditor: FC<Props> = ({ message, topicId, onSave, onResend, onC
|
|||||||
pasteLongTextThreshold,
|
pasteLongTextThreshold,
|
||||||
undefined, // 不需要text
|
undefined, // 不需要text
|
||||||
undefined, // 不需要 resizeTextArea
|
undefined, // 不需要 resizeTextArea
|
||||||
t
|
true
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
[extensions, pasteLongTextThreshold, t]
|
[extensions, pasteLongTextThreshold]
|
||||||
)
|
)
|
||||||
|
|
||||||
// 添加全局粘贴事件处理
|
// 添加全局粘贴事件处理
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { loggerService } from '@logger'
|
import { loggerService } from '@logger'
|
||||||
import { FileMetadata } from '@renderer/types'
|
import { FileMetadata } from '@renderer/types'
|
||||||
import { getFileExtension, isSupportedFile } from '@renderer/utils'
|
import { getFileExtension, isSupportedFile } from '@renderer/utils'
|
||||||
|
import { t } from 'i18next'
|
||||||
|
|
||||||
const logger = loggerService.withContext('PasteService')
|
const logger = loggerService.withContext('PasteService')
|
||||||
|
|
||||||
@ -23,19 +24,33 @@ let isInitialized = false
|
|||||||
/**
|
/**
|
||||||
* 处理粘贴事件的通用服务
|
* 处理粘贴事件的通用服务
|
||||||
* 处理各种粘贴场景,包括文本和文件
|
* 处理各种粘贴场景,包括文本和文件
|
||||||
|
* @param event - 粘贴事件对象
|
||||||
|
* @param supportExts - 支持的文件扩展名数组,undefined表示支持所有类型
|
||||||
|
* @param setFiles - 设置文件的回调函数,undefined表示不处理文件
|
||||||
|
* @param setText - 设置文本的回调函数,undefined表示不设置文本
|
||||||
|
* @param pasteLongTextAsFile - 是否将长文本作为文件粘贴,undefined表示不作为文件处理
|
||||||
|
* @param pasteLongTextThreshold - 长文本阈值,超过此长度的文本将作为文件处理,undefined表示使用默认阈值
|
||||||
|
* @param text - 当前输入框的文本内容,undefined表示无文本
|
||||||
|
* @param resizeTextArea - 调整文本框大小的回调函数,undefined表示不调整大小
|
||||||
|
* @param showMessage - 是否显示提示消息,undefined表示不显示
|
||||||
|
* @returns 返回是否已处理粘贴事件
|
||||||
*/
|
*/
|
||||||
export const handlePaste = async (
|
export const handlePaste = async (
|
||||||
event: ClipboardEvent,
|
event: ClipboardEvent,
|
||||||
supportExts: string[],
|
supportExts?: string[],
|
||||||
setFiles: (updater: (prevFiles: FileMetadata[]) => FileMetadata[]) => void,
|
setFiles?: (updater: (prevFiles: FileMetadata[]) => FileMetadata[]) => void,
|
||||||
setText?: (text: string) => void,
|
setText?: (text: string) => void,
|
||||||
pasteLongTextAsFile?: boolean,
|
pasteLongTextAsFile?: boolean,
|
||||||
pasteLongTextThreshold?: number,
|
pasteLongTextThreshold?: number,
|
||||||
text?: string,
|
text?: string,
|
||||||
resizeTextArea?: () => void,
|
resizeTextArea?: () => void,
|
||||||
t?: (key: string) => string
|
showMessage?: boolean
|
||||||
): Promise<boolean> => {
|
): Promise<boolean> => {
|
||||||
try {
|
try {
|
||||||
|
if (!pasteLongTextThreshold) {
|
||||||
|
// default threshold
|
||||||
|
pasteLongTextThreshold = 2000
|
||||||
|
}
|
||||||
// 优先处理文本粘贴
|
// 优先处理文本粘贴
|
||||||
const clipboardText = event.clipboardData?.getData('text')
|
const clipboardText = event.clipboardData?.getData('text')
|
||||||
if (clipboardText) {
|
if (clipboardText) {
|
||||||
@ -48,7 +63,7 @@ export const handlePaste = async (
|
|||||||
await window.api.file.write(tempFilePath, clipboardText)
|
await window.api.file.write(tempFilePath, clipboardText)
|
||||||
const selectedFile = await window.api.file.get(tempFilePath)
|
const selectedFile = await window.api.file.get(tempFilePath)
|
||||||
if (selectedFile) {
|
if (selectedFile) {
|
||||||
setFiles((prevFiles) => [...prevFiles, selectedFile])
|
setFiles?.((prevFiles) => [...prevFiles, selectedFile])
|
||||||
if (setText && text) setText(text) // 保持输入框内容不变
|
if (setText && text) setText(text) // 保持输入框内容不变
|
||||||
if (resizeTextArea) setTimeout(() => resizeTextArea(), 50)
|
if (resizeTextArea) setTimeout(() => resizeTextArea(), 50)
|
||||||
}
|
}
|
||||||
@ -60,7 +75,6 @@ export const handlePaste = async (
|
|||||||
// 2. 文件/图片粘贴(仅在无文本时处理)
|
// 2. 文件/图片粘贴(仅在无文本时处理)
|
||||||
if (event.clipboardData?.files && event.clipboardData.files.length > 0) {
|
if (event.clipboardData?.files && event.clipboardData.files.length > 0) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
const extensionSet = new Set(supportExts)
|
|
||||||
try {
|
try {
|
||||||
for (const file of event.clipboardData.files) {
|
for (const file of event.clipboardData.files) {
|
||||||
// 使用新的API获取文件路径
|
// 使用新的API获取文件路径
|
||||||
@ -69,18 +83,18 @@ export const handlePaste = async (
|
|||||||
// 如果没有路径,可能是剪贴板中的图像数据
|
// 如果没有路径,可能是剪贴板中的图像数据
|
||||||
if (!filePath) {
|
if (!filePath) {
|
||||||
// 图像生成也支持图像编辑
|
// 图像生成也支持图像编辑
|
||||||
if (file.type.startsWith('image/') && supportExts.includes(getFileExtension(file.name))) {
|
if (file.type.startsWith('image/') && (supportExts?.includes(getFileExtension(file.name)) ?? true)) {
|
||||||
const tempFilePath = await window.api.file.createTempFile(file.name)
|
const tempFilePath = await window.api.file.createTempFile(file.name)
|
||||||
const arrayBuffer = await file.arrayBuffer()
|
const arrayBuffer = await file.arrayBuffer()
|
||||||
const uint8Array = new Uint8Array(arrayBuffer)
|
const uint8Array = new Uint8Array(arrayBuffer)
|
||||||
await window.api.file.write(tempFilePath, uint8Array)
|
await window.api.file.write(tempFilePath, uint8Array)
|
||||||
const selectedFile = await window.api.file.get(tempFilePath)
|
const selectedFile = await window.api.file.get(tempFilePath)
|
||||||
if (selectedFile) {
|
if (selectedFile) {
|
||||||
setFiles((prevFiles) => [...prevFiles, selectedFile])
|
setFiles?.((prevFiles) => [...prevFiles, selectedFile])
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (t) {
|
if (showMessage) {
|
||||||
window.message.info({
|
window.message.info({
|
||||||
key: 'file_not_supported',
|
key: 'file_not_supported',
|
||||||
content: t('chat.input.file_not_supported')
|
content: t('chat.input.file_not_supported')
|
||||||
@ -91,23 +105,24 @@ export const handlePaste = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 有路径的情况
|
// 有路径的情况
|
||||||
if (await isSupportedFile(filePath, extensionSet)) {
|
const extensionSet = new Set(supportExts)
|
||||||
|
if (supportExts === undefined || (await isSupportedFile(filePath, extensionSet))) {
|
||||||
const selectedFile = await window.api.file.get(filePath)
|
const selectedFile = await window.api.file.get(filePath)
|
||||||
if (selectedFile) {
|
if (selectedFile) {
|
||||||
setFiles((prevFiles) => [...prevFiles, selectedFile])
|
setFiles?.((prevFiles) => [...prevFiles, selectedFile])
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (t) {
|
if (showMessage) {
|
||||||
window.message.info({
|
window.message.info({
|
||||||
key: 'file_not_supported',
|
key: 'file_not_supported',
|
||||||
content: t('chat.input.file_not_supported')
|
content: t('common.file.not_supported', { type: getFileExtension(file.name) })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('onPaste:', error as Error)
|
logger.error('onPaste:', error as Error)
|
||||||
if (t) {
|
if (showMessage) {
|
||||||
window.message.error(t('chat.input.file_error'))
|
window.message.error(t('chat.input.file_error'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user