From 125b880760897331393ed2acc4c2b1a41b84fa19 Mon Sep 17 00:00:00 2001
From: gilmarsquinelato <gilmarsquinelato@gmail.com>
Date: Tue, 7 Nov 2017 14:28:02 -0200
Subject: [PATCH] Register user (#44)

* Added feature to register a new user

* login after register working

* Removed username from register and placed on a new view

* loading indicator on username submit

* register/username logo layout issue

* - login and register background white

* - logo removed from logo and register
---
 app/actions/actionsTypes.js           |  12 +-
 app/actions/login.js                  |  40 ++++++
 app/containers/Routes.js              |  20 +--
 app/containers/routes/AuthRoutes.js   |   9 +-
 app/containers/routes/PublicRoutes.js |   7 +
 app/images/logo_with_text.png         | Bin 0 -> 27580 bytes
 app/lib/rocketchat.js                 |  22 +++
 app/presentation/KeyboardView.js      |  20 ++-
 app/presentation/Loading.js           |  77 ++++++++++
 app/reducers/login.js                 |  41 +++++-
 app/sagas/login.js                    |  71 ++++++++--
 app/sagas/selectServer.js             |   2 +-
 app/views/CreateChannelView.js        |  99 ++++++-------
 app/views/LoginView.js                |  38 ++---
 app/views/NewServerView.js            |   8 +-
 app/views/RegisterView.js             | 194 ++++++++++++++++++++++++++
 app/views/RoomView.js                 |   2 +-
 app/views/Styles.js                   |  36 ++---
 package.json                          |   1 +
 yarn.lock                             |  12 +-
 20 files changed, 580 insertions(+), 131 deletions(-)
 create mode 100644 app/images/logo_with_text.png
 create mode 100644 app/presentation/Loading.js
 create mode 100644 app/views/RegisterView.js

diff --git a/app/actions/actionsTypes.js b/app/actions/actionsTypes.js
index ef66104a6..308c4baa6 100644
--- a/app/actions/actionsTypes.js
+++ b/app/actions/actionsTypes.js
@@ -9,7 +9,17 @@ function createRequestTypes(base, types = defaultTypes) {
 }
 
 // Login events
-export const LOGIN = createRequestTypes('LOGIN', [...defaultTypes, 'SET_TOKEN', 'SUBMIT']);
+export const LOGIN = createRequestTypes('LOGIN', [
+	...defaultTypes,
+	'SET_TOKEN',
+	'SUBMIT',
+	'REGISTER_SUBMIT',
+	'REGISTER_REQUEST',
+	'REGISTER_SUCCESS',
+	'SET_USERNAME_SUBMIT',
+	'SET_USERNAME_REQUEST',
+	'SET_USERNAME_SUCCESS'
+]);
 export const ROOMS = createRequestTypes('ROOMS');
 export const APP = createRequestTypes('APP', ['READY', 'INIT']);
 export const MESSAGES = createRequestTypes('MESSAGES');
diff --git a/app/actions/login.js b/app/actions/login.js
index 7969c8090..1a8f753e8 100644
--- a/app/actions/login.js
+++ b/app/actions/login.js
@@ -13,6 +13,46 @@ export function loginRequest(credentials) {
 	};
 }
 
+
+export function registerSubmit(credentials) {
+	return {
+		type: types.LOGIN.REGISTER_SUBMIT,
+		credentials
+	};
+}
+export function registerRequest(credentials) {
+	return {
+		type: types.LOGIN.REGISTER_REQUEST,
+		credentials
+	};
+}
+export function registerSuccess(credentials) {
+	return {
+		type: types.LOGIN.REGISTER_SUCCESS,
+		credentials
+	};
+}
+
+export function setUsernameSubmit(credentials) {
+	return {
+		type: types.LOGIN.SET_USERNAME_SUBMIT,
+		credentials
+	};
+}
+
+export function setUsernameRequest(credentials) {
+	return {
+		type: types.LOGIN.SET_USERNAME_REQUEST,
+		credentials
+	};
+}
+
+export function setUsernameSuccess() {
+	return {
+		type: types.LOGIN.SET_USERNAME_SUCCESS
+	};
+}
+
 export function loginSuccess(user) {
 	return {
 		type: types.LOGIN.SUCCESS,
diff --git a/app/containers/Routes.js b/app/containers/Routes.js
index 485dd389d..83268096c 100644
--- a/app/containers/Routes.js
+++ b/app/containers/Routes.js
@@ -1,15 +1,12 @@
 import PropTypes from 'prop-types';
 import React from 'react';
-import { View, Image } from 'react-native';
 import { bindActionCreators } from 'redux';
 import { connect } from 'react-redux';
-import * as Animatable from 'react-native-animatable';
 import { appInit } from '../actions';
 
-import styles from '../views/Styles';
-
 import AuthRoutes from './routes/AuthRoutes';
 import PublicRoutes from './routes/PublicRoutes';
+import Loading from '../presentation/Loading';
 
 @connect(
 	state => ({
@@ -34,21 +31,10 @@ export default class Routes extends React.Component {
 		const { login, app } = this.props;
 
 		if (app.starting) {
-			return (
-				<View style={styles.logoContainer}>
-					<Animatable.Text
-						animation='pulse'
-						easing='ease-out'
-						iterationCount='infinite'
-						style={{ textAlign: 'center' }}
-					>
-						<Image style={styles.logo} source={require('../images/logo.png')} />
-					</Animatable.Text>
-				</View>
-			);
+			return (<Loading />);
 		}
 
-		if ((login.token && !login.failure) || app.ready) {
+		if ((login.token && !login.failure && !login.isRegistering) || app.ready) {
 			return (<AuthRoutes />);
 		}
 
diff --git a/app/containers/routes/AuthRoutes.js b/app/containers/routes/AuthRoutes.js
index 6bef85455..2c1a9f35e 100644
--- a/app/containers/routes/AuthRoutes.js
+++ b/app/containers/routes/AuthRoutes.js
@@ -1,7 +1,5 @@
 import React from 'react';
-import { Button } from 'react-native';
-import { StackNavigator, DrawerNavigator, NavigationActions } from 'react-navigation';
-// import { Platform } from 'react-native';
+import { StackNavigator, DrawerNavigator, NavigationActions, HeaderBackButton } from 'react-navigation';
 
 import Sidebar from '../../containers/Sidebar';
 import DrawerMenuButton from '../../presentation/DrawerMenuButton';
@@ -39,7 +37,10 @@ const AuthRoutes = StackNavigator(
 				return {
 					title: navigation.state.params.title || 'Room',
 					headerLeft: (
-						<Button title={'Back'} onPress={() => backToScreen(navigation, 'RoomsList')} />
+						<HeaderBackButton
+							title={'Back'}
+							onPress={() => backToScreen(navigation, 'RoomsList')}
+						/>
 					)
 					// [drawerIconPosition]: (<DrawerMenuButton navigation={navigation} />)÷
 				};
diff --git a/app/containers/routes/PublicRoutes.js b/app/containers/routes/PublicRoutes.js
index 3cf851f5c..a99583cd2 100644
--- a/app/containers/routes/PublicRoutes.js
+++ b/app/containers/routes/PublicRoutes.js
@@ -6,6 +6,7 @@ import Icon from 'react-native-vector-icons/FontAwesome';
 import ListServerView from '../../views/ListServerView';
 import NewServerView from '../../views/NewServerView';
 import LoginView from '../../views/LoginView';
+import RegisterView from '../../views/RegisterView';
 
 const PublicRoutes = StackNavigator(
 	{
@@ -36,6 +37,12 @@ const PublicRoutes = StackNavigator(
 			navigationOptions: {
 				title: 'Login'
 			}
+		},
+		Register: {
+			screen: RegisterView,
+			navigationOptions: {
+				title: 'Register'
+			}
 		}
 	},
 	{
diff --git a/app/images/logo_with_text.png b/app/images/logo_with_text.png
new file mode 100644
index 0000000000000000000000000000000000000000..623349a06ad0f2735cb64e6601481882ff4aa153
GIT binary patch
literal 27580
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
P@i&O7wn~MPb;$n!1gNfk

literal 0
HcmV?d00001

diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js
index 71ddb447d..352eb00bb 100644
--- a/app/lib/rocketchat.js
+++ b/app/lib/rocketchat.js
@@ -122,6 +122,28 @@ const RocketChat = {
 		});
 	},
 
+	register({ credentials }) {
+		return new Promise((resolve, reject) => {
+			Meteor.call('registerUser', credentials, (err, userId) => {
+				if (err) {
+					reject(err);
+				}
+				resolve(userId);
+			});
+		});
+	},
+
+	setUsername({ credentials }) {
+		return new Promise((resolve, reject) => {
+			Meteor.call('setUsername', credentials.username, (err, result) => {
+				if (err) {
+					reject(err);
+				}
+				resolve(result);
+			});
+		});
+	},
+
 	loginWithPassword({ username, password, code }, callback) {
 		let params = {};
 		const state = reduxStore.getState();
diff --git a/app/presentation/KeyboardView.js b/app/presentation/KeyboardView.js
index 3a6ea5f66..f3e29d9c2 100644
--- a/app/presentation/KeyboardView.js
+++ b/app/presentation/KeyboardView.js
@@ -1,11 +1,14 @@
 import React from 'react';
 import PropTypes from 'prop-types';
-import { KeyboardAvoidingView } from 'react-native';
+import { ViewPropTypes } from 'react-native';
+import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
 
 export default class KeyboardView extends React.PureComponent {
 	static propTypes = {
-		style: KeyboardAvoidingView.propTypes.style,
+		style: ViewPropTypes.style,
+		contentContainerStyle: ViewPropTypes.style,
 		keyboardVerticalOffset: PropTypes.number,
+		scrollEnabled: PropTypes.bool,
 		children: PropTypes.oneOfType([
 			PropTypes.arrayOf(PropTypes.node),
 			PropTypes.node
@@ -14,9 +17,18 @@ export default class KeyboardView extends React.PureComponent {
 
 	render() {
 		return (
-			<KeyboardAvoidingView style={this.props.style} behavior='padding' keyboardVerticalOffset={this.props.keyboardVerticalOffset}>
+			<KeyboardAwareScrollView
+				keyboardDismissMode='interactive'
+				keyboardShouldPersistTaps='always'
+				style={this.props.style}
+				contentContainerStyle={this.props.contentContainerStyle}
+				scrollEnabled={this.props.scrollEnabled}
+				alwaysBounceVertical={false}
+				extraHeight={this.props.keyboardVerticalOffset}
+				behavior='position'
+			>
 				{this.props.children}
-			</KeyboardAvoidingView>
+			</KeyboardAwareScrollView>
 		);
 	}
 }
diff --git a/app/presentation/Loading.js b/app/presentation/Loading.js
new file mode 100644
index 000000000..ed92f1192
--- /dev/null
+++ b/app/presentation/Loading.js
@@ -0,0 +1,77 @@
+import React, { Component } from 'react';
+import { View, StyleSheet, Animated, Dimensions } from 'react-native';
+
+const logo = require('../images/logo.png');
+
+
+const styles = StyleSheet.create({
+	container: {
+		flex: 1,
+		width: '100%',
+		alignItems: 'center',
+		justifyContent: 'center'
+	},
+	background: {
+		width: Dimensions.get('window').width,
+		height: Dimensions.get('window').height,
+		alignItems: 'center',
+		justifyContent: 'center'
+	},
+	logo: {
+		width: Dimensions.get('window').width - 100,
+		height: Dimensions.get('window').width - 100,
+		resizeMode: 'contain'
+	}
+});
+
+export default class Loading extends Component {
+	constructor(props) {
+		super(props);
+
+		this.scale = new Animated.Value(1.0);
+	}
+
+	componentDidMount() {
+		requestAnimationFrame(() => {
+			this.animate();
+		});
+	}
+
+	animate = () => {
+		Animated.sequence([
+			Animated.timing(
+				this.scale,
+				{
+					toValue: 0.8,
+					duration: 1000,
+					useNativeDriver: true
+				}),
+			Animated.timing(
+				this.scale,
+				{
+					toValue: 1,
+					duration: 1000,
+					useNativeDriver: true
+				})
+		]).start(() => {
+			this.animate();
+		});
+	}
+
+	render() {
+		return (
+			<View style={styles.container}>
+				<Animated.Image
+					style={[
+						styles.logo,
+						{
+							transform: [
+								{ scale: this.scale }
+							]
+						}]}
+					source={logo}
+				/>
+			</View>
+		);
+	}
+}
diff --git a/app/reducers/login.js b/app/reducers/login.js
index 72f36d525..9a3c33de2 100644
--- a/app/reducers/login.js
+++ b/app/reducers/login.js
@@ -3,19 +3,20 @@ import * as types from '../actions/actionsTypes';
 const initialState = {
 	isAuthenticated: false,
 	isFetching: false,
+	isRegistering: false,
 	token: '',
 	user: {},
-	errorMessage: ''
+	error: ''
 };
 
 export default function login(state = initialState, action) {
 	switch (action.type) {
 		case types.LOGIN.REQUEST:
-			console.log('types.LOGIN.REQUEST', action);
 			return { ...state,
 				isFetching: true,
 				isAuthenticated: false,
-				failure: false
+				failure: false,
+				error: ''
 			};
 		case types.LOGIN.SUCCESS:
 			return { ...state,
@@ -23,15 +24,15 @@ export default function login(state = initialState, action) {
 				isAuthenticated: true,
 				user: action.user,
 				token: action.user.token,
-				failure: false
-				// user: action.user
+				failure: false,
+				error: ''
 			};
 		case types.LOGIN.FAILURE:
 			return { ...state,
 				isFetching: false,
 				isAuthenticated: false,
 				failure: true,
-				errorMessage: action.err
+				error: action.err
 			};
 		case types.LOGOUT:
 			return initialState;
@@ -40,6 +41,34 @@ export default function login(state = initialState, action) {
 				token: action.token,
 				user: action.user
 			};
+		case types.LOGIN.REGISTER_SUBMIT:
+			return {
+				...state,
+				isFetching: true,
+				isAuthenticated: false,
+				isRegistering: true,
+				failure: false,
+				error: ''
+			};
+		case types.LOGIN.REGISTER_SUCCESS:
+			return {
+				...state,
+				isFetching: false,
+				isAuthenticated: false,
+				failure: false,
+				error: ''
+			};
+		case types.LOGIN.SET_USERNAME_SUBMIT:
+			return {
+				...state,
+				isFetching: true
+			};
+		case types.LOGIN.SET_USERNAME_SUCCESS:
+			return {
+				...state,
+				isFetching: false,
+				isRegistering: false
+			};
 		default:
 			return state;
 	}
diff --git a/app/sagas/login.js b/app/sagas/login.js
index 780655e7e..a8608e79d 100644
--- a/app/sagas/login.js
+++ b/app/sagas/login.js
@@ -1,13 +1,26 @@
 import { AsyncStorage } from 'react-native';
-import { take, put, call, takeEvery, select, all, race } from 'redux-saga/effects';
+import { take, put, call, takeEvery, takeLatest, select, all } from 'redux-saga/effects';
 import * as types from '../actions/actionsTypes';
-import { loginRequest, loginSuccess, loginFailure, setToken, logout } from '../actions/login';
+import {
+	loginRequest,
+	loginSubmit,
+	registerRequest,
+	loginSuccess,
+	loginFailure,
+	setToken,
+	logout,
+	registerSuccess,
+	setUsernameRequest,
+	setUsernameSuccess
+} from '../actions/login';
 import RocketChat from '../lib/rocketchat';
 
 const TOKEN_KEY = 'reactnativemeteor_usertoken';
 const getUser = state => state.login;
 const getServer = state => state.server.server;
 const loginCall = args => (args.resume ? RocketChat.login(args) : RocketChat.loginWithPassword(args));
+const registerCall = args => RocketChat.register(args);
+const setUsernameCall = args => RocketChat.setUsername(args);
 
 const getToken = function* getToken() {
 	const currentServer = yield select(getServer);
@@ -77,19 +90,57 @@ const handleLoginRequest = function* handleLoginRequest({ credentials }) {
 };
 
 const handleLoginSubmit = function* handleLoginSubmit({ credentials }) {
-	// put a login request
 	yield put(loginRequest(credentials));
+};
+
+const handleRegisterSubmit = function* handleRegisterSubmit({ credentials }) {
+	// put a login request
+	yield put(registerRequest(credentials));
 	// wait for a response
-	yield race({
-		success: take(types.LOGIN.SUCCESS),
-		error: take(types.LOGIN.FAILURE)
-	});
+	// yield race({
+	// 	success: take(types.LOGIN.REGISTER_SUCCESS),
+	// 	error: take(types.LOGIN.FAILURE)
+	// });
+};
+
+const handleRegisterRequest = function* handleRegisterRequest({ credentials }) {
+	try {
+		yield call(registerCall, { credentials });
+		yield put(registerSuccess(credentials));
+	} catch (err) {
+		yield put(loginFailure(err));
+	}
+};
+
+const handleRegisterSuccess = function* handleRegisterSuccess({ credentials }) {
+	yield put(loginSubmit({
+		username: credentials.email,
+		password: credentials.pass
+	}));
+};
+
+const handleSetUsernameSubmit = function* handleSetUsernameSubmit({ credentials }) {
+	yield put(setUsernameRequest(credentials));
+};
+
+const handleSetUsernameRequest = function* handleSetUsernameRequest({ credentials }) {
+	try {
+		yield call(setUsernameCall, { credentials });
+		yield put(setUsernameSuccess());
+	} catch (err) {
+		yield put(loginFailure(err));
+	}
 };
 
 const root = function* root() {
 	yield takeEvery(types.SERVER.CHANGED, handleLoginWhenServerChanges);
-	yield takeEvery(types.LOGIN.REQUEST, handleLoginRequest);
-	yield takeEvery(types.LOGIN.SUCCESS, saveToken);
-	yield takeEvery(types.LOGIN.SUBMIT, handleLoginSubmit);
+	yield takeLatest(types.LOGIN.REQUEST, handleLoginRequest);
+	yield takeLatest(types.LOGIN.SUCCESS, saveToken);
+	yield takeLatest(types.LOGIN.SUBMIT, handleLoginSubmit);
+	yield takeLatest(types.LOGIN.REGISTER_REQUEST, handleRegisterRequest);
+	yield takeLatest(types.LOGIN.REGISTER_SUBMIT, handleRegisterSubmit);
+	yield takeLatest(types.LOGIN.REGISTER_SUCCESS, handleRegisterSuccess);
+	yield takeLatest(types.LOGIN.SET_USERNAME_SUBMIT, handleSetUsernameSubmit);
+	yield takeLatest(types.LOGIN.SET_USERNAME_REQUEST, handleSetUsernameRequest);
 };
 export default root;
diff --git a/app/sagas/selectServer.js b/app/sagas/selectServer.js
index f03f2985f..dc9b039ec 100644
--- a/app/sagas/selectServer.js
+++ b/app/sagas/selectServer.js
@@ -32,7 +32,7 @@ const validateServer = function* validateServer({ server }) {
 };
 
 const addServer = function* addServer({ server }) {
-	yield call(serverRequest, server);
+	yield put(serverRequest(server));
 
 	const { error } = yield race({
 		error: take(SERVER.FAILURE),
diff --git a/app/views/CreateChannelView.js b/app/views/CreateChannelView.js
index 01e5bb374..2041f8ab6 100644
--- a/app/views/CreateChannelView.js
+++ b/app/views/CreateChannelView.js
@@ -1,7 +1,7 @@
 import React from 'react';
 import { connect } from 'react-redux';
 import PropTypes from 'prop-types';
-import { TextInput, View, Text, Switch, TouchableOpacity, ScrollView } from 'react-native';
+import { TextInput, View, Text, Switch, TouchableOpacity } from 'react-native';
 import { createChannelRequest } from '../actions/createChannel';
 import styles from './Styles';
 import KeyboardView from '../presentation/KeyboardView';
@@ -90,55 +90,56 @@ export default class CreateChannelView extends React.Component {
 
 	render() {
 		return (
-			<KeyboardView style={[styles.view_white, { flex: 1, justifyContent: 'flex-start' }]}>
-				<ScrollView>
-					<View style={styles.formContainer}>
-						<Text style={styles.label_white}>Channel Name</Text>
-						<TextInput
-							value={this.state.channelName}
-							style={styles.input_white}
-							onChangeText={channelName => this.setState({ channelName })}
-							autoCorrect={false}
-							returnKeyType='done'
-							autoCapitalize='none'
-							autoFocus
-							// onSubmitEditing={() => this.textInput.focus()}
-							placeholder='Type the channel name here'
-						/>
-						{this.renderChannelNameError()}
-						{this.renderTypeSwitch()}
-						<Text
-							style={[
-								styles.label_white,
-								{
-									color: '#9ea2a8',
-									flexGrow: 1,
-									paddingHorizontal: 0,
-									marginBottom: 20
-								}
-							]}
-						>
-							{this.state.type ? (
-								'Everyone can access this channel'
-							) : (
-								'Just invited people can access this channel'
-							)}
+			<KeyboardView
+				style={[styles.defaultViewBackground, { flex: 1 }]}
+				contentContainerStyle={styles.defaultView}
+			>
+				<View style={styles.formContainer}>
+					<Text style={styles.label_white}>Channel Name</Text>
+					<TextInput
+						value={this.state.channelName}
+						style={styles.input_white}
+						onChangeText={channelName => this.setState({ channelName })}
+						autoCorrect={false}
+						returnKeyType='done'
+						autoCapitalize='none'
+						autoFocus
+						// onSubmitEditing={() => this.textInput.focus()}
+						placeholder='Type the channel name here'
+					/>
+					{this.renderChannelNameError()}
+					{this.renderTypeSwitch()}
+					<Text
+						style={[
+							styles.label_white,
+							{
+								color: '#9ea2a8',
+								flexGrow: 1,
+								paddingHorizontal: 0,
+								marginBottom: 20
+							}
+						]}
+					>
+						{this.state.type ? (
+							'Everyone can access this channel'
+						) : (
+							'Just invited people can access this channel'
+						)}
+					</Text>
+					<TouchableOpacity
+						onPress={() => this.submit()}
+						style={[
+							styles.buttonContainer_white,
+							this.state.channelName.length === 0 || this.props.result.isFetching
+								? styles.disabledButton
+								: styles.enabledButton
+						]}
+					>
+						<Text style={styles.button_white}>
+							{this.props.result.isFetching ? 'LOADING' : 'CREATE'}!
 						</Text>
-						<TouchableOpacity
-							onPress={() => this.submit()}
-							style={[
-								styles.buttonContainer_white,
-								this.state.channelName.length === 0 || this.props.result.isFetching
-									? styles.disabledButton
-									: styles.enabledButton
-							]}
-						>
-							<Text style={styles.button_white}>
-								{this.props.result.isFetching ? 'LOADING' : 'CREATE'}!
-							</Text>
-						</TouchableOpacity>
-					</View>
-				</ScrollView>
+					</TouchableOpacity>
+				</View>
 			</KeyboardView>
 		);
 	}
diff --git a/app/views/LoginView.js b/app/views/LoginView.js
index 7f182b7cb..2f259c3dc 100644
--- a/app/views/LoginView.js
+++ b/app/views/LoginView.js
@@ -3,7 +3,7 @@ import React from 'react';
 import Spinner from 'react-native-loading-spinner-overlay';
 
 import PropTypes from 'prop-types';
-import { Keyboard, Text, TextInput, View, Image, TouchableOpacity } from 'react-native';
+import { Keyboard, Text, TextInput, View, TouchableOpacity } from 'react-native';
 import { connect } from 'react-redux';
 import { bindActionCreators } from 'redux';
 // import * as actions from '../actions';
@@ -18,7 +18,8 @@ class LoginView extends React.Component {
 		loginSubmit: PropTypes.func.isRequired,
 		Accounts_EmailOrUsernamePlaceholder: PropTypes.string,
 		Accounts_PasswordPlaceholder: PropTypes.string,
-		login: PropTypes.object
+		login: PropTypes.object,
+		navigation: PropTypes.object.isRequired
 	}
 
 	static navigationOptions = () => ({
@@ -44,6 +45,10 @@ class LoginView extends React.Component {
 		Keyboard.dismiss();
 	}
 
+	register = () => {
+		this.props.navigation.navigate('Register');
+	}
+
 	renderTOTP = () => {
 		if (this.props.login.errorMessage && this.props.login.errorMessage.error === 'totp-required') {
 			return (
@@ -65,48 +70,47 @@ class LoginView extends React.Component {
 	// {this.props.login.isFetching && <Text> LOGANDO</Text>}
 	render() {
 		return (
-			<KeyboardView style={styles.container} keyboardVerticalOffset={128}>
-				<View style={{ alignItems: 'center' }}>
-					<Image
-						style={styles.logo}
-						source={require('../images/logo.png')}
-					/>
-				</View>
+			<KeyboardView
+				contentContainerStyle={styles.container}
+				keyboardVerticalOffset={128}
+			>
 				<View style={styles.loginView}>
 					<View style={styles.formContainer}>
 						<TextInput
-							placeholderTextColor={'rgba(255,255,255,.2)'}
-							style={styles.input}
+							style={styles.input_white}
 							onChangeText={username => this.setState({ username })}
 							keyboardType='email-address'
 							autoCorrect={false}
 							returnKeyType='next'
 							autoCapitalize='none'
-							autoFocus
-
 							underlineColorAndroid='transparent'
 							onSubmitEditing={() => { this.password.focus(); }}
 							placeholder={this.props.Accounts_EmailOrUsernamePlaceholder || 'Email or username'}
 						/>
 						<TextInput
 							ref={(e) => { this.password = e; }}
-							placeholderTextColor={'rgba(255,255,255,.2)'}
-							style={styles.input}
+							style={styles.input_white}
 							onChangeText={password => this.setState({ password })}
 							secureTextEntry
 							autoCorrect={false}
 							returnKeyType='done'
 							autoCapitalize='none'
-
 							underlineColorAndroid='transparent'
 							onSubmitEditing={this.submit}
 							placeholder={this.props.Accounts_PasswordPlaceholder || 'Password'}
 						/>
+
 						{this.renderTOTP()}
+
 						<TouchableOpacity style={styles.buttonContainer}>
 							<Text style={styles.button} onPress={this.submit}>LOGIN</Text>
 						</TouchableOpacity>
-						{this.props.login.error && <Text style={styles.error}>{this.props.login.error}</Text>}
+
+						<TouchableOpacity style={[styles.buttonContainer, styles.registerContainer]}>
+							<Text style={styles.button} onPress={this.register}>REGISTER</Text>
+						</TouchableOpacity>
+
+						{this.props.login.failure && <Text style={styles.error}>{this.props.login.error.reason}</Text>}
 					</View>
 					<Spinner visible={this.props.login.isFetching} textContent={'Loading...'} textStyle={{ color: '#FFF' }} />
 				</View>
diff --git a/app/views/NewServerView.js b/app/views/NewServerView.js
index 62ce32643..f022bc4ee 100644
--- a/app/views/NewServerView.js
+++ b/app/views/NewServerView.js
@@ -1,6 +1,6 @@
 import React from 'react';
 import PropTypes from 'prop-types';
-import { Text, TextInput, View, StyleSheet } from 'react-native';
+import { Text, TextInput, View, StyleSheet, Dimensions } from 'react-native';
 import { connect } from 'react-redux';
 import { serverRequest, addServer } from '../actions/server';
 import KeyboardView from '../presentation/KeyboardView';
@@ -148,7 +148,11 @@ export default class NewServerView extends React.Component {
 
 	render() {
 		return (
-			<KeyboardView style={styles.view} keyboardVerticalOffset={64}>
+			<KeyboardView
+				scrollEnabled={false}
+				contentContainerStyle={[styles.view, { height: Dimensions.get('window').height }]}
+				keyboardVerticalOffset={128}
+			>
 				<View style={styles.spaceView} />
 				<TextInput
 					ref={ref => this.inputElement = ref}
diff --git a/app/views/RegisterView.js b/app/views/RegisterView.js
new file mode 100644
index 000000000..656605727
--- /dev/null
+++ b/app/views/RegisterView.js
@@ -0,0 +1,194 @@
+import React from 'react';
+
+import Spinner from 'react-native-loading-spinner-overlay';
+
+import PropTypes from 'prop-types';
+import { Keyboard, Text, TextInput, View, TouchableOpacity } from 'react-native';
+import { connect } from 'react-redux';
+import { bindActionCreators } from 'redux';
+import * as loginActions from '../actions/login';
+import KeyboardView from '../presentation/KeyboardView';
+
+import styles from './Styles';
+
+const placeholderTextColor = 'rgba(255,255,255,.2)';
+
+class RegisterView extends React.Component {
+	static propTypes = {
+		registerSubmit: PropTypes.func.isRequired,
+		setUsernameSubmit: PropTypes.func,
+		Accounts_UsernamePlaceholder: PropTypes.string,
+		Accounts_NamePlaceholder: PropTypes.string,
+		Accounts_EmailOrUsernamePlaceholder: PropTypes.string,
+		Accounts_PasswordPlaceholder: PropTypes.string,
+		Accounts_RepeatPasswordPlaceholder: PropTypes.string,
+		login: PropTypes.object
+	}
+
+	constructor(props) {
+		super(props);
+
+		this.state = {
+			name: '',
+			email: '',
+			password: '',
+			confirmPassword: ''
+		};
+	}
+
+	_valid() {
+		const { name, email, password, confirmPassword } = this.state;
+		return name.trim() && email.trim() &&
+			password && confirmPassword && password === confirmPassword;
+	}
+	_invalidEmail() {
+		return this.props.login.failure && /Email/.test(this.props.login.error.reason);
+	}
+	submit = () => {
+		const { name, email, password, code } = this.state;
+		if (!this._valid()) {
+			return;
+		}
+
+		this.props.registerSubmit({ name, email, pass: password, code });
+		Keyboard.dismiss();
+	}
+	usernameSubmit = () => {
+		const { username } = this.state;
+		if (!username) {
+			return;
+		}
+
+		this.props.setUsernameSubmit({ username });
+		Keyboard.dismiss();
+	}
+
+	_renderRegister() {
+		if (this.props.login.token) {
+			return null;
+		}
+		return (
+			<View style={styles.formContainer}>
+				<TextInput
+					ref={(e) => { this.name = e; }}
+					style={styles.input_white}
+					onChangeText={name => this.setState({ name })}
+					autoCorrect={false}
+					autoFocus
+					returnKeyType='next'
+					autoCapitalize='none'
+					underlineColorAndroid='transparent'
+					onSubmitEditing={() => { this.email.focus(); }}
+					placeholder={this.props.Accounts_NamePlaceholder || 'Name'}
+				/>
+
+				<TextInput
+					ref={(e) => { this.email = e; }}
+					style={[styles.input_white, this._invalidEmail() ? { borderColor: 'red' } : {}]}
+					onChangeText={email => this.setState({ email })}
+					keyboardType='email-address'
+					autoCorrect={false}
+					returnKeyType='next'
+					autoCapitalize='none'
+					underlineColorAndroid='transparent'
+					onSubmitEditing={() => { this.password.focus(); }}
+					placeholder={this.props.Accounts_EmailOrUsernamePlaceholder || 'Email'}
+				/>
+				<TextInput
+					ref={(e) => { this.password = e; }}
+					style={styles.input_white}
+					onChangeText={password => this.setState({ password })}
+					secureTextEntry
+					autoCorrect={false}
+					returnKeyType='next'
+					autoCapitalize='none'
+					underlineColorAndroid='transparent'
+					onSubmitEditing={() => { this.confirmPassword.focus(); }}
+					placeholder={this.props.Accounts_PasswordPlaceholder || 'Password'}
+				/>
+				<TextInput
+					ref={(e) => { this.confirmPassword = e; }}
+					style={[styles.input_white, this.state.password && this.state.confirmPassword && this.state.confirmPassword !== this.state.password ? { borderColor: 'red' } : {}]}
+					onChangeText={confirmPassword => this.setState({ confirmPassword })}
+					secureTextEntry
+					autoCorrect={false}
+					returnKeyType='done'
+					autoCapitalize='none'
+					underlineColorAndroid='transparent'
+					onSubmitEditing={this.submit}
+					placeholder={this.props.Accounts_RepeatPasswordPlaceholder || 'Repeat Password'}
+				/>
+
+				<TouchableOpacity style={[styles.buttonContainer, styles.registerContainer]}>
+					<Text
+						style={[styles.button, this._valid() ? {}
+							: { color: placeholderTextColor }
+						]}
+						onPress={this.submit}
+					>REGISTER</Text>
+				</TouchableOpacity>
+
+				{this.props.login.failure && <Text style={styles.error}>{this.props.login.error.reason}</Text>}
+			</View>
+		);
+	}
+
+	_renderUsername() {
+		if (!this.props.login.token) {
+			return null;
+		}
+		return (
+			<View style={styles.formContainer}>
+				<TextInput
+					ref={(e) => { this.username = e; }}
+					style={styles.input_white}
+					onChangeText={username => this.setState({ username })}
+					autoCorrect={false}
+					returnKeyType='next'
+					autoCapitalize='none'
+					underlineColorAndroid='transparent'
+					onSubmitEditing={() => { this.usernameSubmit(); }}
+					placeholder={this.props.Accounts_UsernamePlaceholder || 'Username'}
+				/>
+
+				<TouchableOpacity style={[styles.buttonContainer, styles.registerContainer]}>
+					<Text
+						style={styles.button}
+						onPress={this.usernameSubmit}
+					>REGISTER</Text>
+				</TouchableOpacity>
+
+				{this.props.login.failure && <Text style={styles.error}>{this.props.login.error.reason}</Text>}
+			</View>
+		);
+	}
+
+	render() {
+		return (
+			<KeyboardView contentContainerStyle={styles.container}>
+				<View style={styles.loginView}>
+					{this._renderRegister()}
+					{this._renderUsername()}
+					<Spinner visible={this.props.login.isFetching} textContent={'Loading...'} textStyle={{ color: '#FFF' }} />
+				</View>
+			</KeyboardView>
+		);
+	}
+}
+
+function mapStateToProps(state) {
+	return {
+		server: state.server.server,
+		Accounts_NamePlaceholder: state.settings.Accounts_NamePlaceholder,
+		Accounts_EmailOrUsernamePlaceholder: state.settings.Accounts_EmailOrUsernamePlaceholder,
+		Accounts_PasswordPlaceholder: state.settings.Accounts_PasswordPlaceholder,
+		Accounts_RepeatPasswordPlaceholder: state.settings.Accounts_RepeatPasswordPlaceholder,
+		login: state.login
+	};
+}
+
+function mapDispatchToProps(dispatch) {
+	return bindActionCreators(loginActions, dispatch);
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(RegisterView);
diff --git a/app/views/RoomView.js b/app/views/RoomView.js
index 3f6b473cc..6d1ee4f98 100644
--- a/app/views/RoomView.js
+++ b/app/views/RoomView.js
@@ -193,7 +193,7 @@ export default class RoomView extends React.Component {
 
 	render() {
 		return (
-			<KeyboardView style={styles.container} keyboardVerticalOffset={64}>
+			<KeyboardView contentContainerStyle={styles.container} keyboardVerticalOffset={64}>
 				{this.renderBanner()}
 				<ListView
 					enableEmptySections
diff --git a/app/views/Styles.js b/app/views/Styles.js
index c4c040baa..6fb77cb66 100644
--- a/app/views/Styles.js
+++ b/app/views/Styles.js
@@ -2,11 +2,8 @@ import { StyleSheet, Dimensions } from 'react-native';
 
 export default StyleSheet.create({
 	container: {
-		flex: 1,
-		backgroundColor: '#2f343d',
-		flexDirection: 'column',
-		justifyContent: 'center',
-		alignItems: 'stretch'
+		backgroundColor: 'white',
+		flex: 1
 	},
 	loginView: {
 		padding: 20
@@ -19,29 +16,31 @@ export default StyleSheet.create({
 		alignItems: 'stretch',
 		backgroundColor: '#2f343d'
 	},
-	view_white: {
-		flex: 1,
+	defaultView: {
 		flexDirection: 'column',
 		justifyContent: 'center',
 		padding: 20,
-		alignItems: 'stretch',
+		alignItems: 'stretch'
+	},
+	defaultViewBackground: {
 		backgroundColor: '#fff'
 	},
 	logoContainer: {
-		flex: 1,
 		alignItems: 'center',
-		flexGrow: 1,
-		justifyContent: 'center'
+		justifyContent: 'center',
+		flex: 1
 	},
-	logo: {
-		width: Dimensions.get('window').width - 30,
-		height: Dimensions.get('window').width - 30,
-		borderRadius: 5,
+	loginLogo: {
+		width: Dimensions.get('window').width - 150,
+		height: Dimensions.get('window').width - 150,
 		resizeMode: 'contain'
 	},
-	formContainer: {
-		// marginBottom: 20
+	registerLogo: {
+		width: Dimensions.get('window').width - 40,
+		height: 100,
+		resizeMode: 'contain'
 	},
+	formContainer: {},
 	label: {
 		lineHeight: 40,
 		height: 40,
@@ -94,6 +93,9 @@ export default StyleSheet.create({
 		backgroundColor: '#1d74f5',
 		marginBottom: 20
 	},
+	registerContainer: {
+		marginBottom: 0
+	},
 	button: {
 		textAlign: 'center',
 		color: 'white',
diff --git a/package.json b/package.json
index 4a1688e05..2e1dbb944 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,7 @@
     "react-native-fetch-blob": "^0.10.8",
     "react-native-image-picker": "^0.26.4",
     "react-native-img-cache": "^1.4.0",
+    "react-native-keyboard-aware-scroll-view": "^0.3.0",
     "react-native-loading-spinner-overlay": "^0.5.2",
     "react-native-meteor": "^1.1.0",
     "react-native-modal": "^3.1.0",
diff --git a/yarn.lock b/yarn.lock
index 8ad749b55..aa5ba2d71 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2055,7 +2055,7 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
     safe-buffer "^5.0.1"
     sha.js "^2.4.8"
 
-create-react-class@^15.5.2:
+create-react-class@^15.5.2, create-react-class@^15.6.0:
   version "15.6.0"
   resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.0.tgz#ab448497c26566e1e29413e883207d57cfe7bed4"
   dependencies:
@@ -5729,6 +5729,14 @@ react-native-img-cache@^1.4.0:
   dependencies:
     crypto-js "^3.1.9-1"
 
+react-native-keyboard-aware-scroll-view@^0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/react-native-keyboard-aware-scroll-view/-/react-native-keyboard-aware-scroll-view-0.3.0.tgz#b9d7b0d5b47d2bb4285fe50a3d274b10a3b5e1a7"
+  dependencies:
+    create-react-class "^15.6.0"
+    prop-types "^15.5.10"
+    react-timer-mixin "^0.13.3"
+
 react-native-loading-spinner-overlay@^0.5.2:
   version "0.5.2"
   resolved "https://registry.yarnpkg.com/react-native-loading-spinner-overlay/-/react-native-loading-spinner-overlay-0.5.2.tgz#b7bcd277476d596615fd7feee601789f9bdc7acc"
@@ -5943,7 +5951,7 @@ react-test-renderer@16.0.0-alpha.12:
     fbjs "^0.8.9"
     object-assign "^4.1.0"
 
-react-timer-mixin@^0.13.2:
+react-timer-mixin@^0.13.2, react-timer-mixin@^0.13.3:
   version "0.13.3"
   resolved "https://registry.yarnpkg.com/react-timer-mixin/-/react-timer-mixin-0.13.3.tgz#0da8b9f807ec07dc3e854d082c737c65605b3d22"
 
-- 
GitLab