diff options
author | Vijay A <avijayr@protonmail.com> | 2021-09-11 07:30:56 +0530 |
---|---|---|
committer | Vijay A <avijayr@protonmail.com> | 2021-09-11 07:30:56 +0530 |
commit | a5f3f635525d270bf2b7326fe1c3846b05f87b5d (patch) | |
tree | 403a37786e37ab59ecdd78ff74bc0629ce1d17eb /src/lib | |
parent | docs: updated Changelog with cumulative changes for 5.6.1-beta.3 [skip ci] (diff) | |
parent | 5.6.1-nightly.56 [skip ci] (diff) | |
download | ferdium-app-a5f3f635525d270bf2b7326fe1c3846b05f87b5d.tar.gz ferdium-app-a5f3f635525d270bf2b7326fe1c3846b05f87b5d.tar.zst ferdium-app-a5f3f635525d270bf2b7326fe1c3846b05f87b5d.zip |
Merge branch 'nightly' into release
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/Menu.js | 552 | ||||
-rw-r--r-- | src/lib/Tray.js | 24 |
2 files changed, 334 insertions, 242 deletions
diff --git a/src/lib/Menu.js b/src/lib/Menu.js index 5a99299c5..2c24b696b 100644 --- a/src/lib/Menu.js +++ b/src/lib/Menu.js | |||
@@ -2,18 +2,32 @@ import { clipboard } from 'electron'; | |||
2 | import { app, Menu, dialog, systemPreferences } from '@electron/remote'; | 2 | import { app, Menu, dialog, systemPreferences } from '@electron/remote'; |
3 | import { autorun, observable } from 'mobx'; | 3 | import { autorun, observable } from 'mobx'; |
4 | import { defineMessages } from 'react-intl'; | 4 | import { defineMessages } from 'react-intl'; |
5 | import { CUSTOM_WEBSITE_RECIPE_ID, GITHUB_FERDI_URL, LIVE_API_FERDI_WEBSITE } from '../config'; | ||
6 | import { | 5 | import { |
7 | cmdOrCtrlShortcutKey, altKey, shiftKey, settingsShortcutKey, isLinux, isMac, aboutAppDetails, lockFerdiShortcutKey, todosToggleShortcutKey, workspaceToggleShortcutKey, addNewServiceShortcutKey, muteFerdiShortcutKey, | 6 | CUSTOM_WEBSITE_RECIPE_ID, |
7 | GITHUB_FERDI_URL, | ||
8 | LIVE_API_FERDI_WEBSITE, | ||
9 | } from '../config'; | ||
10 | import { | ||
11 | cmdOrCtrlShortcutKey, | ||
12 | altKey, | ||
13 | shiftKey, | ||
14 | settingsShortcutKey, | ||
15 | isLinux, | ||
16 | isMac, | ||
17 | aboutAppDetails, | ||
18 | lockFerdiShortcutKey, | ||
19 | todosToggleShortcutKey, | ||
20 | workspaceToggleShortcutKey, | ||
21 | addNewServiceShortcutKey, | ||
22 | muteFerdiShortcutKey, | ||
8 | } from '../environment'; | 23 | } from '../environment'; |
9 | import { announcementsStore } from '../features/announcements'; | ||
10 | import { announcementActions } from '../features/announcements/actions'; | ||
11 | import { todosStore } from '../features/todos'; | 24 | import { todosStore } from '../features/todos'; |
12 | import { todoActions } from '../features/todos/actions'; | 25 | import { todoActions } from '../features/todos/actions'; |
13 | import { workspaceActions } from '../features/workspaces/actions'; | 26 | import { workspaceActions } from '../features/workspaces/actions'; |
14 | import { workspaceStore } from '../features/workspaces/index'; | 27 | import { workspaceStore } from '../features/workspaces/index'; |
15 | import apiBase, { termsBase } from '../api/apiBase'; | 28 | import apiBase, { termsBase } from '../api/apiBase'; |
16 | import { openExternalUrl } from '../helpers/url-helpers'; | 29 | import { openExternalUrl } from '../helpers/url-helpers'; |
30 | import globalMessages from '../i18n/globalMessages'; | ||
17 | 31 | ||
18 | const menuItems = defineMessages({ | 32 | const menuItems = defineMessages({ |
19 | edit: { | 33 | edit: { |
@@ -174,7 +188,8 @@ const menuItems = defineMessages({ | |||
174 | }, | 188 | }, |
175 | debugInfoCopiedBody: { | 189 | debugInfoCopiedBody: { |
176 | id: 'menu.help.debugInfoCopiedBody', | 190 | id: 'menu.help.debugInfoCopiedBody', |
177 | defaultMessage: '!!!Your Debug Information has been copied to your clipboard.', | 191 | defaultMessage: |
192 | '!!!Your Debug Information has been copied to your clipboard.', | ||
178 | }, | 193 | }, |
179 | touchId: { | 194 | touchId: { |
180 | id: 'locked.touchId', | 195 | id: 'locked.touchId', |
@@ -216,14 +231,6 @@ const menuItems = defineMessages({ | |||
216 | id: 'menu.app.about', | 231 | id: 'menu.app.about', |
217 | defaultMessage: '!!!About Ferdi', | 232 | defaultMessage: '!!!About Ferdi', |
218 | }, | 233 | }, |
219 | announcement: { | ||
220 | id: 'menu.app.announcement', | ||
221 | defaultMessage: '!!!What\'s new?', | ||
222 | }, | ||
223 | settings: { | ||
224 | id: 'menu.app.settings', | ||
225 | defaultMessage: '!!!Settings', | ||
226 | }, | ||
227 | checkForUpdates: { | 234 | checkForUpdates: { |
228 | id: 'menu.app.checkForUpdates', | 235 | id: 'menu.app.checkForUpdates', |
229 | defaultMessage: '!!!Check for updates', | 236 | defaultMessage: '!!!Check for updates', |
@@ -244,10 +251,6 @@ const menuItems = defineMessages({ | |||
244 | id: 'menu.app.autohideMenuBar', | 251 | id: 'menu.app.autohideMenuBar', |
245 | defaultMessage: '!!!Auto-hide menu bar', | 252 | defaultMessage: '!!!Auto-hide menu bar', |
246 | }, | 253 | }, |
247 | quit: { | ||
248 | id: 'menu.app.quit', | ||
249 | defaultMessage: '!!!Quit', | ||
250 | }, | ||
251 | addNewService: { | 254 | addNewService: { |
252 | id: 'menu.services.addNewService', | 255 | id: 'menu.services.addNewService', |
253 | defaultMessage: '!!!Add New Service...', | 256 | defaultMessage: '!!!Add New Service...', |
@@ -310,8 +313,8 @@ const menuItems = defineMessages({ | |||
310 | }, | 313 | }, |
311 | }); | 314 | }); |
312 | 315 | ||
313 | function getActiveWebview() { | 316 | function getActiveService() { |
314 | return window.ferdi.stores.services.active.webview; | 317 | return window.ferdi.stores.services.active; |
315 | } | 318 | } |
316 | 319 | ||
317 | const _titleBarTemplateFactory = (intl, locked) => [ | 320 | const _titleBarTemplateFactory = (intl, locked) => [ |
@@ -349,9 +352,6 @@ const _titleBarTemplateFactory = (intl, locked) => [ | |||
349 | label: intl.formatMessage(menuItems.pasteAndMatchStyle), | 352 | label: intl.formatMessage(menuItems.pasteAndMatchStyle), |
350 | accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+V`, // Override the accelerator since this adds new key combo in macos | 353 | accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+V`, // Override the accelerator since this adds new key combo in macos |
351 | role: 'pasteAndMatchStyle', | 354 | role: 'pasteAndMatchStyle', |
352 | click() { | ||
353 | getActiveWebview().pasteAndMatchStyle(); | ||
354 | }, | ||
355 | }, | 355 | }, |
356 | { | 356 | { |
357 | label: intl.formatMessage(menuItems.delete), | 357 | label: intl.formatMessage(menuItems.delete), |
@@ -386,18 +386,18 @@ const _titleBarTemplateFactory = (intl, locked) => [ | |||
386 | label: intl.formatMessage(menuItems.findInPage), | 386 | label: intl.formatMessage(menuItems.findInPage), |
387 | accelerator: `${cmdOrCtrlShortcutKey()}+F`, | 387 | accelerator: `${cmdOrCtrlShortcutKey()}+F`, |
388 | click() { | 388 | click() { |
389 | const service = getActiveService(); | ||
389 | // Check if there is a service active | 390 | // Check if there is a service active |
390 | if (!window.ferdi.stores.services.active) return; | 391 | if (service) { |
392 | // Focus webview so find in page popup gets focused | ||
393 | service.webview.focus(); | ||
391 | 394 | ||
392 | // Focus webview so find in page popup gets focused | 395 | window.ferdi.actions.service.sendIPCMessage({ |
393 | window.ferdi.stores.services.active.webview.focus(); | 396 | serviceId: service.id, |
394 | 397 | channel: 'find-in-page', | |
395 | const currentService = window.ferdi.stores.services.active.id; | 398 | args: {}, |
396 | window.ferdi.actions.service.sendIPCMessage({ | 399 | }); |
397 | serviceId: currentService, | 400 | } |
398 | channel: 'find-in-page', | ||
399 | args: {}, | ||
400 | }); | ||
401 | }, | 401 | }, |
402 | }, | 402 | }, |
403 | { | 403 | { |
@@ -407,14 +407,14 @@ const _titleBarTemplateFactory = (intl, locked) => [ | |||
407 | label: intl.formatMessage(menuItems.back), | 407 | label: intl.formatMessage(menuItems.back), |
408 | accelerator: `${cmdOrCtrlShortcutKey()}+Left`, | 408 | accelerator: `${cmdOrCtrlShortcutKey()}+Left`, |
409 | click() { | 409 | click() { |
410 | getActiveWebview().goBack(); | 410 | getActiveService().webview.goBack(); |
411 | }, | 411 | }, |
412 | }, | 412 | }, |
413 | { | 413 | { |
414 | label: intl.formatMessage(menuItems.forward), | 414 | label: intl.formatMessage(menuItems.forward), |
415 | accelerator: `${cmdOrCtrlShortcutKey()}+Right`, | 415 | accelerator: `${cmdOrCtrlShortcutKey()}+Right`, |
416 | click() { | 416 | click() { |
417 | getActiveWebview().goForward(); | 417 | getActiveService().webview.goForward(); |
418 | }, | 418 | }, |
419 | }, | 419 | }, |
420 | { | 420 | { |
@@ -423,17 +423,15 @@ const _titleBarTemplateFactory = (intl, locked) => [ | |||
423 | { | 423 | { |
424 | label: intl.formatMessage(menuItems.resetZoom), | 424 | label: intl.formatMessage(menuItems.resetZoom), |
425 | accelerator: `${cmdOrCtrlShortcutKey()}+0`, | 425 | accelerator: `${cmdOrCtrlShortcutKey()}+0`, |
426 | role: 'resetZoom', | ||
427 | click() { | 426 | click() { |
428 | getActiveWebview().setZoomLevel(0); | 427 | getActiveService().webview.setZoomLevel(0); |
429 | }, | 428 | }, |
430 | }, | 429 | }, |
431 | { | 430 | { |
432 | label: intl.formatMessage(menuItems.zoomIn), | 431 | label: intl.formatMessage(menuItems.zoomIn), |
433 | accelerator: `${cmdOrCtrlShortcutKey()}+plus`, | 432 | accelerator: `${cmdOrCtrlShortcutKey()}+plus`, |
434 | role: 'zoomIn', | ||
435 | click() { | 433 | click() { |
436 | const activeService = getActiveWebview(); | 434 | const activeService = getActiveService().webview; |
437 | const level = activeService.getZoomLevel(); | 435 | const level = activeService.getZoomLevel(); |
438 | 436 | ||
439 | // level 9 =~ +300% and setZoomLevel wouldnt zoom in further | 437 | // level 9 =~ +300% and setZoomLevel wouldnt zoom in further |
@@ -443,9 +441,8 @@ const _titleBarTemplateFactory = (intl, locked) => [ | |||
443 | { | 441 | { |
444 | label: intl.formatMessage(menuItems.zoomOut), | 442 | label: intl.formatMessage(menuItems.zoomOut), |
445 | accelerator: `${cmdOrCtrlShortcutKey()}+-`, | 443 | accelerator: `${cmdOrCtrlShortcutKey()}+-`, |
446 | role: 'zoomOut', | ||
447 | click() { | 444 | click() { |
448 | const activeService = getActiveWebview(); | 445 | const activeService = getActiveService().webview; |
449 | const level = activeService.getZoomLevel(); | 446 | const level = activeService.getZoomLevel(); |
450 | 447 | ||
451 | // level -9 =~ -50% and setZoomLevel wouldnt zoom out further | 448 | // level -9 =~ -50% and setZoomLevel wouldnt zoom out further |
@@ -513,44 +510,49 @@ const _titleBarTemplateFactory = (intl, locked) => [ | |||
513 | submenu: [ | 510 | submenu: [ |
514 | { | 511 | { |
515 | label: intl.formatMessage(menuItems.learnMore), | 512 | label: intl.formatMessage(menuItems.learnMore), |
516 | click() { openExternalUrl(LIVE_API_FERDI_WEBSITE, true); }, | 513 | click() { |
514 | openExternalUrl(LIVE_API_FERDI_WEBSITE, true); | ||
515 | }, | ||
517 | }, | 516 | }, |
518 | { | 517 | { |
519 | label: intl.formatMessage(menuItems.changelog), | 518 | label: intl.formatMessage(menuItems.changelog), |
520 | click() { openExternalUrl(`${GITHUB_FERDI_URL}/ferdi/blob/develop/CHANGELOG.md`, true); }, | 519 | click() { |
520 | openExternalUrl( | ||
521 | `${GITHUB_FERDI_URL}/ferdi/blob/develop/CHANGELOG.md`, | ||
522 | true, | ||
523 | ); | ||
524 | }, | ||
521 | }, | 525 | }, |
522 | { | 526 | { |
523 | label: intl.formatMessage(menuItems.importExportData), | 527 | label: intl.formatMessage(menuItems.importExportData), |
524 | click() { openExternalUrl(apiBase(false), true); }, | 528 | click() { |
525 | enabled: !locked, | 529 | openExternalUrl(apiBase(false), true); |
526 | }, | ||
527 | { | ||
528 | type: 'separator', | ||
529 | }, | ||
530 | { | ||
531 | label: intl.formatMessage(menuItems.announcement), | ||
532 | click: () => { | ||
533 | announcementActions.show(); | ||
534 | }, | 530 | }, |
535 | enabled: !locked && window.ferdi.stores.user.isLoggedIn && announcementsStore.areNewsAvailable, | 531 | enabled: !locked, |
536 | }, | 532 | }, |
537 | { | 533 | { |
538 | type: 'separator', | 534 | type: 'separator', |
539 | }, | 535 | }, |
540 | { | 536 | { |
541 | label: intl.formatMessage(menuItems.support), | 537 | label: intl.formatMessage(menuItems.support), |
542 | click() { openExternalUrl(`${LIVE_API_FERDI_WEBSITE}/contact`, true); }, | 538 | click() { |
539 | openExternalUrl(`${LIVE_API_FERDI_WEBSITE}/contact`, true); | ||
540 | }, | ||
543 | }, | 541 | }, |
544 | { | 542 | { |
545 | type: 'separator', | 543 | type: 'separator', |
546 | }, | 544 | }, |
547 | { | 545 | { |
548 | label: intl.formatMessage(menuItems.tos), | 546 | label: intl.formatMessage(menuItems.tos), |
549 | click() { openExternalUrl(`${termsBase()}/terms`, true); }, | 547 | click() { |
548 | openExternalUrl(`${termsBase()}/terms`, true); | ||
549 | }, | ||
550 | }, | 550 | }, |
551 | { | 551 | { |
552 | label: intl.formatMessage(menuItems.privacy), | 552 | label: intl.formatMessage(menuItems.privacy), |
553 | click() { openExternalUrl(`${termsBase()}/privacy`, true); }, | 553 | click() { |
554 | openExternalUrl(`${termsBase()}/privacy`, true); | ||
555 | }, | ||
554 | }, | 556 | }, |
555 | ], | 557 | ], |
556 | }, | 558 | }, |
@@ -590,6 +592,23 @@ export default class FranzMenu { | |||
590 | const tpl = _titleBarTemplateFactory(intl, this.stores.settings.app.locked); | 592 | const tpl = _titleBarTemplateFactory(intl, this.stores.settings.app.locked); |
591 | const { actions } = this; | 593 | const { actions } = this; |
592 | 594 | ||
595 | // TODO: Extract this into a reusable component and remove the duplications | ||
596 | const quitApp = () => { | ||
597 | const yesButtonIndex = 0; | ||
598 | let selection = yesButtonIndex; | ||
599 | if (window.ferdi.stores.settings.app.confirmOnQuit) { | ||
600 | selection = dialog.showMessageBoxSync(app.mainWindow, { | ||
601 | type: 'question', | ||
602 | message: intl.formatMessage(globalMessages.quit), | ||
603 | detail: intl.formatMessage(globalMessages.quitConfirmation), | ||
604 | buttons: [intl.formatMessage(globalMessages.yes), intl.formatMessage(globalMessages.no)], | ||
605 | }); | ||
606 | } | ||
607 | if (selection === yesButtonIndex) { | ||
608 | app.quit(); | ||
609 | } | ||
610 | }; | ||
611 | |||
593 | if (!isMac) { | 612 | if (!isMac) { |
594 | tpl[1].submenu.push({ | 613 | tpl[1].submenu.push({ |
595 | label: intl.formatMessage(menuItems.autohideMenuBar), | 614 | label: intl.formatMessage(menuItems.autohideMenuBar), |
@@ -599,7 +618,8 @@ export default class FranzMenu { | |||
599 | window.ferdi.actions.settings.update({ | 618 | window.ferdi.actions.settings.update({ |
600 | type: 'app', | 619 | type: 'app', |
601 | data: { | 620 | data: { |
602 | autohideMenuBar: !window.ferdi.stores.settings.app.autohideMenuBar, | 621 | autohideMenuBar: |
622 | !window.ferdi.stores.settings.app.autohideMenuBar, | ||
603 | }, | 623 | }, |
604 | }); | 624 | }); |
605 | }, | 625 | }, |
@@ -607,22 +627,28 @@ export default class FranzMenu { | |||
607 | } | 627 | } |
608 | 628 | ||
609 | if (!this.stores.settings.app.locked) { | 629 | if (!this.stores.settings.app.locked) { |
610 | tpl[1].submenu.push({ | 630 | tpl[1].submenu.push( |
611 | type: 'separator', | 631 | { |
612 | }, { | 632 | type: 'separator', |
613 | label: intl.formatMessage(menuItems.toggleDevTools), | ||
614 | accelerator: `${cmdOrCtrlShortcutKey()}+${altKey()}+I`, | ||
615 | click: (menuItem, browserWindow) => { | ||
616 | browserWindow.webContents.toggleDevTools(); | ||
617 | }, | 633 | }, |
618 | }, { | 634 | { |
619 | label: intl.formatMessage(menuItems.toggleServiceDevTools), | 635 | label: intl.formatMessage(menuItems.toggleDevTools), |
620 | accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+${altKey()}+I`, | 636 | accelerator: `${cmdOrCtrlShortcutKey()}+${altKey()}+I`, |
621 | click: () => { | 637 | click: (menuItem, browserWindow) => { |
622 | this.actions.service.openDevToolsForActiveService(); | 638 | browserWindow.webContents.toggleDevTools(); |
639 | }, | ||
623 | }, | 640 | }, |
624 | enabled: this.stores.user.isLoggedIn && this.stores.services.enabled.length > 0, | 641 | { |
625 | }); | 642 | label: intl.formatMessage(menuItems.toggleServiceDevTools), |
643 | accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+${altKey()}+I`, | ||
644 | click: () => { | ||
645 | this.actions.service.openDevToolsForActiveService(); | ||
646 | }, | ||
647 | enabled: | ||
648 | this.stores.user.isLoggedIn && | ||
649 | this.stores.services.enabled.length > 0, | ||
650 | }, | ||
651 | ); | ||
626 | 652 | ||
627 | if (this.stores.features.features.isTodosEnabled) { | 653 | if (this.stores.features.features.isTodosEnabled) { |
628 | tpl[1].submenu.push({ | 654 | tpl[1].submenu.push({ |
@@ -635,49 +661,58 @@ export default class FranzMenu { | |||
635 | }); | 661 | }); |
636 | } | 662 | } |
637 | 663 | ||
638 | tpl[1].submenu.unshift({ | 664 | tpl[1].submenu.unshift( |
639 | label: intl.formatMessage(menuItems.reloadService), | 665 | { |
640 | id: 'reloadService', // TODO: needed? | 666 | label: intl.formatMessage(menuItems.reloadService), |
641 | accelerator: `${cmdOrCtrlShortcutKey()}+R`, | 667 | accelerator: `${cmdOrCtrlShortcutKey()}+R`, |
642 | click: () => { | 668 | click: () => { |
643 | if (this.stores.user.isLoggedIn | 669 | if ( |
644 | && this.stores.services.enabled.length > 0) { | 670 | this.stores.user.isLoggedIn && |
645 | if (this.stores.services.active.recipe.id === CUSTOM_WEBSITE_RECIPE_ID) { | 671 | this.stores.services.enabled.length > 0 |
646 | this.stores.services.active.webview.reload(); | 672 | ) { |
673 | if (getActiveService().recipe.id === CUSTOM_WEBSITE_RECIPE_ID) { | ||
674 | getActiveService().webview.reload(); | ||
675 | } else { | ||
676 | this.actions.service.reloadActive(); | ||
677 | } | ||
647 | } else { | 678 | } else { |
648 | this.actions.service.reloadActive(); | 679 | window.location.reload(); |
649 | } | 680 | } |
650 | } else { | 681 | }, |
682 | }, | ||
683 | { | ||
684 | label: intl.formatMessage(menuItems.reloadFerdi), | ||
685 | accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+R`, | ||
686 | click: () => { | ||
651 | window.location.reload(); | 687 | window.location.reload(); |
652 | } | 688 | }, |
653 | }, | 689 | }, |
654 | }, { | 690 | { |
655 | label: intl.formatMessage(menuItems.reloadFerdi), | 691 | label: intl.formatMessage(menuItems.reloadTodos), |
656 | accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+R`, | 692 | accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+${altKey()}+R`, |
657 | click: () => { | 693 | click: () => { |
658 | window.location.reload(); | 694 | this.actions.todos.reload(); |
695 | }, | ||
659 | }, | 696 | }, |
660 | }, { | 697 | { |
661 | label: intl.formatMessage(menuItems.reloadTodos), | 698 | type: 'separator', |
662 | accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+${altKey()}+R`, | ||
663 | click: () => { | ||
664 | this.actions.todos.reload(); | ||
665 | }, | 699 | }, |
666 | }, { | 700 | { |
667 | type: 'separator', | 701 | label: intl.formatMessage(menuItems.lockFerdi), |
668 | }, { | 702 | accelerator: `${lockFerdiShortcutKey()}`, |
669 | label: intl.formatMessage(menuItems.lockFerdi), | 703 | enabled: |
670 | accelerator: `${lockFerdiShortcutKey()}`, | 704 | this.stores.user.isLoggedIn && |
671 | enabled: this.stores.user.isLoggedIn && this.stores.settings.app.lockingFeatureEnabled, | 705 | this.stores.settings.app.lockingFeatureEnabled, |
672 | click() { | 706 | click() { |
673 | actions.settings.update({ | 707 | actions.settings.update({ |
674 | type: 'app', | 708 | type: 'app', |
675 | data: { | 709 | data: { |
676 | locked: true, | 710 | locked: true, |
677 | }, | 711 | }, |
678 | }); | 712 | }); |
713 | }, | ||
679 | }, | 714 | }, |
680 | }); | 715 | ); |
681 | 716 | ||
682 | if (serviceTpl.length > 0) { | 717 | if (serviceTpl.length > 0) { |
683 | tpl[2].submenu = serviceTpl; | 718 | tpl[2].submenu = serviceTpl; |
@@ -691,26 +726,34 @@ export default class FranzMenu { | |||
691 | tpl[4].submenu = this.todosMenu(); | 726 | tpl[4].submenu = this.todosMenu(); |
692 | } | 727 | } |
693 | } else { | 728 | } else { |
694 | const touchIdEnabled = isMac ? (this.stores.settings.app.useTouchIdToUnlock && systemPreferences.canPromptTouchID()) : false; | 729 | const touchIdEnabled = isMac |
730 | ? this.stores.settings.app.useTouchIdToUnlock && | ||
731 | systemPreferences.canPromptTouchID() | ||
732 | : false; | ||
695 | 733 | ||
696 | tpl[0].submenu.unshift({ | 734 | tpl[0].submenu.unshift( |
697 | label: intl.formatMessage(menuItems.touchId), | 735 | { |
698 | accelerator: `${lockFerdiShortcutKey()}`, | 736 | label: intl.formatMessage(menuItems.touchId), |
699 | visible: touchIdEnabled, | 737 | accelerator: `${lockFerdiShortcutKey()}`, |
700 | click() { | 738 | visible: touchIdEnabled, |
701 | systemPreferences.promptTouchID(intl.formatMessage(menuItems.touchIdPrompt)).then(() => { | 739 | click() { |
702 | actions.settings.update({ | 740 | systemPreferences |
703 | type: 'app', | 741 | .promptTouchID(intl.formatMessage(menuItems.touchIdPrompt)) |
704 | data: { | 742 | .then(() => { |
705 | locked: false, | 743 | actions.settings.update({ |
706 | }, | 744 | type: 'app', |
707 | }); | 745 | data: { |
708 | }); | 746 | locked: false, |
747 | }, | ||
748 | }); | ||
749 | }); | ||
750 | }, | ||
709 | }, | 751 | }, |
710 | }, { | 752 | { |
711 | type: 'separator', | 753 | type: 'separator', |
712 | visible: touchIdEnabled, | 754 | visible: touchIdEnabled, |
713 | }); | 755 | }, |
756 | ); | ||
714 | } | 757 | } |
715 | 758 | ||
716 | tpl.unshift({ | 759 | tpl.unshift({ |
@@ -725,7 +768,7 @@ export default class FranzMenu { | |||
725 | type: 'separator', | 768 | type: 'separator', |
726 | }, | 769 | }, |
727 | { | 770 | { |
728 | label: intl.formatMessage(menuItems.settings), | 771 | label: intl.formatMessage(globalMessages.settings), |
729 | accelerator: `${settingsShortcutKey()}`, | 772 | accelerator: `${settingsShortcutKey()}`, |
730 | click: () => { | 773 | click: () => { |
731 | this.actions.ui.openSettings({ path: 'app' }); | 774 | this.actions.ui.openSettings({ path: 'app' }); |
@@ -768,18 +811,15 @@ export default class FranzMenu { | |||
768 | type: 'separator', | 811 | type: 'separator', |
769 | }, | 812 | }, |
770 | { | 813 | { |
771 | label: intl.formatMessage(menuItems.quit), | 814 | label: intl.formatMessage(globalMessages.quit), |
772 | role: 'quit', | 815 | accelerator: `${cmdOrCtrlShortcutKey()}+Q`, |
773 | click() { | 816 | click: quitApp, |
774 | app.quit(); | ||
775 | }, | ||
776 | }, | 817 | }, |
777 | ], | 818 | ], |
778 | }); | 819 | }); |
779 | 820 | ||
780 | const about = { | 821 | const about = { |
781 | label: intl.formatMessage(menuItems.about), | 822 | label: intl.formatMessage(menuItems.about), |
782 | role: 'about', | ||
783 | click: () => { | 823 | click: () => { |
784 | dialog.showMessageBox({ | 824 | dialog.showMessageBox({ |
785 | type: 'info', | 825 | type: 'info', |
@@ -829,18 +869,18 @@ export default class FranzMenu { | |||
829 | type: 'separator', | 869 | type: 'separator', |
830 | }, | 870 | }, |
831 | { | 871 | { |
832 | label: intl.formatMessage(menuItems.quit), | 872 | label: intl.formatMessage(globalMessages.quit), |
833 | role: 'quit', | ||
834 | accelerator: `${cmdOrCtrlShortcutKey()}+Q`, | 873 | accelerator: `${cmdOrCtrlShortcutKey()}+Q`, |
835 | click() { | 874 | click: quitApp, |
836 | app.quit(); | ||
837 | }, | ||
838 | }, | 875 | }, |
839 | ]; | 876 | ]; |
840 | 877 | ||
841 | tpl[tpl.length - 1].submenu.push({ | 878 | tpl[tpl.length - 1].submenu.push( |
842 | type: 'separator', | 879 | { |
843 | }, about); | 880 | type: 'separator', |
881 | }, | ||
882 | about, | ||
883 | ); | ||
844 | } | 884 | } |
845 | 885 | ||
846 | if (!this.stores.settings.app.locked) { | 886 | if (!this.stores.settings.app.locked) { |
@@ -856,9 +896,12 @@ export default class FranzMenu { | |||
856 | tpl[5].submenu = this.todosMenu(); | 896 | tpl[5].submenu = this.todosMenu(); |
857 | } | 897 | } |
858 | 898 | ||
859 | tpl[tpl.length - 1].submenu.push({ | 899 | tpl[tpl.length - 1].submenu.push( |
860 | type: 'separator', | 900 | { |
861 | }, ...this.debugMenu()); | 901 | type: 'separator', |
902 | }, | ||
903 | ...this.debugMenu(), | ||
904 | ); | ||
862 | } | 905 | } |
863 | this.currentTemplate = tpl; | 906 | this.currentTemplate = tpl; |
864 | const menu = Menu.buildFromTemplate(tpl); | 907 | const menu = Menu.buildFromTemplate(tpl); |
@@ -872,73 +915,95 @@ export default class FranzMenu { | |||
872 | const menu = []; | 915 | const menu = []; |
873 | const cmdAltShortcutsVisibile = !isLinux; | 916 | const cmdAltShortcutsVisibile = !isLinux; |
874 | 917 | ||
875 | menu.push({ | 918 | menu.push( |
876 | label: intl.formatMessage(menuItems.addNewService), | 919 | { |
877 | accelerator: `${addNewServiceShortcutKey()}`, | 920 | label: intl.formatMessage(menuItems.addNewService), |
878 | click: () => { | 921 | accelerator: `${addNewServiceShortcutKey()}`, |
879 | this.actions.ui.openSettings({ path: 'recipes' }); | 922 | click: () => { |
923 | this.actions.ui.openSettings({ path: 'recipes' }); | ||
924 | }, | ||
880 | }, | 925 | }, |
881 | }, { | 926 | { |
882 | type: 'separator', | 927 | type: 'separator', |
883 | }, { | 928 | }, |
884 | label: intl.formatMessage(menuItems.activateNextService), | 929 | { |
885 | accelerator: `${cmdOrCtrlShortcutKey()}+tab`, | 930 | label: intl.formatMessage(menuItems.activateNextService), |
886 | click: () => this.actions.service.setActiveNext(), | 931 | accelerator: `${cmdOrCtrlShortcutKey()}+tab`, |
887 | visible: !cmdAltShortcutsVisibile, | 932 | click: () => this.actions.service.setActiveNext(), |
888 | }, { | 933 | visible: !cmdAltShortcutsVisibile, |
889 | label: intl.formatMessage(menuItems.activateNextService), | 934 | }, |
890 | accelerator: `${cmdOrCtrlShortcutKey()}+${altKey()}+right`, | 935 | { |
891 | click: () => this.actions.service.setActiveNext(), | 936 | label: intl.formatMessage(menuItems.activateNextService), |
892 | visible: cmdAltShortcutsVisibile, | 937 | accelerator: `${cmdOrCtrlShortcutKey()}+${altKey()}+right`, |
893 | }, { | 938 | click: () => this.actions.service.setActiveNext(), |
894 | label: intl.formatMessage(menuItems.activatePreviousService), | 939 | visible: cmdAltShortcutsVisibile, |
895 | accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+tab`, | 940 | }, |
896 | click: () => this.actions.service.setActivePrev(), | 941 | { |
897 | visible: !cmdAltShortcutsVisibile, | 942 | label: intl.formatMessage(menuItems.activatePreviousService), |
898 | }, { | 943 | accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+tab`, |
899 | label: intl.formatMessage(menuItems.activatePreviousService), | 944 | click: () => this.actions.service.setActivePrev(), |
900 | accelerator: `${cmdOrCtrlShortcutKey()}+${altKey()}+left`, | 945 | visible: !cmdAltShortcutsVisibile, |
901 | click: () => this.actions.service.setActivePrev(), | 946 | }, |
902 | visible: cmdAltShortcutsVisibile, | 947 | { |
903 | }, { | 948 | label: intl.formatMessage(menuItems.activatePreviousService), |
904 | label: intl.formatMessage( | 949 | accelerator: `${cmdOrCtrlShortcutKey()}+${altKey()}+left`, |
905 | settings.all.app.isAppMuted ? menuItems.unmuteApp : menuItems.muteApp, | 950 | click: () => this.actions.service.setActivePrev(), |
906 | ).replace('&', '&&'), | 951 | visible: cmdAltShortcutsVisibile, |
907 | accelerator: `${muteFerdiShortcutKey()}`, | 952 | }, |
908 | click: () => this.actions.app.toggleMuteApp(), | 953 | { |
909 | }, { | 954 | label: intl |
910 | type: 'separator', | 955 | .formatMessage( |
911 | }); | 956 | settings.all.app.isAppMuted |
912 | 957 | ? menuItems.unmuteApp | |
913 | services.allDisplayed.forEach((service, i) => (menu.push({ | 958 | : menuItems.muteApp, |
914 | label: this._getServiceName(service), | 959 | ) |
915 | accelerator: i < 9 ? `${cmdOrCtrlShortcutKey()}+${i + 1}` : null, | 960 | .replace('&', '&&'), |
916 | type: 'radio', | 961 | accelerator: `${muteFerdiShortcutKey()}`, |
917 | checked: service.isActive, | 962 | click: () => this.actions.app.toggleMuteApp(), |
918 | click: () => { | 963 | }, |
919 | this.actions.service.setActive({ serviceId: service.id }); | 964 | { |
920 | 965 | type: 'separator', | |
921 | if (isMac && i === 0) { | ||
922 | app.mainWindow.restore(); | ||
923 | } | ||
924 | }, | 966 | }, |
925 | }))); | 967 | ); |
926 | 968 | ||
927 | if (services.active && services.active.recipe.id === CUSTOM_WEBSITE_RECIPE_ID) { | 969 | services.allDisplayed.forEach((service, i) => |
928 | menu.push({ | 970 | menu.push({ |
929 | type: 'separator', | 971 | label: this._getServiceName(service), |
930 | }, { | 972 | accelerator: i < 9 ? `${cmdOrCtrlShortcutKey()}+${i + 1}` : null, |
931 | label: intl.formatMessage(menuItems.serviceGoHome), | 973 | type: 'radio', |
932 | accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+H`, | 974 | checked: service.isActive, |
933 | click: () => this.actions.service.reloadActive(), | 975 | click: () => { |
934 | }); | 976 | this.actions.service.setActive({ serviceId: service.id }); |
977 | |||
978 | if (isMac && i === 0) { | ||
979 | app.mainWindow.restore(); | ||
980 | } | ||
981 | }, | ||
982 | }), | ||
983 | ); | ||
984 | |||
985 | if ( | ||
986 | services.active && | ||
987 | services.active.recipe.id === CUSTOM_WEBSITE_RECIPE_ID | ||
988 | ) { | ||
989 | menu.push( | ||
990 | { | ||
991 | type: 'separator', | ||
992 | }, | ||
993 | { | ||
994 | label: intl.formatMessage(menuItems.serviceGoHome), | ||
995 | accelerator: `${cmdOrCtrlShortcutKey()}+${shiftKey()}+H`, | ||
996 | click: () => this.actions.service.reloadActive(), | ||
997 | }, | ||
998 | ); | ||
935 | } | 999 | } |
936 | 1000 | ||
937 | return menu; | 1001 | return menu; |
938 | } | 1002 | } |
939 | 1003 | ||
940 | workspacesMenu() { | 1004 | workspacesMenu() { |
941 | const { workspaces, activeWorkspace, isWorkspaceDrawerOpen } = workspaceStore; | 1005 | const { workspaces, activeWorkspace, isWorkspaceDrawerOpen } = |
1006 | workspaceStore; | ||
942 | const { intl } = window.ferdi; | 1007 | const { intl } = window.ferdi; |
943 | const menu = []; | 1008 | const menu = []; |
944 | 1009 | ||
@@ -954,9 +1019,9 @@ export default class FranzMenu { | |||
954 | 1019 | ||
955 | // Open workspace drawer: | 1020 | // Open workspace drawer: |
956 | if (!this.stores.settings.app.alwaysShowWorkspaces) { | 1021 | if (!this.stores.settings.app.alwaysShowWorkspaces) { |
957 | const drawerLabel = ( | 1022 | const drawerLabel = isWorkspaceDrawerOpen |
958 | isWorkspaceDrawerOpen ? menuItems.closeWorkspaceDrawer : menuItems.openWorkspaceDrawer | 1023 | ? menuItems.closeWorkspaceDrawer |
959 | ); | 1024 | : menuItems.openWorkspaceDrawer; |
960 | menu.push({ | 1025 | menu.push({ |
961 | label: intl.formatMessage(drawerLabel), | 1026 | label: intl.formatMessage(drawerLabel), |
962 | accelerator: `${workspaceToggleShortcutKey()}`, | 1027 | accelerator: `${workspaceToggleShortcutKey()}`, |
@@ -983,15 +1048,18 @@ export default class FranzMenu { | |||
983 | }); | 1048 | }); |
984 | 1049 | ||
985 | // Workspace items | 1050 | // Workspace items |
986 | workspaces.forEach((workspace, i) => menu.push({ | 1051 | workspaces.forEach((workspace, i) => |
987 | label: workspace.name, | 1052 | menu.push({ |
988 | accelerator: i < 9 ? `${cmdOrCtrlShortcutKey()}+${altKey()}+${i + 1}` : null, | 1053 | label: workspace.name, |
989 | type: 'radio', | 1054 | accelerator: |
990 | checked: activeWorkspace ? workspace.id === activeWorkspace.id : false, | 1055 | i < 9 ? `${cmdOrCtrlShortcutKey()}+${altKey()}+${i + 1}` : null, |
991 | click: () => { | 1056 | type: 'radio', |
992 | workspaceActions.activate({ workspace }); | 1057 | checked: activeWorkspace ? workspace.id === activeWorkspace.id : false, |
993 | }, | 1058 | click: () => { |
994 | })); | 1059 | workspaceActions.activate({ workspace }); |
1060 | }, | ||
1061 | }), | ||
1062 | ); | ||
995 | 1063 | ||
996 | return menu; | 1064 | return menu; |
997 | } | 1065 | } |
@@ -1001,7 +1069,9 @@ export default class FranzMenu { | |||
1001 | const { intl } = window.ferdi; | 1069 | const { intl } = window.ferdi; |
1002 | const menu = []; | 1070 | const menu = []; |
1003 | 1071 | ||
1004 | const drawerLabel = isTodosPanelVisible ? menuItems.closeTodosDrawer : menuItems.openTodosDrawer; | 1072 | const drawerLabel = isTodosPanelVisible |
1073 | ? menuItems.closeTodosDrawer | ||
1074 | : menuItems.openTodosDrawer; | ||
1005 | 1075 | ||
1006 | menu.push({ | 1076 | menu.push({ |
1007 | label: intl.formatMessage(drawerLabel), | 1077 | label: intl.formatMessage(drawerLabel), |
@@ -1013,14 +1083,17 @@ export default class FranzMenu { | |||
1013 | }); | 1083 | }); |
1014 | 1084 | ||
1015 | if (!isFeatureEnabledByUser) { | 1085 | if (!isFeatureEnabledByUser) { |
1016 | menu.push({ | 1086 | menu.push( |
1017 | type: 'separator', | 1087 | { |
1018 | }, { | 1088 | type: 'separator', |
1019 | label: intl.formatMessage(menuItems.enableTodos), | ||
1020 | click: () => { | ||
1021 | todoActions.toggleTodosFeatureVisibility(); | ||
1022 | }, | 1089 | }, |
1023 | }); | 1090 | { |
1091 | label: intl.formatMessage(menuItems.enableTodos), | ||
1092 | click: () => { | ||
1093 | todoActions.toggleTodosFeatureVisibility(); | ||
1094 | }, | ||
1095 | }, | ||
1096 | ); | ||
1024 | } | 1097 | } |
1025 | 1098 | ||
1026 | return menu; | 1099 | return menu; |
@@ -1029,28 +1102,31 @@ export default class FranzMenu { | |||
1029 | debugMenu() { | 1102 | debugMenu() { |
1030 | const { intl } = window.ferdi; | 1103 | const { intl } = window.ferdi; |
1031 | 1104 | ||
1032 | return [{ | 1105 | return [ |
1033 | label: intl.formatMessage(menuItems.debugInfo), | 1106 | { |
1034 | click: () => { | 1107 | label: intl.formatMessage(menuItems.debugInfo), |
1035 | const { debugInfo } = this.stores.app; | 1108 | click: () => { |
1109 | const { debugInfo } = this.stores.app; | ||
1036 | 1110 | ||
1037 | clipboard.write({ | 1111 | clipboard.write({ |
1038 | text: JSON.stringify(debugInfo), | 1112 | text: JSON.stringify(debugInfo), |
1039 | }); | 1113 | }); |
1040 | 1114 | ||
1041 | this.actions.app.notify({ | 1115 | this.actions.app.notify({ |
1042 | title: intl.formatMessage(menuItems.debugInfoCopiedHeadline), | 1116 | title: intl.formatMessage(menuItems.debugInfoCopiedHeadline), |
1043 | options: { | 1117 | options: { |
1044 | body: intl.formatMessage(menuItems.debugInfoCopiedBody), | 1118 | body: intl.formatMessage(menuItems.debugInfoCopiedBody), |
1045 | }, | 1119 | }, |
1046 | }); | 1120 | }); |
1121 | }, | ||
1047 | }, | 1122 | }, |
1048 | }, { | 1123 | { |
1049 | label: intl.formatMessage(menuItems.publishDebugInfo), | 1124 | label: intl.formatMessage(menuItems.publishDebugInfo), |
1050 | click: () => { | 1125 | click: () => { |
1051 | window.ferdi.features.publishDebugInfo.state.isModalVisible = true; | 1126 | window.ferdi.features.publishDebugInfo.state.isModalVisible = true; |
1127 | }, | ||
1052 | }, | 1128 | }, |
1053 | }]; | 1129 | ]; |
1054 | } | 1130 | } |
1055 | 1131 | ||
1056 | _getServiceName(service) { | 1132 | _getServiceName(service) { |
diff --git a/src/lib/Tray.js b/src/lib/Tray.js index f5970f7e7..c897d597a 100644 --- a/src/lib/Tray.js +++ b/src/lib/Tray.js | |||
@@ -1,5 +1,5 @@ | |||
1 | import { | 1 | import { |
2 | app, Menu, nativeImage, nativeTheme, systemPreferences, Tray, ipcMain, | 2 | app, Menu, nativeImage, nativeTheme, systemPreferences, Tray, ipcMain, dialog, |
3 | } from 'electron'; | 3 | } from 'electron'; |
4 | import { join } from 'path'; | 4 | import { join } from 'path'; |
5 | import macosVersion from 'macos-version'; | 5 | import macosVersion from 'macos-version'; |
@@ -43,9 +43,7 @@ export default class TrayIcon { | |||
43 | }, | 43 | }, |
44 | { | 44 | { |
45 | label: 'Quit Ferdi', | 45 | label: 'Quit Ferdi', |
46 | click() { | 46 | click: this.quitApp, |
47 | app.quit(); | ||
48 | }, | ||
49 | }, | 47 | }, |
50 | ]; | 48 | ]; |
51 | 49 | ||
@@ -178,4 +176,22 @@ export default class TrayIcon { | |||
178 | __dirname, '..', 'assets', 'images', type, platform, `${asset}.${FILE_EXTENSION}`, | 176 | __dirname, '..', 'assets', 'images', type, platform, `${asset}.${FILE_EXTENSION}`, |
179 | )); | 177 | )); |
180 | } | 178 | } |
179 | |||
180 | // TODO: Extract this into a reusable component and remove the duplications | ||
181 | quitApp = () => { | ||
182 | const yesButtonIndex = 0; | ||
183 | let selection = yesButtonIndex; | ||
184 | if (window.ferdi.stores.settings.app.confirmOnQuit) { | ||
185 | selection = dialog.showMessageBoxSync(app.mainWindow, { | ||
186 | // TODO: Externalize strings | ||
187 | type: 'question', | ||
188 | message: 'Quit', | ||
189 | detail: 'Do you really want to quit Ferdi?', | ||
190 | buttons: ['Yes', 'No'], | ||
191 | }); | ||
192 | } | ||
193 | if (selection === yesButtonIndex) { | ||
194 | app.quit(); | ||
195 | } | ||
196 | }; | ||
181 | } | 197 | } |