Create room (#42)
* Added select users view * create room working * - Show photo on avatar * Switched state for redux * Navigating to created room
This commit is contained in:
parent
d55db0fca5
commit
e0777a969e
|
@ -1,11 +1,10 @@
|
|||
|
||||
const REQUEST = 'REQUEST';
|
||||
const SUCCESS = 'SUCCESS';
|
||||
const FAILURE = 'FAILURE';
|
||||
const defaultTypes = [REQUEST, SUCCESS, FAILURE];
|
||||
function createRequestTypes(base, types = defaultTypes) {
|
||||
const res = {};
|
||||
types.forEach(type => res[type] = `${ base }_${ type }`);
|
||||
types.forEach(type => (res[type] = `${ base }_${ type }`));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -14,7 +13,16 @@ export const LOGIN = createRequestTypes('LOGIN', [...defaultTypes, 'SET_TOKEN',
|
|||
export const ROOMS = createRequestTypes('ROOMS');
|
||||
export const APP = createRequestTypes('APP', ['READY', 'INIT']);
|
||||
export const MESSAGES = createRequestTypes('MESSAGES');
|
||||
export const CREATE_CHANNEL = createRequestTypes('CREATE_CHANNEL', [...defaultTypes, 'REQUEST_USERS', 'SUCCESS_USERS', 'FAILURE_USERS', 'SET_USERS']);
|
||||
export const CREATE_CHANNEL = createRequestTypes('CREATE_CHANNEL', [
|
||||
...defaultTypes,
|
||||
'REQUEST_USERS',
|
||||
'SUCCESS_USERS',
|
||||
'FAILURE_USERS',
|
||||
'SET_USERS',
|
||||
'ADD_USER',
|
||||
'REMOVE_USER',
|
||||
'RESET'
|
||||
]);
|
||||
export const NAVIGATION = createRequestTypes('NAVIGATION', ['SET']);
|
||||
export const SERVER = createRequestTypes('SERVER', [...defaultTypes, 'SELECT', 'CHANGED', 'ADD']);
|
||||
export const METEOR = createRequestTypes('METEOR_CONNECT', [...defaultTypes, 'DISCONNECT']);
|
||||
|
|
|
@ -21,7 +21,6 @@ export function createChannelFailure(err) {
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
export function createChannelRequestUsers(data) {
|
||||
return {
|
||||
type: types.CREATE_CHANNEL.REQUEST_USERS,
|
||||
|
@ -49,3 +48,23 @@ export function createChannelFailureUsers(err) {
|
|||
err
|
||||
};
|
||||
}
|
||||
|
||||
export function addUser(user) {
|
||||
return {
|
||||
type: types.CREATE_CHANNEL.ADD_USER,
|
||||
user
|
||||
};
|
||||
}
|
||||
|
||||
export function removeUser(user) {
|
||||
return {
|
||||
type: types.CREATE_CHANNEL.REMOVE_USER,
|
||||
user
|
||||
};
|
||||
}
|
||||
|
||||
export function reset() {
|
||||
return {
|
||||
type: types.CREATE_CHANNEL.RESET
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import { StackNavigator, DrawerNavigator } from 'react-navigation';
|
||||
import { Button } from 'react-native';
|
||||
import { StackNavigator, DrawerNavigator, NavigationActions } from 'react-navigation';
|
||||
// import { Platform } from 'react-native';
|
||||
|
||||
import Sidebar from '../../containers/Sidebar';
|
||||
|
@ -8,10 +9,18 @@ import DrawerMenuButton from '../../presentation/DrawerMenuButton';
|
|||
import RoomsListView from '../../views/RoomsListView';
|
||||
import RoomView from '../../views/RoomView';
|
||||
import CreateChannelView from '../../views/CreateChannelView';
|
||||
import SelectUsersView from '../../views/SelectUsersView';
|
||||
|
||||
const drawerPosition = 'left';
|
||||
const drawerIconPosition = 'headerLeft';
|
||||
|
||||
const backToScreen = (navigation, routeName) => {
|
||||
const action = NavigationActions.reset({
|
||||
index: 0,
|
||||
actions: [NavigationActions.navigate({ routeName })]
|
||||
});
|
||||
navigation.dispatch(action);
|
||||
};
|
||||
|
||||
const AuthRoutes = StackNavigator(
|
||||
{
|
||||
|
@ -20,7 +29,7 @@ const AuthRoutes = StackNavigator(
|
|||
navigationOptions({ navigation }) {
|
||||
return {
|
||||
title: 'Rooms',
|
||||
[drawerIconPosition]: (<DrawerMenuButton navigation={navigation} />)
|
||||
[drawerIconPosition]: <DrawerMenuButton navigation={navigation} />
|
||||
};
|
||||
}
|
||||
},
|
||||
|
@ -28,7 +37,10 @@ const AuthRoutes = StackNavigator(
|
|||
screen: RoomView,
|
||||
navigationOptions({ navigation }) {
|
||||
return {
|
||||
title: navigation.state.params.title || 'Room'
|
||||
title: navigation.state.params.title || 'Room',
|
||||
headerLeft: (
|
||||
<Button title={'Back'} onPress={() => backToScreen(navigation, 'RoomsList')} />
|
||||
)
|
||||
// [drawerIconPosition]: (<DrawerMenuButton navigation={navigation} />)÷
|
||||
};
|
||||
}
|
||||
|
@ -38,25 +50,33 @@ const AuthRoutes = StackNavigator(
|
|||
navigationOptions: {
|
||||
title: 'Create Channel'
|
||||
}
|
||||
},
|
||||
SelectUsers: {
|
||||
screen: SelectUsersView,
|
||||
navigationOptions: {
|
||||
title: 'Select Users'
|
||||
}
|
||||
}
|
||||
},
|
||||
{}
|
||||
);
|
||||
|
||||
const Routes = DrawerNavigator(
|
||||
{
|
||||
Home: {
|
||||
screen: AuthRoutes,
|
||||
navigationOptions({ navigation }) {
|
||||
return {
|
||||
title: 'Rooms',
|
||||
[drawerIconPosition]: <DrawerMenuButton navigation={navigation} />
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
contentComponent: Sidebar,
|
||||
drawerPosition
|
||||
}
|
||||
);
|
||||
|
||||
const Routes = DrawerNavigator({
|
||||
Home: {
|
||||
screen: AuthRoutes,
|
||||
navigationOptions({ navigation }) {
|
||||
return {
|
||||
title: 'Rooms',
|
||||
[drawerIconPosition]: (<DrawerMenuButton navigation={navigation} />)
|
||||
};
|
||||
}
|
||||
}
|
||||
}, {
|
||||
contentComponent: Sidebar,
|
||||
drawerPosition
|
||||
});
|
||||
|
||||
export default Routes;
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'regenerator-runtime/runtime';
|
|||
|
||||
import { createStore, applyMiddleware } from 'redux';
|
||||
import createSagaMiddleware from 'redux-saga';
|
||||
import logger from 'redux-logger';
|
||||
import { composeWithDevTools } from 'remote-redux-devtools';
|
||||
import reducers from '../reducers';
|
||||
import sagas from '../sagas';
|
||||
|
@ -13,9 +14,11 @@ let enhacers;
|
|||
if (__DEV__) {
|
||||
/* eslint-disable global-require */
|
||||
const reduxImmutableStateInvariant = require('redux-immutable-state-invariant').default();
|
||||
|
||||
enhacers = composeWithDevTools(
|
||||
applyMiddleware(reduxImmutableStateInvariant),
|
||||
applyMiddleware(sagaMiddleware)
|
||||
applyMiddleware(sagaMiddleware),
|
||||
applyMiddleware(logger)
|
||||
);
|
||||
} else {
|
||||
enhacers = composeWithDevTools(
|
||||
|
|
|
@ -2,29 +2,45 @@ import { CREATE_CHANNEL } from '../actions/actionsTypes';
|
|||
|
||||
const initialState = {
|
||||
isFetching: false,
|
||||
failure: false
|
||||
failure: false,
|
||||
users: []
|
||||
};
|
||||
|
||||
export default function messages(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case CREATE_CHANNEL.REQUEST:
|
||||
return { ...state,
|
||||
return {
|
||||
...state,
|
||||
error: undefined,
|
||||
failure: false,
|
||||
isFetching: true
|
||||
};
|
||||
case CREATE_CHANNEL.SUCCESS:
|
||||
return { ...state,
|
||||
return {
|
||||
...state,
|
||||
isFetching: false,
|
||||
failure: false,
|
||||
result: action.data
|
||||
};
|
||||
case CREATE_CHANNEL.FAILURE:
|
||||
return { ...state,
|
||||
return {
|
||||
...state,
|
||||
isFetching: false,
|
||||
failure: true,
|
||||
error: action.err
|
||||
};
|
||||
case CREATE_CHANNEL.ADD_USER:
|
||||
return {
|
||||
...state,
|
||||
users: state.users.concat(action.user)
|
||||
};
|
||||
case CREATE_CHANNEL.REMOVE_USER:
|
||||
return {
|
||||
...state,
|
||||
users: state.users.filter(item => item.name !== action.user.name)
|
||||
};
|
||||
case CREATE_CHANNEL.RESET:
|
||||
return initialState;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -1,31 +1,29 @@
|
|||
import { delay } from 'redux-saga';
|
||||
import { select, put, call, take, takeEvery } from 'redux-saga/effects';
|
||||
import { select, put, call, take, takeLatest } from 'redux-saga/effects';
|
||||
import { CREATE_CHANNEL, LOGIN } from '../actions/actionsTypes';
|
||||
import { createChannelSuccess, createChannelFailure } from '../actions/createChannel';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
|
||||
|
||||
const create = function* create(data) {
|
||||
return yield RocketChat.createChannel(data);
|
||||
};
|
||||
|
||||
const get = function* get({ data }) {
|
||||
try {
|
||||
yield delay(1000);
|
||||
const auth = yield select(state => state.login.isAuthenticated);
|
||||
if (!auth) {
|
||||
yield take(LOGIN.SUCCESS);
|
||||
}
|
||||
const result = yield call(create, data);
|
||||
yield put(createChannelSuccess(result));
|
||||
select(({ navigator }) => navigator).dismissModal({
|
||||
animationType: 'slide-down'
|
||||
});
|
||||
} catch (err) {
|
||||
yield delay(2000);
|
||||
yield put(createChannelFailure(err));
|
||||
}
|
||||
};
|
||||
|
||||
const getData = function* getData() {
|
||||
yield takeEvery(CREATE_CHANNEL.REQUEST, get);
|
||||
yield takeLatest(CREATE_CHANNEL.REQUEST, get);
|
||||
};
|
||||
|
||||
export default getData;
|
||||
|
|
|
@ -6,20 +6,25 @@ import { createChannelRequest } from '../actions/createChannel';
|
|||
import styles from './Styles';
|
||||
import KeyboardView from '../presentation/KeyboardView';
|
||||
|
||||
@connect(state => ({
|
||||
result: state.createChannel
|
||||
}), dispatch => ({
|
||||
createChannel: data => dispatch(createChannelRequest(data))
|
||||
}))
|
||||
|
||||
@connect(
|
||||
state => ({
|
||||
result: state.createChannel,
|
||||
users: state.createChannel.users
|
||||
}),
|
||||
dispatch => ({
|
||||
createChannel: data => dispatch(createChannelRequest(data))
|
||||
})
|
||||
)
|
||||
export default class CreateChannelView extends React.Component {
|
||||
static navigationOptions = () => ({
|
||||
title: 'Create a New Channel'
|
||||
});
|
||||
static propTypes = {
|
||||
createChannel: PropTypes.func.isRequired,
|
||||
result: PropTypes.object.isRequired
|
||||
}
|
||||
result: PropTypes.object.isRequired,
|
||||
users: PropTypes.array.isRequired,
|
||||
navigation: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
@ -29,23 +34,42 @@ export default class CreateChannelView extends React.Component {
|
|||
};
|
||||
this.state = this.default;
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (!this.adding) {
|
||||
return;
|
||||
}
|
||||
if (this.props.result.result && !this.props.result.failure) {
|
||||
this.props.navigation.navigate('Room', { room: this.props.result.result });
|
||||
this.adding = false;
|
||||
}
|
||||
}
|
||||
|
||||
submit() {
|
||||
this.adding = true;
|
||||
if (!this.state.channelName.trim() || this.props.result.isFetching) {
|
||||
return;
|
||||
}
|
||||
const { channelName, users = [], type = true } = this.state;
|
||||
const { channelName, type = true } = this.state;
|
||||
let { users } = this.props;
|
||||
|
||||
// transform users object into array of usernames
|
||||
users = users.map(user => user.name);
|
||||
|
||||
// create channel
|
||||
this.props.createChannel({ name: channelName, users, type });
|
||||
}
|
||||
|
||||
renderChannelNameError() {
|
||||
if (!this.props.result.failure || this.props.result.error.error !== 'error-duplicate-channel-name') {
|
||||
if (
|
||||
!this.props.result.failure ||
|
||||
this.props.result.error.error !== 'error-duplicate-channel-name'
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Text style={[styles.label_white, styles.label_error]}>
|
||||
{this.props.result.error.reason}
|
||||
</Text>
|
||||
<Text style={[styles.label_white, styles.label_error]}>{this.props.result.error.reason}</Text>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -91,18 +115,22 @@ export default class CreateChannelView extends React.Component {
|
|||
flexGrow: 1,
|
||||
paddingHorizontal: 0,
|
||||
marginBottom: 20
|
||||
}]}
|
||||
}
|
||||
]}
|
||||
>
|
||||
{this.state.type ?
|
||||
'Everyone can access this channel' :
|
||||
'Just invited people can access this channel'}
|
||||
{this.state.type ? (
|
||||
'Everyone can access this channel'
|
||||
) : (
|
||||
'Just invited people can access this channel'
|
||||
)}
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
onPress={() => this.submit()}
|
||||
style={[
|
||||
styles.buttonContainer_white,
|
||||
(this.state.channelName.length === 0 || this.props.result.isFetching) ?
|
||||
styles.disabledButton : styles.enabledButton
|
||||
this.state.channelName.length === 0 || this.props.result.isFetching
|
||||
? styles.disabledButton
|
||||
: styles.enabledButton
|
||||
]}
|
||||
>
|
||||
<Text style={styles.button_white}>
|
||||
|
|
|
@ -43,16 +43,18 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
@connect(state => ({
|
||||
server: state.server.server,
|
||||
Site_Url: state.settings.Site_Url,
|
||||
Message_TimeFormat: state.settings.Message_TimeFormat,
|
||||
loading: state.messages.isFetching
|
||||
}), dispatch => ({
|
||||
actions: bindActionCreators(actions, dispatch),
|
||||
getMessages: rid => dispatch(messagesRequest({ rid }))
|
||||
}))
|
||||
@connect(
|
||||
state => ({
|
||||
server: state.server.server,
|
||||
Site_Url: state.settings.Site_Url,
|
||||
Message_TimeFormat: state.settings.Message_TimeFormat,
|
||||
loading: state.messages.isFetching
|
||||
}),
|
||||
dispatch => ({
|
||||
actions: bindActionCreators(actions, dispatch),
|
||||
getMessages: rid => dispatch(messagesRequest({ rid }))
|
||||
})
|
||||
)
|
||||
export default class RoomView extends React.Component {
|
||||
static propTypes = {
|
||||
navigation: PropTypes.object.isRequired,
|
||||
|
@ -64,15 +66,21 @@ export default class RoomView extends React.Component {
|
|||
Site_Url: PropTypes.string,
|
||||
Message_TimeFormat: PropTypes.string,
|
||||
loading: PropTypes.bool
|
||||
}
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.sid = props.navigation.state.params.room.sid;
|
||||
this.rid = props.rid || realm.objectForPrimaryKey('subscriptions', this.sid).rid;
|
||||
this.rid =
|
||||
props.rid ||
|
||||
props.navigation.state.params.room.rid ||
|
||||
realm.objectForPrimaryKey('subscriptions', this.sid).rid;
|
||||
|
||||
this.data = realm.objects('messages').filtered('_server.id = $0 AND rid = $1', this.props.server, this.rid).sorted('ts', true);
|
||||
this.data = realm
|
||||
.objects('messages')
|
||||
.filtered('_server.id = $0 AND rid = $1', this.props.server, this.rid)
|
||||
.sorted('ts', true);
|
||||
this.state = {
|
||||
slow: false,
|
||||
dataSource: [],
|
||||
|
@ -83,7 +91,10 @@ export default class RoomView extends React.Component {
|
|||
|
||||
componentWillMount() {
|
||||
this.props.navigation.setParams({
|
||||
title: this.props.name || realm.objectForPrimaryKey('subscriptions', this.sid).name
|
||||
title:
|
||||
this.props.name ||
|
||||
this.props.navigation.state.params.room.name ||
|
||||
realm.objectForPrimaryKey('subscriptions', this.sid).name
|
||||
});
|
||||
this.timer = setTimeout(() => this.setState({ slow: true }), 5000);
|
||||
this.props.getMessages(this.rid);
|
||||
|
@ -103,7 +114,12 @@ export default class RoomView extends React.Component {
|
|||
|
||||
onEndReached = () => {
|
||||
const rowCount = this.state.dataSource.getRowCount();
|
||||
if (rowCount && this.state.loaded && this.state.loadingMore !== true && this.state.end !== true) {
|
||||
if (
|
||||
rowCount &&
|
||||
this.state.loaded &&
|
||||
this.state.loadingMore !== true &&
|
||||
this.state.end !== true
|
||||
) {
|
||||
this.setState({
|
||||
// ...this.state,
|
||||
loadingMore: true
|
||||
|
@ -118,7 +134,7 @@ export default class RoomView extends React.Component {
|
|||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
updateState = () => {
|
||||
this.setState({
|
||||
|
@ -135,13 +151,12 @@ export default class RoomView extends React.Component {
|
|||
});
|
||||
};
|
||||
|
||||
renderBanner = () => (this.state.slow && this.props.loading ?
|
||||
(
|
||||
renderBanner = () =>
|
||||
(this.state.slow && this.props.loading ? (
|
||||
<View style={styles.bannerContainer}>
|
||||
<Text style={styles.bannerText}>Loading new messages...</Text>
|
||||
</View>
|
||||
) : null)
|
||||
|
||||
) : null);
|
||||
|
||||
renderItem = ({ item }) => (
|
||||
<Message
|
||||
|
@ -152,9 +167,7 @@ export default class RoomView extends React.Component {
|
|||
/>
|
||||
);
|
||||
|
||||
renderSeparator = () => (
|
||||
<View style={styles.separator} />
|
||||
);
|
||||
renderSeparator = () => <View style={styles.separator} />;
|
||||
|
||||
renderFooter = () => {
|
||||
if (!this.state.joined) {
|
||||
|
@ -165,14 +178,8 @@ export default class RoomView extends React.Component {
|
|||
</View>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<MessageBox
|
||||
ref={box => this.box = box}
|
||||
onSubmit={this.sendMessage}
|
||||
rid={this.rid}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return <MessageBox ref={box => (this.box = box)} onSubmit={this.sendMessage} rid={this.rid} />;
|
||||
};
|
||||
|
||||
renderHeader = () => {
|
||||
if (this.state.loadingMore) {
|
||||
|
@ -182,7 +189,7 @@ export default class RoomView extends React.Component {
|
|||
if (this.state.end) {
|
||||
return <Text style={styles.header}>Start of conversation</Text>;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
|
|
|
@ -207,7 +207,7 @@ export default class RoomsListView extends React.Component {
|
|||
}
|
||||
|
||||
_createChannel() {
|
||||
this.props.navigation.navigate('CreateChannel');
|
||||
this.props.navigation.navigate('SelectUsers');
|
||||
}
|
||||
|
||||
renderSearchBar = () => (
|
||||
|
|
|
@ -0,0 +1,271 @@
|
|||
import ActionButton from 'react-native-action-button';
|
||||
import { ListView } from 'realm/react-native';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Icon from 'react-native-vector-icons/Ionicons';
|
||||
import { View, StyleSheet, TextInput, Text, TouchableOpacity } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import * as actions from '../actions';
|
||||
import * as server from '../actions/connect';
|
||||
import * as createChannelActions from '../actions/createChannel';
|
||||
import realm from '../lib/realm';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
import RoomItem from '../presentation/RoomItem';
|
||||
import Banner from '../containers/Banner';
|
||||
import Avatar from '../containers/Avatar';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
alignItems: 'stretch',
|
||||
justifyContent: 'center'
|
||||
},
|
||||
list: {
|
||||
width: '100%',
|
||||
backgroundColor: '#FFFFFF'
|
||||
},
|
||||
actionButtonIcon: {
|
||||
fontSize: 20,
|
||||
height: 22,
|
||||
color: 'white'
|
||||
},
|
||||
searchBoxView: {
|
||||
backgroundColor: '#eee'
|
||||
},
|
||||
searchBox: {
|
||||
backgroundColor: '#fff',
|
||||
margin: 5,
|
||||
borderRadius: 5,
|
||||
padding: 5,
|
||||
paddingLeft: 10,
|
||||
color: '#aaa'
|
||||
},
|
||||
selectItemView: {
|
||||
width: 80,
|
||||
height: 80,
|
||||
padding: 8,
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
}
|
||||
});
|
||||
|
||||
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
|
||||
@connect(
|
||||
state => ({
|
||||
server: state.server.server,
|
||||
login: state.login,
|
||||
Site_Url: state.settings.Site_Url,
|
||||
users: state.createChannel.users
|
||||
}),
|
||||
dispatch => ({
|
||||
login: () => dispatch(actions.login()),
|
||||
connect: () => dispatch(server.connectRequest()),
|
||||
addUser: user => dispatch(createChannelActions.addUser(user)),
|
||||
removeUser: user => dispatch(createChannelActions.removeUser(user)),
|
||||
resetCreateChannel: () => dispatch(createChannelActions.reset())
|
||||
})
|
||||
)
|
||||
export default class RoomsListView extends React.Component {
|
||||
static propTypes = {
|
||||
navigation: PropTypes.object.isRequired,
|
||||
Site_Url: PropTypes.string,
|
||||
server: PropTypes.string,
|
||||
addUser: PropTypes.func.isRequired,
|
||||
removeUser: PropTypes.func.isRequired,
|
||||
resetCreateChannel: PropTypes.func.isRequired,
|
||||
users: PropTypes.array
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.data = realm
|
||||
.objects('subscriptions')
|
||||
.filtered('_server.id = $0 AND t = $1', this.props.server, 'd');
|
||||
this.state = {
|
||||
dataSource: ds.cloneWithRows(this.data),
|
||||
searching: false,
|
||||
searchDataSource: [],
|
||||
searchText: '',
|
||||
login: false
|
||||
};
|
||||
this.data.addListener(this.updateState);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.data.removeListener(this.updateState);
|
||||
this.props.resetCreateChannel();
|
||||
}
|
||||
|
||||
onSearchChangeText = (text) => {
|
||||
const searchText = text.trim();
|
||||
this.setState({
|
||||
searchText: text,
|
||||
searching: searchText !== ''
|
||||
});
|
||||
if (searchText === '') {
|
||||
return this.setState({
|
||||
dataSource: ds.cloneWithRows(this.data)
|
||||
});
|
||||
}
|
||||
|
||||
const data = this.data.filtered('name CONTAINS[c] $0', searchText).slice();
|
||||
|
||||
const usernames = [];
|
||||
const dataSource = data.map((sub) => {
|
||||
if (sub.t === 'd') {
|
||||
usernames.push(sub.name);
|
||||
}
|
||||
return sub;
|
||||
});
|
||||
|
||||
if (dataSource.length < 7) {
|
||||
if (this.oldPromise) {
|
||||
this.oldPromise();
|
||||
}
|
||||
Promise.race([
|
||||
RocketChat.spotlight(searchText, usernames),
|
||||
new Promise((resolve, reject) => (this.oldPromise = reject))
|
||||
])
|
||||
.then(
|
||||
(results) => {
|
||||
results.users.forEach((user) => {
|
||||
dataSource.push({
|
||||
...user,
|
||||
name: user.username,
|
||||
t: 'd',
|
||||
search: true
|
||||
});
|
||||
});
|
||||
this.setState({
|
||||
dataSource: ds.cloneWithRows(dataSource)
|
||||
});
|
||||
},
|
||||
() => console.log('spotlight stopped')
|
||||
)
|
||||
.then(() => delete this.oldPromise);
|
||||
}
|
||||
|
||||
this.setState({
|
||||
dataSource: ds.cloneWithRows(dataSource)
|
||||
});
|
||||
};
|
||||
|
||||
updateState = () => {
|
||||
this.setState({
|
||||
dataSource: ds.cloneWithRows(this.data)
|
||||
});
|
||||
};
|
||||
|
||||
toggleUser = (user) => {
|
||||
const index = this.props.users.findIndex(el => el.name === user.name);
|
||||
if (index === -1) {
|
||||
this.props.addUser(user);
|
||||
} else {
|
||||
this.props.removeUser(user);
|
||||
}
|
||||
};
|
||||
|
||||
_onPressItem = (id, item = {}) => {
|
||||
if (item.search) {
|
||||
this.toggleUser({ _id: item._id, name: item.username });
|
||||
} else {
|
||||
this.toggleUser({ _id: item._id, name: item.name });
|
||||
}
|
||||
};
|
||||
|
||||
_onPressSelectedItem = item => this.toggleUser(item);
|
||||
|
||||
_createChannel = () => {
|
||||
this.props.navigation.navigate('CreateChannel');
|
||||
};
|
||||
|
||||
renderHeader = () => (
|
||||
<View style={styles.container}>
|
||||
{this.renderSearchBar()}
|
||||
{this.renderSelected()}
|
||||
</View>
|
||||
);
|
||||
|
||||
renderSearchBar = () => (
|
||||
<View style={styles.searchBoxView}>
|
||||
<TextInput
|
||||
underlineColorAndroid='transparent'
|
||||
style={styles.searchBox}
|
||||
value={this.state.searchText}
|
||||
onChangeText={this.onSearchChangeText}
|
||||
returnKeyType='search'
|
||||
placeholder='Search'
|
||||
clearButtonMode='while-editing'
|
||||
blurOnSubmit
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
renderSelected = () => {
|
||||
if (this.props.users.length === 0) {
|
||||
return null;
|
||||
}
|
||||
const usersDataSource = ds.cloneWithRows(this.props.users);
|
||||
return (
|
||||
<ListView
|
||||
dataSource={usersDataSource}
|
||||
style={styles.list}
|
||||
renderRow={this.renderSelectedItem}
|
||||
enableEmptySections
|
||||
keyboardShouldPersistTaps='always'
|
||||
horizontal
|
||||
/>
|
||||
);
|
||||
};
|
||||
renderSelectedItem = item => (
|
||||
<TouchableOpacity
|
||||
key={item._id}
|
||||
style={styles.selectItemView}
|
||||
onPress={() => this._onPressSelectedItem(item)}
|
||||
>
|
||||
<Avatar text={item.name} baseUrl={this.props.Site_Url} size={40} borderRadius={20} />
|
||||
<Text ellipsizeMode='tail' numberOfLines={1} style={{ fontSize: 10 }}>
|
||||
{item.name}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
renderItem = item => (
|
||||
<RoomItem
|
||||
key={item._id}
|
||||
name={item.name}
|
||||
type={item.t}
|
||||
baseUrl={this.props.Site_Url}
|
||||
onPress={() => this._onPressItem(item._id, item)}
|
||||
/>
|
||||
);
|
||||
renderList = () => (
|
||||
<ListView
|
||||
dataSource={this.state.dataSource}
|
||||
style={styles.list}
|
||||
renderRow={this.renderItem}
|
||||
renderHeader={this.renderHeader}
|
||||
contentOffset={{ x: 0, y: this.props.users.length > 0 ? 40 : 20 }}
|
||||
enableEmptySections
|
||||
keyboardShouldPersistTaps='always'
|
||||
/>
|
||||
);
|
||||
renderCreateButton = () => {
|
||||
if (this.props.users.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<ActionButton
|
||||
buttonColor='rgba(67, 165, 71, 1)'
|
||||
onPress={() => this._createChannel()}
|
||||
icon={<Icon name='md-arrow-forward' style={styles.actionButtonIcon} />}
|
||||
/>
|
||||
);
|
||||
};
|
||||
render = () => (
|
||||
<View style={styles.container}>
|
||||
<Banner />
|
||||
{this.renderList()}
|
||||
{this.renderCreateButton()}
|
||||
</View>
|
||||
);
|
||||
}
|
|
@ -800,7 +800,6 @@
|
|||
TestTargetID = 13B07F861A680F5B00A75B9A;
|
||||
};
|
||||
13B07F861A680F5B00A75B9A = {
|
||||
DevelopmentTeam = S6UPZG7ZR3;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
2D02E47A1E0B4A5D006451C7 = {
|
||||
|
@ -1379,7 +1378,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEAD_CODE_STRIPPING = NO;
|
||||
DEVELOPMENT_TEAM = S6UPZG7ZR3;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(SRCROOT)/../node_modules/realm/src/**",
|
||||
|
@ -1412,7 +1411,7 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = S6UPZG7ZR3;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(SRCROOT)/../node_modules/realm/src/**",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue