mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-05 04:19:02 +08:00
Revert "style(PasteService): 统一文件换行符为LF格式"
This reverts commit 37a1443b73.
This commit is contained in:
parent
37a1443b73
commit
16fbd685c7
@ -1,216 +1,216 @@
|
|||||||
import Logger from '@renderer/config/logger'
|
import Logger from '@renderer/config/logger'
|
||||||
import { FileMetadata } from '@renderer/types'
|
import { FileMetadata } from '@renderer/types'
|
||||||
import { getFileExtension } from '@renderer/utils'
|
import { getFileExtension } from '@renderer/utils'
|
||||||
|
|
||||||
// Track last focused component
|
// Track last focused component
|
||||||
type ComponentType = 'inputbar' | 'messageEditor' | null
|
type ComponentType = 'inputbar' | 'messageEditor' | null
|
||||||
let lastFocusedComponent: ComponentType = 'inputbar' // Default to inputbar
|
let lastFocusedComponent: ComponentType = 'inputbar' // Default to inputbar
|
||||||
|
|
||||||
// 处理函数类型
|
// 处理函数类型
|
||||||
type PasteHandler = (event: ClipboardEvent) => Promise<boolean>
|
type PasteHandler = (event: ClipboardEvent) => Promise<boolean>
|
||||||
|
|
||||||
// 处理函数存储
|
// 处理函数存储
|
||||||
const handlers: {
|
const handlers: {
|
||||||
inputbar?: PasteHandler
|
inputbar?: PasteHandler
|
||||||
messageEditor?: PasteHandler
|
messageEditor?: PasteHandler
|
||||||
} = {}
|
} = {}
|
||||||
|
|
||||||
// 初始化标志
|
// 初始化标志
|
||||||
let isInitialized = false
|
let isInitialized = false
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理粘贴事件的通用服务
|
* 处理粘贴事件的通用服务
|
||||||
* 处理各种粘贴场景,包括文本和文件
|
* 处理各种粘贴场景,包括文本和文件
|
||||||
*/
|
*/
|
||||||
export const handlePaste = async (
|
export const handlePaste = async (
|
||||||
event: ClipboardEvent,
|
event: ClipboardEvent,
|
||||||
isVisionModel: boolean,
|
isVisionModel: boolean,
|
||||||
isGenerateImageModel: boolean,
|
isGenerateImageModel: boolean,
|
||||||
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
|
t?: (key: string) => string
|
||||||
): Promise<boolean> => {
|
): Promise<boolean> => {
|
||||||
try {
|
try {
|
||||||
// 优先处理文本粘贴
|
// 优先处理文本粘贴
|
||||||
const clipboardText = event.clipboardData?.getData('text')
|
const clipboardText = event.clipboardData?.getData('text')
|
||||||
if (clipboardText) {
|
if (clipboardText) {
|
||||||
// 1. 文本粘贴
|
// 1. 文本粘贴
|
||||||
if (pasteLongTextAsFile && pasteLongTextThreshold && clipboardText.length > pasteLongTextThreshold) {
|
if (pasteLongTextAsFile && pasteLongTextThreshold && clipboardText.length > pasteLongTextThreshold) {
|
||||||
// 长文本直接转文件,阻止默认粘贴
|
// 长文本直接转文件,阻止默认粘贴
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
const tempFilePath = await window.api.file.createTempFile('pasted_text.txt')
|
const tempFilePath = await window.api.file.createTempFile('pasted_text.txt')
|
||||||
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)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// 短文本走默认粘贴行为,直接返回
|
// 短文本走默认粘贴行为,直接返回
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 文件/图片粘贴(仅在无文本时处理)
|
// 2. 文件/图片粘贴(仅在无文本时处理)
|
||||||
if (event.clipboardData?.files && event.clipboardData.files.length > 0) {
|
if (event.clipboardData?.files && event.clipboardData.files.length > 0) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
try {
|
try {
|
||||||
for (const file of event.clipboardData.files) {
|
for (const file of event.clipboardData.files) {
|
||||||
// 使用新的API获取文件路径
|
// 使用新的API获取文件路径
|
||||||
const filePath = window.api.file.getPathForFile(file)
|
const filePath = window.api.file.getPathForFile(file)
|
||||||
|
|
||||||
// 如果没有路径,可能是剪贴板中的图像数据
|
// 如果没有路径,可能是剪贴板中的图像数据
|
||||||
if (!filePath) {
|
if (!filePath) {
|
||||||
// 图像生成也支持图像编辑
|
// 图像生成也支持图像编辑
|
||||||
if (file.type.startsWith('image/') && (isVisionModel || isGenerateImageModel)) {
|
if (file.type.startsWith('image/') && (isVisionModel || isGenerateImageModel)) {
|
||||||
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 (t) {
|
||||||
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')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// 有路径的情况
|
// 有路径的情况
|
||||||
if (supportExts.includes(getFileExtension(filePath))) {
|
if (supportExts.includes(getFileExtension(filePath))) {
|
||||||
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 (t) {
|
||||||
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')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Logger.error('[PasteService] onPaste:', error)
|
Logger.error('[PasteService] onPaste:', error)
|
||||||
if (t) {
|
if (t) {
|
||||||
window.message.error(t('chat.input.file_error'))
|
window.message.error(t('chat.input.file_error'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// 其他情况默认粘贴
|
// 其他情况默认粘贴
|
||||||
return false
|
return false
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Logger.error('[PasteService] handlePaste error:', error)
|
Logger.error('[PasteService] handlePaste error:', error)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置最后聚焦的组件
|
* 设置最后聚焦的组件
|
||||||
*/
|
*/
|
||||||
export const setLastFocusedComponent = (component: ComponentType) => {
|
export const setLastFocusedComponent = (component: ComponentType) => {
|
||||||
lastFocusedComponent = component
|
lastFocusedComponent = component
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取最后聚焦的组件
|
* 获取最后聚焦的组件
|
||||||
*/
|
*/
|
||||||
export const getLastFocusedComponent = (): ComponentType => {
|
export const getLastFocusedComponent = (): ComponentType => {
|
||||||
return lastFocusedComponent
|
return lastFocusedComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化全局粘贴事件监听
|
* 初始化全局粘贴事件监听
|
||||||
* 应用启动时只调用一次
|
* 应用启动时只调用一次
|
||||||
*/
|
*/
|
||||||
export const init = () => {
|
export const init = () => {
|
||||||
if (isInitialized) return
|
if (isInitialized) return
|
||||||
|
|
||||||
// 添加全局粘贴事件监听
|
// 添加全局粘贴事件监听
|
||||||
document.addEventListener('paste', async (event) => {
|
document.addEventListener('paste', async (event) => {
|
||||||
await handleGlobalPaste(event)
|
await handleGlobalPaste(event)
|
||||||
})
|
})
|
||||||
|
|
||||||
isInitialized = true
|
isInitialized = true
|
||||||
Logger.info('[PasteService] Global paste handler initialized')
|
Logger.info('[PasteService] Global paste handler initialized')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册组件的粘贴处理函数
|
* 注册组件的粘贴处理函数
|
||||||
*/
|
*/
|
||||||
export const registerHandler = (component: ComponentType, handler: PasteHandler) => {
|
export const registerHandler = (component: ComponentType, handler: PasteHandler) => {
|
||||||
if (!component) return
|
if (!component) return
|
||||||
|
|
||||||
// Only log and update if the handler actually changes
|
// Only log and update if the handler actually changes
|
||||||
if (!handlers[component] || handlers[component] !== handler) {
|
if (!handlers[component] || handlers[component] !== handler) {
|
||||||
handlers[component] = handler
|
handlers[component] = handler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除组件的粘贴处理函数
|
* 移除组件的粘贴处理函数
|
||||||
*/
|
*/
|
||||||
export const unregisterHandler = (component: ComponentType) => {
|
export const unregisterHandler = (component: ComponentType) => {
|
||||||
if (!component || !handlers[component]) return
|
if (!component || !handlers[component]) return
|
||||||
|
|
||||||
delete handlers[component]
|
delete handlers[component]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 全局粘贴处理函数,根据最后聚焦的组件路由粘贴事件
|
* 全局粘贴处理函数,根据最后聚焦的组件路由粘贴事件
|
||||||
*/
|
*/
|
||||||
const handleGlobalPaste = async (event: ClipboardEvent): Promise<boolean> => {
|
const handleGlobalPaste = async (event: ClipboardEvent): Promise<boolean> => {
|
||||||
// 如果当前有活动元素且是输入区域,不执行全局处理
|
// 如果当前有活动元素且是输入区域,不执行全局处理
|
||||||
const activeElement = document.activeElement
|
const activeElement = document.activeElement
|
||||||
if (
|
if (
|
||||||
activeElement &&
|
activeElement &&
|
||||||
(activeElement.tagName === 'INPUT' ||
|
(activeElement.tagName === 'INPUT' ||
|
||||||
activeElement.tagName === 'TEXTAREA' ||
|
activeElement.tagName === 'TEXTAREA' ||
|
||||||
activeElement.getAttribute('contenteditable') === 'true')
|
activeElement.getAttribute('contenteditable') === 'true')
|
||||||
) {
|
) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据最后聚焦的组件调用相应处理程序
|
// 根据最后聚焦的组件调用相应处理程序
|
||||||
if (lastFocusedComponent && handlers[lastFocusedComponent]) {
|
if (lastFocusedComponent && handlers[lastFocusedComponent]) {
|
||||||
const handler = handlers[lastFocusedComponent]
|
const handler = handlers[lastFocusedComponent]
|
||||||
if (handler) {
|
if (handler) {
|
||||||
return await handler(event)
|
return await handler(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果没有匹配的处理程序,默认使用inputbar处理
|
// 如果没有匹配的处理程序,默认使用inputbar处理
|
||||||
if (handlers.inputbar) {
|
if (handlers.inputbar) {
|
||||||
const handler = handlers.inputbar
|
const handler = handlers.inputbar
|
||||||
if (handler) {
|
if (handler) {
|
||||||
return await handler(event)
|
return await handler(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
handlePaste,
|
handlePaste,
|
||||||
setLastFocusedComponent,
|
setLastFocusedComponent,
|
||||||
getLastFocusedComponent,
|
getLastFocusedComponent,
|
||||||
init,
|
init,
|
||||||
registerHandler,
|
registerHandler,
|
||||||
unregisterHandler
|
unregisterHandler
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user