mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-09-21 07:46:06 +08:00
Add Preferences > Subscription empty state that allows you to link ID later
This commit is contained in:
parent
966dcfd92c
commit
48b7338e88
|
@ -5,10 +5,9 @@ import {
|
|||
localized,
|
||||
localizedReactFragment,
|
||||
IIdentity,
|
||||
EMPTY_IDENTITY,
|
||||
} from 'mailspring-exports';
|
||||
import { OpenIdentityPageButton, BillingModal, RetinaImg } from 'mailspring-component-kit';
|
||||
import { shell } from 'electron';
|
||||
import { shell, ipcRenderer } from 'electron';
|
||||
|
||||
class RefreshButton extends React.Component<{}, { refreshing: boolean }> {
|
||||
constructor(props) {
|
||||
|
@ -132,7 +131,7 @@ const ProTourFeatures = [
|
|||
},
|
||||
];
|
||||
|
||||
class PreferencesIdentity extends React.Component<{}, { identity: IIdentity }> {
|
||||
class PreferencesIdentity extends React.Component<{}, { identity: IIdentity | null }> {
|
||||
static displayName = 'PreferencesIdentity';
|
||||
|
||||
unsubscribe: () => void;
|
||||
|
@ -154,7 +153,7 @@ class PreferencesIdentity extends React.Component<{}, { identity: IIdentity }> {
|
|||
|
||||
_getStateFromStores() {
|
||||
return {
|
||||
identity: IdentityStore.identity() || { ...EMPTY_IDENTITY },
|
||||
identity: IdentityStore.identity(),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -166,7 +165,38 @@ class PreferencesIdentity extends React.Component<{}, { identity: IIdentity }> {
|
|||
});
|
||||
};
|
||||
|
||||
_renderBasic() {
|
||||
_onLinkIdentity = () => {
|
||||
ipcRenderer.send('command', 'application:add-identity');
|
||||
};
|
||||
|
||||
_renderNoIdentity() {
|
||||
return (
|
||||
<>
|
||||
<div className="row padded">
|
||||
<div style={{ display: 'flex', alignItems: 'flex-start' }}>
|
||||
<div className="basic-explanation" style={{ display: 'flex' }}>
|
||||
{localizedReactFragment(
|
||||
`You are not signed in to Mailspring. Link the app to a free Mailspring ID to use great free features like send later and snoozing, or upgrade to Mailspring Pro for unlimited message translation and more.`
|
||||
)}
|
||||
<div
|
||||
className="btn btn-emphasis"
|
||||
onClick={this._onLinkIdentity}
|
||||
style={{ verticalAlign: 'top', flexShrink: 0, marginLeft: 30 }}
|
||||
>
|
||||
<RetinaImg name="ic-upgrade.png" mode={RetinaImg.Mode.ContentIsMask} />{' '}
|
||||
{localized(`Setup Mailspring ID`)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row padded" style={{ paddingTop: 0 }}>
|
||||
<ExploreMailspringPro />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
_renderBasicPlan() {
|
||||
const onLearnMore = () => shell.openExternal('https://getmailspring.com/pro');
|
||||
return (
|
||||
<div className="row padded">
|
||||
|
@ -188,92 +218,7 @@ class PreferencesIdentity extends React.Component<{}, { identity: IIdentity }> {
|
|||
`Upgrade to %@ to use all these great features permanently:`,
|
||||
<a onClick={onLearnMore}>{localized('Mailspring Pro')}</a>
|
||||
)}
|
||||
<div className="features">
|
||||
<ul>
|
||||
<li>
|
||||
<RetinaImg
|
||||
name="pro-feature-checkmark.png"
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{localized(`Rich contact profiles`)}
|
||||
</li>
|
||||
<li>
|
||||
<RetinaImg
|
||||
name="pro-feature-checkmark.png"
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{localized(`Follow-up reminders`)}
|
||||
</li>
|
||||
<li>
|
||||
<RetinaImg
|
||||
name="pro-feature-checkmark.png"
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{localized(`Read Receipts`)}
|
||||
</li>
|
||||
<li>
|
||||
<RetinaImg
|
||||
name="pro-feature-checkmark.png"
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{localized(`Link tracking`)}
|
||||
</li>
|
||||
<li>
|
||||
<RetinaImg
|
||||
name="pro-feature-checkmark.png"
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{localized(`Powerful template support`)}
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<RetinaImg
|
||||
name="pro-feature-checkmark.png"
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{localized(`Send Later`)}
|
||||
</li>
|
||||
<li>
|
||||
<RetinaImg
|
||||
name="pro-feature-checkmark.png"
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{localized(`Company overviews`)}
|
||||
</li>
|
||||
<li>
|
||||
<RetinaImg
|
||||
name="pro-feature-checkmark.png"
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{localized(`Snooze messages`)}
|
||||
</li>
|
||||
<li>
|
||||
<RetinaImg
|
||||
name="pro-feature-checkmark.png"
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{localized(`Mailbox insights`)}
|
||||
</li>
|
||||
<li>
|
||||
<RetinaImg
|
||||
name="pro-feature-checkmark.png"
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{localized(`... and much more!`)}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<ExploreMailspringSmall />
|
||||
</div>
|
||||
<div className="subscription-actions">
|
||||
<div className="pro-feature-ring">
|
||||
|
@ -291,6 +236,7 @@ class PreferencesIdentity extends React.Component<{}, { identity: IIdentity }> {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ExploreMailspringPro />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -320,25 +266,7 @@ class PreferencesIdentity extends React.Component<{}, { identity: IIdentity }> {
|
|||
)}
|
||||
{unpaidNote}
|
||||
</div>
|
||||
<div className="feature-explore-title">{localized('Explore Mailspring Pro')}</div>
|
||||
<div className="feature-explore-grid">
|
||||
{ProTourFeatures.map(item => (
|
||||
<a key={item.title} className="feature" href={item.link}>
|
||||
<div className="popout">
|
||||
<RetinaImg name="thread-popout.png" mode={RetinaImg.Mode.ContentDark} />
|
||||
</div>
|
||||
<h3>
|
||||
<RetinaImg
|
||||
name={item.icon}
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{item.title}
|
||||
</h3>
|
||||
<p>{item.text}</p>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
<ExploreMailspringPro />
|
||||
<div style={{ paddingTop: 15 }}>
|
||||
<OpenIdentityPageButton
|
||||
label={localized('Manage Billing')}
|
||||
|
@ -353,46 +281,162 @@ class PreferencesIdentity extends React.Component<{}, { identity: IIdentity }> {
|
|||
|
||||
render() {
|
||||
const { identity } = this.state;
|
||||
const {
|
||||
firstName,
|
||||
lastName,
|
||||
emailAddress,
|
||||
stripePlan = '',
|
||||
stripePlanEffective = '',
|
||||
} = identity;
|
||||
|
||||
const logout = () => Actions.logoutMailspringIdentity();
|
||||
const stripePlan = identity ? identity.stripePlan : null;
|
||||
|
||||
return (
|
||||
<div className="container-identity">
|
||||
<div className="identity-content-box">
|
||||
<div className="row padded">
|
||||
<div className="identity-info">
|
||||
<RefreshButton />
|
||||
<div className="name">
|
||||
{firstName} {lastName}
|
||||
</div>
|
||||
<div className="email">{emailAddress}</div>
|
||||
<div className="identity-actions">
|
||||
<OpenIdentityPageButton
|
||||
label={localized('Account Details')}
|
||||
path="/dashboard"
|
||||
source="Preferences"
|
||||
campaign="Dashboard"
|
||||
/>
|
||||
<div className="btn minor-width" onClick={logout}>
|
||||
{localized('Sign Out')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{stripePlan === 'Basic'
|
||||
? this._renderBasic()
|
||||
: this._renderPaidPlan(stripePlan, stripePlanEffective)}
|
||||
{identity && <IdentitySummary identity={identity} />}
|
||||
|
||||
{!stripePlan
|
||||
? this._renderNoIdentity()
|
||||
: stripePlan === 'Basic'
|
||||
? this._renderBasicPlan()
|
||||
: this._renderPaidPlan(stripePlan, identity.stripePlanEffective)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const ExploreMailspringSmall: React.FunctionComponent = () => (
|
||||
<div className="features">
|
||||
<ul>
|
||||
<li>
|
||||
<RetinaImg
|
||||
name="pro-feature-checkmark.png"
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{localized(`Rich contact profiles`)}
|
||||
</li>
|
||||
<li>
|
||||
<RetinaImg
|
||||
name="pro-feature-checkmark.png"
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{localized(`Follow-up reminders`)}
|
||||
</li>
|
||||
<li>
|
||||
<RetinaImg
|
||||
name="pro-feature-checkmark.png"
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{localized(`Read Receipts`)}
|
||||
</li>
|
||||
<li>
|
||||
<RetinaImg
|
||||
name="pro-feature-checkmark.png"
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{localized(`Link tracking`)}
|
||||
</li>
|
||||
<li>
|
||||
<RetinaImg
|
||||
name="pro-feature-checkmark.png"
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{localized(`Powerful template support`)}
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<RetinaImg
|
||||
name="pro-feature-checkmark.png"
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{localized(`Send Later`)}
|
||||
</li>
|
||||
<li>
|
||||
<RetinaImg
|
||||
name="pro-feature-checkmark.png"
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{localized(`Company overviews`)}
|
||||
</li>
|
||||
<li>
|
||||
<RetinaImg
|
||||
name="pro-feature-checkmark.png"
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{localized(`Snooze messages`)}
|
||||
</li>
|
||||
<li>
|
||||
<RetinaImg
|
||||
name="pro-feature-checkmark.png"
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{localized(`Mailbox insights`)}
|
||||
</li>
|
||||
<li>
|
||||
<RetinaImg
|
||||
name="pro-feature-checkmark.png"
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{localized(`... and much more!`)}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
|
||||
const ExploreMailspringPro: React.FunctionComponent = () => (
|
||||
<>
|
||||
<div className="feature-explore-title">{localized('Explore Mailspring Pro')}</div>
|
||||
<div className="feature-explore-grid">
|
||||
{ProTourFeatures.map(item => (
|
||||
<a key={item.title} className="feature" href={item.link}>
|
||||
<div className="popout">
|
||||
<RetinaImg name="thread-popout.png" mode={RetinaImg.Mode.ContentDark} />
|
||||
</div>
|
||||
<h3>
|
||||
<RetinaImg
|
||||
name={item.icon}
|
||||
style={{ paddingRight: 8 }}
|
||||
mode={RetinaImg.Mode.ContentDark}
|
||||
/>
|
||||
{item.title}
|
||||
</h3>
|
||||
<p>{item.text}</p>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
const IdentitySummary: React.FunctionComponent<{ identity: IIdentity }> = props => {
|
||||
const { firstName, lastName, emailAddress } = props.identity;
|
||||
const logout = () => Actions.logoutMailspringIdentity();
|
||||
return (
|
||||
<div className="row padded">
|
||||
<div className="identity-info">
|
||||
<RefreshButton />
|
||||
<div className="name">
|
||||
{firstName} {lastName}
|
||||
</div>
|
||||
<div className="email">{emailAddress}</div>
|
||||
<div className="identity-actions">
|
||||
<OpenIdentityPageButton
|
||||
label={localized('Account Details')}
|
||||
path="/dashboard"
|
||||
source="Preferences"
|
||||
campaign="Dashboard"
|
||||
/>
|
||||
<div className="btn minor-width" onClick={logout}>
|
||||
{localized('Sign Out')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PreferencesIdentity;
|
||||
|
|
|
@ -139,7 +139,7 @@
|
|||
}
|
||||
.feature-explore-grid {
|
||||
margin-top: 7px;
|
||||
width: 100%;
|
||||
margin-right: -20px;
|
||||
position: relative;
|
||||
|
||||
.feature {
|
||||
|
|
|
@ -31,17 +31,6 @@ export interface IIdentity {
|
|||
|
||||
export type IdentityAuthResponse = IIdentity | { skipped: true };
|
||||
|
||||
export const EMPTY_IDENTITY: IIdentity = {
|
||||
id: '',
|
||||
token: '',
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
emailAddress: '',
|
||||
stripePlan: 'basic',
|
||||
stripePlanEffective: '',
|
||||
featureUsage: {},
|
||||
};
|
||||
|
||||
export const EMPTY_FEATURE_USAGE = {
|
||||
featureLimitName: 'pro',
|
||||
period: 'monthly',
|
||||
|
@ -140,9 +129,10 @@ class _IdentityStore extends MailspringStore {
|
|||
* cache and set the token from the keychain.
|
||||
*/
|
||||
_onIdentityChanged = async () => {
|
||||
const next = Object.assign({}, AppEnv.config.get('identity') || {});
|
||||
next.token = await KeyManager.getPassword(KEYCHAIN_NAME);
|
||||
this._identity = next;
|
||||
const value = AppEnv.config.get('identity');
|
||||
this._identity = value
|
||||
? { ...value, token: await KeyManager.getPassword(KEYCHAIN_NAME) }
|
||||
: null;
|
||||
this.trigger();
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue