Skip to content

Commit 21f0d35

Browse files
committed
Refactor menu to build dynamically & omit autohide on Mac
This allows us to move all logic for autohiding into the menu itself, makes it easier to add similar features in future, and avoids showing this button on Mac where it doesn't make sense (due to fixed OS menu bar).
1 parent 5ec13d2 commit 21f0d35

File tree

2 files changed

+119
-110
lines changed

2 files changed

+119
-110
lines changed

src/index.ts

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,16 @@ import * as semver from 'semver';
4646
import * as rimraf from 'rimraf';
4747
import * as windowStateKeeper from 'electron-window-state';
4848
import { getSystemProxy } from 'os-proxy-config';
49-
import * as ElectronStore from 'electron-store'
5049

5150
import registerContextMenu = require('electron-context-menu');
5251
registerContextMenu({
5352
showSaveImageAs: true
5453
});
5554

5655
import { reportStartupEvents } from './report-install-event';
57-
import { menu } from './menu';
56+
import { getMenu, shouldAutoHideMenu } from './menu';
5857
import { getDeferred, delay } from './util';
5958

60-
const store = new ElectronStore();
6159
const rmRF = promisify(rimraf);
6260

6361
const packageJson = require('../package.json');
@@ -115,7 +113,7 @@ const createWindow = () => {
115113
show: false
116114
});
117115

118-
if (store.get("autoHideMenuBar")) {
116+
if (shouldAutoHideMenu()) {
119117
window.setAutoHideMenuBar(true);
120118
window.setMenuBarVisibility(false);
121119
}
@@ -547,7 +545,7 @@ if (!amMainInstance) {
547545
});
548546

549547
Promise.all([appReady.promise, portCheck]).then(() => {
550-
Menu.setApplicationMenu(menu);
548+
Menu.setApplicationMenu(getMenu(windows));
551549
createWindow();
552550
});
553551

@@ -574,12 +572,4 @@ if (!amMainInstance) {
574572
app.quit();
575573
}
576574
});
577-
}
578-
579-
export function autoHideMenuBar(status: boolean){
580-
windows.forEach((window) => {
581-
window.setAutoHideMenuBar(status);
582-
window.setMenuBarVisibility(!status);
583-
});
584-
store.set({ autoHideMenuBar: status });
585575
}

src/menu.ts

Lines changed: 116 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,109 +1,128 @@
11
import { app, Menu, MenuItemConstructorOptions } from 'electron';
2-
import { autoHideMenuBar } from "./index"
2+
import * as ElectronStore from 'electron-store';
33

4-
const menuTemplate: MenuItemConstructorOptions[] = [
5-
{
6-
label: '&Edit',
7-
submenu: [
8-
{ role: 'undo' },
9-
{ role: 'redo' },
10-
{ type: 'separator' },
11-
{ role: 'cut', registerAccelerator: false },
12-
{ role: 'copy', registerAccelerator: false },
13-
{ role: 'paste', registerAccelerator: false },
14-
{ role: 'pasteAndMatchStyle', registerAccelerator: false },
15-
{ role: 'delete' },
16-
{ role: 'selectAll' }
17-
]
18-
},
19-
{
20-
label: '&View',
21-
submenu: [
22-
{ role: 'resetZoom' },
23-
{ role: 'zoomIn' },
24-
{ role: 'zoomOut' },
25-
{ type: 'separator' },
26-
{ role: 'togglefullscreen' },
27-
{ type: 'separator' },
28-
{ role: 'reload' },
29-
{ role: 'forceReload' },
30-
{ role: 'toggleDevTools' },
31-
{ type: 'checkbox', 'label': 'Toggle Menu Bar', click(event) {
32-
autoHideMenuBar(event.checked || false)
33-
}}
34-
]
35-
},
36-
{
37-
label: '&Window',
38-
role: 'window',
39-
submenu: [
40-
{ role: 'minimize' },
41-
{ role: 'close' }
42-
]
43-
},
44-
{
45-
label: '&Help',
46-
role: 'help',
47-
submenu: [
48-
{
49-
label: 'Learn More',
50-
click () { require('electron').shell.openExternal('https://httptoolkit.tech') }
51-
}
52-
]
53-
}
54-
];
4+
const store = new ElectronStore();
5+
const AUTO_HIDE_SETTING_KEY = "autoHideMenuBar";
556

56-
if (process.platform === 'darwin') {
57-
const macMenu: MenuItemConstructorOptions = {
58-
label: app.getName(),
59-
submenu: [
60-
{ role: 'about' },
61-
{ type: 'separator' },
62-
{ role: 'services' },
63-
{ type: 'separator' },
64-
{ role: 'hide' },
65-
{ role: 'hideOthers' },
66-
{ role: 'unhide' },
67-
{ type: 'separator' },
68-
{ role: 'quit' }
69-
]
70-
};
71-
menuTemplate.unshift(macMenu);
7+
export const shouldAutoHideMenu = () => !!store.get(AUTO_HIDE_SETTING_KEY);
728

73-
// Add to Edit menu
74-
(menuTemplate[1].submenu as MenuItemConstructorOptions[]).push(
75-
{ type: 'separator' },
9+
export const getMenu = (browserWindows: Electron.BrowserWindow[]) => {
10+
const menuTemplate: MenuItemConstructorOptions[] = [
11+
{
12+
label: '&Edit',
13+
submenu: [
14+
{ role: 'undo' },
15+
{ role: 'redo' },
16+
{ type: 'separator' },
17+
{ role: 'cut', registerAccelerator: false },
18+
{ role: 'copy', registerAccelerator: false },
19+
{ role: 'paste', registerAccelerator: false },
20+
{ role: 'pasteAndMatchStyle', registerAccelerator: false },
21+
{ role: 'delete' },
22+
{ role: 'selectAll' }
23+
]
24+
},
7625
{
77-
label: 'Speech',
26+
label: '&View',
7827
submenu: [
79-
{ role: 'startSpeaking' },
80-
{ role: 'stopSpeaking' }
28+
{ role: 'resetZoom' },
29+
{ role: 'zoomIn' },
30+
{ role: 'zoomOut' },
31+
{ type: 'separator' },
32+
{ role: 'togglefullscreen' },
33+
{ type: 'separator' },
34+
{ role: 'reload' },
35+
{ role: 'forceReload' },
36+
{ role: 'toggleDevTools' }
37+
]
38+
},
39+
{
40+
label: '&Window',
41+
role: 'window',
42+
submenu: [
43+
{ role: 'minimize' },
44+
{ role: 'close' }
45+
]
46+
},
47+
{
48+
label: '&Help',
49+
role: 'help',
50+
submenu: [
51+
{
52+
label: 'Learn More',
53+
click () { require('electron').shell.openExternal('https://httptoolkit.tech') }
54+
}
8155
]
8256
}
83-
);
84-
85-
// Window menu
86-
menuTemplate[3].submenu = [
87-
{ role: 'close' },
88-
{ role: 'minimize' },
89-
{ role: 'zoom' },
90-
{ type: 'separator' },
91-
{ role: 'front' }
9257
];
93-
} else {
94-
menuTemplate.unshift({
95-
label: '&File',
96-
submenu: [
58+
59+
if (process.platform === 'darwin') {
60+
const macMenu: MenuItemConstructorOptions = {
61+
label: app.getName(),
62+
submenu: [
63+
{ role: 'about' },
64+
{ type: 'separator' },
65+
{ role: 'services' },
66+
{ type: 'separator' },
67+
{ role: 'hide' },
68+
{ role: 'hideOthers' },
69+
{ role: 'unhide' },
70+
{ type: 'separator' },
71+
{ role: 'quit' }
72+
]
73+
};
74+
menuTemplate.unshift(macMenu);
75+
76+
// Add to Edit menu
77+
(menuTemplate[1].submenu as MenuItemConstructorOptions[]).push(
78+
{ type: 'separator' },
9779
{
98-
// This should close the Window, but look like Quit. End behaviour is that every
99-
// Window _acts_ like a separate process, but is really a separate window.
100-
// (This lets us easily share a single server instance)
101-
role: 'close',
102-
label: 'Quit',
103-
accelerator: 'CommandOrControl+Q'
80+
label: 'Speech',
81+
submenu: [
82+
{ role: 'startSpeaking' },
83+
{ role: 'stopSpeaking' }
84+
]
10485
}
105-
]
106-
});
107-
}
86+
);
87+
88+
// Window menu
89+
menuTemplate[3].submenu = [
90+
{ role: 'close' },
91+
{ role: 'minimize' },
92+
{ role: 'zoom' },
93+
{ type: 'separator' },
94+
{ role: 'front' }
95+
];
96+
} else {
97+
menuTemplate.unshift({
98+
label: '&File',
99+
submenu: [
100+
{
101+
// This should close the Window, but look like Quit. End behaviour is that every
102+
// Window _acts_ like a separate process, but is really a separate window.
103+
// (This lets us easily share a single server instance)
104+
role: 'close',
105+
label: 'Quit',
106+
accelerator: 'CommandOrControl+Q'
107+
}
108+
]
109+
});
110+
111+
// On Windows & Linux, it's possible to autohide the menu bar:
112+
(menuTemplate[2].submenu as MenuItemConstructorOptions[]).push({
113+
type: 'checkbox',
114+
label: 'Autohide Menu Bar',
115+
checked: shouldAutoHideMenu(),
116+
click: (event) => {
117+
const shouldAutoHide = event.checked || false;
118+
browserWindows.forEach((window) => {
119+
window.setAutoHideMenuBar(shouldAutoHide);
120+
window.setMenuBarVisibility(!shouldAutoHide);
121+
});
122+
store.set({ [AUTO_HIDE_SETTING_KEY]: shouldAutoHide });
123+
}
124+
})
125+
}
108126

109-
export const menu = Menu.buildFromTemplate(menuTemplate);
127+
return Menu.buildFromTemplate(menuTemplate);
128+
}

0 commit comments

Comments
 (0)