Register new user using REST API, fixed scrollView Bugs
This commit is contained in:
parent
537007a98a
commit
7f4f5b2593
|
@ -10,6 +10,7 @@ import styles from '../views/Styles';
|
|||
|
||||
import AuthRoutes from './routes/AuthRoutes';
|
||||
import PublicRoutes from './routes/PublicRoutes';
|
||||
import Loading from '../presentation/Loading';
|
||||
|
||||
@connect(
|
||||
state => ({
|
||||
|
@ -34,18 +35,7 @@ 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) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Button } from 'react-native';
|
||||
import { StackNavigator, DrawerNavigator, NavigationActions } from 'react-navigation';
|
||||
import { StackNavigator, DrawerNavigator, NavigationActions, HeaderBackButton } from 'react-navigation';
|
||||
// import { Platform } from 'react-native';
|
||||
|
||||
import Sidebar from '../../containers/Sidebar';
|
||||
|
@ -39,7 +39,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} />)÷
|
||||
};
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
|
@ -122,18 +122,13 @@ const RocketChat = {
|
|||
});
|
||||
},
|
||||
|
||||
register(params, callback) {
|
||||
return new Promise((resolve, reject) => {
|
||||
return Meteor.call('registerUser', params, (err, result) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
if (typeof callback === 'function') {
|
||||
callback(err, result);
|
||||
}
|
||||
});
|
||||
register({ server, credentials }) {
|
||||
return fetch(`${ server }/api/v1/users.register`, {
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(credentials)
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { ViewPropTypes } from 'react-native';
|
||||
import { View, ViewPropTypes } from 'react-native';
|
||||
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||
|
||||
export default class KeyboardView extends React.PureComponent {
|
||||
static propTypes = {
|
||||
style: ViewPropTypes.style,
|
||||
contentContainerStyle: ViewPropTypes.style,
|
||||
keyboardVerticalOffset: PropTypes.number,
|
||||
scrollEnabled: PropTypes.bool,
|
||||
children: PropTypes.oneOfType([
|
||||
PropTypes.arrayOf(PropTypes.node),
|
||||
PropTypes.node
|
||||
|
@ -16,11 +18,14 @@ export default class KeyboardView extends React.PureComponent {
|
|||
render() {
|
||||
return (
|
||||
<KeyboardAwareScrollView
|
||||
contentContainerStyle={this.props.style}
|
||||
behavior='position'
|
||||
extraHeight={this.props.keyboardVerticalOffset}
|
||||
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}
|
||||
</KeyboardAwareScrollView>
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import { AsyncStorage } from 'react-native';
|
||||
import { take, put, call, takeEvery, select, all, race } from 'redux-saga/effects';
|
||||
import * as types from '../actions/actionsTypes';
|
||||
import { loginRequest, registerRequest, loginSuccess, registerSuccess, loginFailure, setToken, logout } from '../actions/login';
|
||||
import { loginRequest, loginSubmit, registerRequest, loginSuccess, registerSuccess, loginFailure, setToken, logout } from '../actions/login';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
|
||||
const TOKEN_KEY = 'reactnativemeteor_usertoken';
|
||||
|
@ -89,8 +89,10 @@ const handleLoginSubmit = function* handleLoginSubmit({ credentials }) {
|
|||
|
||||
const handleRegisterRequest = function* handleRegisterRequest({ credentials }) {
|
||||
try {
|
||||
yield call(registerCall, credentials);
|
||||
yield put(registerSuccess());
|
||||
const server = yield select(getServer);
|
||||
yield call(registerCall, { server, credentials });
|
||||
yield put(loginSubmit(credentials));
|
||||
// yield put(registerSuccess());
|
||||
} catch (err) {
|
||||
yield put(loginFailure(err));
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -70,8 +70,12 @@ class LoginView extends React.Component {
|
|||
// {this.props.login.isFetching && <Text> LOGANDO</Text>}
|
||||
render() {
|
||||
return (
|
||||
<KeyboardView style={styles.container} keyboardVerticalOffset={128}>
|
||||
<View style={{ alignItems: 'center' }}>
|
||||
<KeyboardView
|
||||
style={{ flex: 1 }}
|
||||
contentContainerStyle={styles.container}
|
||||
keyboardVerticalOffset={128}
|
||||
>
|
||||
<View style={styles.logoContainer}>
|
||||
<Image
|
||||
style={styles.loginLogo}
|
||||
source={require('../images/logo.png')}
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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, TouchableOpacity } from 'react-native';
|
||||
import { Keyboard, Text, TextInput, View, TouchableOpacity, Image } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import * as loginActions from '../actions/login';
|
||||
|
@ -16,6 +16,7 @@ const placeholderTextColor = 'rgba(255,255,255,.2)';
|
|||
class RegisterView extends React.Component {
|
||||
static propTypes = {
|
||||
registerSubmit: PropTypes.func.isRequired,
|
||||
Accounts_UsernamePlaceholder: PropTypes.string,
|
||||
Accounts_NamePlaceholder: PropTypes.string,
|
||||
Accounts_EmailOrUsernamePlaceholder: PropTypes.string,
|
||||
Accounts_PasswordPlaceholder: PropTypes.string,
|
||||
|
@ -29,6 +30,7 @@ class RegisterView extends React.Component {
|
|||
|
||||
this.state = {
|
||||
name: '',
|
||||
username: '',
|
||||
email: '',
|
||||
password: '',
|
||||
confirmPassword: ''
|
||||
|
@ -42,26 +44,32 @@ class RegisterView extends React.Component {
|
|||
}
|
||||
}
|
||||
_valid() {
|
||||
const { name, email, password, confirmPassword } = this.state;
|
||||
return name.trim() && email.trim() &&
|
||||
const { name, username, email, password, confirmPassword } = this.state;
|
||||
return name.trim() && username.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;
|
||||
const { name, username, email, password, code } = this.state;
|
||||
if (!this._valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.props.registerSubmit({ name, email, pass: password, code });
|
||||
this.props.registerSubmit({ name, username, email, pass: password, code });
|
||||
Keyboard.dismiss();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<KeyboardView style={styles.container} keyboardVerticalOffset={150}>
|
||||
<KeyboardView contentContainerStyle={styles.container} keyboardVerticalOffset={150}>
|
||||
<View style={styles.logoContainer}>
|
||||
<Image
|
||||
style={styles.registerLogo}
|
||||
source={require('../images/logo_with_text.png')}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.loginView}>
|
||||
<View style={styles.formContainer}>
|
||||
<TextInput
|
||||
|
@ -70,12 +78,27 @@ class RegisterView extends React.Component {
|
|||
style={styles.input}
|
||||
onChangeText={name => this.setState({ name })}
|
||||
autoCorrect={false}
|
||||
autoFocus
|
||||
returnKeyType='next'
|
||||
autoCapitalize='none'
|
||||
|
||||
underlineColorAndroid='transparent'
|
||||
onSubmitEditing={() => { this.username.focus(); }}
|
||||
placeholder={this.props.Accounts_NamePlaceholder || 'Name'}
|
||||
/>
|
||||
|
||||
<TextInput
|
||||
ref={(e) => { this.username = e; }}
|
||||
placeholderTextColor={'rgba(255,255,255,.2)'}
|
||||
style={styles.input}
|
||||
onChangeText={username => this.setState({ username })}
|
||||
autoCorrect={false}
|
||||
returnKeyType='next'
|
||||
autoCapitalize='none'
|
||||
|
||||
underlineColorAndroid='transparent'
|
||||
onSubmitEditing={() => { this.email.focus(); }}
|
||||
placeholder={this.props.Accounts_NamePlaceholder || 'Name'}
|
||||
placeholder={this.props.Accounts_UsernamePlaceholder || 'Username'}
|
||||
/>
|
||||
|
||||
<TextInput
|
||||
|
@ -143,6 +166,7 @@ function mapStateToProps(state) {
|
|||
// console.log(Object.keys(state));
|
||||
return {
|
||||
server: state.server.server,
|
||||
Accounts_UsernamePlaceholder: state.settings.Accounts_UsernamePlaceholder,
|
||||
Accounts_NamePlaceholder: state.settings.Accounts_NamePlaceholder,
|
||||
Accounts_EmailOrUsernamePlaceholder: state.settings.Accounts_EmailOrUsernamePlaceholder,
|
||||
Accounts_PasswordPlaceholder: state.settings.Accounts_PasswordPlaceholder,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -2,11 +2,7 @@ import { StyleSheet, Dimensions } from 'react-native';
|
|||
|
||||
export default StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: '#2f343d',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'stretch'
|
||||
backgroundColor: '#2f343d'
|
||||
},
|
||||
loginView: {
|
||||
padding: 20
|
||||
|
@ -19,30 +15,27 @@ 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'
|
||||
},
|
||||
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'
|
||||
},
|
||||
loginLogo: {
|
||||
width: Dimensions.get('window').width - 80,
|
||||
height: Dimensions.get('window').width - 80,
|
||||
borderRadius: 5,
|
||||
registerLogo: {
|
||||
width: Dimensions.get('window').width - 40,
|
||||
height: 100,
|
||||
resizeMode: 'contain'
|
||||
},
|
||||
formContainer: {
|
||||
|
|
Loading…
Reference in New Issue