diff --git a/src/main/libs/ShortcutRegister.ts b/src/main/libs/ShortcutRegister.ts index 45ff2996..b011a2c7 100644 --- a/src/main/libs/ShortcutRegister.ts +++ b/src/main/libs/ShortcutRegister.ts @@ -1,4 +1,4 @@ -import { BrowserWindow, globalShortcut } from 'electron'; +import { BrowserWindow, globalShortcut, Menu, MenuItem, MenuItemConstructorOptions } from 'electron'; import * as Store from 'electron-store'; import { ShortcutRecord, shortcuts } from 'common/shortcuts'; @@ -6,17 +6,27 @@ const shortcutsStore = new Store({ name: 'shortcuts' }); const isDevelopment = process.env.NODE_ENV !== 'production'; const defaultShortcuts = shortcuts.filter(s => s.os.includes(process.platform)); +export type ShortcutMode = 'local' | 'global' +export type OsMenu = { + [key in NodeJS.Platform]?: MenuItemConstructorOptions[]; +}; + export class ShortcutRegister { private _shortcuts: ShortcutRecord[]; private _mainWindow: BrowserWindow; + private _menu: Menu; + private _menuTemplate: OsMenu; + private _mode: ShortcutMode; private static _instance: ShortcutRegister; - private constructor (args: { mainWindow: BrowserWindow }) { + private constructor (args: { mainWindow: BrowserWindow; menuTemplate: OsMenu; mode: ShortcutMode }) { this._mainWindow = args.mainWindow; + this._menuTemplate = args.menuTemplate; + this._mode = args.mode; this.shortcuts = shortcutsStore.get('shortcuts', defaultShortcuts) as ShortcutRecord[]; } - public static getInstance (args: { mainWindow: BrowserWindow }) { + public static getInstance (args: { mainWindow: BrowserWindow; menuTemplate: OsMenu; mode: ShortcutMode }) { if (!ShortcutRegister._instance) ShortcutRegister._instance = new ShortcutRegister(args); @@ -33,24 +43,73 @@ export class ShortcutRegister { } init () { + this._mainWindow.webContents.send('update-shortcuts', this.shortcuts); + + this.buildBaseMenu(); + + if (this._mode === 'global') + this.setGlobalShortcuts(); + else if (this._mode === 'local') + this.setLocalShortcuts(); + else + throw new Error(`Unknown mode "${this._mode}"`); + + Menu.setApplicationMenu(this._menu); + } + + private buildBaseMenu () { + if (Object.keys(this._menuTemplate).includes(process.platform)) + this._menu = Menu.buildFromTemplate(this._menuTemplate[process.platform]); + else + this._menu = new Menu(); + } + + private setLocalShortcuts () { for (const shortcut of this.shortcuts) { if (shortcut.os.includes(process.platform)) { for (const key of shortcut.keys) { try { - globalShortcut.register(key, () => { - this._mainWindow.webContents.send(shortcut.event); - if (isDevelopment) console.log('EVENT:', shortcut); - }); + this._menu.append(new MenuItem({ + label: 'Shortcuts', + submenu: [{ + label: String(key), + accelerator: key, + visible: false, + click: () => { + this._mainWindow.webContents.send(shortcut.event); + if (isDevelopment) console.log('LOCAL EVENT:', shortcut); + } + }] + })); } catch (error) { + if (isDevelopment) console.log(error); this.restoreDefaults(); throw error; } } } } + } - this._mainWindow.webContents.send('update-shortcuts', this.shortcuts); + private setGlobalShortcuts () { + for (const shortcut of this.shortcuts) { + if (shortcut.os.includes(process.platform)) { + for (const key of shortcut.keys) { + try { + globalShortcut.register(key, () => { + this._mainWindow.webContents.send(shortcut.event); + if (isDevelopment) console.log('GLOBAL EVENT:', shortcut); + }); + } + catch (error) { + if (isDevelopment) console.log(error); + this.restoreDefaults(); + throw error; + } + } + } + } } reload () { @@ -69,6 +128,6 @@ export class ShortcutRegister { } unregister () { - globalShortcut.unregisterAll(); + if (this._mode === 'global') globalShortcut.unregisterAll(); } } diff --git a/src/main/main.ts b/src/main/main.ts index 744e7167..66848df7 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -1,16 +1,14 @@ -import { app, BrowserWindow, globalShortcut, nativeImage, Menu, ipcMain } from 'electron'; +import { app, BrowserWindow, nativeImage, ipcMain } from 'electron'; import * as path from 'path'; import * as Store from 'electron-store'; import * as windowStateKeeper from 'electron-window-state'; import * as remoteMain from '@electron/remote/main'; import ipcHandlers from './ipc-handlers'; -import { ShortcutRegister } from './libs/ShortcutRegister'; +import { OsMenu, ShortcutRegister } from './libs/ShortcutRegister'; Store.initRenderer(); const settingsStore = new Store({ name: 'settings' }); - -let shortCutRegister: ShortcutRegister; const appTheme = settingsStore.get('application_theme'); const isDevelopment = process.env.NODE_ENV !== 'production'; const isMacOS = process.platform === 'darwin'; @@ -122,32 +120,12 @@ else { mainWindow = await createMainWindow(); createAppMenu(); - shortCutRegister = ShortcutRegister.getInstance({ mainWindow }); - if (isWindows) mainWindow.show(); if (isDevelopment) mainWindow.webContents.openDevTools(); - app.on('browser-window-focus', () => { - // Send registered shortcut events to window - shortCutRegister.init(); - - if (isDevelopment) { // Dev shortcuts - globalShortcut.register('Shift+CommandOrControl+F5', () => { - mainWindow.reload(); - }); - globalShortcut.register('Shift+CommandOrControl+F12', () => { - mainWindow.webContents.openDevTools(); - }); - } - }); - - app.on('browser-window-blur', () => { - shortCutRegister.unregister(); - }); - process.on('uncaughtException', error => { mainWindow.webContents.send('unhandled-exception', error); }); @@ -167,10 +145,8 @@ else { } function createAppMenu () { - let menu: Electron.Menu = null; - - if (isMacOS) { - menu = Menu.buildFromTemplate([ + const menuTemplate: OsMenu = { + darwin: [ { label: app.name, submenu: [ @@ -201,10 +177,11 @@ function createAppMenu () { { role: 'windowMenu' } - ]); - } + ] + }; - Menu.setApplicationMenu(menu); + const shortCutRegister = ShortcutRegister.getInstance({ mainWindow, menuTemplate, mode: 'local' }); + shortCutRegister.init(); } function saveWindowState () { diff --git a/src/renderer/components/WorkspaceTabQueryTable.vue b/src/renderer/components/WorkspaceTabQueryTable.vue index 3108f566..c1d9733d 100644 --- a/src/renderer/components/WorkspaceTabQueryTable.vue +++ b/src/renderer/components/WorkspaceTabQueryTable.vue @@ -611,7 +611,7 @@ const onKey = async (e: KeyboardEvent) => { selectAllRows(e); // row navigation stuff - if ((e.code.includes('Arrow') || e.code === 'Tab') && sortedResults.value.length > 0 && !e.altKey) { + if (!(e.ctrlKey || e.metaKey) && (e.code.includes('Arrow') || e.code === 'Tab') && sortedResults.value.length > 0 && !e.altKey) { e.preventDefault(); const aviableFields= Object.keys(sortedResults.value[0]).slice(0, -1); // removes _antares_id