diff --git a/app/actions/actionsTypes.js b/app/actions/actionsTypes.js
index 07ca9a4c2..efacd963b 100644
--- a/app/actions/actionsTypes.js
+++ b/app/actions/actionsTypes.js
@@ -10,9 +10,10 @@ function createRequestTypes(base, types = defaultTypes) {
}
// Login events
-export const LOGIN = createRequestTypes('LOGIN', [...defaultTypes, 'SET_TOKEN']);
+export const LOGIN = createRequestTypes('LOGIN', [...defaultTypes, 'SET_TOKEN', 'SUBMIT']);
export const ROOMS = createRequestTypes('ROOMS');
export const MESSAGES = createRequestTypes('MESSAGES');
+export const NAVIGATION = createRequestTypes('NAVIGATION', ['SET']);
export const SERVER = createRequestTypes('SERVER', ['SELECT', 'CHANGED']);
export const METEOR = createRequestTypes('METEOR_CONNECT', [...defaultTypes, 'DISCONNECT']);
export const LOGOUT = 'LOGOUT'; // logout is always success
diff --git a/app/actions/login.js b/app/actions/login.js
index 4f8c248d8..cffc3cdda 100644
--- a/app/actions/login.js
+++ b/app/actions/login.js
@@ -1,9 +1,15 @@
import * as types from './actionsTypes';
+export function loginSubmit(credentials) {
+ return {
+ type: types.LOGIN.SUBMIT,
+ credentials
+ };
+}
export function loginRequest(credentials) {
return {
type: types.LOGIN.REQUEST,
- ...credentials
+ credentials
};
}
@@ -22,10 +28,11 @@ export function loginFailure(err) {
};
}
-export function setToken(token) {
+export function setToken(user) {
return {
type: types.LOGIN.SET_TOKEN,
- token
+ token: user.token,
+ user
};
}
diff --git a/app/actions/navigator.js b/app/actions/navigator.js
new file mode 100644
index 000000000..b328a2351
--- /dev/null
+++ b/app/actions/navigator.js
@@ -0,0 +1,8 @@
+import * as types from './actionsTypes';
+
+export default function setNavigation(navigator = {}) {
+ return {
+ type: types.NAVIGATION.SET,
+ navigator
+ };
+}
diff --git a/app/animations/fade.js b/app/animations/fade.js
new file mode 100644
index 000000000..725ccbaaf
--- /dev/null
+++ b/app/animations/fade.js
@@ -0,0 +1,53 @@
+import React from 'react';
+import { Animated, Text } from 'react-native';
+
+export default class Fade extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ visible: props.visible
+ };
+ }
+
+ componentWillMount() {
+ this._visibility = new Animated.Value(this.props.visible ? 1 : 0);
+ }
+
+ componentWillReceiveProps(nextProps) {
+ if (nextProps.visible) {
+ this.setState({ visible: true });
+ }
+ Animated.timing(this._visibility, {
+ toValue: nextProps.visible ? 1 : 0,
+ duration: 300
+ }).start(() => {
+ this.setState({ visible: nextProps.visible });
+ });
+ }
+
+ render() {
+ const { visible, style, children, ...rest } = this.props;
+
+ const containerStyle = {
+ opacity: this._visibility.interpolate({
+ inputRange: [0, 1],
+ outputRange: [0, 1]
+ }),
+ transform: [
+ {
+ scale: this._visibility.interpolate({
+ inputRange: [0, 1],
+ outputRange: [1.1, 1]
+ })
+ }
+ ]
+ };
+
+ const combinedStyle = [containerStyle, style];
+ return (
+
+ {this.state.visible ? children : null}
+
+ );
+ }
+}
diff --git a/app/components/banner.js b/app/components/banner.js
index 77a03a1e1..eb159c496 100644
--- a/app/components/banner.js
+++ b/app/components/banner.js
@@ -5,7 +5,11 @@ import { connect } from 'react-redux';
const styles = StyleSheet.create({
bannerContainer: {
- backgroundColor: '#ddd'
+ backgroundColor: '#ddd',
+ position: 'absolute',
+ top: '0%',
+ zIndex: 10,
+ width: '100%'
},
bannerText: {
textAlign: 'center',
diff --git a/app/images/logo.png b/app/images/logo.png
new file mode 100644
index 000000000..57a423a6b
Binary files /dev/null and b/app/images/logo.png differ
diff --git a/app/images/logo.svg b/app/images/logo.svg
new file mode 100644
index 000000000..33663753b
--- /dev/null
+++ b/app/images/logo.svg
@@ -0,0 +1,77 @@
+
+
+
+
diff --git a/app/index.js b/app/index.js
new file mode 100644
index 000000000..89795d768
--- /dev/null
+++ b/app/index.js
@@ -0,0 +1,80 @@
+import React from 'react';
+import { connect } from 'react-redux';
+import { Text } from 'react-native';
+import setNavigator from './actions/navigator';
+import LoginView from './views/login';
+import ListServerView from './views/serverList';
+
+import store from './lib/createStore';
+
+//
+// export const authenticated = (view) => {
+// if (!store.getState().login.authenticated) {
+// return store.getState().navigator.resetTo({
+// screen: 'Login'
+// });
+// }
+// return view;
+// };
+
+export const authenticated = WrappedComponent => class _p extends React.PureComponent {
+ constructor() {
+ super();
+ this.login = store.getState().login;
+ console.log('this.login.token', this.login.token);
+ if (!this.login.token || this.login.failure) {
+ return store.getState().navigator.resetTo({
+ screen: 'Login'
+ });
+ }
+ }
+ render() {
+ // Wraps the input component in a container, without mutating it. Good!
+ return ;
+ }
+};
+//
+export class PublicScreen extends React.PureComponent {
+ // componentWillMount() {
+ // this.props.setNavigator(this.props.navigator);
+ // if (this.props.currentServer) {
+ // return this.props.navigator.navigate('private');
+ // }
+ // }
+ render() {
+ return !this.login.isAuthenticated || !this.login.user ? null : ();
+ }
+}
+
+
+@connect(null, dispatch => ({
+ setNavigator: navigator => dispatch(setNavigator(navigator))
+}))
+export class PrivateScreen extends React.PureComponent {
+ componentWillMount() {
+ // this.props.setNavigator(this.props.navigator);
+ }
+ render() {
+ // if (this.props.logged) {
+ // return (oi);
+ // }
+ return ();
+ }
+}
+@connect(state => ({
+ // logged: state.login.isAuthenticated
+}), dispatch => ({
+ // navigate: routeName => dispatch(NavigationActions.navigate({ routeName })),
+ setNavigator: navigator => dispatch(setNavigator(navigator))
+}))
+export const HomeScreen = class extends React.PureComponent {
+ componentWillMount() {
+ this.props.setNavigator(this.props.navigator);
+ this.props.navigator.resetTo({
+ screen: 'public'
+ });
+ }
+ render() {
+ return (oieee);
+ }
+};
diff --git a/app/lib/createStore.js b/app/lib/createStore.js
index 7e6599e5b..d187127f2 100644
--- a/app/lib/createStore.js
+++ b/app/lib/createStore.js
@@ -13,7 +13,7 @@ let middleware;
if (__DEV__) {
/* eslint-disable global-require */
const reduxImmutableStateInvariant = require('redux-immutable-state-invariant').default();
- middleware = [sagaMiddleware, reduxImmutableStateInvariant, logger];
+ middleware = [sagaMiddleware, reduxImmutableStateInvariant];
} else {
middleware = [sagaMiddleware];
}
diff --git a/app/lib/realm.js b/app/lib/realm.js
index b1219a3b3..c58b4a75a 100644
--- a/app/lib/realm.js
+++ b/app/lib/realm.js
@@ -1,4 +1,5 @@
import Realm from 'realm';
+import { AsyncStorage } from 'react-native';
const serversSchema = {
name: 'servers',
@@ -153,9 +154,9 @@ const messagesSchema = {
// ]
// }
};
-
+//
// Realm.clearTestState();
-
+// AsyncStorage.clear();
const realm = new Realm({
schema: [settingsSchema, serversSchema, subscriptionSchema, messagesSchema, usersSchema, attachment]
});
diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js
index 900cc6a6a..a776eebe5 100644
--- a/app/lib/rocketchat.js
+++ b/app/lib/rocketchat.js
@@ -51,9 +51,9 @@ const RocketChat = {
reduxStore.dispatch(connectSuccess());
resolve();
});
- Meteor.ddp.on('loggin', () => {
- reduxStore.dispatch(loginSuccess({}));
- });
+ // Meteor.ddp.on('loggin', () => {
+ // reduxStore.dispatch(loginSuccess({}));
+ // });
Meteor.ddp.on('connected', () => {
Meteor.call('public-settings/get', (err, data) => {
if (err) {
@@ -105,11 +105,13 @@ const RocketChat = {
},
login(params, callback) {
+ console.log('login(params, callback)');
return new Promise((resolve, reject) => {
Meteor._startLoggingIn();
return Meteor.call('login', params, (err, result) => {
Meteor._endLoggingIn();
Meteor._handleLoginCallback(err, result);
+ console.log('login(params, callback)asdas', err, result);
if (err) {
reject(err);
} else {
@@ -224,6 +226,7 @@ const RocketChat = {
getMessage(rid, msg = {}) {
const _id = Random.id();
+ // console.log('reduxStore.getState().login.id ', reduxStore.getState().login);
const message = {
_id,
rid,
@@ -233,8 +236,8 @@ const RocketChat = {
temp: true,
_server: { id: reduxStore.getState().server },
u: {
- _id: reduxStore.getState()._id,
- username: reduxStore.getState()._id
+ _id: reduxStore.getState().login.user.id || '1',
+ username: reduxStore.getState().login.user.id
}
};
@@ -367,14 +370,15 @@ const RocketChat = {
getRooms() {
// Meteor.Accounts.onLogin(() => {
return Promise.all([call('subscriptions/get'), call('rooms/get')]).then(([subscriptions, rooms]) => {
+ // console.log('getRooms resolved', reduxStore.getState().server, subscriptions);
subscriptions = subscriptions.sort((s1, s2) => (s1.rid > s2.rid ? 1 : -1));
rooms = rooms.sort((s1, s2) => (s1._id > s2._id ? 1 : -1));
const data = subscriptions.map((subscription, index) => {
subscription._updatedAt = rooms[index]._updatedAt;
return subscription;
});
- Meteor.subscribe('stream-notify-user', `${ Meteor.userId() }/subscriptions-changed`, false);
// Meteor.subscribe('stream-notify-user', `${ Meteor.userId() }/rooms-changed`, false);
+ console.log('getRooms resolved', reduxStore.getState().server, data);
realm.write(() => {
data.forEach((subscription) => {
// const subscription = {
@@ -388,6 +392,7 @@ const RocketChat = {
realm.create('subscriptions', subscription, true);
});
});
+ Meteor.subscribe('stream-notify-user', `${ reduxStore.getState().user.id }/subscriptions-changed`, false);
return data;
}).then(data => data);
// });
diff --git a/app/navigation.js b/app/navigation.js
index 65a87c97e..9ee61d2f6 100644
--- a/app/navigation.js
+++ b/app/navigation.js
@@ -9,8 +9,13 @@ import RoomView from './views/room';
import PhotoView from './views/Photo';
import CreateChannel from './views/CreateChannel';
import store from './lib/createStore';
+import { PrivateScreen, HomeScreen, authenticated } from './index';
-Navigation.registerComponent('Rooms', () => RoomsListView, store, Provider);
+// console.log('fisateile/', PublicRoute(PublicScreen));
+Navigation.registerComponent('home', () => HomeScreen, store, Provider);
+Navigation.registerComponent('private', () => PrivateScreen, store, Provider);
+Navigation.registerComponent('public', () => ListServerView, store, Provider);
+Navigation.registerComponent('Rooms', () => authenticated(RoomsListView), store, Provider);
Navigation.registerComponent('Room', () => RoomView, store, Provider);
Navigation.registerComponent('Photo', () => PhotoView, store, Provider);
Navigation.registerComponent('ListServer', () => ListServerView, store, Provider);
@@ -20,8 +25,8 @@ Navigation.registerComponent('CreateChannel', () => CreateChannel, store, Provid
Navigation.startSingleScreenApp({
screen: {
- screen: 'ListServer',
- title: 'ListServer'
+ screen: 'home',
+ title: 'private'
},
- animationType: 'none'
+ animationType: 'slide-up'
});
diff --git a/app/reducers/index.js b/app/reducers/index.js
index bc162c812..108f9add5 100644
--- a/app/reducers/index.js
+++ b/app/reducers/index.js
@@ -1,11 +1,12 @@
import { combineReducers } from 'redux';
-import * as reducers from './reducers';
+import settings from './reducers';
import login from './login';
import meteor from './connect';
import messages from './messages';
import server from './server';
+import navigator from './navigator';
export default combineReducers({
- ...reducers, login, meteor, messages, server
+ settings, login, meteor, messages, server, navigator
});
diff --git a/app/reducers/login.js b/app/reducers/login.js
index 4aacbd590..72f36d525 100644
--- a/app/reducers/login.js
+++ b/app/reducers/login.js
@@ -11,16 +11,18 @@ const initialState = {
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
+ isAuthenticated: false,
+ failure: false
};
case types.LOGIN.SUCCESS:
return { ...state,
isFetching: false,
isAuthenticated: true,
user: action.user,
- // token: action.token,
+ token: action.user.token,
failure: false
// user: action.user
};
@@ -32,13 +34,11 @@ export default function login(state = initialState, action) {
errorMessage: action.err
};
case types.LOGOUT:
- return { ...state,
- isFetching: false,
- isAuthenticated: false
- };
+ return initialState;
case types.LOGIN.SET_TOKEN:
return { ...state,
- token: action.token
+ token: action.token,
+ user: action.user
};
default:
return state;
diff --git a/app/reducers/navigator.js b/app/reducers/navigator.js
new file mode 100644
index 000000000..75c2cf09b
--- /dev/null
+++ b/app/reducers/navigator.js
@@ -0,0 +1,13 @@
+import * as types from '../actions/actionsTypes';
+
+const initialState = {};
+
+export default function navigations(state = initialState, action) {
+ switch (action.type) {
+ case types.NAVIGATION.SET:
+ return action.navigator
+ ;
+ default:
+ return state;
+ }
+}
diff --git a/app/sagas/login.js b/app/sagas/login.js
index 6462ff71d..b21d2503e 100644
--- a/app/sagas/login.js
+++ b/app/sagas/login.js
@@ -1,55 +1,102 @@
import { AsyncStorage } from 'react-native';
-import { take, put, call, takeEvery, fork, select, all } from 'redux-saga/effects';
+import { take, put, call, takeEvery, fork, select, all, race } from 'redux-saga/effects';
import * as types from '../actions/actionsTypes';
import { loginRequest, loginSuccess, loginFailure, setToken } from '../actions/login';
import RocketChat from '../lib/rocketchat';
const TOKEN_KEY = 'reactnativemeteor_usertoken';
-const getUser = state => state.login.user;
+const getUser = state => state.login;
const getServer = state => state.server;
const loginCall = args => (args.resume ? RocketChat.login(args) : RocketChat.loginWithPassword(args));
const getToken = function* getToken() {
const currentServer = yield select(getServer);
- console.log('currentServer', currentServer);
- const token = yield call([AsyncStorage, 'getItem'], `${ TOKEN_KEY }-${ currentServer }`);
- console.log('currentServer TOKEN', token);
- if (token) { yield put(setToken(token)); }
- // yield call([AsyncStorage, 'setItem'], TOKEN_KEY, token || '');
- return token;
-};
-
-const sagaLogin = function* sagaLogin(payload) {
- try {
- const response = yield call(loginCall, payload);
- yield put(loginSuccess(response));
- } catch (err) {
- yield put(loginFailure(err));
+ const user = yield call([AsyncStorage, 'getItem'], `${ TOKEN_KEY }-${ currentServer }`);
+ if (user) {
+ try {
+ yield put(setToken(JSON.parse(user)));
+ yield call([AsyncStorage, 'setItem'], TOKEN_KEY, JSON.parse(user).token || '');
+ return JSON.parse(user);
+ } catch (e) {
+ console.log('getTokenerr', e);
+ }
}
};
-const watchLoginRequest = function* watchLoginRequest() {
- do {
- try {
- yield all([take(types.METEOR.SUCCESS), take(types.SERVER.CHANGED)]);
- const token = yield call(getToken);
- if (token) {
- yield put(loginRequest({ resume: token }));
- }
- } catch (e) {
- console.log(e);
+
+const handleLoginWhenServerChanges = function* handleLoginWhenServerChanges() {
+ // do {
+ try {
+ yield take(types.METEOR.SUCCESS);
+ const { navigator } = yield select(state => state);
+ navigator.resetTo({
+ screen: 'Rooms'
+ });
+ const user = yield select(getUser);
+ if (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'
+ // });
+ // }
}
- } while (true);
+ } catch (e) {
+ console.log(e);
+ }
+ // } while (true);
};
const saveToken = function* saveToken() {
const [server, user] = yield all([select(getServer), select(getUser)]);
yield AsyncStorage.setItem(TOKEN_KEY, user.token);
- yield AsyncStorage.setItem(`${ TOKEN_KEY }-${ server }`, user.token);
+ yield AsyncStorage.setItem(`${ TOKEN_KEY }-${ server }`, JSON.stringify(user));
+};
+
+const handleLoginRequest = function* handleLoginRequest() {
+ while (true) {
+ const { credentials } = yield take(types.LOGIN.REQUEST);
+ try {
+ const response = yield call(loginCall, credentials);
+ yield put(loginSuccess(response));
+ } catch (err) {
+ // console.log('login failed');
+ yield put(loginFailure(err));
+ }
+ }
+};
+
+const handleLoginSubmit = function* handleLoginSubmit() {
+ while (true) {
+ const { credentials } = yield take(types.LOGIN.SUBMIT);
+ // put a login request
+ yield put(loginRequest(credentials));
+ // wait for a response
+ const { error } = yield race({
+ success: take(types.LOGIN.SUCCESS),
+ error: take(types.LOGIN.FAILURE)
+ });
+
+ if (!error) {
+ const { navigator } = yield select(state => state);
+ navigator.resetTo({
+ screen: 'Rooms'
+ });
+ }
+ }
};
const root = function* root() {
- yield fork(watchLoginRequest);
- yield takeEvery(types.LOGIN.REQUEST, sagaLogin);
+ yield takeEvery(types.SERVER.CHANGED, getToken);
+ yield takeEvery(types.SERVER.CHANGED, handleLoginWhenServerChanges);
+ yield fork(handleLoginRequest);
yield takeEvery(types.LOGIN.SUCCESS, saveToken);
+ yield fork(handleLoginSubmit);
};
export default root;
diff --git a/app/sagas/messages.js b/app/sagas/messages.js
index 47774474f..e379398f5 100644
--- a/app/sagas/messages.js
+++ b/app/sagas/messages.js
@@ -5,6 +5,7 @@ import RocketChat from '../lib/rocketchat';
const get = function* get({ rid }) {
const auth = yield select(state => state.login.isAuthenticated);
+ console.log('hey now', yield select(state => state.login));
if (!auth) {
yield take(LOGIN.SUCCESS);
}
@@ -19,9 +20,4 @@ const get = function* get({ rid }) {
const getData = function* getData() {
yield takeLatest(MESSAGES.REQUEST, get);
};
-
-const getMessages = function* getMessages() {
- yield takeEvery(LOGIN.SUCCESS, getData);
-};
-
-export default getMessages;
+export default getData;
diff --git a/app/sagas/rooms.js b/app/sagas/rooms.js
index 9cf6c7b94..a751d6b8d 100644
--- a/app/sagas/rooms.js
+++ b/app/sagas/rooms.js
@@ -9,6 +9,7 @@ const getRooms = function* getRooms() {
const watchRoomsRequest = function* watchRoomsRequest() {
try {
+ console.log('getRooms');
yield call(getRooms);
yield put(roomsSuccess());
} catch (err) {
diff --git a/app/sagas/selectServer.js b/app/sagas/selectServer.js
index 2e81c25bf..f8df5c07f 100644
--- a/app/sagas/selectServer.js
+++ b/app/sagas/selectServer.js
@@ -5,15 +5,9 @@ import { connectRequest, disconnect } from '../actions/connect';
import { changedServer } from '../actions/server';
const selectServer = function* selectServer(server) {
- try {
- yield put(disconnect());
- yield put(changedServer(server));
- yield (server && put(connectRequest(server)));
- // console.log(Actions.login());
- // Actions.replace('login', {});
- } catch (e) {
- console.log(e);
- }
+ yield put(disconnect());
+ yield put(changedServer(server));
+ yield put(connectRequest(server));
};
const root = function* root() {
yield takeEvery(SERVER.SELECT, selectServer);
diff --git a/app/views/login.js b/app/views/login.js
index 48c71e660..e32e21cd7 100644
--- a/app/views/login.js
+++ b/app/views/login.js
@@ -1,41 +1,78 @@
import React from 'react';
+
+import Spinner from 'react-native-loading-spinner-overlay';
+
import PropTypes from 'prop-types';
-import { Text, TextInput, StyleSheet } from 'react-native';
+import { Keyboard, Text, TextInput, StyleSheet, View, Image, TouchableOpacity } from 'react-native';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
// import * as actions from '../actions';
import * as loginActions from '../actions/login';
import KeyboardView from '../components/KeyboardView';
+// import { Keyboard } from 'react-native'
const styles = StyleSheet.create({
view: {
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
+ padding: 20,
alignItems: 'stretch',
- backgroundColor: '#fff'
+ backgroundColor: '#2f343d'
+ },
+ logoContainer: {
+ flex: 1,
+ alignItems: 'center',
+ flexGrow: 1,
+ justifyContent: 'center'
+ },
+ logo: {
+ width: 150,
+ // backgroundColor: 'red'
+ // height: 150,
+ resizeMode: 'contain'
+ },
+ formContainer: {
+ // marginBottom: 20
},
input: {
height: 40,
- borderColor: '#aaa',
- marginLeft: 20,
- marginRight: 20,
- marginTop: 10,
- padding: 5,
+ marginBottom: 20,
+ borderRadius: 2,
+ paddingHorizontal: 10,
borderWidth: 0,
- backgroundColor: '#f6f6f6'
+ backgroundColor: 'rgba(255,255,255,.2)',
+ color: 'white'
+ },
+ buttonContainer: {
+ paddingVertical: 15,
+ backgroundColor: '#414852',
+ marginBottom: 20
+ },
+ button: {
+ textAlign: 'center',
+ color: 'white',
+ borderRadius: 2,
+ fontWeight: '700'
},
error: {
textAlign: 'center',
color: 'red',
paddingTop: 5
+ },
+ loading: {
+ flex: 1,
+ position: 'absolute',
+ backgroundColor: 'rgba(255,255,255,.2)',
+ left: 0,
+ top: 0
}
});
class LoginView extends React.Component {
static propTypes = {
navigator: PropTypes.object.isRequired,
- loginRequest: PropTypes.func.isRequired,
+ loginSubmit: PropTypes.func.isRequired,
server: PropTypes.string.isRequired,
Accounts_EmailOrUsernamePlaceholder: PropTypes.string,
Accounts_PasswordPlaceholder: PropTypes.string
@@ -65,9 +102,8 @@ class LoginView extends React.Component {
}
submit = () => {
const { username, password, code } = this.state;
- console.log({ username, password, code });
- this.props.loginRequest({ username, password, code });
- this.props.navigator.dismissModal();
+ this.props.loginSubmit({ username, password, code });
+ Keyboard.dismiss();
}
renderTOTP = () => {
@@ -92,29 +128,45 @@ class LoginView extends React.Component {
render() {
return (
- this.setState({ username })}
- keyboardType='email-address'
- autoCorrect={false}
- returnKeyType='done'
- autoCapitalize='none'
- autoFocus
- onSubmitEditing={this.submit}
- placeholder={this.props.Accounts_EmailOrUsernamePlaceholder || 'Email or username'}
- />
- this.setState({ password })}
- secureTextEntry
- autoCorrect={false}
- returnKeyType='done'
- autoCapitalize='none'
- onSubmitEditing={this.submit}
- placeholder={this.props.Accounts_PasswordPlaceholder || 'Password'}
- />
- {this.renderTOTP()}
- {this.state.error}
+
+
+
+
+ this.setState({ username })}
+ keyboardType='email-address'
+ autoCorrect={false}
+ returnKeyType='done'
+ autoCapitalize='none'
+ autoFocus
+
+ underlineColorAndroid='transparent'
+ onSubmitEditing={this.submit}
+ placeholder={this.props.Accounts_EmailOrUsernamePlaceholder || 'Email or username'}
+ />
+ this.setState({ password })}
+ secureTextEntry
+ autoCorrect={false}
+ returnKeyType='done'
+ autoCapitalize='none'
+
+ underlineColorAndroid='transparent'
+ onSubmitEditing={this.submit}
+ placeholder={this.props.Accounts_PasswordPlaceholder || 'Password'}
+ />
+ {this.renderTOTP()}
+
+ LOGIN
+
+ {this.props.login.error && {this.props.login.error}}
+
+
+
);
}
diff --git a/app/views/roomsList.js b/app/views/roomsList.js
index fc89ea941..98b27260e 100644
--- a/app/views/roomsList.js
+++ b/app/views/roomsList.js
@@ -1,9 +1,9 @@
import ActionButton from 'react-native-action-button';
-// import { Navigation } from 'react-native-navigation';
+import { Navigation } from 'react-native-navigation';
import { ListView } from 'realm/react-native';
import React from 'react';
import PropTypes from 'prop-types';
-import { View, StyleSheet, TextInput } from 'react-native';
+import { View, StyleSheet, TextInput, Platform } from 'react-native';
import { connect } from 'react-redux';
import * as actions from '../actions';
import * as server from '../actions/connect';
@@ -67,7 +67,7 @@ const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
export default class RoomsListView extends React.Component {
static propTypes = {
- // navigator: PropTypes.object.isRequired,
+ navigator: PropTypes.object.isRequired,
server: PropTypes.string
}
@@ -81,8 +81,29 @@ export default class RoomsListView extends React.Component {
searchText: '',
login: false
};
+ this.data.addListener(this.updateState);
+ this.props.navigator.setOnNavigatorEvent(event => event.type === 'NavBarButtonPress' && event.id === 'servers' &&
+ Navigation.showModal({
+ screen: 'ListServer',
+ passProps: {},
+ navigatorStyle: {},
+ navigatorButtons: {},
+ animationType: 'slide-up'
+ }));
+ this.props.navigator.setSubTitle({
+ subtitle: this.props.server
+ });
+ }
+ componentWillMount() {
+ const button = Platform.OS === 'ios' ? 'leftButtons' : 'rightButtons';
+ this.props.navigator.setButtons({
+ [button]: [{
+ id: 'servers',
+ title: 'Servers'
+ }],
+ animated: true
+ });
}
-
componentWillUnmount() {
this.data.removeListener(this.updateState);
}
@@ -148,16 +169,16 @@ export default class RoomsListView extends React.Component {
updateState = () => {
this.setState({
- dataSource: ds.cloneWithRows(this.state.data)
+ dataSource: ds.cloneWithRows(this.data)
});
};
_onPressItem = (id, item = {}) => {
const navigateToRoom = (room) => {
- // this.props.navigator.push({
- // screen: 'Room',
- // passProps: room
- // });
+ this.props.navigator.push({
+ screen: 'Room',
+ passProps: room
+ });
};
const clearSearch = () => {
@@ -218,6 +239,7 @@ export default class RoomsListView extends React.Component {
this._onPressItem(item._id, item)}
/>
)
@@ -234,15 +256,10 @@ export default class RoomsListView extends React.Component {
)
renderCreateButtons = () => (
);
- render= () => {
- if (this.props.canShowList) {
- return (
-
-
- {this.renderList()}
- {this.renderCreateButtons()}
- );
- }
- return null;
- }
+ render= () => (
+
+
+ {this.renderList()}
+ {this.renderCreateButtons()}
+ )
}
diff --git a/app/views/serverList.js b/app/views/serverList.js
index ab7156cb0..421e7bc58 100644
--- a/app/views/serverList.js
+++ b/app/views/serverList.js
@@ -1,4 +1,6 @@
import React from 'react';
+
+import Icon from 'react-native-vector-icons/Ionicons';
import PropTypes from 'prop-types';
import { Navigation } from 'react-native-navigation';
import Zeroconf from 'react-native-zeroconf';
@@ -6,6 +8,8 @@ import { View, Text, SectionList, Platform, StyleSheet } from 'react-native';
import { connect } from 'react-redux';
import { setServer } from '../actions/server';
import realm from '../lib/realm';
+import Fade from '../animations/fade';
+import Banner from '../components/banner';
const styles = StyleSheet.create({
view: {
@@ -27,11 +31,6 @@ const styles = StyleSheet.create({
textAlign: 'center',
color: '#888'
},
- listItem: {
- lineHeight: 18,
- color: '#666',
- padding: 14
- },
container: {
flex: 1
},
@@ -44,6 +43,21 @@ const styles = StyleSheet.create({
lineHeight: 24,
paddingLeft: 14,
color: '#888'
+ },
+ serverItem: {
+ flex: 1,
+ flexDirection: 'row',
+ // justifyContent: 'center',
+ alignItems: 'center',
+ backgroundColor: '#fff',
+ padding: 14
+ },
+
+ listItem: {
+ color: '#666', flexGrow: 1, lineHeight: 30
+ },
+ serverChecked: {
+ flexGrow: 0
}
});
@@ -166,12 +180,16 @@ export default class ListServerView extends React.Component {
}
renderItem = ({ item }) => (
- { this.onPressItem(item); }}
- >
- {item.id}
-
+
+
+ { this.onPressItem(item); }}
+ >
+ {item.id}
+
+
+
);
renderSectionHeader = ({ section }) => (
@@ -185,6 +203,7 @@ export default class ListServerView extends React.Component {
render() {
return (
+