diff --git a/apps/desktop/README.i18n.yaml b/apps/desktop/README.i18n.yaml index 899796c03a..34fb13cb74 100644 --- a/apps/desktop/README.i18n.yaml +++ b/apps/desktop/README.i18n.yaml @@ -33,8 +33,8 @@ en: 372297005b57a08b zh: 074a635ac17e4362 /deepseek-harness-desktop/installation-ownership: - en: 160b500cdcd6a39a - zh: 6c267f1762ec3689 + en: 9de048b0c7aa1b39 + zh: dbfeffa96db912b9 /deepseek-harness-desktop/installation-ownership/runtime-and-plugin-activation: en: 4951cd3ee659eb33 zh: 96bdd6358dad587a diff --git a/apps/desktop/README.md b/apps/desktop/README.md index bf36a7b9fe..9373150f89 100644 --- a/apps/desktop/README.md +++ b/apps/desktop/README.md @@ -161,7 +161,7 @@ Windows and macOS relay native fullscreen transitions and the state after each p Windows uses a 40-DIP caption with native window controls and colors synchronized from the application palette. Localized Application and Edit entries beside the sidebar toggle open native popup menus. They mount only after the application frame publishes its shell overlay seat, and remain absent during startup loading. Application provides Check for Updates and Exit; Edit provides undo, redo, cut, copy, paste, delete, and select all by sending the corresponding keys to the focused editor, independently of custom shortcut bindings. Plugin management uses the main application's Plugins page. No separate native menu row appears on Alt. Other platforms retain their native menus. Editable fields retain keyboard commands and a context menu without shortcut labels; Chromium supplies command availability, and selected read-only text offers Copy. -On macOS the custom menu retains Electron's standard Window menu and application hide commands, including Minimize (⌘M) and Hide (⌘H). Linux keeps the application and Edit menus. +On macOS the custom menu retains Electron's standard Window menu and application hide commands, including Minimize (⌘M) and Hide (⌘H). Its Edit menu binds Paste and Match Style to ⇧⌘V and keeps Electron's ⌥⇧⌘V as a hidden alias. Linux keeps the application and Edit menus. ### Runtime and plugin activation diff --git a/apps/desktop/README.zh.md b/apps/desktop/README.zh.md index 6241072116..dfcc4b40b4 100644 --- a/apps/desktop/README.zh.md +++ b/apps/desktop/README.zh.md @@ -161,7 +161,7 @@ Windows 和 macOS 会在原生全屏切换及每次页面加载后向渲染器 Windows 使用 40 DIP 顶栏,保留原生窗口按钮,颜色随应用调色板同步。侧栏开关旁的本地化“应用”和“编辑”入口打开原生弹出菜单。仅当应用框架发布 shell overlay 席位后才挂载菜单,启动加载期间不显示。“应用”提供检查更新和退出;“编辑”向当前编辑器发送对应按键,提供撤销、重做、剪切、复制、粘贴、删除和全选,不受自定义快捷键绑定影响。插件管理使用主应用的“插件”页面。按 Alt 不会出现额外的原生菜单行。其他平台保留原生菜单。可编辑区域保留快捷键和不带快捷键标注的右键菜单;命令可用状态由 Chromium 提供,选中的只读文本提供“复制”命令。 -macOS 上自定义菜单保留 Electron 的标准 Window 菜单及应用隐藏命令,包括 Minimize(⌘M)和 Hide(⌘H)。Linux 保留应用菜单和 Edit 菜单。 +macOS 上自定义菜单保留 Electron 的标准 Window 菜单及应用隐藏命令,包括 Minimize(⌘M)和 Hide(⌘H)。其 Edit 菜单把 Paste and Match Style 绑定到 ⇧⌘V,并保留 Electron 默认的 ⌥⇧⌘V 作为隐藏别名。Linux 保留应用菜单和 Edit 菜单。 ### 运行时与插件激活 diff --git a/apps/desktop/src/main.ts b/apps/desktop/src/main.ts index 4c223c3c09..395e2d12db 100644 --- a/apps/desktop/src/main.ts +++ b/apps/desktop/src/main.ts @@ -1043,8 +1043,20 @@ async function main(): Promise { // its standard menus and application hide commands declared explicitly. // Keep app.name stable: Electron derives its default userData directory from it. const darwin = process.platform === 'darwin' + // A copy of Electron's macOS Edit menu, with its English labels, that binds Paste and Match + // Style to Shift+Command+V as chat and document apps do; Electron's Option+Shift+Command+V stays as a hidden alias. + const macEditMenu: MenuItemConstructorOptions = { role: 'editMenu', submenu: [ + { role: 'undo' }, { role: 'redo' }, { type: 'separator' }, + { role: 'cut' }, { role: 'copy' }, { role: 'paste' }, + { role: 'pasteAndMatchStyle', accelerator: 'Shift+Command+V' }, + { role: 'pasteAndMatchStyle', accelerator: 'Option+Shift+Command+V', visible: false }, + { role: 'delete' }, { role: 'selectAll' }, { type: 'separator' }, + { label: 'Substitutions', submenu: [{ role: 'showSubstitutions' }, { type: 'separator' }, + { role: 'toggleSmartQuotes' }, { role: 'toggleSmartDashes' }, { role: 'toggleTextReplacement' }] }, + { label: 'Speech', submenu: [{ role: 'startSpeaking' }, { role: 'stopSpeaking' }] }, + ] } const platformMenus = (): MenuItemConstructorOptions[] => darwin - ? [shortcuts.fileMenu(currentDesktopLocale().messages), { role: 'editMenu' }, { role: 'windowMenu' }] + ? [shortcuts.fileMenu(currentDesktopLocale().messages), macEditMenu, { role: 'windowMenu' }] : [{ role: 'editMenu' }] const hideCommands: MenuItemConstructorOptions[] = darwin ? [{ role: 'hide', label: currentDesktopLocale().messages.hideApplication }, diff --git a/apps/desktop/tests/main-startup.spec.ts b/apps/desktop/tests/main-startup.spec.ts index 924808eb0d..13513cca7c 100644 --- a/apps/desktop/tests/main-startup.spec.ts +++ b/apps/desktop/tests/main-startup.spec.ts @@ -1109,6 +1109,14 @@ describe('desktop main startup', () => { expect(template.map(describeItem)).toEqual(platform === 'darwin' ? ['Desktop test', en.fileMenu, 'editMenu', 'windowMenu'] : ['Application', 'editMenu']) + const edit = template.find(item => item.role === 'editMenu')!.submenu as MenuItemConstructorOptions[] | undefined + expect(edit?.map(item => [describeItem(item), item.accelerator, item.visible])).toEqual(platform === 'darwin' + ? [['undo', undefined, undefined], ['redo', undefined, undefined], ['separator', undefined, undefined], + ['cut', undefined, undefined], ['copy', undefined, undefined], ['paste', undefined, undefined], + ['pasteAndMatchStyle', 'Shift+Command+V', undefined], ['pasteAndMatchStyle', 'Option+Shift+Command+V', false], + ['delete', undefined, undefined], ['selectAll', undefined, undefined], ['separator', undefined, undefined], + ['Substitutions', undefined, undefined], ['Speech', undefined, undefined]] + : undefined) const application = template[0]!.submenu as MenuItemConstructorOptions[] expect(application.filter(item => item.visible !== false).map(describeItem)).toEqual(platform === 'darwin' ? ['about', 'separator', en.checkUpdatesMenu, en.cliCommandMenu, 'separator', 'toggleDevTools', 'separator', 'hide', 'hideOthers', 'unhide', 'separator', 'quit']