aboutsummaryrefslogtreecommitdiffstats
path: root/src/containers
diff options
context:
space:
mode:
Diffstat (limited to 'src/containers')
-rw-r--r--src/containers/auth/PricingScreen.js83
-rw-r--r--src/containers/auth/SetupAssistantScreen.js35
-rw-r--r--src/containers/auth/SignupScreen.js13
-rw-r--r--src/containers/auth/WelcomeScreen.js2
-rw-r--r--src/containers/layout/AppLayoutContainer.js15
-rw-r--r--src/containers/settings/AccountScreen.js25
-rw-r--r--src/containers/settings/EditServiceScreen.js10
-rw-r--r--src/containers/settings/EditSettingsScreen.js41
-rw-r--r--src/containers/settings/EditUserScreen.js2
-rw-r--r--src/containers/settings/RecipesScreen.js38
-rw-r--r--src/containers/settings/TeamScreen.js3
-rw-r--r--src/containers/subscription/SubscriptionFormScreen.js99
-rw-r--r--src/containers/subscription/SubscriptionPopupScreen.js41
13 files changed, 76 insertions, 331 deletions
diff --git a/src/containers/auth/PricingScreen.js b/src/containers/auth/PricingScreen.js
deleted file mode 100644
index 97bf1f6be..000000000
--- a/src/containers/auth/PricingScreen.js
+++ /dev/null
@@ -1,83 +0,0 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import { inject, observer } from 'mobx-react';
4import { RouterStore } from 'mobx-react-router';
5
6import Pricing from '../../components/auth/Pricing';
7import UserStore from '../../stores/UserStore';
8
9import { globalError as globalErrorPropType } from '../../prop-types';
10import FeaturesStore from '../../stores/FeaturesStore';
11
12export default @inject('stores', 'actions') @observer class PricingScreen extends Component {
13 static propTypes = {
14 error: globalErrorPropType.isRequired,
15 };
16
17 async submit() {
18 const {
19 actions,
20 stores,
21 } = this.props;
22
23 const { activateTrialRequest } = stores.user;
24 const { defaultTrialPlan, canSkipTrial } = stores.features.anonymousFeatures;
25
26 if (!canSkipTrial) {
27 stores.router.push('/');
28 stores.user.hasCompletedSignup = true;
29 } else {
30 actions.user.activateTrial({ planId: defaultTrialPlan });
31 await activateTrialRequest._promise;
32
33 if (!activateTrialRequest.isError) {
34 stores.router.push('/');
35 stores.user.hasCompletedSignup = true;
36 }
37 }
38 }
39
40 render() {
41 const {
42 error,
43 stores,
44 } = this.props;
45
46 const { getUserInfoRequest, activateTrialRequest, data } = stores.user;
47 const { featuresRequest, features } = stores.features;
48
49 const { pricingConfig } = features;
50
51 let currency = '$';
52 let price = 5.99;
53 if (pricingConfig) {
54 ({ currency } = pricingConfig);
55 ({ price } = pricingConfig.plans.pro.yearly);
56 }
57
58 return (
59 <Pricing
60 onSubmit={this.submit.bind(this)}
61 isLoadingRequiredData={(getUserInfoRequest.isExecuting || !getUserInfoRequest.wasExecuted) || (featuresRequest.isExecuting || !featuresRequest.wasExecuted)}
62 isActivatingTrial={activateTrialRequest.isExecuting}
63 trialActivationError={activateTrialRequest.isError}
64 canSkipTrial={features.canSkipTrial}
65 error={error}
66 currency={currency}
67 price={price}
68 name={data.firstname}
69 />
70 );
71 }
72}
73
74PricingScreen.wrappedComponent.propTypes = {
75 actions: PropTypes.shape({
76 user: PropTypes.instanceOf(UserStore).isRequired,
77 }).isRequired,
78 stores: PropTypes.shape({
79 user: PropTypes.instanceOf(UserStore).isRequired,
80 router: PropTypes.instanceOf(RouterStore).isRequired,
81 features: PropTypes.instanceOf(FeaturesStore).isRequired,
82 }).isRequired,
83};
diff --git a/src/containers/auth/SetupAssistantScreen.js b/src/containers/auth/SetupAssistantScreen.js
index 2a8f2c010..d7036969a 100644
--- a/src/containers/auth/SetupAssistantScreen.js
+++ b/src/containers/auth/SetupAssistantScreen.js
@@ -4,14 +4,28 @@ import PropTypes from 'prop-types';
4import { inject, observer } from 'mobx-react'; 4import { inject, observer } from 'mobx-react';
5 5
6import { RouterStore } from 'mobx-react-router'; 6import { RouterStore } from 'mobx-react-router';
7import { DEFAULT_TODO_RECIPE_ID, DEFAULT_TODO_SERVICE_NAME } from '../../config'; 7import {
8 DEFAULT_TODO_RECIPE_ID,
9 DEFAULT_TODO_SERVICE_NAME,
10} from '../../config';
8import { sleep } from '../../helpers/async-helpers'; 11import { sleep } from '../../helpers/async-helpers';
9import SetupAssistant from '../../components/auth/SetupAssistant'; 12import SetupAssistant from '../../components/auth/SetupAssistant';
10import ServicesStore from '../../stores/ServicesStore'; 13import ServicesStore from '../../stores/ServicesStore';
11import RecipesStore from '../../stores/RecipesStore'; 14import RecipesStore from '../../stores/RecipesStore';
12import UserStore from '../../stores/UserStore'; 15import UserStore from '../../stores/UserStore';
13 16
14export default @inject('stores', 'actions') @observer class SetupAssistantScreen extends Component { 17export default
18@inject('stores', 'actions')
19@observer
20class SetupAssistantScreen extends Component {
21 constructor(props) {
22 super(props);
23 this.state = {
24 isSettingUpServices: false,
25 };
26 }
27
28 // TODO: Why are these hardcoded here? Do they need to conform to specific services in the packaged recipes? If so, its more important to fix this
15 services = { 29 services = {
16 whatsapp: { 30 whatsapp: {
17 name: 'WhatsApp', 31 name: 'WhatsApp',
@@ -49,21 +63,18 @@ export default @inject('stores', 'actions') @observer class SetupAssistantScreen
49 name: 'LinkedIn', 63 name: 'LinkedIn',
50 hasTeamId: false, 64 hasTeamId: false,
51 }, 65 },
52 } 66 };
53
54 state = {
55 isSettingUpServices: false,
56 }
57 67
58 async setupServices(serviceConfig) { 68 async setupServices(serviceConfig) {
59 const { stores: { services, router, user } } = this.props; 69 const {
60 console.log(serviceConfig); 70 stores: { services },
71 } = this.props;
61 72
62 this.setState({ 73 this.setState({
63 isSettingUpServices: true, 74 isSettingUpServices: true,
64 }); 75 });
65 76
66 // The store requests are not build for paralell requests so we need to finish one request after another 77 // The store requests are not build for parallel requests so we need to finish one request after another
67 for (const config of serviceConfig) { 78 for (const config of serviceConfig) {
68 const serviceData = { 79 const serviceData = {
69 name: this.services[config.id].name, 80 name: this.services[config.id].name,
@@ -96,10 +107,6 @@ export default @inject('stores', 'actions') @observer class SetupAssistantScreen
96 this.setState({ 107 this.setState({
97 isSettingUpServices: false, 108 isSettingUpServices: false,
98 }); 109 });
99
100 await sleep(100);
101
102 router.push(user.pricingRoute);
103 } 110 }
104 111
105 render() { 112 render() {
diff --git a/src/containers/auth/SignupScreen.js b/src/containers/auth/SignupScreen.js
index 42ee09f33..38c5dfb43 100644
--- a/src/containers/auth/SignupScreen.js
+++ b/src/containers/auth/SignupScreen.js
@@ -14,16 +14,7 @@ export default @inject('stores', 'actions') @observer class SignupScreen extends
14 }; 14 };
15 15
16 onSignup(values) { 16 onSignup(values) {
17 const { actions, stores } = this.props; 17 const { actions } = this.props;
18
19 const { canSkipTrial, defaultTrialPlan, pricingConfig } = stores.features.anonymousFeatures;
20
21 if (!canSkipTrial) {
22 Object.assign(values, {
23 plan: defaultTrialPlan,
24 currency: pricingConfig.currencyID,
25 });
26 }
27 18
28 actions.user.signup(values); 19 actions.user.signup(values);
29 } 20 }
@@ -33,7 +24,7 @@ export default @inject('stores', 'actions') @observer class SignupScreen extends
33 24
34 return ( 25 return (
35 <Signup 26 <Signup
36 onSubmit={values => this.onSignup(values)} 27 onSubmit={(values) => this.onSignup(values)}
37 isSubmitting={stores.user.signupRequest.isExecuting} 28 isSubmitting={stores.user.signupRequest.isExecuting}
38 loginRoute={stores.user.loginRoute} 29 loginRoute={stores.user.loginRoute}
39 changeServerRoute={stores.user.changeServerRoute} 30 changeServerRoute={stores.user.changeServerRoute}
diff --git a/src/containers/auth/WelcomeScreen.js b/src/containers/auth/WelcomeScreen.js
index 6f2d0eee6..bfcc880d0 100644
--- a/src/containers/auth/WelcomeScreen.js
+++ b/src/containers/auth/WelcomeScreen.js
@@ -15,7 +15,7 @@ export default @inject('stores', 'actions') @observer class LoginScreen extends
15 loginRoute={user.loginRoute} 15 loginRoute={user.loginRoute}
16 signupRoute={user.signupRoute} 16 signupRoute={user.signupRoute}
17 changeServerRoute={user.changeServerRoute} 17 changeServerRoute={user.changeServerRoute}
18 recipes={recipePreviews.featured} 18 recipes={recipePreviews.all}
19 /> 19 />
20 ); 20 );
21 } 21 }
diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js
index 7a12aee83..32b1f1cf7 100644
--- a/src/containers/layout/AppLayoutContainer.js
+++ b/src/containers/layout/AppLayoutContainer.js
@@ -20,7 +20,6 @@ import Sidebar from '../../components/layout/Sidebar';
20import Services from '../../components/services/content/Services'; 20import Services from '../../components/services/content/Services';
21import AppLoader from '../../components/ui/AppLoader'; 21import AppLoader from '../../components/ui/AppLoader';
22 22
23import { state as delayAppState } from '../../features/delayApp';
24import { workspaceActions } from '../../features/workspaces/actions'; 23import { workspaceActions } from '../../features/workspaces/actions';
25import WorkspaceDrawer from '../../features/workspaces/components/WorkspaceDrawer'; 24import WorkspaceDrawer from '../../features/workspaces/components/WorkspaceDrawer';
26import { workspaceStore } from '../../features/workspaces'; 25import { workspaceStore } from '../../features/workspaces';
@@ -55,8 +54,11 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e
55 reload, 54 reload,
56 toggleNotifications, 55 toggleNotifications,
57 toggleAudio, 56 toggleAudio,
57 toggleDarkMode,
58 deleteService, 58 deleteService,
59 updateService, 59 updateService,
60 hibernate,
61 awake,
60 } = this.props.actions.service; 62 } = this.props.actions.service;
61 63
62 const { hide } = this.props.actions.news; 64 const { hide } = this.props.actions.news;
@@ -91,10 +93,9 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e
91 93
92 const workspacesDrawer = ( 94 const workspacesDrawer = (
93 <WorkspaceDrawer 95 <WorkspaceDrawer
94 getServicesForWorkspace={workspace => ( 96 getServicesForWorkspace={(workspace) => (
95 workspace ? workspaceStore.getWorkspaceServices(workspace).map(s => s.name) : services.all.map(s => s.name) 97 workspace ? workspaceStore.getWorkspaceServices(workspace).map((s) => s.name) : services.all.map((s) => s.name)
96 )} 98 )}
97 onUpgradeAccountClick={() => openSettings({ path: 'user' })}
98 /> 99 />
99 ); 100 );
100 101
@@ -109,8 +110,11 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e
109 reload={reload} 110 reload={reload}
110 toggleNotifications={toggleNotifications} 111 toggleNotifications={toggleNotifications}
111 toggleAudio={toggleAudio} 112 toggleAudio={toggleAudio}
113 toggleDarkMode={toggleDarkMode}
112 deleteService={deleteService} 114 deleteService={deleteService}
113 updateService={updateService} 115 updateService={updateService}
116 hibernateService={hibernate}
117 wakeUpService={awake}
114 toggleMuteApp={toggleMuteApp} 118 toggleMuteApp={toggleMuteApp}
115 toggleWorkspaceDrawer={workspaceActions.toggleWorkspaceDrawer} 119 toggleWorkspaceDrawer={workspaceActions.toggleWorkspaceDrawer}
116 isWorkspaceDrawerOpen={workspaceStore.isWorkspaceDrawerOpen} 120 isWorkspaceDrawerOpen={workspaceStore.isWorkspaceDrawerOpen}
@@ -131,7 +135,6 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e
131 openSettings={openSettings} 135 openSettings={openSettings}
132 update={updateService} 136 update={updateService}
133 userHasCompletedSignup={user.hasCompletedSignup} 137 userHasCompletedSignup={user.hasCompletedSignup}
134 hasActivatedTrial={user.hasActivatedTrial}
135 isSpellcheckerEnabled={settings.app.enableSpellchecking} 138 isSpellcheckerEnabled={settings.app.enableSpellchecking}
136 /> 139 />
137 ); 140 );
@@ -157,8 +160,6 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e
157 areRequiredRequestsSuccessful={requests.areRequiredRequestsSuccessful} 160 areRequiredRequestsSuccessful={requests.areRequiredRequestsSuccessful}
158 retryRequiredRequests={retryRequiredRequests} 161 retryRequiredRequests={retryRequiredRequests}
159 areRequiredRequestsLoading={requests.areRequiredRequestsLoading} 162 areRequiredRequestsLoading={requests.areRequiredRequestsLoading}
160 isDelayAppScreenVisible={delayAppState.isDelayAppScreenVisible}
161 hasActivatedTrial={user.hasActivatedTrial}
162 > 163 >
163 {React.Children.count(children) > 0 ? children : null} 164 {React.Children.count(children) > 0 ? children : null}
164 </AppLayout> 165 </AppLayout>
diff --git a/src/containers/settings/AccountScreen.js b/src/containers/settings/AccountScreen.js
index db3b2a4a7..8d92b01be 100644
--- a/src/containers/settings/AccountScreen.js
+++ b/src/containers/settings/AccountScreen.js
@@ -2,7 +2,6 @@ import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { inject, observer } from 'mobx-react'; 3import { inject, observer } from 'mobx-react';
4 4
5import PaymentStore from '../../stores/PaymentStore';
6import UserStore from '../../stores/UserStore'; 5import UserStore from '../../stores/UserStore';
7import AppStore from '../../stores/AppStore'; 6import AppStore from '../../stores/AppStore';
8import FeaturesStore from '../../stores/FeaturesStore'; 7import FeaturesStore from '../../stores/FeaturesStore';
@@ -24,10 +23,9 @@ class AccountScreen extends Component {
24 } 23 }
25 24
26 reloadData() { 25 reloadData() {
27 const { user, payment } = this.props.stores; 26 const { user } = this.props.stores;
28 27
29 user.getUserInfoRequest.reload(); 28 user.getUserInfoRequest.reload();
30 payment.plansRequest.reload();
31 } 29 }
32 30
33 handleWebsiteLink(route) { 31 handleWebsiteLink(route) {
@@ -48,28 +46,17 @@ class AccountScreen extends Component {
48 } 46 }
49 47
50 render() { 48 render() {
51 const { 49 const { user, settings } = this.props.stores;
52 user, 50 const { user: userActions } = this.props.actions;
53 payment,
54 features,
55 settings,
56 } = this.props.stores;
57 const { user: userActions, payment: paymentActions } = this.props.actions;
58 51
59 const isLoadingUserInfo = user.getUserInfoRequest.isExecuting; 52 const isLoadingUserInfo = user.getUserInfoRequest.isExecuting;
60 const isLoadingPlans = payment.plansRequest.isExecuting;
61
62 const { upgradeAccount } = paymentActions;
63 53
64 return ( 54 return (
65 <ErrorBoundary> 55 <ErrorBoundary>
66 <AccountDashboard 56 <AccountDashboard
67 server={settings.all.app.server} 57 server={settings.all.app.server}
68 user={user.data} 58 user={user.data}
69 isPremiumOverrideUser={user.isPremiumOverride}
70 isProUser={user.isPro}
71 isLoading={isLoadingUserInfo} 59 isLoading={isLoadingUserInfo}
72 isLoadingPlans={isLoadingPlans}
73 userInfoRequestFailed={ 60 userInfoRequestFailed={
74 user.getUserInfoRequest.wasExecuted 61 user.getUserInfoRequest.wasExecuted
75 && user.getUserInfoRequest.isError 62 && user.getUserInfoRequest.isError
@@ -83,10 +70,6 @@ class AccountScreen extends Component {
83 && !user.deleteAccountRequest.isError 70 && !user.deleteAccountRequest.isError
84 } 71 }
85 openEditAccount={() => this.handleWebsiteLink('/user/profile')} 72 openEditAccount={() => this.handleWebsiteLink('/user/profile')}
86 upgradeToPro={() => upgradeAccount({
87 planId: features.features.pricingConfig.plans.pro.yearly.id,
88 })}
89 openBilling={() => this.handleWebsiteLink('/user/billing')}
90 openInvoices={() => this.handleWebsiteLink('/user/invoices')} 73 openInvoices={() => this.handleWebsiteLink('/user/invoices')}
91 /> 74 />
92 </ErrorBoundary> 75 </ErrorBoundary>
@@ -98,12 +81,10 @@ AccountScreen.wrappedComponent.propTypes = {
98 stores: PropTypes.shape({ 81 stores: PropTypes.shape({
99 user: PropTypes.instanceOf(UserStore).isRequired, 82 user: PropTypes.instanceOf(UserStore).isRequired,
100 features: PropTypes.instanceOf(FeaturesStore).isRequired, 83 features: PropTypes.instanceOf(FeaturesStore).isRequired,
101 payment: PropTypes.instanceOf(PaymentStore).isRequired,
102 settings: PropTypes.instanceOf(SettingsStore).isRequired, 84 settings: PropTypes.instanceOf(SettingsStore).isRequired,
103 app: PropTypes.instanceOf(AppStore).isRequired, 85 app: PropTypes.instanceOf(AppStore).isRequired,
104 }).isRequired, 86 }).isRequired,
105 actions: PropTypes.shape({ 87 actions: PropTypes.shape({
106 payment: PropTypes.instanceOf(PaymentStore).isRequired,
107 app: PropTypes.instanceOf(AppStore).isRequired, 88 app: PropTypes.instanceOf(AppStore).isRequired,
108 user: PropTypes.instanceOf(UserStore).isRequired, 89 user: PropTypes.instanceOf(UserStore).isRequired,
109 }).isRequired, 90 }).isRequired,
diff --git a/src/containers/settings/EditServiceScreen.js b/src/containers/settings/EditServiceScreen.js
index ddf2d2d25..c880e97ae 100644
--- a/src/containers/settings/EditServiceScreen.js
+++ b/src/containers/settings/EditServiceScreen.js
@@ -19,7 +19,6 @@ import { required, url, oneRequired } from '../../helpers/validation-helpers';
19import { getSelectOptions } from '../../helpers/i18n-helpers'; 19import { getSelectOptions } from '../../helpers/i18n-helpers';
20 20
21import { config as proxyFeature } from '../../features/serviceProxy'; 21import { config as proxyFeature } from '../../features/serviceProxy';
22import { config as spellcheckerFeature } from '../../features/spellchecker';
23 22
24import { SPELLCHECKER_LOCALES } from '../../i18n/languages'; 23import { SPELLCHECKER_LOCALES } from '../../i18n/languages';
25 24
@@ -346,7 +345,7 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
346 345
347 render() { 346 render() {
348 const { 347 const {
349 recipes, services, user, settings, 348 recipes, services, user,
350 } = this.props.stores; 349 } = this.props.stores;
351 const { action } = this.props.router.params; 350 const { action } = this.props.router.params;
352 351
@@ -395,13 +394,10 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
395 status={services.actionStatus} 394 status={services.actionStatus}
396 isSaving={services.updateServiceRequest.isExecuting || services.createServiceRequest.isExecuting} 395 isSaving={services.updateServiceRequest.isExecuting || services.createServiceRequest.isExecuting}
397 isDeleting={services.deleteServiceRequest.isExecuting} 396 isDeleting={services.deleteServiceRequest.isExecuting}
398 onSubmit={d => this.onSubmit(d)} 397 onSubmit={(d) => this.onSubmit(d)}
399 onDelete={() => this.deleteService()} 398 onDelete={() => this.deleteService()}
400 openRecipeFile={file => this.openRecipeFile(file)} 399 openRecipeFile={(file) => this.openRecipeFile(file)}
401 isProxyFeatureEnabled={proxyFeature.isEnabled} 400 isProxyFeatureEnabled={proxyFeature.isEnabled}
402 isServiceProxyIncludedInCurrentPlan={proxyFeature.isIncludedInCurrentPlan}
403 isSpellcheckerIncludedInCurrentPlan={spellcheckerFeature.isIncludedInCurrentPlan}
404 isHibernationFeatureActive={settings.app.hibernate}
405 /> 401 />
406 </ErrorBoundary> 402 </ErrorBoundary>
407 ); 403 );
diff --git a/src/containers/settings/EditSettingsScreen.js b/src/containers/settings/EditSettingsScreen.js
index d601e03d4..0d718489a 100644
--- a/src/containers/settings/EditSettingsScreen.js
+++ b/src/containers/settings/EditSettingsScreen.js
@@ -11,10 +11,9 @@ import Form from '../../lib/Form';
11import { APP_LOCALES, SPELLCHECKER_LOCALES } from '../../i18n/languages'; 11import { APP_LOCALES, SPELLCHECKER_LOCALES } from '../../i18n/languages';
12import { 12import {
13 HIBERNATION_STRATEGIES, SIDEBAR_WIDTH, ICON_SIZES, NAVIGATION_BAR_BEHAVIOURS, SEARCH_ENGINE_NAMES, TODO_APPS, 13 HIBERNATION_STRATEGIES, SIDEBAR_WIDTH, ICON_SIZES, NAVIGATION_BAR_BEHAVIOURS, SEARCH_ENGINE_NAMES, TODO_APPS,
14 DEFAULT_SETTING_KEEP_ALL_WORKSPACES_LOADED, DEFAULT_IS_FEATURE_ENABLED_BY_USER, 14 DEFAULT_SETTING_KEEP_ALL_WORKSPACES_LOADED, DEFAULT_IS_FEATURE_ENABLED_BY_USER, WAKE_UP_STRATEGIES,
15} from '../../config'; 15} from '../../config';
16import { DEFAULT_APP_SETTINGS, isMac } from '../../environment'; 16import { DEFAULT_APP_SETTINGS, isMac } from '../../environment';
17import { config as spellcheckerConfig } from '../../features/spellchecker';
18 17
19import { getSelectOptions } from '../../helpers/i18n-helpers'; 18import { getSelectOptions } from '../../helpers/i18n-helpers';
20import { hash } from '../../helpers/password-helpers'; 19import { hash } from '../../helpers/password-helpers';
@@ -27,6 +26,8 @@ import globalMessages from '../../i18n/globalMessages';
27import WorkspacesStore from '../../features/workspaces/store'; 26import WorkspacesStore from '../../features/workspaces/store';
28import ServicesStore from '../../stores/ServicesStore'; 27import ServicesStore from '../../stores/ServicesStore';
29 28
29const debug = require('debug')('Ferdi:EditSettingsScreen');
30
30const messages = defineMessages({ 31const messages = defineMessages({
31 autoLaunchOnStart: { 32 autoLaunchOnStart: {
32 id: 'settings.app.form.autoLaunchOnStart', 33 id: 'settings.app.form.autoLaunchOnStart',
@@ -88,10 +89,6 @@ const messages = defineMessages({
88 id: 'settings.app.form.sentry', 89 id: 'settings.app.form.sentry',
89 defaultMessage: '!!!Send telemetry data', 90 defaultMessage: '!!!Send telemetry data',
90 }, 91 },
91 hibernate: {
92 id: 'settings.app.form.hibernate',
93 defaultMessage: '!!!Enable service hibernation',
94 },
95 hibernateOnStartup: { 92 hibernateOnStartup: {
96 id: 'settings.app.form.hibernateOnStartup', 93 id: 'settings.app.form.hibernateOnStartup',
97 defaultMessage: '!!!Keep services in hibernation on startup', 94 defaultMessage: '!!!Keep services in hibernation on startup',
@@ -100,6 +97,10 @@ const messages = defineMessages({
100 id: 'settings.app.form.hibernationStrategy', 97 id: 'settings.app.form.hibernationStrategy',
101 defaultMessage: '!!!Hibernation strategy', 98 defaultMessage: '!!!Hibernation strategy',
102 }, 99 },
100 wakeUpStrategy: {
101 id: 'settings.app.form.wakeUpStrategy',
102 defaultMessage: '!!!Wake up strategy',
103 },
103 predefinedTodoServer: { 104 predefinedTodoServer: {
104 id: 'settings.app.form.predefinedTodoServer', 105 id: 'settings.app.form.predefinedTodoServer',
105 defaultMessage: '!!!Todo Server', 106 defaultMessage: '!!!Todo Server',
@@ -242,6 +243,8 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
242 openInBackground: settingsData.autoLaunchInBackground, 243 openInBackground: settingsData.autoLaunchInBackground,
243 }); 244 });
244 245
246 debug(`Updating settings store with data: ${settingsData}`);
247
245 settings.update({ 248 settings.update({
246 type: 'app', 249 type: 'app',
247 data: { 250 data: {
@@ -257,9 +260,9 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
257 navigationBarBehaviour: settingsData.navigationBarBehaviour, 260 navigationBarBehaviour: settingsData.navigationBarBehaviour,
258 searchEngine: settingsData.searchEngine, 261 searchEngine: settingsData.searchEngine,
259 sentry: settingsData.sentry, 262 sentry: settingsData.sentry,
260 hibernate: settingsData.hibernate,
261 hibernateOnStartup: settingsData.hibernateOnStartup, 263 hibernateOnStartup: settingsData.hibernateOnStartup,
262 hibernationStrategy: settingsData.hibernationStrategy, 264 hibernationStrategy: settingsData.hibernationStrategy,
265 wakeUpStrategy: settingsData.wakeUpStrategy,
263 predefinedTodoServer: settingsData.predefinedTodoServer, 266 predefinedTodoServer: settingsData.predefinedTodoServer,
264 customTodoServer: settingsData.customTodoServer, 267 customTodoServer: settingsData.customTodoServer,
265 lockingFeatureEnabled: settingsData.lockingFeatureEnabled, 268 lockingFeatureEnabled: settingsData.lockingFeatureEnabled,
@@ -339,6 +342,11 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
339 sort: false, 342 sort: false,
340 }); 343 });
341 344
345 const wakeUpStrategies = getSelectOptions({
346 locales: WAKE_UP_STRATEGIES,
347 sort: false,
348 });
349
342 const todoApp = getSelectOptions({ 350 const todoApp = getSelectOptions({
343 locales: TODO_APPS, 351 locales: TODO_APPS,
344 sort: false, 352 sort: false,
@@ -433,11 +441,6 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
433 value: settings.all.app.sentry, 441 value: settings.all.app.sentry,
434 default: DEFAULT_APP_SETTINGS.sentry, 442 default: DEFAULT_APP_SETTINGS.sentry,
435 }, 443 },
436 hibernate: {
437 label: intl.formatMessage(messages.hibernate),
438 value: settings.all.app.hibernate,
439 default: DEFAULT_APP_SETTINGS.hibernate,
440 },
441 hibernateOnStartup: { 444 hibernateOnStartup: {
442 label: intl.formatMessage(messages.hibernateOnStartup), 445 label: intl.formatMessage(messages.hibernateOnStartup),
443 value: settings.all.app.hibernateOnStartup, 446 value: settings.all.app.hibernateOnStartup,
@@ -449,6 +452,12 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
449 options: hibernationStrategies, 452 options: hibernationStrategies,
450 default: DEFAULT_APP_SETTINGS.hibernationStrategy, 453 default: DEFAULT_APP_SETTINGS.hibernationStrategy,
451 }, 454 },
455 wakeUpStrategy: {
456 label: intl.formatMessage(messages.wakeUpStrategy),
457 value: settings.all.app.wakeUpStrategy,
458 options: wakeUpStrategies,
459 default: DEFAULT_APP_SETTINGS.wakeUpStrategy,
460 },
452 predefinedTodoServer: { 461 predefinedTodoServer: {
453 label: intl.formatMessage(messages.predefinedTodoServer), 462 label: intl.formatMessage(messages.predefinedTodoServer),
454 value: settings.all.app.predefinedTodoServer, 463 value: settings.all.app.predefinedTodoServer,
@@ -516,8 +525,8 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
516 }, 525 },
517 enableSpellchecking: { 526 enableSpellchecking: {
518 label: intl.formatMessage(messages.enableSpellchecking), 527 label: intl.formatMessage(messages.enableSpellchecking),
519 value: !this.props.stores.user.data.isPremium && !spellcheckerConfig.isIncludedInCurrentPlan ? false : settings.all.app.enableSpellchecking, 528 value: settings.all.app.enableSpellchecking,
520 default: !this.props.stores.user.data.isPremium && !spellcheckerConfig.isIncludedInCurrentPlan ? false : DEFAULT_APP_SETTINGS.enableSpellchecking, 529 default: DEFAULT_APP_SETTINGS.enableSpellchecking,
521 }, 530 },
522 spellcheckerLanguage: { 531 spellcheckerLanguage: {
523 label: intl.formatMessage(globalMessages.spellcheckerLanguage), 532 label: intl.formatMessage(globalMessages.spellcheckerLanguage),
@@ -646,16 +655,14 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
646 isUpdateAvailable={updateStatus === updateStatusTypes.AVAILABLE} 655 isUpdateAvailable={updateStatus === updateStatusTypes.AVAILABLE}
647 noUpdateAvailable={updateStatus === updateStatusTypes.NOT_AVAILABLE} 656 noUpdateAvailable={updateStatus === updateStatusTypes.NOT_AVAILABLE}
648 updateIsReadyToInstall={updateStatus === updateStatusTypes.DOWNLOADED} 657 updateIsReadyToInstall={updateStatus === updateStatusTypes.DOWNLOADED}
649 onSubmit={d => this.onSubmit(d)} 658 onSubmit={(d) => this.onSubmit(d)}
650 getCacheSize={() => app.cacheSize} 659 getCacheSize={() => app.cacheSize}
651 isClearingAllCache={isClearingAllCache} 660 isClearingAllCache={isClearingAllCache}
652 onClearAllCache={clearAllCache} 661 onClearAllCache={clearAllCache}
653 isSpellcheckerIncludedInCurrentPlan={spellcheckerConfig.isIncludedInCurrentPlan}
654 isTodosEnabled={todos.isFeatureActive} 662 isTodosEnabled={todos.isFeatureActive}
655 isWorkspaceEnabled={workspaces.isFeatureActive} 663 isWorkspaceEnabled={workspaces.isFeatureActive}
656 lockingFeatureEnabled={lockingFeatureEnabled} 664 lockingFeatureEnabled={lockingFeatureEnabled}
657 automaticUpdates={this.props.stores.settings.app.automaticUpdates} 665 automaticUpdates={this.props.stores.settings.app.automaticUpdates}
658 hibernationEnabled={this.props.stores.settings.app.hibernate}
659 isDarkmodeEnabled={this.props.stores.settings.app.darkMode} 666 isDarkmodeEnabled={this.props.stores.settings.app.darkMode}
660 isAdaptableDarkModeEnabled={this.props.stores.settings.app.adaptableDarkMode} 667 isAdaptableDarkModeEnabled={this.props.stores.settings.app.adaptableDarkMode}
661 isTodosActivated={this.props.stores.todos.isFeatureEnabledByUser} 668 isTodosActivated={this.props.stores.todos.isFeatureEnabledByUser}
diff --git a/src/containers/settings/EditUserScreen.js b/src/containers/settings/EditUserScreen.js
index 8e93164de..820b5e4d3 100644
--- a/src/containers/settings/EditUserScreen.js
+++ b/src/containers/settings/EditUserScreen.js
@@ -141,7 +141,7 @@ export default @inject('stores', 'actions') @observer class EditUserScreen exten
141 status={user.actionStatus} 141 status={user.actionStatus}
142 form={form} 142 form={form}
143 isSaving={user.updateUserInfoRequest.isExecuting} 143 isSaving={user.updateUserInfoRequest.isExecuting}
144 onSubmit={d => this.onSubmit(d)} 144 onSubmit={(d) => this.onSubmit(d)}
145 /> 145 />
146 </ErrorBoundary> 146 </ErrorBoundary>
147 ); 147 );
diff --git a/src/containers/settings/RecipesScreen.js b/src/containers/settings/RecipesScreen.js
index f12f67b1f..52bf31383 100644
--- a/src/containers/settings/RecipesScreen.js
+++ b/src/containers/settings/RecipesScreen.js
@@ -1,11 +1,9 @@
1import { shell } from 'electron'; 1import { shell } from 'electron';
2import { app } from '@electron/remote'; 2import { ensureDirSync, readJsonSync } from 'fs-extra';
3import fs from 'fs-extra';
4import React, { Component } from 'react'; 3import React, { Component } from 'react';
5import PropTypes from 'prop-types'; 4import PropTypes from 'prop-types';
6import { autorun } from 'mobx'; 5import { autorun } from 'mobx';
7import { inject, observer } from 'mobx-react'; 6import { inject, observer } from 'mobx-react';
8import path from 'path';
9 7
10import RecipePreviewsStore from '../../stores/RecipePreviewsStore'; 8import RecipePreviewsStore from '../../stores/RecipePreviewsStore';
11import RecipeStore from '../../stores/RecipesStore'; 9import RecipeStore from '../../stores/RecipesStore';
@@ -15,7 +13,7 @@ import UserStore from '../../stores/UserStore';
15import RecipesDashboard from '../../components/settings/recipes/RecipesDashboard'; 13import RecipesDashboard from '../../components/settings/recipes/RecipesDashboard';
16import ErrorBoundary from '../../components/util/ErrorBoundary'; 14import ErrorBoundary from '../../components/util/ErrorBoundary';
17import { CUSTOM_WEBSITE_RECIPE_ID, FRANZ_DEV_DOCS } from '../../config'; 15import { CUSTOM_WEBSITE_RECIPE_ID, FRANZ_DEV_DOCS } from '../../config';
18import { RECIPES_PATH } from '../../environment'; 16import { asarRecipesPath, userDataRecipesPath } from '../../environment';
19import { communityRecipesStore } from '../../features/communityRecipes'; 17import { communityRecipesStore } from '../../features/communityRecipes';
20import RecipePreview from '../../models/RecipePreview'; 18import RecipePreview from '../../models/RecipePreview';
21import AppStore from '../../stores/AppStore'; 19import AppStore from '../../stores/AppStore';
@@ -45,18 +43,16 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
45 constructor(props) { 43 constructor(props) {
46 super(props); 44 super(props);
47 45
48 this.customRecipes = fs.readJsonSync(path.join(RECIPES_PATH, 'all.json')); 46 this.customRecipes = readJsonSync(asarRecipesPath('all.json'));
49 } 47 }
50 48
51 componentDidMount() { 49 componentDidMount() {
52 this.autorunDisposer = autorun(() => { 50 this.autorunDisposer = autorun(() => {
53 const { filter } = this.props.params; 51 const { filter } = { filter: 'all', ...this.props.params };
54 const { currentFilter } = this.state; 52 const { currentFilter } = this.state;
55 53
56 if (filter === 'all' && currentFilter !== 'all') { 54 if (filter === 'all' && currentFilter !== 'all') {
57 this.setState({ currentFilter: 'all' }); 55 this.setState({ currentFilter: 'all' });
58 } else if (filter === 'featured' && currentFilter !== 'featured') {
59 this.setState({ currentFilter: 'featured' });
60 } else if (filter === 'dev' && currentFilter !== 'dev') { 56 } else if (filter === 'dev' && currentFilter !== 'dev') {
61 this.setState({ currentFilter: 'dev' }); 57 this.setState({ currentFilter: 'dev' });
62 } 58 }
@@ -82,7 +78,7 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
82 return recipes 78 return recipes
83 // Filter out duplicate recipes 79 // Filter out duplicate recipes
84 .filter((recipe, index, self) => { 80 .filter((recipe, index, self) => {
85 const ids = self.map(rec => rec.id); 81 const ids = self.map((rec) => rec.id);
86 return ids.indexOf(recipe.id) === index; 82 return ids.indexOf(recipe.id) === index;
87 83
88 // Sort alphabetically 84 // Sort alphabetically
@@ -95,7 +91,7 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
95 91
96 // Create an array of RecipePreviews from an array of recipe objects 92 // Create an array of RecipePreviews from an array of recipe objects
97 createPreviews(recipes) { 93 createPreviews(recipes) {
98 return recipes.map(recipe => new RecipePreview(recipe)); 94 return recipes.map((recipe) => new RecipePreview(recipe));
99 } 95 }
100 96
101 resetSearch() { 97 resetSearch() {
@@ -107,7 +103,6 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
107 recipePreviews, 103 recipePreviews,
108 recipes, 104 recipes,
109 services, 105 services,
110 user,
111 } = this.props.stores; 106 } = this.props.stores;
112 107
113 const { 108 const {
@@ -115,7 +110,7 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
115 service: serviceActions, 110 service: serviceActions,
116 } = this.props.actions; 111 } = this.props.actions;
117 112
118 const { filter } = this.props.params; 113 const { filter } = { filter: 'all', ...this.props.params };
119 let recipeFilter; 114 let recipeFilter;
120 115
121 if (filter === 'all') { 116 if (filter === 'all') {
@@ -125,8 +120,6 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
125 ]); 120 ]);
126 } else if (filter === 'dev') { 121 } else if (filter === 'dev') {
127 recipeFilter = communityRecipesStore.communityRecipes; 122 recipeFilter = communityRecipesStore.communityRecipes;
128 } else {
129 recipeFilter = recipePreviews.featured;
130 } 123 }
131 124
132 const allRecipes = this.state.needle ? this.prepareRecipes([ 125 const allRecipes = this.state.needle ? this.prepareRecipes([
@@ -135,18 +128,17 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
135 // All search recipes from local recipes 128 // All search recipes from local recipes
136 ...this.createPreviews( 129 ...this.createPreviews(
137 this.customRecipes 130 this.customRecipes
138 .filter(service => service.name.toLowerCase().includes(this.state.needle.toLowerCase())), 131 .filter((service) => service.name.toLowerCase().includes(this.state.needle.toLowerCase()) || (service.aliases || []).some(alias => alias.toLowerCase().includes(this.state.needle.toLowerCase()))),
139 ), 132 ),
140 ]) : recipeFilter; 133 ]) : recipeFilter;
141 134
142 const customWebsiteRecipe = recipePreviews.all.find(service => service.id === CUSTOM_WEBSITE_RECIPE_ID); 135 const customWebsiteRecipe = recipePreviews.all.find((service) => service.id === CUSTOM_WEBSITE_RECIPE_ID);
143 136
144 const isLoading = recipePreviews.featuredRecipePreviewsRequest.isExecuting 137 const isLoading = recipePreviews.allRecipePreviewsRequest.isExecuting
145 || recipePreviews.allRecipePreviewsRequest.isExecuting
146 || recipes.installRecipeRequest.isExecuting 138 || recipes.installRecipeRequest.isExecuting
147 || recipePreviews.searchRecipePreviewsRequest.isExecuting; 139 || recipePreviews.searchRecipePreviewsRequest.isExecuting;
148 140
149 const recipeDirectory = path.join(app.getPath('userData'), 'recipes', 'dev'); 141 const recipeDirectory = userDataRecipesPath('dev');
150 142
151 return ( 143 return (
152 <ErrorBoundary> 144 <ErrorBoundary>
@@ -155,24 +147,20 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
155 customWebsiteRecipe={customWebsiteRecipe} 147 customWebsiteRecipe={customWebsiteRecipe}
156 isLoading={isLoading} 148 isLoading={isLoading}
157 addedServiceCount={services.all.length} 149 addedServiceCount={services.all.length}
158 isPremium={user.data.isPremium}
159 hasLoadedRecipes={recipePreviews.featuredRecipePreviewsRequest.wasExecuted}
160 showAddServiceInterface={serviceActions.showAddServiceInterface} 150 showAddServiceInterface={serviceActions.showAddServiceInterface}
161 searchRecipes={e => this.searchRecipes(e)} 151 searchRecipes={(e) => this.searchRecipes(e)}
162 resetSearch={() => this.resetSearch()} 152 resetSearch={() => this.resetSearch()}
163 searchNeedle={this.state.needle} 153 searchNeedle={this.state.needle}
164 serviceStatus={services.actionStatus} 154 serviceStatus={services.actionStatus}
165 recipeFilter={filter} 155 recipeFilter={filter}
166 recipeDirectory={recipeDirectory} 156 recipeDirectory={recipeDirectory}
167 openRecipeDirectory={async () => { 157 openRecipeDirectory={async () => {
168 await fs.ensureDir(recipeDirectory); 158 ensureDirSync(recipeDirectory);
169 shell.openExternal(`file://${recipeDirectory}`); 159 shell.openExternal(`file://${recipeDirectory}`);
170 }} 160 }}
171 openDevDocs={() => { 161 openDevDocs={() => {
172 appActions.openExternalUrl({ url: FRANZ_DEV_DOCS }); 162 appActions.openExternalUrl({ url: FRANZ_DEV_DOCS });
173 }} 163 }}
174 isCommunityRecipesIncludedInCurrentPlan={communityRecipesStore.isCommunityRecipesIncludedInCurrentPlan}
175 isUserPremiumUser={user.isPremium}
176 /> 164 />
177 </ErrorBoundary> 165 </ErrorBoundary>
178 ); 166 );
diff --git a/src/containers/settings/TeamScreen.js b/src/containers/settings/TeamScreen.js
index a627a047a..10c2e36ef 100644
--- a/src/containers/settings/TeamScreen.js
+++ b/src/containers/settings/TeamScreen.js
@@ -9,7 +9,6 @@ import SettingsStore from '../../stores/SettingsStore';
9import TeamDashboard from '../../components/settings/team/TeamDashboard'; 9import TeamDashboard from '../../components/settings/team/TeamDashboard';
10import ErrorBoundary from '../../components/util/ErrorBoundary'; 10import ErrorBoundary from '../../components/util/ErrorBoundary';
11import { DEV_API_FRANZ_WEBSITE } from '../../config'; 11import { DEV_API_FRANZ_WEBSITE } from '../../config';
12import PaymentStore from '../../stores/PaymentStore';
13 12
14export default @inject('stores', 'actions') @observer class TeamScreen extends Component { 13export default @inject('stores', 'actions') @observer class TeamScreen extends Component {
15 handleWebsiteLink(route) { 14 handleWebsiteLink(route) {
@@ -33,7 +32,6 @@ export default @inject('stores', 'actions') @observer class TeamScreen extends C
33 userInfoRequestFailed={user.getUserInfoRequest.wasExecuted && user.getUserInfoRequest.isError} 32 userInfoRequestFailed={user.getUserInfoRequest.wasExecuted && user.getUserInfoRequest.isError}
34 retryUserInfoRequest={() => this.reloadData()} 33 retryUserInfoRequest={() => this.reloadData()}
35 openTeamManagement={() => this.handleWebsiteLink('/user/team')} 34 openTeamManagement={() => this.handleWebsiteLink('/user/team')}
36 isProUser={user.isPro}
37 server={server} 35 server={server}
38 /> 36 />
39 </ErrorBoundary> 37 </ErrorBoundary>
@@ -48,7 +46,6 @@ TeamScreen.wrappedComponent.propTypes = {
48 settings: PropTypes.instanceOf(SettingsStore).isRequired, 46 settings: PropTypes.instanceOf(SettingsStore).isRequired,
49 }).isRequired, 47 }).isRequired,
50 actions: PropTypes.shape({ 48 actions: PropTypes.shape({
51 payment: PropTypes.instanceOf(PaymentStore).isRequired,
52 app: PropTypes.instanceOf(AppStore).isRequired, 49 app: PropTypes.instanceOf(AppStore).isRequired,
53 user: PropTypes.instanceOf(UserStore).isRequired, 50 user: PropTypes.instanceOf(UserStore).isRequired,
54 }).isRequired, 51 }).isRequired,
diff --git a/src/containers/subscription/SubscriptionFormScreen.js b/src/containers/subscription/SubscriptionFormScreen.js
deleted file mode 100644
index e5c8207be..000000000
--- a/src/containers/subscription/SubscriptionFormScreen.js
+++ /dev/null
@@ -1,99 +0,0 @@
1import React, { Component } from 'react';
2import { BrowserWindow, getCurrentWindow } from '@electron/remote';
3import PropTypes from 'prop-types';
4import { inject, observer } from 'mobx-react';
5
6import PaymentStore from '../../stores/PaymentStore';
7
8import SubscriptionForm from '../../components/subscription/SubscriptionForm';
9import TrialForm from '../../components/subscription/TrialForm';
10import UserStore from '../../stores/UserStore';
11import FeaturesStore from '../../stores/FeaturesStore';
12import AppStore from '../../stores/AppStore';
13
14export default @inject('stores', 'actions') @observer class SubscriptionFormScreen extends Component {
15 static propTypes = {
16 onCloseWindow: PropTypes.func,
17 }
18
19 static defaultProps = {
20 onCloseWindow: () => null,
21 }
22
23 async openBrowser() {
24 const {
25 stores,
26 onCloseWindow,
27 } = this.props;
28
29 const {
30 user,
31 features,
32 } = stores;
33
34 let hostedPageURL = features.features.planSelectionURL;
35 hostedPageURL = user.getAuthURL(hostedPageURL);
36
37 const paymentWindow = new BrowserWindow({
38 parent: getCurrentWindow(),
39 modal: true,
40 title: '🔒 Franz Supporter License',
41 width: 800,
42 height: window.innerHeight - 100,
43 maxWidth: 800,
44 minWidth: 600,
45 webPreferences: {
46 nodeIntegration: true,
47 webviewTag: true,
48 enableRemoteModule: true,
49 contextIsolation: false,
50 },
51 });
52 paymentWindow.loadURL(`file://${__dirname}/../../index.html#/payment/${encodeURIComponent(hostedPageURL)}`);
53
54 paymentWindow.on('closed', () => {
55 onCloseWindow();
56 });
57 }
58
59 render() {
60 const {
61 actions,
62 stores,
63 } = this.props;
64
65 const { data: user } = stores.user;
66
67 if (user.hadSubscription) {
68 return (
69 <SubscriptionForm
70 plan={stores.payment.plan}
71 selectPlan={() => this.openBrowser()}
72 isActivatingTrial={stores.user.activateTrialRequest.isExecuting || stores.user.getUserInfoRequest.isExecuting}
73 />
74 );
75 }
76
77 return (
78 <TrialForm
79 plan={stores.payment.plan}
80 activateTrial={() => actions.user.activateTrial({ planId: stores.features.features.defaultTrialPlan })}
81 showAllOptions={() => this.openBrowser()}
82 isActivatingTrial={stores.user.activateTrialRequest.isExecuting || stores.user.getUserInfoRequest.isExecuting}
83 />
84 );
85 }
86}
87
88SubscriptionFormScreen.wrappedComponent.propTypes = {
89 actions: PropTypes.shape({
90 app: PropTypes.instanceOf(AppStore).isRequired,
91 payment: PropTypes.instanceOf(PaymentStore).isRequired,
92 user: PropTypes.instanceOf(UserStore).isRequired,
93 }).isRequired,
94 stores: PropTypes.shape({
95 payment: PropTypes.instanceOf(PaymentStore).isRequired,
96 user: PropTypes.instanceOf(UserStore).isRequired,
97 features: PropTypes.instanceOf(FeaturesStore).isRequired,
98 }).isRequired,
99};
diff --git a/src/containers/subscription/SubscriptionPopupScreen.js b/src/containers/subscription/SubscriptionPopupScreen.js
deleted file mode 100644
index 43966b6a4..000000000
--- a/src/containers/subscription/SubscriptionPopupScreen.js
+++ /dev/null
@@ -1,41 +0,0 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import { inject, observer } from 'mobx-react';
4
5import SubscriptionPopup from '../../components/subscription/SubscriptionPopup';
6import { isDevMode } from '../../environment';
7
8export default @inject('stores', 'actions') @observer class SubscriptionPopupScreen extends Component {
9 state = {
10 complete: false,
11 };
12
13 completeCheck(event) {
14 const { url } = event;
15
16 if ((url.includes('recurly') && url.includes('confirmation')) || ((url.includes('meetfranz') || isDevMode) && url.includes('success'))) {
17 this.setState({
18 complete: true,
19 });
20 }
21 }
22
23 render() {
24 return (
25 <SubscriptionPopup
26 url={this.props.router.params.url}
27 closeWindow={() => window.close()}
28 completeCheck={e => this.completeCheck(e)}
29 isCompleted={this.state.complete}
30 />
31 );
32 }
33}
34
35SubscriptionPopupScreen.wrappedComponent.propTypes = {
36 router: PropTypes.shape({
37 params: PropTypes.shape({
38 url: PropTypes.string.isRequired,
39 }).isRequired,
40 }).isRequired,
41};