mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-11-14 21:57:55 +08:00
7ca04c579e
- This fixes #1354 and #1235 - This issue was caused because the account details preferences component was keeping as state all of the account object fields. `setState` works like `extend`, so when the account changed, state was set to the new set of account fields, but the old values were only removed if they were overriden, and remained the same if the field did not exist in the new state object. Specifically, when a new account was added, setState was called with `{..., defaultAlias: undefined}` which did /not/ remove the the defaultAlias from the previous state. - Switched to managing state with a top level key `account`
168 lines
4.7 KiB
JavaScript
168 lines
4.7 KiB
JavaScript
import _ from 'underscore';
|
|
import React, {Component, PropTypes} from 'react';
|
|
import {EditableList, NewsletterSignup} from 'nylas-component-kit';
|
|
import {RegExpUtils} from 'nylas-exports';
|
|
|
|
class PreferencesAccountDetails extends Component {
|
|
|
|
static propTypes = {
|
|
account: PropTypes.object,
|
|
onAccountUpdated: PropTypes.func.isRequired,
|
|
};
|
|
|
|
constructor(props) {
|
|
super(props);
|
|
this.state = {account: _.clone(props.account)};
|
|
}
|
|
|
|
componentWillReceiveProps(nextProps) {
|
|
this.setState({account: _.clone(nextProps.account)});
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
this._saveChanges();
|
|
}
|
|
|
|
|
|
// Helpers
|
|
|
|
/**
|
|
* @private Will transform any user input into alias format.
|
|
* It will ignore any text after an email, if one is entered.
|
|
* If no email is entered, it will use the account's email.
|
|
* It will treat the text before the email as the name for the alias.
|
|
* If no name is entered, it will use the account's name value.
|
|
* @param {string} str - The string the user entered on the alias input
|
|
* @param {object} [account=this.props.account] - The account object
|
|
*/
|
|
_makeAlias(str, account = this.props.account) {
|
|
const emailRegex = RegExpUtils.emailRegex();
|
|
const match = emailRegex.exec(str);
|
|
if (!match) {
|
|
return `${str || account.name} <${account.emailAddress}>`;
|
|
}
|
|
const email = match[0];
|
|
let name = str.slice(0, Math.max(0, match.index - 1));
|
|
if (!name) {
|
|
name = account.name || 'No name provided';
|
|
}
|
|
name = name.trim();
|
|
// TODO Sanitize the name string
|
|
return `${name} <${email}>`;
|
|
}
|
|
|
|
_saveChanges = ()=> {
|
|
this.props.onAccountUpdated(this.props.account, this.state.account);
|
|
};
|
|
|
|
_setState = (updates, callback = ()=>{})=> {
|
|
const updated = _.extend({}, this.state.account, updates);
|
|
this.setState({account: updated}, callback);
|
|
};
|
|
|
|
_setStateAndSave = (updates)=> {
|
|
this._setState(updates, ()=> {
|
|
this._saveChanges();
|
|
});
|
|
};
|
|
|
|
|
|
// Handlers
|
|
|
|
_onAccountLabelUpdated = (event)=> {
|
|
this._setState({label: event.target.value});
|
|
};
|
|
|
|
_onAccountAliasCreated = (newAlias)=> {
|
|
const coercedAlias = this._makeAlias(newAlias);
|
|
const aliases = this.state.aliases.concat([coercedAlias]);
|
|
this._setStateAndSave({aliases})
|
|
};
|
|
|
|
_onAccountAliasUpdated = (newAlias, alias, idx)=> {
|
|
const coercedAlias = this._makeAlias(newAlias);
|
|
const aliases = this.state.aliases.slice();
|
|
let defaultAlias = this.state.defaultAlias;
|
|
if (defaultAlias === alias) {
|
|
defaultAlias = coercedAlias;
|
|
}
|
|
aliases[idx] = coercedAlias;
|
|
this._setStateAndSave({aliases, defaultAlias});
|
|
};
|
|
|
|
_onAccountAliasRemoved = (alias, idx)=> {
|
|
const aliases = this.state.aliases.slice();
|
|
let defaultAlias = this.state.defaultAlias;
|
|
if (defaultAlias === alias) {
|
|
defaultAlias = null;
|
|
}
|
|
aliases.splice(idx, 1);
|
|
this._setStateAndSave({aliases, defaultAlias});
|
|
};
|
|
|
|
_onDefaultAliasSelected = (event)=> {
|
|
const defaultAlias = event.target.value === 'None' ? null : event.target.value;
|
|
this._setStateAndSave({defaultAlias});
|
|
};
|
|
|
|
|
|
// Renderers
|
|
|
|
_renderDefaultAliasSelector(account) {
|
|
const aliases = account.aliases;
|
|
const defaultAlias = account.defaultAlias || 'None';
|
|
if (aliases.length > 0) {
|
|
return (
|
|
<div className="default-alias-selector">
|
|
<span>Default alias: </span>
|
|
<select value={defaultAlias} onChange={this._onDefaultAliasSelected}>
|
|
<option>None</option>
|
|
{aliases.map((alias, idx)=> <option key={`alias-${idx}`} value={alias}>{alias}</option>)}
|
|
</select>
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
|
|
render() {
|
|
const {account} = this.state;
|
|
const aliasPlaceholder = this._makeAlias(
|
|
`alias@${account.emailAddress.split('@')[1]}`
|
|
);
|
|
|
|
return (
|
|
<div className="account-details">
|
|
<h3>Account Label</h3>
|
|
<input
|
|
type="text"
|
|
value={account.label}
|
|
onBlur={this._saveChanges}
|
|
onChange={this._onAccountLabelUpdated} />
|
|
|
|
<h3>Aliases</h3>
|
|
|
|
<div className="platform-note">
|
|
You may need to configure aliases with your
|
|
mail provider (Outlook, Gmail) before using them.
|
|
</div>
|
|
|
|
<EditableList
|
|
showEditIcon
|
|
items={account.aliases}
|
|
createInputProps={{placeholder: aliasPlaceholder}}
|
|
onItemCreated={this._onAccountAliasCreated}
|
|
onItemEdited={this._onAccountAliasUpdated}
|
|
onDeleteItem={this._onAccountAliasRemoved} />
|
|
|
|
{this._renderDefaultAliasSelector(account)}
|
|
|
|
<div className="newsletter">
|
|
<NewsletterSignup emailAddress={account.emailAddress} name={account.name} />
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
}
|
|
|
|
export default PreferencesAccountDetails;
|