aboutsummaryrefslogtreecommitdiffstats
path: root/packages/main/src/infrastructure/electron/impl
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2022-03-29 18:19:39 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2022-05-16 00:54:56 +0200
commita35d560f8d1ca414e3ba387b50731ca099e2da47 (patch)
tree5a8a90345c04eb0b69ea3fca8185641e26905b5d /packages/main/src/infrastructure/electron/impl
parentfeat: New window banner (diff)
downloadsophie-a35d560f8d1ca414e3ba387b50731ca099e2da47.tar.gz
sophie-a35d560f8d1ca414e3ba387b50731ca099e2da47.tar.zst
sophie-a35d560f8d1ca414e3ba387b50731ca099e2da47.zip
feat: Add custom menubar
The menu is populated reactive from the store with no caching. This doesn't seem to cause any performance problems so far. Currently the menu is electron-specific. In the future, we'll need a more runtime-independent way to build the menu. Signed-off-by: Kristóf Marussy <kristof@marussy.com>
Diffstat (limited to 'packages/main/src/infrastructure/electron/impl')
-rw-r--r--packages/main/src/infrastructure/electron/impl/ElectronServiceView.ts4
-rw-r--r--packages/main/src/infrastructure/electron/impl/electronShell.ts5
-rw-r--r--packages/main/src/infrastructure/electron/impl/setApplicationMenu.ts165
3 files changed, 173 insertions, 1 deletions
diff --git a/packages/main/src/infrastructure/electron/impl/ElectronServiceView.ts b/packages/main/src/infrastructure/electron/impl/ElectronServiceView.ts
index 089e63a..5062da0 100644
--- a/packages/main/src/infrastructure/electron/impl/ElectronServiceView.ts
+++ b/packages/main/src/infrastructure/electron/impl/ElectronServiceView.ts
@@ -178,6 +178,10 @@ export default class ElectronServiceView implements ServiceView {
178 this.browserView.webContents.stop(); 178 this.browserView.webContents.stop();
179 } 179 }
180 180
181 toggleDeveloperTools(): void {
182 this.browserView.webContents.toggleDevTools();
183 }
184
181 setBounds(bounds: BrowserViewBounds): void { 185 setBounds(bounds: BrowserViewBounds): void {
182 this.browserView.setBounds(bounds); 186 this.browserView.setBounds(bounds);
183 } 187 }
diff --git a/packages/main/src/infrastructure/electron/impl/electronShell.ts b/packages/main/src/infrastructure/electron/impl/electronShell.ts
index 0e8c0c1..be1cbe3 100644
--- a/packages/main/src/infrastructure/electron/impl/electronShell.ts
+++ b/packages/main/src/infrastructure/electron/impl/electronShell.ts
@@ -18,7 +18,7 @@
18 * SPDX-License-Identifier: AGPL-3.0-only 18 * SPDX-License-Identifier: AGPL-3.0-only
19 */ 19 */
20 20
21import { shell } from 'electron'; 21import { app, shell } from 'electron';
22import { getLogger } from 'loglevel'; 22import { getLogger } from 'loglevel';
23 23
24import type MainEnv from '../../../stores/MainEnv'; 24import type MainEnv from '../../../stores/MainEnv';
@@ -31,6 +31,9 @@ const electronShell: MainEnv = {
31 log.error('Failed to open', url, 'in external program', error); 31 log.error('Failed to open', url, 'in external program', error);
32 }); 32 });
33 }, 33 },
34 openAboutDialog(): void {
35 app.showAboutPanel();
36 },
34}; 37};
35 38
36export default electronShell; 39export default electronShell;
diff --git a/packages/main/src/infrastructure/electron/impl/setApplicationMenu.ts b/packages/main/src/infrastructure/electron/impl/setApplicationMenu.ts
new file mode 100644
index 0000000..5166719
--- /dev/null
+++ b/packages/main/src/infrastructure/electron/impl/setApplicationMenu.ts
@@ -0,0 +1,165 @@
1/*
2 * Copyright (C) 2022 Kristóf Marussy <kristof@marussy.com>
3 *
4 * This file is part of Sophie.
5 *
6 * Sophie is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as
8 * published by the Free Software Foundation, version 3.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 *
18 * SPDX-License-Identifier: AGPL-3.0-only
19 */
20
21import { Menu, MenuItemConstructorOptions } from 'electron';
22import { autorun } from 'mobx';
23import { addDisposer } from 'mobx-state-tree';
24
25import type MainStore from '../../../stores/MainStore';
26
27export default function setApplicationMenu(
28 store: MainStore,
29 devMode: boolean,
30 isMac: boolean,
31): void {
32 const dispose = autorun(() => {
33 const { settings, shared, visibleService } = store;
34 const { showLocationBar, selectedService } = settings;
35 const { canSwitchServices, services } = shared;
36
37 const template: MenuItemConstructorOptions[] = [
38 ...(isMac ? ([{ role: 'appMenu' }] as MenuItemConstructorOptions[]) : []),
39 { role: 'fileMenu' },
40 { role: 'editMenu' },
41 {
42 role: 'viewMenu',
43 submenu: [
44 {
45 label: 'Show Location Bar',
46 accelerator: 'CommandOrControl+Shift+L',
47 type: 'checkbox',
48 checked: showLocationBar,
49 click() {
50 settings.toggleLocationBar();
51 },
52 },
53 { type: 'separator' },
54 {
55 label: 'Reload',
56 accelerator: 'CommandOrControl+R',
57 enabled: selectedService !== undefined,
58 click() {
59 selectedService?.reload(false);
60 },
61 },
62 {
63 label: 'Force Reload',
64 accelerator: 'CommandOrControl+Shift+R',
65 enabled: selectedService !== undefined,
66 click() {
67 selectedService?.reload(true);
68 },
69 },
70 {
71 label: 'Toggle Developer Tools',
72 accelerator: 'CommandOrControl+Shift+I',
73 enabled: visibleService !== undefined,
74 click() {
75 visibleService?.toggleDeveloperTools();
76 },
77 },
78 { type: 'separator' },
79 ...(devMode
80 ? ([
81 {
82 role: 'forceReload',
83 label: 'Reload Sophie',
84 accelerator: 'CommandOrControl+Shift+Alt+R',
85 },
86 {
87 role: 'toggleDevTools',
88 label: 'Toggle Sophie Developer Tools',
89 accelerator: 'CommandOrControl+Shift+Alt+I',
90 },
91 { type: 'separator' },
92 ] as MenuItemConstructorOptions[])
93 : []),
94 { role: 'togglefullscreen' },
95 ],
96 },
97 {
98 label: 'Services',
99 submenu: [
100 {
101 label: 'Next Service',
102 accelerator: 'CommandOrControl+Tab',
103 enabled: canSwitchServices,
104 click() {
105 shared.activateNextService();
106 },
107 },
108 {
109 label: 'Previous Service',
110 accelerator: 'CommandOrControl+Shift+Tab',
111 enabled: canSwitchServices,
112 click() {
113 shared.activatePreviousService();
114 },
115 },
116 ...(services.length > 0
117 ? ([
118 { type: 'separator' },
119 ...services.map(
120 (service, index): MenuItemConstructorOptions => ({
121 label: service.config.name,
122 type: 'radio',
123 ...(index < 9
124 ? {
125 accelerator: `CommandOrControl+${index + 1}`,
126 }
127 : {}),
128 checked: selectedService === service,
129 click() {
130 settings.setSelectedService(service);
131 },
132 }),
133 ),
134 ] as MenuItemConstructorOptions[])
135 : []),
136 ],
137 },
138 { role: 'windowMenu' },
139 {
140 role: 'help',
141 submenu: [
142 {
143 label: 'Gitlab',
144 click() {
145 store.openWebpageInBrowser();
146 },
147 },
148 ...(isMac
149 ? []
150 : ([
151 {
152 role: 'about',
153 click() {
154 store.openAboutDialog();
155 },
156 },
157 ] as MenuItemConstructorOptions[])),
158 ],
159 },
160 ];
161 const menu = Menu.buildFromTemplate(template);
162 Menu.setApplicationMenu(menu);
163 });
164 addDisposer(store, dispose);
165}