Rocket.Chat.ReactNative/app/views/LoginSignupView.js

363 lines
11 KiB
JavaScript

import React from 'react';
import PropTypes from 'prop-types';
import {
Text, View, ScrollView, TouchableOpacity, LayoutAnimation, Image, StyleSheet, SafeAreaView
} from 'react-native';
import { connect, Provider } from 'react-redux';
import { Navigation } from 'react-native-navigation';
import Icon from 'react-native-vector-icons/FontAwesome';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import { Base64 } from 'js-base64';
import { open as openAction, close as closeAction } from '../actions/login';
import LoggedView from './View';
import sharedStyles from './Styles';
import scrollPersistTaps from '../utils/scrollPersistTaps';
import random from '../utils/random';
import Button from '../containers/Button';
import Loading from '../containers/Loading';
import I18n from '../i18n';
import store from '../lib/createStore';
const styles = StyleSheet.create({
container: {
alignItems: 'center',
justifyContent: 'center'
},
header: {
fontSize: 20
},
servicesContainer: {
backgroundColor: '#F7F8FA',
width: '100%',
borderRadius: 2,
padding: 16,
paddingTop: 20,
marginBottom: 40
},
servicesTitle: {
color: '#292E35',
textAlign: 'left',
fontWeight: '700'
},
planetImage: {
width: 210,
height: 171,
marginVertical: 20
}
});
let OAuthView = null;
let LoginView = null;
let RegisterView = null;
@connect(state => ({
server: state.server.server,
isFetching: state.login.isFetching,
Accounts_EmailOrUsernamePlaceholder: state.settings.Accounts_EmailOrUsernamePlaceholder,
Accounts_PasswordPlaceholder: state.settings.Accounts_PasswordPlaceholder,
Accounts_OAuth_Facebook: state.settings.Accounts_OAuth_Facebook,
Accounts_OAuth_Github: state.settings.Accounts_OAuth_Github,
Accounts_OAuth_Gitlab: state.settings.Accounts_OAuth_Gitlab,
Accounts_OAuth_Google: state.settings.Accounts_OAuth_Google,
Accounts_OAuth_Linkedin: state.settings.Accounts_OAuth_Linkedin,
Accounts_OAuth_Meteor: state.settings.Accounts_OAuth_Meteor,
Accounts_OAuth_Twitter: state.settings.Accounts_OAuth_Twitter,
services: state.login.services
}), dispatch => ({
open: () => dispatch(openAction()),
close: () => dispatch(closeAction())
}))
/** @extends React.Component */
export default class LoginSignupView extends LoggedView {
static propTypes = {
navigator: PropTypes.object,
open: PropTypes.func.isRequired,
close: PropTypes.func.isRequired,
isFetching: PropTypes.bool,
server: PropTypes.string,
Accounts_EmailOrUsernamePlaceholder: PropTypes.bool,
Accounts_PasswordPlaceholder: PropTypes.string,
Accounts_OAuth_Facebook: PropTypes.bool,
Accounts_OAuth_Github: PropTypes.bool,
Accounts_OAuth_Gitlab: PropTypes.bool,
Accounts_OAuth_Google: PropTypes.bool,
Accounts_OAuth_Linkedin: PropTypes.bool,
Accounts_OAuth_Meteor: PropTypes.bool,
Accounts_OAuth_Twitter: PropTypes.bool,
services: PropTypes.object
}
constructor(props) {
super('LoginSignupView', props);
}
componentDidMount() {
const { open } = this.props;
open();
}
componentWillReceiveProps(nextProps) {
const { services } = this.props;
if (services !== nextProps.services) {
LayoutAnimation.easeInEaseOut();
}
}
componentWillUnmount() {
const { close } = this.props;
close();
}
onPressFacebook = () => {
const { services, server } = this.props;
const { appId } = services.facebook;
const endpoint = 'https://m.facebook.com/v2.9/dialog/oauth';
const redirect_uri = `${ server }/_oauth/facebook?close`;
const scope = 'email';
const state = this.getOAuthState();
const params = `?client_id=${ appId }&redirect_uri=${ redirect_uri }&scope=${ scope }&state=${ state }&display=touch`;
this.openOAuth(`${ endpoint }${ params }`);
}
onPressGithub = () => {
const { services, server } = this.props;
const { clientId } = services.github;
const endpoint = `https://github.com/login?client_id=${ clientId }&return_to=${ encodeURIComponent('/login/oauth/authorize') }`;
const redirect_uri = `${ server }/_oauth/github?close`;
const scope = 'user:email';
const state = this.getOAuthState();
const params = `?client_id=${ clientId }&redirect_uri=${ redirect_uri }&scope=${ scope }&state=${ state }`;
this.openOAuth(`${ endpoint }${ encodeURIComponent(params) }`);
}
onPressGitlab = () => {
const { services, server } = this.props;
const { clientId } = services.gitlab;
const endpoint = 'https://gitlab.com/oauth/authorize';
const redirect_uri = `${ server }/_oauth/gitlab?close`;
const scope = 'read_user';
const state = this.getOAuthState();
const params = `?client_id=${ clientId }&redirect_uri=${ redirect_uri }&scope=${ scope }&state=${ state }&response_type=code`;
this.openOAuth(`${ endpoint }${ params }`);
}
onPressGoogle = () => {
const { services, server } = this.props;
const { clientId } = services.google;
const endpoint = 'https://accounts.google.com/o/oauth2/auth';
const redirect_uri = `${ server }/_oauth/google?close`;
const scope = 'email';
const state = this.getOAuthState();
const params = `?client_id=${ clientId }&redirect_uri=${ redirect_uri }&scope=${ scope }&state=${ state }&response_type=code`;
this.openOAuth(`${ endpoint }${ params }`);
}
onPressLinkedin = () => {
const { services, server } = this.props;
const { clientId } = services.linkedin;
const endpoint = 'https://www.linkedin.com/uas/oauth2/authorization';
const redirect_uri = `${ server }/_oauth/linkedin?close`;
const scope = 'r_emailaddress';
const state = this.getOAuthState();
const params = `?client_id=${ clientId }&redirect_uri=${ redirect_uri }&scope=${ scope }&state=${ state }&response_type=code`;
this.openOAuth(`${ endpoint }${ params }`);
}
onPressMeteor = () => {
const { services, server } = this.props;
const { clientId } = services['meteor-developer'];
const endpoint = 'https://www.meteor.com/oauth2/authorize';
const redirect_uri = `${ server }/_oauth/meteor-developer`;
const state = this.getOAuthState();
const params = `?client_id=${ clientId }&redirect_uri=${ redirect_uri }&state=${ state }&response_type=code`;
this.openOAuth(`${ endpoint }${ params }`);
}
onPressTwitter = () => {
const { server } = this.props;
const state = this.getOAuthState();
const url = `${ server }/_oauth/twitter/?requestTokenAndRedirect=true&state=${ state }`;
this.openOAuth(url);
}
getOAuthState = () => {
const credentialToken = random(43);
return Base64.encodeURI(JSON.stringify({ loginStyle: 'popup', credentialToken, isCordova: true }));
}
openOAuth = (oAuthUrl) => {
if (OAuthView == null) {
OAuthView = require('./OAuthView').default;
Navigation.registerComponent('OAuthView', () => OAuthView, store, Provider);
}
const { navigator } = this.props;
navigator.showModal({
screen: 'OAuthView',
title: 'OAuth',
passProps: {
oAuthUrl
}
});
}
login = () => {
if (LoginView == null) {
LoginView = require('./LoginView').default;
Navigation.registerComponent('LoginView', () => LoginView, store, Provider);
}
const { navigator, server } = this.props;
navigator.push({
screen: 'LoginView',
title: server,
backButtonTitle: ''
});
}
register = () => {
if (RegisterView == null) {
RegisterView = require('./RegisterView').default;
Navigation.registerComponent('RegisterView', () => RegisterView, store, Provider);
}
const { navigator, server } = this.props;
navigator.push({
screen: 'RegisterView',
title: server,
backButtonTitle: ''
});
}
renderServices = () => {
const {
services, Accounts_OAuth_Facebook, Accounts_OAuth_Github, Accounts_OAuth_Gitlab, Accounts_OAuth_Google, Accounts_OAuth_Linkedin, Accounts_OAuth_Meteor, Accounts_OAuth_Twitter
} = this.props;
if (!Object.keys(services).length) {
return null;
}
return (
<View style={styles.servicesContainer}>
<Text style={styles.servicesTitle}>
{I18n.t('Or_continue_using_social_accounts')}
</Text>
<View style={sharedStyles.loginOAuthButtons} key='services'>
{Accounts_OAuth_Facebook && services.facebook
? (
<TouchableOpacity
style={[sharedStyles.oauthButton, sharedStyles.facebookButton]}
onPress={this.onPressFacebook}
>
<Icon name='facebook' size={20} color='#ffffff' />
</TouchableOpacity>
)
: null
}
{Accounts_OAuth_Github && services.github
? (
<TouchableOpacity
style={[sharedStyles.oauthButton, sharedStyles.githubButton]}
onPress={this.onPressGithub}
>
<Icon name='github' size={20} color='#ffffff' />
</TouchableOpacity>
)
: null
}
{Accounts_OAuth_Gitlab && services.gitlab
? (
<TouchableOpacity
style={[sharedStyles.oauthButton, sharedStyles.gitlabButton]}
onPress={this.onPressGitlab}
>
<Icon name='gitlab' size={20} color='#ffffff' />
</TouchableOpacity>
)
: null
}
{Accounts_OAuth_Google && services.google
? (
<TouchableOpacity
style={[sharedStyles.oauthButton, sharedStyles.googleButton]}
onPress={this.onPressGoogle}
>
<Icon name='google' size={20} color='#ffffff' />
</TouchableOpacity>
)
: null
}
{Accounts_OAuth_Linkedin && services.linkedin
? (
<TouchableOpacity
style={[sharedStyles.oauthButton, sharedStyles.linkedinButton]}
onPress={this.onPressLinkedin}
>
<Icon name='linkedin' size={20} color='#ffffff' />
</TouchableOpacity>
)
: null
}
{Accounts_OAuth_Meteor && services['meteor-developer']
? (
<TouchableOpacity
style={[sharedStyles.oauthButton, sharedStyles.meteorButton]}
onPress={this.onPressMeteor}
>
<MaterialCommunityIcons name='meteor' size={25} color='#ffffff' />
</TouchableOpacity>
)
: null
}
{Accounts_OAuth_Twitter && services.twitter
? (
<TouchableOpacity
style={[sharedStyles.oauthButton, sharedStyles.twitterButton]}
onPress={this.onPressTwitter}
>
<Icon name='twitter' size={20} color='#ffffff' />
</TouchableOpacity>
)
: null
}
</View>
</View>
);
}
render() {
const { isFetching } = this.props;
return (
<ScrollView
style={[sharedStyles.container, sharedStyles.containerScrollView]}
{...scrollPersistTaps}
>
<SafeAreaView style={sharedStyles.container} testID='welcome-view'>
<View style={styles.container}>
<Text style={[sharedStyles.loginText, styles.header, { color: '#81848A' }]}>{I18n.t('Welcome_title_pt_1')}</Text>
<Text style={[sharedStyles.loginText, styles.header]}>{I18n.t('Welcome_title_pt_2')}</Text>
<Image style={styles.planetImage} source={{ uri: 'new_server' }} />
<Button
title={I18n.t('I_have_an_account')}
type='primary'
onPress={() => this.login()}
testID='welcome-view-login'
/>
<Button
title={I18n.t('Create_account')}
type='secondary'
onPress={() => this.register()}
testID='welcome-view-register'
/>
{this.renderServices()}
</View>
<Loading visible={isFetching} />
</SafeAreaView>
</ScrollView>
);
}
}