aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/services
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/services')
-rw-r--r--src/components/services/content/ServiceView.js77
-rw-r--r--src/components/services/content/ServiceWebview.js20
-rw-r--r--src/components/services/content/Services.js23
3 files changed, 104 insertions, 16 deletions
diff --git a/src/components/services/content/ServiceView.js b/src/components/services/content/ServiceView.js
index e8df58a1e..74d8af0bc 100644
--- a/src/components/services/content/ServiceView.js
+++ b/src/components/services/content/ServiceView.js
@@ -1,8 +1,9 @@
1import React, { Component, Fragment } from 'react'; 1import React, { Component, Fragment } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { autorun } from 'mobx'; 3import { autorun, reaction } from 'mobx';
4import { observer } from 'mobx-react'; 4import { observer, inject } from 'mobx-react';
5import classnames from 'classnames'; 5import classnames from 'classnames';
6import ms from 'ms';
6 7
7import ServiceModel from '../../../models/Service'; 8import ServiceModel from '../../../models/Service';
8import StatusBarTargetUrl from '../../ui/StatusBarTargetUrl'; 9import StatusBarTargetUrl from '../../ui/StatusBarTargetUrl';
@@ -10,11 +11,11 @@ import WebviewLoader from '../../ui/WebviewLoader';
10import WebviewCrashHandler from './WebviewCrashHandler'; 11import WebviewCrashHandler from './WebviewCrashHandler';
11import WebviewErrorHandler from './ErrorHandlers/WebviewErrorHandler'; 12import WebviewErrorHandler from './ErrorHandlers/WebviewErrorHandler';
12import ServiceDisabled from './ServiceDisabled'; 13import ServiceDisabled from './ServiceDisabled';
13import ServiceRestricted from './ServiceRestricted';
14import ServiceWebview from './ServiceWebview'; 14import ServiceWebview from './ServiceWebview';
15import SettingsStore from '../../../stores/SettingsStore';
15import WebControlsScreen from '../../../features/webControls/containers/WebControlsScreen'; 16import WebControlsScreen from '../../../features/webControls/containers/WebControlsScreen';
16 17
17export default @observer class ServiceView extends Component { 18export default @observer @inject('stores') class ServiceView extends Component {
18 static propTypes = { 19 static propTypes = {
19 service: PropTypes.instanceOf(ServiceModel).isRequired, 20 service: PropTypes.instanceOf(ServiceModel).isRequired,
20 setWebviewReference: PropTypes.func.isRequired, 21 setWebviewReference: PropTypes.func.isRequired,
@@ -23,7 +24,9 @@ export default @observer class ServiceView extends Component {
23 edit: PropTypes.func.isRequired, 24 edit: PropTypes.func.isRequired,
24 enable: PropTypes.func.isRequired, 25 enable: PropTypes.func.isRequired,
25 isActive: PropTypes.bool, 26 isActive: PropTypes.bool,
26 upgrade: PropTypes.func.isRequired, 27 stores: PropTypes.shape({
28 settings: PropTypes.instanceOf(SettingsStore).isRequired,
29 }).isRequired,
27 }; 30 };
28 31
29 static defaultProps = { 32 static defaultProps = {
@@ -34,12 +37,20 @@ export default @observer class ServiceView extends Component {
34 forceRepaint: false, 37 forceRepaint: false,
35 targetUrl: '', 38 targetUrl: '',
36 statusBarVisible: false, 39 statusBarVisible: false,
40 hibernate: false,
41 hibernationTimer: null,
37 }; 42 };
38 43
39 autorunDisposer = null; 44 autorunDisposer = null;
40 45
41 forceRepaintTimeout = null; 46 forceRepaintTimeout = null;
42 47
48 constructor(props) {
49 super(props);
50
51 this.startHibernationTimer = this.startHibernationTimer.bind(this);
52 }
53
43 componentDidMount() { 54 componentDidMount() {
44 this.autorunDisposer = autorun(() => { 55 this.autorunDisposer = autorun(() => {
45 if (this.props.service.isActive) { 56 if (this.props.service.isActive) {
@@ -49,6 +60,31 @@ export default @observer class ServiceView extends Component {
49 }, 100); 60 }, 100);
50 } 61 }
51 }); 62 });
63
64 reaction(
65 () => this.props.service.isActive,
66 () => {
67 if (!this.props.service.isActive && this.props.stores.settings.all.app.hibernate) {
68 // Service is inactive - start hibernation countdown
69 this.startHibernationTimer();
70 } else {
71 if (this.state.hibernationTimer) {
72 // Service is active but we have an active hibernation timer: Clear timeout
73 clearTimeout(this.state.hibernationTimer);
74 }
75
76 // Service is active, wake up service from hibernation
77 this.setState({
78 hibernate: false,
79 });
80 }
81 },
82 );
83
84 // Start hibernation counter if we are in background
85 if (!this.props.service.isActive && this.props.stores.settings.all.app.hibernate) {
86 this.startHibernationTimer();
87 }
52 } 88 }
53 89
54 componentWillUnmount() { 90 componentWillUnmount() {
@@ -67,6 +103,18 @@ export default @observer class ServiceView extends Component {
67 }); 103 });
68 }; 104 };
69 105
106 startHibernationTimer() {
107 const hibernationTimer = setTimeout(() => {
108 this.setState({
109 hibernate: true,
110 });
111 }, ms('5m'));
112
113 this.setState({
114 hibernationTimer,
115 });
116 }
117
70 render() { 118 render() {
71 const { 119 const {
72 detachService, 120 detachService,
@@ -75,7 +123,6 @@ export default @observer class ServiceView extends Component {
75 reload, 123 reload,
76 edit, 124 edit,
77 enable, 125 enable,
78 upgrade,
79 } = this.props; 126 } = this.props;
80 127
81 const webviewClasses = classnames({ 128 const webviewClasses = classnames({
@@ -142,11 +189,19 @@ export default @observer class ServiceView extends Component {
142 {service.recipe.id === 'franz-custom-website' && ( 189 {service.recipe.id === 'franz-custom-website' && (
143 <WebControlsScreen service={service} /> 190 <WebControlsScreen service={service} />
144 )} 191 )}
145 <ServiceWebview 192 {!this.state.hibernate ? (
146 service={service} 193 <ServiceWebview
147 setWebviewReference={setWebviewReference} 194 service={service}
148 detachService={detachService} 195 setWebviewReference={setWebviewReference}
149 /> 196 detachService={detachService}
197 />
198 ) : (
199 <div>
200 <span role="img" aria-label="Sleeping Emoji">😴</span>
201 {' '}
202 This service is currently hibernating. If this page doesn&#x27;t close soon, please try reloading Ferdi.
203 </div>
204 )}
150 </> 205 </>
151 )} 206 )}
152 </> 207 </>
diff --git a/src/components/services/content/ServiceWebview.js b/src/components/services/content/ServiceWebview.js
index 07bd17d9c..03d6d5bcc 100644
--- a/src/components/services/content/ServiceWebview.js
+++ b/src/components/services/content/ServiceWebview.js
@@ -1,10 +1,13 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { observable, reaction } from 'mobx';
4import ElectronWebView from 'react-electron-web-view'; 5import ElectronWebView from 'react-electron-web-view';
5 6
6import ServiceModel from '../../../models/Service'; 7import ServiceModel from '../../../models/Service';
7 8
9const debug = require('debug')('Ferdi:Services');
10
8@observer 11@observer
9class ServiceWebview extends Component { 12class ServiceWebview extends Component {
10 static propTypes = { 13 static propTypes = {
@@ -13,7 +16,22 @@ class ServiceWebview extends Component {
13 detachService: PropTypes.func.isRequired, 16 detachService: PropTypes.func.isRequired,
14 }; 17 };
15 18
16 webview = null; 19 @observable webview = null;
20
21 constructor(props) {
22 super(props);
23
24 reaction(
25 () => this.webview,
26 () => {
27 if (this.webview && this.webview.view) {
28 this.webview.view.addEventListener('console-message', (e) => {
29 debug('Service logged a message:', e.message);
30 });
31 }
32 },
33 );
34 }
17 35
18 componentWillUnmount() { 36 componentWillUnmount() {
19 const { service, detachService } = this.props; 37 const { service, detachService } = this.props;
diff --git a/src/components/services/content/Services.js b/src/components/services/content/Services.js
index 73c27bfb6..1afbaabc4 100644
--- a/src/components/services/content/Services.js
+++ b/src/components/services/content/Services.js
@@ -13,12 +13,20 @@ import Appear from '../../ui/effects/Appear';
13const messages = defineMessages({ 13const messages = defineMessages({
14 welcome: { 14 welcome: {
15 id: 'services.welcome', 15 id: 'services.welcome',
16 defaultMessage: '!!!Welcome to Franz', 16 defaultMessage: '!!!Welcome to Ferdi',
17 }, 17 },
18 getStarted: { 18 getStarted: {
19 id: 'services.getStarted', 19 id: 'services.getStarted',
20 defaultMessage: '!!!Get started', 20 defaultMessage: '!!!Get started',
21 }, 21 },
22 login: {
23 id: 'services.login',
24 defaultMessage: '!!!Please login to use Ferdi.',
25 },
26 serverInfo: {
27 id: 'services.serverInfo',
28 defaultMessage: '!!!Optionally, you can change your Ferdi server by clicking the cog in the bottom left corner.',
29 },
22}); 30});
23 31
24 32
@@ -86,6 +94,7 @@ export default @observer @injectSheet(styles) class Services extends Component {
86 } = this.state; 94 } = this.state;
87 95
88 const { intl } = this.context; 96 const { intl } = this.context;
97 const isLoggedIn = Boolean(localStorage.getItem('authToken'));
89 98
90 return ( 99 return (
91 <div className="services"> 100 <div className="services">
@@ -104,14 +113,20 @@ export default @observer @injectSheet(styles) class Services extends Component {
104 transitionName="slideUp" 113 transitionName="slideUp"
105 > 114 >
106 <div className="services__no-service"> 115 <div className="services__no-service">
107 <img src="./assets/images/logo.svg" alt="" /> 116 <img src="./assets/images/logo.svg" alt="Logo" style={{ maxHeight: '50vh' }} />
108 <h1>{intl.formatMessage(messages.welcome)}</h1> 117 <h1>{intl.formatMessage(messages.welcome)}</h1>
118 { !isLoggedIn && (
119 <>
120 <p>{intl.formatMessage(messages.login)}</p>
121 <p>{intl.formatMessage(messages.serverInfo)}</p>
122 </>
123 ) }
109 <Appear 124 <Appear
110 timeout={300} 125 timeout={300}
111 transitionName="slideUp" 126 transitionName="slideUp"
112 > 127 >
113 <Link to="/settings/recipes" className="button"> 128 <Link to={isLoggedIn ? '/settings/services' : '/auth/welcome'} className="button">
114 {intl.formatMessage(messages.getStarted)} 129 { isLoggedIn ? intl.formatMessage(messages.getStarted) : 'Login' }
115 </Link> 130 </Link>
116 </Appear> 131 </Appear>
117 </div> 132 </div>