From 44420c00f00b69604b14421b5b5c922e8c807c3c Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Fri, 29 Nov 2024 11:45:28 +0200 Subject: [PATCH 01/61] Add ability to return menu template --- src/create-menu/index.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/create-menu/index.js b/src/create-menu/index.js index 6601db65..e3a903bd 100644 --- a/src/create-menu/index.js +++ b/src/create-menu/index.js @@ -275,6 +275,10 @@ module.exports = (params) => { } ] + if (params?.shouldMenuTemplateBeReturned) { + return menuTemplate + } + Menu.setApplicationMenu(Menu.buildFromTemplate(menuTemplate)) isMenuInitialized = true } From 6dcfab55e2ea95e3e22cd8bc2117cbcfd7637816 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Fri, 29 Nov 2024 11:46:12 +0200 Subject: [PATCH 02/61] Add menu ipc channel handlers --- .../menu-ipc-channel-handlers.js | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js diff --git a/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js b/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js new file mode 100644 index 00000000..3ca85a33 --- /dev/null +++ b/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js @@ -0,0 +1,30 @@ +'use strict' + +const IpcChannelHandlers = require('./ipc.channel.handlers') +const createMenu = require('../../create-menu') + +class MenuIpcChannelHandlers extends IpcChannelHandlers { + static channelName = 'menu' + + #menuTemplateFactory () { + if (this.menuTemplate) { + return this.menuTemplate + } + + this.menuTemplate = createMenu({ + shouldMenuTemplateBeReturned: true + }) + + return this.menuTemplate + } + + async getMenuTemplateHandler (event, args) { + const menuTemplate = createMenu({ + shouldMenuTemplateBeReturned: true + }) + + return menuTemplate + } +} + +module.exports = MenuIpcChannelHandlers From 02d1dc768777d96d7bb9cc51e17ecadcb46f64cf Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Fri, 29 Nov 2024 11:46:51 +0200 Subject: [PATCH 03/61] Add helper to init ipc channel handlers from list --- src/helpers/index.js | 4 +++- src/helpers/utils.js | 9 ++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/helpers/index.js b/src/helpers/index.js index ceb4e425..4c2866a9 100644 --- a/src/helpers/index.js +++ b/src/helpers/index.js @@ -7,7 +7,8 @@ const { serializeError, deserializeError, rm, - getServerPromise + getServerPromise, + initIpcChannelHandlers } = require('./utils') const isMainWinAvailable = require( './is-main-win-available' @@ -25,6 +26,7 @@ module.exports = { deserializeError, rm, getServerPromise, + initIpcChannelHandlers, isMainWinAvailable, productName, getAlertCustomClassObj, diff --git a/src/helpers/utils.js b/src/helpers/utils.js index 75509573..b7e57d63 100644 --- a/src/helpers/utils.js +++ b/src/helpers/utils.js @@ -98,9 +98,16 @@ const getServerPromise = (srv, port) => { }) } +const initIpcChannelHandlers = (...ipcChannelHandlersList) => { + for (const IpcChannelHandlers of ipcChannelHandlersList) { + IpcChannelHandlers.create() + } +} + module.exports = { serializeError, deserializeError, rm, - getServerPromise + getServerPromise, + initIpcChannelHandlers } From 5ea28ca291198bb8e0f15c2d7d570051a2da6712 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Fri, 29 Nov 2024 11:47:29 +0200 Subject: [PATCH 04/61] Init menu ipc channel handlers --- src/initialize-app.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/initialize-app.js b/src/initialize-app.js index ebceb062..9d01f0ee 100644 --- a/src/initialize-app.js +++ b/src/initialize-app.js @@ -12,6 +12,9 @@ const TranslationIpcChannelHandlers = require( const GeneralIpcChannelHandlers = require( './window-creators/main-renderer-ipc-bridge/general-ipc-channel-handlers' ) +const MenuIpcChannelHandlers = require( + './window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers' +) const triggerSyncAfterUpdates = require('./trigger-sync-after-updates') const triggerElectronLoad = require('./trigger-electron-load') const runServer = require('./run-server') @@ -32,7 +35,8 @@ const { } = require('./errors') const { deserializeError, - getFreePort + getFreePort, + initIpcChannelHandlers } = require('./helpers') const getUserDataPath = require('./helpers/get-user-data-path') const { @@ -159,8 +163,11 @@ const _manageConfigs = (params = {}) => { module.exports = async () => { try { - GeneralIpcChannelHandlers.create() - TranslationIpcChannelHandlers.create() + initIpcChannelHandlers( + GeneralIpcChannelHandlers, + TranslationIpcChannelHandlers, + MenuIpcChannelHandlers + ) app.on('window-all-closed', () => { app.quit() From 4e8268a9a5c400bf8b4c4c555975b8f7a78159d8 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Fri, 29 Nov 2024 11:48:35 +0200 Subject: [PATCH 05/61] Add menu invoke method names into preload script --- src/window-creators/main-renderer-ipc-bridge/preload.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/window-creators/main-renderer-ipc-bridge/preload.js b/src/window-creators/main-renderer-ipc-bridge/preload.js index 5cebe74c..2f2a2be5 100644 --- a/src/window-creators/main-renderer-ipc-bridge/preload.js +++ b/src/window-creators/main-renderer-ipc-bridge/preload.js @@ -5,7 +5,8 @@ const isTestEnv = process.env.NODE_ENV === 'test' const CHANNEL_NAMES = { GENERAL: 'general', - TRANSLATIONS: 'translations' + TRANSLATIONS: 'translations', + MENU: 'menu' } const GENERAL_INVOKE_METHOD_NAMES = { @@ -21,10 +22,14 @@ const TRANSLATIONS_INVOKE_METHOD_NAMES = { GET_AVAILABLE_LANGUAGES: 'getAvailableLanguages', TRANSLATE: 'translate' } +const MENU_INVOKE_METHOD_NAMES = { + GET_MENU_TEMPLATE: 'getMenuTemplate' +} const INVOKE_CHANNEL_MAP = new Map([ [CHANNEL_NAMES.GENERAL, GENERAL_INVOKE_METHOD_NAMES], - [CHANNEL_NAMES.TRANSLATIONS, TRANSLATIONS_INVOKE_METHOD_NAMES] + [CHANNEL_NAMES.TRANSLATIONS, TRANSLATIONS_INVOKE_METHOD_NAMES], + [CHANNEL_NAMES.MENU, MENU_INVOKE_METHOD_NAMES] ]) const EVENT_CHANNEL_MAP = new Map([ [CHANNEL_NAMES.GENERAL, GENERAL_EVENT_METHOD_NAMES] From 97250d1def80bf6ef5f6669dba566242d7f706c5 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Fri, 29 Nov 2024 11:48:58 +0200 Subject: [PATCH 06/61] Add ability to remove the default title bar --- src/window-creators/index.js | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/window-creators/index.js b/src/window-creators/index.js index b17c5cf7..c0bfe435 100644 --- a/src/window-creators/index.js +++ b/src/window-creators/index.js @@ -80,12 +80,14 @@ const _loadUI = async (params) => { } const _createWindow = async ( - { + params, + winProps +) => { + const { pathname = null, winName = 'mainWindow' - } = {}, - props = {} -) => { + } = params ?? {} + const point = electron.screen.getCursorScreenPoint() const { bounds, @@ -109,7 +111,7 @@ const _createWindow = async ( defaultHeight }) : {} - const _props = { + const props = { autoHideMenuBar: true, width, height, @@ -124,15 +126,15 @@ const _createWindow = async ( icon: path.join(__dirname, '../../build/icons/512x512.png'), backgroundColor: '#172d3e', show: false, - ...props, + ...winProps, webPreferences: { preload: path.join(__dirname, 'main-renderer-ipc-bridge/preload.js'), - ...props?.webPreferences + ...winProps?.webPreferences } } - wins[winName] = new BrowserWindow(_props) + wins[winName] = new BrowserWindow(props) wins[winName].on('closed', () => { wins[winName] = null @@ -168,7 +170,7 @@ const _createWindow = async ( return res } - if (_props.center) { + if (props.center) { centerWindow(wins[winName]) } @@ -233,7 +235,13 @@ const createMainWindow = async ({ pathToUserData, pathToUserDocuments }) => { - const winProps = await _createWindow() + const winProps = await _createWindow(null, { + // TODO: Expose this opts after UI implementation of the menu bar + // Remove the default title bar + // titleBarStyle: 'hidden', + // Expose window controlls in Windows/Linux + // ...(isMac ? {} : { titleBarOverlay: true }) + }) const { win, manage, From dd1bfcb6aba3abdf4ffe749b10b76929d0191312 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Thu, 5 Dec 2024 11:22:30 +0200 Subject: [PATCH 07/61] Add ability to serialize menu for ipc --- .../menu-ipc-channel-handlers.js | 77 ++++++++++++++++--- 1 file changed, 65 insertions(+), 12 deletions(-) diff --git a/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js b/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js index 3ca85a33..b72f0da4 100644 --- a/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js +++ b/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js @@ -1,29 +1,82 @@ 'use strict' +const { Menu } = require('electron') + const IpcChannelHandlers = require('./ipc.channel.handlers') -const createMenu = require('../../create-menu') class MenuIpcChannelHandlers extends IpcChannelHandlers { static channelName = 'menu' - #menuTemplateFactory () { - if (this.menuTemplate) { - return this.menuTemplate + #serializeMenu (menu) { + if ( + !Array.isArray(menu?.items) || + menu.items.length === 0 + ) { + return [] } - this.menuTemplate = createMenu({ - shouldMenuTemplateBeReturned: true - }) + const serializedMenu = [] + + for (const [i, menuItem] of menu.items.entries()) { + const { + label, + id, + type, + accelerator, + enabled, + visible, + checked, + submenu + } = menuItem ?? {} + + const serializedMenuItem = { + label, + id, + type, + accelerator, + enabled, + visible, + checked: typeof checked === 'function' + ? checked() + : checked, + submenu: this.#serializeMenu(submenu) + } + const hasSubmenu = ( + Array.isArray(serializedMenuItem.submenu) && + serializedMenuItem.submenu.length > 0 + ) + const isSeparator = ( + type === 'separator' && + serializedMenu[i - 1]?.type && + serializedMenu[i - 1]?.type !== 'separator' + ) + + if (!hasSubmenu) { + serializedMenuItem.submenu = null + } + if (isSeparator) { + serializedMenu.push(serializedMenuItem) + + continue + } + if ( + !id && + !hasSubmenu + ) { + continue + } + + serializedMenu.push(serializedMenuItem) + } - return this.menuTemplate + return serializedMenu } async getMenuTemplateHandler (event, args) { - const menuTemplate = createMenu({ - shouldMenuTemplateBeReturned: true - }) + const menu = Menu.getApplicationMenu() + const serializedMenu = this.#serializeMenu(menu) - return menuTemplate + return serializedMenu } } From 411be10a1412d07291685359472bbf3446c634de Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Thu, 5 Dec 2024 11:22:58 +0200 Subject: [PATCH 08/61] Add exec menu cmd handler --- .../menu-ipc-channel-handlers.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js b/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js index b72f0da4..345cfc70 100644 --- a/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js +++ b/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js @@ -1,6 +1,6 @@ 'use strict' -const { Menu } = require('electron') +const { BaseWindow, webContents, Menu } = require('electron') const IpcChannelHandlers = require('./ipc.channel.handlers') @@ -78,6 +78,20 @@ class MenuIpcChannelHandlers extends IpcChannelHandlers { return serializedMenu } + + async execMenuCmdHandler (event, args) { + if (!args?.id) { + return + } + + const menu = Menu.getApplicationMenu() + const menuItem = menu.getMenuItemById(args.id) + + const focusedWindow = BaseWindow.getFocusedWindow() + const focusedWebContents = webContents.getFocusedWebContents() + + return menuItem.click({}, focusedWindow, focusedWebContents) + } } module.exports = MenuIpcChannelHandlers From 321fd4b823bed24cc9f5a5adbf3d6342b81e7cc4 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Thu, 5 Dec 2024 11:28:13 +0200 Subject: [PATCH 09/61] Register exec menu cmd handler in preload script --- src/window-creators/main-renderer-ipc-bridge/preload.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/window-creators/main-renderer-ipc-bridge/preload.js b/src/window-creators/main-renderer-ipc-bridge/preload.js index 2f2a2be5..e266719f 100644 --- a/src/window-creators/main-renderer-ipc-bridge/preload.js +++ b/src/window-creators/main-renderer-ipc-bridge/preload.js @@ -23,7 +23,8 @@ const TRANSLATIONS_INVOKE_METHOD_NAMES = { TRANSLATE: 'translate' } const MENU_INVOKE_METHOD_NAMES = { - GET_MENU_TEMPLATE: 'getMenuTemplate' + GET_MENU_TEMPLATE: 'getMenuTemplate', + EXEC_MENU_CMD: 'execMenuCmd' } const INVOKE_CHANNEL_MAP = new Map([ From 3eba427d682f4e464ce90c1e4fc59d040c6622af Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Fri, 6 Dec 2024 14:19:10 +0200 Subject: [PATCH 10/61] Extend menu item ids --- src/create-menu/menu.item.ids.js | 48 +++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/src/create-menu/menu.item.ids.js b/src/create-menu/menu.item.ids.js index c9cbb151..634e3d74 100644 --- a/src/create-menu/menu.item.ids.js +++ b/src/create-menu/menu.item.ids.js @@ -1,8 +1,54 @@ 'use strict' module.exports = { + MAC_ABOUT_MENU_ITEM: 'MAC_ABOUT_MENU_ITEM', + MAC_SERVICES_MENU_ITEM: 'MAC_SERVICES_MENU_ITEM', + MAC_HIDE_MENU_ITEM: 'MAC_HIDE_MENU_ITEM', + MAC_HIDE_OTHERS_MENU_ITEM: 'MAC_HIDE_OTHERS_MENU_ITEM', + MAC_UNHIDE_MENU_ITEM: 'MAC_UNHIDE_MENU_ITEM', + MAC_QUIT_MENU_ITEM: 'MAC_QUIT_MENU_ITEM', + MAC_CLOSE_MENU_ITEM: 'MAC_CLOSE_MENU_ITEM', + MAC_PASTE_AND_MATCH_STYLE_MENU_ITEM: 'MAC_PASTE_AND_MATCH_STYLE_MENU_ITEM', + MAC_START_SPEAKING_MENU_ITEM: 'MAC_START_SPEAKING_MENU_ITEM', + MAC_STOP_SPEAKING_MENU_ITEM: 'MAC_STOP_SPEAKING_MENU_ITEM', + MAC_FRONT_MENU_ITEM: 'MAC_FRONT_MENU_ITEM', + MAC_WINDOW_MENU_ITEM: 'MAC_WINDOW_MENU_ITEM', + + QUIT_MENU_ITEM: 'QUIT_MENU_ITEM', + + UNDO_MENU_ITEM: 'UNDO_MENU_ITEM', + REDO_MENU_ITEM: 'REDO_MENU_ITEM', + CUT_MENU_ITEM: 'CUT_MENU_ITEM', + COPY_MENU_ITEM: 'COPY_MENU_ITEM', + PASTE_MENU_ITEM: 'PASTE_MENU_ITEM', + DELETE_MENU_ITEM: 'DELETE_MENU_ITEM', + SELECT_ALL_MENU_ITEM: 'SELECT_ALL_MENU_ITEM', + + RELOAD_MENU_ITEM: 'RELOAD_MENU_ITEM', + FORCE_RELOAD_MENU_ITEM: 'FORCE_RELOAD_MENU_ITEM', + TOGGLE_DEV_TOOLS_MENU_ITEM: 'TOGGLE_DEV_TOOLS_MENU_ITEM', + RESET_ZOOM_MENU_ITEM: 'RESET_ZOOM_MENU_ITEM', + ZOOM_IN_MENU_ITEM: 'ZOOM_IN_MENU_ITEM', + ZOOM_OUT_MENU_ITEM: 'ZOOM_OUT_MENU_ITEM', + TOGGLE_FULL_SCREEN_MENU_ITEM: 'TOGGLE_FULL_SCREEN_MENU_ITEM', + + MINIMIZE_MENU_ITEM: 'MINIMIZE_MENU_ITEM', + ZOOM_MENU_ITEM: 'ZOOM_MENU_ITEM', + CLOSE_MENU_ITEM: 'CLOSE_MENU_ITEM', + + EXPORT_DB_MENU_ITEM: 'EXPORT_DB_MENU_ITEM', + IMPORT_DB_MENU_ITEM: 'IMPORT_DB_MENU_ITEM', + RESTORE_DB_MENU_ITEM: 'RESTORE_DB_MENU_ITEM', + BACKUP_DB_MENU_ITEM: 'BACKUP_DB_MENU_ITEM', + REMOVE_DB_MENU_ITEM: 'REMOVE_DB_MENU_ITEM', + CLEAR_ALL_DATA_MENU_ITEM: 'CLEAR_ALL_DATA_MENU_ITEM', + CHANGE_REPORTS_FOLDER_MENU_ITEM: 'CHANGE_REPORTS_FOLDER_MENU_ITEM', + CHANGE_SYNC_FREQUENCY_MENU_ITEM: 'CHANGE_SYNC_FREQUENCY_MENU_ITEM', + REPORT_BUG_MENU_ITEM: 'REPORT_BUG_MENU_ITEM', CHECK_UPDATE_MENU_ITEM: 'CHECK_UPDATE_MENU_ITEM', INSTALL_UPDATE_MENU_ITEM: 'INSTALL_UPDATE_MENU_ITEM', - SHOW_CHANGE_LOG_MENU_ITEM: 'SHOW_CHANGE_LOG_MENU_ITEM' + USER_MANUAL_MENU_ITEM: 'USER_MANUAL_MENU_ITEM', + SHOW_CHANGE_LOG_MENU_ITEM: 'SHOW_CHANGE_LOG_MENU_ITEM', + ABOUT_MENU_ITEM: 'ABOUT_MENU_ITEM' } From 8928d1fd3f1acf03df098e207eed7f3f8e6b449a Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Fri, 6 Dec 2024 14:19:30 +0200 Subject: [PATCH 11/61] Customize menu item template to be serialized for ui --- src/create-menu/index.js | 188 +++++++++++++++++++++++++++++++++++---- 1 file changed, 171 insertions(+), 17 deletions(-) diff --git a/src/create-menu/index.js b/src/create-menu/index.js index e3a903bd..e0688c14 100644 --- a/src/create-menu/index.js +++ b/src/create-menu/index.js @@ -79,6 +79,7 @@ module.exports = (params) => { const menuTemplate = [ ...(isMac ? [{ + role: 'appMenu', label: app.name, submenu: [ { @@ -86,41 +87,144 @@ module.exports = (params) => { 'menu.helpSubMenu.aboutLabel', { appName: app.name } ), + id: MENU_ITEM_IDS.MAC_ABOUT_MENU_ITEM, click: showAboutModalDialog() }, { type: 'separator' }, { role: 'services', - label: i18next.t('menu.macMainSubmenu.servicesLabel') + label: i18next.t('menu.macMainSubmenu.servicesLabel'), + id: MENU_ITEM_IDS.MAC_SERVICES_MENU_ITEM }, { type: 'separator' }, { role: 'hide', - label: i18next.t('menu.macMainSubmenu.hideLabel') + label: i18next.t('menu.macMainSubmenu.hideLabel'), + id: MENU_ITEM_IDS.MAC_HIDE_MENU_ITEM }, { role: 'hideOthers', - label: i18next.t('menu.macMainSubmenu.hideOthersLabel') + label: i18next.t('menu.macMainSubmenu.hideOthersLabel'), + id: MENU_ITEM_IDS.MAC_HIDE_OTHERS_MENU_ITEM }, { role: 'unhide', - label: i18next.t('menu.macMainSubmenu.unhideLabel') + label: i18next.t('menu.macMainSubmenu.unhideLabel'), + id: MENU_ITEM_IDS.MAC_UNHIDE_MENU_ITEM }, { type: 'separator' }, { role: 'quit', - label: i18next.t('menu.macMainSubmenu.quitLabel') + label: i18next.t('menu.macMainSubmenu.quitLabel'), + id: MENU_ITEM_IDS.MAC_QUIT_MENU_ITEM } ] }] : []), - { role: 'fileMenu', label: i18next.t('menu.fileSubMenu.label') }, - { role: 'editMenu', label: i18next.t('menu.editSubMenu.label') }, { + role: 'fileMenu', + label: i18next.t('menu.fileSubMenu.label'), + submenu: [ + isMac + ? { + role: 'close', + label: 'Close', // TODO: + id: MENU_ITEM_IDS.MAC_CLOSE_MENU_ITEM + } + : { + role: 'quit', + label: 'Quit', // TODO: + id: MENU_ITEM_IDS.QUIT_MENU_ITEM + } + ] + }, + { + role: 'editMenu', + label: i18next.t('menu.editSubMenu.label'), + submenu: [ + { + role: 'undo', + label: 'Undo', // TODO: + id: MENU_ITEM_IDS.UNDO_MENU_ITEM + }, + { + role: 'redo', + label: 'Redo', // TODO: + id: MENU_ITEM_IDS.REDO_MENU_ITEM + }, + { type: 'separator' }, + { + role: 'cut', + label: 'Cut', // TODO: + id: MENU_ITEM_IDS.CUT_MENU_ITEM + }, + { + role: 'copy', + label: 'Copy', // TODO: + id: MENU_ITEM_IDS.COPY_MENU_ITEM + }, + { + role: 'paste', + label: 'Paste', // TODO: + id: MENU_ITEM_IDS.PASTE_MENU_ITEM + }, + ...(isMac + ? [ + { + role: 'pasteAndMatchStyle', + label: 'Paste And Match Style', // TODO: + id: MENU_ITEM_IDS.MAC_PASTE_AND_MATCH_STYLE_MENU_ITEM + }, + { + role: 'delete', + label: 'Delete', // TODO: + id: MENU_ITEM_IDS.DELETE_MENU_ITEM + }, + { + role: 'selectAll', + label: 'Select All', // TODO: + id: MENU_ITEM_IDS.SELECT_ALL_MENU_ITEM + }, + { type: 'separator' }, + { + label: 'Speech', + submenu: [ + { + role: 'startSpeaking', + label: 'Start Speaking', // TODO: + id: MENU_ITEM_IDS.MAC_START_SPEAKING_MENU_ITEM + }, + { + role: 'stopSpeaking', + label: 'Stop Speaking', // TODO: + id: MENU_ITEM_IDS.MAC_STOP_SPEAKING_MENU_ITEM + } + ] + } + ] + : [ + { + role: 'delete', + label: 'Delete', // TODO: + id: MENU_ITEM_IDS.DELETE_MENU_ITEM + }, + { type: 'separator' }, + { + role: 'selectAll', + label: 'Select All', // TODO: + id: MENU_ITEM_IDS.SELECT_ALL_MENU_ITEM + } + ]) + ] + }, + { + role: 'viewMenu', label: i18next.t('menu.viewSubMenu.label'), submenu: [ { + role: 'reload', label: i18next.t('menu.viewSubMenu.reloadLabel'), + id: MENU_ITEM_IDS.RELOAD_MENU_ITEM, accelerator: 'CmdOrCtrl+R', click: (item, focusedWindow) => { if (focusedWindow) { @@ -131,7 +235,9 @@ module.exports = (params) => { } }, { + role: 'forceReload', label: i18next.t('menu.viewSubMenu.forceReloadLabel'), + id: MENU_ITEM_IDS.FORCE_RELOAD_MENU_ITEM, accelerator: 'CmdOrCtrl+Shift+R', click: (item, focusedWindow) => { if (focusedWindow) { @@ -143,29 +249,71 @@ module.exports = (params) => { }, { role: 'toggleDevTools', - label: i18next.t('menu.viewSubMenu.toggleDevToolsLabel') + label: i18next.t('menu.viewSubMenu.toggleDevToolsLabel'), + id: MENU_ITEM_IDS.TOGGLE_DEV_TOOLS_MENU_ITEM }, { type: 'separator' }, { role: 'resetZoom', - label: i18next.t('menu.viewSubMenu.resetZoomLabel') + label: i18next.t('menu.viewSubMenu.resetZoomLabel'), + id: MENU_ITEM_IDS.RESET_ZOOM_MENU_ITEM }, { role: 'zoomIn', - label: i18next.t('menu.viewSubMenu.zoomInLabel') + label: i18next.t('menu.viewSubMenu.zoomInLabel'), + id: MENU_ITEM_IDS.ZOOM_IN_MENU_ITEM }, { role: 'zoomOut', - label: i18next.t('menu.viewSubMenu.zoomOutLabel') + label: i18next.t('menu.viewSubMenu.zoomOutLabel'), + id: MENU_ITEM_IDS.ZOOM_OUT_MENU_ITEM }, { type: 'separator' }, { role: 'togglefullscreen', - label: i18next.t('menu.viewSubMenu.togglefullscreenLabel') + label: i18next.t('menu.viewSubMenu.togglefullscreenLabel'), + id: MENU_ITEM_IDS.TOGGLE_FULL_SCREEN_MENU_ITEM } ] }, - { role: 'windowMenu', label: i18next.t('menu.windowSubMenu.label') }, + { + role: 'windowMenu', + label: i18next.t('menu.windowSubMenu.label'), + submenu: [ + { + role: 'minimize', + label: 'Minimize', // TODO: + id: MENU_ITEM_IDS.MINIMIZE_MENU_ITEM + }, + { + role: 'zoom', + label: 'Zoom', // TODO: + id: MENU_ITEM_IDS.ZOOM_MENU_ITEM + }, + ...(isMac + ? [ + { type: 'separator' }, + { + role: 'front', + label: 'Front', // TODO: + id: MENU_ITEM_IDS.MAC_FRONT_MENU_ITEM + }, + { type: 'separator' }, + { + role: 'window', + label: 'Window', // TODO: + id: MENU_ITEM_IDS.MAC_WINDOW_MENU_ITEM + } + ] + : [ + { + role: 'close', + label: 'Close', // TODO: + id: MENU_ITEM_IDS.CLOSE_MENU_ITEM + } + ]) + ] + }, { label: i18next.t('menu.toolsSubMenu.label'), submenu: [ @@ -174,26 +322,32 @@ module.exports = (params) => { submenu: [ { label: i18next.t('menu.toolsSubMenu.dataManagementSubMenu.exportDbLabel'), + id: MENU_ITEM_IDS.EXPORT_DB_MENU_ITEM, click: exportDB({ pathToUserData, pathToUserDocuments }) }, { label: i18next.t('menu.toolsSubMenu.dataManagementSubMenu.importDbLabel'), + id: MENU_ITEM_IDS.IMPORT_DB_MENU_ITEM, click: importDB({ pathToUserData, pathToUserDocuments }) }, { label: i18next.t('menu.toolsSubMenu.dataManagementSubMenu.restoreDbLabel'), + id: MENU_ITEM_IDS.RESTORE_DB_MENU_ITEM, click: restoreDB() }, { label: i18next.t('menu.toolsSubMenu.dataManagementSubMenu.backupDbLabel'), + id: MENU_ITEM_IDS.BACKUP_DB_MENU_ITEM, click: backupDB() }, { label: i18next.t('menu.toolsSubMenu.dataManagementSubMenu.removeDbLabel'), + id: MENU_ITEM_IDS.REMOVE_DB_MENU_ITEM, click: removeDB({ pathToUserData }) }, { label: i18next.t('menu.toolsSubMenu.dataManagementSubMenu.clearAllDataLabel'), + id: MENU_ITEM_IDS.CLEAR_ALL_DATA_MENU_ITEM, click: removeDB({ pathToUserData, shouldAllTablesBeCleared: true @@ -204,10 +358,12 @@ module.exports = (params) => { { type: 'separator' }, { label: i18next.t('menu.toolsSubMenu.changeReportsFolderLabel'), + id: MENU_ITEM_IDS.CHANGE_REPORTS_FOLDER_MENU_ITEM, click: changeReportsFolder({ pathToUserDocuments }) }, { label: i18next.t('menu.toolsSubMenu.changeSyncFrequencyLabel'), + id: MENU_ITEM_IDS.CHANGE_SYNC_FREQUENCY_MENU_ITEM, click: changeSyncFrequency() } ] @@ -247,6 +403,7 @@ module.exports = (params) => { { type: 'separator' }, { label: i18next.t('menu.helpSubMenu.userManualLabel'), + id: MENU_ITEM_IDS.USER_MANUAL_MENU_ITEM, accelerator: 'CmdOrCtrl+H', click: () => showDocs() }, @@ -268,6 +425,7 @@ module.exports = (params) => { 'menu.helpSubMenu.aboutLabel', { appName: app.name } ), + id: MENU_ITEM_IDS.ABOUT_MENU_ITEM, click: showAboutModalDialog() } ]) @@ -275,10 +433,6 @@ module.exports = (params) => { } ] - if (params?.shouldMenuTemplateBeReturned) { - return menuTemplate - } - Menu.setApplicationMenu(Menu.buildFromTemplate(menuTemplate)) isMenuInitialized = true } From 5f1e543ca75811d28011dec77e289840fa9c0829 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Mon, 9 Dec 2024 14:23:34 +0200 Subject: [PATCH 12/61] Fix reload menu option --- src/create-menu/index.js | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/create-menu/index.js b/src/create-menu/index.js index e0688c14..7b291d1f 100644 --- a/src/create-menu/index.js +++ b/src/create-menu/index.js @@ -23,6 +23,8 @@ const { manageNewGithubIssue } = require('../error-manager') const showDocs = require('../show-docs') const { showChangelog } = require('../changelog-manager') const parseEnvValToBool = require('../helpers/parse-env-val-to-bool') +const isMainWinAvailable = require('../helpers/is-main-win-available') +const wins = require('../window-creators/windows') const MENU_ITEM_IDS = require('./menu.item.ids') @@ -222,28 +224,36 @@ module.exports = (params) => { label: i18next.t('menu.viewSubMenu.label'), submenu: [ { - role: 'reload', label: i18next.t('menu.viewSubMenu.reloadLabel'), id: MENU_ITEM_IDS.RELOAD_MENU_ITEM, accelerator: 'CmdOrCtrl+R', click: (item, focusedWindow) => { - if (focusedWindow) { - focusedWindow.reload() + const win = isMainWinAvailable(wins.mainWindow) + ? wins.mainWindow + : focusedWindow + + if (!win) { + return } + win.reload() triggerElectronLoad() } }, { - role: 'forceReload', label: i18next.t('menu.viewSubMenu.forceReloadLabel'), id: MENU_ITEM_IDS.FORCE_RELOAD_MENU_ITEM, accelerator: 'CmdOrCtrl+Shift+R', click: (item, focusedWindow) => { - if (focusedWindow) { - focusedWindow.webContents.reloadIgnoringCache() + const win = isMainWinAvailable(wins.mainWindow) + ? wins.mainWindow + : focusedWindow + + if (!win) { + return } + win.webContents.reloadIgnoringCache() triggerElectronLoad() } }, From 5d8180061361ed17157b4ff8a14c3f589de22a29 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Tue, 10 Dec 2024 14:22:34 +0200 Subject: [PATCH 13/61] Bump electron up to 33.3.0 to have fix for titleBarStyle --- package.json | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 55b2c813..1a54e33b 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "author": "bitfinex.com", "main": "index.js", "engine": { - "node": ">=18.17.1" + "node": ">=20.18.1" }, "license": "Apache-2.0", "dependencies": { @@ -35,18 +35,16 @@ "yauzl": "3.2.0" }, "devDependencies": { - "@mapbox/node-pre-gyp": "1.0.11", "@wdio/cli": "8.22.1", "@wdio/junit-reporter": "8.21.0", "@wdio/local-runner": "8.22.1", "@wdio/mocha-framework": "8.22.0", "@wdio/spec-reporter": "8.21.0", - "app-builder-bin": "4.2.0", "concurrently": "9.0.1", "cross-env": "7.0.3", "dotenv": "16.3.1", - "electron": "27.3.11", - "electron-builder": "24.10.0", + "electron": "33.3.0", + "electron-builder": "24.13.3", "mocha": "10.2.0", "standard": "17.1.0", "wdio-electron-service": "5.4.0" From ec62c9aee466aba5bdbde109be3bc1739c7830c2 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Tue, 10 Dec 2024 14:24:24 +0200 Subject: [PATCH 14/61] Update nodejs version in docker files --- Dockerfile.linux-builder | 4 ++-- Dockerfile.mac-builder | 4 ++-- Dockerfile.ui-builder | 4 ++-- Dockerfile.win-builder | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Dockerfile.linux-builder b/Dockerfile.linux-builder index c0354e3a..0fd92cbf 100644 --- a/Dockerfile.linux-builder +++ b/Dockerfile.linux-builder @@ -1,6 +1,6 @@ -FROM electronuserland/builder:18 +FROM electronuserland/builder:20 -ARG NODE_VERSION="18.17.1" +ARG NODE_VERSION="20.18.1" ENV IS_BFX_API_STAGING=${IS_BFX_API_STAGING:-0} ENV IS_DEV_ENV=${IS_DEV_ENV:-0} diff --git a/Dockerfile.mac-builder b/Dockerfile.mac-builder index ad1ea892..daf71dbb 100644 --- a/Dockerfile.mac-builder +++ b/Dockerfile.mac-builder @@ -1,6 +1,6 @@ -FROM electronuserland/builder:18 +FROM electronuserland/builder:20 -ARG NODE_VERSION="18.17.1" +ARG NODE_VERSION="20.18.1" ENV IS_BFX_API_STAGING=${IS_BFX_API_STAGING:-0} ENV IS_DEV_ENV=${IS_DEV_ENV:-0} diff --git a/Dockerfile.ui-builder b/Dockerfile.ui-builder index 5f193211..5c236731 100644 --- a/Dockerfile.ui-builder +++ b/Dockerfile.ui-builder @@ -1,6 +1,6 @@ -FROM electronuserland/builder:18 +FROM electronuserland/builder:20 -ARG NODE_VERSION="18.17.1" +ARG NODE_VERSION="20.18.1" ENV IS_BFX_API_STAGING=${IS_BFX_API_STAGING:-0} ENV IS_DEV_ENV=${IS_DEV_ENV:-0} diff --git a/Dockerfile.win-builder b/Dockerfile.win-builder index f8b72453..ccf85cd1 100644 --- a/Dockerfile.win-builder +++ b/Dockerfile.win-builder @@ -1,6 +1,6 @@ -FROM electronuserland/builder:18-wine +FROM electronuserland/builder:20-wine -ARG NODE_VERSION="18.17.1" +ARG NODE_VERSION="20.18.1" ENV IS_BFX_API_STAGING=${IS_BFX_API_STAGING:-0} ENV IS_DEV_ENV=${IS_DEV_ENV:-0} From 822eab471f5cd7191170cbc08bc2617f9b6d8356 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Tue, 10 Dec 2024 14:25:36 +0200 Subject: [PATCH 15/61] Update nodejs installation script --- scripts/helpers/install-nodejs.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/helpers/install-nodejs.sh b/scripts/helpers/install-nodejs.sh index 385062b6..c80fe630 100755 --- a/scripts/helpers/install-nodejs.sh +++ b/scripts/helpers/install-nodejs.sh @@ -13,7 +13,7 @@ script as required NodeJS version!${COLOR_NORMAL}" >&2 exit 1 fi -version="${1:-"18.17.1"}" +version="${1:-"20.18.1"}" echo -e "\n${COLOR_BLUE}Installing the NodeJS v$version...${COLOR_NORMAL}" @@ -26,6 +26,5 @@ unlink /usr/local/LICENSE unlink /usr/local/README.md npm cache clear --force 2>/dev/null -npm install --global node-gyp@9.4.0 echo -e "\n${COLOR_GREEN}The NodeJS has been installed successful${COLOR_NORMAL}" From c9d1cafc88a2045ca27b57b0193e087959e2c7e9 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Tue, 10 Dec 2024 14:26:57 +0200 Subject: [PATCH 16/61] Update nodejs version in gh action workflows --- .github/workflows/build-electron-app.yml | 8 ++++---- .github/workflows/ci.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-electron-app.yml b/.github/workflows/build-electron-app.yml index b05d9f68..2b7fb2f9 100644 --- a/.github/workflows/build-electron-app.yml +++ b/.github/workflows/build-electron-app.yml @@ -161,7 +161,7 @@ jobs: fi - uses: actions/setup-node@v4 with: - node-version: 18.17.1 + node-version: 20.18.1 - name: Cache Electron binaries id: electron-cache uses: actions/cache@v4 @@ -231,7 +231,7 @@ jobs: uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: 18.17.1 + node-version: 20.18.1 - name: Install main dev deps run: npm i --development --no-audit --progress=false --force - name: Download Linux Unpacked build @@ -263,7 +263,7 @@ jobs: uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: 18.17.1 + node-version: 20.18.1 - name: Install main dev deps run: npm i --development --no-audit --progress=false --force - name: Download Linux Unpacked build @@ -297,7 +297,7 @@ jobs: uses: ./.github/actions/prepare-mac-runner - uses: actions/setup-node@v4 with: - node-version: 18.17.1 + node-version: 20.18.1 - name: Install main dev deps run: npm i --development --no-audit --progress=false --force - name: Download Mac Unpacked build diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1bb4fddc..f479010d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: submodules: recursive - uses: actions/setup-node@v4 with: - node-version: 18.17.1 + node-version: 20.18.1 - name: Setup configs and install deps run: ./scripts/setup.sh -u - name: Run tests From a7628d121fe267588e6abc15e3a308b35a93996b Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Tue, 10 Dec 2024 14:31:04 +0200 Subject: [PATCH 17/61] Adjust backend deps instalation script --- scripts/helpers/install-backend-deps.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/helpers/install-backend-deps.sh b/scripts/helpers/install-backend-deps.sh index e17d3b5a..e3b6e819 100755 --- a/scripts/helpers/install-backend-deps.sh +++ b/scripts/helpers/install-backend-deps.sh @@ -43,7 +43,7 @@ function installBackendDeps { echo -e "\n${COLOR_BLUE}Installing the main dev deps...${COLOR_NORMAL}" rm -rf ./node_modules npm i --development --no-audit --progress=false --force - npm ls --depth=0 --only=dev 1<&- + npm ls --depth=0 1<&- export npm_config_target_platform="$targetPlatform" export npm_config_platform="$targetPlatform" @@ -55,9 +55,9 @@ function installBackendDeps { export npm_config_disturl="$DIST_URL" echo -e "\n${COLOR_BLUE}Installing the main prod deps...${COLOR_NORMAL}" - npm i --production --include=dev --no-audit --progress=false --force + npm i --omit=dev --include=dev --no-audit --progress=false --force checkNodeModulesDir "$ROOT" - depsErr=$(npm ls --depth=0 --only=prod 2>&1 >/dev/null | grep -E -v "missing: eslint|--omit=dev" || [[ $? == 1 ]]) + depsErr=$(npm ls --depth=0 --omit=dev 2>&1 >/dev/null | grep -E -v "missing: eslint" || [[ $? == 1 ]]) if [ -n "$depsErr" ]; then echo -e "$depsErr" >&2 exit 1 @@ -66,16 +66,16 @@ function installBackendDeps { cd "$EXPRESS_FOLDER" echo -e "\n${COLOR_BLUE}Installing the prod express deps...${COLOR_NORMAL}" rm -rf ./node_modules - npm i --production --no-audit --progress=false + npm i --omit=dev --no-audit --progress=false checkNodeModulesDir "$EXPRESS_FOLDER" - npm ls --depth=0 --only=prod 1<&- + npm ls --depth=0 --omit=dev 1<&- cd "$WORKER_FOLDER" echo -e "\n${COLOR_BLUE}Installing the prod worker deps...${COLOR_NORMAL}" rm -rf ./node_modules - npm i --production --no-audit --progress=false + npm i --omit=dev --no-audit --progress=false checkNodeModulesDir "$WORKER_FOLDER" - npm ls --depth=0 --only=prod 1<&- + npm ls --depth=0 --omit=dev 1<&- cd "$INSTALL_BACKEND_CURRDIR" } From a750c2eb681a7b1eb9db110ae58aeaaa4f2b5f86 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Tue, 10 Dec 2024 14:35:29 +0200 Subject: [PATCH 18/61] Fix folder ownership issue under docker --- scripts/build-release.sh | 5 ----- scripts/build-ui.sh | 2 -- 2 files changed, 7 deletions(-) diff --git a/scripts/build-release.sh b/scripts/build-release.sh index 5d8ad5f5..e3ac7d1c 100755 --- a/scripts/build-release.sh +++ b/scripts/build-release.sh @@ -161,11 +161,6 @@ else "$ROOT/$ELECTRON_ENV_FILE_NAME"; rm -f "$ROOT/$ELECTRON_ENV_FILE_NAME.bak" fi -changeDirOwnershipToCurrUser "$ELECTRON_CACHE" "$(id -u):$(id -g)" -changeDirOwnershipToCurrUser "$ELECTRON_BUILDER_CACHE" "$(id -u):$(id -g)" -changeDirOwnershipToCurrUser "$COMMON_UI_BUILD_FOLDER" -changeDirOwnershipToCurrUser "$COMMON_DIST_FOLDER" - makeLastCommitJson "$ROOT/$LAST_COMMIT_FILE_NAME" echo -e "\n${COLOR_BLUE}Making backend config files${COLOR_NORMAL}" diff --git a/scripts/build-ui.sh b/scripts/build-ui.sh index 9e43823c..7194f96d 100755 --- a/scripts/build-ui.sh +++ b/scripts/build-ui.sh @@ -81,8 +81,6 @@ if [ $isDevEnv == 1 ]; then export CI_ENVIRONMENT_NAME="development" fi -changeDirOwnershipToCurrUser "$COMMON_UI_BUILD_FOLDER" - rm -rf "$UI_BUILD_FOLDER/"* if [ -d "$COMMON_UI_BUILD_FOLDER" ]; then From b6aa8b2c594e8932101da7e7d47f6dbfb7253d73 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Tue, 10 Dec 2024 14:36:58 +0200 Subject: [PATCH 19/61] Setup main window title bar overlay --- src/window-creators/index.js | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/window-creators/index.js b/src/window-creators/index.js index c0bfe435..db0c7721 100644 --- a/src/window-creators/index.js +++ b/src/window-creators/index.js @@ -33,6 +33,8 @@ const shouldLocalhostBeUsedForLoadingUIInDevMode = parseEnvValToBool( process.env.SHOULD_LOCALHOST_BE_USED_FOR_LOADING_UI_IN_DEV_MODE ) const uiPort = process.env.UI_PORT ?? 3000 +// TODO: Set false by default after UI implementation of the menu bar +const showNativeTitleBar = process.env.SHOW_NATIVE_TITLE_BAR ?? false const publicDir = path.join(__dirname, '../../bfx-report-ui/build') const loadURL = serve({ directory: publicDir }) @@ -235,13 +237,22 @@ const createMainWindow = async ({ pathToUserData, pathToUserDocuments }) => { - const winProps = await _createWindow(null, { - // TODO: Expose this opts after UI implementation of the menu bar - // Remove the default title bar - // titleBarStyle: 'hidden', - // Expose window controlls in Windows/Linux - // ...(isMac ? {} : { titleBarOverlay: true }) - }) + const titleBarOverlayOpt = isMac + ? {} + : { + titleBarOverlay: { + height: 40, + color: '#0b1923ff', + symbolColor: '#fff' + } + } + const titleBarOpts = showNativeTitleBar + ? {} + : { + titleBarStyle: 'hidden', + ...titleBarOverlayOpt + } + const winProps = await _createWindow(null, titleBarOpts) const { win, manage, @@ -261,7 +272,7 @@ const createMainWindow = async ({ }) if (isDevEnv) { - wins.mainWindow.webContents.openDevTools() + wins.mainWindow.webContents.openDevTools({ mode: 'right' }) } if (isBfxApiStaging()) { const title = wins.mainWindow.getTitle() From ef241aac6c8a62b3fd687854686249962104ba07 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Tue, 10 Dec 2024 14:39:01 +0200 Subject: [PATCH 20/61] Fix security warning in renderer process --- index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/index.js b/index.js index 3677828a..992994e1 100644 --- a/index.js +++ b/index.js @@ -27,6 +27,7 @@ app.setName(productName) process.traceProcessWarnings = true app.allowRendererProcessReuse = true +process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = true require('./src/error-manager') .initLogger() From cd84da59cf4d1e8f0f37d8d25ba004c86db7d94d Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Tue, 10 Dec 2024 14:40:23 +0200 Subject: [PATCH 21/61] Disable hardware acceleration to fix errors and speed up --- src/initialize-app.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/initialize-app.js b/src/initialize-app.js index 9d01f0ee..0a5a65fb 100644 --- a/src/initialize-app.js +++ b/src/initialize-app.js @@ -169,6 +169,7 @@ module.exports = async () => { MenuIpcChannelHandlers ) + app.disableHardwareAcceleration() app.on('window-all-closed', () => { app.quit() }) From 2913fb35ac3f887910e296a8feec0b8c6789afa6 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Wed, 11 Dec 2024 14:29:07 +0200 Subject: [PATCH 22/61] Show native title bar by default til ui implementation --- src/window-creators/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/window-creators/index.js b/src/window-creators/index.js index db0c7721..475666ce 100644 --- a/src/window-creators/index.js +++ b/src/window-creators/index.js @@ -34,7 +34,7 @@ const shouldLocalhostBeUsedForLoadingUIInDevMode = parseEnvValToBool( ) const uiPort = process.env.UI_PORT ?? 3000 // TODO: Set false by default after UI implementation of the menu bar -const showNativeTitleBar = process.env.SHOW_NATIVE_TITLE_BAR ?? false +const showNativeTitleBar = process.env.SHOW_NATIVE_TITLE_BAR ?? true const publicDir = path.join(__dirname, '../../bfx-report-ui/build') const loadURL = serve({ directory: publicDir }) From 9d6937220879141fa625571558cab88d1cb7f5b7 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Wed, 11 Dec 2024 14:30:37 +0200 Subject: [PATCH 23/61] Add getTitle method to GeneralIpcChannelHandlers --- .../main-renderer-ipc-bridge/general-ipc-channel-handlers.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/window-creators/main-renderer-ipc-bridge/general-ipc-channel-handlers.js b/src/window-creators/main-renderer-ipc-bridge/general-ipc-channel-handlers.js index b930c6a0..8b82107a 100644 --- a/src/window-creators/main-renderer-ipc-bridge/general-ipc-channel-handlers.js +++ b/src/window-creators/main-renderer-ipc-bridge/general-ipc-channel-handlers.js @@ -2,6 +2,7 @@ const { app } = require('electron') +const wins = require('../windows') const IpcChannelHandlers = require('./ipc.channel.handlers') class GeneralIpcChannelHandlers extends IpcChannelHandlers { @@ -9,6 +10,10 @@ class GeneralIpcChannelHandlers extends IpcChannelHandlers { return app.exit(args?.code ?? 0) } + async getTitleHandler (event, args) { + return wins.mainWindow.getTitle() + } + static onLoadingDescriptionReady (cb) { return this.handleListener(this.onLoadingDescriptionReady, cb) } From 7a48e4e2ca3c937f6125879ab48075aafb954de2 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Wed, 11 Dec 2024 14:30:57 +0200 Subject: [PATCH 24/61] Register getTitle method in context bridge --- src/window-creators/main-renderer-ipc-bridge/preload.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/window-creators/main-renderer-ipc-bridge/preload.js b/src/window-creators/main-renderer-ipc-bridge/preload.js index e266719f..d4d4d3b3 100644 --- a/src/window-creators/main-renderer-ipc-bridge/preload.js +++ b/src/window-creators/main-renderer-ipc-bridge/preload.js @@ -10,7 +10,8 @@ const CHANNEL_NAMES = { } const GENERAL_INVOKE_METHOD_NAMES = { - EXIT: 'exit' + EXIT: 'exit', + GET_TITLE: 'getTitle' } const GENERAL_EVENT_METHOD_NAMES = { ON_LOADING_DESCRIPTION: 'onLoadingDescription', From def9192108ee62d415b62aa5c5d4c3c8a59fd2e2 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Mon, 6 Jan 2025 14:36:32 +0200 Subject: [PATCH 25/61] Extend native menu options translation support --- src/create-menu/index.js | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/create-menu/index.js b/src/create-menu/index.js index 7b291d1f..710a5c3c 100644 --- a/src/create-menu/index.js +++ b/src/create-menu/index.js @@ -130,12 +130,12 @@ module.exports = (params) => { isMac ? { role: 'close', - label: 'Close', // TODO: + label: i18next.t('menu.fileSubMenu.closeLabel'), id: MENU_ITEM_IDS.MAC_CLOSE_MENU_ITEM } : { role: 'quit', - label: 'Quit', // TODO: + label: i18next.t('menu.fileSubMenu.quitLabel'), id: MENU_ITEM_IDS.QUIT_MENU_ITEM } ] @@ -146,59 +146,59 @@ module.exports = (params) => { submenu: [ { role: 'undo', - label: 'Undo', // TODO: + label: i18next.t('menu.editSubMenu.undoLabel'), id: MENU_ITEM_IDS.UNDO_MENU_ITEM }, { role: 'redo', - label: 'Redo', // TODO: + label: i18next.t('menu.editSubMenu.redoLabel'), id: MENU_ITEM_IDS.REDO_MENU_ITEM }, { type: 'separator' }, { role: 'cut', - label: 'Cut', // TODO: + label: i18next.t('menu.editSubMenu.cutLabel'), id: MENU_ITEM_IDS.CUT_MENU_ITEM }, { role: 'copy', - label: 'Copy', // TODO: + label: i18next.t('menu.editSubMenu.copyLabel'), id: MENU_ITEM_IDS.COPY_MENU_ITEM }, { role: 'paste', - label: 'Paste', // TODO: + label: i18next.t('menu.editSubMenu.pasteLabel'), id: MENU_ITEM_IDS.PASTE_MENU_ITEM }, ...(isMac ? [ { role: 'pasteAndMatchStyle', - label: 'Paste And Match Style', // TODO: + label: i18next.t('menu.editSubMenu.pasteAndMatchStyleLabel'), id: MENU_ITEM_IDS.MAC_PASTE_AND_MATCH_STYLE_MENU_ITEM }, { role: 'delete', - label: 'Delete', // TODO: + label: i18next.t('menu.editSubMenu.deleteLabel'), id: MENU_ITEM_IDS.DELETE_MENU_ITEM }, { role: 'selectAll', - label: 'Select All', // TODO: + label: i18next.t('menu.editSubMenu.selectAllLabel'), id: MENU_ITEM_IDS.SELECT_ALL_MENU_ITEM }, { type: 'separator' }, { - label: 'Speech', + label: i18next.t('menu.editSubMenu.speechSubMenu.label'), submenu: [ { role: 'startSpeaking', - label: 'Start Speaking', // TODO: + label: i18next.t('menu.editSubMenu.speechSubMenu.startSpeakingLabel'), id: MENU_ITEM_IDS.MAC_START_SPEAKING_MENU_ITEM }, { role: 'stopSpeaking', - label: 'Stop Speaking', // TODO: + label: i18next.t('menu.editSubMenu.speechSubMenu.stopSpeakingLabel'), id: MENU_ITEM_IDS.MAC_STOP_SPEAKING_MENU_ITEM } ] @@ -207,13 +207,13 @@ module.exports = (params) => { : [ { role: 'delete', - label: 'Delete', // TODO: + label: i18next.t('menu.editSubMenu.deleteLabel'), id: MENU_ITEM_IDS.DELETE_MENU_ITEM }, { type: 'separator' }, { role: 'selectAll', - label: 'Select All', // TODO: + label: i18next.t('menu.editSubMenu.selectAllLabel'), id: MENU_ITEM_IDS.SELECT_ALL_MENU_ITEM } ]) @@ -292,12 +292,12 @@ module.exports = (params) => { submenu: [ { role: 'minimize', - label: 'Minimize', // TODO: + label: i18next.t('menu.windowSubMenu.minimizeLabel'), id: MENU_ITEM_IDS.MINIMIZE_MENU_ITEM }, { role: 'zoom', - label: 'Zoom', // TODO: + label: i18next.t('menu.windowSubMenu.zoomLabel'), id: MENU_ITEM_IDS.ZOOM_MENU_ITEM }, ...(isMac @@ -305,20 +305,20 @@ module.exports = (params) => { { type: 'separator' }, { role: 'front', - label: 'Front', // TODO: + label: i18next.t('menu.windowSubMenu.frontLabel'), id: MENU_ITEM_IDS.MAC_FRONT_MENU_ITEM }, { type: 'separator' }, { role: 'window', - label: 'Window', // TODO: + label: i18next.t('menu.windowSubMenu.windowLabel'), id: MENU_ITEM_IDS.MAC_WINDOW_MENU_ITEM } ] : [ { role: 'close', - label: 'Close', // TODO: + label: i18next.t('menu.fileSubMenu.closeLabel'), id: MENU_ITEM_IDS.CLOSE_MENU_ITEM } ]) From a18add5616696ef39a99d0f9c86e2ed2c6c84ea5 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Mon, 6 Jan 2025 14:36:58 +0200 Subject: [PATCH 26/61] Add en trinslations for native menu options --- build/locales/en/translations.json | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/build/locales/en/translations.json b/build/locales/en/translations.json index 750f9202..c4353cc9 100644 --- a/build/locales/en/translations.json +++ b/build/locales/en/translations.json @@ -12,10 +12,25 @@ "quitLabel": "Quit" }, "fileSubMenu": { - "label": "File" + "label": "File", + "closeLabel": "Close", + "quitLabel": "Quit" }, "editSubMenu": { - "label": "Edit" + "label": "Edit", + "undoLabel": "Undo", + "redoLabel": "Redo", + "cutLabel": "Cut", + "copyLabel": "Copy", + "pasteLabel": "Paste", + "pasteAndMatchStyleLabel": "Paste And Match Style", + "deleteLabel": "Delete", + "selectAllLabel": "Select All", + "speechSubMenu": { + "label": "Speech", + "startSpeakingLabel": "Start Speaking", + "stopSpeakingLabel": "Stop Speaking" + } }, "viewSubMenu": { "label": "View", @@ -28,7 +43,11 @@ "togglefullscreenLabel": "Toggle Full Screen" }, "windowSubMenu": { - "label": "Window" + "label": "Window", + "minimizeLabel": "Minimize", + "zoomLabel": "Zoom", + "frontLabel": "Front", + "windowLabel": "Window" }, "toolsSubMenu": { "label": "Tools", From ee95e66c313dc9ebdff4277d9e663cd9630d48a7 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Mon, 6 Jan 2025 14:37:33 +0200 Subject: [PATCH 27/61] Add ru trinslations for native menu options --- build/locales/ru/translations.json | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/build/locales/ru/translations.json b/build/locales/ru/translations.json index c04a6679..04d667a5 100644 --- a/build/locales/ru/translations.json +++ b/build/locales/ru/translations.json @@ -12,10 +12,25 @@ "quitLabel": "Выйти" }, "fileSubMenu": { - "label": "Файл" + "label": "Файл", + "closeLabel": "Закрыть", + "quitLabel": "Выйти" }, "editSubMenu": { - "label": "Редактировать" + "label": "Редактировать", + "undoLabel": "Отменить", + "redoLabel": "Повторить", + "cutLabel": "Вырезать", + "copyLabel": "Копировать", + "pasteLabel": "Вставить", + "pasteAndMatchStyleLabel": "Вставить и Сопоставить Стиль", + "deleteLabel": "Удалить", + "selectAllLabel": "Выбрать Все", + "speechSubMenu": { + "label": "Речь", + "startSpeakingLabel": "Начать Говорить", + "stopSpeakingLabel": "Перестать Говорить" + } }, "viewSubMenu": { "label": "Вид", @@ -28,7 +43,11 @@ "togglefullscreenLabel": "Переключить на Полный Экран" }, "windowSubMenu": { - "label": "Окно" + "label": "Окно", + "minimizeLabel": "Свернуть", + "zoomLabel": "Увеличить", + "frontLabel": "На Передний План", + "windowLabel": "Окно" }, "toolsSubMenu": { "label": "Инструменты", From 34d746ec7ee1f794f7030fd410e52c2ea7087ac8 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Tue, 7 Jan 2025 12:39:13 +0200 Subject: [PATCH 28/61] Add shortcut accelerators to menu --- src/create-menu/index.js | 64 +++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 18 deletions(-) diff --git a/src/create-menu/index.js b/src/create-menu/index.js index 710a5c3c..2754558f 100644 --- a/src/create-menu/index.js +++ b/src/create-menu/index.js @@ -90,6 +90,7 @@ module.exports = (params) => { { appName: app.name } ), id: MENU_ITEM_IDS.MAC_ABOUT_MENU_ITEM, + accelerator: 'CmdOrCtrl+O', click: showAboutModalDialog() }, { type: 'separator' }, @@ -118,7 +119,8 @@ module.exports = (params) => { { role: 'quit', label: i18next.t('menu.macMainSubmenu.quitLabel'), - id: MENU_ITEM_IDS.MAC_QUIT_MENU_ITEM + id: MENU_ITEM_IDS.MAC_QUIT_MENU_ITEM, + accelerator: 'CmdOrCtrl+Q' } ] }] @@ -136,7 +138,8 @@ module.exports = (params) => { : { role: 'quit', label: i18next.t('menu.fileSubMenu.quitLabel'), - id: MENU_ITEM_IDS.QUIT_MENU_ITEM + id: MENU_ITEM_IDS.QUIT_MENU_ITEM, + accelerator: 'CmdOrCtrl+Q' } ] }, @@ -147,28 +150,33 @@ module.exports = (params) => { { role: 'undo', label: i18next.t('menu.editSubMenu.undoLabel'), - id: MENU_ITEM_IDS.UNDO_MENU_ITEM + id: MENU_ITEM_IDS.UNDO_MENU_ITEM, + accelerator: 'CmdOrCtrl+Z' }, { role: 'redo', label: i18next.t('menu.editSubMenu.redoLabel'), - id: MENU_ITEM_IDS.REDO_MENU_ITEM + id: MENU_ITEM_IDS.REDO_MENU_ITEM, + accelerator: 'CmdOrCtrl+Shift+Z' }, { type: 'separator' }, { role: 'cut', label: i18next.t('menu.editSubMenu.cutLabel'), - id: MENU_ITEM_IDS.CUT_MENU_ITEM + id: MENU_ITEM_IDS.CUT_MENU_ITEM, + accelerator: 'CmdOrCtrl+X' }, { role: 'copy', label: i18next.t('menu.editSubMenu.copyLabel'), - id: MENU_ITEM_IDS.COPY_MENU_ITEM + id: MENU_ITEM_IDS.COPY_MENU_ITEM, + accelerator: 'CmdOrCtrl+C' }, { role: 'paste', label: i18next.t('menu.editSubMenu.pasteLabel'), - id: MENU_ITEM_IDS.PASTE_MENU_ITEM + id: MENU_ITEM_IDS.PASTE_MENU_ITEM, + accelerator: 'CmdOrCtrl+V' }, ...(isMac ? [ @@ -180,12 +188,14 @@ module.exports = (params) => { { role: 'delete', label: i18next.t('menu.editSubMenu.deleteLabel'), - id: MENU_ITEM_IDS.DELETE_MENU_ITEM + id: MENU_ITEM_IDS.DELETE_MENU_ITEM, + accelerator: 'Delete' }, { role: 'selectAll', label: i18next.t('menu.editSubMenu.selectAllLabel'), - id: MENU_ITEM_IDS.SELECT_ALL_MENU_ITEM + id: MENU_ITEM_IDS.SELECT_ALL_MENU_ITEM, + accelerator: 'CmdOrCtrl+A' }, { type: 'separator' }, { @@ -208,13 +218,15 @@ module.exports = (params) => { { role: 'delete', label: i18next.t('menu.editSubMenu.deleteLabel'), - id: MENU_ITEM_IDS.DELETE_MENU_ITEM + id: MENU_ITEM_IDS.DELETE_MENU_ITEM, + accelerator: 'Delete' }, { type: 'separator' }, { role: 'selectAll', label: i18next.t('menu.editSubMenu.selectAllLabel'), - id: MENU_ITEM_IDS.SELECT_ALL_MENU_ITEM + id: MENU_ITEM_IDS.SELECT_ALL_MENU_ITEM, + accelerator: 'CmdOrCtrl+A' } ]) ] @@ -260,29 +272,34 @@ module.exports = (params) => { { role: 'toggleDevTools', label: i18next.t('menu.viewSubMenu.toggleDevToolsLabel'), - id: MENU_ITEM_IDS.TOGGLE_DEV_TOOLS_MENU_ITEM + id: MENU_ITEM_IDS.TOGGLE_DEV_TOOLS_MENU_ITEM, + accelerator: 'CmdOrCtrl+Shift+I' }, { type: 'separator' }, { role: 'resetZoom', label: i18next.t('menu.viewSubMenu.resetZoomLabel'), - id: MENU_ITEM_IDS.RESET_ZOOM_MENU_ITEM + id: MENU_ITEM_IDS.RESET_ZOOM_MENU_ITEM, + accelerator: 'CmdOrCtrl+0' }, { role: 'zoomIn', label: i18next.t('menu.viewSubMenu.zoomInLabel'), - id: MENU_ITEM_IDS.ZOOM_IN_MENU_ITEM + id: MENU_ITEM_IDS.ZOOM_IN_MENU_ITEM, + accelerator: 'CmdOrCtrl++' }, { role: 'zoomOut', label: i18next.t('menu.viewSubMenu.zoomOutLabel'), - id: MENU_ITEM_IDS.ZOOM_OUT_MENU_ITEM + id: MENU_ITEM_IDS.ZOOM_OUT_MENU_ITEM, + accelerator: 'CmdOrCtrl+-' }, { type: 'separator' }, { role: 'togglefullscreen', label: i18next.t('menu.viewSubMenu.togglefullscreenLabel'), - id: MENU_ITEM_IDS.TOGGLE_FULL_SCREEN_MENU_ITEM + id: MENU_ITEM_IDS.TOGGLE_FULL_SCREEN_MENU_ITEM, + accelerator: 'F11' } ] }, @@ -293,7 +310,8 @@ module.exports = (params) => { { role: 'minimize', label: i18next.t('menu.windowSubMenu.minimizeLabel'), - id: MENU_ITEM_IDS.MINIMIZE_MENU_ITEM + id: MENU_ITEM_IDS.MINIMIZE_MENU_ITEM, + accelerator: 'CmdOrCtrl+M' }, { role: 'zoom', @@ -319,7 +337,8 @@ module.exports = (params) => { { role: 'close', label: i18next.t('menu.fileSubMenu.closeLabel'), - id: MENU_ITEM_IDS.CLOSE_MENU_ITEM + id: MENU_ITEM_IDS.CLOSE_MENU_ITEM, + accelerator: 'CmdOrCtrl+W' } ]) ] @@ -333,31 +352,37 @@ module.exports = (params) => { { label: i18next.t('menu.toolsSubMenu.dataManagementSubMenu.exportDbLabel'), id: MENU_ITEM_IDS.EXPORT_DB_MENU_ITEM, + accelerator: 'CmdOrCtrl+Alt+E', click: exportDB({ pathToUserData, pathToUserDocuments }) }, { label: i18next.t('menu.toolsSubMenu.dataManagementSubMenu.importDbLabel'), id: MENU_ITEM_IDS.IMPORT_DB_MENU_ITEM, + accelerator: 'CmdOrCtrl+Alt+I', click: importDB({ pathToUserData, pathToUserDocuments }) }, { label: i18next.t('menu.toolsSubMenu.dataManagementSubMenu.restoreDbLabel'), id: MENU_ITEM_IDS.RESTORE_DB_MENU_ITEM, + accelerator: 'CmdOrCtrl+Alt+R', click: restoreDB() }, { label: i18next.t('menu.toolsSubMenu.dataManagementSubMenu.backupDbLabel'), id: MENU_ITEM_IDS.BACKUP_DB_MENU_ITEM, + accelerator: 'CmdOrCtrl+Alt+B', click: backupDB() }, { label: i18next.t('menu.toolsSubMenu.dataManagementSubMenu.removeDbLabel'), id: MENU_ITEM_IDS.REMOVE_DB_MENU_ITEM, + accelerator: 'CmdOrCtrl+Alt+D', click: removeDB({ pathToUserData }) }, { label: i18next.t('menu.toolsSubMenu.dataManagementSubMenu.clearAllDataLabel'), id: MENU_ITEM_IDS.CLEAR_ALL_DATA_MENU_ITEM, + accelerator: 'CmdOrCtrl+Alt+C', click: removeDB({ pathToUserData, shouldAllTablesBeCleared: true @@ -385,6 +410,7 @@ module.exports = (params) => { { label: i18next.t('menu.helpSubMenu.openNewGitHubIssueLabel'), id: MENU_ITEM_IDS.REPORT_BUG_MENU_ITEM, + accelerator: 'CmdOrCtrl+B', click: manageNewGithubIssue, ..._getPrevMenuItemPropsById(MENU_ITEM_IDS.REPORT_BUG_MENU_ITEM, [ { propName: 'visible', defaultVal: true }, @@ -420,6 +446,7 @@ module.exports = (params) => { { label: i18next.t('menu.helpSubMenu.changelogLabel'), id: MENU_ITEM_IDS.SHOW_CHANGE_LOG_MENU_ITEM, + acceleratorWorksWhenHidden: false, click: () => showChangelog(), ..._getPrevMenuItemPropsById(MENU_ITEM_IDS.SHOW_CHANGE_LOG_MENU_ITEM, [ { propName: 'visible', defaultVal: true }, @@ -436,6 +463,7 @@ module.exports = (params) => { { appName: app.name } ), id: MENU_ITEM_IDS.ABOUT_MENU_ITEM, + accelerator: 'CmdOrCtrl+O', click: showAboutModalDialog() } ]) From 5089709230fb4618c81c55dde163601f0b51ae7b Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Tue, 7 Jan 2025 13:15:28 +0200 Subject: [PATCH 29/61] Remap menu item accelerators separated by platforms --- src/create-menu/menu.item.accelerators.js | 58 +++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 src/create-menu/menu.item.accelerators.js diff --git a/src/create-menu/menu.item.accelerators.js b/src/create-menu/menu.item.accelerators.js new file mode 100644 index 00000000..950ded67 --- /dev/null +++ b/src/create-menu/menu.item.accelerators.js @@ -0,0 +1,58 @@ +'use strict' + +const isMac = process.platform === 'darwin' + +const MENU_ITEM_ACCELERATORS = { + ABOUT_MENU_ITEM: 'CmdOrCtrl+O', + QUIT_MENU_ITEM: 'CmdOrCtrl+Q', + UNDO_MENU_ITEM: 'CmdOrCtrl+Z', + REDO_MENU_ITEM: 'CmdOrCtrl+Shift+Z', + CUT_MENU_ITEM: 'CmdOrCtrl+X', + COPY_MENU_ITEM: 'CmdOrCtrl+C', + PASTE_MENU_ITEM: 'CmdOrCtrl+V', + DELETE_MENU_ITEM: 'Delete', + SELECT_ALL_MENU_ITEM: 'CmdOrCtrl+A', + RELOAD_MENU_ITEM: 'CmdOrCtrl+R', + FORCE_RELOAD_MENU_ITEM: 'CmdOrCtrl+Shift+R', + TOGGLE_DEV_TOOLS_MENU_ITEM: 'CmdOrCtrl+Shift+I', + RESET_ZOOM_MENU_ITEM: 'CmdOrCtrl+0', + ZOOM_IN_MENU_ITEM: 'CmdOrCtrl++', + ZOOM_OUT_MENU_ITEM: 'CmdOrCtrl+-', + TOGGLE_FULL_SCREEN_MENU_ITEM: 'F11', + MINIMIZE_MENU_ITEM: 'CmdOrCtrl+M', + CLOSE_MENU_ITEM: 'CmdOrCtrl+W', + EXPORT_DB_MENU_ITEM: 'CmdOrCtrl+Alt+E', + IMPORT_DB_MENU_ITEM: 'CmdOrCtrl+Alt+I', + RESTORE_DB_MENU_ITEM: 'CmdOrCtrl+Alt+R', + BACKUP_DB_MENU_ITEM: 'CmdOrCtrl+Alt+B', + REMOVE_DB_MENU_ITEM: 'CmdOrCtrl+Alt+D', + CLEAR_ALL_DATA_MENU_ITEM: 'CmdOrCtrl+Alt+C', + REPORT_BUG_MENU_ITEM: 'CmdOrCtrl+B', + USER_MANUAL_MENU_ITEM: 'CmdOrCtrl+H' +} + +const getPlatformShortcut = (shortcut) => { + if ( + shortcut.includes('CmdOrCtrl') || + shortcut.includes('CommandOrControl') + ) { + const cmdOrCtrlShortcut = isMac + ? 'Cmd' + : 'Ctrl' + + return shortcut + .replace('CmdOrCtrl', cmdOrCtrlShortcut) + .replace('CommandOrControl', cmdOrCtrlShortcut) + } + + return shortcut +} + +module.exports = Object.entries(MENU_ITEM_ACCELERATORS) + .reduce((accum, item) => { + const [key, val] = item ?? [] + + accum[key] = getPlatformShortcut(val) + + return accum + }, {}) From 8db8542a34e376438490c157a3ccf7d669e43727 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Tue, 7 Jan 2025 13:15:49 +0200 Subject: [PATCH 30/61] Add shortcut accelerators separated by platforms to menu --- src/create-menu/index.js | 63 ++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/src/create-menu/index.js b/src/create-menu/index.js index 2754558f..9d602faa 100644 --- a/src/create-menu/index.js +++ b/src/create-menu/index.js @@ -27,6 +27,7 @@ const isMainWinAvailable = require('../helpers/is-main-win-available') const wins = require('../window-creators/windows') const MENU_ITEM_IDS = require('./menu.item.ids') +const MENU_ITEM_ACCELERATORS = require('./menu.item.accelerators') const isAutoUpdateDisabled = parseEnvValToBool(process.env.IS_AUTO_UPDATE_DISABLED) @@ -90,7 +91,7 @@ module.exports = (params) => { { appName: app.name } ), id: MENU_ITEM_IDS.MAC_ABOUT_MENU_ITEM, - accelerator: 'CmdOrCtrl+O', + accelerator: MENU_ITEM_ACCELERATORS.ABOUT_MENU_ITEM, click: showAboutModalDialog() }, { type: 'separator' }, @@ -120,7 +121,7 @@ module.exports = (params) => { role: 'quit', label: i18next.t('menu.macMainSubmenu.quitLabel'), id: MENU_ITEM_IDS.MAC_QUIT_MENU_ITEM, - accelerator: 'CmdOrCtrl+Q' + accelerator: MENU_ITEM_ACCELERATORS.QUIT_MENU_ITEM } ] }] @@ -139,7 +140,7 @@ module.exports = (params) => { role: 'quit', label: i18next.t('menu.fileSubMenu.quitLabel'), id: MENU_ITEM_IDS.QUIT_MENU_ITEM, - accelerator: 'CmdOrCtrl+Q' + accelerator: MENU_ITEM_ACCELERATORS.QUIT_MENU_ITEM } ] }, @@ -151,32 +152,32 @@ module.exports = (params) => { role: 'undo', label: i18next.t('menu.editSubMenu.undoLabel'), id: MENU_ITEM_IDS.UNDO_MENU_ITEM, - accelerator: 'CmdOrCtrl+Z' + accelerator: MENU_ITEM_ACCELERATORS.UNDO_MENU_ITEM }, { role: 'redo', label: i18next.t('menu.editSubMenu.redoLabel'), id: MENU_ITEM_IDS.REDO_MENU_ITEM, - accelerator: 'CmdOrCtrl+Shift+Z' + accelerator: MENU_ITEM_ACCELERATORS.REDO_MENU_ITEM }, { type: 'separator' }, { role: 'cut', label: i18next.t('menu.editSubMenu.cutLabel'), id: MENU_ITEM_IDS.CUT_MENU_ITEM, - accelerator: 'CmdOrCtrl+X' + accelerator: MENU_ITEM_ACCELERATORS.CUT_MENU_ITEM }, { role: 'copy', label: i18next.t('menu.editSubMenu.copyLabel'), id: MENU_ITEM_IDS.COPY_MENU_ITEM, - accelerator: 'CmdOrCtrl+C' + accelerator: MENU_ITEM_ACCELERATORS.COPY_MENU_ITEM }, { role: 'paste', label: i18next.t('menu.editSubMenu.pasteLabel'), id: MENU_ITEM_IDS.PASTE_MENU_ITEM, - accelerator: 'CmdOrCtrl+V' + accelerator: MENU_ITEM_ACCELERATORS.PASTE_MENU_ITEM }, ...(isMac ? [ @@ -189,13 +190,13 @@ module.exports = (params) => { role: 'delete', label: i18next.t('menu.editSubMenu.deleteLabel'), id: MENU_ITEM_IDS.DELETE_MENU_ITEM, - accelerator: 'Delete' + accelerator: MENU_ITEM_ACCELERATORS.DELETE_MENU_ITEM }, { role: 'selectAll', label: i18next.t('menu.editSubMenu.selectAllLabel'), id: MENU_ITEM_IDS.SELECT_ALL_MENU_ITEM, - accelerator: 'CmdOrCtrl+A' + accelerator: MENU_ITEM_ACCELERATORS.SELECT_ALL_MENU_ITEM }, { type: 'separator' }, { @@ -219,14 +220,14 @@ module.exports = (params) => { role: 'delete', label: i18next.t('menu.editSubMenu.deleteLabel'), id: MENU_ITEM_IDS.DELETE_MENU_ITEM, - accelerator: 'Delete' + accelerator: MENU_ITEM_ACCELERATORS.DELETE_MENU_ITEM }, { type: 'separator' }, { role: 'selectAll', label: i18next.t('menu.editSubMenu.selectAllLabel'), id: MENU_ITEM_IDS.SELECT_ALL_MENU_ITEM, - accelerator: 'CmdOrCtrl+A' + accelerator: MENU_ITEM_ACCELERATORS.SELECT_ALL_MENU_ITEM } ]) ] @@ -238,7 +239,7 @@ module.exports = (params) => { { label: i18next.t('menu.viewSubMenu.reloadLabel'), id: MENU_ITEM_IDS.RELOAD_MENU_ITEM, - accelerator: 'CmdOrCtrl+R', + accelerator: MENU_ITEM_ACCELERATORS.RELOAD_MENU_ITEM, click: (item, focusedWindow) => { const win = isMainWinAvailable(wins.mainWindow) ? wins.mainWindow @@ -255,7 +256,7 @@ module.exports = (params) => { { label: i18next.t('menu.viewSubMenu.forceReloadLabel'), id: MENU_ITEM_IDS.FORCE_RELOAD_MENU_ITEM, - accelerator: 'CmdOrCtrl+Shift+R', + accelerator: MENU_ITEM_ACCELERATORS.FORCE_RELOAD_MENU_ITEM, click: (item, focusedWindow) => { const win = isMainWinAvailable(wins.mainWindow) ? wins.mainWindow @@ -273,33 +274,33 @@ module.exports = (params) => { role: 'toggleDevTools', label: i18next.t('menu.viewSubMenu.toggleDevToolsLabel'), id: MENU_ITEM_IDS.TOGGLE_DEV_TOOLS_MENU_ITEM, - accelerator: 'CmdOrCtrl+Shift+I' + accelerator: MENU_ITEM_ACCELERATORS.TOGGLE_DEV_TOOLS_MENU_ITEM }, { type: 'separator' }, { role: 'resetZoom', label: i18next.t('menu.viewSubMenu.resetZoomLabel'), id: MENU_ITEM_IDS.RESET_ZOOM_MENU_ITEM, - accelerator: 'CmdOrCtrl+0' + accelerator: MENU_ITEM_ACCELERATORS.RESET_ZOOM_MENU_ITEM }, { role: 'zoomIn', label: i18next.t('menu.viewSubMenu.zoomInLabel'), id: MENU_ITEM_IDS.ZOOM_IN_MENU_ITEM, - accelerator: 'CmdOrCtrl++' + accelerator: MENU_ITEM_ACCELERATORS.ZOOM_IN_MENU_ITEM }, { role: 'zoomOut', label: i18next.t('menu.viewSubMenu.zoomOutLabel'), id: MENU_ITEM_IDS.ZOOM_OUT_MENU_ITEM, - accelerator: 'CmdOrCtrl+-' + accelerator: MENU_ITEM_ACCELERATORS.ZOOM_OUT_MENU_ITEM }, { type: 'separator' }, { role: 'togglefullscreen', label: i18next.t('menu.viewSubMenu.togglefullscreenLabel'), id: MENU_ITEM_IDS.TOGGLE_FULL_SCREEN_MENU_ITEM, - accelerator: 'F11' + accelerator: MENU_ITEM_ACCELERATORS.TOGGLE_FULL_SCREEN_MENU_ITEM } ] }, @@ -311,7 +312,7 @@ module.exports = (params) => { role: 'minimize', label: i18next.t('menu.windowSubMenu.minimizeLabel'), id: MENU_ITEM_IDS.MINIMIZE_MENU_ITEM, - accelerator: 'CmdOrCtrl+M' + accelerator: MENU_ITEM_ACCELERATORS.MINIMIZE_MENU_ITEM }, { role: 'zoom', @@ -338,7 +339,7 @@ module.exports = (params) => { role: 'close', label: i18next.t('menu.fileSubMenu.closeLabel'), id: MENU_ITEM_IDS.CLOSE_MENU_ITEM, - accelerator: 'CmdOrCtrl+W' + accelerator: MENU_ITEM_ACCELERATORS.CLOSE_MENU_ITEM } ]) ] @@ -352,37 +353,37 @@ module.exports = (params) => { { label: i18next.t('menu.toolsSubMenu.dataManagementSubMenu.exportDbLabel'), id: MENU_ITEM_IDS.EXPORT_DB_MENU_ITEM, - accelerator: 'CmdOrCtrl+Alt+E', + accelerator: MENU_ITEM_ACCELERATORS.EXPORT_DB_MENU_ITEM, click: exportDB({ pathToUserData, pathToUserDocuments }) }, { label: i18next.t('menu.toolsSubMenu.dataManagementSubMenu.importDbLabel'), id: MENU_ITEM_IDS.IMPORT_DB_MENU_ITEM, - accelerator: 'CmdOrCtrl+Alt+I', + accelerator: MENU_ITEM_ACCELERATORS.IMPORT_DB_MENU_ITEM, click: importDB({ pathToUserData, pathToUserDocuments }) }, { label: i18next.t('menu.toolsSubMenu.dataManagementSubMenu.restoreDbLabel'), id: MENU_ITEM_IDS.RESTORE_DB_MENU_ITEM, - accelerator: 'CmdOrCtrl+Alt+R', + accelerator: MENU_ITEM_ACCELERATORS.RESTORE_DB_MENU_ITEM, click: restoreDB() }, { label: i18next.t('menu.toolsSubMenu.dataManagementSubMenu.backupDbLabel'), id: MENU_ITEM_IDS.BACKUP_DB_MENU_ITEM, - accelerator: 'CmdOrCtrl+Alt+B', + accelerator: MENU_ITEM_ACCELERATORS.BACKUP_DB_MENU_ITEM, click: backupDB() }, { label: i18next.t('menu.toolsSubMenu.dataManagementSubMenu.removeDbLabel'), id: MENU_ITEM_IDS.REMOVE_DB_MENU_ITEM, - accelerator: 'CmdOrCtrl+Alt+D', + accelerator: MENU_ITEM_ACCELERATORS.REMOVE_DB_MENU_ITEM, click: removeDB({ pathToUserData }) }, { label: i18next.t('menu.toolsSubMenu.dataManagementSubMenu.clearAllDataLabel'), id: MENU_ITEM_IDS.CLEAR_ALL_DATA_MENU_ITEM, - accelerator: 'CmdOrCtrl+Alt+C', + accelerator: MENU_ITEM_ACCELERATORS.CLEAR_ALL_DATA_MENU_ITEM, click: removeDB({ pathToUserData, shouldAllTablesBeCleared: true @@ -410,7 +411,8 @@ module.exports = (params) => { { label: i18next.t('menu.helpSubMenu.openNewGitHubIssueLabel'), id: MENU_ITEM_IDS.REPORT_BUG_MENU_ITEM, - accelerator: 'CmdOrCtrl+B', + accelerator: MENU_ITEM_ACCELERATORS.REPORT_BUG_MENU_ITEM, + acceleratorWorksWhenHidden: false, click: manageNewGithubIssue, ..._getPrevMenuItemPropsById(MENU_ITEM_IDS.REPORT_BUG_MENU_ITEM, [ { propName: 'visible', defaultVal: true }, @@ -440,13 +442,12 @@ module.exports = (params) => { { label: i18next.t('menu.helpSubMenu.userManualLabel'), id: MENU_ITEM_IDS.USER_MANUAL_MENU_ITEM, - accelerator: 'CmdOrCtrl+H', + accelerator: MENU_ITEM_ACCELERATORS.USER_MANUAL_MENU_ITEM, click: () => showDocs() }, { label: i18next.t('menu.helpSubMenu.changelogLabel'), id: MENU_ITEM_IDS.SHOW_CHANGE_LOG_MENU_ITEM, - acceleratorWorksWhenHidden: false, click: () => showChangelog(), ..._getPrevMenuItemPropsById(MENU_ITEM_IDS.SHOW_CHANGE_LOG_MENU_ITEM, [ { propName: 'visible', defaultVal: true }, @@ -463,7 +464,7 @@ module.exports = (params) => { { appName: app.name } ), id: MENU_ITEM_IDS.ABOUT_MENU_ITEM, - accelerator: 'CmdOrCtrl+O', + accelerator: MENU_ITEM_ACCELERATORS.ABOUT_MENU_ITEM, click: showAboutModalDialog() } ]) From d8ca92acd1749c7adf47790e75dee018dffee29a Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Wed, 8 Jan 2025 12:38:15 +0200 Subject: [PATCH 31/61] Adjust menu item ids for mac --- src/create-menu/menu.item.ids.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/create-menu/menu.item.ids.js b/src/create-menu/menu.item.ids.js index 634e3d74..38180e16 100644 --- a/src/create-menu/menu.item.ids.js +++ b/src/create-menu/menu.item.ids.js @@ -2,17 +2,19 @@ module.exports = { MAC_ABOUT_MENU_ITEM: 'MAC_ABOUT_MENU_ITEM', - MAC_SERVICES_MENU_ITEM: 'MAC_SERVICES_MENU_ITEM', MAC_HIDE_MENU_ITEM: 'MAC_HIDE_MENU_ITEM', MAC_HIDE_OTHERS_MENU_ITEM: 'MAC_HIDE_OTHERS_MENU_ITEM', MAC_UNHIDE_MENU_ITEM: 'MAC_UNHIDE_MENU_ITEM', MAC_QUIT_MENU_ITEM: 'MAC_QUIT_MENU_ITEM', MAC_CLOSE_MENU_ITEM: 'MAC_CLOSE_MENU_ITEM', MAC_PASTE_AND_MATCH_STYLE_MENU_ITEM: 'MAC_PASTE_AND_MATCH_STYLE_MENU_ITEM', + MAC_SHOW_SUBSTITUTIONS: 'MAC_SHOW_SUBSTITUTIONS', + MAC_TOGGLE_SMART_QUOTES: 'MAC_TOGGLE_SMART_QUOTES', + MAC_TOGGLE_SMART_DASHES: 'MAC_TOGGLE_SMART_DASHES', + MAC_TOGGLE_TEXT_REPLACEMENT: 'MAC_TOGGLE_TEXT_REPLACEMENT', MAC_START_SPEAKING_MENU_ITEM: 'MAC_START_SPEAKING_MENU_ITEM', MAC_STOP_SPEAKING_MENU_ITEM: 'MAC_STOP_SPEAKING_MENU_ITEM', MAC_FRONT_MENU_ITEM: 'MAC_FRONT_MENU_ITEM', - MAC_WINDOW_MENU_ITEM: 'MAC_WINDOW_MENU_ITEM', QUIT_MENU_ITEM: 'QUIT_MENU_ITEM', From 8e2c7719aa13ba2c4d86e7b73e1452754ac52be2 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Wed, 8 Jan 2025 12:38:41 +0200 Subject: [PATCH 32/61] Adjust menu item accelerators for mac --- src/create-menu/menu.item.accelerators.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/create-menu/menu.item.accelerators.js b/src/create-menu/menu.item.accelerators.js index 950ded67..017b8e51 100644 --- a/src/create-menu/menu.item.accelerators.js +++ b/src/create-menu/menu.item.accelerators.js @@ -3,6 +3,12 @@ const isMac = process.platform === 'darwin' const MENU_ITEM_ACCELERATORS = { + MAC_HIDE_MENU_ITEM: 'CmdOrCtrl+H', + MAC_HIDE_OTHERS_MENU_ITEM: 'CmdOrCtrl+Alt+H', + MAC_PASTE_AND_MATCH_STYLE_MENU_ITEM: 'CmdOrCtrll+Alt+Shift+V', + MAC_TOGGLE_DEV_TOOLS_MENU_ITEM: 'CmdOrCtrl+Alt+I', + MAC_TOGGLE_FULL_SCREEN_MENU_ITEM: 'Option+F', + ABOUT_MENU_ITEM: 'CmdOrCtrl+O', QUIT_MENU_ITEM: 'CmdOrCtrl+Q', UNDO_MENU_ITEM: 'CmdOrCtrl+Z', @@ -10,7 +16,6 @@ const MENU_ITEM_ACCELERATORS = { CUT_MENU_ITEM: 'CmdOrCtrl+X', COPY_MENU_ITEM: 'CmdOrCtrl+C', PASTE_MENU_ITEM: 'CmdOrCtrl+V', - DELETE_MENU_ITEM: 'Delete', SELECT_ALL_MENU_ITEM: 'CmdOrCtrl+A', RELOAD_MENU_ITEM: 'CmdOrCtrl+R', FORCE_RELOAD_MENU_ITEM: 'CmdOrCtrl+Shift+R', From 5d56bfaceb0d1d147a01984f1d32dde8747ba160 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Wed, 8 Jan 2025 12:39:02 +0200 Subject: [PATCH 33/61] Adjust menu item for mac --- src/create-menu/index.js | 57 ++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/src/create-menu/index.js b/src/create-menu/index.js index 9d602faa..b721c296 100644 --- a/src/create-menu/index.js +++ b/src/create-menu/index.js @@ -97,19 +97,20 @@ module.exports = (params) => { { type: 'separator' }, { role: 'services', - label: i18next.t('menu.macMainSubmenu.servicesLabel'), - id: MENU_ITEM_IDS.MAC_SERVICES_MENU_ITEM + label: i18next.t('menu.macMainSubmenu.servicesLabel') }, { type: 'separator' }, { role: 'hide', label: i18next.t('menu.macMainSubmenu.hideLabel'), - id: MENU_ITEM_IDS.MAC_HIDE_MENU_ITEM + id: MENU_ITEM_IDS.MAC_HIDE_MENU_ITEM, + accelerator: MENU_ITEM_ACCELERATORS.MAC_HIDE_MENU_ITEM }, { role: 'hideOthers', label: i18next.t('menu.macMainSubmenu.hideOthersLabel'), - id: MENU_ITEM_IDS.MAC_HIDE_OTHERS_MENU_ITEM + id: MENU_ITEM_IDS.MAC_HIDE_OTHERS_MENU_ITEM, + accelerator: MENU_ITEM_ACCELERATORS.MAC_HIDE_OTHERS_MENU_ITEM }, { role: 'unhide', @@ -134,7 +135,8 @@ module.exports = (params) => { ? { role: 'close', label: i18next.t('menu.fileSubMenu.closeLabel'), - id: MENU_ITEM_IDS.MAC_CLOSE_MENU_ITEM + id: MENU_ITEM_IDS.MAC_CLOSE_MENU_ITEM, + accelerator: MENU_ITEM_ACCELERATORS.CLOSE_MENU_ITEM } : { role: 'quit', @@ -184,13 +186,13 @@ module.exports = (params) => { { role: 'pasteAndMatchStyle', label: i18next.t('menu.editSubMenu.pasteAndMatchStyleLabel'), - id: MENU_ITEM_IDS.MAC_PASTE_AND_MATCH_STYLE_MENU_ITEM + id: MENU_ITEM_IDS.MAC_PASTE_AND_MATCH_STYLE_MENU_ITEM, + accelerator: MENU_ITEM_ACCELERATORS.MAC_PASTE_AND_MATCH_STYLE_MENU_ITEM }, { role: 'delete', label: i18next.t('menu.editSubMenu.deleteLabel'), - id: MENU_ITEM_IDS.DELETE_MENU_ITEM, - accelerator: MENU_ITEM_ACCELERATORS.DELETE_MENU_ITEM + id: MENU_ITEM_IDS.DELETE_MENU_ITEM }, { role: 'selectAll', @@ -199,6 +201,31 @@ module.exports = (params) => { accelerator: MENU_ITEM_ACCELERATORS.SELECT_ALL_MENU_ITEM }, { type: 'separator' }, + { + label: i18next.t('menu.editSubMenu.substitutionsSubMenu.label'), + submenu: [ + { + role: 'showSubstitutions', + label: i18next.t('menu.editSubMenu.substitutionsSubMenu.showSubstitutions'), + id: MENU_ITEM_IDS.MAC_SHOW_SUBSTITUTIONS + }, + { + role: 'toggleSmartQuotes', + label: i18next.t('menu.editSubMenu.substitutionsSubMenu.toggleSmartQuotes'), + id: MENU_ITEM_IDS.MAC_TOGGLE_SMART_QUOTES + }, + { + role: 'toggleSmartDashes', + label: i18next.t('menu.editSubMenu.substitutionsSubMenu.toggleSmartDashes'), + id: MENU_ITEM_IDS.MAC_TOGGLE_SMART_DASHES + }, + { + role: 'toggleTextReplacement', + label: i18next.t('menu.editSubMenu.substitutionsSubMenu.toggleTextReplacement'), + id: MENU_ITEM_IDS.MAC_TOGGLE_TEXT_REPLACEMENT + } + ] + }, { label: i18next.t('menu.editSubMenu.speechSubMenu.label'), submenu: [ @@ -219,8 +246,7 @@ module.exports = (params) => { { role: 'delete', label: i18next.t('menu.editSubMenu.deleteLabel'), - id: MENU_ITEM_IDS.DELETE_MENU_ITEM, - accelerator: MENU_ITEM_ACCELERATORS.DELETE_MENU_ITEM + id: MENU_ITEM_IDS.DELETE_MENU_ITEM }, { type: 'separator' }, { @@ -274,7 +300,9 @@ module.exports = (params) => { role: 'toggleDevTools', label: i18next.t('menu.viewSubMenu.toggleDevToolsLabel'), id: MENU_ITEM_IDS.TOGGLE_DEV_TOOLS_MENU_ITEM, - accelerator: MENU_ITEM_ACCELERATORS.TOGGLE_DEV_TOOLS_MENU_ITEM + accelerator: isMac + ? MENU_ITEM_ACCELERATORS.MAC_TOGGLE_DEV_TOOLS_MENU_ITEM + : MENU_ITEM_ACCELERATORS.TOGGLE_DEV_TOOLS_MENU_ITEM }, { type: 'separator' }, { @@ -300,7 +328,9 @@ module.exports = (params) => { role: 'togglefullscreen', label: i18next.t('menu.viewSubMenu.togglefullscreenLabel'), id: MENU_ITEM_IDS.TOGGLE_FULL_SCREEN_MENU_ITEM, - accelerator: MENU_ITEM_ACCELERATORS.TOGGLE_FULL_SCREEN_MENU_ITEM + accelerator: isMac + ? MENU_ITEM_ACCELERATORS.MAC_TOGGLE_FULL_SCREEN_MENU_ITEM + : MENU_ITEM_ACCELERATORS.TOGGLE_FULL_SCREEN_MENU_ITEM } ] }, @@ -330,8 +360,7 @@ module.exports = (params) => { { type: 'separator' }, { role: 'window', - label: i18next.t('menu.windowSubMenu.windowLabel'), - id: MENU_ITEM_IDS.MAC_WINDOW_MENU_ITEM + label: i18next.t('menu.windowSubMenu.windowLabel') } ] : [ From a911afcd655437e51bc69b838ccba9d5af700ee6 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Wed, 8 Jan 2025 12:39:23 +0200 Subject: [PATCH 34/61] Enhance en menu translation for mac --- build/locales/en/translations.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/build/locales/en/translations.json b/build/locales/en/translations.json index c4353cc9..1939090e 100644 --- a/build/locales/en/translations.json +++ b/build/locales/en/translations.json @@ -26,6 +26,13 @@ "pasteAndMatchStyleLabel": "Paste And Match Style", "deleteLabel": "Delete", "selectAllLabel": "Select All", + "substitutionsSubMenu": { + "label": "Substitutions", + "showSubstitutions": "Show Substitutions", + "toggleSmartQuotes": "Smart Quotes", + "toggleSmartDashes": "Smart Dashes", + "toggleTextReplacement": "Text Replacement" + }, "speechSubMenu": { "label": "Speech", "startSpeakingLabel": "Start Speaking", @@ -46,7 +53,7 @@ "label": "Window", "minimizeLabel": "Minimize", "zoomLabel": "Zoom", - "frontLabel": "Front", + "frontLabel": "Bring All to Front", "windowLabel": "Window" }, "toolsSubMenu": { From fc95c9bcfe218cff425369700d002a48f71f81af Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Wed, 8 Jan 2025 12:39:39 +0200 Subject: [PATCH 35/61] Enhance ru menu translation for mac --- build/locales/ru/translations.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/build/locales/ru/translations.json b/build/locales/ru/translations.json index 04d667a5..3df34d17 100644 --- a/build/locales/ru/translations.json +++ b/build/locales/ru/translations.json @@ -5,7 +5,7 @@ }, "menu": { "macMainSubmenu": { - "servicesLabel": "Услуги", + "servicesLabel": "Службы", "hideLabel": "Скрыть", "hideOthersLabel": "Скрыть Другие", "unhideLabel": "Показать", @@ -26,6 +26,13 @@ "pasteAndMatchStyleLabel": "Вставить и Сопоставить Стиль", "deleteLabel": "Удалить", "selectAllLabel": "Выбрать Все", + "substitutionsSubMenu": { + "label": "Подстановки", + "showSubstitutions": "Показать Подстановки", + "toggleSmartQuotes": "Умные Цитаты", + "toggleSmartDashes": "Умные Тире", + "toggleTextReplacement": "Замена текста" + }, "speechSubMenu": { "label": "Речь", "startSpeakingLabel": "Начать Говорить", From 2b0f4beea03ff7ed6e388f4514f5ad0d476417fe Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Wed, 8 Jan 2025 14:32:46 +0200 Subject: [PATCH 36/61] Unify menu item accelerator key codes --- src/create-menu/index.js | 4 +- src/create-menu/menu.item.accelerators.js | 221 ++++++++++++++++++---- 2 files changed, 187 insertions(+), 38 deletions(-) diff --git a/src/create-menu/index.js b/src/create-menu/index.js index b721c296..dd1f2778 100644 --- a/src/create-menu/index.js +++ b/src/create-menu/index.js @@ -471,7 +471,9 @@ module.exports = (params) => { { label: i18next.t('menu.helpSubMenu.userManualLabel'), id: MENU_ITEM_IDS.USER_MANUAL_MENU_ITEM, - accelerator: MENU_ITEM_ACCELERATORS.USER_MANUAL_MENU_ITEM, + accelerator: isMac + ? MENU_ITEM_ACCELERATORS.MAC_USER_MANUAL_MENU_ITEM + : MENU_ITEM_ACCELERATORS.USER_MANUAL_MENU_ITEM, click: () => showDocs() }, { diff --git a/src/create-menu/menu.item.accelerators.js b/src/create-menu/menu.item.accelerators.js index 017b8e51..f7eb8ac7 100644 --- a/src/create-menu/menu.item.accelerators.js +++ b/src/create-menu/menu.item.accelerators.js @@ -2,52 +2,199 @@ const isMac = process.platform === 'darwin' +const CONJUCTION_CHARACTER = '+' +const KEY_MODIFIERS = { + CMD_OR_CTRL: 'CmdOrCtrl', + COMMAND_OR_CONTROL: 'CommandOrControl', + CMD: 'Cmd', + CTRL: 'Ctrl', + ALT: 'Alt', + SHIFT: 'Shift', + OPTION: 'Option' +} +const KEY_CODES = { + H: 'H', + V: 'V', + I: 'I', + F: 'F', + O: 'O', + Q: 'Q', + Z: 'Z', + X: 'X', + C: 'C', + A: 'A', + R: 'R', + ZERO: '0', + PLUS: '+', + MINUS: '-', + F11: 'F11', + M: 'M', + W: 'W', + E: 'E', + B: 'B', + D: 'D' +} + +const constructAccelerator = (...keys) => { + if (keys.length === 0) { + return '' + } + + return keys.join(CONJUCTION_CHARACTER) +} + const MENU_ITEM_ACCELERATORS = { - MAC_HIDE_MENU_ITEM: 'CmdOrCtrl+H', - MAC_HIDE_OTHERS_MENU_ITEM: 'CmdOrCtrl+Alt+H', - MAC_PASTE_AND_MATCH_STYLE_MENU_ITEM: 'CmdOrCtrll+Alt+Shift+V', - MAC_TOGGLE_DEV_TOOLS_MENU_ITEM: 'CmdOrCtrl+Alt+I', - MAC_TOGGLE_FULL_SCREEN_MENU_ITEM: 'Option+F', - - ABOUT_MENU_ITEM: 'CmdOrCtrl+O', - QUIT_MENU_ITEM: 'CmdOrCtrl+Q', - UNDO_MENU_ITEM: 'CmdOrCtrl+Z', - REDO_MENU_ITEM: 'CmdOrCtrl+Shift+Z', - CUT_MENU_ITEM: 'CmdOrCtrl+X', - COPY_MENU_ITEM: 'CmdOrCtrl+C', - PASTE_MENU_ITEM: 'CmdOrCtrl+V', - SELECT_ALL_MENU_ITEM: 'CmdOrCtrl+A', - RELOAD_MENU_ITEM: 'CmdOrCtrl+R', - FORCE_RELOAD_MENU_ITEM: 'CmdOrCtrl+Shift+R', - TOGGLE_DEV_TOOLS_MENU_ITEM: 'CmdOrCtrl+Shift+I', - RESET_ZOOM_MENU_ITEM: 'CmdOrCtrl+0', - ZOOM_IN_MENU_ITEM: 'CmdOrCtrl++', - ZOOM_OUT_MENU_ITEM: 'CmdOrCtrl+-', - TOGGLE_FULL_SCREEN_MENU_ITEM: 'F11', - MINIMIZE_MENU_ITEM: 'CmdOrCtrl+M', - CLOSE_MENU_ITEM: 'CmdOrCtrl+W', - EXPORT_DB_MENU_ITEM: 'CmdOrCtrl+Alt+E', - IMPORT_DB_MENU_ITEM: 'CmdOrCtrl+Alt+I', - RESTORE_DB_MENU_ITEM: 'CmdOrCtrl+Alt+R', - BACKUP_DB_MENU_ITEM: 'CmdOrCtrl+Alt+B', - REMOVE_DB_MENU_ITEM: 'CmdOrCtrl+Alt+D', - CLEAR_ALL_DATA_MENU_ITEM: 'CmdOrCtrl+Alt+C', - REPORT_BUG_MENU_ITEM: 'CmdOrCtrl+B', - USER_MANUAL_MENU_ITEM: 'CmdOrCtrl+H' + MAC_HIDE_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_CODES.H + ), + MAC_HIDE_OTHERS_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_MODIFIERS.ALT, + KEY_CODES.H + ), + MAC_PASTE_AND_MATCH_STYLE_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_MODIFIERS.ALT, + KEY_MODIFIERS.SHIFT, + KEY_CODES.V + ), + MAC_TOGGLE_DEV_TOOLS_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_MODIFIERS.ALT, + KEY_CODES.I + ), + MAC_TOGGLE_FULL_SCREEN_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.OPTION, + KEY_CODES.F + ), + MAC_USER_MANUAL_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.OPTION, + KEY_CODES.H + ), + + ABOUT_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_CODES.O + ), + QUIT_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_CODES.Q + ), + UNDO_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_CODES.Z + ), + REDO_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_MODIFIERS.SHIFT, + KEY_CODES.Z + ), + CUT_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_CODES.X + ), + COPY_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_CODES.C + ), + PASTE_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_CODES.V + ), + SELECT_ALL_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_CODES.A + ), + RELOAD_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_CODES.R + ), + FORCE_RELOAD_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_MODIFIERS.SHIFT, + KEY_CODES.R + ), + TOGGLE_DEV_TOOLS_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_MODIFIERS.SHIFT, + KEY_CODES.I + ), + RESET_ZOOM_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_CODES.ZERO + ), + ZOOM_IN_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_CODES.PLUS + ), + ZOOM_OUT_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_CODES.MINUS + ), + TOGGLE_FULL_SCREEN_MENU_ITEM: constructAccelerator( + KEY_CODES.F11 + ), + MINIMIZE_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_CODES.M + ), + CLOSE_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_CODES.W + ), + EXPORT_DB_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_MODIFIERS.ALT, + KEY_CODES.E + ), + IMPORT_DB_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_MODIFIERS.ALT, + KEY_CODES.I + ), + RESTORE_DB_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_MODIFIERS.ALT, + KEY_CODES.R + ), + BACKUP_DB_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_MODIFIERS.ALT, + KEY_CODES.B + ), + REMOVE_DB_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_MODIFIERS.ALT, + KEY_CODES.D + ), + CLEAR_ALL_DATA_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_MODIFIERS.ALT, + KEY_CODES.C + ), + REPORT_BUG_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_CODES.B + ), + USER_MANUAL_MENU_ITEM: constructAccelerator( + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_CODES.H + ) } const getPlatformShortcut = (shortcut) => { if ( - shortcut.includes('CmdOrCtrl') || - shortcut.includes('CommandOrControl') + shortcut.includes(KEY_MODIFIERS.CMD_OR_CTRL) || + shortcut.includes(KEY_MODIFIERS.COMMAND_OR_CONTROL) ) { const cmdOrCtrlShortcut = isMac - ? 'Cmd' - : 'Ctrl' + ? KEY_MODIFIERS.CMD + : KEY_MODIFIERS.CTRL return shortcut - .replace('CmdOrCtrl', cmdOrCtrlShortcut) - .replace('CommandOrControl', cmdOrCtrlShortcut) + .replace(KEY_MODIFIERS.CMD_OR_CTRL, cmdOrCtrlShortcut) + .replace(KEY_MODIFIERS.COMMAND_OR_CONTROL, cmdOrCtrlShortcut) } return shortcut From ae41888f87b0c1327f599c7026a300e5091a3e3b Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Thu, 9 Jan 2025 15:02:58 +0200 Subject: [PATCH 37/61] Fix import menu item accelerator for mac --- src/create-menu/menu.item.accelerators.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/create-menu/menu.item.accelerators.js b/src/create-menu/menu.item.accelerators.js index f7eb8ac7..0473f05c 100644 --- a/src/create-menu/menu.item.accelerators.js +++ b/src/create-menu/menu.item.accelerators.js @@ -151,6 +151,7 @@ const MENU_ITEM_ACCELERATORS = { IMPORT_DB_MENU_ITEM: constructAccelerator( KEY_MODIFIERS.CMD_OR_CTRL, KEY_MODIFIERS.ALT, + KEY_MODIFIERS.SHIFT, KEY_CODES.I ), RESTORE_DB_MENU_ITEM: constructAccelerator( From a7536542cf0dc71e00997c0609aa9c740bb7b8d4 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Thu, 9 Jan 2025 15:09:55 +0200 Subject: [PATCH 38/61] Fix user manual menu item accelerator for mac --- src/create-menu/menu.item.accelerators.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/create-menu/menu.item.accelerators.js b/src/create-menu/menu.item.accelerators.js index 0473f05c..cb585567 100644 --- a/src/create-menu/menu.item.accelerators.js +++ b/src/create-menu/menu.item.accelerators.js @@ -69,7 +69,8 @@ const MENU_ITEM_ACCELERATORS = { KEY_CODES.F ), MAC_USER_MANUAL_MENU_ITEM: constructAccelerator( - KEY_MODIFIERS.OPTION, + KEY_MODIFIERS.CMD_OR_CTRL, + KEY_MODIFIERS.SHIFT, KEY_CODES.H ), From b23d1e7c6bbe07c410925d1a12bdce3cef420389 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Thu, 9 Jan 2025 15:23:36 +0200 Subject: [PATCH 39/61] Fix toggle fullscreen menu item accelerator for mac --- src/create-menu/menu.item.accelerators.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/create-menu/menu.item.accelerators.js b/src/create-menu/menu.item.accelerators.js index cb585567..6b862237 100644 --- a/src/create-menu/menu.item.accelerators.js +++ b/src/create-menu/menu.item.accelerators.js @@ -9,8 +9,7 @@ const KEY_MODIFIERS = { CMD: 'Cmd', CTRL: 'Ctrl', ALT: 'Alt', - SHIFT: 'Shift', - OPTION: 'Option' + SHIFT: 'Shift' } const KEY_CODES = { H: 'H', @@ -65,7 +64,7 @@ const MENU_ITEM_ACCELERATORS = { KEY_CODES.I ), MAC_TOGGLE_FULL_SCREEN_MENU_ITEM: constructAccelerator( - KEY_MODIFIERS.OPTION, + KEY_MODIFIERS.CMD_OR_CTRL, KEY_CODES.F ), MAC_USER_MANUAL_MENU_ITEM: constructAccelerator( From a482329f8bb98b1d3bb02884564c4da099e11e39 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Fri, 10 Jan 2025 12:15:31 +0200 Subject: [PATCH 40/61] Prevent custom menu rendering for mac --- .../main-renderer-ipc-bridge/menu-ipc-channel-handlers.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js b/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js index 345cfc70..bae638b8 100644 --- a/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js +++ b/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js @@ -4,11 +4,14 @@ const { BaseWindow, webContents, Menu } = require('electron') const IpcChannelHandlers = require('./ipc.channel.handlers') +const isMac = process.platform === 'darwin' + class MenuIpcChannelHandlers extends IpcChannelHandlers { static channelName = 'menu' #serializeMenu (menu) { if ( + isMac || !Array.isArray(menu?.items) || menu.items.length === 0 ) { From 81b78dbab5cc618bdd004218193c5054bc5d7106 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Fri, 10 Jan 2025 12:18:23 +0200 Subject: [PATCH 41/61] Set title bar overlay height for mac --- src/window-creators/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/window-creators/index.js b/src/window-creators/index.js index 475666ce..1a9f0ad5 100644 --- a/src/window-creators/index.js +++ b/src/window-creators/index.js @@ -238,7 +238,7 @@ const createMainWindow = async ({ pathToUserDocuments }) => { const titleBarOverlayOpt = isMac - ? {} + ? { titleBarOverlay: { height: 26 } } : { titleBarOverlay: { height: 40, From 1e5f3d3f11dd268a4d9f0b9cde6433aa7dcfe960 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Mon, 13 Jan 2025 13:55:47 +0200 Subject: [PATCH 42/61] Add ability to send hide-menu event via ipc to renderer --- .../menu-ipc-channel-handlers.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js b/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js index bae638b8..f7bf4c7d 100644 --- a/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js +++ b/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js @@ -4,6 +4,7 @@ const { BaseWindow, webContents, Menu } = require('electron') const IpcChannelHandlers = require('./ipc.channel.handlers') +const wins = require('../windows') const isMac = process.platform === 'darwin' class MenuIpcChannelHandlers extends IpcChannelHandlers { @@ -77,9 +78,16 @@ class MenuIpcChannelHandlers extends IpcChannelHandlers { async getMenuTemplateHandler (event, args) { const menu = Menu.getApplicationMenu() - const serializedMenu = this.#serializeMenu(menu) - - return serializedMenu + const menuTemplate = this.#serializeMenu(menu) + const shouldMenuBeHidden = ( + isMac && + wins.mainWindow?.isFullScreen() + ) + + return { + menuTemplate, + shouldMenuBeHidden + } } async execMenuCmdHandler (event, args) { @@ -95,6 +103,10 @@ class MenuIpcChannelHandlers extends IpcChannelHandlers { return menuItem.click({}, focusedWindow, focusedWebContents) } + + static sendHideMenuEvent (win, args) { + return this.sendToRenderer(this.sendHideMenuEvent, win, args) + } } module.exports = MenuIpcChannelHandlers From 625e7c1f7792ba8a493a5847104acb6698c565e9 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Mon, 13 Jan 2025 14:00:07 +0200 Subject: [PATCH 43/61] Register onHideMenuEvent method in preload script --- src/window-creators/main-renderer-ipc-bridge/preload.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/window-creators/main-renderer-ipc-bridge/preload.js b/src/window-creators/main-renderer-ipc-bridge/preload.js index d4d4d3b3..c64eacc1 100644 --- a/src/window-creators/main-renderer-ipc-bridge/preload.js +++ b/src/window-creators/main-renderer-ipc-bridge/preload.js @@ -27,6 +27,9 @@ const MENU_INVOKE_METHOD_NAMES = { GET_MENU_TEMPLATE: 'getMenuTemplate', EXEC_MENU_CMD: 'execMenuCmd' } +const MENU_EVENT_METHOD_NAMES = { + ON_HIDE_MENU_EVENT: 'onHideMenuEvent' +} const INVOKE_CHANNEL_MAP = new Map([ [CHANNEL_NAMES.GENERAL, GENERAL_INVOKE_METHOD_NAMES], @@ -34,7 +37,8 @@ const INVOKE_CHANNEL_MAP = new Map([ [CHANNEL_NAMES.MENU, MENU_INVOKE_METHOD_NAMES] ]) const EVENT_CHANNEL_MAP = new Map([ - [CHANNEL_NAMES.GENERAL, GENERAL_EVENT_METHOD_NAMES] + [CHANNEL_NAMES.GENERAL, GENERAL_EVENT_METHOD_NAMES], + [CHANNEL_NAMES.MENU, MENU_EVENT_METHOD_NAMES] ]) const getEventName = (channel, method) => { From e9a0692b76d1d884e4f5e02f02de94bfaa719079 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Mon, 13 Jan 2025 14:02:23 +0200 Subject: [PATCH 44/61] Send hide menu event if main win full-screen entered-left --- src/window-creators/index.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/window-creators/index.js b/src/window-creators/index.js index 1a9f0ad5..5c5235c7 100644 --- a/src/window-creators/index.js +++ b/src/window-creators/index.js @@ -28,6 +28,9 @@ const { parseEnvValToBool, waitPort } = require('../helpers') +const MenuIpcChannelHandlers = require( + './main-renderer-ipc-bridge/menu-ipc-channel-handlers' +) const shouldLocalhostBeUsedForLoadingUIInDevMode = parseEnvValToBool( process.env.SHOULD_LOCALHOST_BE_USED_FOR_LOADING_UI_IN_DEV_MODE @@ -271,6 +274,17 @@ const createMainWindow = async ({ wins.loadingWindow = null }) + if (isMac) { + win.on('enter-full-screen', () => { + MenuIpcChannelHandlers + .sendHideMenuEvent(win, { state: true }) + }) + win.on('leave-full-screen', () => { + MenuIpcChannelHandlers + .sendHideMenuEvent(win, { state: false }) + }) + } + if (isDevEnv) { wins.mainWindow.webContents.openDevTools({ mode: 'right' }) } From 5ec821122e083931a8dc8f4867772497f342807f Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Tue, 14 Jan 2025 11:44:32 +0200 Subject: [PATCH 45/61] Bump electron up to 33.3.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1a54e33b..4400d80d 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "concurrently": "9.0.1", "cross-env": "7.0.3", "dotenv": "16.3.1", - "electron": "33.3.0", + "electron": "33.3.1", "electron-builder": "24.13.3", "mocha": "10.2.0", "standard": "17.1.0", From 125c8b880c019d48a14178c3877175af1f13a6e0 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Tue, 14 Jan 2025 11:47:23 +0200 Subject: [PATCH 46/61] Fix main win full screen processing --- src/window-creators/index.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/window-creators/index.js b/src/window-creators/index.js index 5c5235c7..80b22c2a 100644 --- a/src/window-creators/index.js +++ b/src/window-creators/index.js @@ -36,8 +36,9 @@ const shouldLocalhostBeUsedForLoadingUIInDevMode = parseEnvValToBool( process.env.SHOULD_LOCALHOST_BE_USED_FOR_LOADING_UI_IN_DEV_MODE ) const uiPort = process.env.UI_PORT ?? 3000 -// TODO: Set false by default after UI implementation of the menu bar -const showNativeTitleBar = process.env.SHOW_NATIVE_TITLE_BAR ?? true +const showNativeTitleBar = parseEnvValToBool( + process.env.SHOW_NATIVE_TITLE_BAR +) const publicDir = path.join(__dirname, '../../bfx-report-ui/build') const loadURL = serve({ directory: publicDir }) @@ -109,6 +110,7 @@ const _createWindow = async ( x, y, isMaximized, + isFullScreen, manage } = isMainWindow ? windowStateKeeper({ @@ -164,6 +166,7 @@ const _createWindow = async ( const res = { isMaximized, + isFullScreen, isMainWindow, manage, win: wins[winName] @@ -259,7 +262,8 @@ const createMainWindow = async ({ const { win, manage, - isMaximized + isMaximized, + isFullScreen } = winProps win.on('closed', () => { @@ -274,7 +278,10 @@ const createMainWindow = async ({ wins.loadingWindow = null }) - if (isMac) { + if ( + !showNativeTitleBar && + isMac + ) { win.on('enter-full-screen', () => { MenuIpcChannelHandlers .sendHideMenuEvent(win, { state: true }) @@ -297,6 +304,7 @@ const createMainWindow = async ({ createMenu({ pathToUserData, pathToUserDocuments }) appStates.isMainWinMaximized = isMaximized + appStates.isMainWinFullScreen = isFullScreen manage(win) From 0b046faa619aaa29ce2edee44cfefff96a034076 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Tue, 14 Jan 2025 11:48:36 +0200 Subject: [PATCH 47/61] Expose main win full screen state --- src/app-states.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app-states.js b/src/app-states.js index b3cac96f..2738ab13 100644 --- a/src/app-states.js +++ b/src/app-states.js @@ -2,5 +2,6 @@ module.exports = { isMainWinMaximized: false, + isMainWinFullScreen: false, loadURL: null } From 2b8c1329b26483577e76031e71bdbb69f6994c88 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Tue, 14 Jan 2025 11:50:07 +0200 Subject: [PATCH 48/61] Set main win full screen after init finished --- src/window-creators/change-loading-win-visibility-state.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/window-creators/change-loading-win-visibility-state.js b/src/window-creators/change-loading-win-visibility-state.js index 3962dd31..ec1a223a 100644 --- a/src/window-creators/change-loading-win-visibility-state.js +++ b/src/window-creators/change-loading-win-visibility-state.js @@ -252,11 +252,12 @@ const hideLoadingWindow = async (opts) => { { shouldWinBeFocused: true } ) - // Legacy fix related to reprodducing the same behavior on all OS, - // waiting for checks that it was resolved in the last electron ver if (appStates.isMainWinMaximized) { wins.mainWindow.maximize() } + if (appStates.isMainWinFullScreen) { + wins.mainWindow.setFullScreen(true) + } } return hideWindow( From 0066efc6bd7a789e29e81954653b6d7c3e40582d Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Tue, 14 Jan 2025 11:51:21 +0200 Subject: [PATCH 49/61] Drop wrong full screen eneting in window-state-keeper --- src/window-creators/window-state-keeper.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/window-creators/window-state-keeper.js b/src/window-creators/window-state-keeper.js index 54c3e135..22854784 100644 --- a/src/window-creators/window-state-keeper.js +++ b/src/window-creators/window-state-keeper.js @@ -12,7 +12,6 @@ module.exports = (options) => { const eventHandlingDelay = 100 const config = { maximize: true, - fullScreen: true, ...options } @@ -132,10 +131,6 @@ module.exports = (options) => { } const manage = (win) => { - if (config.fullScreen && state.isFullScreen) { - win.setFullScreen(true) - } - win.on('resize', stateChangeHandler) win.on('move', stateChangeHandler) win.on('close', closeHandler) From ded50357d11c039d289476f2ba00a03331fb3891 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Tue, 14 Jan 2025 11:53:13 +0200 Subject: [PATCH 50/61] Add ability to hide ui menu bar using electron env var --- .../menu-ipc-channel-handlers.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js b/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js index f7bf4c7d..17a817e5 100644 --- a/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js +++ b/src/window-creators/main-renderer-ipc-bridge/menu-ipc-channel-handlers.js @@ -3,9 +3,15 @@ const { BaseWindow, webContents, Menu } = require('electron') const IpcChannelHandlers = require('./ipc.channel.handlers') +const parseEnvValToBool = require( + '../../helpers/parse-env-val-to-bool' +) const wins = require('../windows') const isMac = process.platform === 'darwin' +const showNativeTitleBar = parseEnvValToBool( + process.env.SHOW_NATIVE_TITLE_BAR +) class MenuIpcChannelHandlers extends IpcChannelHandlers { static channelName = 'menu' @@ -80,8 +86,11 @@ class MenuIpcChannelHandlers extends IpcChannelHandlers { const menu = Menu.getApplicationMenu() const menuTemplate = this.#serializeMenu(menu) const shouldMenuBeHidden = ( - isMac && - wins.mainWindow?.isFullScreen() + showNativeTitleBar || + ( + isMac && + wins.mainWindow?.isFullScreen() + ) ) return { From 40c022fa806f5e7c8050f618adffe76af7f8d7e1 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Tue, 14 Jan 2025 11:54:25 +0200 Subject: [PATCH 51/61] Add electron env var to show native menu bar --- electronEnv.json.example | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/electronEnv.json.example b/electronEnv.json.example index ef13f6be..b5b75fee 100644 --- a/electronEnv.json.example +++ b/electronEnv.json.example @@ -1,5 +1,6 @@ { "NODE_ENV": "production", "IS_AUTO_UPDATE_DISABLED": false, - "REPO_OWNER": "bitfinexcom" + "REPO_OWNER": "bitfinexcom", + "SHOW_NATIVE_TITLE_BAR": true } From 98f05fe4836f00e632d1f6bd8a6a68fc01de5a96 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Thu, 16 Jan 2025 12:06:00 +0200 Subject: [PATCH 52/61] Add layout for minimization button for loading window --- src/window-creators/layouts/app-init.html | 42 +++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/window-creators/layouts/app-init.html b/src/window-creators/layouts/app-init.html index 82f5afe4..6d4a6b38 100644 --- a/src/window-creators/layouts/app-init.html +++ b/src/window-creators/layouts/app-init.html @@ -22,6 +22,44 @@ font-family: "Roboto", sans-serif; } + .win-control-btn { + position: absolute; + top: 0; + right: 0; + display: block; + min-height: 30px; + margin: 0; + padding: 5px; + } + + .minimize-btn { + position: relative; + display: block; + width: 30px; + height: 30px; + border-radius: 50%; + background-color: #172d3e; + transition: background-color .3s; + cursor: pointer; + } + + .minimize-btn::after { + content: ""; + display: block; + position: absolute; + width: 12px; + height: 1px; + background: #9b9a9a; + bottom: 9px; + left: calc((30px - 12px) / 2); + } + + .minimize-btn:hover, + .minimize-btn:active, + .minimize-btn:focus { + background-color: #1c3649; + } + .lds-roller { display: inline-block; position: absolute; @@ -190,6 +228,9 @@ +
+
+
@@ -210,6 +251,7 @@ window.addEventListener('load', () => { const rollers = document.getElementsByClassName('lds-roller') const descriptionElem = document.getElementById('description') + const minBtnElem = document.getElementById('minBtn') setTimeout(() => { for (const roller of rollers) { From e3db1040207b0b5186298fc5aae3c749f868a43d Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Thu, 16 Jan 2025 12:08:01 +0200 Subject: [PATCH 53/61] Add window modification properties for loading window --- src/window-creators/index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/window-creators/index.js b/src/window-creators/index.js index 80b22c2a..2d077841 100644 --- a/src/window-creators/index.js +++ b/src/window-creators/index.js @@ -327,7 +327,10 @@ const createLoadingWindow = async () => { 'loadingWindow', { width: 350, - height: 350 + height: 350, + maximizable: false, + closable: false, + fullscreenable: false } ) From 88d8279688dc0572e0f3ca96af8fdc97d4c8b979 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Thu, 16 Jan 2025 12:17:50 +0200 Subject: [PATCH 54/61] Add handler for loading window minimization --- .../main-renderer-ipc-bridge/general-ipc-channel-handlers.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/window-creators/main-renderer-ipc-bridge/general-ipc-channel-handlers.js b/src/window-creators/main-renderer-ipc-bridge/general-ipc-channel-handlers.js index 8b82107a..9ee5b7e3 100644 --- a/src/window-creators/main-renderer-ipc-bridge/general-ipc-channel-handlers.js +++ b/src/window-creators/main-renderer-ipc-bridge/general-ipc-channel-handlers.js @@ -10,6 +10,10 @@ class GeneralIpcChannelHandlers extends IpcChannelHandlers { return app.exit(args?.code ?? 0) } + async minimizeLoadingWinHandler (event, args) { + return wins.loadingWindow?.minimize() + } + async getTitleHandler (event, args) { return wins.mainWindow.getTitle() } From b4ed14740c98d3c5ab524215ebcf45bc18cf78b0 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Thu, 16 Jan 2025 12:18:29 +0200 Subject: [PATCH 55/61] Register loading window minimization handler in preload script --- src/window-creators/main-renderer-ipc-bridge/preload.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/window-creators/main-renderer-ipc-bridge/preload.js b/src/window-creators/main-renderer-ipc-bridge/preload.js index c64eacc1..533218b9 100644 --- a/src/window-creators/main-renderer-ipc-bridge/preload.js +++ b/src/window-creators/main-renderer-ipc-bridge/preload.js @@ -11,6 +11,7 @@ const CHANNEL_NAMES = { const GENERAL_INVOKE_METHOD_NAMES = { EXIT: 'exit', + MINIMIZE_LOADING_WIN: 'minimizeLoadingWin', GET_TITLE: 'getTitle' } const GENERAL_EVENT_METHOD_NAMES = { From 524b0d98923cf2814558c2b583a3759559bad3e1 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Thu, 16 Jan 2025 12:25:31 +0200 Subject: [PATCH 56/61] Add listener for loading window minimization event --- src/window-creators/layouts/app-init.html | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/window-creators/layouts/app-init.html b/src/window-creators/layouts/app-init.html index 6d4a6b38..a35acecf 100644 --- a/src/window-creators/layouts/app-init.html +++ b/src/window-creators/layouts/app-init.html @@ -253,6 +253,14 @@ const descriptionElem = document.getElementById('description') const minBtnElem = document.getElementById('minBtn') + minBtnElem.onclick = async () => { + try { + await window.bfxReportElectronApi?.minimizeLoadingWin() + } catch (err) { + console.error(err) + } + } + setTimeout(() => { for (const roller of rollers) { roller.classList.add("show-roller") From ae8fbd606d773ecb1efaca29cc2df90455f8306a Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Fri, 17 Jan 2025 13:11:38 +0200 Subject: [PATCH 57/61] Fix approach for loading window minimization on mac --- src/window-creators/layouts/app-init.html | 2 +- .../general-ipc-channel-handlers.js | 15 +++++++++++++-- .../main-renderer-ipc-bridge/preload.js | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/window-creators/layouts/app-init.html b/src/window-creators/layouts/app-init.html index a35acecf..29ded962 100644 --- a/src/window-creators/layouts/app-init.html +++ b/src/window-creators/layouts/app-init.html @@ -255,7 +255,7 @@ minBtnElem.onclick = async () => { try { - await window.bfxReportElectronApi?.minimizeLoadingWin() + await window.bfxReportElectronApi?.hideLoadingWindow() } catch (err) { console.error(err) } diff --git a/src/window-creators/main-renderer-ipc-bridge/general-ipc-channel-handlers.js b/src/window-creators/main-renderer-ipc-bridge/general-ipc-channel-handlers.js index 9ee5b7e3..7fbb45a2 100644 --- a/src/window-creators/main-renderer-ipc-bridge/general-ipc-channel-handlers.js +++ b/src/window-creators/main-renderer-ipc-bridge/general-ipc-channel-handlers.js @@ -6,12 +6,23 @@ const wins = require('../windows') const IpcChannelHandlers = require('./ipc.channel.handlers') class GeneralIpcChannelHandlers extends IpcChannelHandlers { + #hideLoadingWindow = null + + constructor (...args) { + super(...args) + + // Resolve circular dependency issue + this.#hideLoadingWindow = require( + '../change-loading-win-visibility-state' + ).hideLoadingWindow + } + async exitHandler (event, args) { return app.exit(args?.code ?? 0) } - async minimizeLoadingWinHandler (event, args) { - return wins.loadingWindow?.minimize() + async hideLoadingWindowHandler (event, args) { + await this.#hideLoadingWindow() } async getTitleHandler (event, args) { diff --git a/src/window-creators/main-renderer-ipc-bridge/preload.js b/src/window-creators/main-renderer-ipc-bridge/preload.js index 533218b9..24a9ee1f 100644 --- a/src/window-creators/main-renderer-ipc-bridge/preload.js +++ b/src/window-creators/main-renderer-ipc-bridge/preload.js @@ -11,7 +11,7 @@ const CHANNEL_NAMES = { const GENERAL_INVOKE_METHOD_NAMES = { EXIT: 'exit', - MINIMIZE_LOADING_WIN: 'minimizeLoadingWin', + HIDE_LOADING_WINDOW: 'hideLoadingWindow', GET_TITLE: 'getTitle' } const GENERAL_EVENT_METHOD_NAMES = { From 5be96fdd801ed08c6a9cc66b78e46ba774662448 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Fri, 17 Jan 2025 13:39:30 +0200 Subject: [PATCH 58/61] Fix loading window close behavior on mac --- src/window-creators/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/window-creators/index.js b/src/window-creators/index.js index 2d077841..d87f000e 100644 --- a/src/window-creators/index.js +++ b/src/window-creators/index.js @@ -329,7 +329,6 @@ const createLoadingWindow = async () => { width: 350, height: 350, maximizable: false, - closable: false, fullscreenable: false } ) From 3b8f2ea8422f2151219cc43f77eee3ab470bf7cf Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Tue, 21 Jan 2025 12:47:53 +0200 Subject: [PATCH 59/61] Bump version up to v4.32.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4400d80d..23c69f6f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bfx-report-electron", - "version": "4.31.0", + "version": "4.32.0", "repository": "https://github.com/bitfinexcom/bfx-report-electron", "description": "Reporting tool", "author": "bitfinex.com", From aa9d07427c38f82dc706d7974bb006311a4ad7cc Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Tue, 21 Jan 2025 13:14:36 +0200 Subject: [PATCH 60/61] Add changelog for v4.32.0 --- CHANGELOG.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e7cdccd..5e8c7c50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [4.32.0] - 2025-01-22 + +### Added + +- Added the backend logic to move the electron app menu bar to the UI title instead of the electron one so that we can customize the electron menu, as the native electron menu API doesn't provide that. It allows us to build the menu in the UI in one small line with the main app title and typical window buttons (minimize, maximize, and close in the top corner). This is very useful as it saves overall space and at the same time constantly displays the menu and does not require the user to press the `Alt` key to display it (as practice has shown, because of the last one, many inexperienced users do not even know about the existence of menu functions). PRs: [bfx-report-electron#478](https://github.com/bitfinexcom/bfx-report-electron/pull/478), [bfx-facs-db-better-sqlite#11](https://github.com/bitfinexcom/bfx-facs-db-better-sqlite/pull/11) +- Added a small typical `_` button (in the top right corner) to minimize the loading window. PR: [bfx-report-electron#479](https://github.com/bitfinexcom/bfx-report-electron/pull/479) +- Added the logout flow for web users and prevented the issue when logged-out users are still logged in after the page refreshing. PR: [bfx-report-ui#889](https://github.com/bitfinexcom/bfx-report-ui/pull/889) + +### Changed + +- Renamed `Filter` button to `Generate` and also disabled it during the initial synchronization to prevent `Tax Report` generation errors. Implemented corresponding notice for the users during the initial sync. PR: [bfx-report-ui#888](https://github.com/bitfinexcom/bfx-report-ui/pull/888) +- Actualized app download link generation flow. PR: [bfx-report-ui#890](https://github.com/bitfinexcom/bfx-report-ui/pull/890) +- Actualized `Reports` translations and extended coverage for newly added elements/features. PR: [bfx-report-ui#891](https://github.com/bitfinexcom/bfx-report-ui/pull/891) +- Improved theme setting flow and fixed issues noted after the latest `Electron` version update. PR: [bfx-report-ui#893](https://github.com/bitfinexcom/bfx-report-ui/pull/893) + +### Fixed + +- Fixed `isAuthTokenGenerationError` flag processing in query response for the 2FA re-login after token expiration. PR: [bfx-report-ui#892](https://github.com/bitfinexcom/bfx-report-ui/pull/892) + ## [4.31.0] - 2024-12-04 ### Added From 833aeb48de9d803dfcb15a2cdd7935577b100165 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Thu, 23 Jan 2025 06:39:47 +0200 Subject: [PATCH 61/61] Update sub-modules --- bfx-report-ui | 2 +- bfx-reports-framework | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bfx-report-ui b/bfx-report-ui index bb304084..f7ce617d 160000 --- a/bfx-report-ui +++ b/bfx-report-ui @@ -1 +1 @@ -Subproject commit bb304084e04f316d74ef6c40618feefcf6c12d09 +Subproject commit f7ce617d3f8af6cbd2f8f0f8397b68d4605bc350 diff --git a/bfx-reports-framework b/bfx-reports-framework index 43421486..56cbe765 160000 --- a/bfx-reports-framework +++ b/bfx-reports-framework @@ -1 +1 @@ -Subproject commit 4342148668bdffd30e790fc338ac736d32aa9fbc +Subproject commit 56cbe765e373d4402c1020e9c0d435245d5c8cfa