Cleaning up refactors code, fixing sagas. By Gazzo
This commit is contained in:
parent
c498901aac
commit
46b491cf32
|
@ -10,9 +10,10 @@ function createRequestTypes(base, types = defaultTypes) {
|
|||
}
|
||||
|
||||
// Login events
|
||||
export const LOGIN = createRequestTypes('LOGIN');
|
||||
export const LOGIN = createRequestTypes('LOGIN', [...defaultTypes, 'SET_TOKEN']);
|
||||
export const ROOMS = createRequestTypes('ROOMS');
|
||||
export const MESSAGES = createRequestTypes('MESSAGES');
|
||||
export const SERVER = createRequestTypes('SERVER', ['SELECT', 'CHANGED']);
|
||||
export const METEOR = createRequestTypes('METEOR_CONNECT', [...defaultTypes, 'DISCONNECT']);
|
||||
export const LOGOUT = 'LOGOUT'; // logout is always success
|
||||
|
||||
|
|
|
@ -10,7 +10,8 @@ export function loginRequest(credentials) {
|
|||
export function loginSuccess(user) {
|
||||
return {
|
||||
type: types.LOGIN.SUCCESS,
|
||||
user
|
||||
user,
|
||||
token: user.token
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -21,8 +22,14 @@ export function loginFailure(err) {
|
|||
};
|
||||
}
|
||||
|
||||
export function setToken(token) {
|
||||
return {
|
||||
type: types.LOGIN.SET_TOKEN,
|
||||
token
|
||||
};
|
||||
}
|
||||
|
||||
export function logout() {
|
||||
console.log('LOGOUT');
|
||||
return {
|
||||
type: types.LOGOUT
|
||||
};
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import { SERVER } from './actionsTypes';
|
||||
|
||||
export function setServer(server) {
|
||||
return {
|
||||
type: SERVER.SELECT,
|
||||
server
|
||||
};
|
||||
}
|
||||
export function changedServer(server) {
|
||||
return {
|
||||
type: SERVER.CHANGED,
|
||||
server
|
||||
};
|
||||
}
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||
import { CachedImage } from 'react-native-img-cache';
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import PropTypes from 'prop-types';
|
||||
import { View, Text, StyleSheet } from 'react-native';
|
||||
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
|
||||
|
||||
import avatarInitialsAndColor from '../utils/avatarInitialsAndColor';
|
||||
|
||||
|
@ -106,16 +106,17 @@ export default class RoomItem extends React.PureComponent {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { item } = this.props;
|
||||
let extraSpace = {};
|
||||
if (this.props.item.unread) {
|
||||
if (item.unread) {
|
||||
extraSpace = { paddingRight: 92 };
|
||||
}
|
||||
return (
|
||||
<View style={[styles.container, extraSpace]}>
|
||||
<TouchableOpacity key={item._id} onPress={() => this.props.onPress(item._id, item)} style={[styles.container, extraSpace]}>
|
||||
{this.icon}
|
||||
<Text style={styles.roomName} ellipsizeMode='tail' numberOfLines={1}>{ this.props.item.name }</Text>
|
||||
{this.renderNumber(this.props.item)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,8 +14,8 @@ const styles = StyleSheet.create({
|
|||
});
|
||||
|
||||
@connect(state => ({
|
||||
connecting: state.meteor && state.meteor.connecting,
|
||||
authenticating: state.login && state.login.isFetching,
|
||||
connecting: state.meteor.connecting,
|
||||
authenticating: state.login.isFetching,
|
||||
offline: !state.meteor.connected
|
||||
}))
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Meteor from 'react-native-meteor';
|
||||
import { connect } from 'react-redux';
|
||||
import { CachedImage } from 'react-native-img-cache';
|
||||
import { Text, TouchableOpacity } from 'react-native';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
|
@ -24,6 +25,11 @@ const CustomButton = ({ text }) => (
|
|||
);
|
||||
|
||||
Navigation.registerComponent('CustomButton', () => CustomButton);
|
||||
@connect(state => ({
|
||||
base: state.settings.Site_Url,
|
||||
canShowList: state.login.token.length || state.login.user.token
|
||||
}))
|
||||
|
||||
export default class Cards extends React.PureComponent {
|
||||
static propTypes = {
|
||||
data: PropTypes.object.isRequired
|
||||
|
@ -33,7 +39,7 @@ export default class Cards extends React.PureComponent {
|
|||
const user = Meteor.user();
|
||||
this.state = {};
|
||||
RocketChat.getUserToken().then((token) => {
|
||||
this.setState({ img: `${ RocketChat.currentServer }${ this.props.data.image_url }?rc_uid=${ user._id }&rc_token=${ token }` });
|
||||
this.setState({ img: `${ this.props.base }${ this.props.data.image_url }?rc_uid=${ user._id }&rc_token=${ token }` });
|
||||
});
|
||||
}
|
||||
_onPressButton() {
|
||||
|
|
|
@ -20,6 +20,6 @@ if (__DEV__) {
|
|||
|
||||
export default createStore(
|
||||
reducers,
|
||||
applyMiddleware(sagaMiddleware)
|
||||
applyMiddleware(...middleware)
|
||||
);
|
||||
sagaMiddleware.run(sagas);
|
||||
|
|
|
@ -9,7 +9,7 @@ import settingsType from '../constants/settings';
|
|||
import realm from './realm';
|
||||
import * as actions from '../actions';
|
||||
import { disconnect, connectSuccess } from '../actions/connect';
|
||||
import { logout, loginSuccess } from '../actions/login';
|
||||
import { loginSuccess } from '../actions/login';
|
||||
|
||||
export { Accounts } from 'react-native-meteor';
|
||||
|
||||
|
@ -29,18 +29,6 @@ const RocketChat = {
|
|||
});
|
||||
},
|
||||
|
||||
get currentServer() {
|
||||
const current = realm.objects('servers').filtered('current = true').slice(0, 1)[0];
|
||||
return current && current.id;
|
||||
},
|
||||
|
||||
set currentServer(server) {
|
||||
realm.write(() => {
|
||||
realm.objects('servers').filtered('current = true').forEach(item => (item.current = false));
|
||||
realm.create('servers', { id: server, current: true }, true);
|
||||
});
|
||||
},
|
||||
|
||||
async getUserToken() {
|
||||
const TOKEN_KEY = 'reactnativemeteor_usertoken';
|
||||
try {
|
||||
|
@ -50,23 +38,20 @@ const RocketChat = {
|
|||
}
|
||||
},
|
||||
|
||||
connect(cb) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = `${ RocketChat.currentServer }/websocket`;
|
||||
connect(_url) {
|
||||
return new Promise((resolve) => {
|
||||
const url = `${ _url }/websocket`;
|
||||
|
||||
Meteor.connect(url, { autoConnect: true, autoReconnect: true });
|
||||
// , { autoConnect: false, autoReconnect: false }
|
||||
Meteor.ddp.on('disconnected', () => {
|
||||
console.log('disconnected');
|
||||
reduxStore.dispatch(disconnect());
|
||||
});
|
||||
Meteor.ddp.on('connected', (err) => {
|
||||
console.log('connected');
|
||||
Meteor.ddp.on('connected', () => {
|
||||
reduxStore.dispatch(connectSuccess());
|
||||
resolve();
|
||||
});
|
||||
Meteor.ddp.on('loggin', () => {
|
||||
console.log('Meteor.ddp.on(\'loggin\',');
|
||||
reduxStore.dispatch(loginSuccess({}));
|
||||
});
|
||||
Meteor.ddp.on('connected', () => {
|
||||
|
@ -81,7 +66,7 @@ const RocketChat = {
|
|||
const setting = {
|
||||
_id: item._id
|
||||
};
|
||||
setting._server = { id: RocketChat.currentServer };
|
||||
setting._server = { id: reduxStore.getState().server };
|
||||
if (settingsType[item.type]) {
|
||||
setting[settingsType[item.type]] = item.value;
|
||||
realm.create('settings', setting, true);
|
||||
|
@ -91,10 +76,6 @@ const RocketChat = {
|
|||
});
|
||||
});
|
||||
reduxStore.dispatch(actions.setAllSettings(settings));
|
||||
|
||||
if (typeof cb === 'function') {
|
||||
cb();
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.ddp.on('changed', (ddbMessage) => {
|
||||
|
@ -103,7 +84,7 @@ const RocketChat = {
|
|||
realm.write(() => {
|
||||
const message = ddbMessage.fields.args[0];
|
||||
message.temp = false;
|
||||
message._server = { id: RocketChat.currentServer };
|
||||
message._server = { id: reduxStore.getState().server };
|
||||
// write('messages', message);
|
||||
realm.create('messages', message, true);
|
||||
});
|
||||
|
@ -113,24 +94,27 @@ const RocketChat = {
|
|||
// console.log(ddbMessage);
|
||||
realm.write(() => {
|
||||
const data = ddbMessage.fields.args[1];
|
||||
data._server = { id: RocketChat.currentServer };
|
||||
data._server = { id: reduxStore.getState().server };
|
||||
realm.create('subscriptions', data, true);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(e => console.error(e));
|
||||
},
|
||||
|
||||
login(params, callback) {
|
||||
return new Promise((resolve, reject) => {
|
||||
Meteor._startLoggingIn();
|
||||
console.log('meteor login', params);
|
||||
return Meteor.call('login', params, (err, result) => {
|
||||
Meteor._endLoggingIn();
|
||||
Meteor._handleLoginCallback(err, result);
|
||||
console.log(result);
|
||||
err ? reject(err) : resolve(result);
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
if (typeof callback === 'function') {
|
||||
callback(err, result);
|
||||
}
|
||||
|
@ -194,7 +178,7 @@ const RocketChat = {
|
|||
// if (typeof item.value === 'string') {
|
||||
// subscription.value = item.value;
|
||||
// }
|
||||
subscription._server = { id: RocketChat.currentServer };
|
||||
subscription._server = { id: reduxStore.getState().server };
|
||||
// write('subscriptions', subscription);
|
||||
realm.create('subscriptions', subscription, true);
|
||||
});
|
||||
|
@ -218,7 +202,7 @@ const RocketChat = {
|
|||
realm.write(() => {
|
||||
data.messages.forEach((message) => {
|
||||
message.temp = false;
|
||||
message._server = { id: RocketChat.currentServer };
|
||||
message._server = { id: reduxStore.getState().server };
|
||||
// write('messages', message);
|
||||
realm.create('messages', message, true);
|
||||
});
|
||||
|
@ -240,7 +224,6 @@ const RocketChat = {
|
|||
|
||||
getMessage(rid, msg = {}) {
|
||||
const _id = Random.id();
|
||||
const user = Meteor.user();
|
||||
const message = {
|
||||
_id,
|
||||
rid,
|
||||
|
@ -248,10 +231,10 @@ const RocketChat = {
|
|||
ts: new Date(),
|
||||
_updatedAt: new Date(),
|
||||
temp: true,
|
||||
_server: { id: RocketChat.currentServer },
|
||||
_server: { id: reduxStore.getState().server },
|
||||
u: {
|
||||
_id: user._id,
|
||||
username: user.username
|
||||
_id: reduxStore.getState()._id,
|
||||
username: reduxStore.getState()._id
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -400,16 +383,13 @@ const RocketChat = {
|
|||
// if (typeof item.value === 'string') {
|
||||
// subscription.value = item.value;
|
||||
// }
|
||||
subscription._server = { id: RocketChat.currentServer };
|
||||
subscription._server = { id: reduxStore.getState().server };
|
||||
// write('subscriptions', subscription);
|
||||
realm.create('subscriptions', subscription, true);
|
||||
});
|
||||
});
|
||||
return data;
|
||||
}).then((data) => {
|
||||
console.log('subscriptions done.');
|
||||
return data;
|
||||
});
|
||||
}).then(data => data);
|
||||
// });
|
||||
},
|
||||
logout() {
|
||||
|
@ -418,9 +398,3 @@ const RocketChat = {
|
|||
};
|
||||
|
||||
export default RocketChat;
|
||||
|
||||
if (RocketChat.currentServer) {
|
||||
reduxStore.dispatch(actions.setCurrentServer(RocketChat.currentServer));
|
||||
}
|
||||
// Use for logout
|
||||
// AsyncStorage.clear();
|
||||
|
|
|
@ -20,8 +20,8 @@ Navigation.registerComponent('CreateChannel', () => CreateChannel, store, Provid
|
|||
|
||||
Navigation.startSingleScreenApp({
|
||||
screen: {
|
||||
screen: 'Rooms',
|
||||
title: 'Channels'
|
||||
screen: 'ListServer',
|
||||
title: 'ListServer'
|
||||
},
|
||||
animationType: 'none'
|
||||
});
|
||||
|
|
|
@ -3,10 +3,9 @@ import * as reducers from './reducers';
|
|||
import login from './login';
|
||||
import meteor from './connect';
|
||||
import messages from './messages';
|
||||
import server from './server';
|
||||
|
||||
|
||||
console.log(Object.keys({
|
||||
...reducers, login, meteor, messages
|
||||
}));
|
||||
export default combineReducers({
|
||||
...reducers, login, meteor, messages
|
||||
...reducers, login, meteor, messages, server
|
||||
});
|
||||
|
|
|
@ -32,11 +32,14 @@ export default function login(state = initialState, action) {
|
|||
errorMessage: action.err
|
||||
};
|
||||
case types.LOGOUT:
|
||||
console.log('LOGOUT');
|
||||
return { ...state,
|
||||
isFetching: false,
|
||||
isAuthenticated: false
|
||||
};
|
||||
case types.LOGIN.SET_TOKEN:
|
||||
return { ...state,
|
||||
token: action.token
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -1,17 +1,7 @@
|
|||
import RocketChat from '../lib/rocketchat';
|
||||
import * as types from '../constants/types';
|
||||
import initialState from './initialState';
|
||||
|
||||
export function server(state = initialState.server, action) {
|
||||
if (action.type === types.SET_CURRENT_SERVER) {
|
||||
RocketChat.currentServer = action.payload;
|
||||
return action.payload;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
export function settings(state = initialState.settings, action) {
|
||||
export default function settings(state = initialState.settings, action) {
|
||||
if (action.type === types.SET_ALL_SETTINGS) {
|
||||
return { ...state,
|
||||
...action.payload
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
import { SERVER } from '../actions/actionsTypes';
|
||||
|
||||
export default function server(state = '', action) {
|
||||
switch (action.type) {
|
||||
case SERVER.SELECT:
|
||||
return action.server;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
|
@ -1,33 +1,26 @@
|
|||
import { take, put, call, fork, takeLatest } from 'redux-saga/effects';
|
||||
import { take, put, call, fork, takeLatest, select } from 'redux-saga/effects';
|
||||
import { METEOR } from '../actions/actionsTypes';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
|
||||
import { connectSuccess, connectRequest, connectFailure } from '../actions/connect';
|
||||
import { connectSuccess, connectFailure } from '../actions/connect';
|
||||
|
||||
function connect(...args) {
|
||||
return RocketChat.connect(...args);
|
||||
}
|
||||
const auto = function* auto() {
|
||||
while (true) {
|
||||
yield take(METEOR.DISCONNECT);
|
||||
console.log('\n\n[METEOR DISCONNECT]\n\n');
|
||||
yield put(connectRequest());
|
||||
const getServer = ({ server }) => server;
|
||||
|
||||
|
||||
const connect = url => RocketChat.connect(url);
|
||||
const test = function* test() {
|
||||
try {
|
||||
const server = yield select(getServer);
|
||||
const response = yield call(connect, server);
|
||||
yield put(connectSuccess(response));
|
||||
} catch (err) {
|
||||
yield put(connectFailure(err.status));
|
||||
}
|
||||
};
|
||||
const test = function* test() {
|
||||
const response = yield call(connect);
|
||||
yield put(connectSuccess(response));
|
||||
console.log('\n\n[METEOR CONNECTED]\n\n');
|
||||
};
|
||||
const watchConnect = function* watchConnect() {
|
||||
yield takeLatest(METEOR.REQUEST, test);
|
||||
while (true) {
|
||||
try {
|
||||
yield takeLatest(METEOR.REQUEST, test);
|
||||
} catch (err) {
|
||||
yield put(connectFailure(err.status));
|
||||
}
|
||||
yield take(METEOR.DISCONNECT);
|
||||
console.log('\n\n[METEOR DISCONNECT]\n\n');
|
||||
}
|
||||
};
|
||||
const root = function* root() {
|
||||
|
|
|
@ -3,16 +3,16 @@ import hello from './hello';
|
|||
import login from './login';
|
||||
import connect from './connect';
|
||||
import rooms from './rooms';
|
||||
import logger from './logger';
|
||||
import messages from './messages';
|
||||
import selectServer from './selectServer';
|
||||
|
||||
const root = function* root() {
|
||||
yield fork(hello);
|
||||
yield fork(rooms);
|
||||
yield fork(login);
|
||||
yield fork(connect);
|
||||
yield fork(logger);
|
||||
yield fork(messages);
|
||||
yield fork(selectServer);
|
||||
};
|
||||
// Consider using takeEvery
|
||||
export default root;
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
import { select, takeEvery } from 'redux-saga/effects';
|
||||
|
||||
const root = function* watchAndLog() {
|
||||
// yield takeEvery('*', function* logger(action) {
|
||||
// const state = yield select();
|
||||
// const tmp = { ...state };
|
||||
// delete tmp.settings;
|
||||
// console.log('action', action);
|
||||
// console.log('state after', tmp);
|
||||
// });
|
||||
};
|
||||
export default root;
|
|
@ -1,48 +1,55 @@
|
|||
import React from 'react';
|
||||
import { take, put, call, takeLast, fork, select } from 'redux-saga/effects';
|
||||
import { AsyncStorage } from 'react-native';
|
||||
import { take, put, call, takeEvery, fork, select, all } from 'redux-saga/effects';
|
||||
import * as types from '../actions/actionsTypes';
|
||||
import { loginRequest, loginSuccess, loginFailure, logout } from '../actions/login';
|
||||
import { loginRequest, loginSuccess, loginFailure, setToken } from '../actions/login';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
|
||||
const TOKEN_KEY = 'reactnativemeteor_usertoken';
|
||||
const getUser = state => state.login.user;
|
||||
function loginCall(args) {
|
||||
return args.resume ? RocketChat.login(args) : RocketChat.loginWithPassword(args);
|
||||
}
|
||||
const auto = function* auto() {
|
||||
while (true) {
|
||||
yield take(types.LOGOUT);
|
||||
yield take(types.METEOR.SUCCESS);
|
||||
const user = yield select(getUser);
|
||||
if (user.token) {
|
||||
yield put(loginRequest({ resume: user.token }));
|
||||
}
|
||||
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 watchLoginRequest = function* watchLoginRequest() {
|
||||
while (true) {
|
||||
do {
|
||||
try {
|
||||
yield take(types.METEOR.SUCCESS);
|
||||
// console.log('\n\n[LOGIN METEOR CONNECTED]\n\n');
|
||||
const payload = yield take(types.LOGIN.REQUEST);
|
||||
try {
|
||||
const response = yield call(loginCall, payload);
|
||||
yield put(loginSuccess(response));
|
||||
console.log('\n\n[LOGIN SUCCESS]\n\n');
|
||||
} catch (err) {
|
||||
// console.log('\n\n[LOGIN FAILURE]\n\n', err);
|
||||
yield put(loginFailure(err.status));
|
||||
yield all([take(types.METEOR.SUCCESS), take(types.SERVER.CHANGED)]);
|
||||
const token = yield call(getToken);
|
||||
if (token) {
|
||||
yield put(loginRequest({ resume: token }));
|
||||
}
|
||||
yield take(types.METEOR.DISCONNECT);
|
||||
console.log('\n\n[METEOR DISCONNECT LOGOUT]\n\n');
|
||||
yield put(logout());
|
||||
} catch (e) {
|
||||
console.error(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);
|
||||
};
|
||||
|
||||
const root = function* root() {
|
||||
yield fork(watchLoginRequest);
|
||||
yield fork(auto);
|
||||
yield takeEvery(types.LOGIN.REQUEST, sagaLogin);
|
||||
yield takeEvery(types.LOGIN.SUCCESS, saveToken);
|
||||
};
|
||||
export default root;
|
||||
|
|
|
@ -1,28 +1,21 @@
|
|||
import { take, put, call, fork } from 'redux-saga/effects';
|
||||
import { put, call, takeEvery } from 'redux-saga/effects';
|
||||
import * as types from '../actions/actionsTypes';
|
||||
import { roomsSuccess, roomsFailure } from '../actions/rooms';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
|
||||
function getRooms(...args) {
|
||||
// console.log('\n\n\n\n\n\naqui\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n');
|
||||
return RocketChat.getRooms(...args);
|
||||
}
|
||||
|
||||
const watchRoomsRequest = function* watchRoomsRequest() {
|
||||
// console.log('\n\n\n\n\n\n\n\nWAINTING FOR LOGINsss\n\n\n\n\n\n\n\n');
|
||||
while (true) {
|
||||
// console.log('\n\n\n\n\n\n\n\nWAINTING FOR LOGIN\n\n\n\n\n\n\n\n');
|
||||
yield take(types.LOGIN.SUCCESS);
|
||||
// console.log('\n\n\n\n\n\n\n\nWAINTING FOR LOGIN NO MORE\n\n\n\n\n\n\n\n');
|
||||
// const payload = yield take(types.ROOMS.REQUEST);
|
||||
try {
|
||||
yield call(getRooms);
|
||||
yield put(roomsSuccess());
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
yield put(roomsFailure(err.status));
|
||||
}
|
||||
}
|
||||
const getRooms = function* getRooms() {
|
||||
return yield RocketChat.getRooms();
|
||||
};
|
||||
|
||||
export default watchRoomsRequest;
|
||||
const watchRoomsRequest = function* watchRoomsRequest() {
|
||||
try {
|
||||
yield call(getRooms);
|
||||
yield put(roomsSuccess());
|
||||
} catch (err) {
|
||||
yield put(roomsFailure(err.status));
|
||||
}
|
||||
};
|
||||
const root = function* root() {
|
||||
yield takeEvery(types.LOGIN.SUCCESS, watchRoomsRequest);
|
||||
};
|
||||
export default root;
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
import { put, takeEvery } from 'redux-saga/effects';
|
||||
|
||||
import { SERVER } from '../actions/actionsTypes';
|
||||
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);
|
||||
}
|
||||
};
|
||||
const root = function* root() {
|
||||
yield takeEvery(SERVER.SELECT, selectServer);
|
||||
};
|
||||
export default root;
|
|
@ -68,27 +68,6 @@ class LoginView extends React.Component {
|
|||
console.log({ username, password, code });
|
||||
this.props.loginRequest({ username, password, code });
|
||||
this.props.navigator.dismissModal();
|
||||
//
|
||||
//
|
||||
// this.setState({
|
||||
// error: undefined
|
||||
// });
|
||||
//
|
||||
//
|
||||
// RocketChat.loginWithPassword(credentials, (error) => {
|
||||
// if (error) {
|
||||
// if (error.error === 'totp-required') {
|
||||
// this.setState({ totp: true });
|
||||
// this.codeInput.focus();
|
||||
// } else {
|
||||
// this.setState({
|
||||
// error: error.reason
|
||||
// });
|
||||
// }
|
||||
// } else {
|
||||
// this.props.navigator.dismissModal();
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
renderTOTP = () => {
|
||||
|
@ -147,7 +126,7 @@ function mapStateToProps(state) {
|
|||
server: state.server,
|
||||
Accounts_EmailOrUsernamePlaceholder: state.settings.Accounts_EmailOrUsernamePlaceholder,
|
||||
Accounts_PasswordPlaceholder: state.settings.Accounts_PasswordPlaceholder,
|
||||
login: state.login || state.default
|
||||
login: state.login
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,20 +1,16 @@
|
|||
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 Icon from 'react-native-vector-icons/Ionicons';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Text, View, StyleSheet, TouchableOpacity, Platform, TextInput } from 'react-native';
|
||||
import Meteor from 'react-native-meteor';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { View, StyleSheet, TextInput } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import * as actions from '../actions';
|
||||
import * as meteor from '../actions/connect';
|
||||
import * as server from '../actions/connect';
|
||||
import realm from '../lib/realm';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
import RoomItem from '../components/RoomItem';
|
||||
import Banner from '../components/banner';
|
||||
// import debounce from '../utils/debounce';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -58,106 +54,37 @@ const styles = StyleSheet.create({
|
|||
});
|
||||
|
||||
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
|
||||
class RoomsListItem extends React.PureComponent {
|
||||
static propTypes = {
|
||||
item: PropTypes.object.isRequired,
|
||||
onPress: PropTypes.func.isRequired,
|
||||
baseUrl: PropTypes.string
|
||||
}
|
||||
_onPress = (...args) => {
|
||||
this.props.onPress(...args);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { item } = this.props;
|
||||
return (
|
||||
<TouchableOpacity key={item._id} onPress={() => this.props.onPress(item._id, item)}>
|
||||
<RoomItem
|
||||
id={item._id}
|
||||
item={item}
|
||||
baseUrl={this.props.baseUrl}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@connect(state => ({
|
||||
server: state.server,
|
||||
Site_Url: state.settings.Site_Url
|
||||
login: state.login,
|
||||
Site_Url: state.settings.Site_Url,
|
||||
canShowList: state.login.token.length || state.login.user.token
|
||||
}), dispatch => ({
|
||||
actions: bindActionCreators(actions, dispatch),
|
||||
login: () => dispatch(actions.login()),
|
||||
connect: () => dispatch(meteor.connectRequest())
|
||||
connect: () => dispatch(server.connectRequest())
|
||||
}))
|
||||
|
||||
export default class RoomsListView extends React.Component {
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object.isRequired,
|
||||
server: PropTypes.string,
|
||||
Site_Url: PropTypes.string
|
||||
// navigator: PropTypes.object.isRequired,
|
||||
server: PropTypes.string
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
// this.data = realm.objects('subscriptions').filtered('_server.id = $0', this.props.server);
|
||||
this.data = realm.objects('subscriptions').filtered('_server.id = $0', this.props.server);
|
||||
this.state = {
|
||||
dataSource: ds.cloneWithRows([]),
|
||||
dataSource: ds.cloneWithRows(this.data),
|
||||
searching: false,
|
||||
searchDataSource: [],
|
||||
searchText: ''
|
||||
searchText: '',
|
||||
login: false
|
||||
};
|
||||
|
||||
this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const button = Platform.OS === 'ios' ? 'leftButtons' : 'rightButtons';
|
||||
this.props.navigator.setButtons({
|
||||
[button]: [{
|
||||
id: 'servers',
|
||||
title: 'Servers'
|
||||
}],
|
||||
animated: true
|
||||
});
|
||||
|
||||
if (this.props.server) {
|
||||
this.setInitialData();
|
||||
} else {
|
||||
Navigation.showModal({
|
||||
screen: 'ListServer',
|
||||
passProps: {},
|
||||
navigatorStyle: {},
|
||||
navigatorButtons: {},
|
||||
animationType: 'none'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.server !== this.props.server) {
|
||||
this.setInitialData(nextProps);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.state.data.removeListener(this.updateState);
|
||||
}
|
||||
|
||||
onNavigatorEvent = (event) => {
|
||||
if (event.type === 'NavBarButtonPress') {
|
||||
if (event.id === 'servers') {
|
||||
Navigation.showModal({
|
||||
screen: 'ListServer',
|
||||
passProps: {},
|
||||
navigatorStyle: {},
|
||||
navigatorButtons: {},
|
||||
animationType: 'slide-up'
|
||||
// animationType: 'none'
|
||||
});
|
||||
}
|
||||
}
|
||||
this.data.removeListener(this.updateState);
|
||||
}
|
||||
|
||||
onSearchChangeText = (text) => {
|
||||
|
@ -168,11 +95,11 @@ export default class RoomsListView extends React.Component {
|
|||
});
|
||||
if (searchText === '') {
|
||||
return this.setState({
|
||||
dataSource: ds.cloneWithRows(this.state.data)
|
||||
dataSource: ds.cloneWithRows(this.data)
|
||||
});
|
||||
}
|
||||
|
||||
const data = this.state.data.filtered('name CONTAINS[c] $0', searchText).slice();
|
||||
const data = this.data.filtered('name CONTAINS[c] $0', searchText).slice();
|
||||
|
||||
const usernames = [];
|
||||
const dataSource = data.map((sub) => {
|
||||
|
@ -218,31 +145,6 @@ export default class RoomsListView extends React.Component {
|
|||
});
|
||||
}
|
||||
|
||||
setInitialData = (props = this.props) => {
|
||||
// console.log(this.props);
|
||||
this.props.connect();
|
||||
props.navigator.setSubTitle({
|
||||
subtitle: props.server
|
||||
});
|
||||
RocketChat.getUserToken().then((token) => {
|
||||
if (!token) {
|
||||
Navigation.showModal({
|
||||
screen: 'Login',
|
||||
animationType: 'slide-up'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const data = realm.objects('subscriptions').filtered('_server.id = $0', props.server).sorted('_updatedAt', true);
|
||||
|
||||
this.setState({
|
||||
dataSource: ds.cloneWithRows(data),
|
||||
data
|
||||
});
|
||||
|
||||
data.addListener(this.updateState);
|
||||
});
|
||||
}
|
||||
|
||||
updateState = () => {
|
||||
this.setState({
|
||||
|
@ -252,10 +154,10 @@ export default class RoomsListView extends React.Component {
|
|||
|
||||
_onPressItem = (id, item = {}) => {
|
||||
const navigateToRoom = (room) => {
|
||||
this.props.navigator.push({
|
||||
screen: 'Room',
|
||||
passProps: room
|
||||
});
|
||||
// this.props.navigator.push({
|
||||
// screen: 'Room',
|
||||
// passProps: room
|
||||
// });
|
||||
};
|
||||
|
||||
const clearSearch = () => {
|
||||
|
@ -297,26 +199,10 @@ export default class RoomsListView extends React.Component {
|
|||
clearSearch();
|
||||
}
|
||||
|
||||
_createChannel = () => {
|
||||
this.props.navigator.showModal({
|
||||
screen: 'CreateChannel'
|
||||
});
|
||||
}
|
||||
renderItem = ({ item }) => (
|
||||
<RoomsListItem
|
||||
item={item}
|
||||
onPress={() => this._onPressItem(item._id, item)}
|
||||
baseUrl={this.props.Site_Url}
|
||||
/>
|
||||
);
|
||||
|
||||
renderSeparator = () => (
|
||||
<View style={styles.separator} />
|
||||
);
|
||||
|
||||
renderSearchBar = () => (
|
||||
<View style={styles.searchBoxView}>
|
||||
<TextInput
|
||||
underlineColorAndroid='transparent'
|
||||
style={styles.searchBox}
|
||||
value={this.state.searchText}
|
||||
onChangeText={this.onSearchChangeText}
|
||||
|
@ -328,44 +214,35 @@ export default class RoomsListView extends React.Component {
|
|||
</View>
|
||||
);
|
||||
|
||||
// if (!this.state.searching && !this.state.dataSource.length) {
|
||||
// return (
|
||||
// <View style={styles.emptyView}>
|
||||
// <Text style={styles.emptyText}>No rooms</Text>
|
||||
// </View>
|
||||
// );
|
||||
// }
|
||||
renderItem = item => (
|
||||
<RoomItem
|
||||
id={item._id}
|
||||
item={item}
|
||||
onPress={() => this._onPressItem(item._id, item)}
|
||||
/>
|
||||
)
|
||||
renderList = () => (
|
||||
// data={this.state.searching ? this.state.searchDataSource : this.state.dataSource}
|
||||
// keyExtractor={item => item._id}
|
||||
// ItemSeparatorComponent={this.renderSeparator}
|
||||
// renderItem={this.renderItem}
|
||||
<ListView
|
||||
dataSource={this.state.dataSource}
|
||||
style={styles.list}
|
||||
renderRow={item => this.renderItem({ item })}
|
||||
renderRow={this.renderItem}
|
||||
renderHeader={this.renderSearchBar}
|
||||
contentOffset={{ x: 0, y: 20 }}
|
||||
enableEmptySections
|
||||
keyboardShouldPersistTaps='always'
|
||||
/>
|
||||
)
|
||||
|
||||
renderCreateButtons() {
|
||||
return (
|
||||
<ActionButton buttonColor='rgba(231,76,60,1)'>
|
||||
<ActionButton.Item buttonColor='#9b59b6' title='Create Channel' onPress={() => { this.props.login(); }} >
|
||||
<Icon name='md-chatbubbles' style={styles.actionButtonIcon} />
|
||||
</ActionButton.Item>
|
||||
</ActionButton>);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Banner />
|
||||
{this.renderList()}
|
||||
{this.renderCreateButtons()}
|
||||
</View>
|
||||
);
|
||||
renderCreateButtons = () => (
|
||||
<ActionButton buttonColor='rgba(231,76,60,1)' />);
|
||||
render= () => {
|
||||
if (this.props.canShowList) {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Banner />
|
||||
{this.renderList()}
|
||||
{this.renderCreateButtons()}
|
||||
</View>);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import Zeroconf from 'react-native-zeroconf';
|
||||
import { View, Text, SectionList, Platform, StyleSheet } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import * as actions from '../actions';
|
||||
import { setServer } from '../actions/server';
|
||||
import realm from '../lib/realm';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
view: {
|
||||
|
@ -56,7 +53,7 @@ const zeroconf = new Zeroconf();
|
|||
@connect(state => ({
|
||||
server: state.server
|
||||
}), dispatch => ({
|
||||
actions: bindActionCreators(actions, dispatch)
|
||||
selectServer: server => dispatch(setServer(server))
|
||||
}))
|
||||
export default class ListServerView extends React.Component {
|
||||
static propTypes = {
|
||||
|
@ -131,14 +128,7 @@ export default class ListServerView extends React.Component {
|
|||
}
|
||||
|
||||
onPressItem = (item) => {
|
||||
RocketChat.logout();
|
||||
Navigation.dismissModal({
|
||||
animationType: 'slide-down'
|
||||
});
|
||||
|
||||
this.setState({
|
||||
server: item.id
|
||||
});
|
||||
this.props.selectServer(item.id);
|
||||
}
|
||||
|
||||
getState = () => {
|
||||
|
@ -177,7 +167,7 @@ export default class ListServerView extends React.Component {
|
|||
|
||||
renderItem = ({ item }) => (
|
||||
<Text
|
||||
style={styles.listItem}
|
||||
style={[styles.listItem, this.props.server === item.id ? { backgroundColor: 'red' } : {}]}
|
||||
onPress={() => { this.onPressItem(item); }}
|
||||
>
|
||||
{item.id}
|
||||
|
|
Loading…
Reference in New Issue