aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/Menu.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/Menu.js')
-rw-r--r--src/lib/Menu.js441
1 files changed, 102 insertions, 339 deletions
diff --git a/src/lib/Menu.js b/src/lib/Menu.js
index c60536f0c..e4056e536 100644
--- a/src/lib/Menu.js
+++ b/src/lib/Menu.js
@@ -6,7 +6,7 @@ import { autorun, observable } from 'mobx';
6import { defineMessages } from 'react-intl'; 6import { defineMessages } from 'react-intl';
7import { CUSTOM_WEBSITE_RECIPE_ID, GITHUB_FERDI_URL, LIVE_API_FERDI_WEBSITE } from '../config'; 7import { CUSTOM_WEBSITE_RECIPE_ID, GITHUB_FERDI_URL, LIVE_API_FERDI_WEBSITE } from '../config';
8import { 8import {
9 cmdKey, ctrlKey, isLinux, isMac, aboutAppDetails, termsBase, 9 shortcutKey, altKey, shiftKey, settingsShortcutKey, isLinux, isMac, aboutAppDetails, lockFerdiShortcutKey, todosToggleShortcutKey, workspaceToggleShortcutKey, addNewServiceShortcutKey, muteFerdiShortcutKey,
10} from '../environment'; 10} from '../environment';
11import { announcementsStore } from '../features/announcements'; 11import { announcementsStore } from '../features/announcements';
12import { announcementActions } from '../features/announcements/actions'; 12import { announcementActions } from '../features/announcements/actions';
@@ -14,6 +14,7 @@ import { todosStore } from '../features/todos';
14import { todoActions } from '../features/todos/actions'; 14import { todoActions } from '../features/todos/actions';
15import { workspaceActions } from '../features/workspaces/actions'; 15import { workspaceActions } from '../features/workspaces/actions';
16import { workspaceStore } from '../features/workspaces/index'; 16import { workspaceStore } from '../features/workspaces/index';
17import apiBase, { termsBase } from '../api/apiBase';
17 18
18const menuItems = defineMessages({ 19const menuItems = defineMessages({
19 edit: { 20 edit: {
@@ -100,14 +101,6 @@ const menuItems = defineMessages({
100 id: 'menu.view.zoomOut', 101 id: 'menu.view.zoomOut',
101 defaultMessage: '!!!Zoom Out', 102 defaultMessage: '!!!Zoom Out',
102 }, 103 },
103 enterFullScreen: {
104 id: 'menu.view.enterFullScreen',
105 defaultMessage: '!!!Enter Full Screen',
106 },
107 exitFullScreen: {
108 id: 'menu.view.exitFullScreen',
109 defaultMessage: '!!!Exit Full Screen',
110 },
111 toggleFullScreen: { 104 toggleFullScreen: {
112 id: 'menu.view.toggleFullScreen', 105 id: 'menu.view.toggleFullScreen',
113 defaultMessage: '!!!Toggle Full Screen', 106 defaultMessage: '!!!Toggle Full Screen',
@@ -132,8 +125,8 @@ const menuItems = defineMessages({
132 id: 'menu.view.reloadService', 125 id: 'menu.view.reloadService',
133 defaultMessage: '!!!Reload Service', 126 defaultMessage: '!!!Reload Service',
134 }, 127 },
135 reloadFranz: { 128 reloadFerdi: {
136 id: 'menu.view.reloadFranz', 129 id: 'menu.view.reloadFerdi',
137 defaultMessage: '!!!Reload Ferdi', 130 defaultMessage: '!!!Reload Ferdi',
138 }, 131 },
139 lockFerdi: { 132 lockFerdi: {
@@ -160,6 +153,10 @@ const menuItems = defineMessages({
160 id: 'menu.help.changelog', 153 id: 'menu.help.changelog',
161 defaultMessage: '!!!Changelog', 154 defaultMessage: '!!!Changelog',
162 }, 155 },
156 importExportData: {
157 id: 'menu.help.importExportData',
158 defaultMessage: '!!!Import/Export Configuration Data',
159 },
163 support: { 160 support: {
164 id: 'menu.help.support', 161 id: 'menu.help.support',
165 defaultMessage: '!!!Support', 162 defaultMessage: '!!!Support',
@@ -318,9 +315,10 @@ function getActiveWebview() {
318 return window.ferdi.stores.services.active.webview; 315 return window.ferdi.stores.services.active.webview;
319} 316}
320 317
321const _templateFactory = (intl, locked) => [ 318const _titleBarTemplateFactory = (intl, locked) => [
322 { 319 {
323 label: intl.formatMessage(menuItems.edit), 320 label: intl.formatMessage(menuItems.edit),
321 accelerator: `${altKey}+E`,
324 submenu: [ 322 submenu: [
325 { 323 {
326 label: intl.formatMessage(menuItems.undo), 324 label: intl.formatMessage(menuItems.undo),
@@ -335,23 +333,23 @@ const _templateFactory = (intl, locked) => [
335 }, 333 },
336 { 334 {
337 label: intl.formatMessage(menuItems.cut), 335 label: intl.formatMessage(menuItems.cut),
338 accelerator: 'Cmd+X', 336 accelerator: `${shortcutKey()}+X`,
339 selector: 'cut:', 337 role: 'cut',
340 }, 338 },
341 { 339 {
342 label: intl.formatMessage(menuItems.copy), 340 label: intl.formatMessage(menuItems.copy),
343 accelerator: 'Cmd+C', 341 accelerator: `${shortcutKey()}+C`,
344 selector: 'copy:', 342 role: 'copy',
345 }, 343 },
346 { 344 {
347 label: intl.formatMessage(menuItems.paste), 345 label: intl.formatMessage(menuItems.paste),
348 accelerator: 'Cmd+V', 346 accelerator: `${shortcutKey()}+V`,
349 selector: 'paste:', 347 role: 'paste',
350 }, 348 },
351 { 349 {
352 label: intl.formatMessage(menuItems.pasteAndMatchStyle), 350 label: intl.formatMessage(menuItems.pasteAndMatchStyle),
353 accelerator: 'Cmd+Shift+V', 351 accelerator: `${shortcutKey()}+${shiftKey}+V`, // Override the accelerator since this adds new key combo in macos
354 selector: 'pasteAndMatchStyle:', 352 role: 'pasteAndMatchStyle',
355 click() { 353 click() {
356 getActiveWebview().pasteAndMatchStyle(); 354 getActiveWebview().pasteAndMatchStyle();
357 }, 355 },
@@ -362,13 +360,14 @@ const _templateFactory = (intl, locked) => [
362 }, 360 },
363 { 361 {
364 label: intl.formatMessage(menuItems.selectAll), 362 label: intl.formatMessage(menuItems.selectAll),
365 accelerator: 'Cmd+A', 363 accelerator: `${shortcutKey()}+A`,
366 selector: 'selectAll:', 364 role: 'selectall',
367 }, 365 },
368 ], 366 ],
369 }, 367 },
370 { 368 {
371 label: intl.formatMessage(menuItems.view), 369 label: intl.formatMessage(menuItems.view),
370 accelerator: `${altKey}+V`,
372 visible: !locked, 371 visible: !locked,
373 submenu: [ 372 submenu: [
374 { 373 {
@@ -376,7 +375,7 @@ const _templateFactory = (intl, locked) => [
376 }, 375 },
377 { 376 {
378 label: intl.formatMessage(menuItems.openQuickSwitch), 377 label: intl.formatMessage(menuItems.openQuickSwitch),
379 accelerator: 'CmdOrCtrl+S', 378 accelerator: `${shortcutKey()}+S`,
380 click() { 379 click() {
381 window.ferdi.features.quickSwitch.state.isModalVisible = true; 380 window.ferdi.features.quickSwitch.state.isModalVisible = true;
382 }, 381 },
@@ -386,7 +385,7 @@ const _templateFactory = (intl, locked) => [
386 }, 385 },
387 { 386 {
388 label: intl.formatMessage(menuItems.findInPage), 387 label: intl.formatMessage(menuItems.findInPage),
389 accelerator: 'CmdOrCtrl+F', 388 accelerator: `${shortcutKey()}+F`,
390 click() { 389 click() {
391 // Check if there is a service active 390 // Check if there is a service active
392 if (!window.ferdi.stores.services.active) return; 391 if (!window.ferdi.stores.services.active) return;
@@ -407,18 +406,16 @@ const _templateFactory = (intl, locked) => [
407 }, 406 },
408 { 407 {
409 label: intl.formatMessage(menuItems.back), 408 label: intl.formatMessage(menuItems.back),
410 accelerator: 'CmdOrCtrl+Left', 409 accelerator: `${shortcutKey()}+Left`,
411 click() { 410 click() {
412 const activeService = getActiveWebview(); 411 getActiveWebview().goBack();
413 activeService.goBack();
414 }, 412 },
415 }, 413 },
416 { 414 {
417 label: intl.formatMessage(menuItems.forward), 415 label: intl.formatMessage(menuItems.forward),
418 accelerator: 'CmdOrCtrl+Right', 416 accelerator: `${shortcutKey()}+Right`,
419 click() { 417 click() {
420 const activeService = getActiveWebview(); 418 getActiveWebview().goForward();
421 activeService.goForward();
422 }, 419 },
423 }, 420 },
424 { 421 {
@@ -426,14 +423,16 @@ const _templateFactory = (intl, locked) => [
426 }, 423 },
427 { 424 {
428 label: intl.formatMessage(menuItems.resetZoom), 425 label: intl.formatMessage(menuItems.resetZoom),
429 accelerator: 'Cmd+0', 426 accelerator: `${shortcutKey()}+0`,
427 role: 'resetZoom',
430 click() { 428 click() {
431 getActiveWebview().setZoomLevel(0); 429 getActiveWebview().setZoomLevel(0);
432 }, 430 },
433 }, 431 },
434 { 432 {
435 label: intl.formatMessage(menuItems.zoomIn), 433 label: intl.formatMessage(menuItems.zoomIn),
436 accelerator: 'Cmd+plus', 434 accelerator: `${shortcutKey()}+plus`,
435 role: 'zoomIn',
437 click() { 436 click() {
438 const activeService = getActiveWebview(); 437 const activeService = getActiveWebview();
439 const level = activeService.getZoomLevel(); 438 const level = activeService.getZoomLevel();
@@ -444,7 +443,8 @@ const _templateFactory = (intl, locked) => [
444 }, 443 },
445 { 444 {
446 label: intl.formatMessage(menuItems.zoomOut), 445 label: intl.formatMessage(menuItems.zoomOut),
447 accelerator: 'Cmd+-', 446 accelerator: `${shortcutKey()}+-`,
447 role: 'zoomOut',
448 click() { 448 click() {
449 const activeService = getActiveWebview(); 449 const activeService = getActiveWebview();
450 const level = activeService.getZoomLevel(); 450 const level = activeService.getZoomLevel();
@@ -457,15 +457,13 @@ const _templateFactory = (intl, locked) => [
457 type: 'separator', 457 type: 'separator',
458 }, 458 },
459 { 459 {
460 label: app.mainWindow.isFullScreen() // label doesn't work, gets overridden by Electron 460 label: intl.formatMessage(menuItems.toggleFullScreen),
461 ? intl.formatMessage(menuItems.exitFullScreen) 461 role: 'toggleFullScreen',
462 : intl.formatMessage(menuItems.enterFullScreen),
463 role: 'togglefullscreen',
464 }, 462 },
465 { 463 {
466 label: intl.formatMessage(menuItems.toggleDarkMode), 464 label: intl.formatMessage(menuItems.toggleDarkMode),
467 type: 'checkbox', 465 type: 'checkbox',
468 accelerator: `${cmdKey}+Shift+D`, 466 accelerator: `${shortcutKey()}+${shiftKey}+D`,
469 checked: window.ferdi.stores.settings.app.darkMode, 467 checked: window.ferdi.stores.settings.app.darkMode,
470 click: () => { 468 click: () => {
471 window.ferdi.actions.settings.update({ 469 window.ferdi.actions.settings.update({
@@ -480,11 +478,13 @@ const _templateFactory = (intl, locked) => [
480 }, 478 },
481 { 479 {
482 label: intl.formatMessage(menuItems.services), 480 label: intl.formatMessage(menuItems.services),
481 accelerator: `${altKey}+S`,
483 visible: !locked, 482 visible: !locked,
484 submenu: [], 483 submenu: [],
485 }, 484 },
486 { 485 {
487 label: intl.formatMessage(menuItems.workspaces), 486 label: intl.formatMessage(menuItems.workspaces),
487 accelerator: `${altKey}+W`,
488 submenu: [], 488 submenu: [],
489 visible: !locked && workspaceStore.isFeatureEnabled, 489 visible: !locked && workspaceStore.isFeatureEnabled,
490 }, 490 },
@@ -509,6 +509,7 @@ const _templateFactory = (intl, locked) => [
509 }, 509 },
510 { 510 {
511 label: intl.formatMessage(menuItems.help), 511 label: intl.formatMessage(menuItems.help),
512 accelerator: `${altKey}+H`,
512 role: 'help', 513 role: 'help',
513 submenu: [ 514 submenu: [
514 { 515 {
@@ -516,274 +517,23 @@ const _templateFactory = (intl, locked) => [
516 click() { shell.openExternal(LIVE_API_FERDI_WEBSITE); }, 517 click() { shell.openExternal(LIVE_API_FERDI_WEBSITE); },
517 }, 518 },
518 { 519 {
519 label: intl.formatMessage(menuItems.announcement), 520 label: intl.formatMessage(menuItems.changelog),
520 click: () => { 521 click() { shell.openExternal(`${GITHUB_FERDI_URL}/ferdi/blob/master/CHANGELOG.md`); },
521 announcementActions.show();
522 },
523 visible: !locked && window.ferdi.stores.user.isLoggedIn && announcementsStore.areNewsAvailable,
524 },
525 {
526 type: 'separator',
527 },
528 {
529 label: intl.formatMessage(menuItems.support),
530 click() { shell.openExternal(`${LIVE_API_FERDI_WEBSITE}/contact`); },
531 },
532 {
533 type: 'separator',
534 },
535 {
536 label: intl.formatMessage(menuItems.tos),
537 click() { shell.openExternal(`${termsBase()}/terms`); },
538 },
539 {
540 label: intl.formatMessage(menuItems.privacy),
541 click() { shell.openExternal(`${termsBase()}/privacy`); },
542 },
543 ],
544 },
545];
546
547const _titleBarTemplateFactory = (intl, locked) => [
548 {
549 label: intl.formatMessage(menuItems.edit),
550 accelerator: 'Alt+E',
551 submenu: [
552 {
553 label: intl.formatMessage(menuItems.undo),
554 accelerator: `${ctrlKey}+Z`,
555 click() {
556 getActiveWebview().undo();
557 },
558 },
559 {
560 label: intl.formatMessage(menuItems.redo),
561 accelerator: `${ctrlKey}+Y`,
562 click() {
563 getActiveWebview().redo();
564 },
565 },
566 {
567 type: 'separator',
568 },
569 {
570 label: intl.formatMessage(menuItems.cut),
571 accelerator: `${ctrlKey}+X`,
572 click() {
573 getActiveWebview().cut();
574 },
575 },
576 {
577 label: intl.formatMessage(menuItems.copy),
578 accelerator: `${ctrlKey}+C`,
579 click() {
580 getActiveWebview().copy();
581 },
582 },
583 {
584 label: intl.formatMessage(menuItems.paste),
585 accelerator: `${ctrlKey}+V`,
586 click() {
587 getActiveWebview().paste();
588 },
589 },
590 {
591 label: intl.formatMessage(menuItems.pasteAndMatchStyle),
592 accelerator: `${ctrlKey}+Shift+V`,
593 click() {
594 getActiveWebview().pasteAndMatchStyle();
595 },
596 },
597 {
598 label: intl.formatMessage(menuItems.delete),
599 click() {
600 getActiveWebview().delete();
601 },
602 },
603 {
604 label: intl.formatMessage(menuItems.selectAll),
605 accelerator: `${ctrlKey}+A`,
606 click() {
607 getActiveWebview().selectAll();
608 },
609 },
610 ],
611 },
612 {
613 label: intl.formatMessage(menuItems.view),
614 accelerator: 'Alt+V',
615 visible: !locked,
616 submenu: [
617 {
618 type: 'separator',
619 },
620 {
621 label: intl.formatMessage(menuItems.openQuickSwitch),
622 accelerator: 'CmdOrCtrl+S',
623 click() {
624 window.ferdi.features.quickSwitch.state.isModalVisible = true;
625 },
626 },
627 {
628 type: 'separator',
629 },
630 {
631 label: intl.formatMessage(menuItems.findInPage),
632 accelerator: 'CmdOrCtrl+F',
633 click() {
634 // Check if there is a service active
635 if (!window.ferdi.stores.services.active) return;
636
637 // Focus webview so find in page popup gets focused
638 window.ferdi.stores.services.active.webview.focus();
639
640 const currentService = window.ferdi.stores.services.active.id;
641 window.ferdi.actions.service.sendIPCMessage({
642 serviceId: currentService,
643 channel: 'find-in-page',
644 args: {},
645 });
646 },
647 },
648 {
649 type: 'separator',
650 },
651 {
652 label: intl.formatMessage(menuItems.back),
653 accelerator: 'CmdOrCtrl+Left',
654 click() {
655 const activeService = getActiveWebview();
656 activeService.goBack();
657 },
658 },
659 {
660 label: intl.formatMessage(menuItems.forward),
661 accelerator: 'CmdOrCtrl+Right',
662 click() {
663 const activeService = getActiveWebview();
664 activeService.goForward();
665 },
666 },
667 {
668 type: 'separator',
669 },
670 {
671 label: intl.formatMessage(menuItems.resetZoom),
672 accelerator: `${ctrlKey}+0`,
673 click() {
674 getActiveWebview().setZoomLevel(0);
675 },
676 },
677 {
678 label: intl.formatMessage(menuItems.zoomIn),
679 accelerator: `${ctrlKey}+=`,
680 click() {
681 const activeService = getActiveWebview();
682 const level = activeService.getZoomLevel();
683
684 // level 9 =~ +300% and setZoomLevel wouldnt zoom in further
685 if (level < 9) activeService.setZoomLevel(level + 1);
686 },
687 }, 522 },
688 { 523 {
689 label: intl.formatMessage(menuItems.zoomOut), 524 label: intl.formatMessage(menuItems.importExportData),
690 accelerator: `${ctrlKey}+-`, 525 click() { shell.openExternal(apiBase(false)); },
691 click() { 526 enabled: !locked,
692 const activeService = getActiveWebview();
693 const level = activeService.getZoomLevel();
694
695 // level -9 =~ -50% and setZoomLevel wouldnt zoom out further
696 if (level > -9) activeService.setZoomLevel(level - 1);
697 },
698 }, 527 },
699 { 528 {
700 type: 'separator', 529 type: 'separator',
701 }, 530 },
702 { 531 {
703 label: app.mainWindow.isFullScreen() // label doesn't work, gets overridden by Electron 532 label: intl.formatMessage(menuItems.announcement),
704 ? intl.formatMessage(menuItems.exitFullScreen)
705 : intl.formatMessage(menuItems.enterFullScreen),
706 accelerator: 'F11',
707 click(menuItem, browserWindow) {
708 browserWindow.setFullScreen(!browserWindow.isFullScreen());
709 },
710 },
711 {
712 label: intl.formatMessage(menuItems.toggleDarkMode),
713 type: 'checkbox',
714 accelerator: `${cmdKey}+Shift+D`,
715 checked: window.ferdi.stores.settings.app.darkMode,
716 click: () => {
717 window.ferdi.actions.settings.update({
718 type: 'app',
719 data: {
720 darkMode: !window.ferdi.stores.settings.app.darkMode,
721 },
722 });
723 },
724 },
725 {
726 label: intl.formatMessage(menuItems.autohideMenuBar),
727 type: 'checkbox',
728 checked: window.ferdi.stores.settings.app.autohideMenuBar,
729 click: () => { 533 click: () => {
730 window.ferdi.actions.settings.update({ 534 announcementActions.show();
731 type: 'app',
732 data: {
733 autohideMenuBar: !window.ferdi.stores.settings.app.autohideMenuBar,
734 },
735 });
736 },
737 },
738 ],
739 },
740 {
741 label: intl.formatMessage(menuItems.services),
742 accelerator: 'Alt+S',
743 visible: !locked,
744 submenu: [],
745 },
746 {
747 label: intl.formatMessage(menuItems.workspaces),
748 accelerator: 'Alt+W',
749 submenu: [],
750 visible: !locked && workspaceStore.isFeatureEnabled,
751 },
752 {
753 label: intl.formatMessage(menuItems.todos),
754 submenu: [],
755 visible: !locked && todosStore.isFeatureEnabled,
756 },
757 {
758 label: intl.formatMessage(menuItems.window),
759 submenu: [
760 {
761 label: intl.formatMessage(menuItems.minimize),
762 accelerator: 'Ctrl+M',
763 click(menuItem, browserWindow) {
764 browserWindow.minimize();
765 }, 535 },
766 }, 536 enabled: !locked && window.ferdi.stores.user.isLoggedIn && announcementsStore.areNewsAvailable,
767 {
768 label: intl.formatMessage(menuItems.close),
769 accelerator: 'Ctrl+W',
770 click(menuItem, browserWindow) {
771 browserWindow.close();
772 },
773 },
774 ],
775 },
776 {
777 label: '?',
778 accelerator: 'Alt+?',
779 submenu: [
780 {
781 label: intl.formatMessage(menuItems.learnMore),
782 click() { shell.openExternal(LIVE_API_FERDI_WEBSITE); },
783 },
784 {
785 label: intl.formatMessage(menuItems.changelog),
786 click() { shell.openExternal(`${GITHUB_FERDI_URL}/ferdi/blob/master/CHANGELOG.md`); },
787 }, 537 },
788 { 538 {
789 type: 'separator', 539 type: 'separator',
@@ -831,30 +581,44 @@ export default class FranzMenu {
831 // need to clone object so we don't modify computed (cached) object 581 // need to clone object so we don't modify computed (cached) object
832 const serviceTpl = Object.assign([], this.serviceTpl()); 582 const serviceTpl = Object.assign([], this.serviceTpl());
833 583
834 // Don't initialize when window.franz is undefined or when we are on a payment window route 584 // Don't initialize when window.ferdi is undefined
835 if (window.ferdi === undefined || this.stores.router.location.pathname.startsWith('/payment/')) { 585 if (window.ferdi === undefined) {
836 console.log('skipping menu init'); 586 console.log('skipping menu init');
837 return; 587 return;
838 } 588 }
839 589
840 const { intl } = window.ferdi; 590 const { intl } = window.ferdi;
841 const tpl = isMac 591 const tpl = _titleBarTemplateFactory(intl, this.stores.settings.app.locked);
842 ? _templateFactory(intl, this.stores.settings.app.locked)
843 : _titleBarTemplateFactory(intl, this.stores.settings.app.locked);
844 const { actions } = this; 592 const { actions } = this;
845 593
594 if (!isMac) {
595 tpl[1].submenu.push({
596 label: intl.formatMessage(menuItems.autohideMenuBar),
597 type: 'checkbox',
598 checked: window.ferdi.stores.settings.app.autohideMenuBar,
599 click: () => {
600 window.ferdi.actions.settings.update({
601 type: 'app',
602 data: {
603 autohideMenuBar: !window.ferdi.stores.settings.app.autohideMenuBar,
604 },
605 });
606 },
607 });
608 }
609
846 if (!this.stores.settings.app.locked) { 610 if (!this.stores.settings.app.locked) {
847 tpl[1].submenu.push({ 611 tpl[1].submenu.push({
848 type: 'separator', 612 type: 'separator',
849 }, { 613 }, {
850 label: intl.formatMessage(menuItems.toggleDevTools), 614 label: intl.formatMessage(menuItems.toggleDevTools),
851 accelerator: `${cmdKey}+Alt+I`, 615 accelerator: `${shortcutKey()}+${altKey}+I`,
852 click: (menuItem, browserWindow) => { 616 click: (menuItem, browserWindow) => {
853 browserWindow.webContents.toggleDevTools(); 617 browserWindow.webContents.toggleDevTools();
854 }, 618 },
855 }, { 619 }, {
856 label: intl.formatMessage(menuItems.toggleServiceDevTools), 620 label: intl.formatMessage(menuItems.toggleServiceDevTools),
857 accelerator: `${cmdKey}+Shift+Alt+I`, 621 accelerator: `${shortcutKey()}+${shiftKey}+${altKey}+I`,
858 click: () => { 622 click: () => {
859 this.actions.service.openDevToolsForActiveService(); 623 this.actions.service.openDevToolsForActiveService();
860 }, 624 },
@@ -864,7 +628,7 @@ export default class FranzMenu {
864 if (this.stores.features.features.isTodosEnabled) { 628 if (this.stores.features.features.isTodosEnabled) {
865 tpl[1].submenu.push({ 629 tpl[1].submenu.push({
866 label: intl.formatMessage(menuItems.toggleTodosDevTools), 630 label: intl.formatMessage(menuItems.toggleTodosDevTools),
867 accelerator: `${cmdKey}+Shift+Alt+O`, 631 accelerator: `${shortcutKey()}+${shiftKey}+${altKey}+O`,
868 click: () => { 632 click: () => {
869 const webview = document.querySelector('#todos-panel webview'); 633 const webview = document.querySelector('#todos-panel webview');
870 if (webview) this.actions.todos.openDevTools(); 634 if (webview) this.actions.todos.openDevTools();
@@ -875,7 +639,7 @@ export default class FranzMenu {
875 tpl[1].submenu.unshift({ 639 tpl[1].submenu.unshift({
876 label: intl.formatMessage(menuItems.reloadService), 640 label: intl.formatMessage(menuItems.reloadService),
877 id: 'reloadService', // TODO: needed? 641 id: 'reloadService', // TODO: needed?
878 accelerator: `${cmdKey}+R`, 642 accelerator: `${shortcutKey()}+R`,
879 click: () => { 643 click: () => {
880 if (this.stores.user.isLoggedIn 644 if (this.stores.user.isLoggedIn
881 && this.stores.services.enabled.length > 0) { 645 && this.stores.services.enabled.length > 0) {
@@ -889,14 +653,14 @@ export default class FranzMenu {
889 } 653 }
890 }, 654 },
891 }, { 655 }, {
892 label: intl.formatMessage(menuItems.reloadFranz), 656 label: intl.formatMessage(menuItems.reloadFerdi),
893 accelerator: `${cmdKey}+Shift+R`, 657 accelerator: `${shortcutKey()}+${shiftKey}+R`,
894 click: () => { 658 click: () => {
895 window.location.reload(); 659 window.location.reload();
896 }, 660 },
897 }, { 661 }, {
898 label: intl.formatMessage(menuItems.reloadTodos), 662 label: intl.formatMessage(menuItems.reloadTodos),
899 accelerator: `${cmdKey}+Shift+Alt+R`, 663 accelerator: `${shortcutKey()}+${shiftKey}+${altKey}+R`,
900 click: () => { 664 click: () => {
901 this.actions.todos.reload(); 665 this.actions.todos.reload();
902 }, 666 },
@@ -904,7 +668,7 @@ export default class FranzMenu {
904 type: 'separator', 668 type: 'separator',
905 }, { 669 }, {
906 label: intl.formatMessage(menuItems.lockFerdi), 670 label: intl.formatMessage(menuItems.lockFerdi),
907 accelerator: 'CmdOrCtrl+Shift+L', 671 accelerator: `${lockFerdiShortcutKey()}`,
908 enabled: this.stores.user.isLoggedIn && this.stores.settings.app.lockingFeatureEnabled, 672 enabled: this.stores.user.isLoggedIn && this.stores.settings.app.lockingFeatureEnabled,
909 click() { 673 click() {
910 actions.settings.update({ 674 actions.settings.update({
@@ -932,7 +696,7 @@ export default class FranzMenu {
932 696
933 tpl[0].submenu.unshift({ 697 tpl[0].submenu.unshift({
934 label: intl.formatMessage(menuItems.touchId), 698 label: intl.formatMessage(menuItems.touchId),
935 accelerator: 'CmdOrCtrl+Shift+L', 699 accelerator: `${lockFerdiShortcutKey()}`,
936 visible: touchIdEnabled, 700 visible: touchIdEnabled,
937 click() { 701 click() {
938 systemPreferences.promptTouchID(intl.formatMessage(menuItems.touchIdPrompt)).then(() => { 702 systemPreferences.promptTouchID(intl.formatMessage(menuItems.touchIdPrompt)).then(() => {
@@ -952,7 +716,7 @@ export default class FranzMenu {
952 716
953 tpl.unshift({ 717 tpl.unshift({
954 label: isMac ? app.name : intl.formatMessage(menuItems.file), 718 label: isMac ? app.name : intl.formatMessage(menuItems.file),
955 accelerator: 'Alt+F', 719 accelerator: `${altKey}+F`,
956 submenu: [ 720 submenu: [
957 { 721 {
958 label: intl.formatMessage(menuItems.about), 722 label: intl.formatMessage(menuItems.about),
@@ -963,7 +727,7 @@ export default class FranzMenu {
963 }, 727 },
964 { 728 {
965 label: intl.formatMessage(menuItems.settings), 729 label: intl.formatMessage(menuItems.settings),
966 accelerator: 'CmdOrCtrl+,', 730 accelerator: `${settingsShortcutKey()}`,
967 click: () => { 731 click: () => {
968 this.actions.ui.openSettings({ path: 'app' }); 732 this.actions.ui.openSettings({ path: 'app' });
969 }, 733 },
@@ -995,7 +759,7 @@ export default class FranzMenu {
995 }, 759 },
996 { 760 {
997 label: intl.formatMessage(menuItems.hideOthers), 761 label: intl.formatMessage(menuItems.hideOthers),
998 role: 'hideothers', 762 role: 'hideOthers',
999 }, 763 },
1000 { 764 {
1001 label: intl.formatMessage(menuItems.unhide), 765 label: intl.formatMessage(menuItems.unhide),
@@ -1016,6 +780,7 @@ export default class FranzMenu {
1016 780
1017 const about = { 781 const about = {
1018 label: intl.formatMessage(menuItems.about), 782 label: intl.formatMessage(menuItems.about),
783 role: 'about',
1019 click: () => { 784 click: () => {
1020 dialog.showMessageBox({ 785 dialog.showMessageBox({
1021 type: 'info', 786 type: 'info',
@@ -1054,7 +819,7 @@ export default class FranzMenu {
1054 tpl[0].submenu = [ 819 tpl[0].submenu = [
1055 { 820 {
1056 label: intl.formatMessage(menuItems.settings), 821 label: intl.formatMessage(menuItems.settings),
1057 accelerator: 'Ctrl+P', 822 accelerator: `${settingsShortcutKey()}`,
1058 click: () => { 823 click: () => {
1059 this.actions.ui.openSettings({ path: 'app' }); 824 this.actions.ui.openSettings({ path: 'app' });
1060 }, 825 },
@@ -1067,7 +832,7 @@ export default class FranzMenu {
1067 { 832 {
1068 label: intl.formatMessage(menuItems.quit), 833 label: intl.formatMessage(menuItems.quit),
1069 role: 'quit', 834 role: 'quit',
1070 accelerator: 'Ctrl+Q', 835 accelerator: `${shortcutKey()}+Q`,
1071 click() { 836 click() {
1072 app.quit(); 837 app.quit();
1073 }, 838 },
@@ -1110,7 +875,7 @@ export default class FranzMenu {
1110 875
1111 menu.push({ 876 menu.push({
1112 label: intl.formatMessage(menuItems.addNewService), 877 label: intl.formatMessage(menuItems.addNewService),
1113 accelerator: `${cmdKey}+N`, 878 accelerator: `${addNewServiceShortcutKey()}`,
1114 click: () => { 879 click: () => {
1115 this.actions.ui.openSettings({ path: 'recipes' }); 880 this.actions.ui.openSettings({ path: 'recipes' });
1116 }, 881 },
@@ -1118,29 +883,29 @@ export default class FranzMenu {
1118 type: 'separator', 883 type: 'separator',
1119 }, { 884 }, {
1120 label: intl.formatMessage(menuItems.activateNextService), 885 label: intl.formatMessage(menuItems.activateNextService),
1121 accelerator: `${cmdKey}+tab`, 886 accelerator: `${shortcutKey()}+tab`,
1122 click: () => this.actions.service.setActiveNext(), 887 click: () => this.actions.service.setActiveNext(),
1123 visible: !cmdAltShortcutsVisibile, 888 visible: !cmdAltShortcutsVisibile,
1124 }, { 889 }, {
1125 label: intl.formatMessage(menuItems.activateNextService), 890 label: intl.formatMessage(menuItems.activateNextService),
1126 accelerator: `${cmdKey}+alt+right`, 891 accelerator: `${shortcutKey()}+${altKey}+right`,
1127 click: () => this.actions.service.setActiveNext(), 892 click: () => this.actions.service.setActiveNext(),
1128 visible: cmdAltShortcutsVisibile, 893 visible: cmdAltShortcutsVisibile,
1129 }, { 894 }, {
1130 label: intl.formatMessage(menuItems.activatePreviousService), 895 label: intl.formatMessage(menuItems.activatePreviousService),
1131 accelerator: `${cmdKey}+shift+tab`, 896 accelerator: `${shortcutKey()}+${shiftKey}+tab`,
1132 click: () => this.actions.service.setActivePrev(), 897 click: () => this.actions.service.setActivePrev(),
1133 visible: !cmdAltShortcutsVisibile, 898 visible: !cmdAltShortcutsVisibile,
1134 }, { 899 }, {
1135 label: intl.formatMessage(menuItems.activatePreviousService), 900 label: intl.formatMessage(menuItems.activatePreviousService),
1136 accelerator: `${cmdKey}+alt+left`, 901 accelerator: `${shortcutKey()}+${altKey}+left`,
1137 click: () => this.actions.service.setActivePrev(), 902 click: () => this.actions.service.setActivePrev(),
1138 visible: cmdAltShortcutsVisibile, 903 visible: cmdAltShortcutsVisibile,
1139 }, { 904 }, {
1140 label: intl.formatMessage( 905 label: intl.formatMessage(
1141 settings.all.app.isAppMuted ? menuItems.unmuteApp : menuItems.muteApp, 906 settings.all.app.isAppMuted ? menuItems.unmuteApp : menuItems.muteApp,
1142 ).replace('&', '&&'), 907 ).replace('&', '&&'),
1143 accelerator: `${cmdKey}+shift+m`, 908 accelerator: `${muteFerdiShortcutKey()}`,
1144 click: () => this.actions.app.toggleMuteApp(), 909 click: () => this.actions.app.toggleMuteApp(),
1145 }, { 910 }, {
1146 type: 'separator', 911 type: 'separator',
@@ -1148,7 +913,7 @@ export default class FranzMenu {
1148 913
1149 services.allDisplayed.forEach((service, i) => (menu.push({ 914 services.allDisplayed.forEach((service, i) => (menu.push({
1150 label: this._getServiceName(service), 915 label: this._getServiceName(service),
1151 accelerator: i < 9 ? `${cmdKey}+${i + 1}` : null, 916 accelerator: i < 9 ? `${shortcutKey()}+${i + 1}` : null,
1152 type: 'radio', 917 type: 'radio',
1153 checked: service.isActive, 918 checked: service.isActive,
1154 click: () => { 919 click: () => {
@@ -1165,7 +930,7 @@ export default class FranzMenu {
1165 type: 'separator', 930 type: 'separator',
1166 }, { 931 }, {
1167 label: intl.formatMessage(menuItems.serviceGoHome), 932 label: intl.formatMessage(menuItems.serviceGoHome),
1168 accelerator: `${cmdKey}+shift+H`, 933 accelerator: `${shortcutKey()}+${shiftKey}+H`,
1169 click: () => this.actions.service.reloadActive(), 934 click: () => this.actions.service.reloadActive(),
1170 }); 935 });
1171 } 936 }
@@ -1181,7 +946,7 @@ export default class FranzMenu {
1181 // Add new workspace item: 946 // Add new workspace item:
1182 menu.push({ 947 menu.push({
1183 label: intl.formatMessage(menuItems.addNewWorkspace), 948 label: intl.formatMessage(menuItems.addNewWorkspace),
1184 accelerator: `${cmdKey}+Shift+N`, 949 accelerator: `${shortcutKey()}+${shiftKey}+N`,
1185 click: () => { 950 click: () => {
1186 workspaceActions.openWorkspaceSettings(); 951 workspaceActions.openWorkspaceSettings();
1187 }, 952 },
@@ -1195,7 +960,7 @@ export default class FranzMenu {
1195 ); 960 );
1196 menu.push({ 961 menu.push({
1197 label: intl.formatMessage(drawerLabel), 962 label: intl.formatMessage(drawerLabel),
1198 accelerator: `${cmdKey}+D`, 963 accelerator: `${workspaceToggleShortcutKey()}`,
1199 click: () => { 964 click: () => {
1200 workspaceActions.toggleWorkspaceDrawer(); 965 workspaceActions.toggleWorkspaceDrawer();
1201 }, 966 },
@@ -1210,7 +975,7 @@ export default class FranzMenu {
1210 // Default workspace 975 // Default workspace
1211 menu.push({ 976 menu.push({
1212 label: intl.formatMessage(menuItems.defaultWorkspace), 977 label: intl.formatMessage(menuItems.defaultWorkspace),
1213 accelerator: `${cmdKey}+Alt+0`, 978 accelerator: `${shortcutKey()}+${altKey}+0`,
1214 type: 'radio', 979 type: 'radio',
1215 checked: !activeWorkspace, 980 checked: !activeWorkspace,
1216 click: () => { 981 click: () => {
@@ -1219,17 +984,15 @@ export default class FranzMenu {
1219 }); 984 });
1220 985
1221 // Workspace items 986 // Workspace items
1222 if (this.stores.user.isPremium) { 987 workspaces.forEach((workspace, i) => menu.push({
1223 workspaces.forEach((workspace, i) => menu.push({ 988 label: workspace.name,
1224 label: workspace.name, 989 accelerator: i < 9 ? `${shortcutKey()}+${altKey}+${i + 1}` : null,
1225 accelerator: i < 9 ? `${cmdKey}+Alt+${i + 1}` : null, 990 type: 'radio',
1226 type: 'radio', 991 checked: activeWorkspace ? workspace.id === activeWorkspace.id : false,
1227 checked: activeWorkspace ? workspace.id === activeWorkspace.id : false, 992 click: () => {
1228 click: () => { 993 workspaceActions.activate({ workspace });
1229 workspaceActions.activate({ workspace }); 994 },
1230 }, 995 }));
1231 }));
1232 }
1233 996
1234 return menu; 997 return menu;
1235 } 998 }
@@ -1243,7 +1006,7 @@ export default class FranzMenu {
1243 1006
1244 menu.push({ 1007 menu.push({
1245 label: intl.formatMessage(drawerLabel), 1008 label: intl.formatMessage(drawerLabel),
1246 accelerator: `${cmdKey}+T`, 1009 accelerator: `${todosToggleShortcutKey()}`,
1247 click: () => { 1010 click: () => {
1248 todoActions.toggleTodosPanel(); 1011 todoActions.toggleTodosPanel();
1249 }, 1012 },