aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/services/content
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/services/content')
-rw-r--r--src/components/services/content/ServiceDisabled.js48
-rw-r--r--src/components/services/content/ServiceWebview.js59
-rw-r--r--src/components/services/content/Services.js15
-rw-r--r--src/components/services/content/WebviewCrashHandler.js81
4 files changed, 183 insertions, 20 deletions
diff --git a/src/components/services/content/ServiceDisabled.js b/src/components/services/content/ServiceDisabled.js
new file mode 100644
index 000000000..b5af3743d
--- /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__info-layer">
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 3ee3155be..faa356d3d 100644
--- a/src/components/services/content/ServiceWebview.js
+++ b/src/components/services/content/ServiceWebview.js
@@ -7,12 +7,17 @@ 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 WebviewCrashHandler from './WebviewCrashHandler';
11import ServiceDisabled from './ServiceDisabled';
10 12
11@observer 13@observer
12export default class ServiceWebview extends Component { 14export default class ServiceWebview extends Component {
13 static propTypes = { 15 static propTypes = {
14 service: PropTypes.instanceOf(ServiceModel).isRequired, 16 service: PropTypes.instanceOf(ServiceModel).isRequired,
15 setWebviewReference: PropTypes.func.isRequired, 17 setWebviewReference: PropTypes.func.isRequired,
18 reload: PropTypes.func.isRequired,
19 isAppMuted: PropTypes.bool.isRequired,
20 enable: PropTypes.func.isRequired,
16 }; 21 };
17 22
18 static defaultProps = { 23 static defaultProps = {
@@ -53,6 +58,9 @@ export default class ServiceWebview extends Component {
53 const { 58 const {
54 service, 59 service,
55 setWebviewReference, 60 setWebviewReference,
61 reload,
62 isAppMuted,
63 enable,
56 } = this.props; 64 } = this.props;
57 65
58 const webviewClasses = classnames({ 66 const webviewClasses = classnames({
@@ -70,26 +78,37 @@ export default class ServiceWebview extends Component {
70 78
71 return ( 79 return (
72 <div className={webviewClasses}> 80 <div className={webviewClasses}>
73 <Webview 81 {service.hasCrashed && (
74 ref={(element) => { this.webview = element; }} 82 <WebviewCrashHandler
75 83 name={service.recipe.name}
76 autosize 84 webview={service.webview}
77 src={service.url} 85 reload={reload}
78 preload="./webview/plugin.js" 86 />
79 partition={`persist:service-${service.id}`} 87 )}
80 88 {!service.isEnabled ? (
81 onDidAttach={() => setWebviewReference({ 89 <ServiceDisabled
82 serviceId: service.id, 90 name={service.recipe.name}
83 webview: this.webview.view, 91 webview={service.webview}
84 })} 92 enable={enable}
85 93 />
86 onUpdateTargetUrl={this.updateTargetUrl} 94 ) : (
87 95 <Webview
88 useragent={service.userAgent} 96 ref={(element) => { this.webview = element; }}
89 97 autosize
90 disablewebsecurity 98 src={service.url}
91 allowpopups 99 preload="./webview/plugin.js"
92 /> 100 partition={`persist:service-${service.id}`}
101 onDidAttach={() => setWebviewReference({
102 serviceId: service.id,
103 webview: this.webview.view,
104 })}
105 onUpdateTargetUrl={this.updateTargetUrl}
106 useragent={service.userAgent}
107 muted={isAppMuted || service.isMuted}
108 disablewebsecurity
109 allowpopups
110 />
111 )}
93 {statusBar} 112 {statusBar}
94 </div> 113 </div>
95 ); 114 );
diff --git a/src/components/services/content/Services.js b/src/components/services/content/Services.js
index 03c68b06f..b1322afc2 100644
--- a/src/components/services/content/Services.js
+++ b/src/components/services/content/Services.js
@@ -25,6 +25,9 @@ export default class Services extends Component {
25 setWebviewReference: PropTypes.func.isRequired, 25 setWebviewReference: PropTypes.func.isRequired,
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,
29 isAppMuted: PropTypes.bool.isRequired,
30 update: PropTypes.func.isRequired,
28 }; 31 };
29 32
30 static defaultProps = { 33 static defaultProps = {
@@ -42,6 +45,9 @@ export default class Services extends Component {
42 handleIPCMessage, 45 handleIPCMessage,
43 setWebviewReference, 46 setWebviewReference,
44 openWindow, 47 openWindow,
48 reload,
49 isAppMuted,
50 update,
45 } = this.props; 51 } = this.props;
46 const { intl } = this.context; 52 const { intl } = this.context;
47 53
@@ -73,6 +79,15 @@ export default class Services extends Component {
73 handleIPCMessage={handleIPCMessage} 79 handleIPCMessage={handleIPCMessage}
74 setWebviewReference={setWebviewReference} 80 setWebviewReference={setWebviewReference}
75 openWindow={openWindow} 81 openWindow={openWindow}
82 reload={() => reload({ serviceId: service.id })}
83 isAppMuted={isAppMuted}
84 enable={() => update({
85 serviceId: service.id,
86 serviceData: {
87 isEnabled: true,
88 },
89 redirect: false,
90 })}
76 /> 91 />
77 ))} 92 ))}
78 </div> 93 </div>
diff --git a/src/components/services/content/WebviewCrashHandler.js b/src/components/services/content/WebviewCrashHandler.js
new file mode 100644
index 000000000..d3e6951f3
--- /dev/null
+++ b/src/components/services/content/WebviewCrashHandler.js
@@ -0,0 +1,81 @@
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.crashHandler.headline',
11 defaultMessage: '!!!Oh no!',
12 },
13 text: {
14 id: 'service.crashHandler.text',
15 defaultMessage: '!!!{name} has caused an error.',
16 },
17 action: {
18 id: 'service.crashHandler.action',
19 defaultMessage: '!!!Reload {name}',
20 },
21 autoReload: {
22 id: 'service.crashHandler.autoReload',
23 defaultMessage: '!!!Trying to automatically restore {name} in {seconds} seconds',
24 },
25});
26
27@observer
28export default class WebviewCrashHandler extends Component {
29 static propTypes = {
30 name: PropTypes.string.isRequired,
31 reload: PropTypes.func.isRequired,
32 };
33
34 static contextTypes = {
35 intl: intlShape,
36 };
37
38 state = {
39 countdown: 10000,
40 }
41
42 componentDidMount() {
43 const { reload } = this.props;
44
45 this.countdownInterval = setInterval(() => {
46 this.setState({
47 countdown: this.state.countdown - this.countdownIntervalTimeout,
48 });
49
50 if (this.state.countdown <= 0) {
51 reload();
52 clearInterval(this.countdownInterval);
53 }
54 }, this.countdownIntervalTimeout);
55 }
56
57 countdownInterval = null;
58 countdownIntervalTimeout = 1000;
59
60 render() {
61 const { name, reload } = this.props;
62 const { intl } = this.context;
63
64 return (
65 <div className="services__info-layer">
66 <h1>{intl.formatMessage(messages.headline)}</h1>
67 <p>{intl.formatMessage(messages.text, { name })}</p>
68 <Button
69 // label={`Reload ${name}`}
70 label={intl.formatMessage(messages.action, { name })}
71 buttonType="inverted"
72 onClick={() => reload()}
73 />
74 <p className="footnote">{intl.formatMessage(messages.autoReload, {
75 name,
76 seconds: this.state.countdown / 1000,
77 })}</p>
78 </div>
79 );
80 }
81}