Merge branch 'pass-lifetime-fixes' into 'main'
[ProtonMail-WebClient.git] / applications / pass-desktop / src / menu-view / application-menu.ts
blobf44ac9f08e5d4e1fa54971220f2d081b45296bd0
1 import { type BrowserWindow, Menu, type MenuItemConstructorOptions, app, shell } from 'electron';
2 import { c } from 'ttag';
4 import { PASS_APP_NAME } from '@proton/shared/lib/constants';
6 import { uninstallProton } from '../uninstallers/macos/uninstall';
7 import { isMac, isProdEnv } from '../utils/platform';
9 type MenuKey = 'app' | 'file' | 'edit' | 'view' | 'window';
10 type MenuProps = MenuItemConstructorOptions & { key: MenuKey };
12 type MenuInsertProps = {
13     menu: MenuProps[];
14     key: MenuKey;
15     otherOsEntries?: MenuItemConstructorOptions[];
16     macEntries?: MenuItemConstructorOptions[];
17     allOSEntries?: MenuItemConstructorOptions[];
20 const insertInMenu = ({ menu, key, otherOsEntries, macEntries, allOSEntries }: MenuInsertProps) => {
21     const editIndex = menu.findIndex((item) => item.key === key);
22     if (!editIndex) return;
24     const submenu = menu[editIndex].submenu as MenuItemConstructorOptions[];
25     if (isMac && macEntries) {
26         menu[editIndex].submenu = [...submenu, ...macEntries];
27     } else if (!isMac && otherOsEntries) {
28         menu[editIndex].submenu = [...submenu, ...otherOsEntries];
29     }
31     menu[editIndex].submenu = [...submenu, ...(allOSEntries ?? [])];
34 export const setApplicationMenu = (mainWindow: BrowserWindow) => {
35     const temp: MenuProps[] = [
36         {
37             label: c('Menu').t`File`,
38             key: 'file',
39             submenu: [
40                 {
41                     label: c('App menu').t`Show logs`,
42                     type: 'normal',
43                     click: () => shell.openPath(app.getPath('logs')),
44                 },
45                 {
46                     role: 'quit',
47                 },
48             ],
49         },
50         {
51             label: c('Menu').t`Edit`,
52             key: 'edit',
53             submenu: [
54                 { role: 'undo' },
55                 { role: 'redo' },
56                 { type: 'separator' },
57                 { role: 'cut' },
58                 { role: 'copy' },
59                 { role: 'paste' },
60                 { role: 'pasteAndMatchStyle', accelerator: isMac ? 'Cmd+Shift+V' : 'Ctrl+Shift+V' },
61                 { role: 'selectAll' },
62             ],
63         },
64         {
65             label: c('Menu').t`View`,
66             key: 'view',
67             submenu: [
68                 {
69                     label: c('App menu').t`Reload`,
70                     accelerator: isMac ? 'Cmd+R' : 'Ctrl+R',
71                     click: () => mainWindow.webContents.reload(),
72                 },
73                 {
74                     label: c('App menu').t`Force Reload`,
75                     accelerator: isMac ? 'Cmd+Shift+R' : 'Ctrl+Shift+R',
76                     click: () => mainWindow.webContents.reloadIgnoringCache(),
77                 },
78                 { type: 'separator' },
79                 { role: 'resetZoom' },
80                 { role: 'zoomIn' },
81                 { role: 'zoomOut' },
82                 { type: 'separator' },
83                 { role: 'togglefullscreen' },
84             ],
85         },
86         {
87             label: c('Menu').t`Window`,
88             key: 'window',
89             submenu: [{ role: 'minimize' }, { role: 'close' }, { role: 'zoom' }],
90         },
91     ];
93     if (isMac) {
94         temp.unshift({
95             label: app.name,
96             key: 'app',
97             submenu: [
98                 { role: 'about' },
99                 { type: 'separator' },
100                 { role: 'hide' },
101                 { role: 'hideOthers' },
102                 { role: 'unhide' },
103                 { type: 'separator' },
104                 {
105                     label: c('App menu').t`Start ${PASS_APP_NAME} at login`,
106                     type: 'checkbox',
107                     checked: app.getLoginItemSettings().openAtLogin,
108                     click: () => {
109                         app.setLoginItemSettings({ openAtLogin: !app.getLoginItemSettings().openAtLogin });
110                     },
111                 },
112                 {
113                     label: c('App menu').t`Uninstall ${PASS_APP_NAME}`,
114                     type: 'normal',
115                     click: () => uninstallProton(),
116                 },
117                 { type: 'separator' },
118                 { role: 'quit' },
119             ],
120         });
122         if (!isProdEnv()) {
123             const submenu = temp[0].submenu as MenuItemConstructorOptions[];
124             temp[0].submenu = [...submenu, { type: 'separator' }, { role: 'services' }];
125         }
126     }
128     insertInMenu({
129         menu: temp,
130         key: 'edit',
131         otherOsEntries: [{ role: 'delete' }, { type: 'separator' }, { role: 'selectAll' }],
132         macEntries: [
133             { role: 'pasteAndMatchStyle' },
134             { role: 'delete' },
135             { role: 'selectAll' },
136             { type: 'separator' },
137             {
138                 label: c('App menu').t`Speech`,
139                 submenu: [{ role: 'startSpeaking' }, { role: 'stopSpeaking' }],
140             },
141         ],
142     });
144     if (!isProdEnv() || Boolean(process.env.PASS_DEBUG)) {
145         insertInMenu({
146             menu: temp,
147             key: 'view',
148             allOSEntries: [
149                 { type: 'separator' },
150                 {
151                     label: c('App menu').t`Toggle developers tools`,
152                     accelerator: isMac ? 'Cmd+Alt+I' : 'Ctrl+Shift+I',
153                     click: () => mainWindow.webContents.toggleDevTools(),
154                 },
155             ],
156         });
157     }
159     Menu.setApplicationMenu(Menu.buildFromTemplate(temp));