diff options
Diffstat (limited to 'src/components/services/content')
-rw-r--r-- | src/components/services/content/ServiceDisabled.js | 48 | ||||
-rw-r--r-- | src/components/services/content/ServiceWebview.js | 59 | ||||
-rw-r--r-- | src/components/services/content/Services.js | 15 | ||||
-rw-r--r-- | src/components/services/content/WebviewCrashHandler.js | 81 |
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 @@ | |||
1 | import React, { Component } from 'react'; | ||
2 | import PropTypes from 'prop-types'; | ||
3 | import { observer } from 'mobx-react'; | ||
4 | import { defineMessages, intlShape } from 'react-intl'; | ||
5 | |||
6 | import Button from '../../ui/Button'; | ||
7 | |||
8 | const 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 | ||
20 | export 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 | ||
8 | import ServiceModel from '../../../models/Service'; | 8 | import ServiceModel from '../../../models/Service'; |
9 | import StatusBarTargetUrl from '../../ui/StatusBarTargetUrl'; | 9 | import StatusBarTargetUrl from '../../ui/StatusBarTargetUrl'; |
10 | import WebviewCrashHandler from './WebviewCrashHandler'; | ||
11 | import ServiceDisabled from './ServiceDisabled'; | ||
10 | 12 | ||
11 | @observer | 13 | @observer |
12 | export default class ServiceWebview extends Component { | 14 | export 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 @@ | |||
1 | import React, { Component } from 'react'; | ||
2 | import PropTypes from 'prop-types'; | ||
3 | import { observer } from 'mobx-react'; | ||
4 | import { defineMessages, intlShape } from 'react-intl'; | ||
5 | |||
6 | import Button from '../../ui/Button'; | ||
7 | |||
8 | const 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 | ||
28 | export 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 | } | ||