aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Stefan Malzner <stefan@adlk.io>2017-11-09 12:11:16 +0100
committerLibravatar Stefan Malzner <stefan@adlk.io>2017-11-09 12:15:36 +0100
commit1839eff4fcad186871672499b6c3cc68e9539ce2 (patch)
tree207f0c0cf694309f6d84afeee220cacdc9b56242
parentMerge branch 'develop' of github.com:meetfranz/franz into develop (diff)
downloadferdium-app-1839eff4fcad186871672499b6c3cc68e9539ce2.tar.gz
ferdium-app-1839eff4fcad186871672499b6c3cc68e9539ce2.tar.zst
ferdium-app-1839eff4fcad186871672499b6c3cc68e9539ce2.zip
feat(Service): Add option to display disabled services in tabs
-rw-r--r--src/components/services/content/ServiceDisabled.js48
-rw-r--r--src/components/services/content/ServiceWebview.js56
-rw-r--r--src/components/services/content/Services.js9
-rw-r--r--src/components/services/content/WebviewCrashHandler.js2
-rw-r--r--src/components/services/tabs/TabBarSortableList.js3
-rw-r--r--src/components/services/tabs/TabItem.js11
-rw-r--r--src/components/services/tabs/Tabbar.js15
-rw-r--r--src/components/settings/settings/EditSettingsForm.js6
-rw-r--r--src/config.js3
-rw-r--r--src/containers/layout/AppLayoutContainer.js6
-rw-r--r--src/containers/settings/EditSettingsScreen.js10
-rw-r--r--src/i18n/locales/en-US.json7
-rw-r--r--src/stores/ServicesStore.js34
-rw-r--r--src/stores/SettingsStore.js3
-rw-r--r--src/styles/services.scss4
-rw-r--r--src/styles/tabs.scss6
16 files changed, 172 insertions, 51 deletions
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 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl';
5
6import Button from '../../ui/Button';
7
8const messages = defineMessages({
9 headline: {
10 id: 'service.disabledHandler.headline',
11 defaultMessage: '!!!{name} is disabled',
12 },
13 action: {
14 id: 'service.disabledHandler.action',
15 defaultMessage: '!!!Enable {name}',
16 },
17});
18
19@observer
20export default class ServiceDisabled extends Component {
21 static propTypes = {
22 name: PropTypes.string.isRequired,
23 enable: PropTypes.func.isRequired,
24 };
25
26 static contextTypes = {
27 intl: intlShape,
28 };
29
30 countdownInterval = null;
31 countdownIntervalTimeout = 1000;
32
33 render() {
34 const { name, enable } = this.props;
35 const { intl } = this.context;
36
37 return (
38 <div className="services__crash-handler">
39 <h1>{intl.formatMessage(messages.headline, { name })}</h1>
40 <Button
41 label={intl.formatMessage(messages.action, { name })}
42 buttonType="inverted"
43 onClick={() => enable()}
44 />
45 </div>
46 );
47 }
48}
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';
8import ServiceModel from '../../../models/Service'; 8import ServiceModel from '../../../models/Service';
9import StatusBarTargetUrl from '../../ui/StatusBarTargetUrl'; 9import StatusBarTargetUrl from '../../ui/StatusBarTargetUrl';
10import WebviewCrashHandler from './WebviewCrashHandler'; 10import WebviewCrashHandler from './WebviewCrashHandler';
11import ServiceDisabled from './ServiceDisabled';
11 12
12@observer 13@observer
13export default class ServiceWebview extends Component { 14export default class ServiceWebview extends Component {
@@ -15,6 +16,7 @@ export default class ServiceWebview extends Component {
15 service: PropTypes.instanceOf(ServiceModel).isRequired, 16 service: PropTypes.instanceOf(ServiceModel).isRequired,
16 setWebviewReference: PropTypes.func.isRequired, 17 setWebviewReference: PropTypes.func.isRequired,
17 reload: PropTypes.func.isRequired, 18 reload: PropTypes.func.isRequired,
19 enable: PropTypes.func.isRequired,
18 }; 20 };
19 21
20 static defaultProps = { 22 static defaultProps = {
@@ -56,6 +58,7 @@ export default class ServiceWebview extends Component {
56 service, 58 service,
57 setWebviewReference, 59 setWebviewReference,
58 reload, 60 reload,
61 enable,
59 } = this.props; 62 } = this.props;
60 63
61 const webviewClasses = classnames({ 64 const webviewClasses = classnames({
@@ -80,27 +83,38 @@ export default class ServiceWebview extends Component {
80 reload={reload} 83 reload={reload}
81 /> 84 />
82 )} 85 )}
83 <Webview 86 {!service.isEnabled && (
84 ref={(element) => { this.webview = element; }} 87 <ServiceDisabled
85 88 name={service.recipe.name}
86 autosize 89 webview={service.webview}
87 src={service.url} 90 enable={enable}
88 preload="./webview/plugin.js" 91 />
89 partition={`persist:service-${service.id}`} 92 )}
90 93 {service.isEnabled && (
91 onDidAttach={() => setWebviewReference({ 94 <div className="services__webview-wrapper">
92 serviceId: service.id, 95 <Webview
93 webview: this.webview.view, 96 ref={(element) => { this.webview = element; }}
94 })} 97
95 98 autosize
96 onUpdateTargetUrl={this.updateTargetUrl} 99 src={service.url}
97 100 preload="./webview/plugin.js"
98 useragent={service.userAgent} 101 partition={`persist:service-${service.id}`}
99 102
100 disablewebsecurity 103 onDidAttach={() => setWebviewReference({
101 allowpopups 104 serviceId: service.id,
102 /> 105 webview: this.webview.view,
103 {statusBar} 106 })}
107
108 onUpdateTargetUrl={this.updateTargetUrl}
109
110 useragent={service.userAgent}
111
112 disablewebsecurity
113 allowpopups
114 />
115 {statusBar}
116 </div>
117 )}
104 </div> 118 </div>
105 ); 119 );
106 } 120 }
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 {
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 update: PropTypes.func.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 update,
47 } = this.props; 49 } = this.props;
48 const { intl } = this.context; 50 const { intl } = this.context;
49 51
@@ -76,6 +78,13 @@ 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 enable={() => update({
82 serviceId: service.id,
83 serviceData: {
84 isEnabled: true,
85 },
86 redirect: false,
87 })}
79 /> 88 />
80 ))} 89 ))}
81 </div> 90 </div>
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({
25}); 25});
26 26
27@observer 27@observer
28export default class ServiceWebview extends Component { 28export default class WebviewCrashHandler extends Component {
29 static propTypes = { 29 static propTypes = {
30 name: PropTypes.string.isRequired, 30 name: PropTypes.string.isRequired,
31 reload: PropTypes.func.isRequired, 31 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 {
24 toggleNotifications: PropTypes.func.isRequired, 24 toggleNotifications: PropTypes.func.isRequired,
25 deleteService: PropTypes.func.isRequired, 25 deleteService: PropTypes.func.isRequired,
26 disableService: PropTypes.func.isRequired, 26 disableService: PropTypes.func.isRequired,
27 enableService: PropTypes.func.isRequired,
27 } 28 }
28 29
29 static contextTypes = { 30 static contextTypes = {
@@ -38,6 +39,7 @@ class TabBarSortableList extends Component {
38 toggleNotifications, 39 toggleNotifications,
39 deleteService, 40 deleteService,
40 disableService, 41 disableService,
42 enableService,
41 openSettings, 43 openSettings,
42 } = this.props; 44 } = this.props;
43 45
@@ -58,6 +60,7 @@ class TabBarSortableList extends Component {
58 toggleNotifications={() => toggleNotifications({ serviceId: service.id })} 60 toggleNotifications={() => toggleNotifications({ serviceId: service.id })}
59 deleteService={() => deleteService({ serviceId: service.id })} 61 deleteService={() => deleteService({ serviceId: service.id })}
60 disableService={() => disableService({ serviceId: service.id })} 62 disableService={() => disableService({ serviceId: service.id })}
63 enableService={() => enableService({ serviceId: service.id })}
61 openSettings={openSettings} 64 openSettings={openSettings}
62 /> 65 />
63 ))} 66 ))}
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({
32 id: 'tabs.item.disableService', 32 id: 'tabs.item.disableService',
33 defaultMessage: '!!!Disable Service', 33 defaultMessage: '!!!Disable Service',
34 }, 34 },
35 enableService: {
36 id: 'tabs.item.enableService',
37 defaultMessage: '!!!Enable Service',
38 },
35 deleteService: { 39 deleteService: {
36 id: 'tabs.item.deleteService', 40 id: 'tabs.item.deleteService',
37 defaultMessage: '!!!Delete Service', 41 defaultMessage: '!!!Delete Service',
@@ -49,6 +53,7 @@ class TabItem extends Component {
49 openSettings: PropTypes.func.isRequired, 53 openSettings: PropTypes.func.isRequired,
50 deleteService: PropTypes.func.isRequired, 54 deleteService: PropTypes.func.isRequired,
51 disableService: PropTypes.func.isRequired, 55 disableService: PropTypes.func.isRequired,
56 enableService: PropTypes.func.isRequired,
52 }; 57 };
53 58
54 static contextTypes = { 59 static contextTypes = {
@@ -64,6 +69,7 @@ class TabItem extends Component {
64 toggleNotifications, 69 toggleNotifications,
65 deleteService, 70 deleteService,
66 disableService, 71 disableService,
72 enableService,
67 openSettings, 73 openSettings,
68 } = this.props; 74 } = this.props;
69 const { intl } = this.context; 75 const { intl } = this.context;
@@ -90,8 +96,8 @@ class TabItem extends Component {
90 : intl.formatMessage(messages.enableNotifications), 96 : intl.formatMessage(messages.enableNotifications),
91 click: () => toggleNotifications(), 97 click: () => toggleNotifications(),
92 }, { 98 }, {
93 label: intl.formatMessage(messages.disableService), 99 label: intl.formatMessage(service.isEnabled ? messages.disableService : messages.enableService),
94 click: () => disableService(), 100 click: () => (service.isEnabled ? disableService() : enableService()),
95 }, { 101 }, {
96 type: 'separator', 102 type: 'separator',
97 }, { 103 }, {
@@ -106,6 +112,7 @@ class TabItem extends Component {
106 'tab-item': true, 112 'tab-item': true,
107 'is-active': service.isActive, 113 'is-active': service.isActive,
108 'has-custom-icon': service.hasCustomIcon, 114 'has-custom-icon': service.hasCustomIcon,
115 'is-disabled': !service.isEnabled,
109 })} 116 })}
110 onClick={clickHandler} 117 onClick={clickHandler}
111 onContextMenu={() => menu.popup(remote.getCurrentWindow())} 118 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 {
29 reorder({ oldIndex, newIndex }); 29 reorder({ oldIndex, newIndex });
30 }; 30 };
31 31
32 disableService = ({ serviceId }) => { 32 toggleService = ({ serviceId, isEnabled }) => {
33 const { updateService } = this.props; 33 const { updateService } = this.props;
34 34
35 if (serviceId) { 35 if (serviceId) {
36 updateService({ 36 updateService({
37 serviceId, 37 serviceId,
38 serviceData: { 38 serviceData: {
39 isEnabled: false, 39 isEnabled,
40 }, 40 },
41 redirect: false, 41 redirect: false,
42 }); 42 });
43 } 43 }
44 } 44 }
45 45
46 disableService({ serviceId }) {
47 this.toggleService({ serviceId, isEnabled: false });
48 }
49
50 enableService({ serviceId }) {
51 this.toggleService({ serviceId, isEnabled: true });
52 }
53
46 render() { 54 render() {
47 const { 55 const {
48 services, 56 services,
@@ -64,7 +72,8 @@ export default class TabBar extends Component {
64 reload={reload} 72 reload={reload}
65 toggleNotifications={toggleNotifications} 73 toggleNotifications={toggleNotifications}
66 deleteService={deleteService} 74 deleteService={deleteService}
67 disableService={this.disableService} 75 disableService={args => this.disableService(args)}
76 enableService={args => this.enableService(args)}
68 openSettings={openSettings} 77 openSettings={openSettings}
69 distance={20} 78 distance={20}
70 axis="y" 79 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({
26 id: 'settings.app.headlineUpdates', 26 id: 'settings.app.headlineUpdates',
27 defaultMessage: '!!!Updates', 27 defaultMessage: '!!!Updates',
28 }, 28 },
29 headlineAppearance: {
30 id: 'settings.app.headlineAppearance',
31 defaultMessage: '!!!Appearance',
32 },
29 buttonSearchForUpdate: { 33 buttonSearchForUpdate: {
30 id: 'settings.app.buttonSearchForUpdate', 34 id: 'settings.app.buttonSearchForUpdate',
31 defaultMessage: '!!!Check for updates', 35 defaultMessage: '!!!Check for updates',
@@ -119,6 +123,8 @@ export default class EditSettingsForm extends Component {
119 {process.platform === 'win32' && ( 123 {process.platform === 'win32' && (
120 <Toggle field={form.$('minimizeToSystemTray')} /> 124 <Toggle field={form.$('minimizeToSystemTray')} />
121 )} 125 )}
126 <h2>{intl.formatMessage(messages.headlineAppearance)}</h2>
127 <Toggle field={form.$('showDisabledServices')} />
122 <h2>{intl.formatMessage(messages.headlineLanguage)}</h2> 128 <h2>{intl.formatMessage(messages.headlineLanguage)}</h2>
123 <Select field={form.$('locale')} showLabel={false} /> 129 <Select field={form.$('locale')} showLabel={false} />
124 <h2>{intl.formatMessage(messages.headlineUpdates)}</h2> 130 <h2>{intl.formatMessage(messages.headlineUpdates)}</h2>
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 = {
10 runInBackground: false, 10 runInBackground: false,
11 enableSystemTray: true, 11 enableSystemTray: true,
12 minimizeToSystemTray: false, 12 minimizeToSystemTray: false,
13 locale: 'en-us', // TODO: Replace with proper solution once translations are in 13 showDisabledServices: true,
14 locale: 'en-US',
14 beta: false, 15 beta: false,
15}; 16};
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 {
61 } = this.props.actions.ui; 61 } = this.props.actions.ui;
62 62
63 const { children } = this.props; 63 const { children } = this.props;
64 const allServices = services.enabled;
65 64
66 const isLoadingServices = services.allServicesRequest.isExecuting 65 const isLoadingServices = services.allServicesRequest.isExecuting
67 && services.allServicesRequest.isExecutingFirstTime; 66 && services.allServicesRequest.isExecutingFirstTime;
@@ -77,7 +76,7 @@ export default class AppLayoutContainer extends Component {
77 76
78 const sidebar = ( 77 const sidebar = (
79 <Sidebar 78 <Sidebar
80 services={allServices} 79 services={services.allDisplayed}
81 setActive={setActive} 80 setActive={setActive}
82 openSettings={openSettings} 81 openSettings={openSettings}
83 closeSettings={closeSettings} 82 closeSettings={closeSettings}
@@ -92,11 +91,12 @@ export default class AppLayoutContainer extends Component {
92 91
93 const servicesContainer = ( 92 const servicesContainer = (
94 <Services 93 <Services
95 services={allServices} 94 services={services.allDisplayed}
96 handleIPCMessage={handleIPCMessage} 95 handleIPCMessage={handleIPCMessage}
97 setWebviewReference={setWebviewReference} 96 setWebviewReference={setWebviewReference}
98 openWindow={openWindow} 97 openWindow={openWindow}
99 reload={reload} 98 reload={reload}
99 update={updateService}
100 /> 100 />
101 ); 101 );
102 102
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({
39 id: 'settings.app.form.language', 39 id: 'settings.app.form.language',
40 defaultMessage: '!!!Language', 40 defaultMessage: '!!!Language',
41 }, 41 },
42 showDisabledServices: {
43 id: 'settings.app.form.showDisabledServices',
44 defaultMessage: '!!!Display disabled services tabs',
45 },
42 beta: { 46 beta: {
43 id: 'settings.app.form.beta', 47 id: 'settings.app.form.beta',
44 defaultMessage: '!!!Include beta versions', 48 defaultMessage: '!!!Include beta versions',
@@ -68,6 +72,7 @@ export default class EditSettingsScreen extends Component {
68 runInBackground: settingsData.runInBackground, 72 runInBackground: settingsData.runInBackground,
69 enableSystemTray: settingsData.enableSystemTray, 73 enableSystemTray: settingsData.enableSystemTray,
70 minimizeToSystemTray: settingsData.minimizeToSystemTray, 74 minimizeToSystemTray: settingsData.minimizeToSystemTray,
75 showDisabledServices: settingsData.showDisabledServices,
71 locale: settingsData.locale, 76 locale: settingsData.locale,
72 beta: settingsData.beta, 77 beta: settingsData.beta,
73 }, 78 },
@@ -119,6 +124,11 @@ export default class EditSettingsScreen extends Component {
119 value: settings.all.minimizeToSystemTray, 124 value: settings.all.minimizeToSystemTray,
120 default: DEFAULT_APP_SETTINGS.minimizeToSystemTray, 125 default: DEFAULT_APP_SETTINGS.minimizeToSystemTray,
121 }, 126 },
127 showDisabledServices: {
128 label: intl.formatMessage(messages.showDisabledServices),
129 value: settings.all.showDisabledServices,
130 default: DEFAULT_APP_SETTINGS.showDisabledServices,
131 },
122 locale: { 132 locale: {
123 label: intl.formatMessage(messages.language), 133 label: intl.formatMessage(messages.language),
124 value: app.locale, 134 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 @@
120 "settings.app.headlineGeneral": "General", 120 "settings.app.headlineGeneral": "General",
121 "settings.app.headlineLanguage": "Language", 121 "settings.app.headlineLanguage": "Language",
122 "settings.app.headlineUpdates": "Updates", 122 "settings.app.headlineUpdates": "Updates",
123 "settings.app.headlineAppearance": "Appearance",
123 "settings.app.buttonSearchForUpdate": "Check for updates", 124 "settings.app.buttonSearchForUpdate": "Check for updates",
124 "settings.app.buttonInstallUpdate": "Restart & install update", 125 "settings.app.buttonInstallUpdate": "Restart & install update",
125 "settings.app.updateStatusSearching": "Is searching for update", 126 "settings.app.updateStatusSearching": "Is searching for update",
@@ -131,6 +132,7 @@
131 "settings.app.form.minimizeToSystemTray": "Minimize Franz to system tray", 132 "settings.app.form.minimizeToSystemTray": "Minimize Franz to system tray",
132 "settings.app.form.runInBackground": "Keep Franz in background when closing the window", 133 "settings.app.form.runInBackground": "Keep Franz in background when closing the window",
133 "settings.app.form.language": "Language", 134 "settings.app.form.language": "Language",
135 "settings.app.form.showDisabledServices": "Display disabled services tabs",
134 "settings.app.form.beta": "Include beta versions", 136 "settings.app.form.beta": "Include beta versions",
135 "settings.app.currentVersion": "Current version:", 137 "settings.app.currentVersion": "Current version:",
136 "settings.service.form.name": "Name", 138 "settings.service.form.name": "Name",
@@ -165,9 +167,12 @@
165 "tabs.item.disableNotifications": "Disable notifications", 167 "tabs.item.disableNotifications": "Disable notifications",
166 "tabs.item.enableNotification": "Enable notifications", 168 "tabs.item.enableNotification": "Enable notifications",
167 "tabs.item.disableService": "Disable service", 169 "tabs.item.disableService": "Disable service",
170 "tabs.item.enableService": "Enable service",
168 "tabs.item.deleteService": "Delete service", 171 "tabs.item.deleteService": "Delete service",
169 "service.crashHandler.headline": "Oh no!", 172 "service.crashHandler.headline": "Oh no!",
170 "service.crashHandler.text": "{name} has caused an error.", 173 "service.crashHandler.text": "{name} has caused an error.",
171 "service.crashHandler.action": "Reload {name}", 174 "service.crashHandler.action": "Reload {name}",
172 "service.crashHandler.autoReload": "Trying to automatically restore {name} in {seconds} seconds" 175 "service.crashHandler.autoReload": "Trying to automatically restore {name} in {seconds} seconds",
176 "service.disabledHandler.headline": "{name} is disabled",
177 "service.disabledHandler.action": "Enable {name}"
173} 178}
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 {
78 return this.all.filter(service => service.isEnabled); 78 return this.all.filter(service => service.isEnabled);
79 } 79 }
80 80
81 @computed get allDisplayed() {
82 return this.stores.settings.all.showDisabledServices ? this.all : this.enabled;
83 }
84
81 @computed get filtered() { 85 @computed get filtered() {
82 return this.all.filter(service => service.name.toLowerCase().includes(this.filterNeedle.toLowerCase())); 86 return this.all.filter(service => service.name.toLowerCase().includes(this.filterNeedle.toLowerCase()));
83 } 87 }
@@ -208,21 +212,23 @@ export default class ServicesStore extends Store {
208 } 212 }
209 213
210 @action _setActiveNext() { 214 @action _setActiveNext() {
211 const nextIndex = this._wrapIndex(this.enabled.findIndex(service => service.isActive), 1, this.enabled.length); 215 const nextIndex = this._wrapIndex(this.allDisplayed.findIndex(service => service.isActive), 1, this.allDisplayed.length);
212 216
217 // TODO: simplify this;
213 this.all.forEach((s, index) => { 218 this.all.forEach((s, index) => {
214 this.all[index].isActive = false; 219 this.all[index].isActive = false;
215 }); 220 });
216 this.enabled[nextIndex].isActive = true; 221 this.allDisplayed[nextIndex].isActive = true;
217 } 222 }
218 223
219 @action _setActivePrev() { 224 @action _setActivePrev() {
220 const prevIndex = this._wrapIndex(this.enabled.findIndex(service => service.isActive), -1, this.enabled.length); 225 const prevIndex = this._wrapIndex(this.allDisplayed.findIndex(service => service.isActive), -1, this.allDisplayed.length);
221 226
227 // TODO: simplify this;
222 this.all.forEach((s, index) => { 228 this.all.forEach((s, index) => {
223 this.all[index].isActive = false; 229 this.all[index].isActive = false;
224 }); 230 });
225 this.enabled[prevIndex].isActive = true; 231 this.allDisplayed[prevIndex].isActive = true;
226 } 232 }
227 233
228 @action _setUnreadMessageCount({ serviceId, count }) { 234 @action _setUnreadMessageCount({ serviceId, count }) {
@@ -373,9 +379,9 @@ export default class ServicesStore extends Store {
373 } 379 }
374 380
375 @action _reorder({ oldIndex, newIndex }) { 381 @action _reorder({ oldIndex, newIndex }) {
376 const oldEnabledSortIndex = this.all.indexOf(this.enabled[oldIndex]); 382 const showDisabledServices = this.stores.settings.all.showDisabledServices;
377 const newEnabledSortIndex = this.all.indexOf(this.enabled[newIndex]); 383 const oldEnabledSortIndex = showDisabledServices ? oldIndex : this.all.indexOf(this.enabled[oldIndex]);
378 384 const newEnabledSortIndex = showDisabledServices ? newIndex : this.all.indexOf(this.enabled[newIndex]);
379 385
380 this.all.splice(newEnabledSortIndex, 0, this.all.splice(oldEnabledSortIndex, 1)[0]); 386 this.all.splice(newEnabledSortIndex, 0, this.all.splice(oldEnabledSortIndex, 1)[0]);
381 387
@@ -444,19 +450,11 @@ export default class ServicesStore extends Store {
444 450
445 _mapActiveServiceToServiceModelReaction() { 451 _mapActiveServiceToServiceModelReaction() {
446 const { activeService } = this.stores.settings.all; 452 const { activeService } = this.stores.settings.all;
447 const services = this.enabled; 453 if (this.allDisplayed.length) {
448 if (services.length) { 454 this.allDisplayed.map(service => Object.assign(service, {
449 services.map(service => Object.assign(service, { 455 isActive: activeService ? activeService === service.id : this.allDisplayed[0].id === service.id,
450 isActive: activeService ? activeService === service.id : services[0].id === service.id,
451 })); 456 }));
452
453 // if (!services.active) {
454 //
455 // }
456 } 457 }
457 // else if (!activeService && services.length) {
458 // services[0].isActive = true;
459 // }
460 } 458 }
461 459
462 _getUnreadMessageCountReaction() { 460 _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';
5import Request from './lib/Request'; 5import Request from './lib/Request';
6import CachedRequest from './lib/CachedRequest'; 6import CachedRequest from './lib/CachedRequest';
7import { gaEvent } from '../lib/analytics'; 7import { gaEvent } from '../lib/analytics';
8import { DEFAULT_APP_SETTINGS } from '../config';
8 9
9export default class SettingsStore extends Store { 10export default class SettingsStore extends Store {
10 @observable allSettingsRequest = new CachedRequest(this.api.local, 'getSettings'); 11 @observable allSettingsRequest = new CachedRequest(this.api.local, 'getSettings');
@@ -29,7 +30,7 @@ export default class SettingsStore extends Store {
29 } 30 }
30 31
31 @computed get all() { 32 @computed get all() {
32 return this.allSettingsRequest.result || {}; 33 return observable(Object.assign(DEFAULT_APP_SETTINGS, this.allSettingsRequest.result));
33 } 34 }
34 35
35 @action async _update({ settings }) { 36 @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 @@
8 background: #FFF; 8 background: #FFF;
9 order: 5; 9 order: 5;
10 10
11 .services__webview-wrapper {
12 background: $theme-gray-lighter;
13 }
14
11 .services__webview, 15 .services__webview,
12 .services__crash-handler { 16 .services__crash-handler {
13 position: absolute; 17 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 @@
33 } 33 }
34 } 34 }
35 35
36 &.is-disabled {
37 .tab-item__icon {
38 filter: grayscale(100%) opacity(0.2);
39 }
40 }
41
36 &.has-custom-icon { 42 &.has-custom-icon {
37 .tab-item__icon { 43 .tab-item__icon {
38 border-radius: $theme-border-radius; 44 border-radius: $theme-border-radius;