mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-11 08:19:01 +08:00
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:
parent
51071d65fb
commit
f84358adfd
@ -2,7 +2,7 @@ import type { ExtractChunkData } from '@cherrystudio/embedjs-interfaces'
|
|||||||
import { electronAPI } from '@electron-toolkit/preload'
|
import { electronAPI } from '@electron-toolkit/preload'
|
||||||
import { IpcChannel } from '@shared/IpcChannel'
|
import { IpcChannel } from '@shared/IpcChannel'
|
||||||
import { FileType, KnowledgeBaseParams, KnowledgeItem, MCPServer, Shortcut, WebDavConfig } from '@types'
|
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'
|
import { CreateDirectoryOptions } from 'webdav'
|
||||||
|
|
||||||
// Custom APIs for renderer
|
// Custom APIs for renderer
|
||||||
@ -73,7 +73,8 @@ const api = {
|
|||||||
download: (url: string) => ipcRenderer.invoke(IpcChannel.File_Download, url),
|
download: (url: string) => ipcRenderer.invoke(IpcChannel.File_Download, url),
|
||||||
copy: (fileId: string, destPath: string) => ipcRenderer.invoke(IpcChannel.File_Copy, fileId, destPath),
|
copy: (fileId: string, destPath: string) => ipcRenderer.invoke(IpcChannel.File_Copy, fileId, destPath),
|
||||||
binaryImage: (fileId: string) => ipcRenderer.invoke(IpcChannel.File_BinaryImage, fileId),
|
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: {
|
fs: {
|
||||||
read: (path: string) => ipcRenderer.invoke(IpcChannel.Fs_Read, path)
|
read: (path: string) => ipcRenderer.invoke(IpcChannel.Fs_Read, path)
|
||||||
|
|||||||
@ -163,6 +163,7 @@
|
|||||||
"input.estimated_tokens.tip": "Estimated tokens",
|
"input.estimated_tokens.tip": "Estimated tokens",
|
||||||
"input.expand": "Expand",
|
"input.expand": "Expand",
|
||||||
"input.file_not_supported": "Model does not support this file type",
|
"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": "Generate image",
|
||||||
"input.generate_image_not_supported": "The model does not support generating images.",
|
"input.generate_image_not_supported": "The model does not support generating images.",
|
||||||
"input.knowledge_base": "Knowledge Base",
|
"input.knowledge_base": "Knowledge Base",
|
||||||
|
|||||||
@ -163,6 +163,7 @@
|
|||||||
"input.estimated_tokens.tip": "推定トークン数",
|
"input.estimated_tokens.tip": "推定トークン数",
|
||||||
"input.expand": "展開",
|
"input.expand": "展開",
|
||||||
"input.file_not_supported": "モデルはこのファイルタイプをサポートしません",
|
"input.file_not_supported": "モデルはこのファイルタイプをサポートしません",
|
||||||
|
"input.file_error": "ファイル処理エラー",
|
||||||
"input.generate_image": "画像を生成する",
|
"input.generate_image": "画像を生成する",
|
||||||
"input.generate_image_not_supported": "モデルは画像の生成をサポートしていません。",
|
"input.generate_image_not_supported": "モデルは画像の生成をサポートしていません。",
|
||||||
"input.knowledge_base": "ナレッジベース",
|
"input.knowledge_base": "ナレッジベース",
|
||||||
|
|||||||
@ -163,6 +163,7 @@
|
|||||||
"input.estimated_tokens.tip": "Затраты токенов",
|
"input.estimated_tokens.tip": "Затраты токенов",
|
||||||
"input.expand": "Развернуть",
|
"input.expand": "Развернуть",
|
||||||
"input.file_not_supported": "Модель не поддерживает этот тип файла",
|
"input.file_not_supported": "Модель не поддерживает этот тип файла",
|
||||||
|
"input.file_error": "Ошибка обработки файла",
|
||||||
"input.generate_image": "Сгенерировать изображение",
|
"input.generate_image": "Сгенерировать изображение",
|
||||||
"input.generate_image_not_supported": "Модель не поддерживает генерацию изображений.",
|
"input.generate_image_not_supported": "Модель не поддерживает генерацию изображений.",
|
||||||
"input.knowledge_base": "База знаний",
|
"input.knowledge_base": "База знаний",
|
||||||
|
|||||||
@ -163,6 +163,7 @@
|
|||||||
"input.estimated_tokens.tip": "预估 token 数",
|
"input.estimated_tokens.tip": "预估 token 数",
|
||||||
"input.expand": "展开",
|
"input.expand": "展开",
|
||||||
"input.file_not_supported": "模型不支持此文件类型",
|
"input.file_not_supported": "模型不支持此文件类型",
|
||||||
|
"input.file_error": "文件处理出错",
|
||||||
"input.generate_image": "生成图片",
|
"input.generate_image": "生成图片",
|
||||||
"input.generate_image_not_supported": "模型不支持生成图片",
|
"input.generate_image_not_supported": "模型不支持生成图片",
|
||||||
"input.knowledge_base": "知识库",
|
"input.knowledge_base": "知识库",
|
||||||
|
|||||||
@ -163,6 +163,7 @@
|
|||||||
"input.estimated_tokens.tip": "預估 Token 數",
|
"input.estimated_tokens.tip": "預估 Token 數",
|
||||||
"input.expand": "展開",
|
"input.expand": "展開",
|
||||||
"input.file_not_supported": "模型不支援此檔案類型",
|
"input.file_not_supported": "模型不支援此檔案類型",
|
||||||
|
"input.file_error": "檔案處理錯誤",
|
||||||
"input.generate_image": "生成圖片",
|
"input.generate_image": "生成圖片",
|
||||||
"input.generate_image_not_supported": "模型不支援生成圖片",
|
"input.generate_image_not_supported": "模型不支援生成圖片",
|
||||||
"input.knowledge_base": "知識庫",
|
"input.knowledge_base": "知識庫",
|
||||||
|
|||||||
@ -584,27 +584,33 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
|||||||
if (event.clipboardData?.files && event.clipboardData.files.length > 0) {
|
if (event.clipboardData?.files && event.clipboardData.files.length > 0) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
for (const file of event.clipboardData.files) {
|
for (const file of event.clipboardData.files) {
|
||||||
if (file.path === '') {
|
try {
|
||||||
// 图像生成也支持图像编辑
|
// 使用新的API获取文件路径
|
||||||
if (file.type.startsWith('image/') && (isVisionModel(model) || isGenerateImageModel(model))) {
|
const filePath = window.api.file.getPathForFile(file)
|
||||||
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')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file.path) {
|
// 如果没有路径,可能是剪贴板中的图像数据
|
||||||
if (supportExts.includes(getFileExtension(file.path))) {
|
if (!filePath) {
|
||||||
const selectedFile = await window.api.file.get(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')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 有路径的情况
|
||||||
|
if (supportExts.includes(getFileExtension(filePath))) {
|
||||||
|
const selectedFile = await window.api.file.get(filePath)
|
||||||
selectedFile && setFiles((prevFiles) => [...prevFiles, selectedFile])
|
selectedFile && setFiles((prevFiles) => [...prevFiles, selectedFile])
|
||||||
} else {
|
} else {
|
||||||
window.message.info({
|
window.message.info({
|
||||||
@ -612,6 +618,9 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
|||||||
content: t('chat.input.file_not_supported')
|
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
|
return
|
||||||
|
|||||||
@ -3,14 +3,27 @@ import { FileType } from '@renderer/types'
|
|||||||
|
|
||||||
export const getFilesFromDropEvent = async (e: React.DragEvent<HTMLDivElement>): Promise<FileType[]> => {
|
export const getFilesFromDropEvent = async (e: React.DragEvent<HTMLDivElement>): Promise<FileType[]> => {
|
||||||
if (e.dataTransfer.files.length > 0) {
|
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[] = []
|
const list: FileType[] = []
|
||||||
for (const result of results) {
|
for (const result of results) {
|
||||||
if (result.status === 'fulfilled') {
|
if (result.status === 'fulfilled' && result.value !== null) {
|
||||||
if (result.value !== null) {
|
list.push(result.value)
|
||||||
list.push(result.value)
|
} else if (result.status === 'rejected') {
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Logger.error('[src/renderer/src/utils/input.ts] getFilesFromDropEvent:', result.reason)
|
Logger.error('[src/renderer/src/utils/input.ts] getFilesFromDropEvent:', result.reason)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user