diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/actions/app.js | 4 | ||||
-rw-r--r-- | src/actions/service.js | 3 | ||||
-rw-r--r-- | src/components/layout/Sidebar.js | 52 | ||||
-rw-r--r-- | src/components/services/content/ServiceWebview.js | 4 | ||||
-rw-r--r-- | src/components/services/content/Services.js | 3 | ||||
-rw-r--r-- | src/components/services/tabs/TabBarSortableList.js | 22 | ||||
-rw-r--r-- | src/components/services/tabs/TabItem.js | 15 | ||||
-rw-r--r-- | src/components/services/tabs/Tabbar.js | 3 | ||||
-rw-r--r-- | src/config.js | 1 | ||||
-rw-r--r-- | src/containers/layout/AppLayoutContainer.js | 16 | ||||
-rw-r--r-- | src/i18n/locales/en-US.json | 4 | ||||
-rw-r--r-- | src/stores/AppStore.js | 14 | ||||
-rw-r--r-- | src/stores/ServicesStore.js | 17 | ||||
-rw-r--r-- | src/styles/layout.scss | 32 | ||||
-rw-r--r-- | src/styles/tabs.scss | 7 |
15 files changed, 139 insertions, 58 deletions
diff --git a/src/actions/app.js b/src/actions/app.js index 5db4b739e..25ff9344d 100644 --- a/src/actions/app.js +++ b/src/actions/app.js | |||
@@ -20,4 +20,8 @@ export default { | |||
20 | resetUpdateStatus: {}, | 20 | resetUpdateStatus: {}, |
21 | installUpdate: {}, | 21 | installUpdate: {}, |
22 | healthCheck: {}, | 22 | healthCheck: {}, |
23 | muteApp: { | ||
24 | isMuted: PropTypes.bool.isRequired, | ||
25 | }, | ||
26 | toggleMuteApp: {}, | ||
23 | }; | 27 | }; |
diff --git a/src/actions/service.js b/src/actions/service.js index ea6ea5acc..1b918251b 100644 --- a/src/actions/service.js +++ b/src/actions/service.js | |||
@@ -71,6 +71,9 @@ export default { | |||
71 | toggleNotifications: { | 71 | toggleNotifications: { |
72 | serviceId: PropTypes.string.isRequired, | 72 | serviceId: PropTypes.string.isRequired, |
73 | }, | 73 | }, |
74 | toggleAudio: { | ||
75 | serviceId: PropTypes.string.isRequired, | ||
76 | }, | ||
74 | openDevTools: { | 77 | openDevTools: { |
75 | serviceId: PropTypes.string.isRequired, | 78 | serviceId: PropTypes.string.isRequired, |
76 | }, | 79 | }, |
diff --git a/src/components/layout/Sidebar.js b/src/components/layout/Sidebar.js index 6a5c0f365..72ee2b3b7 100644 --- a/src/components/layout/Sidebar.js +++ b/src/components/layout/Sidebar.js | |||
@@ -11,16 +11,25 @@ const messages = defineMessages({ | |||
11 | id: 'sidebar.settings', | 11 | id: 'sidebar.settings', |
12 | defaultMessage: '!!!Settings', | 12 | defaultMessage: '!!!Settings', |
13 | }, | 13 | }, |
14 | addNewService: { | ||
15 | id: 'sidebar.addNewService', | ||
16 | defaultMessage: '!!!Add new service', | ||
17 | }, | ||
18 | mute: { | ||
19 | id: 'sidebar.mute', | ||
20 | defaultMessage: '!!!Disable audio', | ||
21 | }, | ||
22 | unmute: { | ||
23 | id: 'sidebar.unmute', | ||
24 | defaultMessage: '!!!Enable audio', | ||
25 | }, | ||
14 | }); | 26 | }); |
15 | 27 | ||
16 | export default class Sidebar extends Component { | 28 | export default class Sidebar extends Component { |
17 | static propTypes = { | 29 | static propTypes = { |
18 | openSettings: PropTypes.func.isRequired, | 30 | openSettings: PropTypes.func.isRequired, |
19 | isPremiumUser: PropTypes.bool, | 31 | toggleMuteApp: PropTypes.func.isRequired, |
20 | } | 32 | isAppMuted: PropTypes.bool.isRequired, |
21 | |||
22 | static defaultProps = { | ||
23 | isPremiumUser: false, | ||
24 | } | 33 | } |
25 | 34 | ||
26 | static contextTypes = { | 35 | static contextTypes = { |
@@ -40,8 +49,9 @@ export default class Sidebar extends Component { | |||
40 | } | 49 | } |
41 | 50 | ||
42 | render() { | 51 | render() { |
43 | const { openSettings, isPremiumUser } = this.props; | 52 | const { openSettings, toggleMuteApp, isAppMuted } = this.props; |
44 | const { intl } = this.context; | 53 | const { intl } = this.context; |
54 | |||
45 | return ( | 55 | return ( |
46 | <div className="sidebar"> | 56 | <div className="sidebar"> |
47 | <Tabbar | 57 | <Tabbar |
@@ -50,21 +60,25 @@ export default class Sidebar extends Component { | |||
50 | disableToolTip={() => this.disableToolTip()} | 60 | disableToolTip={() => this.disableToolTip()} |
51 | /> | 61 | /> |
52 | <button | 62 | <button |
53 | onClick={openSettings} | 63 | onClick={toggleMuteApp} |
54 | className="sidebar__settings-button" | 64 | className={`sidebar__button ${isAppMuted ? 'is-muted' : ''}`} |
65 | data-tip={`${intl.formatMessage(isAppMuted ? messages.unmute : messages.mute)} (${ctrlKey}+Shift+M)`} | ||
66 | > | ||
67 | <i className={`mdi mdi-bell${isAppMuted ? '-off' : ''}`} /> | ||
68 | </button> | ||
69 | <button | ||
70 | onClick={() => openSettings({ path: 'recipes' })} | ||
71 | className="sidebar__button" | ||
72 | data-tip={`${intl.formatMessage(messages.addNewService)} (${ctrlKey}+N)`} | ||
73 | > | ||
74 | <i className="mdi mdi-plus-box" /> | ||
75 | </button> | ||
76 | <button | ||
77 | onClick={() => openSettings({ path: 'app' })} | ||
78 | className="sidebar__button" | ||
55 | data-tip={`${intl.formatMessage(messages.settings)} (${ctrlKey}+,)`} | 79 | data-tip={`${intl.formatMessage(messages.settings)} (${ctrlKey}+,)`} |
56 | > | 80 | > |
57 | {isPremiumUser && ( | 81 | <i className="mdi mdi-settings" /> |
58 | <span className="emoji"> | ||
59 | <img src="./assets/images/emoji/star.png" alt="" /> | ||
60 | </span> | ||
61 | )} | ||
62 | <img | ||
63 | src="./assets/images/logo.svg" | ||
64 | className="sidebar__logo" | ||
65 | alt="" | ||
66 | /> | ||
67 | {intl.formatMessage(messages.settings)} | ||
68 | </button> | 82 | </button> |
69 | {this.state.tooltipEnabled && ( | 83 | {this.state.tooltipEnabled && ( |
70 | <ReactTooltip place="right" type="dark" effect="solid" /> | 84 | <ReactTooltip place="right" type="dark" effect="solid" /> |
diff --git a/src/components/services/content/ServiceWebview.js b/src/components/services/content/ServiceWebview.js index d7e0a4f38..60bdf7e47 100644 --- a/src/components/services/content/ServiceWebview.js +++ b/src/components/services/content/ServiceWebview.js | |||
@@ -15,6 +15,7 @@ export default class ServiceWebview extends Component { | |||
15 | service: PropTypes.instanceOf(ServiceModel).isRequired, | 15 | service: PropTypes.instanceOf(ServiceModel).isRequired, |
16 | setWebviewReference: PropTypes.func.isRequired, | 16 | setWebviewReference: PropTypes.func.isRequired, |
17 | reload: PropTypes.func.isRequired, | 17 | reload: PropTypes.func.isRequired, |
18 | isAppMuted: PropTypes.bool.isRequired, | ||
18 | }; | 19 | }; |
19 | 20 | ||
20 | static defaultProps = { | 21 | static defaultProps = { |
@@ -56,6 +57,7 @@ export default class ServiceWebview extends Component { | |||
56 | service, | 57 | service, |
57 | setWebviewReference, | 58 | setWebviewReference, |
58 | reload, | 59 | reload, |
60 | isAppMuted, | ||
59 | } = this.props; | 61 | } = this.props; |
60 | 62 | ||
61 | const webviewClasses = classnames({ | 63 | const webviewClasses = classnames({ |
@@ -92,7 +94,7 @@ export default class ServiceWebview extends Component { | |||
92 | })} | 94 | })} |
93 | onUpdateTargetUrl={this.updateTargetUrl} | 95 | onUpdateTargetUrl={this.updateTargetUrl} |
94 | useragent={service.userAgent} | 96 | useragent={service.userAgent} |
95 | muted={service.isMuted} | 97 | muted={isAppMuted || service.isMuted} |
96 | disablewebsecurity | 98 | disablewebsecurity |
97 | allowpopups | 99 | allowpopups |
98 | /> | 100 | /> |
diff --git a/src/components/services/content/Services.js b/src/components/services/content/Services.js index bad525d22..55a47cdd3 100644 --- a/src/components/services/content/Services.js +++ b/src/components/services/content/Services.js | |||
@@ -26,6 +26,7 @@ export default class Services extends Component { | |||
26 | handleIPCMessage: PropTypes.func.isRequired, | 26 | handleIPCMessage: PropTypes.func.isRequired, |
27 | openWindow: PropTypes.func.isRequired, | 27 | openWindow: PropTypes.func.isRequired, |
28 | reload: PropTypes.func.isRequired, | 28 | reload: PropTypes.func.isRequired, |
29 | isAppMuted: PropTypes.bool.isRequired, | ||
29 | }; | 30 | }; |
30 | 31 | ||
31 | static defaultProps = { | 32 | static defaultProps = { |
@@ -44,6 +45,7 @@ export default class Services extends Component { | |||
44 | setWebviewReference, | 45 | setWebviewReference, |
45 | openWindow, | 46 | openWindow, |
46 | reload, | 47 | reload, |
48 | isAppMuted, | ||
47 | } = this.props; | 49 | } = this.props; |
48 | const { intl } = this.context; | 50 | const { intl } = this.context; |
49 | 51 | ||
@@ -76,6 +78,7 @@ export default class Services extends Component { | |||
76 | setWebviewReference={setWebviewReference} | 78 | setWebviewReference={setWebviewReference} |
77 | openWindow={openWindow} | 79 | openWindow={openWindow} |
78 | reload={() => reload({ serviceId: service.id })} | 80 | reload={() => reload({ serviceId: service.id })} |
81 | isAppMuted={isAppMuted} | ||
79 | /> | 82 | /> |
80 | ))} | 83 | ))} |
81 | </div> | 84 | </div> |
diff --git a/src/components/services/tabs/TabBarSortableList.js b/src/components/services/tabs/TabBarSortableList.js index e5ae36419..0146f5b35 100644 --- a/src/components/services/tabs/TabBarSortableList.js +++ b/src/components/services/tabs/TabBarSortableList.js | |||
@@ -2,17 +2,8 @@ import React, { Component } from 'react'; | |||
2 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; | 2 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; |
3 | import PropTypes from 'prop-types'; | 3 | import PropTypes from 'prop-types'; |
4 | import { SortableContainer } from 'react-sortable-hoc'; | 4 | import { SortableContainer } from 'react-sortable-hoc'; |
5 | import { defineMessages, intlShape } from 'react-intl'; | ||
6 | 5 | ||
7 | import TabItem from './TabItem'; | 6 | import TabItem from './TabItem'; |
8 | import { ctrlKey } from '../../../environment'; | ||
9 | |||
10 | const messages = defineMessages({ | ||
11 | addNewService: { | ||
12 | id: 'sidebar.addNewService', | ||
13 | defaultMessage: '!!!Add new service', | ||
14 | }, | ||
15 | }); | ||
16 | 7 | ||
17 | @observer | 8 | @observer |
18 | class TabBarSortableList extends Component { | 9 | class TabBarSortableList extends Component { |
@@ -22,27 +13,23 @@ class TabBarSortableList extends Component { | |||
22 | openSettings: PropTypes.func.isRequired, | 13 | openSettings: PropTypes.func.isRequired, |
23 | reload: PropTypes.func.isRequired, | 14 | reload: PropTypes.func.isRequired, |
24 | toggleNotifications: PropTypes.func.isRequired, | 15 | toggleNotifications: PropTypes.func.isRequired, |
16 | toggleAudio: PropTypes.func.isRequired, | ||
25 | deleteService: PropTypes.func.isRequired, | 17 | deleteService: PropTypes.func.isRequired, |
26 | disableService: PropTypes.func.isRequired, | 18 | disableService: PropTypes.func.isRequired, |
27 | } | 19 | } |
28 | 20 | ||
29 | static contextTypes = { | ||
30 | intl: intlShape, | ||
31 | }; | ||
32 | |||
33 | render() { | 21 | render() { |
34 | const { | 22 | const { |
35 | services, | 23 | services, |
36 | setActive, | 24 | setActive, |
37 | reload, | 25 | reload, |
38 | toggleNotifications, | 26 | toggleNotifications, |
27 | toggleAudio, | ||
39 | deleteService, | 28 | deleteService, |
40 | disableService, | 29 | disableService, |
41 | openSettings, | 30 | openSettings, |
42 | } = this.props; | 31 | } = this.props; |
43 | 32 | ||
44 | const { intl } = this.context; | ||
45 | |||
46 | return ( | 33 | return ( |
47 | <ul | 34 | <ul |
48 | className="tabs" | 35 | className="tabs" |
@@ -56,12 +43,13 @@ class TabBarSortableList extends Component { | |||
56 | shortcutIndex={index + 1} | 43 | shortcutIndex={index + 1} |
57 | reload={() => reload({ serviceId: service.id })} | 44 | reload={() => reload({ serviceId: service.id })} |
58 | toggleNotifications={() => toggleNotifications({ serviceId: service.id })} | 45 | toggleNotifications={() => toggleNotifications({ serviceId: service.id })} |
46 | toggleAudio={() => toggleAudio({ serviceId: service.id })} | ||
59 | deleteService={() => deleteService({ serviceId: service.id })} | 47 | deleteService={() => deleteService({ serviceId: service.id })} |
60 | disableService={() => disableService({ serviceId: service.id })} | 48 | disableService={() => disableService({ serviceId: service.id })} |
61 | openSettings={openSettings} | 49 | openSettings={openSettings} |
62 | /> | 50 | /> |
63 | ))} | 51 | ))} |
64 | <li> | 52 | {/* <li> |
65 | <button | 53 | <button |
66 | className="sidebar__add-service" | 54 | className="sidebar__add-service" |
67 | onClick={() => openSettings({ path: 'recipes' })} | 55 | onClick={() => openSettings({ path: 'recipes' })} |
@@ -69,7 +57,7 @@ class TabBarSortableList extends Component { | |||
69 | > | 57 | > |
70 | <span className="mdi mdi-plus" /> | 58 | <span className="mdi mdi-plus" /> |
71 | </button> | 59 | </button> |
72 | </li> | 60 | </li> */} |
73 | </ul> | 61 | </ul> |
74 | ); | 62 | ); |
75 | } | 63 | } |
diff --git a/src/components/services/tabs/TabItem.js b/src/components/services/tabs/TabItem.js index 9e03d2e21..7b001f6ee 100644 --- a/src/components/services/tabs/TabItem.js +++ b/src/components/services/tabs/TabItem.js | |||
@@ -28,6 +28,14 @@ const messages = defineMessages({ | |||
28 | id: 'tabs.item.enableNotification', | 28 | id: 'tabs.item.enableNotification', |
29 | defaultMessage: '!!!Enable notifications', | 29 | defaultMessage: '!!!Enable notifications', |
30 | }, | 30 | }, |
31 | disableAudio: { | ||
32 | id: 'tabs.item.disableAudio', | ||
33 | defaultMessage: '!!!Disable audio', | ||
34 | }, | ||
35 | enableAudio: { | ||
36 | id: 'tabs.item.enableAudio', | ||
37 | defaultMessage: '!!!Enable audio', | ||
38 | }, | ||
31 | disableService: { | 39 | disableService: { |
32 | id: 'tabs.item.disableService', | 40 | id: 'tabs.item.disableService', |
33 | defaultMessage: '!!!Disable Service', | 41 | defaultMessage: '!!!Disable Service', |
@@ -46,6 +54,7 @@ class TabItem extends Component { | |||
46 | shortcutIndex: PropTypes.number.isRequired, | 54 | shortcutIndex: PropTypes.number.isRequired, |
47 | reload: PropTypes.func.isRequired, | 55 | reload: PropTypes.func.isRequired, |
48 | toggleNotifications: PropTypes.func.isRequired, | 56 | toggleNotifications: PropTypes.func.isRequired, |
57 | toggleAudio: PropTypes.func.isRequired, | ||
49 | openSettings: PropTypes.func.isRequired, | 58 | openSettings: PropTypes.func.isRequired, |
50 | deleteService: PropTypes.func.isRequired, | 59 | deleteService: PropTypes.func.isRequired, |
51 | disableService: PropTypes.func.isRequired, | 60 | disableService: PropTypes.func.isRequired, |
@@ -62,6 +71,7 @@ class TabItem extends Component { | |||
62 | shortcutIndex, | 71 | shortcutIndex, |
63 | reload, | 72 | reload, |
64 | toggleNotifications, | 73 | toggleNotifications, |
74 | toggleAudio, | ||
65 | deleteService, | 75 | deleteService, |
66 | disableService, | 76 | disableService, |
67 | openSettings, | 77 | openSettings, |
@@ -90,6 +100,11 @@ class TabItem extends Component { | |||
90 | : intl.formatMessage(messages.enableNotifications), | 100 | : intl.formatMessage(messages.enableNotifications), |
91 | click: () => toggleNotifications(), | 101 | click: () => toggleNotifications(), |
92 | }, { | 102 | }, { |
103 | label: service.isMuted | ||
104 | ? intl.formatMessage(messages.enableAudio) | ||
105 | : intl.formatMessage(messages.disableAudio), | ||
106 | click: () => toggleAudio(), | ||
107 | }, { | ||
93 | label: intl.formatMessage(messages.disableService), | 108 | label: intl.formatMessage(messages.disableService), |
94 | click: () => disableService(), | 109 | click: () => disableService(), |
95 | }, { | 110 | }, { |
diff --git a/src/components/services/tabs/Tabbar.js b/src/components/services/tabs/Tabbar.js index fdb2c0a59..e8cd80e33 100644 --- a/src/components/services/tabs/Tabbar.js +++ b/src/components/services/tabs/Tabbar.js | |||
@@ -15,6 +15,7 @@ export default class TabBar extends Component { | |||
15 | reorder: PropTypes.func.isRequired, | 15 | reorder: PropTypes.func.isRequired, |
16 | reload: PropTypes.func.isRequired, | 16 | reload: PropTypes.func.isRequired, |
17 | toggleNotifications: PropTypes.func.isRequired, | 17 | toggleNotifications: PropTypes.func.isRequired, |
18 | toggleAudio: PropTypes.func.isRequired, | ||
18 | deleteService: PropTypes.func.isRequired, | 19 | deleteService: PropTypes.func.isRequired, |
19 | updateService: PropTypes.func.isRequired, | 20 | updateService: PropTypes.func.isRequired, |
20 | } | 21 | } |
@@ -51,6 +52,7 @@ export default class TabBar extends Component { | |||
51 | disableToolTip, | 52 | disableToolTip, |
52 | reload, | 53 | reload, |
53 | toggleNotifications, | 54 | toggleNotifications, |
55 | toggleAudio, | ||
54 | deleteService, | 56 | deleteService, |
55 | } = this.props; | 57 | } = this.props; |
56 | 58 | ||
@@ -63,6 +65,7 @@ export default class TabBar extends Component { | |||
63 | onSortStart={disableToolTip} | 65 | onSortStart={disableToolTip} |
64 | reload={reload} | 66 | reload={reload} |
65 | toggleNotifications={toggleNotifications} | 67 | toggleNotifications={toggleNotifications} |
68 | toggleAudio={toggleAudio} | ||
66 | deleteService={deleteService} | 69 | deleteService={deleteService} |
67 | disableService={this.disableService} | 70 | disableService={this.disableService} |
68 | openSettings={openSettings} | 71 | openSettings={openSettings} |
diff --git a/src/config.js b/src/config.js index 0a4856ece..651f2e174 100644 --- a/src/config.js +++ b/src/config.js | |||
@@ -12,4 +12,5 @@ export const DEFAULT_APP_SETTINGS = { | |||
12 | minimizeToSystemTray: false, | 12 | minimizeToSystemTray: false, |
13 | locale: 'en-us', // TODO: Replace with proper solution once translations are in | 13 | locale: 'en-us', // TODO: Replace with proper solution once translations are in |
14 | beta: false, | 14 | beta: false, |
15 | isAppMuted: false, | ||
15 | }; | 16 | }; |
diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js index 68ad1039e..5ef4fbb35 100644 --- a/src/containers/layout/AppLayoutContainer.js +++ b/src/containers/layout/AppLayoutContainer.js | |||
@@ -7,7 +7,7 @@ import RecipesStore from '../../stores/RecipesStore'; | |||
7 | import ServicesStore from '../../stores/ServicesStore'; | 7 | import ServicesStore from '../../stores/ServicesStore'; |
8 | import UIStore from '../../stores/UIStore'; | 8 | import UIStore from '../../stores/UIStore'; |
9 | import NewsStore from '../../stores/NewsStore'; | 9 | import NewsStore from '../../stores/NewsStore'; |
10 | import UserStore from '../../stores/UserStore'; | 10 | import SettingsStore from '../../stores/SettingsStore'; |
11 | import RequestStore from '../../stores/RequestStore'; | 11 | import RequestStore from '../../stores/RequestStore'; |
12 | import GlobalErrorStore from '../../stores/GlobalErrorStore'; | 12 | import GlobalErrorStore from '../../stores/GlobalErrorStore'; |
13 | 13 | ||
@@ -29,8 +29,8 @@ export default class AppLayoutContainer extends Component { | |||
29 | services, | 29 | services, |
30 | ui, | 30 | ui, |
31 | news, | 31 | news, |
32 | settings, | ||
32 | globalError, | 33 | globalError, |
33 | user, | ||
34 | requests, | 34 | requests, |
35 | } = this.props.stores; | 35 | } = this.props.stores; |
36 | 36 | ||
@@ -43,6 +43,7 @@ export default class AppLayoutContainer extends Component { | |||
43 | reorder, | 43 | reorder, |
44 | reload, | 44 | reload, |
45 | toggleNotifications, | 45 | toggleNotifications, |
46 | toggleAudio, | ||
46 | deleteService, | 47 | deleteService, |
47 | updateService, | 48 | updateService, |
48 | } = this.props.actions.service; | 49 | } = this.props.actions.service; |
@@ -53,6 +54,7 @@ export default class AppLayoutContainer extends Component { | |||
53 | 54 | ||
54 | const { | 55 | const { |
55 | installUpdate, | 56 | installUpdate, |
57 | toggleMuteApp, | ||
56 | } = this.props.actions.app; | 58 | } = this.props.actions.app; |
57 | 59 | ||
58 | const { | 60 | const { |
@@ -79,14 +81,16 @@ export default class AppLayoutContainer extends Component { | |||
79 | <Sidebar | 81 | <Sidebar |
80 | services={allServices} | 82 | services={allServices} |
81 | setActive={setActive} | 83 | setActive={setActive} |
84 | isAppMuted={settings.all.isMuted} | ||
82 | openSettings={openSettings} | 85 | openSettings={openSettings} |
83 | closeSettings={closeSettings} | 86 | closeSettings={closeSettings} |
84 | reorder={reorder} | 87 | reorder={reorder} |
85 | reload={reload} | 88 | reload={reload} |
86 | toggleNotifications={toggleNotifications} | 89 | toggleNotifications={toggleNotifications} |
90 | toggleAudio={toggleAudio} | ||
87 | deleteService={deleteService} | 91 | deleteService={deleteService} |
88 | updateService={updateService} | 92 | updateService={updateService} |
89 | isPremiumUser={user.data.isPremium} | 93 | toggleMuteApp={toggleMuteApp} |
90 | /> | 94 | /> |
91 | ); | 95 | ); |
92 | 96 | ||
@@ -97,6 +101,7 @@ export default class AppLayoutContainer extends Component { | |||
97 | setWebviewReference={setWebviewReference} | 101 | setWebviewReference={setWebviewReference} |
98 | openWindow={openWindow} | 102 | openWindow={openWindow} |
99 | reload={reload} | 103 | reload={reload} |
104 | isAppMuted={settings.all.isMuted} | ||
100 | /> | 105 | /> |
101 | ); | 106 | ); |
102 | 107 | ||
@@ -130,7 +135,7 @@ AppLayoutContainer.wrappedComponent.propTypes = { | |||
130 | app: PropTypes.instanceOf(AppStore).isRequired, | 135 | app: PropTypes.instanceOf(AppStore).isRequired, |
131 | ui: PropTypes.instanceOf(UIStore).isRequired, | 136 | ui: PropTypes.instanceOf(UIStore).isRequired, |
132 | news: PropTypes.instanceOf(NewsStore).isRequired, | 137 | news: PropTypes.instanceOf(NewsStore).isRequired, |
133 | user: PropTypes.instanceOf(UserStore).isRequired, | 138 | settings: PropTypes.instanceOf(SettingsStore).isRequired, |
134 | requests: PropTypes.instanceOf(RequestStore).isRequired, | 139 | requests: PropTypes.instanceOf(RequestStore).isRequired, |
135 | globalError: PropTypes.instanceOf(GlobalErrorStore).isRequired, | 140 | globalError: PropTypes.instanceOf(GlobalErrorStore).isRequired, |
136 | }).isRequired, | 141 | }).isRequired, |
@@ -139,6 +144,7 @@ AppLayoutContainer.wrappedComponent.propTypes = { | |||
139 | setActive: PropTypes.func.isRequired, | 144 | setActive: PropTypes.func.isRequired, |
140 | reload: PropTypes.func.isRequired, | 145 | reload: PropTypes.func.isRequired, |
141 | toggleNotifications: PropTypes.func.isRequired, | 146 | toggleNotifications: PropTypes.func.isRequired, |
147 | toggleAudio: PropTypes.func.isRequired, | ||
142 | handleIPCMessage: PropTypes.func.isRequired, | 148 | handleIPCMessage: PropTypes.func.isRequired, |
143 | setWebviewReference: PropTypes.func.isRequired, | 149 | setWebviewReference: PropTypes.func.isRequired, |
144 | openWindow: PropTypes.func.isRequired, | 150 | openWindow: PropTypes.func.isRequired, |
@@ -156,7 +162,7 @@ AppLayoutContainer.wrappedComponent.propTypes = { | |||
156 | }).isRequired, | 162 | }).isRequired, |
157 | app: PropTypes.shape({ | 163 | app: PropTypes.shape({ |
158 | installUpdate: PropTypes.func.isRequired, | 164 | installUpdate: PropTypes.func.isRequired, |
159 | healthCheck: PropTypes.func.isRequired, | 165 | toggleMuteApp: PropTypes.func.isRequired, |
160 | }).isRequired, | 166 | }).isRequired, |
161 | requests: PropTypes.shape({ | 167 | requests: PropTypes.shape({ |
162 | retryRequiredRequests: PropTypes.func.isRequired, | 168 | retryRequiredRequests: PropTypes.func.isRequired, |
diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json index e298728d1..aa66d4bd0 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json | |||
@@ -61,6 +61,8 @@ | |||
61 | "infobar.requiredRequestsFailed": "Could not load services and user information", | 61 | "infobar.requiredRequestsFailed": "Could not load services and user information", |
62 | "sidebar.settings": "Settings", | 62 | "sidebar.settings": "Settings", |
63 | "sidebar.addNewService": "Add new service", | 63 | "sidebar.addNewService": "Add new service", |
64 | "sidebar.mute": "Disable audio", | ||
65 | "sidebar.unmute": "Enable audio", | ||
64 | "services.welcome": "Welcome to Franz", | 66 | "services.welcome": "Welcome to Franz", |
65 | "services.getStarted": "Get started", | 67 | "services.getStarted": "Get started", |
66 | "settings.account.headline": "Account", | 68 | "settings.account.headline": "Account", |
@@ -167,6 +169,8 @@ | |||
167 | "tabs.item.edit": "Edit", | 169 | "tabs.item.edit": "Edit", |
168 | "tabs.item.disableNotifications": "Disable notifications", | 170 | "tabs.item.disableNotifications": "Disable notifications", |
169 | "tabs.item.enableNotification": "Enable notifications", | 171 | "tabs.item.enableNotification": "Enable notifications", |
172 | "tabs.item.disableAudio": "Disable audio", | ||
173 | "tabs.item.enableAudio": "Enable audio", | ||
170 | "tabs.item.disableService": "Disable service", | 174 | "tabs.item.disableService": "Disable service", |
171 | "tabs.item.deleteService": "Delete service", | 175 | "tabs.item.deleteService": "Delete service", |
172 | "service.crashHandler.headline": "Oh no!", | 176 | "service.crashHandler.headline": "Oh no!", |
diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index ecfd621d3..6580157d4 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js | |||
@@ -57,6 +57,8 @@ export default class AppStore extends Store { | |||
57 | this.actions.app.installUpdate.listen(this._installUpdate.bind(this)); | 57 | this.actions.app.installUpdate.listen(this._installUpdate.bind(this)); |
58 | this.actions.app.resetUpdateStatus.listen(this._resetUpdateStatus.bind(this)); | 58 | this.actions.app.resetUpdateStatus.listen(this._resetUpdateStatus.bind(this)); |
59 | this.actions.app.healthCheck.listen(this._healthCheck.bind(this)); | 59 | this.actions.app.healthCheck.listen(this._healthCheck.bind(this)); |
60 | this.actions.app.muteApp.listen(this._muteApp.bind(this)); | ||
61 | this.actions.app.toggleMuteApp.listen(this._toggleMuteApp.bind(this)); | ||
60 | 62 | ||
61 | this.registerReactions([ | 63 | this.registerReactions([ |
62 | this._offlineCheck.bind(this), | 64 | this._offlineCheck.bind(this), |
@@ -202,6 +204,18 @@ export default class AppStore extends Store { | |||
202 | this.healthCheckRequest.execute(); | 204 | this.healthCheckRequest.execute(); |
203 | } | 205 | } |
204 | 206 | ||
207 | @action _muteApp({ isMuted }) { | ||
208 | this.actions.settings.update({ | ||
209 | settings: { | ||
210 | isMuted, | ||
211 | }, | ||
212 | }); | ||
213 | } | ||
214 | |||
215 | @action _toggleMuteApp() { | ||
216 | this._muteApp({ isMuted: !this.stores.settings.all.isMuted }); | ||
217 | } | ||
218 | |||
205 | // Reactions | 219 | // Reactions |
206 | _offlineCheck() { | 220 | _offlineCheck() { |
207 | if (!this.isOnline) { | 221 | if (!this.isOnline) { |
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index 96c503510..a20718eca 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js | |||
@@ -48,6 +48,7 @@ export default class ServicesStore extends Store { | |||
48 | this.actions.service.reloadUpdatedServices.listen(this._reloadUpdatedServices.bind(this)); | 48 | this.actions.service.reloadUpdatedServices.listen(this._reloadUpdatedServices.bind(this)); |
49 | this.actions.service.reorder.listen(this._reorder.bind(this)); | 49 | this.actions.service.reorder.listen(this._reorder.bind(this)); |
50 | this.actions.service.toggleNotifications.listen(this._toggleNotifications.bind(this)); | 50 | this.actions.service.toggleNotifications.listen(this._toggleNotifications.bind(this)); |
51 | this.actions.service.toggleAudio.listen(this._toggleAudio.bind(this)); | ||
51 | this.actions.service.openDevTools.listen(this._openDevTools.bind(this)); | 52 | this.actions.service.openDevTools.listen(this._openDevTools.bind(this)); |
52 | this.actions.service.openDevToolsForActiveService.listen(this._openDevToolsForActiveService.bind(this)); | 53 | this.actions.service.openDevToolsForActiveService.listen(this._openDevToolsForActiveService.bind(this)); |
53 | 54 | ||
@@ -399,11 +400,25 @@ export default class ServicesStore extends Store { | |||
399 | @action _toggleNotifications({ serviceId }) { | 400 | @action _toggleNotifications({ serviceId }) { |
400 | const service = this.one(serviceId); | 401 | const service = this.one(serviceId); |
401 | 402 | ||
403 | this.actions.service.updateService({ | ||
404 | serviceId, | ||
405 | serviceData: { | ||
406 | isNotificationEnabled: !service.isNotificationEnabled, | ||
407 | }, | ||
408 | redirect: false, | ||
409 | }); | ||
410 | } | ||
411 | |||
412 | @action _toggleAudio({ serviceId }) { | ||
413 | const service = this.one(serviceId); | ||
414 | |||
402 | service.isNotificationEnabled = !service.isNotificationEnabled; | 415 | service.isNotificationEnabled = !service.isNotificationEnabled; |
403 | 416 | ||
404 | this.actions.service.updateService({ | 417 | this.actions.service.updateService({ |
405 | serviceId, | 418 | serviceId, |
406 | serviceData: service, | 419 | serviceData: { |
420 | isMuted: !service.isMuted, | ||
421 | }, | ||
407 | redirect: false, | 422 | redirect: false, |
408 | }); | 423 | }); |
409 | } | 424 | } |
diff --git a/src/styles/layout.scss b/src/styles/layout.scss index d87df2684..9f32bf2c4 100644 --- a/src/styles/layout.scss +++ b/src/styles/layout.scss | |||
@@ -42,6 +42,7 @@ html { | |||
42 | z-index: 200; | 42 | z-index: 200; |
43 | text-align: center; | 43 | text-align: center; |
44 | color: $theme-text-color; | 44 | color: $theme-text-color; |
45 | padding-bottom: 5px; | ||
45 | 46 | ||
46 | .sidebar__add-service { | 47 | .sidebar__add-service { |
47 | width: 32px; | 48 | width: 32px; |
@@ -52,26 +53,27 @@ html { | |||
52 | color: $theme-gray-light; | 53 | color: $theme-gray-light; |
53 | } | 54 | } |
54 | 55 | ||
55 | .sidebar__settings-button { | 56 | .sidebar__button { |
56 | height: auto; | 57 | width: $theme-sidebar-width; |
57 | padding: 20px 0; | 58 | padding: 10px 0; |
58 | font-size: 12px; | 59 | font-size: 24px; |
59 | position: relative; | 60 | position: relative; |
61 | color: $theme-gray-light; | ||
62 | transition: color 0.25s, transform 0.25s; | ||
60 | 63 | ||
61 | .emoji { | 64 | &:hover { |
62 | position: absolute; | 65 | transform: scale(1.15); |
63 | top: 18px; | 66 | color: darken($theme-gray-light, 10%); |
64 | right: 12px; | 67 | } |
65 | 68 | ||
66 | img { | 69 | &:active { |
67 | width: 18px; | 70 | transition: transform 0.1s; |
68 | } | 71 | transform: scale(1); |
69 | } | 72 | } |
70 | } | ||
71 | 73 | ||
72 | .sidebar__logo { | 74 | &.is-muted { |
73 | width: 40px; | 75 | color: $theme-brand-primary; |
74 | height: auto; | 76 | } |
75 | } | 77 | } |
76 | 78 | ||
77 | & > div { | 79 | & > div { |
diff --git a/src/styles/tabs.scss b/src/styles/tabs.scss index 75568898b..abafdb53c 100644 --- a/src/styles/tabs.scss +++ b/src/styles/tabs.scss | |||
@@ -41,9 +41,16 @@ | |||
41 | } | 41 | } |
42 | } | 42 | } |
43 | 43 | ||
44 | &:hover { | ||
45 | .tab-item__icon { | ||
46 | transform: scale(1.1); | ||
47 | } | ||
48 | } | ||
49 | |||
44 | .tab-item__icon { | 50 | .tab-item__icon { |
45 | width: 30px; | 51 | width: 30px; |
46 | height: auto; | 52 | height: auto; |
53 | transition: transform 0.25s; | ||
47 | } | 54 | } |
48 | 55 | ||
49 | .tab-item__message-count { | 56 | .tab-item__message-count { |