Skip to content

Commit f5a9aa2

Browse files
committed
feat(App): Add option to mute all services in sidebar
Closes #8 #162
1 parent b405ba1 commit f5a9aa2

File tree

15 files changed

+139
-58
lines changed

15 files changed

+139
-58
lines changed

src/actions/app.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,8 @@ export default {
2020
resetUpdateStatus: {},
2121
installUpdate: {},
2222
healthCheck: {},
23+
muteApp: {
24+
isMuted: PropTypes.bool.isRequired,
25+
},
26+
toggleMuteApp: {},
2327
};

src/actions/service.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ export default {
7171
toggleNotifications: {
7272
serviceId: PropTypes.string.isRequired,
7373
},
74+
toggleAudio: {
75+
serviceId: PropTypes.string.isRequired,
76+
},
7477
openDevTools: {
7578
serviceId: PropTypes.string.isRequired,
7679
},

src/components/layout/Sidebar.js

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,25 @@ const messages = defineMessages({
1111
id: 'sidebar.settings',
1212
defaultMessage: '!!!Settings',
1313
},
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+
},
1426
});
1527

1628
export default class Sidebar extends Component {
1729
static propTypes = {
1830
openSettings: PropTypes.func.isRequired,
19-
isPremiumUser: PropTypes.bool,
20-
}
21-
22-
static defaultProps = {
23-
isPremiumUser: false,
31+
toggleMuteApp: PropTypes.func.isRequired,
32+
isAppMuted: PropTypes.bool.isRequired,
2433
}
2534

2635
static contextTypes = {
@@ -40,8 +49,9 @@ export default class Sidebar extends Component {
4049
}
4150

4251
render() {
43-
const { openSettings, isPremiumUser } = this.props;
52+
const { openSettings, toggleMuteApp, isAppMuted } = this.props;
4453
const { intl } = this.context;
54+
4555
return (
4656
<div className="sidebar">
4757
<Tabbar
@@ -50,21 +60,25 @@ export default class Sidebar extends Component {
5060
disableToolTip={() => this.disableToolTip()}
5161
/>
5262
<button
53-
onClick={openSettings}
54-
className="sidebar__settings-button"
63+
onClick={toggleMuteApp}
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"
5579
data-tip={`${intl.formatMessage(messages.settings)} (${ctrlKey}+,)`}
5680
>
57-
{isPremiumUser && (
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)}
81+
<i className="mdi mdi-settings" />
6882
</button>
6983
{this.state.tooltipEnabled && (
7084
<ReactTooltip place="right" type="dark" effect="solid" />

src/components/services/content/ServiceWebview.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export default class ServiceWebview extends Component {
1515
service: PropTypes.instanceOf(ServiceModel).isRequired,
1616
setWebviewReference: PropTypes.func.isRequired,
1717
reload: PropTypes.func.isRequired,
18+
isAppMuted: PropTypes.bool.isRequired,
1819
};
1920

2021
static defaultProps = {
@@ -56,6 +57,7 @@ export default class ServiceWebview extends Component {
5657
service,
5758
setWebviewReference,
5859
reload,
60+
isAppMuted,
5961
} = this.props;
6062

6163
const webviewClasses = classnames({
@@ -92,7 +94,7 @@ export default class ServiceWebview extends Component {
9294
})}
9395
onUpdateTargetUrl={this.updateTargetUrl}
9496
useragent={service.userAgent}
95-
muted={service.isMuted}
97+
muted={isAppMuted || service.isMuted}
9698
disablewebsecurity
9799
allowpopups
98100
/>

src/components/services/content/Services.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export default class Services extends Component {
2626
handleIPCMessage: PropTypes.func.isRequired,
2727
openWindow: PropTypes.func.isRequired,
2828
reload: PropTypes.func.isRequired,
29+
isAppMuted: PropTypes.bool.isRequired,
2930
};
3031

3132
static defaultProps = {
@@ -44,6 +45,7 @@ export default class Services extends Component {
4445
setWebviewReference,
4546
openWindow,
4647
reload,
48+
isAppMuted,
4749
} = this.props;
4850
const { intl } = this.context;
4951

@@ -76,6 +78,7 @@ export default class Services extends Component {
7678
setWebviewReference={setWebviewReference}
7779
openWindow={openWindow}
7880
reload={() => reload({ serviceId: service.id })}
81+
isAppMuted={isAppMuted}
7982
/>
8083
))}
8184
</div>

src/components/services/tabs/TabBarSortableList.js

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,8 @@ import React, { Component } from 'react';
22
import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
33
import PropTypes from 'prop-types';
44
import { SortableContainer } from 'react-sortable-hoc';
5-
import { defineMessages, intlShape } from 'react-intl';
65

76
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-
});
167

178
@observer
189
class TabBarSortableList extends Component {
@@ -22,27 +13,23 @@ class TabBarSortableList extends Component {
2213
openSettings: PropTypes.func.isRequired,
2314
reload: PropTypes.func.isRequired,
2415
toggleNotifications: PropTypes.func.isRequired,
16+
toggleAudio: PropTypes.func.isRequired,
2517
deleteService: PropTypes.func.isRequired,
2618
disableService: PropTypes.func.isRequired,
2719
}
2820

29-
static contextTypes = {
30-
intl: intlShape,
31-
};
32-
3321
render() {
3422
const {
3523
services,
3624
setActive,
3725
reload,
3826
toggleNotifications,
27+
toggleAudio,
3928
deleteService,
4029
disableService,
4130
openSettings,
4231
} = this.props;
4332

44-
const { intl } = this.context;
45-
4633
return (
4734
<ul
4835
className="tabs"
@@ -56,20 +43,21 @@ class TabBarSortableList extends Component {
5643
shortcutIndex={index + 1}
5744
reload={() => reload({ serviceId: service.id })}
5845
toggleNotifications={() => toggleNotifications({ serviceId: service.id })}
46+
toggleAudio={() => toggleAudio({ serviceId: service.id })}
5947
deleteService={() => deleteService({ serviceId: service.id })}
6048
disableService={() => disableService({ serviceId: service.id })}
6149
openSettings={openSettings}
6250
/>
6351
))}
64-
<li>
52+
{/* <li>
6553
<button
6654
className="sidebar__add-service"
6755
onClick={() => openSettings({ path: 'recipes' })}
6856
data-tip={`${intl.formatMessage(messages.addNewService)} (${ctrlKey}+N)`}
6957
>
7058
<span className="mdi mdi-plus" />
7159
</button>
72-
</li>
60+
</li> */}
7361
</ul>
7462
);
7563
}

src/components/services/tabs/TabItem.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ const messages = defineMessages({
2828
id: 'tabs.item.enableNotification',
2929
defaultMessage: '!!!Enable notifications',
3030
},
31+
disableAudio: {
32+
id: 'tabs.item.disableAudio',
33+
defaultMessage: '!!!Disable audio',
34+
},
35+
enableAudio: {
36+
id: 'tabs.item.enableAudio',
37+
defaultMessage: '!!!Enable audio',
38+
},
3139
disableService: {
3240
id: 'tabs.item.disableService',
3341
defaultMessage: '!!!Disable Service',
@@ -46,6 +54,7 @@ class TabItem extends Component {
4654
shortcutIndex: PropTypes.number.isRequired,
4755
reload: PropTypes.func.isRequired,
4856
toggleNotifications: PropTypes.func.isRequired,
57+
toggleAudio: PropTypes.func.isRequired,
4958
openSettings: PropTypes.func.isRequired,
5059
deleteService: PropTypes.func.isRequired,
5160
disableService: PropTypes.func.isRequired,
@@ -62,6 +71,7 @@ class TabItem extends Component {
6271
shortcutIndex,
6372
reload,
6473
toggleNotifications,
74+
toggleAudio,
6575
deleteService,
6676
disableService,
6777
openSettings,
@@ -89,6 +99,11 @@ class TabItem extends Component {
8999
? intl.formatMessage(messages.disableNotifications)
90100
: intl.formatMessage(messages.enableNotifications),
91101
click: () => toggleNotifications(),
102+
}, {
103+
label: service.isMuted
104+
? intl.formatMessage(messages.enableAudio)
105+
: intl.formatMessage(messages.disableAudio),
106+
click: () => toggleAudio(),
92107
}, {
93108
label: intl.formatMessage(messages.disableService),
94109
click: () => disableService(),

src/components/services/tabs/Tabbar.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export default class TabBar extends Component {
1515
reorder: PropTypes.func.isRequired,
1616
reload: PropTypes.func.isRequired,
1717
toggleNotifications: PropTypes.func.isRequired,
18+
toggleAudio: PropTypes.func.isRequired,
1819
deleteService: PropTypes.func.isRequired,
1920
updateService: PropTypes.func.isRequired,
2021
}
@@ -51,6 +52,7 @@ export default class TabBar extends Component {
5152
disableToolTip,
5253
reload,
5354
toggleNotifications,
55+
toggleAudio,
5456
deleteService,
5557
} = this.props;
5658

@@ -63,6 +65,7 @@ export default class TabBar extends Component {
6365
onSortStart={disableToolTip}
6466
reload={reload}
6567
toggleNotifications={toggleNotifications}
68+
toggleAudio={toggleAudio}
6669
deleteService={deleteService}
6770
disableService={this.disableService}
6871
openSettings={openSettings}

src/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ export const DEFAULT_APP_SETTINGS = {
1212
minimizeToSystemTray: false,
1313
locale: 'en-us', // TODO: Replace with proper solution once translations are in
1414
beta: false,
15+
isAppMuted: false,
1516
};

src/containers/layout/AppLayoutContainer.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import RecipesStore from '../../stores/RecipesStore';
77
import ServicesStore from '../../stores/ServicesStore';
88
import UIStore from '../../stores/UIStore';
99
import NewsStore from '../../stores/NewsStore';
10-
import UserStore from '../../stores/UserStore';
10+
import SettingsStore from '../../stores/SettingsStore';
1111
import RequestStore from '../../stores/RequestStore';
1212
import GlobalErrorStore from '../../stores/GlobalErrorStore';
1313

@@ -29,8 +29,8 @@ export default class AppLayoutContainer extends Component {
2929
services,
3030
ui,
3131
news,
32+
settings,
3233
globalError,
33-
user,
3434
requests,
3535
} = this.props.stores;
3636

@@ -43,6 +43,7 @@ export default class AppLayoutContainer extends Component {
4343
reorder,
4444
reload,
4545
toggleNotifications,
46+
toggleAudio,
4647
deleteService,
4748
updateService,
4849
} = this.props.actions.service;
@@ -53,6 +54,7 @@ export default class AppLayoutContainer extends Component {
5354

5455
const {
5556
installUpdate,
57+
toggleMuteApp,
5658
} = this.props.actions.app;
5759

5860
const {
@@ -79,14 +81,16 @@ export default class AppLayoutContainer extends Component {
7981
<Sidebar
8082
services={allServices}
8183
setActive={setActive}
84+
isAppMuted={settings.all.isMuted}
8285
openSettings={openSettings}
8386
closeSettings={closeSettings}
8487
reorder={reorder}
8588
reload={reload}
8689
toggleNotifications={toggleNotifications}
90+
toggleAudio={toggleAudio}
8791
deleteService={deleteService}
8892
updateService={updateService}
89-
isPremiumUser={user.data.isPremium}
93+
toggleMuteApp={toggleMuteApp}
9094
/>
9195
);
9296

@@ -97,6 +101,7 @@ export default class AppLayoutContainer extends Component {
97101
setWebviewReference={setWebviewReference}
98102
openWindow={openWindow}
99103
reload={reload}
104+
isAppMuted={settings.all.isMuted}
100105
/>
101106
);
102107

@@ -130,7 +135,7 @@ AppLayoutContainer.wrappedComponent.propTypes = {
130135
app: PropTypes.instanceOf(AppStore).isRequired,
131136
ui: PropTypes.instanceOf(UIStore).isRequired,
132137
news: PropTypes.instanceOf(NewsStore).isRequired,
133-
user: PropTypes.instanceOf(UserStore).isRequired,
138+
settings: PropTypes.instanceOf(SettingsStore).isRequired,
134139
requests: PropTypes.instanceOf(RequestStore).isRequired,
135140
globalError: PropTypes.instanceOf(GlobalErrorStore).isRequired,
136141
}).isRequired,
@@ -139,6 +144,7 @@ AppLayoutContainer.wrappedComponent.propTypes = {
139144
setActive: PropTypes.func.isRequired,
140145
reload: PropTypes.func.isRequired,
141146
toggleNotifications: PropTypes.func.isRequired,
147+
toggleAudio: PropTypes.func.isRequired,
142148
handleIPCMessage: PropTypes.func.isRequired,
143149
setWebviewReference: PropTypes.func.isRequired,
144150
openWindow: PropTypes.func.isRequired,
@@ -156,7 +162,7 @@ AppLayoutContainer.wrappedComponent.propTypes = {
156162
}).isRequired,
157163
app: PropTypes.shape({
158164
installUpdate: PropTypes.func.isRequired,
159-
healthCheck: PropTypes.func.isRequired,
165+
toggleMuteApp: PropTypes.func.isRequired,
160166
}).isRequired,
161167
requests: PropTypes.shape({
162168
retryRequiredRequests: PropTypes.func.isRequired,

0 commit comments

Comments
 (0)