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