diff options
Diffstat (limited to 'src/lib/Menu.ts')
-rw-r--r-- | src/lib/Menu.ts | 1286 |
1 files changed, 1286 insertions, 0 deletions
diff --git a/src/lib/Menu.ts b/src/lib/Menu.ts new file mode 100644 index 000000000..c206ea55d --- /dev/null +++ b/src/lib/Menu.ts | |||
@@ -0,0 +1,1286 @@ | |||
1 | import { clipboard, MenuItemConstructorOptions } from 'electron'; | ||
2 | import { | ||
3 | app, | ||
4 | Menu, | ||
5 | dialog, | ||
6 | webContents, | ||
7 | systemPreferences, | ||
8 | getCurrentWindow, | ||
9 | } from '@electron/remote'; | ||
10 | import { autorun, action, makeObservable, observable } from 'mobx'; | ||
11 | import { defineMessages, IntlShape } from 'react-intl'; | ||
12 | import osName from 'os-name'; | ||
13 | import { fromJS } from 'immutable'; | ||
14 | import semver from 'semver'; | ||
15 | import os from 'os'; | ||
16 | import { | ||
17 | isWindows, | ||
18 | cmdOrCtrlShortcutKey, | ||
19 | altKey, | ||
20 | shiftKey, | ||
21 | settingsShortcutKey, | ||
22 | isLinux, | ||
23 | isMac, | ||
24 | lockFerdiumShortcutKey, | ||
25 | todosToggleShortcutKey, | ||
26 | workspaceToggleShortcutKey, | ||
27 | addNewServiceShortcutKey, | ||
28 | splitModeToggleShortcutKey, | ||
29 | muteFerdiumShortcutKey, | ||
30 | electronVersion, | ||
31 | chromeVersion, | ||
32 | nodeVersion, | ||
33 | osArch, | ||
34 | toggleFullScreenKey, | ||
35 | } from '../environment'; | ||
36 | import { CUSTOM_WEBSITE_RECIPE_ID, LIVE_API_FERDIUM_WEBSITE } from '../config'; | ||
37 | import { ferdiumVersion } from '../environment-remote'; | ||
38 | import { todoActions } from '../features/todos/actions'; | ||
39 | import workspaceActions from '../features/workspaces/actions'; | ||
40 | import { workspaceStore } from '../features/workspaces/index'; | ||
41 | import { importExportURL, serverBase, serverName } from '../api/apiBase'; | ||
42 | import { openExternalUrl } from '../helpers/url-helpers'; | ||
43 | import globalMessages from '../i18n/globalMessages'; | ||
44 | import { onAuthGoToReleaseNotes } from '../helpers/update-helpers'; | ||
45 | // @ts-expect-error Cannot find module '../buildInfo.json' or its corresponding type declarations. | ||
46 | import { timestamp, gitHashShort, gitBranch } from '../buildInfo.json'; | ||
47 | import Service from '../models/Service'; | ||
48 | import { StoresProps } from '../@types/ferdium-components.types'; | ||
49 | import { RealStores } from '../stores'; | ||
50 | |||
51 | const menuItems = defineMessages({ | ||
52 | edit: { | ||
53 | id: 'menu.edit', | ||
54 | defaultMessage: 'Edit', | ||
55 | }, | ||
56 | undo: { | ||
57 | id: 'menu.edit.undo', | ||
58 | defaultMessage: 'Undo', | ||
59 | }, | ||
60 | redo: { | ||
61 | id: 'menu.edit.redo', | ||
62 | defaultMessage: 'Redo', | ||
63 | }, | ||
64 | cut: { | ||
65 | id: 'menu.edit.cut', | ||
66 | defaultMessage: 'Cut', | ||
67 | }, | ||
68 | copy: { | ||
69 | id: 'menu.edit.copy', | ||
70 | defaultMessage: 'Copy', | ||
71 | }, | ||
72 | paste: { | ||
73 | id: 'menu.edit.paste', | ||
74 | defaultMessage: 'Paste', | ||
75 | }, | ||
76 | pasteAndMatchStyle: { | ||
77 | id: 'menu.edit.pasteAndMatchStyle', | ||
78 | defaultMessage: 'Paste And Match Style', | ||
79 | }, | ||
80 | delete: { | ||
81 | id: 'menu.edit.delete', | ||
82 | defaultMessage: 'Delete', | ||
83 | }, | ||
84 | selectAll: { | ||
85 | id: 'menu.edit.selectAll', | ||
86 | defaultMessage: 'Select All', | ||
87 | }, | ||
88 | findInPage: { | ||
89 | id: 'menu.edit.findInPage', | ||
90 | defaultMessage: 'Find in Page', | ||
91 | }, | ||
92 | speech: { | ||
93 | id: 'menu.edit.speech', | ||
94 | defaultMessage: 'Speech', | ||
95 | }, | ||
96 | startSpeaking: { | ||
97 | id: 'menu.edit.startSpeaking', | ||
98 | defaultMessage: 'Start Speaking', | ||
99 | }, | ||
100 | stopSpeaking: { | ||
101 | id: 'menu.edit.stopSpeaking', | ||
102 | defaultMessage: 'Stop Speaking', | ||
103 | }, | ||
104 | startDictation: { | ||
105 | id: 'menu.edit.startDictation', | ||
106 | defaultMessage: 'Start Dictation', | ||
107 | }, | ||
108 | emojiSymbols: { | ||
109 | id: 'menu.edit.emojiSymbols', | ||
110 | defaultMessage: 'Emoji & Symbols', | ||
111 | }, | ||
112 | openQuickSwitch: { | ||
113 | id: 'menu.view.openQuickSwitch', | ||
114 | defaultMessage: 'Open Quick Switch', | ||
115 | }, | ||
116 | back: { | ||
117 | id: 'menu.view.back', | ||
118 | defaultMessage: 'Back', | ||
119 | }, | ||
120 | forward: { | ||
121 | id: 'menu.view.forward', | ||
122 | defaultMessage: 'Forward', | ||
123 | }, | ||
124 | resetZoom: { | ||
125 | id: 'menu.view.resetZoom', | ||
126 | defaultMessage: 'Actual Size', | ||
127 | }, | ||
128 | zoomIn: { | ||
129 | id: 'menu.view.zoomIn', | ||
130 | defaultMessage: 'Zoom In', | ||
131 | }, | ||
132 | zoomOut: { | ||
133 | id: 'menu.view.zoomOut', | ||
134 | defaultMessage: 'Zoom Out', | ||
135 | }, | ||
136 | toggleFullScreen: { | ||
137 | id: 'menu.view.toggleFullScreen', | ||
138 | defaultMessage: 'Toggle Full Screen', | ||
139 | }, | ||
140 | toggleNavigationBar: { | ||
141 | id: 'menu.view.toggleNavigationBar', | ||
142 | defaultMessage: 'Toggle Navigation Bar', | ||
143 | }, | ||
144 | splitModeToggle: { | ||
145 | id: 'menu.view.splitModeToggle', | ||
146 | defaultMessage: 'Toggle Split Mode', | ||
147 | }, | ||
148 | toggleDarkMode: { | ||
149 | id: 'menu.view.toggleDarkMode', | ||
150 | defaultMessage: 'Toggle Dark Mode', | ||
151 | }, | ||
152 | toggleDevTools: { | ||
153 | id: 'menu.view.toggleDevTools', | ||
154 | defaultMessage: 'Toggle Developer Tools', | ||
155 | }, | ||
156 | toggleTodosDevTools: { | ||
157 | id: 'menu.view.toggleTodosDevTools', | ||
158 | defaultMessage: 'Toggle Todos Developer Tools', | ||
159 | }, | ||
160 | toggleServiceDevTools: { | ||
161 | id: 'menu.view.toggleServiceDevTools', | ||
162 | defaultMessage: 'Toggle Service Developer Tools', | ||
163 | }, | ||
164 | reloadService: { | ||
165 | id: 'menu.view.reloadService', | ||
166 | defaultMessage: 'Reload Service', | ||
167 | }, | ||
168 | reloadFerdium: { | ||
169 | id: 'menu.view.reloadFerdium', | ||
170 | defaultMessage: 'Reload Ferdium', | ||
171 | }, | ||
172 | lockFerdium: { | ||
173 | id: 'menu.view.lockFerdium', | ||
174 | defaultMessage: 'Lock Ferdium', | ||
175 | }, | ||
176 | reloadTodos: { | ||
177 | id: 'menu.view.reloadTodos', | ||
178 | defaultMessage: 'Reload ToDos', | ||
179 | }, | ||
180 | minimize: { | ||
181 | id: 'menu.window.minimize', | ||
182 | defaultMessage: 'Minimize', | ||
183 | }, | ||
184 | close: { | ||
185 | id: 'menu.window.close', | ||
186 | defaultMessage: 'Close', | ||
187 | }, | ||
188 | learnMore: { | ||
189 | id: 'menu.help.learnMore', | ||
190 | defaultMessage: 'Learn More', | ||
191 | }, | ||
192 | changelog: { | ||
193 | id: 'menu.help.changelog', | ||
194 | defaultMessage: 'Changelog', | ||
195 | }, | ||
196 | importExportData: { | ||
197 | id: 'menu.help.importExportData', | ||
198 | defaultMessage: 'Import/Export Configuration Data', | ||
199 | }, | ||
200 | support: { | ||
201 | id: 'menu.help.support', | ||
202 | defaultMessage: 'Support', | ||
203 | }, | ||
204 | debugInfo: { | ||
205 | id: 'menu.help.debugInfo', | ||
206 | defaultMessage: 'Copy Debug Information', | ||
207 | }, | ||
208 | publishDebugInfo: { | ||
209 | id: 'menu.help.publishDebugInfo', | ||
210 | defaultMessage: 'Publish Debug Information', | ||
211 | }, | ||
212 | debugInfoCopiedHeadline: { | ||
213 | id: 'menu.help.debugInfoCopiedHeadline', | ||
214 | defaultMessage: 'Ferdium Debug Information', | ||
215 | }, | ||
216 | debugInfoCopiedBody: { | ||
217 | id: 'menu.help.debugInfoCopiedBody', | ||
218 | defaultMessage: 'Your Debug Information has been copied to your clipboard.', | ||
219 | }, | ||
220 | touchId: { | ||
221 | id: 'locked.touchId', | ||
222 | defaultMessage: 'Unlock with Touch ID', | ||
223 | }, | ||
224 | touchIdPrompt: { | ||
225 | id: 'locked.touchIdPrompt', | ||
226 | defaultMessage: 'unlock via Touch ID', | ||
227 | }, | ||
228 | tos: { | ||
229 | id: 'menu.help.tos', | ||
230 | defaultMessage: 'Terms of Service', | ||
231 | }, | ||
232 | privacy: { | ||
233 | id: 'menu.help.privacy', | ||
234 | defaultMessage: 'Privacy Statement', | ||
235 | }, | ||
236 | file: { | ||
237 | id: 'menu.file', | ||
238 | defaultMessage: 'File', | ||
239 | }, | ||
240 | view: { | ||
241 | id: 'menu.view', | ||
242 | defaultMessage: 'View', | ||
243 | }, | ||
244 | services: { | ||
245 | id: 'menu.services', | ||
246 | defaultMessage: 'Services', | ||
247 | }, | ||
248 | window: { | ||
249 | id: 'menu.window', | ||
250 | defaultMessage: 'Window', | ||
251 | }, | ||
252 | help: { | ||
253 | id: 'menu.help', | ||
254 | defaultMessage: 'Help', | ||
255 | }, | ||
256 | about: { | ||
257 | id: 'menu.app.about', | ||
258 | defaultMessage: 'About Ferdium', | ||
259 | }, | ||
260 | checkForUpdates: { | ||
261 | id: 'menu.app.checkForUpdates', | ||
262 | defaultMessage: 'Check for updates', | ||
263 | }, | ||
264 | hide: { | ||
265 | id: 'menu.app.hide', | ||
266 | defaultMessage: 'Hide', | ||
267 | }, | ||
268 | hideOthers: { | ||
269 | id: 'menu.app.hideOthers', | ||
270 | defaultMessage: 'Hide Others', | ||
271 | }, | ||
272 | unhide: { | ||
273 | id: 'menu.app.unhide', | ||
274 | defaultMessage: 'Unhide', | ||
275 | }, | ||
276 | autohideMenuBar: { | ||
277 | id: 'menu.app.autohideMenuBar', | ||
278 | defaultMessage: 'Auto-hide menu bar', | ||
279 | }, | ||
280 | addNewService: { | ||
281 | id: 'menu.services.addNewService', | ||
282 | defaultMessage: 'Add New Service...', | ||
283 | }, | ||
284 | addNewWorkspace: { | ||
285 | id: 'menu.workspaces.addNewWorkspace', | ||
286 | defaultMessage: 'Add New Workspace...', | ||
287 | }, | ||
288 | openWorkspaceDrawer: { | ||
289 | id: 'menu.workspaces.openWorkspaceDrawer', | ||
290 | defaultMessage: 'Open workspace drawer', | ||
291 | }, | ||
292 | closeWorkspaceDrawer: { | ||
293 | id: 'menu.workspaces.closeWorkspaceDrawer', | ||
294 | defaultMessage: 'Close workspace drawer', | ||
295 | }, | ||
296 | activateNextService: { | ||
297 | id: 'menu.services.setNextServiceActive', | ||
298 | defaultMessage: 'Activate next service', | ||
299 | }, | ||
300 | activatePreviousService: { | ||
301 | id: 'menu.services.activatePreviousService', | ||
302 | defaultMessage: 'Activate previous service', | ||
303 | }, | ||
304 | muteApp: { | ||
305 | id: 'sidebar.muteApp', | ||
306 | defaultMessage: 'Disable notifications & audio', | ||
307 | }, | ||
308 | unmuteApp: { | ||
309 | id: 'sidebar.unmuteApp', | ||
310 | defaultMessage: 'Enable notifications & audio', | ||
311 | }, | ||
312 | workspaces: { | ||
313 | id: 'menu.workspaces', | ||
314 | defaultMessage: 'Workspaces', | ||
315 | }, | ||
316 | defaultWorkspace: { | ||
317 | id: 'menu.workspaces.defaultWorkspace', | ||
318 | defaultMessage: 'All services', | ||
319 | }, | ||
320 | todos: { | ||
321 | id: 'menu.todos', | ||
322 | defaultMessage: 'Todos', | ||
323 | }, | ||
324 | openTodosDrawer: { | ||
325 | id: 'menu.Todoss.openTodosDrawer', | ||
326 | defaultMessage: 'Open Todos drawer', | ||
327 | }, | ||
328 | closeTodosDrawer: { | ||
329 | id: 'menu.Todoss.closeTodosDrawer', | ||
330 | defaultMessage: 'Close Todos drawer', | ||
331 | }, | ||
332 | enableTodos: { | ||
333 | id: 'menu.todos.enableTodos', | ||
334 | defaultMessage: 'Enable Todos', | ||
335 | }, | ||
336 | disableTodos: { | ||
337 | id: 'menu.todos.disableTodos', | ||
338 | defaultMessage: 'Disable Todos', | ||
339 | }, | ||
340 | serviceGoHome: { | ||
341 | id: 'menu.services.goHome', | ||
342 | defaultMessage: 'Home', | ||
343 | }, | ||
344 | ok: { | ||
345 | id: 'global.ok', | ||
346 | defaultMessage: 'Ok', | ||
347 | }, | ||
348 | copyToClipboard: { | ||
349 | id: 'menu.services.copyToClipboard', | ||
350 | defaultMessage: 'Copy to clipboard', | ||
351 | }, | ||
352 | }); | ||
353 | |||
354 | function getActiveService(): Service | undefined { | ||
355 | return window['ferdium'].stores.services.active; | ||
356 | } | ||
357 | |||
358 | function toggleFullScreen(): void { | ||
359 | const mainWindow = getCurrentWindow(); | ||
360 | |||
361 | if (!mainWindow) return; | ||
362 | |||
363 | if (mainWindow.isFullScreen()) { | ||
364 | mainWindow.setFullScreen(false); | ||
365 | } else { | ||
366 | mainWindow.setFullScreen(true); | ||
367 | } | ||
368 | } | ||
369 | |||
370 | function titleBarTemplateFactory( | ||
371 | intl: IntlShape, | ||
372 | locked: boolean, | ||
373 | ): MenuItemConstructorOptions[] { | ||
374 | return [ | ||
375 | { | ||
376 | label: intl.formatMessage(menuItems.edit), | ||
377 | accelerator: `${altKey()}+E`, | ||
378 | submenu: [ | ||
379 | { | ||
380 | label: intl.formatMessage(menuItems.undo), | ||
381 | role: 'undo', | ||
382 | }, | ||
383 | { | ||
384 | label: intl.formatMessage(menuItems.redo), | ||
385 | role: 'redo', | ||
386 | }, | ||
387 | { | ||
388 | type: 'separator', | ||
389 | }, | ||
390 | { | ||
391 | label: intl.formatMessage(menuItems.cut), | ||
392 | accelerator: `${cmdOrCtrlShortcutKey()}+X`, | ||
393 | role: 'cut', | ||
394 | }, | ||
395 | { | ||
396 | label: intl.formatMessage(menuItems.copy), | ||
397 | accelerator: `${cmdOrCtrlShortcutKey()}+C`, | ||
398 | role: 'copy', | ||
399 | }, | ||
400 | { | ||
401 | label: intl.formatMessage(menuItems.paste), | ||
402 | accelerator: `${cmdOrCtrlShortcutKey()}+V`, | ||
403 | role: 'paste', | ||
404 | }, | ||
405 | { | ||
406 | label: intl.formatMessage(menuItems.pasteAndMatchStyle), | ||
407 | accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+V`, // Override the accelerator since this adds new key combo in macos | ||
408 | role: 'pasteAndMatchStyle', | ||
409 | }, | ||
410 | { | ||
411 | label: intl.formatMessage(menuItems.delete), | ||
412 | role: 'delete', | ||
413 | }, | ||
414 | { | ||
415 | label: intl.formatMessage(menuItems.selectAll), | ||
416 | accelerator: `${cmdOrCtrlShortcutKey()}+A`, | ||
417 | role: 'selectAll', | ||
418 | }, | ||
419 | ], | ||
420 | }, | ||
421 | { | ||
422 | label: intl.formatMessage(menuItems.view), | ||
423 | accelerator: `${altKey()}+V`, | ||
424 | visible: !locked, | ||
425 | submenu: [ | ||
426 | { | ||
427 | type: 'separator', | ||
428 | }, | ||
429 | { | ||
430 | label: intl.formatMessage(menuItems.openQuickSwitch), | ||
431 | accelerator: `${cmdOrCtrlShortcutKey()}+S`, | ||
432 | click() { | ||
433 | window['ferdium'].features.quickSwitch.state.isModalVisible = true; | ||
434 | }, | ||
435 | }, | ||
436 | { | ||
437 | type: 'separator', | ||
438 | }, | ||
439 | { | ||
440 | label: intl.formatMessage(menuItems.findInPage), | ||
441 | accelerator: `${cmdOrCtrlShortcutKey()}+F`, | ||
442 | click() { | ||
443 | const activeService = getActiveService(); | ||
444 | if (!activeService) { | ||
445 | return; | ||
446 | } | ||
447 | activeService.webview.focus(); | ||
448 | window['ferdium'].actions.service.sendIPCMessage({ | ||
449 | serviceId: activeService.id, | ||
450 | channel: 'find-in-page', | ||
451 | args: {}, | ||
452 | }); | ||
453 | }, | ||
454 | }, | ||
455 | { | ||
456 | type: 'separator', | ||
457 | }, | ||
458 | { | ||
459 | label: intl.formatMessage(menuItems.back), | ||
460 | accelerator: `${!isMac ? altKey() : cmdOrCtrlShortcutKey()}+Left`, | ||
461 | click() { | ||
462 | const activeService = getActiveService(); | ||
463 | if (!activeService) { | ||
464 | return; | ||
465 | } | ||
466 | activeService.webview.goBack(); | ||
467 | }, | ||
468 | }, | ||
469 | { | ||
470 | label: intl.formatMessage(menuItems.forward), | ||
471 | accelerator: `${!isMac ? altKey() : cmdOrCtrlShortcutKey()}+Right`, | ||
472 | click() { | ||
473 | const activeService = getActiveService(); | ||
474 | if (!activeService) { | ||
475 | return; | ||
476 | } | ||
477 | activeService.webview.goForward(); | ||
478 | }, | ||
479 | }, | ||
480 | { | ||
481 | type: 'separator', | ||
482 | }, | ||
483 | { | ||
484 | label: intl.formatMessage(menuItems.resetZoom), | ||
485 | accelerator: `${cmdOrCtrlShortcutKey()}+0`, | ||
486 | click() { | ||
487 | const activeService = getActiveService(); | ||
488 | if (!activeService) { | ||
489 | return; | ||
490 | } | ||
491 | activeService.webview.setZoomLevel(0); | ||
492 | }, | ||
493 | }, | ||
494 | { | ||
495 | label: intl.formatMessage(menuItems.zoomIn), | ||
496 | accelerator: `${cmdOrCtrlShortcutKey()}+plus`, | ||
497 | click() { | ||
498 | const activeService = getActiveService(); | ||
499 | if (!activeService) { | ||
500 | return; | ||
501 | } | ||
502 | const { webview } = activeService; | ||
503 | const level = webview.getZoomLevel(); | ||
504 | webview.setZoomLevel(level + 0.5); | ||
505 | }, | ||
506 | }, | ||
507 | { | ||
508 | label: intl.formatMessage(menuItems.zoomOut), | ||
509 | accelerator: `${cmdOrCtrlShortcutKey()}+-`, | ||
510 | click() { | ||
511 | const activeService = getActiveService(); | ||
512 | if (!activeService) { | ||
513 | return; | ||
514 | } | ||
515 | const { webview } = activeService; | ||
516 | const level = webview.getZoomLevel(); | ||
517 | webview.setZoomLevel(level - 0.5); | ||
518 | }, | ||
519 | }, | ||
520 | { | ||
521 | type: 'separator', | ||
522 | }, | ||
523 | { | ||
524 | label: intl.formatMessage(menuItems.toggleFullScreen), | ||
525 | click: () => { | ||
526 | toggleFullScreen(); | ||
527 | }, | ||
528 | accelerator: toggleFullScreenKey(), | ||
529 | }, | ||
530 | { | ||
531 | label: intl.formatMessage(menuItems.toggleNavigationBar), | ||
532 | accelerator: `${cmdOrCtrlShortcutKey()}+B`, | ||
533 | // role: 'toggleNavigationBar', | ||
534 | type: 'checkbox', | ||
535 | checked: | ||
536 | window['ferdium'].stores.settings.app.navigationBarManualActive, | ||
537 | click: () => { | ||
538 | window['ferdium'].actions.settings.update({ | ||
539 | type: 'app', | ||
540 | data: { | ||
541 | navigationBarManualActive: | ||
542 | !window['ferdium'].stores.settings.app | ||
543 | .navigationBarManualActive, | ||
544 | }, | ||
545 | }); | ||
546 | }, | ||
547 | }, | ||
548 | { | ||
549 | label: intl.formatMessage(menuItems.splitModeToggle), | ||
550 | accelerator: `${splitModeToggleShortcutKey()}`, | ||
551 | // role: 'splitModeToggle', | ||
552 | type: 'checkbox', | ||
553 | checked: window['ferdium'].stores.settings.app.splitMode, | ||
554 | click: () => { | ||
555 | window['ferdium'].actions.settings.update({ | ||
556 | type: 'app', | ||
557 | data: { | ||
558 | splitMode: !window['ferdium'].stores.settings.app.splitMode, | ||
559 | }, | ||
560 | }); | ||
561 | }, | ||
562 | }, | ||
563 | { | ||
564 | label: intl.formatMessage(menuItems.toggleDarkMode), | ||
565 | type: 'checkbox', | ||
566 | accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+D`, | ||
567 | checked: window['ferdium'].stores.settings.app.darkMode, | ||
568 | click: () => { | ||
569 | window['ferdium'].actions.settings.update({ | ||
570 | type: 'app', | ||
571 | data: { | ||
572 | darkMode: !window['ferdium'].stores.settings.app.darkMode, | ||
573 | }, | ||
574 | }); | ||
575 | }, | ||
576 | }, | ||
577 | ], | ||
578 | }, | ||
579 | { | ||
580 | label: intl.formatMessage(menuItems.services), | ||
581 | accelerator: `${altKey()}+S`, | ||
582 | visible: !locked, | ||
583 | submenu: [], | ||
584 | }, | ||
585 | { | ||
586 | label: intl.formatMessage(menuItems.workspaces), | ||
587 | accelerator: `${altKey()}+W`, | ||
588 | submenu: [], | ||
589 | visible: !locked, | ||
590 | }, | ||
591 | { | ||
592 | label: intl.formatMessage(menuItems.todos), | ||
593 | submenu: [], | ||
594 | visible: !locked, | ||
595 | }, | ||
596 | { | ||
597 | label: intl.formatMessage(menuItems.window), | ||
598 | role: 'window', | ||
599 | submenu: [ | ||
600 | { | ||
601 | label: intl.formatMessage(menuItems.minimize), | ||
602 | role: 'minimize', | ||
603 | }, | ||
604 | { | ||
605 | label: intl.formatMessage(menuItems.close), | ||
606 | role: 'close', | ||
607 | }, | ||
608 | ], | ||
609 | }, | ||
610 | { | ||
611 | label: intl.formatMessage(menuItems.help), | ||
612 | accelerator: `${altKey()}+H`, | ||
613 | role: 'help', | ||
614 | submenu: [ | ||
615 | { | ||
616 | label: intl.formatMessage(menuItems.learnMore), | ||
617 | click() { | ||
618 | openExternalUrl(LIVE_API_FERDIUM_WEBSITE, true); | ||
619 | }, | ||
620 | }, | ||
621 | { | ||
622 | label: intl.formatMessage(menuItems.changelog), | ||
623 | click() { | ||
624 | window.location.href = onAuthGoToReleaseNotes(window.location.href); | ||
625 | }, | ||
626 | }, | ||
627 | { | ||
628 | label: intl.formatMessage(menuItems.importExportData), | ||
629 | click() { | ||
630 | openExternalUrl(importExportURL(), true); | ||
631 | }, | ||
632 | enabled: !locked, | ||
633 | }, | ||
634 | { | ||
635 | type: 'separator', | ||
636 | }, | ||
637 | { | ||
638 | label: intl.formatMessage(menuItems.support), | ||
639 | click() { | ||
640 | openExternalUrl(`${LIVE_API_FERDIUM_WEBSITE}/contact`, true); | ||
641 | }, | ||
642 | }, | ||
643 | { | ||
644 | type: 'separator', | ||
645 | }, | ||
646 | { | ||
647 | label: intl.formatMessage(menuItems.tos), | ||
648 | click() { | ||
649 | openExternalUrl(`${serverBase()}/terms`, true); | ||
650 | }, | ||
651 | }, | ||
652 | { | ||
653 | label: intl.formatMessage(menuItems.privacy), | ||
654 | click() { | ||
655 | openExternalUrl(`${serverBase()}/privacy`, true); | ||
656 | }, | ||
657 | }, | ||
658 | ], | ||
659 | }, | ||
660 | ]; | ||
661 | } | ||
662 | |||
663 | class FranzMenu implements StoresProps { | ||
664 | @observable currentTemplate: MenuItemConstructorOptions[]; | ||
665 | |||
666 | actions: any; | ||
667 | |||
668 | stores: RealStores; | ||
669 | |||
670 | constructor(stores: RealStores, actions: any) { | ||
671 | this.stores = stores; | ||
672 | this.actions = actions; | ||
673 | this.currentTemplate = []; | ||
674 | |||
675 | makeObservable(this); | ||
676 | |||
677 | setTimeout(() => autorun(this._build.bind(this)), 10); | ||
678 | } | ||
679 | |||
680 | @action _setCurrentTemplate(tpl: MenuItemConstructorOptions[]): void { | ||
681 | this.currentTemplate = tpl; | ||
682 | } | ||
683 | |||
684 | rebuild(): void { | ||
685 | this._build(); | ||
686 | } | ||
687 | |||
688 | get template(): any { | ||
689 | return fromJS(this.currentTemplate).toJS(); | ||
690 | } | ||
691 | |||
692 | getOsName(): string { | ||
693 | let osNameParse = osName(); | ||
694 | const isWin11 = semver.satisfies(os.release(), '>=10.0.22000'); | ||
695 | osNameParse = isWindows && isWin11 ? 'Windows 11' : osNameParse; | ||
696 | |||
697 | return osNameParse; | ||
698 | } | ||
699 | |||
700 | _build(): void { | ||
701 | // need to clone object so we don't modify computed (cached) object | ||
702 | const serviceTpl = Object.assign([], this.serviceTpl()); | ||
703 | |||
704 | // Don't initialize when window['ferdium'] is undefined | ||
705 | if (window['ferdium'] === undefined) { | ||
706 | console.log('skipping menu init'); | ||
707 | return; | ||
708 | } | ||
709 | |||
710 | const { intl } = window['ferdium']; | ||
711 | const locked = | ||
712 | this.stores.settings.app.locked && | ||
713 | this.stores.settings.app.lockingFeatureEnabled && | ||
714 | this.stores.user.isLoggedIn; | ||
715 | const { actions } = this; | ||
716 | const tpl = titleBarTemplateFactory(intl, locked); | ||
717 | |||
718 | if (!isMac) { | ||
719 | (tpl[1].submenu as MenuItemConstructorOptions[]).push({ | ||
720 | label: intl.formatMessage(menuItems.autohideMenuBar), | ||
721 | type: 'checkbox', | ||
722 | checked: window['ferdium'].stores.settings.app.autohideMenuBar, | ||
723 | click: () => { | ||
724 | window['ferdium'].actions.settings.update({ | ||
725 | type: 'app', | ||
726 | data: { | ||
727 | autohideMenuBar: | ||
728 | !window['ferdium'].stores.settings.app.autohideMenuBar, | ||
729 | }, | ||
730 | }); | ||
731 | }, | ||
732 | }); | ||
733 | } | ||
734 | |||
735 | if (!locked) { | ||
736 | (tpl[1].submenu as MenuItemConstructorOptions[]).push( | ||
737 | { | ||
738 | type: 'separator', | ||
739 | }, | ||
740 | { | ||
741 | label: intl.formatMessage(menuItems.toggleDevTools), | ||
742 | accelerator: `${cmdOrCtrlShortcutKey()}+${altKey()}+I`, | ||
743 | click: () => { | ||
744 | const windowWebContents = webContents.fromId(1); | ||
745 | const { isDevToolsOpened, openDevTools, closeDevTools } = | ||
746 | windowWebContents; | ||
747 | |||
748 | if (isDevToolsOpened()) { | ||
749 | closeDevTools(); | ||
750 | } else { | ||
751 | openDevTools({ mode: 'right' }); | ||
752 | } | ||
753 | }, | ||
754 | }, | ||
755 | { | ||
756 | label: intl.formatMessage(menuItems.toggleServiceDevTools), | ||
757 | accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+${altKey()}+I`, | ||
758 | click: () => { | ||
759 | this.actions.service.openDevToolsForActiveService(); | ||
760 | }, | ||
761 | enabled: | ||
762 | this.stores.user.isLoggedIn && | ||
763 | this.stores.services.enabled.length > 0, | ||
764 | }, | ||
765 | ); | ||
766 | |||
767 | if (this.stores.todos.isFeatureEnabledByUser) { | ||
768 | (tpl[1].submenu as MenuItemConstructorOptions[]).push({ | ||
769 | label: intl.formatMessage(menuItems.toggleTodosDevTools), | ||
770 | accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+${altKey()}+O`, | ||
771 | click: () => { | ||
772 | const webview = document.querySelector('#todos-panel webview'); | ||
773 | if (webview) this.actions.todos.openDevTools(); | ||
774 | }, | ||
775 | }); | ||
776 | } | ||
777 | |||
778 | (tpl[1].submenu as MenuItemConstructorOptions[]).unshift( | ||
779 | { | ||
780 | label: intl.formatMessage(menuItems.reloadService), | ||
781 | accelerator: `${cmdOrCtrlShortcutKey()}+R`, | ||
782 | click: () => { | ||
783 | if ( | ||
784 | this.stores.user.isLoggedIn && | ||
785 | this.stores.services.enabled.length > 0 | ||
786 | ) { | ||
787 | if (getActiveService()?.recipe.id === CUSTOM_WEBSITE_RECIPE_ID) { | ||
788 | getActiveService()?.webview.reload(); | ||
789 | } else { | ||
790 | this.actions.service.reloadActive(); | ||
791 | } | ||
792 | } else { | ||
793 | window.location.reload(); | ||
794 | } | ||
795 | }, | ||
796 | }, | ||
797 | { | ||
798 | label: intl.formatMessage(menuItems.reloadFerdium), | ||
799 | accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+R`, | ||
800 | click: () => { | ||
801 | window.location.reload(); | ||
802 | }, | ||
803 | }, | ||
804 | { | ||
805 | label: intl.formatMessage(menuItems.reloadTodos), | ||
806 | accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+${altKey()}+R`, | ||
807 | click: () => { | ||
808 | this.actions.todos.reload(); | ||
809 | }, | ||
810 | }, | ||
811 | { | ||
812 | type: 'separator', | ||
813 | }, | ||
814 | { | ||
815 | label: intl.formatMessage(menuItems.lockFerdium), | ||
816 | accelerator: `${lockFerdiumShortcutKey()}`, | ||
817 | enabled: | ||
818 | this.stores.user.isLoggedIn && | ||
819 | this.stores.settings.app.lockingFeatureEnabled, | ||
820 | click() { | ||
821 | actions.settings.update({ | ||
822 | type: 'app', | ||
823 | data: { | ||
824 | locked: true, | ||
825 | }, | ||
826 | }); | ||
827 | }, | ||
828 | }, | ||
829 | ); | ||
830 | |||
831 | if (serviceTpl.length > 0) { | ||
832 | tpl[2].submenu = serviceTpl; | ||
833 | } | ||
834 | |||
835 | tpl[3].submenu = this.workspacesMenu(); | ||
836 | |||
837 | tpl[4].submenu = this.todosMenu(); | ||
838 | } else { | ||
839 | const touchIdEnabled = isMac | ||
840 | ? this.stores.settings.app.useTouchIdToUnlock && | ||
841 | systemPreferences.canPromptTouchID() | ||
842 | : false; | ||
843 | |||
844 | (tpl[0].submenu as MenuItemConstructorOptions[]).unshift( | ||
845 | { | ||
846 | label: intl.formatMessage(menuItems.touchId), | ||
847 | accelerator: `${lockFerdiumShortcutKey()}`, | ||
848 | visible: touchIdEnabled, | ||
849 | click() { | ||
850 | systemPreferences | ||
851 | .promptTouchID(intl.formatMessage(menuItems.touchIdPrompt)) | ||
852 | .then(() => { | ||
853 | actions.settings.update({ | ||
854 | type: 'app', | ||
855 | data: { | ||
856 | locked: false, | ||
857 | }, | ||
858 | }); | ||
859 | }); | ||
860 | }, | ||
861 | }, | ||
862 | { | ||
863 | type: 'separator', | ||
864 | visible: touchIdEnabled, | ||
865 | }, | ||
866 | ); | ||
867 | } | ||
868 | |||
869 | tpl.unshift({ | ||
870 | label: isMac ? app.name : intl.formatMessage(menuItems.file), | ||
871 | accelerator: `${altKey()}+F`, | ||
872 | submenu: [ | ||
873 | { | ||
874 | type: 'separator', | ||
875 | }, | ||
876 | { | ||
877 | label: intl.formatMessage(globalMessages.settings), | ||
878 | accelerator: `${settingsShortcutKey()}`, | ||
879 | click: () => { | ||
880 | this.actions.ui.openSettings({ path: 'app' }); | ||
881 | }, | ||
882 | enabled: this.stores.user.isLoggedIn, | ||
883 | visible: !locked, | ||
884 | }, | ||
885 | { | ||
886 | label: intl.formatMessage(menuItems.checkForUpdates), | ||
887 | visible: !locked, | ||
888 | click: () => { | ||
889 | this.actions.app.checkForUpdates(); | ||
890 | }, | ||
891 | }, | ||
892 | { | ||
893 | type: 'separator', | ||
894 | visible: !locked, | ||
895 | }, | ||
896 | { | ||
897 | label: intl.formatMessage(menuItems.services), | ||
898 | role: 'services', | ||
899 | submenu: [], | ||
900 | }, | ||
901 | { | ||
902 | type: 'separator', | ||
903 | }, | ||
904 | { | ||
905 | label: intl.formatMessage(menuItems.hide), | ||
906 | role: 'hide', | ||
907 | }, | ||
908 | { | ||
909 | label: intl.formatMessage(menuItems.hideOthers), | ||
910 | role: 'hideOthers', | ||
911 | }, | ||
912 | { | ||
913 | label: intl.formatMessage(menuItems.unhide), | ||
914 | role: 'unhide', | ||
915 | }, | ||
916 | { | ||
917 | type: 'separator', | ||
918 | }, | ||
919 | { | ||
920 | label: intl.formatMessage(globalMessages.quit), | ||
921 | accelerator: `${cmdOrCtrlShortcutKey()}+Q`, | ||
922 | click() { | ||
923 | app.quit(); | ||
924 | }, | ||
925 | }, | ||
926 | ], | ||
927 | }); | ||
928 | |||
929 | const aboutAppDetails = [ | ||
930 | `Version: ${ferdiumVersion}`, | ||
931 | `Server: ${serverName()} Server`, | ||
932 | `Electron: ${electronVersion}`, | ||
933 | `Chrome: ${chromeVersion}`, | ||
934 | `Node.js: ${nodeVersion}`, | ||
935 | `Platform: ${this.getOsName()}`, | ||
936 | `Arch: ${osArch}`, | ||
937 | `Build date: ${new Date(Number(timestamp))}`, | ||
938 | `Git SHA: ${gitHashShort}`, | ||
939 | `Git branch: ${gitBranch}`, | ||
940 | ].join('\n'); | ||
941 | |||
942 | const about = { | ||
943 | label: intl.formatMessage(menuItems.about), | ||
944 | click: () => { | ||
945 | dialog | ||
946 | .showMessageBox({ | ||
947 | type: 'info', | ||
948 | title: 'Ferdium', | ||
949 | message: 'Ferdium', | ||
950 | detail: aboutAppDetails, | ||
951 | buttons: [ | ||
952 | intl.formatMessage(menuItems.ok), | ||
953 | intl.formatMessage(menuItems.copyToClipboard), | ||
954 | ], | ||
955 | }) | ||
956 | .then(result => { | ||
957 | if (result.response === 1) { | ||
958 | clipboard.write({ | ||
959 | text: aboutAppDetails, | ||
960 | }); | ||
961 | } | ||
962 | }); | ||
963 | }, | ||
964 | }; | ||
965 | |||
966 | if (isMac) { | ||
967 | // Edit menu. | ||
968 | (tpl[1].submenu as MenuItemConstructorOptions[]).push( | ||
969 | { | ||
970 | type: 'separator', | ||
971 | }, | ||
972 | { | ||
973 | label: intl.formatMessage(menuItems.speech), | ||
974 | submenu: [ | ||
975 | { | ||
976 | label: intl.formatMessage(menuItems.startSpeaking), | ||
977 | role: 'startSpeaking', | ||
978 | }, | ||
979 | { | ||
980 | label: intl.formatMessage(menuItems.stopSpeaking), | ||
981 | role: 'stopSpeaking', | ||
982 | }, | ||
983 | ], | ||
984 | }, | ||
985 | ); | ||
986 | |||
987 | (tpl[0].submenu as MenuItemConstructorOptions[]).unshift(about, { | ||
988 | type: 'separator', | ||
989 | }); | ||
990 | } else { | ||
991 | tpl[0].submenu = [ | ||
992 | { | ||
993 | label: intl.formatMessage(globalMessages.settings), | ||
994 | accelerator: `${settingsShortcutKey()}`, | ||
995 | click: () => { | ||
996 | this.actions.ui.openSettings({ path: 'app' }); | ||
997 | }, | ||
998 | enabled: this.stores.user.isLoggedIn, | ||
999 | visible: !locked, | ||
1000 | }, | ||
1001 | { | ||
1002 | type: 'separator', | ||
1003 | }, | ||
1004 | { | ||
1005 | label: intl.formatMessage(globalMessages.quit), | ||
1006 | accelerator: `${cmdOrCtrlShortcutKey()}+Q`, | ||
1007 | click() { | ||
1008 | app.quit(); | ||
1009 | }, | ||
1010 | }, | ||
1011 | ]; | ||
1012 | |||
1013 | (tpl[tpl.length - 1].submenu as MenuItemConstructorOptions[]).push( | ||
1014 | { | ||
1015 | type: 'separator', | ||
1016 | }, | ||
1017 | about, | ||
1018 | ); | ||
1019 | } | ||
1020 | |||
1021 | if (!locked) { | ||
1022 | if (serviceTpl.length > 0) { | ||
1023 | tpl[3].submenu = serviceTpl; | ||
1024 | } | ||
1025 | |||
1026 | tpl[4].submenu = this.workspacesMenu(); | ||
1027 | |||
1028 | tpl[5].submenu = this.todosMenu(); | ||
1029 | |||
1030 | (tpl[tpl.length - 1].submenu as MenuItemConstructorOptions[]).push( | ||
1031 | { | ||
1032 | type: 'separator', | ||
1033 | }, | ||
1034 | ...this.debugMenu(), | ||
1035 | ); | ||
1036 | } | ||
1037 | this._setCurrentTemplate(tpl); | ||
1038 | const menu = Menu.buildFromTemplate(tpl); | ||
1039 | Menu.setApplicationMenu(menu); | ||
1040 | } | ||
1041 | |||
1042 | serviceTpl(): MenuItemConstructorOptions[] { | ||
1043 | const { intl } = window['ferdium']; | ||
1044 | const { user, services, settings } = this.stores; | ||
1045 | if (!user.isLoggedIn) { | ||
1046 | return []; | ||
1047 | } | ||
1048 | |||
1049 | const cmdAltShortcutsVisibile = !isLinux; | ||
1050 | const menu: MenuItemConstructorOptions[] = []; | ||
1051 | menu.push( | ||
1052 | { | ||
1053 | label: intl.formatMessage(menuItems.addNewService), | ||
1054 | accelerator: `${addNewServiceShortcutKey()}`, | ||
1055 | click: () => { | ||
1056 | this.actions.ui.openSettings({ path: 'recipes' }); | ||
1057 | }, | ||
1058 | }, | ||
1059 | { | ||
1060 | type: 'separator', | ||
1061 | }, | ||
1062 | { | ||
1063 | label: intl.formatMessage(menuItems.activateNextService), | ||
1064 | accelerator: `${cmdOrCtrlShortcutKey()}+tab`, | ||
1065 | click: () => this.actions.service.setActiveNext(), | ||
1066 | visible: !cmdAltShortcutsVisibile, | ||
1067 | }, | ||
1068 | { | ||
1069 | label: intl.formatMessage(menuItems.activateNextService), | ||
1070 | accelerator: `${cmdOrCtrlShortcutKey()}+${altKey()}+right`, | ||
1071 | click: () => this.actions.service.setActiveNext(), | ||
1072 | visible: cmdAltShortcutsVisibile, | ||
1073 | }, | ||
1074 | { | ||
1075 | label: intl.formatMessage(menuItems.activatePreviousService), | ||
1076 | accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+tab`, | ||
1077 | click: () => this.actions.service.setActivePrev(), | ||
1078 | visible: !cmdAltShortcutsVisibile, | ||
1079 | }, | ||
1080 | { | ||
1081 | label: intl.formatMessage(menuItems.activatePreviousService), | ||
1082 | accelerator: `${cmdOrCtrlShortcutKey()}+${altKey()}+left`, | ||
1083 | click: () => this.actions.service.setActivePrev(), | ||
1084 | visible: cmdAltShortcutsVisibile, | ||
1085 | }, | ||
1086 | { | ||
1087 | label: intl | ||
1088 | .formatMessage( | ||
1089 | settings.all.app.isAppMuted | ||
1090 | ? menuItems.unmuteApp | ||
1091 | : menuItems.muteApp, | ||
1092 | ) | ||
1093 | .replace('&', '&&'), | ||
1094 | accelerator: `${muteFerdiumShortcutKey()}`, | ||
1095 | click: () => this.actions.app.toggleMuteApp(), | ||
1096 | }, | ||
1097 | { | ||
1098 | type: 'separator', | ||
1099 | }, | ||
1100 | ); | ||
1101 | |||
1102 | for (const [i, service] of services.allDisplayed.entries()) { | ||
1103 | menu.push({ | ||
1104 | label: this._getServiceName(service), | ||
1105 | accelerator: i < 9 ? `${cmdOrCtrlShortcutKey()}+${i + 1}` : undefined, | ||
1106 | type: 'radio', | ||
1107 | checked: service.isActive, | ||
1108 | click: () => { | ||
1109 | this.actions.service.setActive({ serviceId: service.id }); | ||
1110 | |||
1111 | if (isMac && i === 0) { | ||
1112 | // feat(Mac): Open Window with Cmd+1 | ||
1113 | getCurrentWindow().restore(); | ||
1114 | } | ||
1115 | }, | ||
1116 | }); | ||
1117 | } | ||
1118 | |||
1119 | if ( | ||
1120 | services.active && | ||
1121 | services.active.recipe.id === CUSTOM_WEBSITE_RECIPE_ID | ||
1122 | ) { | ||
1123 | menu.push( | ||
1124 | { | ||
1125 | type: 'separator', | ||
1126 | }, | ||
1127 | { | ||
1128 | label: intl.formatMessage(menuItems.serviceGoHome), | ||
1129 | accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+H`, | ||
1130 | click: () => this.actions.service.reloadActive(), | ||
1131 | }, | ||
1132 | ); | ||
1133 | } | ||
1134 | |||
1135 | return menu; | ||
1136 | } | ||
1137 | |||
1138 | workspacesMenu(): MenuItemConstructorOptions[] { | ||
1139 | const { workspaces, activeWorkspace, isWorkspaceDrawerOpen } = | ||
1140 | workspaceStore; | ||
1141 | const { intl } = window['ferdium']; | ||
1142 | |||
1143 | const menu: MenuItemConstructorOptions[] = []; | ||
1144 | // Add new workspace item: | ||
1145 | menu.push({ | ||
1146 | label: intl.formatMessage(menuItems.addNewWorkspace), | ||
1147 | accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+N`, | ||
1148 | click: () => { | ||
1149 | workspaceActions.openWorkspaceSettings(); | ||
1150 | }, | ||
1151 | enabled: this.stores.user.isLoggedIn, | ||
1152 | }); | ||
1153 | |||
1154 | // Open workspace drawer: | ||
1155 | if (!this.stores.settings.app.alwaysShowWorkspaces) { | ||
1156 | const drawerLabel = isWorkspaceDrawerOpen | ||
1157 | ? menuItems.closeWorkspaceDrawer | ||
1158 | : menuItems.openWorkspaceDrawer; | ||
1159 | menu.push({ | ||
1160 | label: intl.formatMessage(drawerLabel), | ||
1161 | accelerator: `${workspaceToggleShortcutKey()}`, | ||
1162 | click: () => { | ||
1163 | workspaceActions.toggleWorkspaceDrawer(); | ||
1164 | }, | ||
1165 | enabled: this.stores.user.isLoggedIn, | ||
1166 | }); | ||
1167 | } | ||
1168 | |||
1169 | menu.push( | ||
1170 | { | ||
1171 | type: 'separator', | ||
1172 | }, | ||
1173 | { | ||
1174 | label: intl.formatMessage(menuItems.defaultWorkspace), | ||
1175 | accelerator: `${cmdOrCtrlShortcutKey()}+${altKey()}+0`, | ||
1176 | type: 'radio', | ||
1177 | checked: !activeWorkspace, | ||
1178 | click: () => { | ||
1179 | workspaceActions.deactivate(); | ||
1180 | }, | ||
1181 | }, | ||
1182 | ); | ||
1183 | |||
1184 | // Workspace items | ||
1185 | for (const [i, workspace] of workspaces.entries()) { | ||
1186 | menu.push({ | ||
1187 | label: workspace.name, | ||
1188 | accelerator: | ||
1189 | i < 9 ? `${cmdOrCtrlShortcutKey()}+${altKey()}+${i + 1}` : undefined, | ||
1190 | type: 'radio', | ||
1191 | checked: activeWorkspace ? workspace.id === activeWorkspace.id : false, | ||
1192 | click: () => { | ||
1193 | workspaceActions.activate({ workspace }); | ||
1194 | }, | ||
1195 | }); | ||
1196 | } | ||
1197 | |||
1198 | return menu; | ||
1199 | } | ||
1200 | |||
1201 | todosMenu(): MenuItemConstructorOptions[] { | ||
1202 | const { isTodosPanelVisible, isFeatureEnabledByUser } = this.stores.todos; | ||
1203 | const { intl } = window['ferdium']; | ||
1204 | |||
1205 | const menu: MenuItemConstructorOptions[] = []; | ||
1206 | menu.push({ | ||
1207 | label: intl.formatMessage( | ||
1208 | isFeatureEnabledByUser ? menuItems.disableTodos : menuItems.enableTodos, | ||
1209 | ), | ||
1210 | click: () => { | ||
1211 | todoActions.toggleTodosFeatureVisibility(); | ||
1212 | }, | ||
1213 | enabled: this.stores.user.isLoggedIn, | ||
1214 | }); | ||
1215 | |||
1216 | if (isFeatureEnabledByUser) { | ||
1217 | menu.push( | ||
1218 | { | ||
1219 | type: 'separator', | ||
1220 | }, | ||
1221 | { | ||
1222 | label: intl.formatMessage( | ||
1223 | isTodosPanelVisible | ||
1224 | ? menuItems.closeTodosDrawer | ||
1225 | : menuItems.openTodosDrawer, | ||
1226 | ), | ||
1227 | accelerator: `${todosToggleShortcutKey()}`, | ||
1228 | click: () => { | ||
1229 | todoActions.toggleTodosPanel(); | ||
1230 | }, | ||
1231 | enabled: this.stores.user.isLoggedIn, | ||
1232 | }, | ||
1233 | ); | ||
1234 | } | ||
1235 | |||
1236 | return menu; | ||
1237 | } | ||
1238 | |||
1239 | debugMenu(): MenuItemConstructorOptions[] { | ||
1240 | const { intl } = window['ferdium']; | ||
1241 | |||
1242 | return [ | ||
1243 | { | ||
1244 | label: intl.formatMessage(menuItems.debugInfo), | ||
1245 | click: () => { | ||
1246 | const { debugInfo } = this.stores.app; | ||
1247 | |||
1248 | clipboard.write({ | ||
1249 | text: JSON.stringify(debugInfo), | ||
1250 | }); | ||
1251 | |||
1252 | this.actions.app.notify({ | ||
1253 | title: intl.formatMessage(menuItems.debugInfoCopiedHeadline), | ||
1254 | options: { | ||
1255 | body: intl.formatMessage(menuItems.debugInfoCopiedBody), | ||
1256 | }, | ||
1257 | }); | ||
1258 | }, | ||
1259 | }, | ||
1260 | { | ||
1261 | label: intl.formatMessage(menuItems.publishDebugInfo), | ||
1262 | click: () => { | ||
1263 | window['ferdium'].features.publishDebugInfo.state.isModalVisible = | ||
1264 | true; | ||
1265 | }, | ||
1266 | }, | ||
1267 | ]; | ||
1268 | } | ||
1269 | |||
1270 | _getServiceName(service) { | ||
1271 | if (service.name) { | ||
1272 | return service.name; | ||
1273 | } | ||
1274 | |||
1275 | let { name: serviceName } = service.recipe; | ||
1276 | if (service.team) { | ||
1277 | serviceName = `${serviceName} (${service.team})`; | ||
1278 | } else if (service.customUrl) { | ||
1279 | serviceName = `${serviceName} (${service.customUrl})`; | ||
1280 | } | ||
1281 | |||
1282 | return serviceName; | ||
1283 | } | ||
1284 | } | ||
1285 | |||
1286 | export default FranzMenu; | ||