Skip to content

Commit 72d1802

Browse files
authored
fix(menu): remove accelerators for linux COMPASS-8494 (#6485)
* remove accelerators for linux menu * fix tests * add todo ticket * add test * filter more accelerators for linux * compass menu accelerator assertions * skip tests on linux * use actual menu for tests
1 parent 2c3f6d0 commit 72d1802

File tree

2 files changed

+147
-19
lines changed

2 files changed

+147
-19
lines changed

packages/compass/src/main/menu.spec.ts

Lines changed: 102 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { MenuItemConstructorOptions } from 'electron';
33
import { BrowserWindow, ipcMain, Menu, app, dialog } from 'electron';
44
import { expect } from 'chai';
55
import sinon from 'sinon';
6+
import os from 'os';
67
import { createSandboxFromDefaultPreferences } from 'compass-preferences-model';
78

89
import type { CompassApplication } from './application';
@@ -457,7 +458,8 @@ describe('CompassMenu', function () {
457458
]);
458459
});
459460

460-
['linux', 'win32'].forEach((platform) => {
461+
// TODO(COMPASS-8505): Add `linux` back to this list
462+
['win32'].forEach((platform) => {
461463
// TODO(COMPASS-7906): remove
462464
it.skip(`[single-connection] should generate a menu template for ${platform}`, function () {
463465
sinon.stub(process, 'platform').value(platform);
@@ -588,6 +590,87 @@ describe('CompassMenu', function () {
588590
});
589591
});
590592

593+
// TODO(COMPASS-8505): Remove this test
594+
it('should generate a menu template for linux', async function () {
595+
await App.preferences.savePreferences({
596+
enableMultipleConnectionSystem: true,
597+
});
598+
sinon.stub(process, 'platform').value('linux');
599+
600+
expect(serializable(CompassMenu.getTemplate(0))).to.deep.equal([
601+
{
602+
label: '&Connections',
603+
submenu: [
604+
{ label: '&Import Saved Connections' },
605+
{ label: '&Export Saved Connections' },
606+
{ type: 'separator' },
607+
{ label: 'E&xit' },
608+
],
609+
},
610+
{
611+
label: 'Edit',
612+
submenu: [
613+
{ label: 'Undo', role: 'undo' },
614+
{ label: 'Redo', role: 'redo' },
615+
{ type: 'separator' },
616+
{ label: 'Cut', role: 'cut' },
617+
{ label: 'Copy', role: 'copy' },
618+
{ label: 'Paste', role: 'paste' },
619+
{
620+
label: 'Select All',
621+
role: 'selectAll',
622+
},
623+
{ type: 'separator' },
624+
{ label: 'Find' },
625+
{ type: 'separator' },
626+
{ label: '&Settings' },
627+
],
628+
},
629+
{
630+
label: '&View',
631+
submenu: [
632+
{ label: '&Reload' },
633+
{ label: '&Reload Data' },
634+
{ type: 'separator' },
635+
{ label: 'Actual Size' },
636+
{ label: 'Zoom In' },
637+
{ label: 'Zoom Out' },
638+
],
639+
},
640+
{
641+
label: '&Help',
642+
submenu: [
643+
{ label: `&Online ${app.getName()} Help` },
644+
{ label: '&License' },
645+
{ label: `&View Source Code on GitHub` },
646+
{ label: `&Suggest a Feature` },
647+
{ label: `&Report a Bug` },
648+
{ label: '&Open Log File' },
649+
{ type: 'separator' },
650+
{ label: `&About ${app.getName()}` },
651+
{ label: 'Check for updates…' },
652+
],
653+
},
654+
]);
655+
});
656+
657+
it('does not crash when rendering menu item with an accelerator', () => {
658+
const window = new BrowserWindow({ show: false });
659+
const template = CompassMenu.getTemplate(window.id);
660+
661+
// As the root menu items do not have accelerators, we test
662+
// against each item's submenu.
663+
for (const item of template) {
664+
// for TS. compass menu has submenus
665+
if (!Array.isArray(item.submenu)) {
666+
continue;
667+
}
668+
const menu = Menu.buildFromTemplate(item.submenu);
669+
menu.popup({ window });
670+
menu.closePopup();
671+
}
672+
});
673+
591674
it('should generate a menu template without collection submenu if `showCollection` is `false`', function () {
592675
expect(
593676
CompassMenu.getTemplate(0).find((item) => item.label === '&Collection')
@@ -612,7 +695,12 @@ describe('CompassMenu', function () {
612695
label: '&Collection',
613696
submenu: [
614697
{
615-
accelerator: 'Alt+CmdOrCtrl+S',
698+
// TODO(COMPASS-8505): Add `accelerator` back to this
699+
...(os.platform() === 'linux'
700+
? {}
701+
: {
702+
accelerator: 'Alt+CmdOrCtrl+S',
703+
}),
616704
label: '&Share Schema as JSON',
617705
},
618706
{
@@ -646,7 +734,12 @@ describe('CompassMenu', function () {
646734
label: '&Collection',
647735
submenu: [
648736
{
649-
accelerator: 'Alt+CmdOrCtrl+S',
737+
// TODO(COMPASS-8505): Add `accelerator` back to this
738+
...(os.platform() === 'linux'
739+
? {}
740+
: {
741+
accelerator: 'Alt+CmdOrCtrl+S',
742+
}),
650743
label: '&Share Schema as JSON',
651744
},
652745
{
@@ -670,7 +763,12 @@ describe('CompassMenu', function () {
670763
expect(
671764
menu.find((item: any) => item.label === '&Toggle DevTools')
672765
).to.deep.eq({
673-
accelerator: 'Alt+CmdOrCtrl+I',
766+
// TODO(COMPASS-8505): Add `accelerator` back to this
767+
...(os.platform() === 'linux'
768+
? {}
769+
: {
770+
accelerator: 'Alt+CmdOrCtrl+I',
771+
}),
674772
label: '&Toggle DevTools',
675773
});
676774
});

packages/compass/src/main/menu.ts

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
import type { MenuItemConstructorOptions } from 'electron';
2-
import { BrowserWindow, Menu, app, dialog, shell } from 'electron';
2+
import {
3+
BrowserWindow,
4+
Menu,
5+
app as electronApp,
6+
dialog,
7+
shell,
8+
} from 'electron';
39
import { ipcMain } from 'hadron-ipc';
410
import fs from 'fs';
11+
import os from 'os';
512
import path from 'path';
613
import createDebug from 'debug';
714
import type { THEMES } from 'compass-preferences-model';
@@ -34,11 +41,11 @@ function quitItem(
3441
accelerator: 'CmdOrCtrl+Q',
3542
click() {
3643
!compassApp.preferences.getPreferences().enableShowDialogOnQuit
37-
? app.quit()
44+
? electronApp.quit()
3845
: void dialog
3946
.showMessageBox({
4047
type: 'warning',
41-
title: `Quit ${app.getName()}`,
48+
title: `Quit ${electronApp.getName()}`,
4249
icon: COMPASS_ICON,
4350
message: 'Are you sure you want to quit?',
4451
buttons: ['Quit', 'Cancel'],
@@ -50,7 +57,7 @@ function quitItem(
5057
void compassApp.preferences.savePreferences({
5158
enableShowDialogOnQuit: false,
5259
});
53-
app.quit();
60+
electronApp.quit();
5461
}
5562
});
5663
},
@@ -96,10 +103,10 @@ function darwinCompassSubMenu(
96103
compassApp: typeof CompassApplication
97104
): MenuItemConstructorOptions {
98105
return {
99-
label: app.getName(),
106+
label: electronApp.getName(),
100107
submenu: [
101108
{
102-
label: `About ${app.getName()}`,
109+
label: `About ${electronApp.getName()}`,
103110
role: 'about',
104111
},
105112
updateSubmenu(windowState, compassApp),
@@ -239,14 +246,14 @@ function editSubMenu(): MenuItemConstructorOptions {
239246

240247
function nonDarwinAboutItem(): MenuItemConstructorOptions {
241248
return {
242-
label: `&About ${app.getName()}`,
249+
label: `&About ${electronApp.getName()}`,
243250
click() {
244251
void dialog.showMessageBox({
245252
type: 'info',
246-
title: 'About ' + app.getName(),
253+
title: 'About ' + electronApp.getName(),
247254
icon: COMPASS_ICON,
248-
message: app.getName(),
249-
detail: 'Version ' + app.getVersion(),
255+
message: electronApp.getName(),
256+
detail: 'Version ' + electronApp.getVersion(),
250257
buttons: ['OK'],
251258
});
252259
},
@@ -255,7 +262,7 @@ function nonDarwinAboutItem(): MenuItemConstructorOptions {
255262

256263
function helpWindowItem(): MenuItemConstructorOptions {
257264
return {
258-
label: `&Online ${app.getName()} Help`,
265+
label: `&Online ${electronApp.getName()} Help`,
259266
accelerator: 'F1',
260267
click() {
261268
void shell.openExternal(COMPASS_HELP);
@@ -299,7 +306,7 @@ function license(): MenuItemConstructorOptions {
299306
label: '&License',
300307
click() {
301308
void import('../../LICENSE').then(({ default: LICENSE }) => {
302-
const licenseTemp = path.join(app.getPath('temp'), 'License');
309+
const licenseTemp = path.join(electronApp.getPath('temp'), 'License');
303310
fs.writeFile(licenseTemp, LICENSE, (err) => {
304311
if (!err) {
305312
void shell.openPath(licenseTemp);
@@ -513,6 +520,24 @@ class WindowMenuState {
513520
updateManagerState: UpdateManagerState = 'idle';
514521
}
515522

523+
function removeAcceleratorFromMenu(
524+
menu?: MenuItemConstructorOptions[]
525+
): MenuItemConstructorOptions[] {
526+
if (!Array.isArray(menu)) {
527+
return [];
528+
}
529+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
530+
return menu.map(({ accelerator, ...item }) => {
531+
if (!item.submenu || !Array.isArray(item.submenu)) {
532+
return item;
533+
}
534+
return {
535+
...item,
536+
submenu: removeAcceleratorFromMenu(item.submenu),
537+
};
538+
});
539+
}
540+
516541
class CompassMenu {
517542
private constructor() {
518543
// marking constructor as private to disallow usage
@@ -618,9 +643,9 @@ class CompassMenu {
618643
}
619644

620645
private static async setupDockMenu() {
621-
await app.whenReady();
646+
await electronApp.whenReady();
622647
if (process.platform === 'darwin') {
623-
app.dock.setMenu(
648+
electronApp.dock.setMenu(
624649
Menu.buildFromTemplate([
625650
{
626651
label: 'New Window',
@@ -686,7 +711,12 @@ class CompassMenu {
686711
if (process.platform === 'darwin') {
687712
return darwinMenu(menuState, this.app);
688713
}
689-
return nonDarwinMenu(menuState, this.app);
714+
const menu = nonDarwinMenu(menuState, this.app);
715+
// TODO(COMPASS-8505): Remove this check once accelerator issue is resolve for linux.
716+
if (os.platform() === 'linux') {
717+
return removeAcceleratorFromMenu(menu);
718+
}
719+
return menu;
690720
}
691721

692722
private static refreshMenu = () => {

0 commit comments

Comments
 (0)