aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/components/auth/Import.js5
-rw-r--r--src/components/settings/services/EditServiceForm.js32
-rw-r--r--src/components/settings/settings/EditSettingsForm.tsx92
-rw-r--r--src/components/ui/Toggle.js72
-rw-r--r--src/components/ui/button/index.tsx4
-rw-r--r--src/components/ui/toggle/index.tsx56
-rw-r--r--src/features/workspaces/components/EditWorkspaceForm.js7
-rw-r--r--src/features/workspaces/components/WorkspaceServiceListItem.tsx26
-rw-r--r--src/lib/Tray.ts36
9 files changed, 126 insertions, 204 deletions
diff --git a/src/components/auth/Import.js b/src/components/auth/Import.js
index 41b887974..b897116e2 100644
--- a/src/components/auth/Import.js
+++ b/src/components/auth/Import.js
@@ -4,9 +4,8 @@ import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4import { defineMessages, injectIntl } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5import { Link } from 'react-router-dom'; 5import { Link } from 'react-router-dom';
6import classnames from 'classnames'; 6import classnames from 'classnames';
7
8import Form from '../../lib/Form'; 7import Form from '../../lib/Form';
9import Toggle from '../ui/Toggle'; 8import Toggle from '../ui/toggle';
10import Button from '../ui/button'; 9import Button from '../ui/button';
11import { H1 } from '../ui/headline'; 10import { H1 } from '../ui/headline';
12 11
@@ -97,7 +96,7 @@ class Import extends Component {
97 {this.form.$('import').map((service, i) => ( 96 {this.form.$('import').map((service, i) => (
98 <tr key={service.id} className="service-table__row"> 97 <tr key={service.id} className="service-table__row">
99 <td className="service-table__toggle"> 98 <td className="service-table__toggle">
100 <Toggle field={service.$('add')} showLabel={false} /> 99 <Toggle {...service.$('add').bind()} showLabel={false} />
101 </td> 100 </td>
102 <td className="service-table__column-icon"> 101 <td className="service-table__column-icon">
103 <img 102 <img
diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js
index eeb9ef54d..eb18b57eb 100644
--- a/src/components/settings/services/EditServiceForm.js
+++ b/src/components/settings/services/EditServiceForm.js
@@ -4,7 +4,6 @@ import { observer } from 'mobx-react';
4import { Link } from 'react-router-dom'; 4import { Link } from 'react-router-dom';
5import { defineMessages, injectIntl } from 'react-intl'; 5import { defineMessages, injectIntl } from 'react-intl';
6import normalizeUrl from 'normalize-url'; 6import normalizeUrl from 'normalize-url';
7
8import { mdiInformation } from '@mdi/js'; 7import { mdiInformation } from '@mdi/js';
9import Form from '../../../lib/Form'; 8import Form from '../../../lib/Form';
10import Recipe from '../../../models/Recipe'; 9import Recipe from '../../../models/Recipe';
@@ -12,12 +11,11 @@ import Service from '../../../models/Service';
12import Tabs from '../../ui/Tabs/Tabs'; 11import Tabs from '../../ui/Tabs/Tabs';
13import TabItem from '../../ui/Tabs/TabItem'; 12import TabItem from '../../ui/Tabs/TabItem';
14import Input from '../../ui/input/index'; 13import Input from '../../ui/input/index';
15import Toggle from '../../ui/Toggle'; 14import Toggle from '../../ui/toggle';
16import Slider from '../../ui/Slider'; 15import Slider from '../../ui/Slider';
17import Button from '../../ui/button'; 16import Button from '../../ui/button';
18import ImageUpload from '../../ui/ImageUpload'; 17import ImageUpload from '../../ui/ImageUpload';
19import Select from '../../ui/Select'; 18import Select from '../../ui/Select';
20
21import { isMac } from '../../../environment'; 19import { isMac } from '../../../environment';
22import globalMessages from '../../../i18n/globalMessages'; 20import globalMessages from '../../../i18n/globalMessages';
23import Icon from '../../ui/icon'; 21import Icon from '../../ui/icon';
@@ -342,22 +340,22 @@ class EditServiceForm extends Component {
342 <div className="settings__options"> 340 <div className="settings__options">
343 <div className="settings__settings-group"> 341 <div className="settings__settings-group">
344 <H3>{intl.formatMessage(messages.headlineNotifications)}</H3> 342 <H3>{intl.formatMessage(messages.headlineNotifications)}</H3>
345 <Toggle field={form.$('isNotificationEnabled')} /> 343 <Toggle {...form.$('isNotificationEnabled').bind()} />
346 <Toggle field={form.$('isMuted')} /> 344 <Toggle {...form.$('isMuted').bind()} />
347 <p className="settings__help indented__help"> 345 <p className="settings__help indented__help">
348 {intl.formatMessage(messages.isMutedInfo)} 346 {intl.formatMessage(messages.isMutedInfo)}
349 </p> 347 </p>
350 <Toggle field={form.$('isMediaBadgeEnabled')} /> 348 <Toggle {...form.$('isMediaBadgeEnabled').bind()} />
351 </div> 349 </div>
352 350
353 <div className="settings__settings-group"> 351 <div className="settings__settings-group">
354 <H3>{intl.formatMessage(messages.headlineBadges)}</H3> 352 <H3>{intl.formatMessage(messages.headlineBadges)}</H3>
355 <Toggle field={form.$('isBadgeEnabled')} /> 353 <Toggle {...form.$('isBadgeEnabled').bind()} />
356 {recipe.hasIndirectMessages && 354 {recipe.hasIndirectMessages &&
357 form.$('isBadgeEnabled').value && ( 355 form.$('isBadgeEnabled').value && (
358 <> 356 <>
359 <Toggle 357 <Toggle
360 field={form.$('isIndirectMessageBadgeEnabled')} 358 {...form.$('isIndirectMessageBadgeEnabled').bind()}
361 /> 359 />
362 <p className="settings__help indented__help"> 360 <p className="settings__help indented__help">
363 {intl.formatMessage(messages.indirectMessageInfo)} 361 {intl.formatMessage(messages.indirectMessageInfo)}
@@ -365,19 +363,21 @@ class EditServiceForm extends Component {
365 </> 363 </>
366 )} 364 )}
367 {recipe.allowFavoritesDelineationInUnreadCount && ( 365 {recipe.allowFavoritesDelineationInUnreadCount && (
368 <Toggle field={form.$('onlyShowFavoritesInUnreadCount')} /> 366 <Toggle
367 {...form.$('onlyShowFavoritesInUnreadCount').bind()}
368 />
369 )} 369 )}
370 </div> 370 </div>
371 371
372 <div className="settings__settings-group"> 372 <div className="settings__settings-group">
373 <H3>{intl.formatMessage(messages.headlineGeneral)}</H3> 373 <H3>{intl.formatMessage(messages.headlineGeneral)}</H3>
374 <Toggle field={form.$('isEnabled')} /> 374 <Toggle {...form.$('isEnabled').bind()} />
375 <Toggle field={form.$('isHibernationEnabled')} /> 375 <Toggle {...form.$('isHibernationEnabled').bind()} />
376 <p className="settings__help indented__help"> 376 <p className="settings__help indented__help">
377 {intl.formatMessage(messages.isHibernationEnabledInfo)} 377 {intl.formatMessage(messages.isHibernationEnabledInfo)}
378 </p> 378 </p>
379 <Toggle field={form.$('isWakeUpEnabled')} /> 379 <Toggle {...form.$('isWakeUpEnabled').bind()} />
380 <Toggle field={form.$('trapLinkClicks')} /> 380 <Toggle {...form.$('trapLinkClicks').bind()} />
381 {/* TODO: Need to figure out how to effect this change without a reload of the recipe */} 381 {/* TODO: Need to figure out how to effect this change without a reload of the recipe */}
382 <p className="settings__help indented__help"> 382 <p className="settings__help indented__help">
383 {intl.formatMessage(messages.serviceReloadRequired)} 383 {intl.formatMessage(messages.serviceReloadRequired)}
@@ -386,7 +386,7 @@ class EditServiceForm extends Component {
386 386
387 <div className="settings__settings-group"> 387 <div className="settings__settings-group">
388 <H3>{intl.formatMessage(messages.headlineAppearance)}</H3> 388 <H3>{intl.formatMessage(messages.headlineAppearance)}</H3>
389 <Toggle field={form.$('isDarkModeEnabled')} /> 389 <Toggle {...form.$('isDarkModeEnabled').bind()} />
390 {form.$('isDarkModeEnabled').value && ( 390 {form.$('isDarkModeEnabled').value && (
391 <> 391 <>
392 <H3> 392 <H3>
@@ -399,7 +399,7 @@ class EditServiceForm extends Component {
399 <Slider field={form.$('darkReaderSepia')} /> 399 <Slider field={form.$('darkReaderSepia')} />
400 </> 400 </>
401 )} 401 )}
402 <Toggle field={form.$('isProgressbarEnabled')} /> 402 <Toggle {...form.$('isProgressbarEnabled').bind()} />
403 </div> 403 </div>
404 </div> 404 </div>
405 <div className="service-icon"> 405 <div className="service-icon">
@@ -429,7 +429,7 @@ class EditServiceForm extends Component {
429 {intl.formatMessage(messages.headlineProxy)} 429 {intl.formatMessage(messages.headlineProxy)}
430 <span className="badge badge--success">beta</span> 430 <span className="badge badge--success">beta</span>
431 </H3> 431 </H3>
432 <Toggle field={form.$('proxy.isEnabled')} /> 432 <Toggle {...form.$('proxy.isEnabled').bind()} />
433 {form.$('proxy.isEnabled').value && ( 433 {form.$('proxy.isEnabled').value && (
434 <> 434 <>
435 <div className="grid"> 435 <div className="grid">
diff --git a/src/components/settings/settings/EditSettingsForm.tsx b/src/components/settings/settings/EditSettingsForm.tsx
index 1d89b53a9..e796a48ec 100644
--- a/src/components/settings/settings/EditSettingsForm.tsx
+++ b/src/components/settings/settings/EditSettingsForm.tsx
@@ -6,7 +6,7 @@ import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl';
6import { mdiGithub, mdiOpenInNew, mdiPowerPlug } from '@mdi/js'; 6import { mdiGithub, mdiOpenInNew, mdiPowerPlug } from '@mdi/js';
7import Form from '../../../lib/Form'; 7import Form from '../../../lib/Form';
8import Button from '../../ui/button'; 8import Button from '../../ui/button';
9import Toggle from '../../ui/Toggle.js'; 9import Toggle from '../../ui/toggle';
10import Select from '../../ui/Select'; 10import Select from '../../ui/Select';
11import Input from '../../ui/input/index'; 11import Input from '../../ui/input/index';
12import ColorPickerInput from '../../ui/ColorPickerInput'; 12import ColorPickerInput from '../../ui/ColorPickerInput';
@@ -522,26 +522,30 @@ class EditSettingsForm extends Component<IProps, IState> {
522 <H2 className="settings__section_header"> 522 <H2 className="settings__section_header">
523 {intl.formatMessage(messages.sectionMain)} 523 {intl.formatMessage(messages.sectionMain)}
524 </H2> 524 </H2>
525 <Toggle field={form.$('autoLaunchOnStart')} /> 525 <Toggle {...form.$('autoLaunchOnStart').bind()} />
526 <Toggle field={form.$('runInBackground')} /> 526 <Toggle {...form.$('runInBackground').bind()} />
527 <Toggle field={form.$('confirmOnQuit')} /> 527 <Toggle {...form.$('confirmOnQuit').bind()} />
528 <Toggle field={form.$('enableSystemTray')} /> 528 <Toggle {...form.$('enableSystemTray').bind()} />
529 {reloadAfterResume && <Hr />} 529 {reloadAfterResume && <Hr />}
530 <Toggle field={form.$('reloadAfterResume')} /> 530 <Toggle {...form.$('reloadAfterResume').bind()} />
531 {reloadAfterResume && ( 531 {reloadAfterResume && (
532 <div> 532 <div>
533 <Input {...form.$('reloadAfterResumeTime').bind()} /> 533 <Input {...form.$('reloadAfterResumeTime').bind()} />
534 <Hr /> 534 <Hr />
535 </div> 535 </div>
536 )} 536 )}
537 <Toggle field={form.$('startMinimized')} /> 537 <Toggle {...form.$('startMinimized').bind()} />
538 {isWindows && <Toggle field={form.$('minimizeToSystemTray')} />} 538 {isWindows && (
539 {isWindows && <Toggle field={form.$('closeToSystemTray')} />} 539 <Toggle {...form.$('minimizeToSystemTray').bind()} />
540 )}
541 {isWindows && (
542 <Toggle {...form.$('closeToSystemTray').bind()} />
543 )}
540 544
541 <Toggle field={form.$('keepAllWorkspacesLoaded')} /> 545 <Toggle {...form.$('keepAllWorkspacesLoaded').bind()} />
542 546
543 {isTodosActivated && <Hr />} 547 {isTodosActivated && <Hr />}
544 <Toggle field={form.$('enableTodos')} /> 548 <Toggle {...form.$('enableTodos').bind()} />
545 {isTodosActivated && ( 549 {isTodosActivated && (
546 <div> 550 <div>
547 <Select field={form.$('predefinedTodoServer')} /> 551 <Select field={form.$('predefinedTodoServer')} />
@@ -571,7 +575,7 @@ class EditSettingsForm extends Component<IProps, IState> {
571 {isTodosActivated && <Hr />} 575 {isTodosActivated && <Hr />}
572 576
573 {scheduledDNDEnabled && <Hr />} 577 {scheduledDNDEnabled && <Hr />}
574 <Toggle field={form.$('scheduledDNDEnabled')} /> 578 <Toggle {...form.$('scheduledDNDEnabled').bind()} />
575 579
576 {scheduledDNDEnabled && ( 580 {scheduledDNDEnabled && (
577 <> 581 <>
@@ -632,12 +636,12 @@ class EditSettingsForm extends Component<IProps, IState> {
632 {intl.formatMessage(messages.sectionServiceIconsSettings)} 636 {intl.formatMessage(messages.sectionServiceIconsSettings)}
633 </H2> 637 </H2>
634 638
635 <Toggle field={form.$('showDisabledServices')} /> 639 <Toggle {...form.$('showDisabledServices').bind()} />
636 <Toggle field={form.$('showServiceName')} /> 640 <Toggle {...form.$('showServiceName').bind()} />
637 641
638 {isUseGrayscaleServicesEnabled && <Hr />} 642 {isUseGrayscaleServicesEnabled && <Hr />}
639 643
640 <Toggle field={form.$('useGrayscaleServices')} /> 644 <Toggle {...form.$('useGrayscaleServices').bind()} />
641 645
642 {isUseGrayscaleServicesEnabled && ( 646 {isUseGrayscaleServicesEnabled && (
643 <> 647 <>
@@ -650,8 +654,8 @@ class EditSettingsForm extends Component<IProps, IState> {
650 </> 654 </>
651 )} 655 )}
652 656
653 <Toggle field={form.$('showMessageBadgeWhenMuted')} /> 657 <Toggle {...form.$('showMessageBadgeWhenMuted').bind()} />
654 <Toggle field={form.$('enableLongPressServiceHint')} /> 658 <Toggle {...form.$('enableLongPressServiceHint').bind()} />
655 <Select field={form.$('iconSize')} /> 659 <Select field={form.$('iconSize')} />
656 660
657 <Select field={form.$('navigationBarBehaviour')} /> 661 <Select field={form.$('navigationBarBehaviour')} />
@@ -662,7 +666,7 @@ class EditSettingsForm extends Component<IProps, IState> {
662 {intl.formatMessage(messages.sectionHibernation)} 666 {intl.formatMessage(messages.sectionHibernation)}
663 </H2> 667 </H2>
664 <Select field={form.$('hibernationStrategy')} /> 668 <Select field={form.$('hibernationStrategy')} />
665 <Toggle field={form.$('hibernateOnStartup')} /> 669 <Toggle {...form.$('hibernateOnStartup').bind()} />
666 <p 670 <p
667 className="settings__message" 671 className="settings__message"
668 style={{ 672 style={{
@@ -677,7 +681,7 @@ class EditSettingsForm extends Component<IProps, IState> {
677 681
678 <Select field={form.$('wakeUpStrategy')} /> 682 <Select field={form.$('wakeUpStrategy')} />
679 <Select field={form.$('wakeUpHibernationStrategy')} /> 683 <Select field={form.$('wakeUpHibernationStrategy')} />
680 <Toggle field={form.$('wakeUpHibernationSplay')} /> 684 <Toggle {...form.$('wakeUpHibernationSplay').bind()} />
681 </div> 685 </div>
682 )} 686 )}
683 687
@@ -687,15 +691,15 @@ class EditSettingsForm extends Component<IProps, IState> {
687 <H2 className="settings__section_header"> 691 <H2 className="settings__section_header">
688 {intl.formatMessage(messages.sectionGeneralUi)} 692 {intl.formatMessage(messages.sectionGeneralUi)}
689 </H2> 693 </H2>
690 {isMac && <Toggle field={form.$('showDragArea')} />} 694 {isMac && <Toggle {...form.$('showDragArea').bind()} />}
691 695
692 <Toggle field={form.$('adaptableDarkMode')} /> 696 <Toggle {...form.$('adaptableDarkMode').bind()} />
693 {!isAdaptableDarkModeEnabled && ( 697 {!isAdaptableDarkModeEnabled && (
694 <Toggle field={form.$('darkMode')} /> 698 <Toggle {...form.$('darkMode').bind()} />
695 )} 699 )}
696 {(isDarkmodeEnabled || isAdaptableDarkModeEnabled) && ( 700 {(isDarkmodeEnabled || isAdaptableDarkModeEnabled) && (
697 <> 701 <>
698 <Toggle field={form.$('universalDarkMode')} /> 702 <Toggle {...form.$('universalDarkMode').bind()} />
699 <p 703 <p
700 className="settings__message" 704 className="settings__message"
701 style={{ 705 style={{
@@ -713,7 +717,7 @@ class EditSettingsForm extends Component<IProps, IState> {
713 )} 717 )}
714 718
715 {isSplitModeEnabled && <Hr />} 719 {isSplitModeEnabled && <Hr />}
716 <Toggle field={form.$('splitMode')} /> 720 <Toggle {...form.$('splitMode').bind()} />
717 {isSplitModeEnabled && ( 721 {isSplitModeEnabled && (
718 <Input 722 <Input
719 type="number" 723 type="number"
@@ -776,21 +780,21 @@ class EditSettingsForm extends Component<IProps, IState> {
776 780
777 <Select field={form.$('sidebarServicesLocation')} /> 781 <Select field={form.$('sidebarServicesLocation')} />
778 782
779 <Toggle field={form.$('useHorizontalStyle')} /> 783 <Toggle {...form.$('useHorizontalStyle').bind()} />
780 784
781 <Toggle field={form.$('hideCollapseButton')} /> 785 <Toggle {...form.$('hideCollapseButton').bind()} />
782 786
783 <Toggle field={form.$('hideRecipesButton')} /> 787 <Toggle {...form.$('hideRecipesButton').bind()} />
784 788
785 <Toggle field={form.$('hideSplitModeButton')} /> 789 <Toggle {...form.$('hideSplitModeButton').bind()} />
786 790
787 <Toggle field={form.$('hideWorkspacesButton')} /> 791 <Toggle {...form.$('hideWorkspacesButton').bind()} />
788 792
789 <Toggle field={form.$('hideNotificationsButton')} /> 793 <Toggle {...form.$('hideNotificationsButton').bind()} />
790 794
791 <Toggle field={form.$('hideSettingsButton')} /> 795 <Toggle {...form.$('hideSettingsButton').bind()} />
792 796
793 <Toggle field={form.$('alwaysShowWorkspaces')} /> 797 <Toggle {...form.$('alwaysShowWorkspaces').bind()} />
794 </div> 798 </div>
795 )} 799 )}
796 800
@@ -801,17 +805,17 @@ class EditSettingsForm extends Component<IProps, IState> {
801 {intl.formatMessage(messages.sectionPrivacy)} 805 {intl.formatMessage(messages.sectionPrivacy)}
802 </H2> 806 </H2>
803 807
804 <Toggle field={form.$('privateNotifications')} /> 808 <Toggle {...form.$('privateNotifications').bind()} />
805 <Toggle field={form.$('clipboardNotifications')} /> 809 <Toggle {...form.$('clipboardNotifications').bind()} />
806 {(isWindows || isMac) && ( 810 {(isWindows || isMac) && (
807 <Toggle field={form.$('notifyTaskBarOnMessage')} /> 811 <Toggle {...form.$('notifyTaskBarOnMessage').bind()} />
808 )} 812 )}
809 813
810 <Hr /> 814 <Hr />
811 815
812 <Select field={form.$('webRTCIPHandlingPolicy')} /> 816 <Select field={form.$('webRTCIPHandlingPolicy')} />
813 817
814 <Toggle field={form.$('sentry')} /> 818 <Toggle {...form.$('sentry').bind()} />
815 <p className="settings__help"> 819 <p className="settings__help">
816 {intl.formatMessage(messages.sentryInfo)} 820 {intl.formatMessage(messages.sentryInfo)}
817 </p> 821 </p>
@@ -830,11 +834,11 @@ class EditSettingsForm extends Component<IProps, IState> {
830 834
831 <Hr /> 835 <Hr />
832 836
833 <Toggle field={form.$('lockingFeatureEnabled')} /> 837 <Toggle {...form.$('lockingFeatureEnabled').bind()} />
834 {lockingFeatureEnabled && ( 838 {lockingFeatureEnabled && (
835 <> 839 <>
836 {isMac && systemPreferences.canPromptTouchID() && ( 840 {isMac && systemPreferences.canPromptTouchID() && (
837 <Toggle field={form.$('useTouchIdToUnlock')} /> 841 <Toggle {...form.$('useTouchIdToUnlock').bind()} />
838 )} 842 )}
839 843
840 <Input 844 <Input
@@ -885,7 +889,7 @@ class EditSettingsForm extends Component<IProps, IState> {
885 889
886 <Hr /> 890 <Hr />
887 891
888 <Toggle field={form.$('enableSpellchecking')} /> 892 <Toggle {...form.$('enableSpellchecking').bind()} />
889 {!isMac && form.$('enableSpellchecking').value && ( 893 {!isMac && form.$('enableSpellchecking').value && (
890 <Select field={form.$('spellcheckerLanguage')} /> 894 <Select field={form.$('spellcheckerLanguage')} />
891 )} 895 )}
@@ -901,7 +905,7 @@ class EditSettingsForm extends Component<IProps, IState> {
901 905
902 <Hr /> 906 <Hr />
903 907
904 <Toggle field={form.$('enableTranslator')} /> 908 <Toggle {...form.$('enableTranslator').bind()} />
905 909
906 {form.$('enableTranslator').value && ( 910 {form.$('enableTranslator').value && (
907 <Select field={form.$('translatorEngine')} /> 911 <Select field={form.$('translatorEngine')} />
@@ -931,8 +935,8 @@ class EditSettingsForm extends Component<IProps, IState> {
931 {intl.formatMessage(messages.sectionAdvanced)} 935 {intl.formatMessage(messages.sectionAdvanced)}
932 </H2> 936 </H2>
933 937
934 <Toggle field={form.$('enableGPUAcceleration')} /> 938 <Toggle {...form.$('enableGPUAcceleration').bind()} />
935 <Toggle field={form.$('enableGlobalHideShortcut')} /> 939 <Toggle {...form.$('enableGlobalHideShortcut').bind()} />
936 <p className="settings__help indented__help"> 940 <p className="settings__help indented__help">
937 {intl.formatMessage(messages.appRestartRequired)} 941 {intl.formatMessage(messages.appRestartRequired)}
938 </p> 942 </p>
@@ -1036,12 +1040,12 @@ class EditSettingsForm extends Component<IProps, IState> {
1036 {intl.formatMessage(messages.sectionUpdates)} 1040 {intl.formatMessage(messages.sectionUpdates)}
1037 </H2> 1041 </H2>
1038 1042
1039 <Toggle field={form.$('automaticUpdates')} /> 1043 <Toggle {...form.$('automaticUpdates').bind()} />
1040 {automaticUpdates && ( 1044 {automaticUpdates && (
1041 <> 1045 <>
1042 <> 1046 <>
1043 <div> 1047 <div>
1044 <Toggle field={form.$('beta')} /> 1048 <Toggle {...form.$('beta').bind()} />
1045 {updateIsReadyToInstall ? ( 1049 {updateIsReadyToInstall ? (
1046 <Button 1050 <Button
1047 label={intl.formatMessage( 1051 label={intl.formatMessage(
diff --git a/src/components/ui/Toggle.js b/src/components/ui/Toggle.js
deleted file mode 100644
index c1d86a7f6..000000000
--- a/src/components/ui/Toggle.js
+++ /dev/null
@@ -1,72 +0,0 @@
1import { Component } from 'react';
2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react';
4import classnames from 'classnames';
5import { Field } from 'mobx-react-form';
6
7// Can this file be merged into the './toggle/index.tsx' file?
8class Toggle extends Component {
9 static propTypes = {
10 field: PropTypes.instanceOf(Field).isRequired,
11 className: PropTypes.string,
12 showLabel: PropTypes.bool,
13 disabled: PropTypes.bool,
14 };
15
16 static defaultProps = {
17 className: '',
18 showLabel: true,
19 disabled: false,
20 };
21
22 onChange(e) {
23 const { field } = this.props;
24
25 field.onChange(e);
26 }
27
28 render() {
29 const { field, className, showLabel, disabled } = this.props;
30
31 if (field.value === '' && field.default !== '') {
32 field.value = field.default;
33 }
34
35 return (
36 <div
37 className={classnames([
38 'franz-form__field',
39 'franz-form__toggle-wrapper',
40 'franz-form__toggle-disabled',
41 className,
42 ])}
43 >
44 <label
45 htmlFor={field.id}
46 className={classnames({
47 'franz-form__toggle': true,
48 'is-active': field.value,
49 })}
50 >
51 <div className="franz-form__toggle-button" />
52 <input
53 type="checkbox"
54 id={field.id}
55 name={field.name}
56 value={field.name}
57 checked={field.value}
58 onChange={e => (!disabled ? this.onChange(e) : null)}
59 />
60 </label>
61 {field.error && <div className={field.error}>{field.error}</div>}
62 {field.label && showLabel && (
63 <label className="franz-form__label" htmlFor={field.id}>
64 {field.label}
65 </label>
66 )}
67 </div>
68 );
69 }
70}
71
72export default observer(Toggle);
diff --git a/src/components/ui/button/index.tsx b/src/components/ui/button/index.tsx
index c1e647bc0..dc984bf95 100644
--- a/src/components/ui/button/index.tsx
+++ b/src/components/ui/button/index.tsx
@@ -2,7 +2,7 @@ import Icon from '@mdi/react';
2import classnames from 'classnames'; 2import classnames from 'classnames';
3import { Property } from 'csstype'; 3import { Property } from 'csstype';
4import { noop } from 'lodash'; 4import { noop } from 'lodash';
5import { Component, MouseEvent } from 'react'; 5import { Component, MouseEventHandler } from 'react';
6import withStyles, { WithStylesProps } from 'react-jss'; 6import withStyles, { WithStylesProps } from 'react-jss';
7import Loader from 'react-loader'; 7import Loader from 'react-loader';
8import { Theme } from '../../../themes'; 8import { Theme } from '../../../themes';
@@ -136,7 +136,7 @@ interface IProps extends IFormField, WithStylesProps<typeof styles> {
136 disabled?: boolean; 136 disabled?: boolean;
137 id?: string; 137 id?: string;
138 type?: 'button' | 'reset' | 'submit' | undefined; 138 type?: 'button' | 'reset' | 'submit' | undefined;
139 onClick: (event: MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => void; 139 onClick?: MouseEventHandler<HTMLInputElement>;
140 buttonType?: ButtonType; 140 buttonType?: ButtonType;
141 loaded?: boolean; 141 loaded?: boolean;
142 busy?: boolean; 142 busy?: boolean;
diff --git a/src/components/ui/toggle/index.tsx b/src/components/ui/toggle/index.tsx
index d478cbba5..fee8adbc7 100644
--- a/src/components/ui/toggle/index.tsx
+++ b/src/components/ui/toggle/index.tsx
@@ -1,27 +1,26 @@
1import classnames from 'classnames'; 1import classnames from 'classnames';
2import { Property } from 'csstype'; 2import { Property } from 'csstype';
3import { noop } from 'lodash';
3import { Component, InputHTMLAttributes } from 'react'; 4import { Component, InputHTMLAttributes } from 'react';
4import injectStyle, { WithStylesProps } from 'react-jss'; 5import withStyles, { WithStylesProps } from 'react-jss';
5
6import { Theme } from '../../../themes'; 6import { Theme } from '../../../themes';
7import { IFormField } from '../typings/generic';
8
9import Error from '../error'; 7import Error from '../error';
10import Label from '../label'; 8import Label from '../label';
9import { IFormField } from '../typings/generic';
11import Wrapper from '../wrapper'; 10import Wrapper from '../wrapper';
12 11
13interface IProps 12interface IProps
14 extends InputHTMLAttributes<HTMLInputElement>, 13 extends Omit<InputHTMLAttributes<HTMLInputElement>, 'value'>,
15 IFormField, 14 IFormField,
16 WithStylesProps<typeof styles> { 15 WithStylesProps<typeof styles> {
17 className?: string; 16 className?: string;
17 value: boolean | undefined; // due to type capability between InputHTMLAttributes and mobx-react-form
18} 18}
19 19
20let buttonTransition: string = 'none'; 20const buttonTransition: string =
21 21 window && window.matchMedia('(prefers-reduced-motion: no-preference)')
22if (window && window.matchMedia('(prefers-reduced-motion: no-preference)')) { 22 ? 'all .5s'
23 buttonTransition = 'all .5s'; 23 : 'none';
24}
25 24
26const styles = (theme: Theme) => ({ 25const styles = (theme: Theme) => ({
27 toggle: { 26 toggle: {
@@ -64,25 +63,18 @@ const styles = (theme: Theme) => ({
64}); 63});
65 64
66class ToggleComponent extends Component<IProps> { 65class ToggleComponent extends Component<IProps> {
67 public static defaultProps = {
68 onChange: () => {},
69 showLabel: true,
70 disabled: false,
71 error: '',
72 };
73
74 render() { 66 render() {
75 const { 67 const {
76 classes, 68 classes,
77 className, 69 className,
78 disabled, 70 id = '',
79 error, 71 name = '',
80 id, 72 label = '',
81 label, 73 error = '',
82 showLabel, 74 value = false,
83 checked, 75 showLabel = true,
84 value, 76 disabled = false,
85 onChange, 77 onChange = noop,
86 } = this.props; 78 } = this.props;
87 79
88 return ( 80 return (
@@ -102,24 +94,24 @@ class ToggleComponent extends Component<IProps> {
102 <div 94 <div
103 className={classnames({ 95 className={classnames({
104 [`${classes.button}`]: true, 96 [`${classes.button}`]: true,
105 [`${classes.buttonActive}`]: checked, 97 [`${classes.buttonActive}`]: value,
106 })} 98 })}
107 /> 99 />
108 <input 100 <input
109 className={classes.input}
110 id={id}
111 type="checkbox" 101 type="checkbox"
112 checked={checked} 102 id={id}
113 value={value} 103 name={name}
104 checked={value as boolean | undefined}
105 className={classes.input}
114 onChange={onChange} 106 onChange={onChange}
115 disabled={disabled} 107 disabled={disabled}
116 /> 108 />
117 </div> 109 </div>
118 </Label> 110 </Label>
119 {error && <Error message={error} />} 111 {error ? <Error message={error as string} /> : null}
120 </Wrapper> 112 </Wrapper>
121 ); 113 );
122 } 114 }
123} 115}
124 116
125export default injectStyle(styles, { injectTheme: true })(ToggleComponent); 117export default withStyles(styles, { injectTheme: true })(ToggleComponent);
diff --git a/src/features/workspaces/components/EditWorkspaceForm.js b/src/features/workspaces/components/EditWorkspaceForm.js
index 6bc9ae6f0..ff4e71260 100644
--- a/src/features/workspaces/components/EditWorkspaceForm.js
+++ b/src/features/workspaces/components/EditWorkspaceForm.js
@@ -4,7 +4,6 @@ import { observer } from 'mobx-react';
4import { defineMessages, injectIntl } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5import { Link } from 'react-router-dom'; 5import { Link } from 'react-router-dom';
6import injectSheet from 'react-jss'; 6import injectSheet from 'react-jss';
7
8import Infobox from '../../../components/ui/infobox/index'; 7import Infobox from '../../../components/ui/infobox/index';
9import Input from '../../../components/ui/input/index'; 8import Input from '../../../components/ui/input/index';
10import Button from '../../../components/ui/button'; 9import Button from '../../../components/ui/button';
@@ -14,10 +13,8 @@ import Form from '../../../lib/Form';
14import { required } from '../../../helpers/validation-helpers'; 13import { required } from '../../../helpers/validation-helpers';
15import WorkspaceServiceListItem from './WorkspaceServiceListItem'; 14import WorkspaceServiceListItem from './WorkspaceServiceListItem';
16import Request from '../../../stores/lib/Request'; 15import Request from '../../../stores/lib/Request';
17
18import { KEEP_WS_LOADED_USID } from '../../../config'; 16import { KEEP_WS_LOADED_USID } from '../../../config';
19 17import Toggle from '../../../components/ui/toggle';
20import Toggle from '../../../components/ui/Toggle';
21import { H2 } from '../../../components/ui/headline'; 18import { H2 } from '../../../components/ui/headline';
22 19
23const messages = defineMessages({ 20const messages = defineMessages({
@@ -176,7 +173,7 @@ class EditWorkspaceForm extends Component {
176 )} 173 )}
177 <div className={classes.nameInput}> 174 <div className={classes.nameInput}>
178 <Input {...form.$('name').bind()} /> 175 <Input {...form.$('name').bind()} />
179 <Toggle field={form.$('keepLoaded')} /> 176 <Toggle {...form.$('keepLoaded').bind()} />
180 <p className={`${classes.keepLoadedInfo} franz-form__label`}> 177 <p className={`${classes.keepLoadedInfo} franz-form__label`}>
181 {intl.formatMessage(messages.keepLoadedInfo)} 178 {intl.formatMessage(messages.keepLoadedInfo)}
182 </p> 179 </p>
diff --git a/src/features/workspaces/components/WorkspaceServiceListItem.tsx b/src/features/workspaces/components/WorkspaceServiceListItem.tsx
index 0233d5749..420aed595 100644
--- a/src/features/workspaces/components/WorkspaceServiceListItem.tsx
+++ b/src/features/workspaces/components/WorkspaceServiceListItem.tsx
@@ -1,10 +1,10 @@
1import { Component } from 'react'; 1import { Component, ReactElement } from 'react';
2import { observer } from 'mobx-react'; 2import { observer } from 'mobx-react';
3import injectSheet from 'react-jss'; 3import withStyles, { WithStylesProps } from 'react-jss';
4import classnames from 'classnames'; 4import classnames from 'classnames';
5 5import Toggle from '../../../components/ui/toggle';
6import Toggle from '../../../components/ui/toggle/index';
7import ServiceIcon from '../../../components/ui/ServiceIcon'; 6import ServiceIcon from '../../../components/ui/ServiceIcon';
7import Service from '../../../models/Service';
8 8
9const styles = theme => ({ 9const styles = theme => ({
10 listItem: { 10 listItem: {
@@ -29,15 +29,15 @@ const styles = theme => ({
29 }, 29 },
30}); 30});
31 31
32type Props = { 32interface IProps extends WithStylesProps<typeof styles> {
33 classes: any;
34 isInWorkspace: boolean; 33 isInWorkspace: boolean;
35 onToggle: () => void; 34 onToggle: () => void;
36 service: any; 35 service: Service;
37}; 36}
38 37
39class WorkspaceServiceListItem extends Component<Props> { 38@observer
40 render() { 39class WorkspaceServiceListItem extends Component<IProps> {
40 render(): ReactElement {
41 const { classes, isInWorkspace, onToggle, service } = this.props; 41 const { classes, isInWorkspace, onToggle, service } = this.props;
42 42
43 return ( 43 return (
@@ -53,7 +53,7 @@ class WorkspaceServiceListItem extends Component<Props> {
53 </span> 53 </span>
54 <Toggle 54 <Toggle
55 className={classes.toggle} 55 className={classes.toggle}
56 checked={isInWorkspace} 56 value={isInWorkspace}
57 onChange={onToggle} 57 onChange={onToggle}
58 /> 58 />
59 </div> 59 </div>
@@ -61,6 +61,6 @@ class WorkspaceServiceListItem extends Component<Props> {
61 } 61 }
62} 62}
63 63
64export default injectSheet(styles, { injectTheme: true })( 64export default withStyles(styles, { injectTheme: true })(
65 observer(WorkspaceServiceListItem), 65 WorkspaceServiceListItem,
66); 66);
diff --git a/src/lib/Tray.ts b/src/lib/Tray.ts
index 8e489edde..dafbb68aa 100644
--- a/src/lib/Tray.ts
+++ b/src/lib/Tray.ts
@@ -20,7 +20,7 @@ const INDICATOR_TRAY_INDIRECT = 'tray-indirect';
20 20
21// TODO: Need to support i18n for a lot of the hard-coded strings in this file 21// TODO: Need to support i18n for a lot of the hard-coded strings in this file
22export default class TrayIcon { 22export default class TrayIcon {
23 trayIcon: Tray | null = null; 23 tray: Tray | null = null;
24 24
25 indicator: string | number = 0; 25 indicator: string | number = 0;
26 26
@@ -97,7 +97,9 @@ export default class TrayIcon {
97 } 97 }
98 98
99 _updateTrayMenu(appSettings): void { 99 _updateTrayMenu(appSettings): void {
100 if (!this.trayIcon) return; 100 if (!this.tray) {
101 return;
102 }
101 103
102 if (appSettings && appSettings.type === 'app') { 104 if (appSettings && appSettings.type === 'app') {
103 this.isAppMuted = appSettings.data.isAppMuted; // save current state after a change 105 this.isAppMuted = appSettings.data.isAppMuted; // save current state after a change
@@ -105,7 +107,7 @@ export default class TrayIcon {
105 107
106 this.trayMenu = Menu.buildFromTemplate(this.trayMenuTemplate(this)); 108 this.trayMenu = Menu.buildFromTemplate(this.trayMenuTemplate(this));
107 if (isLinux) { 109 if (isLinux) {
108 this.trayIcon.setContextMenu(this.trayMenu); 110 this.tray.setContextMenu(this.trayMenu);
109 } 111 }
110 } 112 }
111 113
@@ -115,26 +117,26 @@ export default class TrayIcon {
115 } 117 }
116 118
117 _show(): void { 119 _show(): void {
118 if (this.trayIcon) { 120 if (this.tray) {
119 return; 121 return;
120 } 122 }
121 123
122 this.trayIcon = new Tray(this._getAsset('tray', INDICATOR_TRAY_PLAIN)); 124 this.tray = new Tray(this._getAsset('tray', INDICATOR_TRAY_PLAIN));
123 this.trayIcon.setToolTip('Ferdium'); 125 this.tray.setToolTip('Ferdium');
124 126
125 this.trayMenu = Menu.buildFromTemplate(this.trayMenuTemplate(this)); 127 this.trayMenu = Menu.buildFromTemplate(this.trayMenuTemplate(this));
126 if (isLinux) { 128 if (isLinux) {
127 this.trayIcon.setContextMenu(this.trayMenu); 129 this.tray.setContextMenu(this.trayMenu);
128 } 130 }
129 131
130 this.trayIcon.on('click', () => { 132 this.tray.on('click', () => {
131 this._toggleWindow(); 133 this._toggleWindow();
132 }); 134 });
133 135
134 if (isMac || isWindows) { 136 if (isMac || isWindows) {
135 this.trayIcon.on('right-click', () => { 137 this.tray.on('right-click', () => {
136 if (this.trayIcon && this.trayMenu) { 138 if (this.tray && this.trayMenu) {
137 this.trayIcon.popUpContextMenu(this.trayMenu); 139 this.tray.popUpContextMenu(this.trayMenu);
138 } 140 }
139 }); 141 });
140 } 142 }
@@ -177,10 +179,10 @@ export default class TrayIcon {
177 } 179 }
178 180
179 _hide(): void { 181 _hide(): void {
180 if (!this.trayIcon) return; 182 if (!this.tray) return;
181 183
182 this.trayIcon.destroy(); 184 this.tray.destroy();
183 this.trayIcon = null; 185 this.tray = null;
184 186
185 if (isMac && this.themeChangeSubscriberId) { 187 if (isMac && this.themeChangeSubscriberId) {
186 systemPreferences.unsubscribeNotification(this.themeChangeSubscriberId); 188 systemPreferences.unsubscribeNotification(this.themeChangeSubscriberId);
@@ -216,16 +218,16 @@ export default class TrayIcon {
216 } 218 }
217 219
218 _refreshIcon(): void { 220 _refreshIcon(): void {
219 if (!this.trayIcon) { 221 if (!this.tray) {
220 return; 222 return;
221 } 223 }
222 224
223 this.trayIcon.setImage( 225 this.tray.setImage(
224 this._getAsset('tray', this._getAssetFromIndicator(this.indicator)), 226 this._getAsset('tray', this._getAssetFromIndicator(this.indicator)),
225 ); 227 );
226 228
227 if (isMac && !macosVersion.isGreaterThanOrEqualTo('11')) { 229 if (isMac && !macosVersion.isGreaterThanOrEqualTo('11')) {
228 this.trayIcon.setPressedImage( 230 this.tray.setPressedImage(
229 this._getAsset( 231 this._getAsset(
230 'tray', 232 'tray',
231 `${this._getAssetFromIndicator(this.indicator)}-active`, 233 `${this._getAssetFromIndicator(this.indicator)}-active`,