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, 102 insertions, 18 deletions
diff --git a/src/components/services/content/ServiceView.js b/src/components/services/content/ServiceView.js
index 3b09518c5..273653ea2 100644
--- a/src/components/services/content/ServiceView.js
+++ b/src/components/services/content/ServiceView.js
@@ -1,7 +1,7 @@
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';
6 6
7import ServiceModel from '../../../models/Service'; 7import ServiceModel from '../../../models/Service';
@@ -10,12 +10,12 @@ import WebviewLoader from '../../ui/WebviewLoader';
10import WebviewCrashHandler from './WebviewCrashHandler'; 10import WebviewCrashHandler from './WebviewCrashHandler';
11import WebviewErrorHandler from './ErrorHandlers/WebviewErrorHandler'; 11import WebviewErrorHandler from './ErrorHandlers/WebviewErrorHandler';
12import ServiceDisabled from './ServiceDisabled'; 12import ServiceDisabled from './ServiceDisabled';
13import ServiceRestricted from './ServiceRestricted';
14import ServiceWebview from './ServiceWebview'; 13import ServiceWebview from './ServiceWebview';
14import SettingsStore from '../../../stores/SettingsStore';
15import WebControlsScreen from '../../../features/webControls/containers/WebControlsScreen'; 15import WebControlsScreen from '../../../features/webControls/containers/WebControlsScreen';
16import { CUSTOM_WEBSITE_ID } from '../../../features/webControls/constants'; 16import { CUSTOM_WEBSITE_ID } from '../../../features/webControls/constants';
17 17
18export default @observer class ServiceView extends Component { 18export default @observer @inject('stores') class ServiceView extends Component {
19 static propTypes = { 19 static propTypes = {
20 service: PropTypes.instanceOf(ServiceModel).isRequired, 20 service: PropTypes.instanceOf(ServiceModel).isRequired,
21 setWebviewReference: PropTypes.func.isRequired, 21 setWebviewReference: PropTypes.func.isRequired,
@@ -24,7 +24,9 @@ export default @observer class ServiceView extends Component {
24 edit: PropTypes.func.isRequired, 24 edit: PropTypes.func.isRequired,
25 enable: PropTypes.func.isRequired, 25 enable: PropTypes.func.isRequired,
26 isActive: PropTypes.bool, 26 isActive: PropTypes.bool,
27 upgrade: PropTypes.func.isRequired, 27 stores: PropTypes.shape({
28 settings: PropTypes.instanceOf(SettingsStore).isRequired,
29 }).isRequired,
28 }; 30 };
29 31
30 static defaultProps = { 32 static defaultProps = {
@@ -35,12 +37,20 @@ export default @observer class ServiceView extends Component {
35 forceRepaint: false, 37 forceRepaint: false,
36 targetUrl: '', 38 targetUrl: '',
37 statusBarVisible: false, 39 statusBarVisible: false,
40 hibernate: false,
41 hibernationTimer: null,
38 }; 42 };
39 43
40 autorunDisposer = null; 44 autorunDisposer = null;
41 45
42 forceRepaintTimeout = null; 46 forceRepaintTimeout = null;
43 47
48 constructor(props) {
49 super(props);
50
51 this.startHibernationTimer = this.startHibernationTimer.bind(this);
52 }
53
44 componentDidMount() { 54 componentDidMount() {
45 this.autorunDisposer = autorun(() => { 55 this.autorunDisposer = autorun(() => {
46 if (this.props.service.isActive) { 56 if (this.props.service.isActive) {
@@ -50,6 +60,31 @@ export default @observer class ServiceView extends Component {
50 }, 100); 60 }, 100);
51 } 61 }
52 }); 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 }
53 } 88 }
54 89
55 componentWillUnmount() { 90 componentWillUnmount() {
@@ -68,6 +103,20 @@ export default @observer class ServiceView extends Component {
68 }); 103 });
69 }; 104 };
70 105
106 startHibernationTimer() {
107 const timerDuration = (Number(this.props.stores.settings.all.app.hibernationStrategy) || 300) * 1000;
108
109 const hibernationTimer = setTimeout(() => {
110 this.setState({
111 hibernate: true,
112 });
113 }, timerDuration);
114
115 this.setState({
116 hibernationTimer,
117 });
118 }
119
71 render() { 120 render() {
72 const { 121 const {
73 detachService, 122 detachService,
@@ -76,7 +125,6 @@ export default @observer class ServiceView extends Component {
76 reload, 125 reload,
77 edit, 126 edit,
78 enable, 127 enable,
79 upgrade,
80 } = this.props; 128 } = this.props;
81 129
82 const webviewClasses = classnames({ 130 const webviewClasses = classnames({
@@ -132,13 +180,10 @@ export default @observer class ServiceView extends Component {
132 </Fragment> 180 </Fragment>
133 ) : ( 181 ) : (
134 <> 182 <>
135 {service.isServiceAccessRestricted ? ( 183 {service.recipe.id === 'franz-custom-website' && (
136 <ServiceRestricted 184 <WebControlsScreen service={service} />
137 name={service.recipe.name} 185 )}
138 upgrade={upgrade} 186 {!this.state.hibernate ? (
139 type={service.restrictionType}
140 />
141 ) : (
142 <> 187 <>
143 {service.recipe.id === CUSTOM_WEBSITE_ID && ( 188 {service.recipe.id === CUSTOM_WEBSITE_ID && (
144 <WebControlsScreen service={service} /> 189 <WebControlsScreen service={service} />
@@ -149,6 +194,12 @@ export default @observer class ServiceView extends Component {
149 detachService={detachService} 194 detachService={detachService}
150 /> 195 />
151 </> 196 </>
197 ) : (
198 <div>
199 <span role="img" aria-label="Sleeping Emoji">😴</span>
200 {' '}
201 This service is currently hibernating. If this page doesn&#x27;t close soon, please try reloading Ferdi.
202 </div>
152 )} 203 )}
153 </> 204 </>
154 )} 205 )}
diff --git a/src/components/services/content/ServiceWebview.js b/src/components/services/content/ServiceWebview.js
index 4bab4a964..e6ebb6afb 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 b6291666b..edff29ae8 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
@@ -94,6 +102,7 @@ export default @observer @injectSheet(styles) class Services extends Component {
94 } = this.state; 102 } = this.state;
95 103
96 const { intl } = this.context; 104 const { intl } = this.context;
105 const isLoggedIn = Boolean(localStorage.getItem('authToken'));
97 106
98 return ( 107 return (
99 <div className="services"> 108 <div className="services">
@@ -112,14 +121,20 @@ export default @observer @injectSheet(styles) class Services extends Component {
112 transitionName="slideUp" 121 transitionName="slideUp"
113 > 122 >
114 <div className="services__no-service"> 123 <div className="services__no-service">
115 <img src="./assets/images/logo.svg" alt="" /> 124 <img src="./assets/images/logo.svg" alt="Logo" style={{ maxHeight: '50vh' }} />
116 <h1>{intl.formatMessage(messages.welcome)}</h1> 125 <h1>{intl.formatMessage(messages.welcome)}</h1>
126 { !isLoggedIn && (
127 <>
128 <p>{intl.formatMessage(messages.login)}</p>
129 <p>{intl.formatMessage(messages.serverInfo)}</p>
130 </>
131 ) }
117 <Appear 132 <Appear
118 timeout={300} 133 timeout={300}
119 transitionName="slideUp" 134 transitionName="slideUp"
120 > 135 >
121 <Link to="/settings/recipes" className="button"> 136 <Link to={isLoggedIn ? '/settings/services' : '/auth/welcome'} className="button">
122 {intl.formatMessage(messages.getStarted)} 137 { isLoggedIn ? intl.formatMessage(messages.getStarted) : 'Login' }
123 </Link> 138 </Link>
124 </Appear> 139 </Appear>
125 </div> 140 </div>