From b405ba11aa3c669a21831d016084e0c47bffdebc Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Thu, 9 Nov 2017 16:28:03 +0100 Subject: [PATCH 01/11] feat(Service): Add option to mute service --- .../services/content/ServiceWebview.js | 6 +---- .../settings/services/EditServiceForm.js | 12 ++++++++-- .../settings/services/ServiceItem.js | 22 +++++++++++++------ src/containers/settings/EditServiceScreen.js | 15 +++++++++++-- src/i18n/locales/en-US.json | 15 ++++++++----- src/models/Service.js | 3 +++ src/stores/ServicesStore.js | 2 +- src/styles/settings.scss | 2 +- 8 files changed, 53 insertions(+), 24 deletions(-) diff --git a/src/components/services/content/ServiceWebview.js b/src/components/services/content/ServiceWebview.js index cd59e0a8a..d7e0a4f38 100644 --- a/src/components/services/content/ServiceWebview.js +++ b/src/components/services/content/ServiceWebview.js @@ -82,21 +82,17 @@ export default class ServiceWebview extends Component { )} { this.webview = element; }} - autosize src={service.url} preload="./webview/plugin.js" partition={`persist:service-${service.id}`} - onDidAttach={() => setWebviewReference({ serviceId: service.id, webview: this.webview.view, })} - onUpdateTargetUrl={this.updateTargetUrl} - useragent={service.userAgent} - + muted={service.isMuted} disablewebsecurity allowpopups /> diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js index 9b359a78e..753781507 100644 --- a/src/components/settings/services/EditServiceForm.js +++ b/src/components/settings/services/EditServiceForm.js @@ -61,7 +61,11 @@ const messages = defineMessages({ }, indirectMessageInfo: { id: 'settings.service.form.indirectMessageInfo', - defaultMessage: '!!!You will be notified about all new messages in a channel, not just @username, @channel, @here, ...', // eslint-disable-line + defaultMessage: '!!!You will be notified about all new messages in a channel, not just @username, @channel, @here, ...', + }, + isMutedInfo: { + id: 'settings.service.form.isMutedInfo', + defaultMessage: '!!!When disabled, all notification sounds and audio playback are muted', }, }); @@ -231,11 +235,15 @@ export default class EditServiceForm extends Component { {recipe.hasIndirectMessages && (
-

+

{intl.formatMessage(messages.indirectMessageInfo)}

)} + +

+ {intl.formatMessage(messages.isMutedInfo)} +

{recipe.message && ( diff --git a/src/components/settings/services/ServiceItem.js b/src/components/settings/services/ServiceItem.js index 20d8581d0..9743315b0 100644 --- a/src/components/settings/services/ServiceItem.js +++ b/src/components/settings/services/ServiceItem.js @@ -16,6 +16,10 @@ const messages = defineMessages({ id: 'settings.services.tooltip.notificationsDisabled', defaultMessage: '!!!Notifications are disabled', }, + tooltipIsMuted: { + id: 'settings.services.tooltip.isMuted', + defaultMessage: '!!!All sounds are muted', + }, }); @observer @@ -62,6 +66,17 @@ export default class ServiceItem extends Component { > {service.name !== '' ? service.name : service.recipe.name} + + {service.isMuted && ( + + )} + - {/* - - */} ); } diff --git a/src/containers/settings/EditServiceScreen.js b/src/containers/settings/EditServiceScreen.js index 6c614b941..191ef447b 100644 --- a/src/containers/settings/EditServiceScreen.js +++ b/src/containers/settings/EditServiceScreen.js @@ -9,7 +9,6 @@ import ServicesStore from '../../stores/ServicesStore'; import Form from '../../lib/Form'; import { gaPage } from '../../lib/analytics'; - import ServiceError from '../../components/settings/services/ServiceError'; import EditServiceForm from '../../components/settings/services/EditServiceForm'; import { required, url, oneRequired } from '../../helpers/validation-helpers'; @@ -27,6 +26,10 @@ const messages = defineMessages({ id: 'settings.service.form.enableNotification', defaultMessage: '!!!Enable Notifications', }, + enableAudio: { + id: 'settings.service.form.enableAudio', + defaultMessage: '!!!Enable audio', + }, team: { id: 'settings.service.form.team', defaultMessage: '!!!Team', @@ -51,11 +54,14 @@ export default class EditServiceScreen extends Component { gaPage('Settings/Service/Edit'); } - onSubmit(serviceData) { + onSubmit(data) { const { action } = this.props.router.params; const { recipes, services } = this.props.stores; const { createService, updateService } = this.props.actions.service; + const serviceData = data; + serviceData.isMuted = !serviceData.isMuted; + if (action === 'edit') { updateService({ serviceId: services.activeSettings.id, serviceData }); } else { @@ -82,6 +88,11 @@ export default class EditServiceScreen extends Component { value: service.isNotificationEnabled, default: true, }, + isMuted: { + label: intl.formatMessage(messages.enableAudio), + value: !service.isMuted, + default: true, + }, }, }; diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json index 0493b547f..e298728d1 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json @@ -106,11 +106,20 @@ "settings.service.form.customUrlPremiumInfo": "To add self hosted services, you need a Franz Premium Supporter Account.", "settings.service.form.customUrlUpgradeAccount": "Upgrade your account", "settings.service.form.indirectMessageInfo": "You will be notified about all new messages in a channel, not just @username, @channel, @here, ...", + "settings.service.form.name": "Name", + "settings.service.form.enableService": "Enable service", + "settings.service.form.enableNotification": "Enable notifications", + "settings.service.form.team": "Team", + "settings.service.form.customUrl": "Custom server", + "settings.service.form.indirectMessages": "Show message badge for all new messages", + "settings.service.form.enableAudio": "Enable audio", + "settings.service.form.isMutedInfo": "When disabled, all notification sounds and audio playback are muted", "settings.service.error.headline": "Error", "settings.service.error.goBack": "Back to services", "settings.service.error.message": "Could not load service recipe.", "settings.services.tooltip.isDisabled": "Service is disabled", "settings.services.tooltip.notificationsDisabled": "Notifications are disabled", + "settings.services.tooltip.isMuted": "All sounds are muted", "settings.services.headline": "Your services", "settings.services.noServicesAdded": "You haven't added any services yet.", "settings.services.discoverServices": "Discover services", @@ -133,12 +142,6 @@ "settings.app.form.language": "Language", "settings.app.form.beta": "Include beta versions", "settings.app.currentVersion": "Current version:", - "settings.service.form.name": "Name", - "settings.service.form.enableService": "Enable service", - "settings.service.form.enableNotification": "Enable notifications", - "settings.service.form.team": "Team", - "settings.service.form.customUrl": "Custom server", - "settings.service.form.indirectMessages": "Show message badge for all new messages", "settings.user.form.firstname": "Firstname", "settings.user.form.lastname": "Lastname", "settings.user.form.email": "Email", diff --git a/src/models/Service.js b/src/models/Service.js index dc53807f7..eb68493fe 100644 --- a/src/models/Service.js +++ b/src/models/Service.js @@ -18,6 +18,7 @@ export default class Service { @observable order = 99; @observable isEnabled = true; + @observable isMuted = false; @observable team = ''; @observable customUrl = ''; @observable isNotificationEnabled = true; @@ -54,6 +55,8 @@ export default class Service { this.isIndirectMessageBadgeEnabled = data.isIndirectMessageBadgeEnabled !== undefined ? data.isIndirectMessageBadgeEnabled : this.isIndirectMessageBadgeEnabled; + this.isMuted = data.isMuted !== undefined ? data.isMuted : this.isMuted; + this.recipe = recipe; } diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index 1d895d532..96c503510 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js @@ -287,7 +287,7 @@ export default class ServicesStore extends Store { }); } else if (channel === 'notification') { const options = args[0].options; - if (service.recipe.hasNotificationSound) { + if (service.recipe.hasNotificationSound || service.isMuted) { Object.assign(options, { silent: true, }); diff --git a/src/styles/settings.scss b/src/styles/settings.scss index 9b19deb4e..48d12a807 100644 --- a/src/styles/settings.scss +++ b/src/styles/settings.scss @@ -169,7 +169,7 @@ } } - .settings__indirect-message-help { + .settings__help { margin: -10px 0 20px 55px;; font-size: 12px; color: $theme-gray-light; From f5a9aa21e2ab958f60c143668f4836bc47e2b539 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Fri, 10 Nov 2017 12:08:35 +0100 Subject: [PATCH 02/11] feat(App): Add option to mute all services in sidebar Closes #8 #162 --- src/actions/app.js | 4 ++ src/actions/service.js | 3 ++ src/components/layout/Sidebar.js | 52 ++++++++++++------- .../services/content/ServiceWebview.js | 4 +- src/components/services/content/Services.js | 3 ++ .../services/tabs/TabBarSortableList.js | 22 ++------ src/components/services/tabs/TabItem.js | 15 ++++++ src/components/services/tabs/Tabbar.js | 3 ++ src/config.js | 1 + src/containers/layout/AppLayoutContainer.js | 16 ++++-- src/i18n/locales/en-US.json | 4 ++ src/stores/AppStore.js | 14 +++++ src/stores/ServicesStore.js | 17 +++++- src/styles/layout.scss | 32 ++++++------ 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 { resetUpdateStatus: {}, installUpdate: {}, healthCheck: {}, + muteApp: { + isMuted: PropTypes.bool.isRequired, + }, + toggleMuteApp: {}, }; 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 { toggleNotifications: { serviceId: PropTypes.string.isRequired, }, + toggleAudio: { + serviceId: PropTypes.string.isRequired, + }, openDevTools: { serviceId: PropTypes.string.isRequired, }, 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({ 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 = { @@ -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 (
this.disableToolTip()} /> + + {this.state.tooltipEnabled && ( 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 { service: PropTypes.instanceOf(ServiceModel).isRequired, setWebviewReference: PropTypes.func.isRequired, reload: PropTypes.func.isRequired, + isAppMuted: PropTypes.bool.isRequired, }; static defaultProps = { @@ -56,6 +57,7 @@ export default class ServiceWebview extends Component { service, setWebviewReference, reload, + isAppMuted, } = this.props; const webviewClasses = classnames({ @@ -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 /> 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 { handleIPCMessage: PropTypes.func.isRequired, openWindow: PropTypes.func.isRequired, reload: PropTypes.func.isRequired, + isAppMuted: PropTypes.bool.isRequired, }; static defaultProps = { @@ -44,6 +45,7 @@ export default class Services extends Component { setWebviewReference, openWindow, reload, + isAppMuted, } = this.props; const { intl } = this.context; @@ -76,6 +78,7 @@ export default class Services extends Component { setWebviewReference={setWebviewReference} openWindow={openWindow} reload={() => reload({ serviceId: service.id })} + isAppMuted={isAppMuted} /> ))}
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'; 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 { @@ -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 (
    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} /> ))} -
  • + {/*
  • -
  • + */}
); } 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({ 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', @@ -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, @@ -62,6 +71,7 @@ class TabItem extends Component { shortcutIndex, reload, toggleNotifications, + toggleAudio, deleteService, disableService, openSettings, @@ -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(), 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 { reorder: PropTypes.func.isRequired, reload: PropTypes.func.isRequired, toggleNotifications: PropTypes.func.isRequired, + toggleAudio: PropTypes.func.isRequired, deleteService: PropTypes.func.isRequired, updateService: PropTypes.func.isRequired, } @@ -51,6 +52,7 @@ export default class TabBar extends Component { disableToolTip, reload, toggleNotifications, + toggleAudio, deleteService, } = this.props; @@ -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} 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 = { minimizeToSystemTray: false, locale: 'en-us', // TODO: Replace with proper solution once translations are in beta: false, + isAppMuted: false, }; 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'; 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'; @@ -29,8 +29,8 @@ export default class AppLayoutContainer extends Component { services, ui, news, + settings, globalError, - user, requests, } = this.props.stores; @@ -43,6 +43,7 @@ export default class AppLayoutContainer extends Component { reorder, reload, toggleNotifications, + toggleAudio, deleteService, updateService, } = this.props.actions.service; @@ -53,6 +54,7 @@ export default class AppLayoutContainer extends Component { const { installUpdate, + toggleMuteApp, } = this.props.actions.app; const { @@ -79,14 +81,16 @@ export default class AppLayoutContainer extends Component { ); @@ -97,6 +101,7 @@ export default class AppLayoutContainer extends Component { setWebviewReference={setWebviewReference} openWindow={openWindow} reload={reload} + isAppMuted={settings.all.isMuted} /> ); @@ -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, @@ -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, @@ -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, 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 @@ "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", @@ -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!", 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 { this.actions.app.installUpdate.listen(this._installUpdate.bind(this)); this.actions.app.resetUpdateStatus.listen(this._resetUpdateStatus.bind(this)); this.actions.app.healthCheck.listen(this._healthCheck.bind(this)); + this.actions.app.muteApp.listen(this._muteApp.bind(this)); + this.actions.app.toggleMuteApp.listen(this._toggleMuteApp.bind(this)); this.registerReactions([ this._offlineCheck.bind(this), @@ -202,6 +204,18 @@ export default class AppStore extends Store { this.healthCheckRequest.execute(); } + @action _muteApp({ isMuted }) { + this.actions.settings.update({ + settings: { + isMuted, + }, + }); + } + + @action _toggleMuteApp() { + this._muteApp({ isMuted: !this.stores.settings.all.isMuted }); + } + // Reactions _offlineCheck() { 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 { this.actions.service.reloadUpdatedServices.listen(this._reloadUpdatedServices.bind(this)); this.actions.service.reorder.listen(this._reorder.bind(this)); this.actions.service.toggleNotifications.listen(this._toggleNotifications.bind(this)); + this.actions.service.toggleAudio.listen(this._toggleAudio.bind(this)); this.actions.service.openDevTools.listen(this._openDevTools.bind(this)); this.actions.service.openDevToolsForActiveService.listen(this._openDevToolsForActiveService.bind(this)); @@ -399,11 +400,25 @@ export default class ServicesStore extends Store { @action _toggleNotifications({ serviceId }) { const service = this.one(serviceId); + this.actions.service.updateService({ + serviceId, + serviceData: { + isNotificationEnabled: !service.isNotificationEnabled, + }, + redirect: false, + }); + } + + @action _toggleAudio({ serviceId }) { + const service = this.one(serviceId); + service.isNotificationEnabled = !service.isNotificationEnabled; this.actions.service.updateService({ serviceId, - serviceData: service, + serviceData: { + isMuted: !service.isMuted, + }, redirect: false, }); } 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 { z-index: 200; text-align: center; color: $theme-text-color; + padding-bottom: 5px; .sidebar__add-service { width: 32px; @@ -52,26 +53,27 @@ html { color: $theme-gray-light; } - .sidebar__settings-button { - height: auto; - padding: 20px 0; - font-size: 12px; + .sidebar__button { + width: $theme-sidebar-width; + padding: 10px 0; + font-size: 24px; position: relative; + color: $theme-gray-light; + transition: color 0.25s, transform 0.25s; - .emoji { - position: absolute; - top: 18px; - right: 12px; + &:hover { + transform: scale(1.15); + color: darken($theme-gray-light, 10%); + } - img { - width: 18px; - } + &:active { + transition: transform 0.1s; + transform: scale(1); } - } - .sidebar__logo { - width: 40px; - height: auto; + &.is-muted { + color: $theme-brand-primary; + } } & > 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 @@ } } + &:hover { + .tab-item__icon { + transform: scale(1.1); + } + } + .tab-item__icon { width: 30px; height: auto; + transition: transform 0.25s; } .tab-item__message-count { From 7d41227cb78bed23fcac4c8b40dcadae57c098bc Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Fri, 10 Nov 2017 14:51:38 +0100 Subject: [PATCH 03/11] feat(App): Respect System DoNotDisturb mode for service audio Closes #162 --- package.json | 1 + src/containers/layout/AppLayoutContainer.js | 2 +- src/stores/AppStore.js | 13 +++++++- yarn.lock | 35 ++++++++++++++++++++- 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 9b56cdf27..f9f6ca91c 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "author": "Stefan Malzner ", "license": "Apache-2.0", "dependencies": { + "@meetfranz/electron-notification-state": "^1.0.0", "@paulcbetts/system-idle-time": "^1.0.4", "address-rfc2822": "^2.0.1", "auto-launch": "https://github.com/meetfranz/node-auto-launch.git", diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js index 5ef4fbb35..28b6a105f 100644 --- a/src/containers/layout/AppLayoutContainer.js +++ b/src/containers/layout/AppLayoutContainer.js @@ -81,7 +81,7 @@ export default class AppLayoutContainer extends Component { this._systemDND(), 5000); + // Check for updates once every 4 hours setInterval(() => this._checkForUpdates(), CHECK_INTERVAL); // Check for an update in 30s (need a delay to prevent Squirrel Installer lock file issues) @@ -311,4 +318,8 @@ export default class AppStore extends Store { async _checkAutoStart() { return autoLauncher.isEnabled() || false; } + + _systemDND() { + this.isSystemMuted = getDoNotDisturb(); + } } diff --git a/yarn.lock b/yarn.lock index 0bedbac27..6c3f807a4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22,6 +22,14 @@ "7zip-bin-mac" "^1.0.1" "7zip-bin-win" "^2.1.0" +"@meetfranz/electron-notification-state@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@meetfranz/electron-notification-state/-/electron-notification-state-1.0.0.tgz#75e9d774bdaf15991eacd92cde8469b348259d8c" + dependencies: + macos-notification-state "^1.1.0" + windows-notification-state "^1.3.0" + windows-quiet-hours "^1.2.2" + "@paulcbetts/cld@^2.4.6": version "2.4.6" resolved "https://registry.yarnpkg.com/@paulcbetts/cld/-/cld-2.4.6.tgz#a992f6bc43cab212ac2c4488a671cf302f8b62e7" @@ -1168,6 +1176,10 @@ binary@^0.3.0: buffers "~0.1.1" chainsaw "~0.1.0" +bindings@^1.2.1, bindings@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.0.tgz#b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7" + bindings@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11" @@ -4012,6 +4024,13 @@ macaddress@^0.2.7: version "0.2.8" resolved "https://registry.yarnpkg.com/macaddress/-/macaddress-0.2.8.tgz#5904dc537c39ec6dbefeae902327135fa8511f12" +macos-notification-state@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/macos-notification-state/-/macos-notification-state-1.1.0.tgz#ee59671e05c1ec388c0b09101ef611c85b4b4e0e" + dependencies: + bindings "^1.2.1" + nan "^2.4.0" + make-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.0.0.tgz#97a011751e91dd87cfadef58832ebb04936de978" @@ -4243,7 +4262,7 @@ mute-stream@0.0.7, mute-stream@~0.0.4: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" -nan@^2.0.0, nan@^2.0.5, nan@^2.3.0, nan@^2.3.2: +nan@^2.0.0, nan@^2.0.5, nan@^2.3.0, nan@^2.3.2, nan@^2.4.0, nan@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.7.0.tgz#d95bf721ec877e08db276ed3fc6eb78f9083ad46" @@ -6155,6 +6174,20 @@ window-size@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876" +windows-notification-state@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/windows-notification-state/-/windows-notification-state-1.3.0.tgz#9f727782ecac8d920a408f1026be6f8e08fd902e" + dependencies: + bindings "^1.2.1" + nan "^2.4.0" + +windows-quiet-hours@^1.2.2: + version "1.2.4" + resolved "https://registry.yarnpkg.com/windows-quiet-hours/-/windows-quiet-hours-1.2.4.tgz#7ae57b13fe9423f2635ac0ed5791f674401a7c7a" + dependencies: + bindings "^1.3.0" + nan "^2.7.0" + winreg@1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/winreg/-/winreg-1.2.2.tgz#8509afa3b71c5bbd110a6d7c6247ec67736c598f" From cdb9d5686841d82c5dd0623f223de55dd0fc94d0 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Fri, 10 Nov 2017 16:16:51 +0100 Subject: [PATCH 04/11] fix merging issues --- src/components/services/content/ServiceWebview.js | 3 --- src/components/services/tabs/TabItem.js | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/components/services/content/ServiceWebview.js b/src/components/services/content/ServiceWebview.js index 08ba5f33d..abbf21dee 100644 --- a/src/components/services/content/ServiceWebview.js +++ b/src/components/services/content/ServiceWebview.js @@ -16,11 +16,8 @@ export default class ServiceWebview extends Component { service: PropTypes.instanceOf(ServiceModel).isRequired, setWebviewReference: PropTypes.func.isRequired, reload: PropTypes.func.isRequired, -<<<<<<< HEAD isAppMuted: PropTypes.bool.isRequired, -======= enable: PropTypes.func.isRequired, ->>>>>>> develop }; static defaultProps = { diff --git a/src/components/services/tabs/TabItem.js b/src/components/services/tabs/TabItem.js index 4a37bad57..a7136c43f 100644 --- a/src/components/services/tabs/TabItem.js +++ b/src/components/services/tabs/TabItem.js @@ -111,8 +111,8 @@ class TabItem extends Component { : intl.formatMessage(messages.disableAudio), click: () => toggleAudio(), }, { - label: intl.formatMessage(messages.disableService), - click: () => disableService(), + label: intl.formatMessage(service.isEnabled ? messages.disableService : messages.enableService), + click: () => (service.isEnabled ? disableService() : enableService()), }, { type: 'separator', }, { From 8433a52774677cf1ecabac9166964b29ec64b172 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Fri, 10 Nov 2017 16:25:59 +0100 Subject: [PATCH 05/11] replace :hover animation by a more decent :active effect --- src/styles/layout.scss | 5 +---- src/styles/tabs.scss | 5 ++--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/styles/layout.scss b/src/styles/layout.scss index 9f32bf2c4..b35ab2a7b 100644 --- a/src/styles/layout.scss +++ b/src/styles/layout.scss @@ -59,16 +59,13 @@ html { font-size: 24px; position: relative; color: $theme-gray-light; - transition: color 0.25s, transform 0.25s; &:hover { - transform: scale(1.15); color: darken($theme-gray-light, 10%); } &:active { - transition: transform 0.1s; - transform: scale(1); + color: lighten($theme-gray-light, 10%); } &.is-muted { diff --git a/src/styles/tabs.scss b/src/styles/tabs.scss index 9b13df1f0..7d8c63ba3 100644 --- a/src/styles/tabs.scss +++ b/src/styles/tabs.scss @@ -47,16 +47,15 @@ } } - &:hover { + &:active { .tab-item__icon { - transform: scale(1.1); + opacity: 0.7; } } .tab-item__icon { width: 30px; height: auto; - transition: transform 0.25s; } .tab-item__message-count { From 1f2535f259e7fc74d50f652e268b1a529e752d07 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Fri, 10 Nov 2017 20:16:53 +0100 Subject: [PATCH 06/11] disable yarn cache --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index c00198312..a35484458 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,8 +14,8 @@ install: - yarn add global gulpjs/gulp#4.0 - yarn install -cache: - - "%LOCALAPPDATA%\\Yarn" +# cache: +# - "%LOCALAPPDATA%\\Yarn" before_build: - yarn lint From 4cfc193a74284bb3b3dbd708102537218531281e Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Fri, 10 Nov 2017 20:26:20 +0100 Subject: [PATCH 07/11] add yarn clean cache command --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index a35484458..83cce8ad6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -10,6 +10,7 @@ version: 5.0.0.{build} install: - ps: Install-Product node 7 + - yarn cache clean - yarn add global gulp-cli@1.2.2 - yarn add global gulpjs/gulp#4.0 - yarn install From 15ff32977c882ef651ce79ebdfd46299f817736b Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Fri, 10 Nov 2017 20:45:52 +0100 Subject: [PATCH 08/11] test with node 8 --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 83cce8ad6..4b2796f4b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,7 +9,7 @@ environment: version: 5.0.0.{build} install: - - ps: Install-Product node 7 + - ps: Install-Product node 8 - yarn cache clean - yarn add global gulp-cli@1.2.2 - yarn add global gulpjs/gulp#4.0 From fb0b38228fd743079ffc6180f45ddaebaa3f3255 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Fri, 10 Nov 2017 21:41:20 +0100 Subject: [PATCH 09/11] fix undefined prop for isAppMuted --- src/containers/layout/AppLayoutContainer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js index 1b0f4d495..8e5b3d2ed 100644 --- a/src/containers/layout/AppLayoutContainer.js +++ b/src/containers/layout/AppLayoutContainer.js @@ -80,7 +80,7 @@ export default class AppLayoutContainer extends Component { ); From 623f8c9d25f28eb9d2aef045029f74387a9281c3 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Fri, 10 Nov 2017 21:48:28 +0100 Subject: [PATCH 10/11] optimize sidebar button size --- src/components/layout/Sidebar.js | 6 +++--- src/styles/layout.scss | 8 ++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/components/layout/Sidebar.js b/src/components/layout/Sidebar.js index 72ee2b3b7..ea34e8702 100644 --- a/src/components/layout/Sidebar.js +++ b/src/components/layout/Sidebar.js @@ -61,21 +61,21 @@ export default class Sidebar extends Component { />