summaryrefslogtreecommitdiffhomepage
path: root/app/components/Login.js
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2018-06-01 16:13:10 +0200
committerAndrej Mihajlov <and@mullvad.net>2018-06-05 12:11:55 +0200
commitca2f6fbfcad7b73d4ea63ef46cb1cab943ec9087 (patch)
treeb1f7754eb50896ab3681e35fa4e08be642b940c9 /app/components/Login.js
parent5852c980980de53e00d76a0bdb4b41bf5c0f5b39 (diff)
downloadmullvadvpn-ca2f6fbfcad7b73d4ea63ef46cb1cab943ec9087.tar.xz
mullvadvpn-ca2f6fbfcad7b73d4ea63ef46cb1cab943ec9087.zip
Add formatted source code
Diffstat (limited to 'app/components/Login.js')
-rw-r--r--app/components/Login.js320
1 files changed, 183 insertions, 137 deletions
diff --git a/app/components/Login.js b/app/components/Login.js
index b711f089b5..3100cc54f0 100644
--- a/app/components/Login.js
+++ b/app/components/Login.js
@@ -16,7 +16,7 @@ import type { AccountToken } from '../lib/ipc-facade';
export type LoginPropTypes = {
account: AccountReduxState,
onLogin: (accountToken: AccountToken) => void,
- onSettings: ?(() => void),
+ onSettings: ?() => void,
onFirstChangeAfterFailure: () => void,
onExternalLink: (type: string) => void,
onAccountTokenChange: (accountToken: AccountToken) => void,
@@ -48,14 +48,18 @@ export default class Login extends Component<LoginPropTypes, State> {
constructor(props: LoginPropTypes) {
super(props);
- if(props.account.status === 'failed') {
+ if (props.account.status === 'failed') {
this.state.notifyOnFirstChangeAfterFailure = true;
}
this.state.footerAnimationStyle = Styles.createAnimatedViewStyle({
- transform: [{translateY: this.state.animatedFooterValue }]
+ transform: [{ translateY: this.state.animatedFooterValue }],
});
this.state.loginButtonAnimationStyle = Styles.createAnimatedViewStyle({
- backgroundColor: Animated.interpolate(this.state.animatedLoginButtonValue, [0.0, 1.0], [colors.white, colors.green]),
+ backgroundColor: Animated.interpolate(
+ this.state.animatedLoginButtonValue,
+ [0.0, 1.0],
+ [colors.white, colors.green],
+ ),
});
}
@@ -63,7 +67,7 @@ export default class Login extends Component<LoginPropTypes, State> {
const prev = this.props.account || {};
const next = nextProps.account || {};
- if(prev.status !== next.status && next.status === 'failed') {
+ if (prev.status !== next.status && next.status === 'failed') {
this.setState({ notifyOnFirstChangeAfterFailure: true });
}
@@ -73,36 +77,38 @@ export default class Login extends Component<LoginPropTypes, State> {
render() {
return (
<Layout>
- <Header showSettings={ true } onSettings={ this.props.onSettings } />
+ <Header showSettings={true} onSettings={this.props.onSettings} />
<Container>
<View style={styles.login_form}>
- { this._getStatusIcon() }
- <Text style={styles.title}>{ this._formTitle() }</Text>
+ {this._getStatusIcon()}
+ <Text style={styles.title}>{this._formTitle()}</Text>
- {this._shouldShowLoginForm() && <View>
- { this._createLoginForm() }
- </View>}
+ {this._shouldShowLoginForm() && <View>{this._createLoginForm()}</View>}
</View>
- <Animated.View onLayout={this._onFooterLayout} style={[styles.login_footer, this.state.footerAnimationStyle]} testName={'footerVisibility ' + this._shouldShowFooter(this.props).toString()}>
- { this._createFooter() }
+ <Animated.View
+ onLayout={this._onFooterLayout}
+ style={[styles.login_footer, this.state.footerAnimationStyle]}
+ testName={'footerVisibility ' + this._shouldShowFooter(this.props).toString()}>
+ {this._createFooter()}
</Animated.View>
</Container>
</Layout>
);
}
- _onCreateAccount = () => this.props.onExternalLink('createAccount')
+ _onCreateAccount = () => this.props.onExternalLink('createAccount');
- _onFocus = () => this.setState({ isActive: true }, () => {
- this._animate(this.props);
- })
+ _onFocus = () =>
+ this.setState({ isActive: true }, () => {
+ this._animate(this.props);
+ });
_onBlur = (e) => {
const relatedTarget = e.relatedTarget;
// restore focus if click happened within dropdown
- if(relatedTarget) {
+ if (relatedTarget) {
e.target.focus();
return;
}
@@ -110,7 +116,7 @@ export default class Login extends Component<LoginPropTypes, State> {
this.setState({ isActive: false }, () => {
this._animate(this.props);
});
- }
+ };
_animate = (props: LoginPropTypes) => {
if (this.state.animation) {
@@ -119,95 +125,103 @@ export default class Login extends Component<LoginPropTypes, State> {
const accountToken = props.account.accountToken || [];
const footerPosition = this._shouldShowFooter(props) ? 0 : this.state.footerHeight;
- const loginButtonValue = (accountToken.length) > 0 ? 1 : 0;
- this._setAnimation(this._getFooterAnimation(footerPosition), this._getLoginButtonAnimation(loginButtonValue));
- }
+ const loginButtonValue = accountToken.length > 0 ? 1 : 0;
+ this._setAnimation(
+ this._getFooterAnimation(footerPosition),
+ this._getLoginButtonAnimation(loginButtonValue),
+ );
+ };
- _setAnimation = (footerAnimation: Animated.CompositeAnimation, loginButtonAnimation: Animated.CompositeAnimation) => {
- let compositeAnimation = Animated.parallel([ footerAnimation, loginButtonAnimation]);
- this.setState({animation: compositeAnimation}, () => {
- compositeAnimation.start(() => this.setState({
- animation: null
- }));
+ _setAnimation = (
+ footerAnimation: Animated.CompositeAnimation,
+ loginButtonAnimation: Animated.CompositeAnimation,
+ ) => {
+ let compositeAnimation = Animated.parallel([footerAnimation, loginButtonAnimation]);
+ this.setState({ animation: compositeAnimation }, () => {
+ compositeAnimation.start(() =>
+ this.setState({
+ animation: null,
+ }),
+ );
});
- }
+ };
_onLogin = () => {
const accountToken = this.props.account.accountToken;
- if(accountToken && accountToken.length > 0) {
+ if (accountToken && accountToken.length > 0) {
this.props.onLogin(accountToken);
}
- }
+ };
_onInputChange = (value: string) => {
// notify delegate on first change after login failure
- if(this.state.notifyOnFirstChangeAfterFailure) {
+ if (this.state.notifyOnFirstChangeAfterFailure) {
this.setState({ notifyOnFirstChangeAfterFailure: false });
this.props.onFirstChangeAfterFailure();
}
this.props.onAccountTokenChange(value);
- }
+ };
_formTitle() {
- switch(this.props.account.status) {
- case 'logging in':
- return 'Logging in...';
- case 'failed':
- return 'Login failed';
- case 'ok':
- return 'Login successful';
- default:
- return 'Login';
+ switch (this.props.account.status) {
+ case 'logging in':
+ return 'Logging in...';
+ case 'failed':
+ return 'Login failed';
+ case 'ok':
+ return 'Login successful';
+ default:
+ return 'Login';
}
}
_formSubtitle() {
const { status, error } = this.props.account;
- switch(status) {
- case 'failed':
- return (error && error.message) || 'Unknown error';
- case 'logging in':
- return 'Checking account number';
- default:
- return 'Enter your account number';
+ switch (status) {
+ case 'failed':
+ return (error && error.message) || 'Unknown error';
+ case 'logging in':
+ return 'Checking account number';
+ default:
+ return 'Enter your account number';
}
}
_getStatusIcon() {
const statusIconPath = this._getStatusIconPath();
- return <View style={ styles.status_icon}>
- { statusIconPath ?
- <Img source={ statusIconPath } height={48} width={48} alt="" /> :
- null }
- </View>;
+ return (
+ <View style={styles.status_icon}>
+ {statusIconPath ? <Img source={statusIconPath} height={48} width={48} alt="" /> : null}
+ </View>
+ );
}
_getStatusIconPath(): ?string {
- switch(this.props.account.status) {
- case 'logging in':
- return 'icon-spinner';
- case 'failed':
- return 'icon-fail';
- case 'ok':
- return 'icon-success';
- default:
- return undefined;
+ switch (this.props.account.status) {
+ case 'logging in':
+ return 'icon-spinner';
+ case 'failed':
+ return 'icon-fail';
+ case 'ok':
+ return 'icon-success';
+ default:
+ return undefined;
}
}
_accountInputGroupStyles(): Array<Object> {
const classes = [styles.account_input_group];
- if(this.state.isActive) {
+ if (this.state.isActive) {
classes.push(styles.account_input_group__active);
}
- switch(this.props.account.status) {
- case 'logging in':
- classes.push(styles.account_input_group__inactive);
- break;
- case 'failed':
- classes.push(styles.account_input_group__error);
- break;
+ switch (this.props.account.status) {
+ case 'logging in':
+ classes.push(styles.account_input_group__inactive);
+ break;
+ case 'failed':
+ classes.push(styles.account_input_group__error);
+ break;
}
return classes;
@@ -217,7 +231,7 @@ export default class Login extends Component<LoginPropTypes, State> {
const { status } = this.props.account;
const classes = [styles.input_button];
- if(status === 'logging in') {
+ if (status === 'logging in') {
classes.push(styles.input_button__invisible);
}
@@ -230,11 +244,11 @@ export default class Login extends Component<LoginPropTypes, State> {
const { accountToken, status } = this.props.account;
const classes = [styles.input_arrow];
- if(accountToken && accountToken.length > 0) {
+ if (accountToken && accountToken.length > 0) {
classes.push(styles.input_arrow__active);
}
- if(status === 'logging in') {
+ if (status === 'logging in') {
classes.push(styles.input_arrow__invisible);
}
@@ -247,9 +261,11 @@ export default class Login extends Component<LoginPropTypes, State> {
}
_shouldShowAccountHistory(props: LoginPropTypes) {
- return this._shouldEnableAccountInput(props) &&
+ return (
+ this._shouldEnableAccountInput(props) &&
this.state.isActive &&
- props.account.accountHistory.length > 0;
+ props.account.accountHistory.length > 0
+ );
}
_shouldShowLoginForm() {
@@ -261,7 +277,7 @@ export default class Login extends Component<LoginPropTypes, State> {
return (status === 'none' || status === 'failed') && !this._shouldShowAccountHistory(props);
}
- _getFooterAnimation(toValue: number){
+ _getFooterAnimation(toValue: number) {
return Animated.timing(this.state.animatedFooterValue, {
toValue: toValue,
easing: Animated.Easing.InOut(),
@@ -271,10 +287,10 @@ export default class Login extends Component<LoginPropTypes, State> {
}
_onFooterLayout = (layout) => {
- this.setState({footerHeight: layout.height});
- }
+ this.setState({ footerHeight: layout.height });
+ };
- _getLoginButtonAnimation(toValue: number){
+ _getLoginButtonAnimation(toValue: number) {
return Animated.timing(this.state.animatedLoginButtonValue, {
toValue: toValue,
easing: Animated.Easing.Linear(),
@@ -286,7 +302,7 @@ export default class Login extends Component<LoginPropTypes, State> {
_onSelectAccountFromHistory = (accountToken) => {
this.props.onAccountTokenChange(accountToken);
this.props.onLogin(accountToken);
- }
+ };
_createLoginForm() {
const { accountHistory, accountToken } = this.props.account;
@@ -295,50 +311,68 @@ export default class Login extends Component<LoginPropTypes, State> {
// do not refactor this into instance method,
// it has to be new function each time to be called on each render
const autoFocusOnFailure = (input) => {
- if(this.props.account.status === 'failed' && input) {
+ if (this.props.account.status === 'failed' && input) {
input.focus();
}
};
- return <View>
- <Text style={ styles.subtitle }>{ this._formSubtitle() }</Text>
- <View style={ this._accountInputGroupStyles() }>
- <View style={ styles.account_input_backdrop}>
- <AccountInput style={styles.account_input_textfield}
- type="text"
- placeholder="0000 0000 0000 0000"
- placeholderTextColor={colors.blue40}
- onFocus={ this._onFocus }
- onBlur={ this._onBlur }
- onChange={ this._onInputChange }
- onEnter={ this._onLogin }
- value={ accountToken || '' }
- disabled={ !this._shouldEnableAccountInput(this.props) }
- autoFocus={ true }
- ref={ autoFocusOnFailure }
- testName='AccountInput'/>
- <Animated.View style={this._accountInputButtonStyles()} onPress={ this._onLogin } testName='account-input-button'>
- <Img style={this._accountInputArrowStyles()} source='icon-arrow' height={16} width={24} tintColor='currentColor' />
- </Animated.View>
+ return (
+ <View>
+ <Text style={styles.subtitle}>{this._formSubtitle()}</Text>
+ <View style={this._accountInputGroupStyles()}>
+ <View style={styles.account_input_backdrop}>
+ <AccountInput
+ style={styles.account_input_textfield}
+ type="text"
+ placeholder="0000 0000 0000 0000"
+ placeholderTextColor={colors.blue40}
+ onFocus={this._onFocus}
+ onBlur={this._onBlur}
+ onChange={this._onInputChange}
+ onEnter={this._onLogin}
+ value={accountToken || ''}
+ disabled={!this._shouldEnableAccountInput(this.props)}
+ autoFocus={true}
+ ref={autoFocusOnFailure}
+ testName="AccountInput"
+ />
+ <Animated.View
+ style={this._accountInputButtonStyles()}
+ onPress={this._onLogin}
+ testName="account-input-button">
+ <Img
+ style={this._accountInputArrowStyles()}
+ source="icon-arrow"
+ height={16}
+ width={24}
+ tintColor="currentColor"
+ />
+ </Animated.View>
+ </View>
+ <Accordion height={this._shouldShowAccountHistory(this.props) ? 'auto' : 0}>
+ {
+ <AccountDropdown
+ items={accountHistory.slice().reverse()}
+ onSelect={this._onSelectAccountFromHistory}
+ onRemove={this.props.onRemoveAccountTokenFromHistory}
+ />
+ }
+ </Accordion>
</View>
- <Accordion height={ this._shouldShowAccountHistory(this.props) ? 'auto' : 0 }>
- { <AccountDropdown
- items={ accountHistory.slice().reverse() }
- onSelect={ this._onSelectAccountFromHistory }
- onRemove={ this.props.onRemoveAccountTokenFromHistory } /> }
- </Accordion>
</View>
- </View>;
+ );
}
_createFooter() {
- return <View>
- <Text style={ styles.login_footer__prompt}>{ 'Don\'t have an account number?' }</Text>
- <BlueButton onPress={ this._onCreateAccount }>
- <Label>Create account</Label>
- <Img source='icon-extLink' height={16} width={16} />
- </BlueButton>
- </View>;
+ return (
+ <View>
+ <Text style={styles.login_footer__prompt}>{"Don't have an account number?"}</Text>
+ <BlueButton onPress={this._onCreateAccount}>
+ <Label>Create account</Label>
+ <Img source="icon-extLink" height={16} width={16} />
+ </BlueButton>
+ </View>
+ );
}
}
@@ -353,13 +387,15 @@ class AccountDropdown extends React.Component<AccountDropdownProps> {
const uniqueItems = [...new Set(this.props.items)];
return (
<View>
- { uniqueItems.map(token => (
- <AccountDropdownItem key={ token }
- value={ token }
- label={ formatAccount(token) }
- onSelect={ this.props.onSelect }
- onRemove={ this.props.onRemove } />
- )) }
+ {uniqueItems.map((token) => (
+ <AccountDropdownItem
+ key={token}
+ value={token}
+ label={formatAccount(token)}
+ onSelect={this.props.onSelect}
+ onRemove={this.props.onRemove}
+ />
+ ))}
</View>
);
}
@@ -374,19 +410,29 @@ type AccountDropdownItemProps = {
class AccountDropdownItem extends React.Component<AccountDropdownItemProps> {
render() {
- return (<View>
- <View style={ styles.account_dropdown__spacer }/>
- <CellButton style={ styles.account_dropdown__item } cellHoverStyle={ styles.account_dropdown__item_hover }>
- <Label style={styles.account_dropdown__label} cellHoverStyle={ styles.account_dropdown__label_hover } onPress={ () => this.props.onSelect(this.props.value) }>
- { this.props.label }
- </Label>
- <Img style={styles.account_dropdown__remove}
- cellHoverStyle={ styles.account_dropdown__remove_cell_hover }
- hoverStyle={ styles.account_dropdown__remove_hover }
- source='icon-close-sml'
- height={16} width={16}
- onPress={ () => this.props.onRemove(this.props.value) }/>
- </CellButton>
- </View>);
+ return (
+ <View>
+ <View style={styles.account_dropdown__spacer} />
+ <CellButton
+ style={styles.account_dropdown__item}
+ cellHoverStyle={styles.account_dropdown__item_hover}>
+ <Label
+ style={styles.account_dropdown__label}
+ cellHoverStyle={styles.account_dropdown__label_hover}
+ onPress={() => this.props.onSelect(this.props.value)}>
+ {this.props.label}
+ </Label>
+ <Img
+ style={styles.account_dropdown__remove}
+ cellHoverStyle={styles.account_dropdown__remove_cell_hover}
+ hoverStyle={styles.account_dropdown__remove_hover}
+ source="icon-close-sml"
+ height={16}
+ width={16}
+ onPress={() => this.props.onRemove(this.props.value)}
+ />
+ </CellButton>
+ </View>
+ );
}
}