aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/services
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/services')
-rw-r--r--src/components/services/content/ErrorHandlers/WebviewErrorHandler.js84
-rw-r--r--src/components/services/content/ErrorHandlers/styles.js25
-rw-r--r--src/components/services/content/ServiceDisabled.js1
-rw-r--r--src/components/services/content/ServiceWebview.js65
-rw-r--r--src/components/services/content/Services.js6
-rw-r--r--src/components/services/content/WebviewCrashHandler.js24
6 files changed, 177 insertions, 28 deletions
diff --git a/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js b/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js
new file mode 100644
index 000000000..415a8d1b5
--- /dev/null
+++ b/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js
@@ -0,0 +1,84 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl';
5import injectSheet from 'react-jss';
6
7import Button from '../../../ui/Button';
8
9import styles from './styles';
10
11const messages = defineMessages({
12 headline: {
13 id: 'service.errorHandler.headline',
14 defaultMessage: '!!!Oh no!',
15 },
16 text: {
17 id: 'service.errorHandler.text',
18 defaultMessage: '!!!{name} has failed to load.',
19 },
20 action: {
21 id: 'service.errorHandler.action',
22 defaultMessage: '!!!Reload {name}',
23 },
24 editAction: {
25 id: 'service.errorHandler.editAction',
26 defaultMessage: '!!!Edit {name}',
27 },
28 errorMessage: {
29 id: 'service.errorHandler.message',
30 defaultMessage: '!!!Error:',
31 },
32});
33
34export default @injectSheet(styles) @observer class WebviewCrashHandler extends Component {
35 static propTypes = {
36 name: PropTypes.string.isRequired,
37 reload: PropTypes.func.isRequired,
38 edit: PropTypes.func.isRequired,
39 errorMessage: PropTypes.string.isRequired,
40 classes: PropTypes.object.isRequired,
41 };
42
43 static contextTypes = {
44 intl: intlShape,
45 };
46
47 render() {
48 const {
49 name,
50 reload,
51 edit,
52 errorMessage,
53 classes,
54 } = this.props;
55 const { intl } = this.context;
56
57 return (
58 <div className={classes.component}>
59 <h1>{intl.formatMessage(messages.headline)}</h1>
60 <p>{intl.formatMessage(messages.text, { name })}</p>
61 <p>
62 <strong>
63 {intl.formatMessage(messages.errorMessage)}
64:
65 </strong>
66 {' '}
67 {errorMessage}
68 </p>
69 <div className={classes.buttonContainer}>
70 <Button
71 label={intl.formatMessage(messages.editAction, { name })}
72 buttonType="inverted"
73 onClick={() => edit()}
74 />
75 <Button
76 label={intl.formatMessage(messages.action, { name })}
77 buttonType="inverted"
78 onClick={() => reload()}
79 />
80 </div>
81 </div>
82 );
83 }
84}
diff --git a/src/components/services/content/ErrorHandlers/styles.js b/src/components/services/content/ErrorHandlers/styles.js
new file mode 100644
index 000000000..f11386798
--- /dev/null
+++ b/src/components/services/content/ErrorHandlers/styles.js
@@ -0,0 +1,25 @@
1export default {
2 component: {
3 left: 0,
4 position: 'absolute',
5 top: 0,
6 width: '100%',
7 zIndex: 0,
8 alignItems: 'center',
9 // background: $theme-gray-lighter;
10 display: 'flex',
11 flexDirection: 'column',
12 justifyContent: 'center',
13 textAlign: 'center',
14 },
15 buttonContainer: {
16 display: 'flex',
17 flexDirection: 'row',
18 height: 'auto',
19 margin: [40, 0, 20],
20
21 '& button': {
22 margin: [0, 10, 0, 10],
23 },
24 },
25};
diff --git a/src/components/services/content/ServiceDisabled.js b/src/components/services/content/ServiceDisabled.js
index 58fb38d8c..d0f12256e 100644
--- a/src/components/services/content/ServiceDisabled.js
+++ b/src/components/services/content/ServiceDisabled.js
@@ -27,6 +27,7 @@ export default @observer class ServiceDisabled extends Component {
27 }; 27 };
28 28
29 countdownInterval = null; 29 countdownInterval = null;
30
30 countdownIntervalTimeout = 1000; 31 countdownIntervalTimeout = 1000;
31 32
32 render() { 33 render() {
diff --git a/src/components/services/content/ServiceWebview.js b/src/components/services/content/ServiceWebview.js
index 7163209ee..b1a2c0207 100644
--- a/src/components/services/content/ServiceWebview.js
+++ b/src/components/services/content/ServiceWebview.js
@@ -1,4 +1,4 @@
1import React, { Component } from 'react'; 1import React, { Component, Fragment } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { autorun } from 'mobx'; 3import { autorun } from 'mobx';
4import { observer } from 'mobx-react'; 4import { observer } from 'mobx-react';
@@ -7,7 +7,9 @@ import classnames from 'classnames';
7 7
8import ServiceModel from '../../../models/Service'; 8import ServiceModel from '../../../models/Service';
9import StatusBarTargetUrl from '../../ui/StatusBarTargetUrl'; 9import StatusBarTargetUrl from '../../ui/StatusBarTargetUrl';
10import WebviewLoader from '../../ui/WebviewLoader';
10import WebviewCrashHandler from './WebviewCrashHandler'; 11import WebviewCrashHandler from './WebviewCrashHandler';
12import WebviewErrorHandler from './ErrorHandlers/WebviewErrorHandler';
11import ServiceDisabled from './ServiceDisabled'; 13import ServiceDisabled from './ServiceDisabled';
12 14
13export default @observer class ServiceWebview extends Component { 15export default @observer class ServiceWebview extends Component {
@@ -15,8 +17,10 @@ export default @observer class ServiceWebview extends Component {
15 service: PropTypes.instanceOf(ServiceModel).isRequired, 17 service: PropTypes.instanceOf(ServiceModel).isRequired,
16 setWebviewReference: PropTypes.func.isRequired, 18 setWebviewReference: PropTypes.func.isRequired,
17 reload: PropTypes.func.isRequired, 19 reload: PropTypes.func.isRequired,
20 edit: PropTypes.func.isRequired,
18 isAppMuted: PropTypes.bool.isRequired, 21 isAppMuted: PropTypes.bool.isRequired,
19 enable: PropTypes.func.isRequired, 22 enable: PropTypes.func.isRequired,
23 isActive: PropTypes.bool,
20 }; 24 };
21 25
22 static defaultProps = { 26 static defaultProps = {
@@ -29,8 +33,12 @@ export default @observer class ServiceWebview extends Component {
29 statusBarVisible: false, 33 statusBarVisible: false,
30 }; 34 };
31 35
36 autorunDisposer = null;
37
38 webview = null;
39
32 componentDidMount() { 40 componentDidMount() {
33 autorun(() => { 41 this.autorunDisposer = autorun(() => {
34 if (this.props.service.isActive) { 42 if (this.props.service.isActive) {
35 this.setState({ forceRepaint: true }); 43 this.setState({ forceRepaint: true });
36 setTimeout(() => { 44 setTimeout(() => {
@@ -40,6 +48,10 @@ export default @observer class ServiceWebview extends Component {
40 }); 48 });
41 } 49 }
42 50
51 componentWillUnmount() {
52 this.autorunDisposer();
53 }
54
43 updateTargetUrl = (event) => { 55 updateTargetUrl = (event) => {
44 let visible = true; 56 let visible = true;
45 if (event.url === '' || event.url === '#') { 57 if (event.url === '' || event.url === '#') {
@@ -51,13 +63,12 @@ export default @observer class ServiceWebview extends Component {
51 }); 63 });
52 } 64 }
53 65
54 webview = null;
55
56 render() { 66 render() {
57 const { 67 const {
58 service, 68 service,
59 setWebviewReference, 69 setWebviewReference,
60 reload, 70 reload,
71 edit,
61 isAppMuted, 72 isAppMuted,
62 enable, 73 enable,
63 } = this.props; 74 } = this.props;
@@ -78,25 +89,47 @@ export default @observer class ServiceWebview extends Component {
78 89
79 return ( 90 return (
80 <div className={webviewClasses}> 91 <div className={webviewClasses}>
81 {service.hasCrashed && ( 92 {service.isActive && service.isEnabled && (
82 <WebviewCrashHandler 93 <Fragment>
83 name={service.recipe.name} 94 {service.hasCrashed && (
84 webview={service.webview} 95 <WebviewCrashHandler
85 reload={reload} 96 name={service.recipe.name}
86 /> 97 webview={service.webview}
98 reload={reload}
99 />
100 )}
101 {service.isEnabled && service.isLoading && service.isFirstLoad && (
102 <WebviewLoader
103 loaded={false}
104 name={service.name}
105 />
106 )}
107 {service.isError && (
108 <WebviewErrorHandler
109 name={service.recipe.name}
110 errorMessage={service.errorMessage}
111 reload={reload}
112 edit={edit}
113 />
114 )}
115 </Fragment>
87 )} 116 )}
88 {!service.isEnabled ? ( 117 {!service.isEnabled ? (
89 <ServiceDisabled 118 <Fragment>
90 name={service.recipe.name} 119 {service.isActive && (
91 webview={service.webview} 120 <ServiceDisabled
92 enable={enable} 121 name={service.recipe.name}
93 /> 122 webview={service.webview}
123 enable={enable}
124 />
125 )}
126 </Fragment>
94 ) : ( 127 ) : (
95 <Webview 128 <Webview
96 ref={(element) => { this.webview = element; }} 129 ref={(element) => { this.webview = element; }}
97 autosize 130 autosize
98 src={service.url} 131 src={service.url}
99 preload="./webview/plugin.js" 132 preload="./webview/recipe.js"
100 partition={`persist:service-${service.id}`} 133 partition={`persist:service-${service.id}`}
101 onDidAttach={() => setWebviewReference({ 134 onDidAttach={() => setWebviewReference({
102 serviceId: service.id, 135 serviceId: service.id,
diff --git a/src/components/services/content/Services.js b/src/components/services/content/Services.js
index 4cbd51043..1aeb17e03 100644
--- a/src/components/services/content/Services.js
+++ b/src/components/services/content/Services.js
@@ -20,18 +20,18 @@ const messages = defineMessages({
20 20
21export default @observer class Services extends Component { 21export default @observer class Services extends Component {
22 static propTypes = { 22 static propTypes = {
23 services: MobxPropTypes.arrayOrObservableArray.isRequired, 23 services: MobxPropTypes.arrayOrObservableArray,
24 setWebviewReference: PropTypes.func.isRequired, 24 setWebviewReference: PropTypes.func.isRequired,
25 handleIPCMessage: PropTypes.func.isRequired, 25 handleIPCMessage: PropTypes.func.isRequired,
26 openWindow: PropTypes.func.isRequired, 26 openWindow: PropTypes.func.isRequired,
27 reload: PropTypes.func.isRequired, 27 reload: PropTypes.func.isRequired,
28 openSettings: PropTypes.func.isRequired,
28 isAppMuted: PropTypes.bool.isRequired, 29 isAppMuted: PropTypes.bool.isRequired,
29 update: PropTypes.func.isRequired, 30 update: PropTypes.func.isRequired,
30 }; 31 };
31 32
32 static defaultProps = { 33 static defaultProps = {
33 services: [], 34 services: [],
34 activeService: '',
35 }; 35 };
36 36
37 static contextTypes = { 37 static contextTypes = {
@@ -45,6 +45,7 @@ export default @observer class Services extends Component {
45 setWebviewReference, 45 setWebviewReference,
46 openWindow, 46 openWindow,
47 reload, 47 reload,
48 openSettings,
48 isAppMuted, 49 isAppMuted,
49 update, 50 update,
50 } = this.props; 51 } = this.props;
@@ -79,6 +80,7 @@ export default @observer class Services extends Component {
79 setWebviewReference={setWebviewReference} 80 setWebviewReference={setWebviewReference}
80 openWindow={openWindow} 81 openWindow={openWindow}
81 reload={() => reload({ serviceId: service.id })} 82 reload={() => reload({ serviceId: service.id })}
83 edit={() => openSettings({ path: `services/edit/${service.id}` })}
82 isAppMuted={isAppMuted} 84 isAppMuted={isAppMuted}
83 enable={() => update({ 85 enable={() => update({
84 serviceId: service.id, 86 serviceId: service.id,
diff --git a/src/components/services/content/WebviewCrashHandler.js b/src/components/services/content/WebviewCrashHandler.js
index 3be1fccf4..42bc3c877 100644
--- a/src/components/services/content/WebviewCrashHandler.js
+++ b/src/components/services/content/WebviewCrashHandler.js
@@ -38,13 +38,18 @@ export default @observer class WebviewCrashHandler extends Component {
38 countdown: 10000, 38 countdown: 10000,
39 } 39 }
40 40
41 countdownInterval = null;
42
43 countdownIntervalTimeout = 1000;
44
45
41 componentDidMount() { 46 componentDidMount() {
42 const { reload } = this.props; 47 const { reload } = this.props;
43 48
44 this.countdownInterval = setInterval(() => { 49 this.countdownInterval = setInterval(() => {
45 this.setState({ 50 this.setState(prevState => ({
46 countdown: this.state.countdown - this.countdownIntervalTimeout, 51 countdown: prevState.countdown - this.countdownIntervalTimeout,
47 }); 52 }));
48 53
49 if (this.state.countdown <= 0) { 54 if (this.state.countdown <= 0) {
50 reload(); 55 reload();
@@ -53,9 +58,6 @@ export default @observer class WebviewCrashHandler extends Component {
53 }, this.countdownIntervalTimeout); 58 }, this.countdownIntervalTimeout);
54 } 59 }
55 60
56 countdownInterval = null;
57 countdownIntervalTimeout = 1000;
58
59 render() { 61 render() {
60 const { name, reload } = this.props; 62 const { name, reload } = this.props;
61 const { intl } = this.context; 63 const { intl } = this.context;
@@ -70,10 +72,12 @@ export default @observer class WebviewCrashHandler extends Component {
70 buttonType="inverted" 72 buttonType="inverted"
71 onClick={() => reload()} 73 onClick={() => reload()}
72 /> 74 />
73 <p className="footnote">{intl.formatMessage(messages.autoReload, { 75 <p className="footnote">
74 name, 76 {intl.formatMessage(messages.autoReload, {
75 seconds: this.state.countdown / 1000, 77 name,
76 })}</p> 78 seconds: this.state.countdown / 1000,
79 })}
80 </p>
77 </div> 81 </div>
78 ); 82 );
79 } 83 }