diff --git a/app/src/electron.js b/app/src/electron.js index e2d7f701..b5160ae1 100644 --- a/app/src/electron.js +++ b/app/src/electron.js @@ -86,7 +86,7 @@ function commandItem(item) { } function buildMenu() { - let template = _cloneDeepWith(mainMenuDefinition, item => { + let template = _cloneDeepWith(mainMenuDefinition({ editMenu: true }), item => { if (item.divider) { return { type: 'separator' }; } @@ -164,6 +164,9 @@ ipcMain.on('app-started', async (event, arg) => { } }); ipcMain.on('window-action', async (event, arg) => { + if (!mainWindow) { + return; + } switch (arg) { case 'minimize': mainWindow.minimize(); @@ -199,6 +202,23 @@ ipcMain.on('window-action', async (event, arg) => { case 'zoomreset': mainWindow.webContents.zoomLevel = 0; break; + + // edit + case 'undo': + mainWindow.webContents.undo(); + break; + case 'redo': + mainWindow.webContents.redo(); + break; + case 'cut': + mainWindow.webContents.cut(); + break; + case 'copy': + mainWindow.webContents.copy(); + break; + case 'paste': + mainWindow.webContents.paste(); + break; } }); diff --git a/app/src/mainMenuDefinition.js b/app/src/mainMenuDefinition.js index 94bcbd0e..8efc4c7d 100644 --- a/app/src/mainMenuDefinition.js +++ b/app/src/mainMenuDefinition.js @@ -1,4 +1,4 @@ -module.exports = [ +module.exports = ({ editMenu }) => [ { label: 'File', submenu: [ @@ -34,6 +34,20 @@ module.exports = [ ], }, + editMenu + ? { + label: 'Edit', + submenu: [ + { command: 'edit.undo' }, + { command: 'edit.redo' }, + { divider: true }, + { command: 'edit.cut' }, + { command: 'edit.copy' }, + { command: 'edit.paste' }, + ], + } + : null, + // { // label: 'Edit', // submenu: [ diff --git a/packages/web/src/commands/CommandListener.svelte b/packages/web/src/commands/CommandListener.svelte index 885de4b1..180cc875 100644 --- a/packages/web/src/commands/CommandListener.svelte +++ b/packages/web/src/commands/CommandListener.svelte @@ -13,7 +13,7 @@ keyText += e.key; const commandsValue = get(commandsCustomized); - const commandsFiltered: any = Object.values(commandsValue).filter( + let commandsFiltered: any = Object.values(commandsValue).filter( (x: any) => x.keyText && resolveKeyText(x.keyText) @@ -34,7 +34,20 @@ e.stopPropagation(); } + if ( + commandsFiltered.length > 1 && + commandsFiltered.find(x => x.systemCommand) && + commandsFiltered.find(x => !x.systemCommand) + ) { + commandsFiltered = commandsFiltered.filter(x => !x.systemCommand); + } + const notGroup = commandsFiltered.filter(x => x.enabled && !x.isGroupCommand); + + if (notGroup.length > 1) { + console.log('Warning, multiple commands mapped to', keyText, notGroup); + } + if (notGroup.length == 1) { const command = notGroup[0]; if (command.onClick) command.onClick(); @@ -44,6 +57,10 @@ const group = commandsFiltered.filter(x => x.enabled && x.isGroupCommand); + if (group.length > 1) { + console.log('Warning, multiple commands mapped to', keyText, group); + } + if (group.length == 1) { const command = group[0]; runGroupCommand(command.group); diff --git a/packages/web/src/commands/registerCommand.ts b/packages/web/src/commands/registerCommand.ts index c125f484..11753296 100644 --- a/packages/web/src/commands/registerCommand.ts +++ b/packages/web/src/commands/registerCommand.ts @@ -28,6 +28,7 @@ export interface GlobalCommand { toolbarOrder?: number; disableHandleKeyText?: string; isRelatedToTab?: boolean, + systemCommand?: boolean; } export default function registerCommand(command: GlobalCommand) { diff --git a/packages/web/src/commands/stdCommands.ts b/packages/web/src/commands/stdCommands.ts index 359b2c5c..297ecf15 100644 --- a/packages/web/src/commands/stdCommands.ts +++ b/packages/web/src/commands/stdCommands.ts @@ -690,6 +690,55 @@ registerCommand({ onClick: () => getElectron().send('window-action', 'zoomreset'), }); +registerCommand({ + id: 'edit.undo', + category: 'Edit', + name: 'Undo', + keyText: 'CtrlOrCommand+Z', + systemCommand: true, + testEnabled: () => getElectron() != null, + onClick: () => getElectron().send('window-action', 'undo'), +}); + +registerCommand({ + id: 'edit.redo', + category: 'Edit', + name: 'Redo', + systemCommand: true, + testEnabled: () => getElectron() != null, + onClick: () => getElectron().send('window-action', 'redo'), +}); + +registerCommand({ + id: 'edit.cut', + category: 'Edit', + name: 'Cut', + keyText: 'CtrlOrCommand+X', + systemCommand: true, + testEnabled: () => getElectron() != null, + onClick: () => getElectron().send('window-action', 'cut'), +}); + +registerCommand({ + id: 'edit.copy', + category: 'Edit', + name: 'Copy', + keyText: 'CtrlOrCommand+C', + systemCommand: true, + testEnabled: () => getElectron() != null, + onClick: () => getElectron().send('window-action', 'copy'), +}); + +registerCommand({ + id: 'edit.paste', + category: 'Edit', + name: 'Paste', + keyText: 'CtrlOrCommand+V', + systemCommand: true, + testEnabled: () => getElectron() != null, + onClick: () => getElectron().send('window-action', 'paste'), +}); + const electron = getElectron(); if (electron) { electron.addEventListener('run-command', (e, commandId) => runCommand(commandId)); diff --git a/packages/web/src/datagrid/DataGridCore.svelte b/packages/web/src/datagrid/DataGridCore.svelte index febd606c..ae351b1c 100644 --- a/packages/web/src/datagrid/DataGridCore.svelte +++ b/packages/web/src/datagrid/DataGridCore.svelte @@ -47,7 +47,7 @@ name: 'Insert new row', toolbarName: 'New row', icon: 'icon add', - keyText: 'Insert', + keyText: isMac() ? 'Command+I' : 'Insert', testEnabled: () => getCurrentDataGrid()?.getGrider()?.editable, onClick: () => getCurrentDataGrid().insertNewRow(), }); @@ -191,7 +191,6 @@ id: 'dataGrid.clearFilter', category: 'Data grid', name: 'Clear filter', - keyText: 'CtrlOrCommand+I', testEnabled: () => getCurrentDataGrid()?.clearFilterEnabled(), onClick: () => getCurrentDataGrid().clearFilter(), }); @@ -306,7 +305,7 @@ import EditJsonModal from '../modals/EditJsonModal.svelte'; import { apiCall } from '../utility/api'; import getElectron from '../utility/getElectron'; - import { isCtrlOrCommandKey } from '../utility/common'; + import { isCtrlOrCommandKey, isMac } from '../utility/common'; export let onLoadNextData = undefined; export let grider = undefined; diff --git a/packages/web/src/widgets/TitleBar.svelte b/packages/web/src/widgets/TitleBar.svelte index c91df8f8..38b2f799 100644 --- a/packages/web/src/widgets/TitleBar.svelte +++ b/packages/web/src/widgets/TitleBar.svelte @@ -16,7 +16,7 @@ {#if !isMac()}
{/if}
{title}
diff --git a/packages/web/src/widgets/WidgetIconPanel.svelte b/packages/web/src/widgets/WidgetIconPanel.svelte index 7c0e68a5..0bc12c0d 100644 --- a/packages/web/src/widgets/WidgetIconPanel.svelte +++ b/packages/web/src/widgets/WidgetIconPanel.svelte @@ -76,7 +76,7 @@ const rect = domMainMenu.getBoundingClientRect(); const left = rect.right; const top = rect.top; - const items = mainMenuDefinition; + const items = mainMenuDefinition({ editMenu: false }); currentDropDownMenu.set({ left, top, items }); }