chore: upgrade Electron to 44.5.1 and adapt clipboard APIs
This commit is contained in:
@@ -148,7 +148,7 @@ async function main() {
|
||||
[
|
||||
'appId: live.digiman.goodbuddy.harness-smoke',
|
||||
'productName: GoodBuddyHarnessSmoke',
|
||||
'electronVersion: "43.2.0"',
|
||||
`electronVersion: "${require('electron/package.json').version}"`,
|
||||
'asar: true',
|
||||
'npmRebuild: false',
|
||||
'files:',
|
||||
|
||||
@@ -10,7 +10,7 @@ Debian `loong64` 桌面,不代表 GoodBuddy 已将龙芯纳入正式发布支
|
||||
均为 LoongArch ELF。
|
||||
|
||||
预览版使用社区维护的 Electron 42.3.0 LoongArch 构建。GoodBuddy 正式版本
|
||||
当前使用 Electron 43.2.0,因此该预览包只用于移植和真机验证,不能作为正式
|
||||
当前使用 Electron 44.5.1,因此该预览包只用于移植和真机验证,不能作为正式
|
||||
发布基线。Electron 官方目前也不提供 Linux LoongArch 预编译包。
|
||||
|
||||
已完成的实际构建结果:
|
||||
|
||||
Generated
+4
-4
@@ -84,7 +84,7 @@
|
||||
"@xterm/addon-search": "0.16.0",
|
||||
"@xterm/addon-webgl": "0.19.0",
|
||||
"@xterm/xterm": "6.0.0",
|
||||
"electron": "^43.2.0",
|
||||
"electron": "^44.5.1",
|
||||
"electron-builder": "^26.15.3",
|
||||
"electron-vite": "^5.0.0",
|
||||
"esbuild": "0.25.12",
|
||||
@@ -14755,9 +14755,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron": {
|
||||
"version": "43.2.0",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-43.2.0.tgz",
|
||||
"integrity": "sha512-80zvrgG7ZRXD+tD0IyLvrnN9n+veSxadMRsMaC9wKKP3iUbtC7rGM8+dVuCmOb0Rrwwv8ESW4awnUZh9Hbp1fA==",
|
||||
"version": "44.5.1",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-44.5.1.tgz",
|
||||
"integrity": "sha512-lx7AYoFIiyvEvgvpyWO9kOC60xtNPpiPZAth6Fmg9NutzpCAMLwpUlaBY2EXfZyIgUdzEmLMj9KvK0Vrokl1yQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
||||
+1
-1
@@ -385,7 +385,7 @@
|
||||
"@xterm/addon-search": "0.16.0",
|
||||
"@xterm/addon-webgl": "0.19.0",
|
||||
"@xterm/xterm": "6.0.0",
|
||||
"electron": "^43.2.0",
|
||||
"electron": "^44.5.1",
|
||||
"electron-builder": "^26.15.3",
|
||||
"electron-vite": "^5.0.0",
|
||||
"esbuild": "0.25.12",
|
||||
|
||||
@@ -4,13 +4,16 @@ import { basename, join } from 'node:path'
|
||||
import { strToU8, zipSync } from 'fflate'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
const { createFromBuffer, getSources, showOpenDialog } = vi.hoisted(() => ({
|
||||
const { createFromBuffer, getSources, showOpenDialog, readText, readClipboard } = vi.hoisted(() => ({
|
||||
readText: vi.fn(),
|
||||
readClipboard: vi.fn(),
|
||||
createFromBuffer: vi.fn(),
|
||||
getSources: vi.fn(),
|
||||
showOpenDialog: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('electron', () => ({
|
||||
clipboard: { readText, read: readClipboard },
|
||||
desktopCapturer: {
|
||||
getSources
|
||||
},
|
||||
@@ -31,6 +34,8 @@ import { defaultDocumentParsingSettings } from './document-parsing-settings-stor
|
||||
const temporaryDirectories: string[] = []
|
||||
|
||||
afterEach(async () => {
|
||||
readText.mockReset()
|
||||
readClipboard.mockReset()
|
||||
getSources.mockReset()
|
||||
showOpenDialog.mockReset()
|
||||
createFromBuffer.mockReset()
|
||||
@@ -42,6 +47,40 @@ afterEach(async () => {
|
||||
})
|
||||
|
||||
describe('ContextManager', () => {
|
||||
it('awaits clipboard text and prefers it over images', async () => {
|
||||
readText.mockResolvedValue(' clipboard text ')
|
||||
const manager = new ContextManager()
|
||||
const attachment = await manager.readClipboard()
|
||||
expect(attachment.kind).toBe('text')
|
||||
expect(attachment.preview).toContain('clipboard text')
|
||||
expect(readClipboard).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('decodes an asynchronous clipboard PNG when text is empty', async () => {
|
||||
readText.mockResolvedValue('')
|
||||
const data = Buffer.from([0x89, 0x50, 0x4e, 0x47])
|
||||
const getType = vi.fn().mockResolvedValue(new Blob([data]))
|
||||
readClipboard.mockResolvedValue([{ types: ['image/png'], getType }])
|
||||
const image = {
|
||||
isEmpty: () => false,
|
||||
getSize: () => ({ width: 640, height: 480 }),
|
||||
resize: vi.fn(),
|
||||
toJPEG: () => Buffer.from([0xff, 0xd8, 0xff, 0xd9])
|
||||
}
|
||||
image.resize.mockReturnValue(image)
|
||||
createFromBuffer.mockReturnValue(image)
|
||||
const attachment = await new ContextManager().readClipboard()
|
||||
expect(getType).toHaveBeenCalledWith('image/png')
|
||||
expect(createFromBuffer).toHaveBeenCalledWith(data)
|
||||
expect(attachment.kind).toBe('image')
|
||||
})
|
||||
|
||||
it('rejects a clipboard without text or a supported image', async () => {
|
||||
readText.mockResolvedValue('')
|
||||
readClipboard.mockResolvedValue([{ types: ['text/html'] }])
|
||||
await expect(new ContextManager().readClipboard()).rejects.toThrow('剪贴板中没有可用的文本或图片')
|
||||
})
|
||||
|
||||
it('preserves logical attachment identity and frozen message bytes across a draft reparse', async () => {
|
||||
const directory = await mkdtemp(join(tmpdir(), 'goodbuddy-reparse-'))
|
||||
temporaryDirectories.push(directory)
|
||||
|
||||
@@ -568,14 +568,18 @@ export class ContextManager {
|
||||
)
|
||||
}
|
||||
|
||||
readClipboard(): ContextAttachment {
|
||||
const text = clipboard.readText().trim()
|
||||
async readClipboard(): Promise<ContextAttachment> {
|
||||
const text = (await clipboard.readText()).trim()
|
||||
if (text) {
|
||||
return this.storeText('剪贴板文本.txt', text)
|
||||
}
|
||||
const image = clipboard.readImage()
|
||||
if (!image.isEmpty()) {
|
||||
return this.storeImage('剪贴板图片.png', image)
|
||||
for (const item of await clipboard.read()) {
|
||||
if (!item.types.includes('image/png')) continue
|
||||
const blob = await item.getType('image/png')
|
||||
const image = nativeImage.createFromBuffer(Buffer.from(await blob.arrayBuffer()))
|
||||
if (!image.isEmpty()) {
|
||||
return this.storeImage('剪贴板图片.png', image)
|
||||
}
|
||||
}
|
||||
throw new Error('剪贴板中没有可用的文本或图片')
|
||||
}
|
||||
|
||||
@@ -264,9 +264,9 @@ describe('terminal IPC boundary', () => {
|
||||
snapshot.sessionId
|
||||
)
|
||||
|
||||
expect(
|
||||
await expect(
|
||||
electronMocks.handlers.get(ipcChannels.clipboardReadText)?.(event)
|
||||
).toBe('Get-Location\r')
|
||||
).resolves.toBe('Get-Location\r')
|
||||
expect(electronMocks.readClipboardText).toHaveBeenCalledOnce()
|
||||
|
||||
electronMocks.handlers.get(ipcChannels.clipboardWriteText)?.(
|
||||
@@ -353,8 +353,8 @@ const electronMocks = vi.hoisted(() => {
|
||||
openPath: vi.fn(async () => ''),
|
||||
showItemInFolder: vi.fn(),
|
||||
openExternal: vi.fn(async () => undefined),
|
||||
readClipboardText: vi.fn(() => 'Get-Location\r'),
|
||||
writeClipboardText: vi.fn()
|
||||
readClipboardText: vi.fn(async () => 'Get-Location\r'),
|
||||
writeClipboardText: vi.fn(async () => {})
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -10,12 +10,12 @@ export function registerClipboardIpcHandlers(
|
||||
): void {
|
||||
registerHandler(ipcChannels.clipboardReadText, (event) => {
|
||||
assertTrustedSender(event, window)
|
||||
return clipboardTextSchema.parse(clipboard.readText())
|
||||
return clipboard.readText().then((text) => clipboardTextSchema.parse(text))
|
||||
})
|
||||
|
||||
registerHandler(ipcChannels.clipboardWriteText, (event, input) => {
|
||||
assertTrustedSender(event, window)
|
||||
clipboard.writeText(clipboardTextSchema.parse(input))
|
||||
return clipboard.writeText(clipboardTextSchema.parse(input))
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user