Skip to content

Commit

Permalink
Merge branch 'update/monetization' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
adlk committed Nov 28, 2018
2 parents 72d4164 + 4f3db81 commit 8b64855
Show file tree
Hide file tree
Showing 36 changed files with 611 additions and 179 deletions.
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"react/jsx-filename-extension": [1, {
"extensions": [".js", ".jsx"]
}],
"react/forbid-prop-types": 1,
"no-underscore-dangle": 0,
"max-len": 0,
"class-methods-use-this": 0,
Expand Down
8 changes: 4 additions & 4 deletions src/api/LocalApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ export default class LocalApi {
this.local = local;
}

getAppSettings() {
return this.local.getAppSettings();
getAppSettings(type) {
return this.local.getAppSettings(type);
}

updateAppSettings(data) {
return this.local.updateAppSettings(data);
updateAppSettings(type, data) {
return this.local.updateAppSettings(type, data);
}

getAppCacheSize() {
Expand Down
19 changes: 11 additions & 8 deletions src/api/server/LocalApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,23 @@ const { session } = remote;

export default class LocalApi {
// Settings
getAppSettings() {
getAppSettings(type) {
return new Promise((resolve) => {
ipcRenderer.once('appSettings', (event, data) => {
debug('LocalApi::getAppSettings resolves', data);
resolve(data);
ipcRenderer.once('appSettings', (event, resp) => {
debug('LocalApi::getAppSettings resolves', resp.type, resp.data);
resolve(resp);
});

ipcRenderer.send('getAppSettings');
ipcRenderer.send('getAppSettings', type);
});
}

async updateAppSettings(data) {
debug('LocalApi::updateAppSettings resolves', data);
ipcRenderer.send('updateAppSettings', data);
async updateAppSettings(type, data) {
debug('LocalApi::updateAppSettings resolves', type, data);
ipcRenderer.send('updateAppSettings', {
type,
data,
});
}

// Services
Expand Down
2 changes: 1 addition & 1 deletion src/components/layout/AppLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { defineMessages, intlShape } from 'react-intl';
import { TitleBar } from 'electron-react-titlebar';

import InfoBar from '../ui/InfoBar';
import { component as DelayApp } from '../../features/delayApp';
import { Component as DelayApp } from '../../features/delayApp';
import globalMessages from '../../i18n/globalMessages';

import { isWindows } from '../../environment';
Expand Down
8 changes: 3 additions & 5 deletions src/components/settings/account/AccountDashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,9 @@ export default @observer class AccountDashboard extends Component {
<span className="badge badge--success">{intl.formatMessage(messages.accountTypeEnterprise)}</span>
)}
</div>
{!user.isSSO && (
<Link to="/settings/user/edit" className="button">
{intl.formatMessage(messages.accountEditButton)}
</Link>
)}
<Link to="/settings/user/edit" className="button">
{intl.formatMessage(messages.accountEditButton)}
</Link>
{user.emailValidated}
</div>
</div>
Expand Down
25 changes: 7 additions & 18 deletions src/components/settings/navigation/SettingsNavigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,17 @@ export default @inject('stores') @observer class SettingsNavigation extends Comp

render() {
const { serviceCount } = this.props;
const { features } = this.props.stores.features;
const { intl } = this.context;

return (
<div className="settings-navigation">
{features.userCanManageServices && (
<Link
to="/settings/recipes"
className="settings-navigation__link"
activeClassName="is-active"
>
{intl.formatMessage(messages.availableServices)}
</Link>
)}
<Link
to="/settings/recipes"
className="settings-navigation__link"
activeClassName="is-active"
>
{intl.formatMessage(messages.availableServices)}
</Link>
<Link
to="/settings/services"
className="settings-navigation__link"
Expand Down Expand Up @@ -97,11 +94,3 @@ export default @inject('stores') @observer class SettingsNavigation extends Comp
}
}

SettingsNavigation.wrappedComponent.propTypes = {
stores: PropTypes.shape({
features: PropTypes.shape({
features: PropTypes.object.isRequired,
}).isRequired,
}).isRequired,
};

45 changes: 42 additions & 3 deletions src/components/settings/services/EditServiceForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import Toggle from '../../ui/Toggle';
import Button from '../../ui/Button';
import ImageUpload from '../../ui/ImageUpload';

import PremiumFeatureContainer from '../../ui/PremiumFeatureContainer';

const messages = defineMessages({
saveService: {
id: 'settings.service.form.saveButton',
Expand Down Expand Up @@ -92,6 +94,14 @@ const messages = defineMessages({
id: 'settings.service.form.iconUpload',
defaultMessage: '!!!Drop your image, or click here',
},
headlineProxy: {
id: 'settings.service.form.proxy.headline',
defaultMessage: '!!!Proxy Settings',
},
proxyInfo: {
id: 'settings.service.form.proxy.info',
defaultMessage: '!!!Proxy settings will not be synchronized with the Franz servers.',
},
});

export default @observer class EditServiceForm extends Component {
Expand All @@ -106,13 +116,14 @@ export default @observer class EditServiceForm extends Component {
return null;
},
user: PropTypes.instanceOf(User).isRequired,
userCanManageServices: PropTypes.bool.isRequired,
action: PropTypes.string.isRequired,
form: PropTypes.instanceOf(Form).isRequired,
onSubmit: PropTypes.func.isRequired,
onDelete: PropTypes.func.isRequired,
isSaving: PropTypes.bool.isRequired,
isDeleting: PropTypes.bool.isRequired,
isProxyFeatureEnabled: PropTypes.bool.isRequired,
isProxyFeaturePremiumFeature: PropTypes.bool.isRequired,
};

static defaultProps = {
Expand Down Expand Up @@ -169,11 +180,12 @@ export default @observer class EditServiceForm extends Component {
service,
action,
user,
userCanManageServices,
form,
isSaving,
isDeleting,
onDelete,
isProxyFeatureEnabled,
isProxyFeaturePremiumFeature,
} = this.props;
const { intl } = this.context;

Expand Down Expand Up @@ -318,6 +330,33 @@ export default @observer class EditServiceForm extends Component {
/>
</div>
</div>

{isProxyFeatureEnabled && (
<PremiumFeatureContainer condition={isProxyFeaturePremiumFeature}>
<div className="settings__settings-group">
<h3>
{intl.formatMessage(messages.headlineProxy)}
<span className="badge badge--success">beta</span>
</h3>
<Toggle field={form.$('proxy.isEnabled')} />
{form.$('proxy.isEnabled').value && (
<div>
<Input field={form.$('proxy.host')} />
<Input field={form.$('proxy.user')} />
<Input
field={form.$('proxy.password')}
showPasswordToggle
/>
<p>
<span className="mdi mdi-information" />
{intl.formatMessage(messages.proxyInfo)}
</p>
</div>
)}
</div>
</PremiumFeatureContainer>
)}

{recipe.message && (
<p className="settings__message">
<span className="mdi mdi-information" />
Expand All @@ -328,7 +367,7 @@ export default @observer class EditServiceForm extends Component {
</div>
<div className="settings__controls">
{/* Delete Button */}
{action === 'edit' && userCanManageServices && deleteButton}
{action === 'edit' && deleteButton}

{/* Save Button */}
{isSaving || isValidatingCustomUrl ? (
Expand Down
12 changes: 11 additions & 1 deletion src/components/settings/settings/EditSettingsForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Form from '../../../lib/Form';
import Button from '../../ui/Button';
import Toggle from '../../ui/Toggle';
import Select from '../../ui/Select';
import PremiumFeatureContainer from '../../ui/PremiumFeatureContainer';

import { FRANZ_TRANSLATION } from '../../../config';

Expand Down Expand Up @@ -95,6 +96,7 @@ export default @observer class EditSettingsForm extends Component {
isClearingAllCache: PropTypes.bool.isRequired,
onClearAllCache: PropTypes.func.isRequired,
cacheSize: PropTypes.string.isRequired,
isSpellcheckerPremiumFeature: PropTypes.bool.isRequired,
};

static contextTypes = {
Expand Down Expand Up @@ -124,6 +126,7 @@ export default @observer class EditSettingsForm extends Component {
isClearingAllCache,
onClearAllCache,
cacheSize,
isSpellcheckerPremiumFeature,
} = this.props;
const { intl } = this.context;

Expand Down Expand Up @@ -175,7 +178,14 @@ export default @observer class EditSettingsForm extends Component {

{/* Advanced */}
<h2 id="advanced">{intl.formatMessage(messages.headlineAdvanced)}</h2>
<Toggle field={form.$('enableSpellchecking')} />
<PremiumFeatureContainer
condition={isSpellcheckerPremiumFeature}
>
<Toggle
field={form.$('enableSpellchecking')}
disabled
/>
</PremiumFeatureContainer>
<Toggle field={form.$('enableGPUAcceleration')} />
<p className="settings__help">{intl.formatMessage(messages.enableGPUAccelerationInfo)}</p>
{/* <Select field={form.$('spellcheckingLanguage')} /> */}
Expand Down
32 changes: 11 additions & 21 deletions src/components/subscription/SubscriptionForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,26 +36,22 @@ const messages = defineMessages({
defaultMessage: '!!!The Franz Premium Supporter Account includes',
},
features: {
unlimitedServices: {
id: 'subscription.features.unlimitedServices',
defaultMessage: '!!!Add unlimited services',
},
onpremise: {
id: 'subscription.features.onpremise',
defaultMessage: '!!!Add on-premise/hosted services like HipChat',
},
customServices: {
id: 'subscription.features.customServices',
defaultMessage: '!!!Add your custom services',
id: 'subscription.features.onpremise.mattermost',
defaultMessage: '!!!Add on-premise/hosted services like Mattermost',
},
encryptedSync: {
id: 'subscription.features.encryptedSync',
defaultMessage: '!!!Encrypted session synchronization',
noInterruptions: {
id: 'subscription.features.noInterruptions',
defaultMessage: '!!!No app delays & nagging to upgrade license',
},
vpn: {
id: 'subscription.features.vpn',
defaultMessage: '!!!Proxy & VPN support',
},
spellchecker: {
id: 'subscription.features.spellchecker',
defaultMessage: '!!!Support for Spellchecker',
},
ads: {
id: 'subscription.features.ads',
defaultMessage: '!!!No ads, ever!',
Expand Down Expand Up @@ -170,16 +166,10 @@ export default @observer class SubscriptionForm extends Component {
<ul className="subscription__premium-features">
<li>{intl.formatMessage(messages.features.onpremise)}</li>
<li>
{intl.formatMessage(messages.features.encryptedSync)}
<span className="badge">{intl.formatMessage(messages.features.comingSoon)}</span>
</li>
<li>
{intl.formatMessage(messages.features.customServices)}
<span className="badge">{intl.formatMessage(messages.features.comingSoon)}</span>
{intl.formatMessage(messages.features.noInterruptions)}
</li>
<li>
{intl.formatMessage(messages.features.vpn)}
<span className="badge">{intl.formatMessage(messages.features.comingSoon)}</span>
{intl.formatMessage(messages.features.spellchecker)}
</li>
<li>
{intl.formatMessage(messages.features.ads)}
Expand Down
76 changes: 76 additions & 0 deletions src/components/ui/PremiumFeatureContainer/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { Component } from 'react';
import { inject, observer } from 'mobx-react';
import PropTypes from 'prop-types';
import { defineMessages, intlShape } from 'react-intl';
import injectSheet from 'react-jss';

import { oneOrManyChildElements } from '../../../prop-types';

import UserStore from '../../../stores/UserStore';

import styles from './styles';

const messages = defineMessages({
action: {
id: 'premiumFeature.button.upgradeAccount',
defaultMessage: '!!!Upgrade account',
},
});

export default @inject('stores', 'actions') @injectSheet(styles) @observer class PremiumFeatureContainer extends Component {
static propTypes = {
classes: PropTypes.object.isRequired,
condition: PropTypes.bool,
};

static defaultProps = {
condition: true,
};

static contextTypes = {
intl: intlShape,
};

render() {
const {
classes,
children,
actions,
condition,
stores,
} = this.props;

const { intl } = this.context;

return !stores.user.data.isPremium && !!condition ? (
<div className={classes.container}>
<div className={classes.titleContainer}>
<p className={classes.title}>Premium Feature</p>
<button
className={classes.actionButton}
type="button"
onClick={() => actions.ui.openSettings({ path: 'user' })}
>
{intl.formatMessage(messages.action)}
</button>
</div>
<div className={classes.content}>
{children}
</div>
</div>
) : children;
}
}

PremiumFeatureContainer.wrappedComponent.propTypes = {
children: oneOrManyChildElements.isRequired,
stores: PropTypes.shape({
user: PropTypes.instanceOf(UserStore).isRequired,
}).isRequired,
actions: PropTypes.shape({
ui: PropTypes.shape({
openSettings: PropTypes.func.isRequired,
}).isRequired,
}).isRequired,
};

Loading

0 comments on commit 8b64855

Please sign in to comment.