Skip to content

Commit

Permalink
feat(App): Add option to mute all services in sidebar
Browse files Browse the repository at this point in the history
Closes #8 #162
  • Loading branch information
adlk committed Nov 10, 2017
1 parent b405ba1 commit f5a9aa2
Show file tree
Hide file tree
Showing 15 changed files with 139 additions and 58 deletions.
4 changes: 4 additions & 0 deletions src/actions/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@ export default {
resetUpdateStatus: {},
installUpdate: {},
healthCheck: {},
muteApp: {
isMuted: PropTypes.bool.isRequired,
},
toggleMuteApp: {},
};
3 changes: 3 additions & 0 deletions src/actions/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ export default {
toggleNotifications: {
serviceId: PropTypes.string.isRequired,
},
toggleAudio: {
serviceId: PropTypes.string.isRequired,
},
openDevTools: {
serviceId: PropTypes.string.isRequired,
},
Expand Down
52 changes: 33 additions & 19 deletions src/components/layout/Sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,25 @@ const messages = defineMessages({
id: 'sidebar.settings',
defaultMessage: '!!!Settings',
},
addNewService: {
id: 'sidebar.addNewService',
defaultMessage: '!!!Add new service',
},
mute: {
id: 'sidebar.mute',
defaultMessage: '!!!Disable audio',
},
unmute: {
id: 'sidebar.unmute',
defaultMessage: '!!!Enable audio',
},
});

export default class Sidebar extends Component {
static propTypes = {
openSettings: PropTypes.func.isRequired,
isPremiumUser: PropTypes.bool,
}

static defaultProps = {
isPremiumUser: false,
toggleMuteApp: PropTypes.func.isRequired,
isAppMuted: PropTypes.bool.isRequired,
}

static contextTypes = {
Expand All @@ -40,8 +49,9 @@ export default class Sidebar extends Component {
}

render() {
const { openSettings, isPremiumUser } = this.props;
const { openSettings, toggleMuteApp, isAppMuted } = this.props;
const { intl } = this.context;

return (
<div className="sidebar">
<Tabbar
Expand All @@ -50,21 +60,25 @@ export default class Sidebar extends Component {
disableToolTip={() => this.disableToolTip()}
/>
<button
onClick={openSettings}
className="sidebar__settings-button"
onClick={toggleMuteApp}
className={`sidebar__button ${isAppMuted ? 'is-muted' : ''}`}
data-tip={`${intl.formatMessage(isAppMuted ? messages.unmute : messages.mute)} (${ctrlKey}+Shift+M)`}
>
<i className={`mdi mdi-bell${isAppMuted ? '-off' : ''}`} />
</button>
<button
onClick={() => openSettings({ path: 'recipes' })}
className="sidebar__button"
data-tip={`${intl.formatMessage(messages.addNewService)} (${ctrlKey}+N)`}
>
<i className="mdi mdi-plus-box" />
</button>
<button
onClick={() => openSettings({ path: 'app' })}
className="sidebar__button"
data-tip={`${intl.formatMessage(messages.settings)} (${ctrlKey}+,)`}
>
{isPremiumUser && (
<span className="emoji">
<img src="./assets/images/emoji/star.png" alt="" />
</span>
)}
<img
src="./assets/images/logo.svg"
className="sidebar__logo"
alt=""
/>
{intl.formatMessage(messages.settings)}
<i className="mdi mdi-settings" />
</button>
{this.state.tooltipEnabled && (
<ReactTooltip place="right" type="dark" effect="solid" />
Expand Down
4 changes: 3 additions & 1 deletion src/components/services/content/ServiceWebview.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export default class ServiceWebview extends Component {
service: PropTypes.instanceOf(ServiceModel).isRequired,
setWebviewReference: PropTypes.func.isRequired,
reload: PropTypes.func.isRequired,
isAppMuted: PropTypes.bool.isRequired,
};

static defaultProps = {
Expand Down Expand Up @@ -56,6 +57,7 @@ export default class ServiceWebview extends Component {
service,
setWebviewReference,
reload,
isAppMuted,
} = this.props;

const webviewClasses = classnames({
Expand Down Expand Up @@ -92,7 +94,7 @@ export default class ServiceWebview extends Component {
})}
onUpdateTargetUrl={this.updateTargetUrl}
useragent={service.userAgent}
muted={service.isMuted}
muted={isAppMuted || service.isMuted}
disablewebsecurity
allowpopups
/>
Expand Down
3 changes: 3 additions & 0 deletions src/components/services/content/Services.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export default class Services extends Component {
handleIPCMessage: PropTypes.func.isRequired,
openWindow: PropTypes.func.isRequired,
reload: PropTypes.func.isRequired,
isAppMuted: PropTypes.bool.isRequired,
};

static defaultProps = {
Expand All @@ -44,6 +45,7 @@ export default class Services extends Component {
setWebviewReference,
openWindow,
reload,
isAppMuted,
} = this.props;
const { intl } = this.context;

Expand Down Expand Up @@ -76,6 +78,7 @@ export default class Services extends Component {
setWebviewReference={setWebviewReference}
openWindow={openWindow}
reload={() => reload({ serviceId: service.id })}
isAppMuted={isAppMuted}
/>
))}
</div>
Expand Down
22 changes: 5 additions & 17 deletions src/components/services/tabs/TabBarSortableList.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,8 @@ import React, { Component } from 'react';
import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
import PropTypes from 'prop-types';
import { SortableContainer } from 'react-sortable-hoc';
import { defineMessages, intlShape } from 'react-intl';

import TabItem from './TabItem';
import { ctrlKey } from '../../../environment';

const messages = defineMessages({
addNewService: {
id: 'sidebar.addNewService',
defaultMessage: '!!!Add new service',
},
});

@observer
class TabBarSortableList extends Component {
Expand All @@ -22,27 +13,23 @@ class TabBarSortableList extends Component {
openSettings: PropTypes.func.isRequired,
reload: PropTypes.func.isRequired,
toggleNotifications: PropTypes.func.isRequired,
toggleAudio: PropTypes.func.isRequired,
deleteService: PropTypes.func.isRequired,
disableService: PropTypes.func.isRequired,
}

static contextTypes = {
intl: intlShape,
};

render() {
const {
services,
setActive,
reload,
toggleNotifications,
toggleAudio,
deleteService,
disableService,
openSettings,
} = this.props;

const { intl } = this.context;

return (
<ul
className="tabs"
Expand All @@ -56,20 +43,21 @@ class TabBarSortableList extends Component {
shortcutIndex={index + 1}
reload={() => reload({ serviceId: service.id })}
toggleNotifications={() => toggleNotifications({ serviceId: service.id })}
toggleAudio={() => toggleAudio({ serviceId: service.id })}
deleteService={() => deleteService({ serviceId: service.id })}
disableService={() => disableService({ serviceId: service.id })}
openSettings={openSettings}
/>
))}
<li>
{/* <li>
<button
className="sidebar__add-service"
onClick={() => openSettings({ path: 'recipes' })}
data-tip={`${intl.formatMessage(messages.addNewService)} (${ctrlKey}+N)`}
>
<span className="mdi mdi-plus" />
</button>
</li>
</li> */}
</ul>
);
}
Expand Down
15 changes: 15 additions & 0 deletions src/components/services/tabs/TabItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ const messages = defineMessages({
id: 'tabs.item.enableNotification',
defaultMessage: '!!!Enable notifications',
},
disableAudio: {
id: 'tabs.item.disableAudio',
defaultMessage: '!!!Disable audio',
},
enableAudio: {
id: 'tabs.item.enableAudio',
defaultMessage: '!!!Enable audio',
},
disableService: {
id: 'tabs.item.disableService',
defaultMessage: '!!!Disable Service',
Expand All @@ -46,6 +54,7 @@ class TabItem extends Component {
shortcutIndex: PropTypes.number.isRequired,
reload: PropTypes.func.isRequired,
toggleNotifications: PropTypes.func.isRequired,
toggleAudio: PropTypes.func.isRequired,
openSettings: PropTypes.func.isRequired,
deleteService: PropTypes.func.isRequired,
disableService: PropTypes.func.isRequired,
Expand All @@ -62,6 +71,7 @@ class TabItem extends Component {
shortcutIndex,
reload,
toggleNotifications,
toggleAudio,
deleteService,
disableService,
openSettings,
Expand Down Expand Up @@ -89,6 +99,11 @@ class TabItem extends Component {
? intl.formatMessage(messages.disableNotifications)
: intl.formatMessage(messages.enableNotifications),
click: () => toggleNotifications(),
}, {
label: service.isMuted
? intl.formatMessage(messages.enableAudio)
: intl.formatMessage(messages.disableAudio),
click: () => toggleAudio(),
}, {
label: intl.formatMessage(messages.disableService),
click: () => disableService(),
Expand Down
3 changes: 3 additions & 0 deletions src/components/services/tabs/Tabbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export default class TabBar extends Component {
reorder: PropTypes.func.isRequired,
reload: PropTypes.func.isRequired,
toggleNotifications: PropTypes.func.isRequired,
toggleAudio: PropTypes.func.isRequired,
deleteService: PropTypes.func.isRequired,
updateService: PropTypes.func.isRequired,
}
Expand Down Expand Up @@ -51,6 +52,7 @@ export default class TabBar extends Component {
disableToolTip,
reload,
toggleNotifications,
toggleAudio,
deleteService,
} = this.props;

Expand All @@ -63,6 +65,7 @@ export default class TabBar extends Component {
onSortStart={disableToolTip}
reload={reload}
toggleNotifications={toggleNotifications}
toggleAudio={toggleAudio}
deleteService={deleteService}
disableService={this.disableService}
openSettings={openSettings}
Expand Down
1 change: 1 addition & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ export const DEFAULT_APP_SETTINGS = {
minimizeToSystemTray: false,
locale: 'en-us', // TODO: Replace with proper solution once translations are in
beta: false,
isAppMuted: false,
};
16 changes: 11 additions & 5 deletions src/containers/layout/AppLayoutContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import RecipesStore from '../../stores/RecipesStore';
import ServicesStore from '../../stores/ServicesStore';
import UIStore from '../../stores/UIStore';
import NewsStore from '../../stores/NewsStore';
import UserStore from '../../stores/UserStore';
import SettingsStore from '../../stores/SettingsStore';
import RequestStore from '../../stores/RequestStore';
import GlobalErrorStore from '../../stores/GlobalErrorStore';

Expand All @@ -29,8 +29,8 @@ export default class AppLayoutContainer extends Component {
services,
ui,
news,
settings,
globalError,
user,
requests,
} = this.props.stores;

Expand All @@ -43,6 +43,7 @@ export default class AppLayoutContainer extends Component {
reorder,
reload,
toggleNotifications,
toggleAudio,
deleteService,
updateService,
} = this.props.actions.service;
Expand All @@ -53,6 +54,7 @@ export default class AppLayoutContainer extends Component {

const {
installUpdate,
toggleMuteApp,
} = this.props.actions.app;

const {
Expand All @@ -79,14 +81,16 @@ export default class AppLayoutContainer extends Component {
<Sidebar
services={allServices}
setActive={setActive}
isAppMuted={settings.all.isMuted}
openSettings={openSettings}
closeSettings={closeSettings}
reorder={reorder}
reload={reload}
toggleNotifications={toggleNotifications}
toggleAudio={toggleAudio}
deleteService={deleteService}
updateService={updateService}
isPremiumUser={user.data.isPremium}
toggleMuteApp={toggleMuteApp}
/>
);

Expand All @@ -97,6 +101,7 @@ export default class AppLayoutContainer extends Component {
setWebviewReference={setWebviewReference}
openWindow={openWindow}
reload={reload}
isAppMuted={settings.all.isMuted}
/>
);

Expand Down Expand Up @@ -130,7 +135,7 @@ AppLayoutContainer.wrappedComponent.propTypes = {
app: PropTypes.instanceOf(AppStore).isRequired,
ui: PropTypes.instanceOf(UIStore).isRequired,
news: PropTypes.instanceOf(NewsStore).isRequired,
user: PropTypes.instanceOf(UserStore).isRequired,
settings: PropTypes.instanceOf(SettingsStore).isRequired,
requests: PropTypes.instanceOf(RequestStore).isRequired,
globalError: PropTypes.instanceOf(GlobalErrorStore).isRequired,
}).isRequired,
Expand All @@ -139,6 +144,7 @@ AppLayoutContainer.wrappedComponent.propTypes = {
setActive: PropTypes.func.isRequired,
reload: PropTypes.func.isRequired,
toggleNotifications: PropTypes.func.isRequired,
toggleAudio: PropTypes.func.isRequired,
handleIPCMessage: PropTypes.func.isRequired,
setWebviewReference: PropTypes.func.isRequired,
openWindow: PropTypes.func.isRequired,
Expand All @@ -156,7 +162,7 @@ AppLayoutContainer.wrappedComponent.propTypes = {
}).isRequired,
app: PropTypes.shape({
installUpdate: PropTypes.func.isRequired,
healthCheck: PropTypes.func.isRequired,
toggleMuteApp: PropTypes.func.isRequired,
}).isRequired,
requests: PropTypes.shape({
retryRequiredRequests: PropTypes.func.isRequired,
Expand Down
4 changes: 4 additions & 0 deletions src/i18n/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@
"infobar.requiredRequestsFailed": "Could not load services and user information",
"sidebar.settings": "Settings",
"sidebar.addNewService": "Add new service",
"sidebar.mute": "Disable audio",
"sidebar.unmute": "Enable audio",
"services.welcome": "Welcome to Franz",
"services.getStarted": "Get started",
"settings.account.headline": "Account",
Expand Down Expand Up @@ -167,6 +169,8 @@
"tabs.item.edit": "Edit",
"tabs.item.disableNotifications": "Disable notifications",
"tabs.item.enableNotification": "Enable notifications",
"tabs.item.disableAudio": "Disable audio",
"tabs.item.enableAudio": "Enable audio",
"tabs.item.disableService": "Disable service",
"tabs.item.deleteService": "Delete service",
"service.crashHandler.headline": "Oh no!",
Expand Down
Loading

0 comments on commit f5a9aa2

Please sign in to comment.