Home Manual Reference Source

App/Containers/LoginScreen.js

import React, {PropTypes} from 'react';
import {
  View,
  ScrollView,
  Text,
  TextInput,
  TouchableOpacity,
  Image,
  Keyboard,
  LayoutAnimation,
  Switch
} from 'react-native';
import { connect } from 'react-redux';
import Styles from './Styles/LoginScreenStyle';
import Actions from '../Actions/Creators';
import {Images, Metrics} from '../Themes';
import { Actions as NavigationActions } from 'react-native-router-flux';

// I18n
import I18n from '../I18n/I18n.js';

class LoginScreen extends React.Component {

  constructor (props) {
    super(props);
    this.state = {
      username: '',
      password: '',
      instanceName: '',
      host: '',
      port: '',
      visibleHeight: Metrics.screenHeight,
      topLogo: { width: Metrics.screenWidth },
      https: false
    };
    this.isAttempting = false;
  }

  componentWillReceiveProps (newProps) {
    this.forceUpdate();
    // Did the login attempt complete?
    if (this.isAttempting && !newProps.attempting && newProps.loginSuccess) {
      console.log(newProps);
      this.props.close();
    }
  }

  componentWillMount () {
    // Using keyboardWillShow/Hide looks 1,000 times better, but doesn't work on Android
    // TODO: Revisit this if Android begins to support - https://github.com/facebook/react-native/issues/3468
    this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this.keyboardDidShow);
    this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this.keyboardDidHide);
  }

  componentWillUnmount () {
    this.keyboardDidShowListener.remove();
    this.keyboardDidHideListener.remove();
  }

  keyboardDidShow = (e) => {
    // Animation types easeInEaseOut/linear/spring
    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
    let newSize = Metrics.screenHeight - e.endCoordinates.height;
    this.setState({
      visibleHeight: newSize,
      topLogo: {width: 100, height: 70}
    });
  };

  keyboardDidHide = (e) => {
    // Animation types easeInEaseOut/linear/spring
    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
    this.setState({
      visibleHeight: Metrics.screenHeight,
      topLogo: {width: Metrics.screenWidth}
    });
  };

  handlePressLogin = () => {
    const { username, password, instanceName, host, port, https } = this.state;
    this.isAttempting = true;
    // attempt a login - a saga is listening to pick it up from here.
    this.props.attemptLogin(username, password, instanceName, host, port, https );
  };

  handleChangeUsername = (text) => {
    this.setState({ username: text });
  };

  handleChangePassword = (text) => {
    this.setState({ password: text });
  };

  handleChangeInstanceName = (text) => {
    this.setState({ instanceName: text });
  };

  handleChangeHost = (text) => {
    this.setState({ host: text });
  };

  handleChangePort = (text) => {
    this.setState({ port: text });
  };

  handleChangeHttps = (value) => {
    this.setState({ https: value });
  };

  render () {
    const { username, password, instanceName, host, port, https } = this.state;
    const { attempting } = this.props;
    const editable = !attempting;
    const textInputStyle = editable ? Styles.textInput : Styles.textInputReadonly;
    return (
      <ScrollView contentContainerStyle={{justifyContent: 'center'}} style={[Styles.container, {height: this.state.visibleHeight}]}>
        <Image source={Images.logo} style={[Styles.topLogo, this.state.topLogo]} />
        <View style={Styles.form}>
          <View style={Styles.row}>
            <Text style={Styles.rowLabel}>{I18n.t('instanceName')}</Text>
            <TextInput
              ref='instanceName'
              autoCapitalize="none"
              style={textInputStyle}
              value={instanceName}
              editable={editable}
              keyboardType='default'
              returnKeyType='next'
              onChangeText={this.handleChangeInstanceName}
              underlineColorAndroid='transparent'
              onSubmitEditing={() => this.refs.instanceName.focus()}
              placeholder={I18n.t('instanceName')} />
          </View>

          <View style={Styles.row}>
            <Text style={Styles.rowLabel}>{I18n.t('host')}</Text>
            <TextInput
              ref='host'
              autoCapitalize="none"
              style={textInputStyle}
              value={host}
              editable={editable}
              keyboardType='default'
              returnKeyType='next'
              onChangeText={this.handleChangeHost}
              underlineColorAndroid='transparent'
              onSubmitEditing={() => this.refs.host.focus()}
              placeholder={I18n.t('host')} />
          </View>

          <View style={Styles.row}>
            <Text style={Styles.rowLabel}>{I18n.t('port')}</Text>
            <TextInput
              ref='port'
              autoCapitalize="none"
              style={textInputStyle}
              value={port}
              editable={editable}
              keyboardType='default'
              returnKeyType='next'
              onChangeText={this.handleChangePort}
              underlineColorAndroid='transparent'
              onSubmitEditing={() => this.refs.port.focus()}
              placeholder={I18n.t('port')} />
          </View>

          <View style={Styles.row}>
            <Text style={Styles.rowLabel}>{I18n.t('username')}</Text>
            <TextInput
              ref='username'
              autoCapitalize="none"
              style={textInputStyle}
              value={username}
              editable={editable}
              keyboardType='default'
              returnKeyType='next'
              onChangeText={this.handleChangeUsername}
              underlineColorAndroid='transparent'
              onSubmitEditing={() => this.refs.password.focus()}
              placeholder={I18n.t('username')} />
          </View>

          <View style={Styles.row}>
            <Text style={Styles.rowLabel}>{I18n.t('password')}</Text>
            <TextInput
              ref='password'
              autoCapitalize="none"
              style={textInputStyle}
              value={password}
              editable={editable}
              keyboardType='default'
              returnKeyType='go'
              secureTextEntry
              onChangeText={this.handleChangePassword}
              underlineColorAndroid='transparent'
              onSubmitEditing={this.handlePressLogin}
              placeholder={I18n.t('password')} />
          </View>

          <View style={Styles.row}>
            <Text style={Styles.rowLabel}>{I18n.t('https')}</Text>
            <Switch
              style={Styles.toggle}
              onValueChange={this.handleChangeHttps}
              value={https} />
          </View>

          <View style={[Styles.loginRow]}>
            <TouchableOpacity style={Styles.loginButtonWrapper} onPress={this.handlePressLogin}>
              <View style={Styles.loginButton}>
                <Text style={Styles.loginText}>{I18n.t('signIn')}</Text>
              </View>
            </TouchableOpacity>
            <TouchableOpacity style={Styles.loginButtonWrapper} onPress={this.props.close}>
              <View style={Styles.loginButton}>
                <Text style={Styles.loginText}>{I18n.t('cancel')}</Text>
              </View>
            </TouchableOpacity>
          </View>
        </View>

      </ScrollView>
    );
  }

}

LoginScreen.propTypes = {
  dispatch: PropTypes.func,
  attempting: PropTypes.bool,
  close: PropTypes.func,
  attemptLogin: PropTypes.func,
  loginFail: PropTypes.bool,
  loginSuccess: PropTypes.bool
};

const mapStateToProps = (state) => {
  return {
    attempting: state.login.attempting,
    username: state.login.username,
    jobs: state.jobs.data,
    loginSuccess: state.login.loginSuccess,
    loginFail: state.login.fail
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    close: NavigationActions.pop,
    attemptLogin: (username, password, instanceName, host, port, https) => dispatch(Actions.attemptLogin(username, password, instanceName, host, port, https))
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(LoginScreen);