diff --git a/src/components/services/content/ServiceDisabled.js b/src/components/services/content/ServiceDisabled.js
new file mode 100644
index 000000000..732b6c003
--- /dev/null
+++ b/src/components/services/content/ServiceDisabled.js
@@ -0,0 +1,48 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { observer } from 'mobx-react';
+import { defineMessages, intlShape } from 'react-intl';
+
+import Button from '../../ui/Button';
+
+const messages = defineMessages({
+ headline: {
+ id: 'service.disabledHandler.headline',
+ defaultMessage: '!!!{name} is disabled',
+ },
+ action: {
+ id: 'service.disabledHandler.action',
+ defaultMessage: '!!!Enable {name}',
+ },
+});
+
+@observer
+export default class ServiceDisabled extends Component {
+ static propTypes = {
+ name: PropTypes.string.isRequired,
+ enable: PropTypes.func.isRequired,
+ };
+
+ static contextTypes = {
+ intl: intlShape,
+ };
+
+ countdownInterval = null;
+ countdownIntervalTimeout = 1000;
+
+ render() {
+ const { name, enable } = this.props;
+ const { intl } = this.context;
+
+ return (
+
+
{intl.formatMessage(messages.headline, { name })}
+
+ );
+ }
+}
diff --git a/src/components/services/content/ServiceWebview.js b/src/components/services/content/ServiceWebview.js
index cd59e0a8a..a71017a6e 100644
--- a/src/components/services/content/ServiceWebview.js
+++ b/src/components/services/content/ServiceWebview.js
@@ -8,6 +8,7 @@ import classnames from 'classnames';
import ServiceModel from '../../../models/Service';
import StatusBarTargetUrl from '../../ui/StatusBarTargetUrl';
import WebviewCrashHandler from './WebviewCrashHandler';
+import ServiceDisabled from './ServiceDisabled';
@observer
export default class ServiceWebview extends Component {
@@ -15,6 +16,7 @@ export default class ServiceWebview extends Component {
service: PropTypes.instanceOf(ServiceModel).isRequired,
setWebviewReference: PropTypes.func.isRequired,
reload: PropTypes.func.isRequired,
+ enable: PropTypes.func.isRequired,
};
static defaultProps = {
@@ -56,6 +58,7 @@ export default class ServiceWebview extends Component {
service,
setWebviewReference,
reload,
+ enable,
} = this.props;
const webviewClasses = classnames({
@@ -80,27 +83,38 @@ export default class ServiceWebview extends Component {
reload={reload}
/>
)}
- { 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}
-
- disablewebsecurity
- allowpopups
- />
- {statusBar}
+ {!service.isEnabled && (
+
+ )}
+ {service.isEnabled && (
+
+ { 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}
+
+ disablewebsecurity
+ allowpopups
+ />
+ {statusBar}
+
+ )}
);
}
diff --git a/src/components/services/content/Services.js b/src/components/services/content/Services.js
index bad525d22..5230508f7 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,
+ update: PropTypes.func.isRequired,
};
static defaultProps = {
@@ -44,6 +45,7 @@ export default class Services extends Component {
setWebviewReference,
openWindow,
reload,
+ update,
} = this.props;
const { intl } = this.context;
@@ -76,6 +78,13 @@ export default class Services extends Component {
setWebviewReference={setWebviewReference}
openWindow={openWindow}
reload={() => reload({ serviceId: service.id })}
+ enable={() => update({
+ serviceId: service.id,
+ serviceData: {
+ isEnabled: true,
+ },
+ redirect: false,
+ })}
/>
))}
diff --git a/src/components/services/content/WebviewCrashHandler.js b/src/components/services/content/WebviewCrashHandler.js
index 24903f3c5..d48152c18 100644
--- a/src/components/services/content/WebviewCrashHandler.js
+++ b/src/components/services/content/WebviewCrashHandler.js
@@ -25,7 +25,7 @@ const messages = defineMessages({
});
@observer
-export default class ServiceWebview extends Component {
+export default class WebviewCrashHandler extends Component {
static propTypes = {
name: PropTypes.string.isRequired,
reload: PropTypes.func.isRequired,
diff --git a/src/components/services/tabs/TabBarSortableList.js b/src/components/services/tabs/TabBarSortableList.js
index e5ae36419..3340cbbbb 100644
--- a/src/components/services/tabs/TabBarSortableList.js
+++ b/src/components/services/tabs/TabBarSortableList.js
@@ -24,6 +24,7 @@ class TabBarSortableList extends Component {
toggleNotifications: PropTypes.func.isRequired,
deleteService: PropTypes.func.isRequired,
disableService: PropTypes.func.isRequired,
+ enableService: PropTypes.func.isRequired,
}
static contextTypes = {
@@ -38,6 +39,7 @@ class TabBarSortableList extends Component {
toggleNotifications,
deleteService,
disableService,
+ enableService,
openSettings,
} = this.props;
@@ -58,6 +60,7 @@ class TabBarSortableList extends Component {
toggleNotifications={() => toggleNotifications({ serviceId: service.id })}
deleteService={() => deleteService({ serviceId: service.id })}
disableService={() => disableService({ serviceId: service.id })}
+ enableService={() => enableService({ serviceId: service.id })}
openSettings={openSettings}
/>
))}
diff --git a/src/components/services/tabs/TabItem.js b/src/components/services/tabs/TabItem.js
index 9e03d2e21..638e17d95 100644
--- a/src/components/services/tabs/TabItem.js
+++ b/src/components/services/tabs/TabItem.js
@@ -32,6 +32,10 @@ const messages = defineMessages({
id: 'tabs.item.disableService',
defaultMessage: '!!!Disable Service',
},
+ enableService: {
+ id: 'tabs.item.enableService',
+ defaultMessage: '!!!Enable Service',
+ },
deleteService: {
id: 'tabs.item.deleteService',
defaultMessage: '!!!Delete Service',
@@ -49,6 +53,7 @@ class TabItem extends Component {
openSettings: PropTypes.func.isRequired,
deleteService: PropTypes.func.isRequired,
disableService: PropTypes.func.isRequired,
+ enableService: PropTypes.func.isRequired,
};
static contextTypes = {
@@ -64,6 +69,7 @@ class TabItem extends Component {
toggleNotifications,
deleteService,
disableService,
+ enableService,
openSettings,
} = this.props;
const { intl } = this.context;
@@ -90,8 +96,8 @@ class TabItem extends Component {
: intl.formatMessage(messages.enableNotifications),
click: () => toggleNotifications(),
}, {
- label: intl.formatMessage(messages.disableService),
- click: () => disableService(),
+ label: intl.formatMessage(service.isEnabled ? messages.disableService : messages.enableService),
+ click: () => (service.isEnabled ? disableService() : enableService()),
}, {
type: 'separator',
}, {
@@ -106,6 +112,7 @@ class TabItem extends Component {
'tab-item': true,
'is-active': service.isActive,
'has-custom-icon': service.hasCustomIcon,
+ 'is-disabled': !service.isEnabled,
})}
onClick={clickHandler}
onContextMenu={() => menu.popup(remote.getCurrentWindow())}
diff --git a/src/components/services/tabs/Tabbar.js b/src/components/services/tabs/Tabbar.js
index fdb2c0a59..5f63aed16 100644
--- a/src/components/services/tabs/Tabbar.js
+++ b/src/components/services/tabs/Tabbar.js
@@ -29,20 +29,28 @@ export default class TabBar extends Component {
reorder({ oldIndex, newIndex });
};
- disableService = ({ serviceId }) => {
+ toggleService = ({ serviceId, isEnabled }) => {
const { updateService } = this.props;
if (serviceId) {
updateService({
serviceId,
serviceData: {
- isEnabled: false,
+ isEnabled,
},
redirect: false,
});
}
}
+ disableService({ serviceId }) {
+ this.toggleService({ serviceId, isEnabled: false });
+ }
+
+ enableService({ serviceId }) {
+ this.toggleService({ serviceId, isEnabled: true });
+ }
+
render() {
const {
services,
@@ -64,7 +72,8 @@ export default class TabBar extends Component {
reload={reload}
toggleNotifications={toggleNotifications}
deleteService={deleteService}
- disableService={this.disableService}
+ disableService={args => this.disableService(args)}
+ enableService={args => this.enableService(args)}
openSettings={openSettings}
distance={20}
axis="y"
diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js
index 5675fecf4..ba07b1a5b 100644
--- a/src/components/settings/settings/EditSettingsForm.js
+++ b/src/components/settings/settings/EditSettingsForm.js
@@ -26,6 +26,10 @@ const messages = defineMessages({
id: 'settings.app.headlineUpdates',
defaultMessage: '!!!Updates',
},
+ headlineAppearance: {
+ id: 'settings.app.headlineAppearance',
+ defaultMessage: '!!!Appearance',
+ },
buttonSearchForUpdate: {
id: 'settings.app.buttonSearchForUpdate',
defaultMessage: '!!!Check for updates',
@@ -119,6 +123,8 @@ export default class EditSettingsForm extends Component {
{process.platform === 'win32' && (
)}
+ {intl.formatMessage(messages.headlineAppearance)}
+
{intl.formatMessage(messages.headlineLanguage)}
{intl.formatMessage(messages.headlineUpdates)}
diff --git a/src/config.js b/src/config.js
index 0a4856ece..868c0cdf1 100644
--- a/src/config.js
+++ b/src/config.js
@@ -10,6 +10,7 @@ export const DEFAULT_APP_SETTINGS = {
runInBackground: false,
enableSystemTray: true,
minimizeToSystemTray: false,
- locale: 'en-us', // TODO: Replace with proper solution once translations are in
+ showDisabledServices: true,
+ locale: 'en-US',
beta: false,
};
diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js
index 68ad1039e..cd3251082 100644
--- a/src/containers/layout/AppLayoutContainer.js
+++ b/src/containers/layout/AppLayoutContainer.js
@@ -61,7 +61,6 @@ export default class AppLayoutContainer extends Component {
} = this.props.actions.ui;
const { children } = this.props;
- const allServices = services.enabled;
const isLoadingServices = services.allServicesRequest.isExecuting
&& services.allServicesRequest.isExecutingFirstTime;
@@ -77,7 +76,7 @@ export default class AppLayoutContainer extends Component {
const sidebar = (
);
diff --git a/src/containers/settings/EditSettingsScreen.js b/src/containers/settings/EditSettingsScreen.js
index 6dc2175e1..b10acf3c6 100644
--- a/src/containers/settings/EditSettingsScreen.js
+++ b/src/containers/settings/EditSettingsScreen.js
@@ -39,6 +39,10 @@ const messages = defineMessages({
id: 'settings.app.form.language',
defaultMessage: '!!!Language',
},
+ showDisabledServices: {
+ id: 'settings.app.form.showDisabledServices',
+ defaultMessage: '!!!Display disabled services tabs',
+ },
beta: {
id: 'settings.app.form.beta',
defaultMessage: '!!!Include beta versions',
@@ -68,6 +72,7 @@ export default class EditSettingsScreen extends Component {
runInBackground: settingsData.runInBackground,
enableSystemTray: settingsData.enableSystemTray,
minimizeToSystemTray: settingsData.minimizeToSystemTray,
+ showDisabledServices: settingsData.showDisabledServices,
locale: settingsData.locale,
beta: settingsData.beta,
},
@@ -119,6 +124,11 @@ export default class EditSettingsScreen extends Component {
value: settings.all.minimizeToSystemTray,
default: DEFAULT_APP_SETTINGS.minimizeToSystemTray,
},
+ showDisabledServices: {
+ label: intl.formatMessage(messages.showDisabledServices),
+ value: settings.all.showDisabledServices,
+ default: DEFAULT_APP_SETTINGS.showDisabledServices,
+ },
locale: {
label: intl.formatMessage(messages.language),
value: app.locale,
diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json
index 0493b547f..505e19f0f 100644
--- a/src/i18n/locales/en-US.json
+++ b/src/i18n/locales/en-US.json
@@ -120,6 +120,7 @@
"settings.app.headlineGeneral": "General",
"settings.app.headlineLanguage": "Language",
"settings.app.headlineUpdates": "Updates",
+ "settings.app.headlineAppearance": "Appearance",
"settings.app.buttonSearchForUpdate": "Check for updates",
"settings.app.buttonInstallUpdate": "Restart & install update",
"settings.app.updateStatusSearching": "Is searching for update",
@@ -131,6 +132,7 @@
"settings.app.form.minimizeToSystemTray": "Minimize Franz to system tray",
"settings.app.form.runInBackground": "Keep Franz in background when closing the window",
"settings.app.form.language": "Language",
+ "settings.app.form.showDisabledServices": "Display disabled services tabs",
"settings.app.form.beta": "Include beta versions",
"settings.app.currentVersion": "Current version:",
"settings.service.form.name": "Name",
@@ -165,9 +167,12 @@
"tabs.item.disableNotifications": "Disable notifications",
"tabs.item.enableNotification": "Enable notifications",
"tabs.item.disableService": "Disable service",
+ "tabs.item.enableService": "Enable service",
"tabs.item.deleteService": "Delete service",
"service.crashHandler.headline": "Oh no!",
"service.crashHandler.text": "{name} has caused an error.",
"service.crashHandler.action": "Reload {name}",
- "service.crashHandler.autoReload": "Trying to automatically restore {name} in {seconds} seconds"
+ "service.crashHandler.autoReload": "Trying to automatically restore {name} in {seconds} seconds",
+ "service.disabledHandler.headline": "{name} is disabled",
+ "service.disabledHandler.action": "Enable {name}"
}
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js
index 1d895d532..6c41c22cf 100644
--- a/src/stores/ServicesStore.js
+++ b/src/stores/ServicesStore.js
@@ -78,6 +78,10 @@ export default class ServicesStore extends Store {
return this.all.filter(service => service.isEnabled);
}
+ @computed get allDisplayed() {
+ return this.stores.settings.all.showDisabledServices ? this.all : this.enabled;
+ }
+
@computed get filtered() {
return this.all.filter(service => service.name.toLowerCase().includes(this.filterNeedle.toLowerCase()));
}
@@ -208,21 +212,23 @@ export default class ServicesStore extends Store {
}
@action _setActiveNext() {
- const nextIndex = this._wrapIndex(this.enabled.findIndex(service => service.isActive), 1, this.enabled.length);
+ const nextIndex = this._wrapIndex(this.allDisplayed.findIndex(service => service.isActive), 1, this.allDisplayed.length);
+ // TODO: simplify this;
this.all.forEach((s, index) => {
this.all[index].isActive = false;
});
- this.enabled[nextIndex].isActive = true;
+ this.allDisplayed[nextIndex].isActive = true;
}
@action _setActivePrev() {
- const prevIndex = this._wrapIndex(this.enabled.findIndex(service => service.isActive), -1, this.enabled.length);
+ const prevIndex = this._wrapIndex(this.allDisplayed.findIndex(service => service.isActive), -1, this.allDisplayed.length);
+ // TODO: simplify this;
this.all.forEach((s, index) => {
this.all[index].isActive = false;
});
- this.enabled[prevIndex].isActive = true;
+ this.allDisplayed[prevIndex].isActive = true;
}
@action _setUnreadMessageCount({ serviceId, count }) {
@@ -373,9 +379,9 @@ export default class ServicesStore extends Store {
}
@action _reorder({ oldIndex, newIndex }) {
- const oldEnabledSortIndex = this.all.indexOf(this.enabled[oldIndex]);
- const newEnabledSortIndex = this.all.indexOf(this.enabled[newIndex]);
-
+ const showDisabledServices = this.stores.settings.all.showDisabledServices;
+ const oldEnabledSortIndex = showDisabledServices ? oldIndex : this.all.indexOf(this.enabled[oldIndex]);
+ const newEnabledSortIndex = showDisabledServices ? newIndex : this.all.indexOf(this.enabled[newIndex]);
this.all.splice(newEnabledSortIndex, 0, this.all.splice(oldEnabledSortIndex, 1)[0]);
@@ -444,19 +450,11 @@ export default class ServicesStore extends Store {
_mapActiveServiceToServiceModelReaction() {
const { activeService } = this.stores.settings.all;
- const services = this.enabled;
- if (services.length) {
- services.map(service => Object.assign(service, {
- isActive: activeService ? activeService === service.id : services[0].id === service.id,
+ if (this.allDisplayed.length) {
+ this.allDisplayed.map(service => Object.assign(service, {
+ isActive: activeService ? activeService === service.id : this.allDisplayed[0].id === service.id,
}));
-
- // if (!services.active) {
- //
- // }
}
- // else if (!activeService && services.length) {
- // services[0].isActive = true;
- // }
}
_getUnreadMessageCountReaction() {
diff --git a/src/stores/SettingsStore.js b/src/stores/SettingsStore.js
index 816f545ee..331df5c15 100644
--- a/src/stores/SettingsStore.js
+++ b/src/stores/SettingsStore.js
@@ -5,6 +5,7 @@ import Store from './lib/Store';
import Request from './lib/Request';
import CachedRequest from './lib/CachedRequest';
import { gaEvent } from '../lib/analytics';
+import { DEFAULT_APP_SETTINGS } from '../config';
export default class SettingsStore extends Store {
@observable allSettingsRequest = new CachedRequest(this.api.local, 'getSettings');
@@ -29,7 +30,7 @@ export default class SettingsStore extends Store {
}
@computed get all() {
- return this.allSettingsRequest.result || {};
+ return observable(Object.assign(DEFAULT_APP_SETTINGS, this.allSettingsRequest.result));
}
@action async _update({ settings }) {
diff --git a/src/styles/services.scss b/src/styles/services.scss
index 95738f123..2a6540e0b 100644
--- a/src/styles/services.scss
+++ b/src/styles/services.scss
@@ -8,6 +8,10 @@
background: #FFF;
order: 5;
+ .services__webview-wrapper {
+ background: $theme-gray-lighter;
+ }
+
.services__webview,
.services__crash-handler {
position: absolute;
diff --git a/src/styles/tabs.scss b/src/styles/tabs.scss
index 75568898b..3e5904d2c 100644
--- a/src/styles/tabs.scss
+++ b/src/styles/tabs.scss
@@ -33,6 +33,12 @@
}
}
+ &.is-disabled {
+ .tab-item__icon {
+ filter: grayscale(100%) opacity(0.2);
+ }
+ }
+
&.has-custom-icon {
.tab-item__icon {
border-radius: $theme-border-radius;