aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/services/content
diff options
context:
space:
mode:
authorLibravatar Stefan Malzner <stefan@adlk.io>2017-11-07 15:29:31 +0100
committerLibravatar Stefan Malzner <stefan@adlk.io>2017-11-07 15:29:31 +0100
commitdd307e3deb14f1738029ea38f7c1de7893455283 (patch)
tree9e1148d98476f864903900e819b509dfe12a7f14 /src/components/services/content
parentRemove cumbersome style nesting (diff)
downloadferdium-app-dd307e3deb14f1738029ea38f7c1de7893455283.tar.gz
ferdium-app-dd307e3deb14f1738029ea38f7c1de7893455283.tar.zst
ferdium-app-dd307e3deb14f1738029ea38f7c1de7893455283.zip
feature(Service): Add webview crash handler to display a user friendly message
Diffstat (limited to 'src/components/services/content')
-rw-r--r--src/components/services/content/ServiceWebview.js10
-rw-r--r--src/components/services/content/Services.js3
-rw-r--r--src/components/services/content/WebviewCrashHandler.js81
3 files changed, 94 insertions, 0 deletions
diff --git a/src/components/services/content/ServiceWebview.js b/src/components/services/content/ServiceWebview.js
index 3ee3155be..cd59e0a8a 100644
--- a/src/components/services/content/ServiceWebview.js
+++ b/src/components/services/content/ServiceWebview.js
@@ -7,12 +7,14 @@ 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';
10 11
11@observer 12@observer
12export default class ServiceWebview extends Component { 13export default class ServiceWebview extends Component {
13 static propTypes = { 14 static propTypes = {
14 service: PropTypes.instanceOf(ServiceModel).isRequired, 15 service: PropTypes.instanceOf(ServiceModel).isRequired,
15 setWebviewReference: PropTypes.func.isRequired, 16 setWebviewReference: PropTypes.func.isRequired,
17 reload: PropTypes.func.isRequired,
16 }; 18 };
17 19
18 static defaultProps = { 20 static defaultProps = {
@@ -53,6 +55,7 @@ export default class ServiceWebview extends Component {
53 const { 55 const {
54 service, 56 service,
55 setWebviewReference, 57 setWebviewReference,
58 reload,
56 } = this.props; 59 } = this.props;
57 60
58 const webviewClasses = classnames({ 61 const webviewClasses = classnames({
@@ -70,6 +73,13 @@ export default class ServiceWebview extends Component {
70 73
71 return ( 74 return (
72 <div className={webviewClasses}> 75 <div className={webviewClasses}>
76 {service.hasCrashed && (
77 <WebviewCrashHandler
78 name={service.recipe.name}
79 webview={service.webview}
80 reload={reload}
81 />
82 )}
73 <Webview 83 <Webview
74 ref={(element) => { this.webview = element; }} 84 ref={(element) => { this.webview = element; }}
75 85
diff --git a/src/components/services/content/Services.js b/src/components/services/content/Services.js
index 03c68b06f..bad525d22 100644
--- a/src/components/services/content/Services.js
+++ b/src/components/services/content/Services.js
@@ -25,6 +25,7 @@ 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,
28 }; 29 };
29 30
30 static defaultProps = { 31 static defaultProps = {
@@ -42,6 +43,7 @@ export default class Services extends Component {
42 handleIPCMessage, 43 handleIPCMessage,
43 setWebviewReference, 44 setWebviewReference,
44 openWindow, 45 openWindow,
46 reload,
45 } = this.props; 47 } = this.props;
46 const { intl } = this.context; 48 const { intl } = this.context;
47 49
@@ -73,6 +75,7 @@ export default class Services extends Component {
73 handleIPCMessage={handleIPCMessage} 75 handleIPCMessage={handleIPCMessage}
74 setWebviewReference={setWebviewReference} 76 setWebviewReference={setWebviewReference}
75 openWindow={openWindow} 77 openWindow={openWindow}
78 reload={() => reload({ serviceId: service.id })}
76 /> 79 />
77 ))} 80 ))}
78 </div> 81 </div>
diff --git a/src/components/services/content/WebviewCrashHandler.js b/src/components/services/content/WebviewCrashHandler.js
new file mode 100644
index 000000000..24903f3c5
--- /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 ServiceWebview 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__crash-handler">
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}