fix: Update file API usage for Electron 35.2.2 and add translations f… (#6087)

* Fix: Update file API usage for Electron 35.2.2 and add translations for file error messages

* 修复Electron 35.2.2中的文件API问题
This commit is contained in:
1600822305 2025-05-17 08:09:30 +08:00 committed by GitHub
parent 77f3770835
commit a6aea0c8c9
8 changed files with 56 additions and 28 deletions

View File

@ -2,7 +2,7 @@ import type { ExtractChunkData } from '@cherrystudio/embedjs-interfaces'
import { electronAPI } from '@electron-toolkit/preload'
import { IpcChannel } from '@shared/IpcChannel'
import { FileType, KnowledgeBaseParams, KnowledgeItem, MCPServer, Shortcut, WebDavConfig } from '@types'
import { contextBridge, ipcRenderer, OpenDialogOptions, shell } from 'electron'
import { contextBridge, ipcRenderer, OpenDialogOptions, shell, webUtils } from 'electron'
import { CreateDirectoryOptions } from 'webdav'
// Custom APIs for renderer
@ -73,7 +73,8 @@ const api = {
download: (url: string) => ipcRenderer.invoke(IpcChannel.File_Download, url),
copy: (fileId: string, destPath: string) => ipcRenderer.invoke(IpcChannel.File_Copy, fileId, destPath),
binaryImage: (fileId: string) => ipcRenderer.invoke(IpcChannel.File_BinaryImage, fileId),
base64File: (fileId: string) => ipcRenderer.invoke(IpcChannel.File_Base64File, fileId)
base64File: (fileId: string) => ipcRenderer.invoke(IpcChannel.File_Base64File, fileId),
getPathForFile: (file: File) => webUtils.getPathForFile(file)
},
fs: {
read: (path: string) => ipcRenderer.invoke(IpcChannel.Fs_Read, path)

View File

@ -163,6 +163,7 @@
"input.estimated_tokens.tip": "Estimated tokens",
"input.expand": "Expand",
"input.file_not_supported": "Model does not support this file type",
"input.file_error": "Error processing file",
"input.generate_image": "Generate image",
"input.generate_image_not_supported": "The model does not support generating images.",
"input.knowledge_base": "Knowledge Base",

View File

@ -163,6 +163,7 @@
"input.estimated_tokens.tip": "推定トークン数",
"input.expand": "展開",
"input.file_not_supported": "モデルはこのファイルタイプをサポートしません",
"input.file_error": "ファイル処理エラー",
"input.generate_image": "画像を生成する",
"input.generate_image_not_supported": "モデルは画像の生成をサポートしていません。",
"input.knowledge_base": "ナレッジベース",

View File

@ -163,6 +163,7 @@
"input.estimated_tokens.tip": "Затраты токенов",
"input.expand": "Развернуть",
"input.file_not_supported": "Модель не поддерживает этот тип файла",
"input.file_error": "Ошибка обработки файла",
"input.generate_image": "Сгенерировать изображение",
"input.generate_image_not_supported": "Модель не поддерживает генерацию изображений.",
"input.knowledge_base": "База знаний",

View File

@ -163,6 +163,7 @@
"input.estimated_tokens.tip": "预估 token 数",
"input.expand": "展开",
"input.file_not_supported": "模型不支持此文件类型",
"input.file_error": "文件处理出错",
"input.generate_image": "生成图片",
"input.generate_image_not_supported": "模型不支持生成图片",
"input.knowledge_base": "知识库",

View File

@ -163,6 +163,7 @@
"input.estimated_tokens.tip": "預估 Token 數",
"input.expand": "展開",
"input.file_not_supported": "模型不支援此檔案類型",
"input.file_error": "檔案處理錯誤",
"input.generate_image": "生成圖片",
"input.generate_image_not_supported": "模型不支援生成圖片",
"input.knowledge_base": "知識庫",

View File

@ -584,27 +584,33 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
if (event.clipboardData?.files && event.clipboardData.files.length > 0) {
event.preventDefault()
for (const file of event.clipboardData.files) {
if (file.path === '') {
// 图像生成也支持图像编辑
if (file.type.startsWith('image/') && (isVisionModel(model) || isGenerateImageModel(model))) {
const tempFilePath = await window.api.file.create(file.name)
const arrayBuffer = await file.arrayBuffer()
const uint8Array = new Uint8Array(arrayBuffer)
await window.api.file.write(tempFilePath, uint8Array)
const selectedFile = await window.api.file.get(tempFilePath)
selectedFile && setFiles((prevFiles) => [...prevFiles, selectedFile])
break
} else {
window.message.info({
key: 'file_not_supported',
content: t('chat.input.file_not_supported')
})
}
}
try {
// 使用新的API获取文件路径
const filePath = window.api.file.getPathForFile(file)
if (file.path) {
if (supportExts.includes(getFileExtension(file.path))) {
const selectedFile = await window.api.file.get(file.path)
// 如果没有路径,可能是剪贴板中的图像数据
if (!filePath) {
// 图像生成也支持图像编辑
if (file.type.startsWith('image/') && (isVisionModel(model) || isGenerateImageModel(model))) {
const tempFilePath = await window.api.file.create(file.name)
const arrayBuffer = await file.arrayBuffer()
const uint8Array = new Uint8Array(arrayBuffer)
await window.api.file.write(tempFilePath, uint8Array)
const selectedFile = await window.api.file.get(tempFilePath)
selectedFile && setFiles((prevFiles) => [...prevFiles, selectedFile])
break
} else {
window.message.info({
key: 'file_not_supported',
content: t('chat.input.file_not_supported')
})
}
continue
}
// 有路径的情况
if (supportExts.includes(getFileExtension(filePath))) {
const selectedFile = await window.api.file.get(filePath)
selectedFile && setFiles((prevFiles) => [...prevFiles, selectedFile])
} else {
window.message.info({
@ -612,6 +618,9 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
content: t('chat.input.file_not_supported')
})
}
} catch (error) {
Logger.error('[src/renderer/src/pages/home/Inputbar/Inputbar.tsx] onPaste:', error)
window.message.error(t('chat.input.file_error'))
}
}
return

View File

@ -3,14 +3,27 @@ import { FileType } from '@renderer/types'
export const getFilesFromDropEvent = async (e: React.DragEvent<HTMLDivElement>): Promise<FileType[]> => {
if (e.dataTransfer.files.length > 0) {
const results = await Promise.allSettled([...e.dataTransfer.files].map((file) => window.api.file.get(file.path)))
// 使用新的API获取文件路径
const filePromises = [...e.dataTransfer.files].map(async (file) => {
try {
// 使用新的webUtils.getPathForFile API获取文件路径
const filePath = window.api.file.getPathForFile(file)
if (filePath) {
return window.api.file.get(filePath)
}
return null
} catch (error) {
Logger.error('[src/renderer/src/utils/input.ts] getFilesFromDropEvent - getPathForFile error:', error)
return null
}
})
const results = await Promise.allSettled(filePromises)
const list: FileType[] = []
for (const result of results) {
if (result.status === 'fulfilled') {
if (result.value !== null) {
list.push(result.value)
}
} else {
if (result.status === 'fulfilled' && result.value !== null) {
list.push(result.value)
} else if (result.status === 'rejected') {
Logger.error('[src/renderer/src/utils/input.ts] getFilesFromDropEvent:', result.reason)
}
}