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/ConnectionLostBanner.js34
-rw-r--r--src/components/services/content/ErrorHandlers/styles.js2
-rw-r--r--src/components/services/content/ServiceRestricted.js78
-rw-r--r--src/components/services/content/ServiceView.js16
-rw-r--r--src/components/services/content/ServiceWebview.js6
-rw-r--r--src/components/services/content/Services.js9
-rw-r--r--src/components/services/content/WebviewCrashHandler.js2
7 files changed, 29 insertions, 118 deletions
diff --git a/src/components/services/content/ConnectionLostBanner.js b/src/components/services/content/ConnectionLostBanner.js
index e54a88faa..ebe863333 100644
--- a/src/components/services/content/ConnectionLostBanner.js
+++ b/src/components/services/content/ConnectionLostBanner.js
@@ -5,9 +5,7 @@ import injectSheet from 'react-jss';
5import { Icon } from '@meetfranz/ui'; 5import { Icon } from '@meetfranz/ui';
6import { intlShape, defineMessages } from 'react-intl'; 6import { intlShape, defineMessages } from 'react-intl';
7 7
8import { 8import { mdiAlert } from '@mdi/js';
9 mdiAlert,
10} from '@mdi/js';
11import { LIVE_API_FERDI_WEBSITE } from '../../../config'; 9import { LIVE_API_FERDI_WEBSITE } from '../../../config';
12// import { Button } from '@meetfranz/forms'; 10// import { Button } from '@meetfranz/forms';
13 11
@@ -26,6 +24,12 @@ const messages = defineMessages({
26 }, 24 },
27}); 25});
28 26
27let buttonTransition = 'none';
28
29if (window && window.matchMedia('(prefers-reduced-motion: no-preference)')) {
30 buttonTransition = 'opacity 0.25s';
31}
32
29const styles = theme => ({ 33const styles = theme => ({
30 root: { 34 root: {
31 background: theme.colorBackground, 35 background: theme.colorBackground,
@@ -47,7 +51,7 @@ const styles = theme => ({
47 opacity: 0.7, 51 opacity: 0.7,
48 }, 52 },
49 button: { 53 button: {
50 transition: 'opacity 0.25s', 54 transition: buttonTransition,
51 color: theme.colorText, 55 color: theme.colorText,
52 border: [1, 'solid', theme.colorText], 56 border: [1, 'solid', theme.colorText],
53 borderRadius: theme.borderRadiusSmall, 57 borderRadius: theme.borderRadiusSmall,
@@ -65,13 +69,14 @@ const styles = theme => ({
65 }, 69 },
66}); 70});
67 71
68@injectSheet(styles) @observer 72@injectSheet(styles)
73@observer
69class ConnectionLostBanner extends Component { 74class ConnectionLostBanner extends Component {
70 static propTypes = { 75 static propTypes = {
71 classes: PropTypes.object.isRequired, 76 classes: PropTypes.object.isRequired,
72 name: PropTypes.string.isRequired, 77 name: PropTypes.string.isRequired,
73 reload: PropTypes.func.isRequired, 78 reload: PropTypes.func.isRequired,
74 } 79 };
75 80
76 static contextTypes = { 81 static contextTypes = {
77 intl: intlShape, 82 intl: intlShape,
@@ -80,20 +85,13 @@ class ConnectionLostBanner extends Component {
80 inputRef = React.createRef(); 85 inputRef = React.createRef();
81 86
82 render() { 87 render() {
83 const { 88 const { classes, name, reload } = this.props;
84 classes,
85 name,
86 reload,
87 } = this.props;
88 89
89 const { intl } = this.context; 90 const { intl } = this.context;
90 91
91 return ( 92 return (
92 <div className={classes.root}> 93 <div className={classes.root}>
93 <Icon 94 <Icon icon={mdiAlert} className={classes.icon} />
94 icon={mdiAlert}
95 className={classes.icon}
96 />
97 <p> 95 <p>
98 {intl.formatMessage(messages.text, { name })} 96 {intl.formatMessage(messages.text, { name })}
99 <br /> 97 <br />
@@ -104,11 +102,7 @@ class ConnectionLostBanner extends Component {
104 {intl.formatMessage(messages.moreInformation)} 102 {intl.formatMessage(messages.moreInformation)}
105 </a> 103 </a>
106 </p> 104 </p>
107 <button 105 <button type="button" className={classes.button} onClick={reload}>
108 type="button"
109 className={classes.button}
110 onClick={reload}
111 >
112 {intl.formatMessage(messages.cta)} 106 {intl.formatMessage(messages.cta)}
113 </button> 107 </button>
114 </div> 108 </div>
diff --git a/src/components/services/content/ErrorHandlers/styles.js b/src/components/services/content/ErrorHandlers/styles.js
index 9e2509ee5..72d62f5e3 100644
--- a/src/components/services/content/ErrorHandlers/styles.js
+++ b/src/components/services/content/ErrorHandlers/styles.js
@@ -1,4 +1,4 @@
1export default theme => ({ 1export default (theme) => ({
2 component: { 2 component: {
3 left: 0, 3 left: 0,
4 position: 'absolute', 4 position: 'absolute',
diff --git a/src/components/services/content/ServiceRestricted.js b/src/components/services/content/ServiceRestricted.js
deleted file mode 100644
index 4b8d926aa..000000000
--- a/src/components/services/content/ServiceRestricted.js
+++ /dev/null
@@ -1,78 +0,0 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl';
5
6import { serviceLimitStore } from '../../../features/serviceLimit';
7import Button from '../../ui/Button';
8import { RESTRICTION_TYPES } from '../../../models/Service';
9
10const messages = defineMessages({
11 headlineServiceLimit: {
12 id: 'service.restrictedHandler.serviceLimit.headline',
13 defaultMessage: '!!!You have reached your service limit.',
14 },
15 textServiceLimit: {
16 id: 'service.restrictedHandler.serviceLimit.text',
17 defaultMessage: '!!!Please upgrade your account to use more than {count} services.',
18 },
19 headlineCustomUrl: {
20 id: 'service.restrictedHandler.customUrl.headline',
21 defaultMessage: '!!!Franz Professional Plan required',
22 },
23 textCustomUrl: {
24 id: 'service.restrictedHandler.customUrl.text',
25 defaultMessage: '!!!Please upgrade to the Franz Professional plan to use custom urls & self hosted services.',
26 },
27 action: {
28 id: 'service.restrictedHandler.action',
29 defaultMessage: '!!!Upgrade Account',
30 },
31});
32
33export default @observer class ServiceRestricted extends Component {
34 static propTypes = {
35 name: PropTypes.string.isRequired,
36 upgrade: PropTypes.func.isRequired,
37 type: PropTypes.number.isRequired,
38 };
39
40 static contextTypes = {
41 intl: intlShape,
42 };
43
44 countdownInterval = null;
45
46 countdownIntervalTimeout = 1000;
47
48 render() {
49 const {
50 name,
51 upgrade,
52 type,
53 } = this.props;
54 const { intl } = this.context;
55
56 return (
57 <div className="services__info-layer">
58 {type === RESTRICTION_TYPES.SERVICE_LIMIT && (
59 <>
60 <h1>{intl.formatMessage(messages.headlineServiceLimit)}</h1>
61 <p>{intl.formatMessage(messages.textServiceLimit, { count: serviceLimitStore.serviceLimit })}</p>
62 </>
63 )}
64 {type === RESTRICTION_TYPES.CUSTOM_URL && (
65 <>
66 <h1>{intl.formatMessage(messages.headlineCustomUrl)}</h1>
67 <p>{intl.formatMessage(messages.textCustomUrl)}</p>
68 </>
69 )}
70 <Button
71 label={intl.formatMessage(messages.action, { name })}
72 buttonType="inverted"
73 onClick={() => upgrade()}
74 />
75 </div>
76 );
77 }
78}
diff --git a/src/components/services/content/ServiceView.js b/src/components/services/content/ServiceView.js
index 17d2db5a0..3fc084ff0 100644
--- a/src/components/services/content/ServiceView.js
+++ b/src/components/services/content/ServiceView.js
@@ -145,19 +145,17 @@ export default @inject('stores', 'actions') @observer class ServiceView extends
145 </> 145 </>
146 ) : ( 146 ) : (
147 <> 147 <>
148 {(!service.isHibernating || service.isHibernationEnabled) ? ( 148 {!service.isHibernating ? (
149 <> 149 <>
150 {showNavBar && ( 150 {showNavBar && (
151 <WebControlsScreen service={service} /> 151 <WebControlsScreen service={service} />
152 )} 152 )}
153 {!service.isHibernating && ( 153 <ServiceWebview
154 <ServiceWebview 154 service={service}
155 service={service} 155 setWebviewReference={setWebviewReference}
156 setWebviewReference={setWebviewReference} 156 detachService={detachService}
157 detachService={detachService} 157 isSpellcheckerEnabled={isSpellcheckerEnabled}
158 isSpellcheckerEnabled={isSpellcheckerEnabled} 158 />
159 />
160 )}
161 </> 159 </>
162 ) : ( 160 ) : (
163 <div> 161 <div>
diff --git a/src/components/services/content/ServiceWebview.js b/src/components/services/content/ServiceWebview.js
index 9e5fed996..3b499a5db 100644
--- a/src/components/services/content/ServiceWebview.js
+++ b/src/components/services/content/ServiceWebview.js
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { observable, reaction } from 'mobx'; 4import { observable, reaction } from 'mobx';
5import ElectronWebView from 'react-electron-web-view'; 5import ElectronWebView from 'react-electron-web-view';
6import path from 'path'; 6import { join } from 'path';
7 7
8import ServiceModel from '../../../models/Service'; 8import ServiceModel from '../../../models/Service';
9 9
@@ -59,7 +59,7 @@ class ServiceWebview extends Component {
59 isSpellcheckerEnabled, 59 isSpellcheckerEnabled,
60 } = this.props; 60 } = this.props;
61 61
62 const preloadScript = path.join(__dirname, '../../../', 'webview', 'recipe.js'); 62 const preloadScript = join(__dirname, '..', '..', '..', 'webview', 'recipe.js');
63 63
64 return ( 64 return (
65 <ElectronWebView 65 <ElectronWebView
@@ -83,7 +83,7 @@ class ServiceWebview extends Component {
83 useragent={service.userAgent} 83 useragent={service.userAgent}
84 disablewebsecurity={service.recipe.disablewebsecurity ? true : undefined} 84 disablewebsecurity={service.recipe.disablewebsecurity ? true : undefined}
85 allowpopups 85 allowpopups
86 webpreferences={`spellcheck=${isSpellcheckerEnabled ? 1 : 0}, contextIsolation=false`} 86 webpreferences={`spellcheck=${isSpellcheckerEnabled ? 1 : 0}`}
87 /> 87 />
88 ); 88 );
89 } 89 }
diff --git a/src/components/services/content/Services.js b/src/components/services/content/Services.js
index caa3cf9aa..bb93ff7d4 100644
--- a/src/components/services/content/Services.js
+++ b/src/components/services/content/Services.js
@@ -30,7 +30,7 @@ const messages = defineMessages({
30 }, 30 },
31 serverInfo: { 31 serverInfo: {
32 id: 'services.serverInfo', 32 id: 'services.serverInfo',
33 defaultMessage: '!!!Optionally, you can change your Ferdi server by clicking the cog in the bottom left corner.', 33 defaultMessage: '!!!Optionally, you can change your Ferdi server by clicking the cog in the bottom left corner. If you are switching over (from one of the hosted servers) to using Ferdi without an account, please be informed that you can export your data from that server and subsequently import it using the Help menu to resurrect all your workspaces and configured services!',
34 }, 34 },
35}); 35});
36 36
@@ -54,7 +54,6 @@ export default @injectSheet(styles) @inject('actions') @observer class Services
54 openSettings: PropTypes.func.isRequired, 54 openSettings: PropTypes.func.isRequired,
55 update: PropTypes.func.isRequired, 55 update: PropTypes.func.isRequired,
56 userHasCompletedSignup: PropTypes.bool.isRequired, 56 userHasCompletedSignup: PropTypes.bool.isRequired,
57 hasActivatedTrial: PropTypes.bool.isRequired,
58 classes: PropTypes.object.isRequired, 57 classes: PropTypes.object.isRequired,
59 actions: PropTypes.object.isRequired, 58 actions: PropTypes.object.isRequired,
60 isSpellcheckerEnabled: PropTypes.bool.isRequired, 59 isSpellcheckerEnabled: PropTypes.bool.isRequired,
@@ -109,7 +108,6 @@ export default @injectSheet(styles) @inject('actions') @observer class Services
109 openSettings, 108 openSettings,
110 update, 109 update,
111 userHasCompletedSignup, 110 userHasCompletedSignup,
112 hasActivatedTrial,
113 classes, 111 classes,
114 isSpellcheckerEnabled, 112 isSpellcheckerEnabled,
115 } = this.props; 113 } = this.props;
@@ -123,7 +121,7 @@ export default @injectSheet(styles) @inject('actions') @observer class Services
123 121
124 return ( 122 return (
125 <div className="services"> 123 <div className="services">
126 {(userHasCompletedSignup || hasActivatedTrial) && ( 124 {userHasCompletedSignup && (
127 <div className={classes.confettiContainer}> 125 <div className={classes.confettiContainer}>
128 <Confetti 126 <Confetti
129 width={window.width} 127 width={window.width}
@@ -169,7 +167,7 @@ export default @injectSheet(styles) @inject('actions') @observer class Services
169 </div> 167 </div>
170 </Appear> 168 </Appear>
171 )} 169 )}
172 {services.filter(service => !service.isTodosService).map(service => ( 170 {services.filter((service) => !service.isTodosService).map((service) => (
173 <ServiceView 171 <ServiceView
174 key={service.id} 172 key={service.id}
175 service={service} 173 service={service}
@@ -186,7 +184,6 @@ export default @injectSheet(styles) @inject('actions') @observer class Services
186 }, 184 },
187 redirect: false, 185 redirect: false,
188 })} 186 })}
189 upgrade={() => openSettings({ path: 'user' })}
190 isSpellcheckerEnabled={isSpellcheckerEnabled} 187 isSpellcheckerEnabled={isSpellcheckerEnabled}
191 /> 188 />
192 ))} 189 ))}
diff --git a/src/components/services/content/WebviewCrashHandler.js b/src/components/services/content/WebviewCrashHandler.js
index b62940c06..10ff0bbbb 100644
--- a/src/components/services/content/WebviewCrashHandler.js
+++ b/src/components/services/content/WebviewCrashHandler.js
@@ -47,7 +47,7 @@ export default @observer class WebviewCrashHandler extends Component {
47 const { reload } = this.props; 47 const { reload } = this.props;
48 48
49 this.countdownInterval = setInterval(() => { 49 this.countdownInterval = setInterval(() => {
50 this.setState(prevState => ({ 50 this.setState((prevState) => ({
51 countdown: prevState.countdown - this.countdownIntervalTimeout, 51 countdown: prevState.countdown - this.countdownIntervalTimeout,
52 })); 52 }));
53 53