Merge remote-tracking branch 'origin/develop' into update
# Conflicts: # app/views/LoginView.js # app/views/RegisterView.js
This commit is contained in:
commit
6c4cef143d
|
@ -12,10 +12,12 @@ function createRequestTypes(base, types = defaultTypes) {
|
||||||
export const LOGIN = createRequestTypes('LOGIN', [
|
export const LOGIN = createRequestTypes('LOGIN', [
|
||||||
...defaultTypes,
|
...defaultTypes,
|
||||||
'SET_TOKEN',
|
'SET_TOKEN',
|
||||||
|
'RESTORE_TOKEN',
|
||||||
'SUBMIT',
|
'SUBMIT',
|
||||||
'REGISTER_SUBMIT',
|
'REGISTER_SUBMIT',
|
||||||
'REGISTER_REQUEST',
|
'REGISTER_REQUEST',
|
||||||
'REGISTER_SUCCESS',
|
'REGISTER_SUCCESS',
|
||||||
|
'REGISTER_INCOMPLETE',
|
||||||
'SET_USERNAME_SUBMIT',
|
'SET_USERNAME_SUBMIT',
|
||||||
'SET_USERNAME_REQUEST',
|
'SET_USERNAME_REQUEST',
|
||||||
'SET_USERNAME_SUCCESS'
|
'SET_USERNAME_SUCCESS'
|
||||||
|
@ -38,7 +40,13 @@ export const CREATE_CHANNEL = createRequestTypes('CREATE_CHANNEL', [
|
||||||
'RESET'
|
'RESET'
|
||||||
]);
|
]);
|
||||||
export const NAVIGATION = createRequestTypes('NAVIGATION', ['SET']);
|
export const NAVIGATION = createRequestTypes('NAVIGATION', ['SET']);
|
||||||
export const SERVER = createRequestTypes('SERVER', [...defaultTypes, 'SELECT', 'CHANGED', 'ADD']);
|
export const SERVER = createRequestTypes('SERVER', [
|
||||||
|
...defaultTypes,
|
||||||
|
'SELECT',
|
||||||
|
'CHANGED',
|
||||||
|
'ADD',
|
||||||
|
'GOTO_ADD'
|
||||||
|
]);
|
||||||
export const METEOR = createRequestTypes('METEOR_CONNECT', [...defaultTypes, 'DISCONNECT']);
|
export const METEOR = createRequestTypes('METEOR_CONNECT', [...defaultTypes, 'DISCONNECT']);
|
||||||
export const LOGOUT = 'LOGOUT'; // logout is always success
|
export const LOGOUT = 'LOGOUT'; // logout is always success
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,11 @@ export function registerSuccess(credentials) {
|
||||||
credentials
|
credentials
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
export function registerIncomplete() {
|
||||||
|
return {
|
||||||
|
type: types.LOGIN.REGISTER_INCOMPLETE
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function setUsernameSubmit(credentials) {
|
export function setUsernameSubmit(credentials) {
|
||||||
return {
|
return {
|
||||||
|
@ -76,6 +81,13 @@ export function setToken(user = {}) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function restoreToken(token) {
|
||||||
|
return {
|
||||||
|
type: types.LOGIN.RESTORE_TOKEN,
|
||||||
|
token
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function logout() {
|
export function logout() {
|
||||||
return {
|
return {
|
||||||
type: types.LOGOUT
|
type: types.LOGOUT
|
||||||
|
|
|
@ -41,3 +41,9 @@ export function changedServer(server) {
|
||||||
server
|
server
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function gotoAddServer() {
|
||||||
|
return {
|
||||||
|
type: SERVER.GOTO_ADD
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { appInit } from '../actions';
|
||||||
import AuthRoutes from './routes/AuthRoutes';
|
import AuthRoutes from './routes/AuthRoutes';
|
||||||
import PublicRoutes from './routes/PublicRoutes';
|
import PublicRoutes from './routes/PublicRoutes';
|
||||||
import Loading from '../presentation/Loading';
|
import Loading from '../presentation/Loading';
|
||||||
|
import * as NavigationService from './routes/NavigationService';
|
||||||
|
|
||||||
@connect(
|
@connect(
|
||||||
state => ({
|
state => ({
|
||||||
|
@ -27,6 +28,11 @@ export default class Routes extends React.Component {
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.props.appInit();
|
this.props.appInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidUpdate() {
|
||||||
|
NavigationService.setNavigator(this.navigator);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { login, app } = this.props;
|
const { login, app } = this.props;
|
||||||
|
|
||||||
|
@ -35,9 +41,9 @@ export default class Routes extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((login.token && !login.failure && !login.isRegistering) || app.ready) {
|
if ((login.token && !login.failure && !login.isRegistering) || app.ready) {
|
||||||
return (<AuthRoutes />);
|
return (<AuthRoutes ref={nav => this.navigator = nav} />);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (<PublicRoutes />);
|
return (<PublicRoutes ref={nav => this.navigator = nav} />);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { DrawerItems } from 'react-navigation';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import realm from '../lib/realm';
|
import realm from '../lib/realm';
|
||||||
import { setServer } from '../actions/server';
|
import { setServer, gotoAddServer } from '../actions/server';
|
||||||
import { logout } from '../actions/login';
|
import { logout } from '../actions/login';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
@ -41,14 +41,16 @@ const styles = StyleSheet.create({
|
||||||
server: state.server.server
|
server: state.server.server
|
||||||
}), dispatch => ({
|
}), dispatch => ({
|
||||||
selectServer: server => dispatch(setServer(server)),
|
selectServer: server => dispatch(setServer(server)),
|
||||||
logout: () => dispatch(logout())
|
logout: () => dispatch(logout()),
|
||||||
|
gotoAddServer: () => dispatch(gotoAddServer())
|
||||||
}))
|
}))
|
||||||
export default class Sidebar extends Component {
|
export default class Sidebar extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
server: PropTypes.string.isRequired,
|
server: PropTypes.string.isRequired,
|
||||||
selectServer: PropTypes.func.isRequired,
|
selectServer: PropTypes.func.isRequired,
|
||||||
navigation: PropTypes.object.isRequired,
|
navigation: PropTypes.object.isRequired,
|
||||||
logout: PropTypes.func.isRequired
|
logout: PropTypes.func.isRequired,
|
||||||
|
gotoAddServer: PropTypes.func.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
|
@ -117,6 +119,15 @@ export default class Sidebar extends Component {
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</TouchableHighlight>
|
</TouchableHighlight>
|
||||||
|
<TouchableHighlight
|
||||||
|
onPress={() => { this.props.gotoAddServer(); }}
|
||||||
|
>
|
||||||
|
<View style={styles.serverItem}>
|
||||||
|
<Text>
|
||||||
|
Add Server
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</TouchableHighlight>
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { NavigationActions } from 'react-navigation';
|
||||||
|
|
||||||
|
const config = {};
|
||||||
|
|
||||||
|
export function setNavigator(nav) {
|
||||||
|
if (nav) {
|
||||||
|
config.navigator = nav;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function navigate(routeName, params) {
|
||||||
|
if (config.navigator && routeName) {
|
||||||
|
const action = NavigationActions.navigate({ routeName, params });
|
||||||
|
config.navigator.dispatch(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function goBack() {
|
||||||
|
if (config.navigator) {
|
||||||
|
const action = NavigationActions.back({});
|
||||||
|
config.navigator.dispatch(action);
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,9 @@ import ListServerView from '../../views/ListServerView';
|
||||||
import NewServerView from '../../views/NewServerView';
|
import NewServerView from '../../views/NewServerView';
|
||||||
import LoginView from '../../views/LoginView';
|
import LoginView from '../../views/LoginView';
|
||||||
import RegisterView from '../../views/RegisterView';
|
import RegisterView from '../../views/RegisterView';
|
||||||
|
|
||||||
|
import TermsServiceView from '../../views/TermsServiceView';
|
||||||
|
import PrivacyPolicyView from '../../views/PrivacyPolicyView';
|
||||||
import ForgotPasswordView from '../../views/ForgotPasswordView';
|
import ForgotPasswordView from '../../views/ForgotPasswordView';
|
||||||
|
|
||||||
const PublicRoutes = StackNavigator(
|
const PublicRoutes = StackNavigator(
|
||||||
|
@ -45,6 +48,18 @@ const PublicRoutes = StackNavigator(
|
||||||
title: 'Register'
|
title: 'Register'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
TermsService: {
|
||||||
|
screen: TermsServiceView,
|
||||||
|
navigationOptions: {
|
||||||
|
title: 'Terms of service'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
PrivacyPolicy: {
|
||||||
|
screen: PrivacyPolicyView,
|
||||||
|
navigationOptions: {
|
||||||
|
title: 'Privacy policy'
|
||||||
|
}
|
||||||
|
},
|
||||||
ForgotPassword: {
|
ForgotPassword: {
|
||||||
screen: ForgotPasswordView,
|
screen: ForgotPasswordView,
|
||||||
navigationOptions: {
|
navigationOptions: {
|
||||||
|
|
|
@ -23,6 +23,8 @@ const call = (method, ...params) => new Promise((resolve, reject) => {
|
||||||
const TOKEN_KEY = 'reactnativemeteor_usertoken';
|
const TOKEN_KEY = 'reactnativemeteor_usertoken';
|
||||||
|
|
||||||
const RocketChat = {
|
const RocketChat = {
|
||||||
|
TOKEN_KEY,
|
||||||
|
|
||||||
createChannel({ name, users, type }) {
|
createChannel({ name, users, type }) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
Meteor.call(type ? 'createChannel' : 'createPrivateGroup', name, users, type, (err, res) => (err ? reject(err) : resolve(res)));
|
Meteor.call(type ? 'createChannel' : 'createPrivateGroup', name, users, type, (err, res) => (err ? reject(err) : resolve(res)));
|
||||||
|
@ -122,6 +124,17 @@ const RocketChat = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
me({ server, token, userId }) {
|
||||||
|
return fetch(`${ server }/api/v1/me`, {
|
||||||
|
method: 'get',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-Auth-Token': token,
|
||||||
|
'X-User-Id': userId
|
||||||
|
}
|
||||||
|
}).then(response => response.json());
|
||||||
|
},
|
||||||
|
|
||||||
register({ credentials }) {
|
register({ credentials }) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
Meteor.call('registerUser', credentials, (err, userId) => {
|
Meteor.call('registerUser', credentials, (err, userId) => {
|
||||||
|
@ -438,6 +451,7 @@ const RocketChat = {
|
||||||
},
|
},
|
||||||
logout({ server }) {
|
logout({ server }) {
|
||||||
Meteor.logout();
|
Meteor.logout();
|
||||||
|
Meteor.disconnect();
|
||||||
AsyncStorage.removeItem(TOKEN_KEY);
|
AsyncStorage.removeItem(TOKEN_KEY);
|
||||||
AsyncStorage.removeItem(`${ TOKEN_KEY }-${ server }`);
|
AsyncStorage.removeItem(`${ TOKEN_KEY }-${ server }`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,11 @@ export default function login(state = initialState, action) {
|
||||||
token: action.token,
|
token: action.token,
|
||||||
user: action.user
|
user: action.user
|
||||||
};
|
};
|
||||||
|
case types.LOGIN.RESTORE_TOKEN:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
token: action.token
|
||||||
|
};
|
||||||
case types.LOGIN.REGISTER_SUBMIT:
|
case types.LOGIN.REGISTER_SUBMIT:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
@ -73,6 +78,11 @@ export default function login(state = initialState, action) {
|
||||||
isFetching: false,
|
isFetching: false,
|
||||||
isRegistering: false
|
isRegistering: false
|
||||||
};
|
};
|
||||||
|
case types.LOGIN.REGISTER_INCOMPLETE:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
isRegistering: true
|
||||||
|
};
|
||||||
case types.FORGOT_PASSWORD.INIT:
|
case types.FORGOT_PASSWORD.INIT:
|
||||||
return initialState;
|
return initialState;
|
||||||
case types.FORGOT_PASSWORD.REQUEST:
|
case types.FORGOT_PASSWORD.REQUEST:
|
||||||
|
|
|
@ -2,16 +2,23 @@ import { AsyncStorage } from 'react-native';
|
||||||
import { call, put, take } from 'redux-saga/effects';
|
import { call, put, take } from 'redux-saga/effects';
|
||||||
import * as actions from '../actions';
|
import * as actions from '../actions';
|
||||||
import { setServer } from '../actions/server';
|
import { setServer } from '../actions/server';
|
||||||
|
import { restoreToken } from '../actions/login';
|
||||||
import { APP } from '../actions/actionsTypes';
|
import { APP } from '../actions/actionsTypes';
|
||||||
|
|
||||||
const restore = function* restore() {
|
const restore = function* restore() {
|
||||||
try {
|
try {
|
||||||
yield take(APP.INIT);
|
yield take(APP.INIT);
|
||||||
|
const token = yield call([AsyncStorage, 'getItem'], 'reactnativemeteor_usertoken');
|
||||||
|
if (token) {
|
||||||
|
yield put(restoreToken(token));
|
||||||
|
}
|
||||||
|
|
||||||
const currentServer = yield call([AsyncStorage, 'getItem'], 'currentServer');
|
const currentServer = yield call([AsyncStorage, 'getItem'], 'currentServer');
|
||||||
yield put(actions.appReady({}));
|
|
||||||
if (currentServer) {
|
if (currentServer) {
|
||||||
yield put(setServer(currentServer));
|
yield put(setServer(currentServer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
yield put(actions.appReady({}));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {
|
||||||
loginRequest,
|
loginRequest,
|
||||||
loginSubmit,
|
loginSubmit,
|
||||||
registerRequest,
|
registerRequest,
|
||||||
|
registerIncomplete,
|
||||||
loginSuccess,
|
loginSuccess,
|
||||||
loginFailure,
|
loginFailure,
|
||||||
setToken,
|
setToken,
|
||||||
|
@ -16,23 +17,24 @@ import {
|
||||||
forgotPasswordFailure
|
forgotPasswordFailure
|
||||||
} from '../actions/login';
|
} from '../actions/login';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
|
import * as NavigationService from '../containers/routes/NavigationService';
|
||||||
|
|
||||||
const TOKEN_KEY = 'reactnativemeteor_usertoken';
|
|
||||||
const getUser = state => state.login;
|
const getUser = state => state.login;
|
||||||
const getServer = state => state.server.server;
|
const getServer = state => state.server.server;
|
||||||
const loginCall = args => (args.resume ? RocketChat.login(args) : RocketChat.loginWithPassword(args));
|
const loginCall = args => (args.resume ? RocketChat.login(args) : RocketChat.loginWithPassword(args));
|
||||||
const registerCall = args => RocketChat.register(args);
|
const registerCall = args => RocketChat.register(args);
|
||||||
const setUsernameCall = args => RocketChat.setUsername(args);
|
const setUsernameCall = args => RocketChat.setUsername(args);
|
||||||
const logoutCall = args => RocketChat.logout(args);
|
const logoutCall = args => RocketChat.logout(args);
|
||||||
|
const meCall = args => RocketChat.me(args);
|
||||||
const forgotPasswordCall = args => RocketChat.forgotPassword(args);
|
const forgotPasswordCall = args => RocketChat.forgotPassword(args);
|
||||||
|
|
||||||
const getToken = function* getToken() {
|
const getToken = function* getToken() {
|
||||||
const currentServer = yield select(getServer);
|
const currentServer = yield select(getServer);
|
||||||
const user = yield call([AsyncStorage, 'getItem'], `${ TOKEN_KEY }-${ currentServer }`);
|
const user = yield call([AsyncStorage, 'getItem'], `${ RocketChat.TOKEN_KEY }-${ currentServer }`);
|
||||||
if (user) {
|
if (user) {
|
||||||
try {
|
try {
|
||||||
yield put(setToken(JSON.parse(user)));
|
yield put(setToken(JSON.parse(user)));
|
||||||
yield call([AsyncStorage, 'setItem'], TOKEN_KEY, JSON.parse(user).token || '');
|
yield call([AsyncStorage, 'setItem'], RocketChat.TOKEN_KEY, JSON.parse(user).token || '');
|
||||||
return JSON.parse(user);
|
return JSON.parse(user);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('getTokenerr', e);
|
console.log('getTokenerr', e);
|
||||||
|
@ -43,47 +45,41 @@ const getToken = function* getToken() {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleLoginWhenServerChanges = function* handleLoginWhenServerChanges() {
|
const handleLoginWhenServerChanges = function* handleLoginWhenServerChanges() {
|
||||||
// do {
|
|
||||||
try {
|
try {
|
||||||
yield take(types.METEOR.SUCCESS);
|
yield take(types.METEOR.SUCCESS);
|
||||||
yield call(getToken);
|
yield call(getToken);
|
||||||
// const { navigator } = yield select(state => state);
|
|
||||||
|
|
||||||
const user = yield select(getUser);
|
const user = yield select(getUser);
|
||||||
if (user.token) {
|
if (user.token) {
|
||||||
yield put(loginRequest({ resume: user.token }));
|
yield put(loginRequest({ resume: user.token }));
|
||||||
// console.log('AEEEEEEEEOOOOO');
|
|
||||||
// // wait for a response
|
|
||||||
// const { error } = yield race({
|
|
||||||
// success: take(types.LOGIN.SUCCESS),
|
|
||||||
// error: take(types.LOGIN.FAILURE)
|
|
||||||
// });
|
|
||||||
// console.log('AEEEEEEEEOOOOO', error);
|
|
||||||
// if (!error) {
|
|
||||||
// navigator.resetTo({
|
|
||||||
// screen: 'Rooms'
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
// navigator.resetTo({
|
|
||||||
// screen: 'Rooms'
|
|
||||||
// });
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
// } while (true);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveToken = function* saveToken() {
|
const saveToken = function* saveToken() {
|
||||||
const [server, user] = yield all([select(getServer), select(getUser)]);
|
const [server, user] = yield all([select(getServer), select(getUser)]);
|
||||||
yield AsyncStorage.setItem(TOKEN_KEY, user.token);
|
yield AsyncStorage.setItem(RocketChat.TOKEN_KEY, user.token);
|
||||||
yield AsyncStorage.setItem(`${ TOKEN_KEY }-${ server }`, JSON.stringify(user));
|
yield AsyncStorage.setItem(`${ RocketChat.TOKEN_KEY }-${ server }`, JSON.stringify(user));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleLoginRequest = function* handleLoginRequest({ credentials }) {
|
const handleLoginRequest = function* handleLoginRequest({ credentials }) {
|
||||||
try {
|
try {
|
||||||
const response = yield call(loginCall, credentials);
|
const server = yield select(getServer);
|
||||||
yield put(loginSuccess(response));
|
const user = yield call(loginCall, credentials);
|
||||||
|
|
||||||
|
// GET /me from REST API
|
||||||
|
const me = yield call(meCall, { server, token: user.token, userId: user.id });
|
||||||
|
|
||||||
|
// if user has username
|
||||||
|
if (me.username) {
|
||||||
|
user.username = me.username;
|
||||||
|
} else {
|
||||||
|
yield put(registerIncomplete());
|
||||||
|
}
|
||||||
|
|
||||||
|
yield put(loginSuccess(user));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.error === 403) {
|
if (err.error === 403) {
|
||||||
yield put(logout());
|
yield put(logout());
|
||||||
|
@ -98,13 +94,7 @@ const handleLoginSubmit = function* handleLoginSubmit({ credentials }) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRegisterSubmit = function* handleRegisterSubmit({ credentials }) {
|
const handleRegisterSubmit = function* handleRegisterSubmit({ credentials }) {
|
||||||
// put a login request
|
|
||||||
yield put(registerRequest(credentials));
|
yield put(registerRequest(credentials));
|
||||||
// wait for a response
|
|
||||||
// yield race({
|
|
||||||
// success: take(types.LOGIN.REGISTER_SUCCESS),
|
|
||||||
// error: take(types.LOGIN.FAILURE)
|
|
||||||
// });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRegisterRequest = function* handleRegisterRequest({ credentials }) {
|
const handleRegisterRequest = function* handleRegisterRequest({ credentials }) {
|
||||||
|
@ -141,6 +131,10 @@ const handleLogout = function* handleLogout() {
|
||||||
yield call(logoutCall, { server });
|
yield call(logoutCall, { server });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleRegisterIncomplete = function* handleRegisterIncomplete() {
|
||||||
|
yield call(NavigationService.navigate, 'Register');
|
||||||
|
};
|
||||||
|
|
||||||
const handleForgotPasswordRequest = function* handleForgotPasswordRequest({ email }) {
|
const handleForgotPasswordRequest = function* handleForgotPasswordRequest({ email }) {
|
||||||
try {
|
try {
|
||||||
yield call(forgotPasswordCall, email);
|
yield call(forgotPasswordCall, email);
|
||||||
|
@ -158,6 +152,7 @@ const root = function* root() {
|
||||||
yield takeLatest(types.LOGIN.REGISTER_REQUEST, handleRegisterRequest);
|
yield takeLatest(types.LOGIN.REGISTER_REQUEST, handleRegisterRequest);
|
||||||
yield takeLatest(types.LOGIN.REGISTER_SUBMIT, handleRegisterSubmit);
|
yield takeLatest(types.LOGIN.REGISTER_SUBMIT, handleRegisterSubmit);
|
||||||
yield takeLatest(types.LOGIN.REGISTER_SUCCESS, handleRegisterSuccess);
|
yield takeLatest(types.LOGIN.REGISTER_SUCCESS, handleRegisterSuccess);
|
||||||
|
yield takeLatest(types.LOGIN.REGISTER_INCOMPLETE, handleRegisterIncomplete);
|
||||||
yield takeLatest(types.LOGIN.SET_USERNAME_SUBMIT, handleSetUsernameSubmit);
|
yield takeLatest(types.LOGIN.SET_USERNAME_SUBMIT, handleSetUsernameSubmit);
|
||||||
yield takeLatest(types.LOGIN.SET_USERNAME_REQUEST, handleSetUsernameRequest);
|
yield takeLatest(types.LOGIN.SET_USERNAME_REQUEST, handleSetUsernameRequest);
|
||||||
yield takeLatest(types.LOGOUT, handleLogout);
|
yield takeLatest(types.LOGOUT, handleLogout);
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import { put, takeEvery, call, takeLatest, race, take } from 'redux-saga/effects';
|
import { put, takeEvery, call, takeLatest, race, take } from 'redux-saga/effects';
|
||||||
import { delay } from 'redux-saga';
|
import { delay } from 'redux-saga';
|
||||||
import { AsyncStorage } from 'react-native';
|
import { AsyncStorage } from 'react-native';
|
||||||
// import { Navigation } from 'react-native-navigation';
|
|
||||||
import { SERVER } from '../actions/actionsTypes';
|
import { SERVER } from '../actions/actionsTypes';
|
||||||
import { connectRequest, disconnect } from '../actions/connect';
|
import { connectRequest, disconnect } from '../actions/connect';
|
||||||
import { changedServer, serverSuccess, serverFailure, serverRequest } from '../actions/server';
|
import { changedServer, serverSuccess, serverFailure, serverRequest, setServer } from '../actions/server';
|
||||||
|
import { logout } from '../actions/login';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
import realm from '../lib/realm';
|
import realm from '../lib/realm';
|
||||||
|
import * as NavigationService from '../containers/routes/NavigationService';
|
||||||
|
|
||||||
const validate = function* validate(server) {
|
const validate = function* validate(server) {
|
||||||
return yield RocketChat.testServer(server);
|
return yield RocketChat.testServer(server);
|
||||||
|
@ -42,13 +43,21 @@ const addServer = function* addServer({ server }) {
|
||||||
realm.write(() => {
|
realm.write(() => {
|
||||||
realm.create('servers', { id: server, current: false }, true);
|
realm.create('servers', { id: server, current: false }, true);
|
||||||
});
|
});
|
||||||
|
yield put(setServer(server));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleGotoAddServer = function* handleGotoAddServer() {
|
||||||
|
yield put(logout());
|
||||||
|
yield call(AsyncStorage.removeItem, RocketChat.TOKEN_KEY);
|
||||||
|
yield delay(1000);
|
||||||
|
yield call(NavigationService.navigate, 'AddServer');
|
||||||
|
};
|
||||||
|
|
||||||
const root = function* root() {
|
const root = function* root() {
|
||||||
yield takeLatest(SERVER.REQUEST, validateServer);
|
yield takeLatest(SERVER.REQUEST, validateServer);
|
||||||
yield takeEvery(SERVER.SELECT, selectServer);
|
yield takeEvery(SERVER.SELECT, selectServer);
|
||||||
yield takeEvery(SERVER.ADD, addServer);
|
yield takeEvery(SERVER.ADD, addServer);
|
||||||
|
yield takeEvery(SERVER.GOTO_ADD, handleGotoAddServer);
|
||||||
};
|
};
|
||||||
export default root;
|
export default root;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import Spinner from 'react-native-loading-spinner-overlay';
|
// import Spinner from 'react-native-loading-spinner-overlay';
|
||||||
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Keyboard, Text, TextInput, View, TouchableOpacity, SafeAreaView } from 'react-native';
|
import { Keyboard, Text, TextInput, View, TouchableOpacity, SafeAreaView } from 'react-native';
|
||||||
|
@ -49,6 +49,14 @@ class LoginView extends React.Component {
|
||||||
this.props.navigation.navigate('Register');
|
this.props.navigation.navigate('Register');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
termsService = () => {
|
||||||
|
this.props.navigation.navigate('TermsService');
|
||||||
|
}
|
||||||
|
|
||||||
|
privacyPolicy = () => {
|
||||||
|
this.props.navigation.navigate('PrivacyPolicy');
|
||||||
|
}
|
||||||
|
|
||||||
forgotPassword = () => {
|
forgotPassword = () => {
|
||||||
this.props.navigation.navigate('ForgotPassword');
|
this.props.navigation.navigate('ForgotPassword');
|
||||||
}
|
}
|
||||||
|
@ -78,8 +86,8 @@ class LoginView extends React.Component {
|
||||||
contentContainerStyle={styles.container}
|
contentContainerStyle={styles.container}
|
||||||
keyboardVerticalOffset={128}
|
keyboardVerticalOffset={128}
|
||||||
>
|
>
|
||||||
<SafeAreaView>
|
|
||||||
<View style={styles.loginView}>
|
<View style={styles.loginView}>
|
||||||
|
<SafeAreaView>
|
||||||
<View style={styles.formContainer}>
|
<View style={styles.formContainer}>
|
||||||
<TextInput
|
<TextInput
|
||||||
style={styles.input_white}
|
style={styles.input_white}
|
||||||
|
@ -107,23 +115,32 @@ class LoginView extends React.Component {
|
||||||
|
|
||||||
{this.renderTOTP()}
|
{this.renderTOTP()}
|
||||||
|
|
||||||
<TouchableOpacity style={styles.buttonContainer}>
|
<TouchableOpacity
|
||||||
<Text style={styles.button} onPress={this.submit}>LOGIN</Text>
|
style={styles.buttonContainer}
|
||||||
|
onPress={this.submit}
|
||||||
|
>
|
||||||
|
<Text style={styles.button}>LOGIN</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
<TouchableOpacity style={styles.buttonContainer}>
|
<TouchableOpacity style={styles.buttonContainer} onPress={this.register}>
|
||||||
<Text style={styles.button} onPress={this.register}>REGISTER</Text>
|
<Text style={styles.button}>REGISTER</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<TouchableOpacity style={styles.buttonContainer} onPress={this.termsService}>
|
||||||
|
<Text style={styles.button}>TERMS OF SERVICE</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<TouchableOpacity style={styles.buttonContainer} onPress={this.privacyPolicy}>
|
||||||
|
<Text style={styles.button}>PRIVACY POLICY</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
<TouchableOpacity style={styles.buttonContainer} onPress={this.forgotPassword}>
|
<TouchableOpacity style={styles.buttonContainer} onPress={this.forgotPassword}>
|
||||||
<Text style={styles.button}>FORGOT MY PASSWORD</Text>
|
<Text style={styles.button}>FORGOT MY PASSWORD</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
{this.props.login.failure && <Text style={styles.error}>{this.props.login.error.reason}</Text>}
|
{this.props.login.failure && <Text style={styles.error}>{this.props.login.error.reason}</Text>}
|
||||||
</View>
|
</View>
|
||||||
<Spinner visible={this.props.login.isFetching} textContent='Loading...' textStyle={{ color: '#FFF' }} />
|
|
||||||
</View>
|
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
|
</View>
|
||||||
</KeyboardView>
|
</KeyboardView>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { WebView } from 'react-native';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
class PrivacyPolicyView extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
privacyPolicy: PropTypes.string
|
||||||
|
}
|
||||||
|
|
||||||
|
static navigationOptions = () => ({
|
||||||
|
title: 'Terms of service'
|
||||||
|
});
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<WebView source={{ html: this.props.privacyPolicy }} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapStateToProps(state) {
|
||||||
|
return {
|
||||||
|
privacyPolicy: state.settings.Layout_Privacy_Policy
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps)(PrivacyPolicyView);
|
|
@ -125,12 +125,14 @@ class RegisterView extends React.Component {
|
||||||
placeholder={this.props.Accounts_RepeatPasswordPlaceholder || 'Repeat Password'}
|
placeholder={this.props.Accounts_RepeatPasswordPlaceholder || 'Repeat Password'}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TouchableOpacity style={[styles.buttonContainer, styles.registerContainer]}>
|
<TouchableOpacity
|
||||||
|
style={[styles.buttonContainer, styles.registerContainer]}
|
||||||
|
onPress={this.submit}
|
||||||
|
>
|
||||||
<Text
|
<Text
|
||||||
style={[styles.button, this._valid() ? {}
|
style={[styles.button, this._valid() ? {}
|
||||||
: { color: placeholderTextColor }
|
: { color: placeholderTextColor }
|
||||||
]}
|
]}
|
||||||
onPress={this.submit}
|
|
||||||
>REGISTER
|
>REGISTER
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
@ -158,12 +160,11 @@ class RegisterView extends React.Component {
|
||||||
placeholder={this.props.Accounts_UsernamePlaceholder || 'Username'}
|
placeholder={this.props.Accounts_UsernamePlaceholder || 'Username'}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TouchableOpacity style={[styles.buttonContainer, styles.registerContainer]}>
|
<TouchableOpacity
|
||||||
<Text
|
style={[styles.buttonContainer, styles.registerContainer]}
|
||||||
style={styles.button}
|
|
||||||
onPress={this.usernameSubmit}
|
onPress={this.usernameSubmit}
|
||||||
>REGISTER
|
>
|
||||||
</Text>
|
<Text style={styles.button}>REGISTER</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
{this.props.login.failure && <Text style={styles.error}>{this.props.login.error.reason}</Text>}
|
{this.props.login.failure && <Text style={styles.error}>{this.props.login.error.reason}</Text>}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { WebView } from 'react-native';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
class TermsServiceView extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
termsService: PropTypes.string
|
||||||
|
}
|
||||||
|
|
||||||
|
static navigationOptions = () => ({
|
||||||
|
title: 'Terms of service'
|
||||||
|
});
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<WebView source={{ html: this.props.termsService }} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapStateToProps(state) {
|
||||||
|
return {
|
||||||
|
termsService: state.settings.Layout_Terms_of_Service
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps)(TermsServiceView);
|
Loading…
Reference in New Issue