commit
6fbabc87d8
|
@ -27,6 +27,7 @@ export const FORGOT_PASSWORD = createRequestTypes('FORGOT_PASSWORD', [
|
||||||
'INIT'
|
'INIT'
|
||||||
]);
|
]);
|
||||||
export const ROOMS = createRequestTypes('ROOMS');
|
export const ROOMS = createRequestTypes('ROOMS');
|
||||||
|
export const ROOM = createRequestTypes('ROOM', ['ADD_USER_TYPING', 'REMOVE_USER_TYPING', 'SOMEONE_TYPING', 'OPEN', 'USER_TYPING']);
|
||||||
export const APP = createRequestTypes('APP', ['READY', 'INIT']);
|
export const APP = createRequestTypes('APP', ['READY', 'INIT']);
|
||||||
export const MESSAGES = createRequestTypes('MESSAGES', [
|
export const MESSAGES = createRequestTypes('MESSAGES', [
|
||||||
...defaultTypes,
|
...defaultTypes,
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
import * as types from './actionsTypes';
|
||||||
|
|
||||||
|
|
||||||
|
export function removeUserTyping(username) {
|
||||||
|
return {
|
||||||
|
type: types.ROOM.REMOVE_USER_TYPING,
|
||||||
|
username
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function someoneTyping(data) {
|
||||||
|
return {
|
||||||
|
type: types.ROOM.SOMEONE_TYPING,
|
||||||
|
...data
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addUserTyping(username) {
|
||||||
|
return {
|
||||||
|
type: types.ROOM.ADD_USER_TYPING,
|
||||||
|
username
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function openRoom(room) {
|
||||||
|
return {
|
||||||
|
type: types.ROOM.OPEN,
|
||||||
|
room
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function userTyping(status = true) {
|
||||||
|
return {
|
||||||
|
type: types.ROOM.USER_TYPING,
|
||||||
|
status
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
import * as types from './actionsTypes';
|
import * as types from './actionsTypes';
|
||||||
|
|
||||||
|
|
||||||
export function roomsRequest() {
|
export function roomsRequest() {
|
||||||
return {
|
return {
|
||||||
type: types.ROOMS.REQUEST
|
type: types.ROOMS.REQUEST
|
||||||
|
|
|
@ -4,12 +4,14 @@ import { View, TextInput, StyleSheet, SafeAreaView } from 'react-native';
|
||||||
import Icon from 'react-native-vector-icons/MaterialIcons';
|
import Icon from 'react-native-vector-icons/MaterialIcons';
|
||||||
import ImagePicker from 'react-native-image-picker';
|
import ImagePicker from 'react-native-image-picker';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { userTyping } from '../actions/room';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
import { editRequest } from '../actions/messages';
|
import { editRequest } from '../actions/messages';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
textBox: {
|
textBox: {
|
||||||
paddingTop: 1,
|
paddingTop: 1,
|
||||||
|
paddingHorizontal: 15,
|
||||||
borderTopWidth: 1,
|
borderTopWidth: 1,
|
||||||
borderTopColor: '#ccc',
|
borderTopColor: '#ccc',
|
||||||
backgroundColor: '#fff'
|
backgroundColor: '#fff'
|
||||||
|
@ -25,8 +27,6 @@ const styles = StyleSheet.create({
|
||||||
},
|
},
|
||||||
fileButton: {
|
fileButton: {
|
||||||
color: '#aaa',
|
color: '#aaa',
|
||||||
paddingLeft: 23,
|
|
||||||
paddingRight: 20,
|
|
||||||
paddingTop: 10,
|
paddingTop: 10,
|
||||||
paddingBottom: 10,
|
paddingBottom: 10,
|
||||||
fontSize: 20
|
fontSize: 20
|
||||||
|
@ -40,7 +40,8 @@ const styles = StyleSheet.create({
|
||||||
message: state.messages.message,
|
message: state.messages.message,
|
||||||
editing: state.messages.editing
|
editing: state.messages.editing
|
||||||
}), dispatch => ({
|
}), dispatch => ({
|
||||||
editRequest: message => dispatch(editRequest(message))
|
editRequest: message => dispatch(editRequest(message)),
|
||||||
|
typing: status => dispatch(userTyping(status))
|
||||||
}))
|
}))
|
||||||
export default class MessageBox extends React.Component {
|
export default class MessageBox extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -48,7 +49,8 @@ export default class MessageBox extends React.Component {
|
||||||
rid: PropTypes.string.isRequired,
|
rid: PropTypes.string.isRequired,
|
||||||
editRequest: PropTypes.func.isRequired,
|
editRequest: PropTypes.func.isRequired,
|
||||||
message: PropTypes.object,
|
message: PropTypes.object,
|
||||||
editing: PropTypes.bool
|
editing: PropTypes.bool,
|
||||||
|
typing: PropTypes.bool
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
|
@ -106,7 +108,6 @@ export default class MessageBox extends React.Component {
|
||||||
return (
|
return (
|
||||||
<View style={[styles.textBox, (this.props.editing ? styles.editing : null)]}>
|
<View style={[styles.textBox, (this.props.editing ? styles.editing : null)]}>
|
||||||
<SafeAreaView style={styles.safeAreaView}>
|
<SafeAreaView style={styles.safeAreaView}>
|
||||||
<Icon style={styles.fileButton} name='add-circle-outline' onPress={this.addFile} />
|
|
||||||
<TextInput
|
<TextInput
|
||||||
ref={component => this.component = component}
|
ref={component => this.component = component}
|
||||||
style={styles.textBoxInput}
|
style={styles.textBoxInput}
|
||||||
|
@ -114,9 +115,11 @@ export default class MessageBox extends React.Component {
|
||||||
onSubmitEditing={event => this.submit(event.nativeEvent.text)}
|
onSubmitEditing={event => this.submit(event.nativeEvent.text)}
|
||||||
blurOnSubmit={false}
|
blurOnSubmit={false}
|
||||||
placeholder='New message'
|
placeholder='New message'
|
||||||
|
onChangeText={text => this.props.typing(text.length > 0)}
|
||||||
underlineColorAndroid='transparent'
|
underlineColorAndroid='transparent'
|
||||||
defaultValue=''
|
defaultValue=''
|
||||||
/>
|
/>
|
||||||
|
<Icon style={styles.fileButton} name='add-circle-outline' onPress={this.addFile} />
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
|
@ -8,6 +8,7 @@ import reduxStore from './createStore';
|
||||||
import settingsType from '../constants/settings';
|
import settingsType from '../constants/settings';
|
||||||
import realm from './realm';
|
import realm from './realm';
|
||||||
import * as actions from '../actions';
|
import * as actions from '../actions';
|
||||||
|
import { someoneTyping } from '../actions/room';
|
||||||
import { disconnect, connectSuccess } from '../actions/connect';
|
import { disconnect, connectSuccess } from '../actions/connect';
|
||||||
|
|
||||||
export { Accounts } from 'react-native-meteor';
|
export { Accounts } from 'react-native-meteor';
|
||||||
|
@ -61,11 +62,11 @@ const RocketChat = {
|
||||||
});
|
});
|
||||||
|
|
||||||
Meteor.ddp.on('connected', async() => {
|
Meteor.ddp.on('connected', async() => {
|
||||||
Meteor.ddp.on('changed', (ddbMessage) => {
|
Meteor.ddp.on('changed', (ddpMessage) => {
|
||||||
const server = { id: reduxStore.getState().server.server };
|
const server = { id: reduxStore.getState().server.server };
|
||||||
if (ddbMessage.collection === 'stream-room-messages') {
|
if (ddpMessage.collection === 'stream-room-messages') {
|
||||||
realm.write(() => {
|
return realm.write(() => {
|
||||||
const message = ddbMessage.fields.args[0];
|
const message = ddpMessage.fields.args[0];
|
||||||
message.temp = false;
|
message.temp = false;
|
||||||
message._server = server;
|
message._server = server;
|
||||||
message.attachments = message.attachments || [];
|
message.attachments = message.attachments || [];
|
||||||
|
@ -73,10 +74,16 @@ const RocketChat = {
|
||||||
realm.create('messages', message, true);
|
realm.create('messages', message, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (ddpMessage.collection === 'stream-notify-room') {
|
||||||
if (ddbMessage.collection === 'stream-notify-user') {
|
const [_rid, ev] = ddpMessage.fields.eventName.split('/');
|
||||||
const [type, data] = ddbMessage.fields.args;
|
if (ev !== 'typing') {
|
||||||
const [, ev] = ddbMessage.fields.eventName.split('/');
|
return;
|
||||||
|
}
|
||||||
|
return reduxStore.dispatch(someoneTyping({ _rid, username: ddpMessage.fields.args[0], typing: ddpMessage.fields.args[1] }));
|
||||||
|
}
|
||||||
|
if (ddpMessage.collection === 'stream-notify-user') {
|
||||||
|
const [type, data] = ddpMessage.fields.args;
|
||||||
|
const [, ev] = ddpMessage.fields.eventName.split('/');
|
||||||
if (/subscriptions/.test(ev)) {
|
if (/subscriptions/.test(ev)) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'inserted':
|
case 'inserted':
|
||||||
|
@ -265,7 +272,6 @@ const RocketChat = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resolve();
|
resolve();
|
||||||
Meteor.subscribe('stream-room-messages', rid, false);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -446,40 +452,27 @@ const RocketChat = {
|
||||||
return call('pinMessage', message);
|
return call('pinMessage', message);
|
||||||
},
|
},
|
||||||
getRoom(rid) {
|
getRoom(rid) {
|
||||||
return new Promise((resolve, reject) => {
|
const result = realm.objects('subscriptions').filtered('rid = $0', rid);
|
||||||
const result = realm.objects('subscriptions').filtered('rid = $0', rid);
|
if (result.length === 0) {
|
||||||
|
return Promise.reject(new Error('Room not found'));
|
||||||
if (result.length === 0) {
|
}
|
||||||
return reject(new Error('Room not found'));
|
return Promise.resolve(result[0]);
|
||||||
}
|
|
||||||
return resolve(result[0]);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
async getPermalink(message) {
|
async getPermalink(message) {
|
||||||
return new Promise(async(resolve, reject) => {
|
const room = await RocketChat.getRoom(message.rid);
|
||||||
let room;
|
const roomType = {
|
||||||
try {
|
p: 'group',
|
||||||
room = await RocketChat.getRoom(message.rid);
|
c: 'channel',
|
||||||
} catch (error) {
|
d: 'direct'
|
||||||
return reject(error);
|
}[room.t];
|
||||||
}
|
return `${ room._server.id }/${ roomType }/${ room.name }?msg=${ message._id }`;
|
||||||
|
},
|
||||||
let roomType;
|
subscribe(...args) {
|
||||||
switch (room.t) {
|
return Meteor.subscribe(...args);
|
||||||
case 'p':
|
},
|
||||||
roomType = 'group';
|
emitTyping(room, t = true) {
|
||||||
break;
|
const { login } = reduxStore.getState();
|
||||||
case 'c':
|
return call('stream-notify-room', `${ room }/typing`, login.user.username, t);
|
||||||
roomType = 'channel';
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
roomType = 'direct';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return resolve(`${ room._server.id }/${ roomType }/${ room.name }?msg=${ message._id }`);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ import settings from './reducers';
|
||||||
import login from './login';
|
import login from './login';
|
||||||
import meteor from './connect';
|
import meteor from './connect';
|
||||||
import messages from './messages';
|
import messages from './messages';
|
||||||
|
import room from './room';
|
||||||
import server from './server';
|
import server from './server';
|
||||||
import navigator from './navigator';
|
import navigator from './navigator';
|
||||||
import createChannel from './createChannel';
|
import createChannel from './createChannel';
|
||||||
|
@ -10,5 +11,5 @@ import app from './app';
|
||||||
|
|
||||||
|
|
||||||
export default combineReducers({
|
export default combineReducers({
|
||||||
settings, login, meteor, messages, server, navigator, createChannel, app
|
settings, login, meteor, messages, server, navigator, createChannel, app, room
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
import * as types from '../actions/actionsTypes';
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
usersTyping: []
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function room(state = initialState, action) {
|
||||||
|
switch (action.type) {
|
||||||
|
case types.ROOM.OPEN:
|
||||||
|
return {
|
||||||
|
...initialState,
|
||||||
|
...action.room
|
||||||
|
};
|
||||||
|
case types.ROOM.ADD_USER_TYPING:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
usersTyping: [...state.usersTyping.filter(user => user !== action.username), action.username]
|
||||||
|
};
|
||||||
|
case types.ROOM.REMOVE_USER_TYPING:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
usersTyping: [...state.usersTyping.filter(user => user !== action.username)]
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,7 +29,6 @@ const get = function* get({ rid }) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
yield RocketChat.loadMessagesForRoom(rid, null);
|
yield RocketChat.loadMessagesForRoom(rid, null);
|
||||||
yield RocketChat.readMessages(rid);
|
|
||||||
yield put(messagesSuccess());
|
yield put(messagesSuccess());
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
import { put, call, takeEvery } from 'redux-saga/effects';
|
import { put, call, takeLatest, take, select, race, fork, cancel } from 'redux-saga/effects';
|
||||||
|
import { delay } from 'redux-saga';
|
||||||
import * as types from '../actions/actionsTypes';
|
import * as types from '../actions/actionsTypes';
|
||||||
import { roomsSuccess, roomsFailure } from '../actions/rooms';
|
import { roomsSuccess, roomsFailure } from '../actions/rooms';
|
||||||
|
import { addUserTyping, removeUserTyping } from '../actions/room';
|
||||||
|
import { messagesRequest } from '../actions/messages';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
|
|
||||||
const getRooms = function* getRooms() {
|
const getRooms = function* getRooms() {
|
||||||
|
@ -9,15 +12,86 @@ const getRooms = function* getRooms() {
|
||||||
|
|
||||||
const watchRoomsRequest = function* watchRoomsRequest() {
|
const watchRoomsRequest = function* watchRoomsRequest() {
|
||||||
try {
|
try {
|
||||||
console.log('getRooms');
|
|
||||||
yield call(getRooms);
|
yield call(getRooms);
|
||||||
yield put(roomsSuccess());
|
yield put(roomsSuccess());
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
|
||||||
yield put(roomsFailure(err.status));
|
yield put(roomsFailure(err.status));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const cancelTyping = function* cancelTyping(username) {
|
||||||
|
while (true) {
|
||||||
|
const { typing, timeout } = yield race({
|
||||||
|
typing: take(types.ROOM.SOMEONE_TYPING),
|
||||||
|
timeout: yield call(delay, 5000)
|
||||||
|
});
|
||||||
|
if (timeout || (typing.username === username && !typing.typing)) {
|
||||||
|
return yield put(removeUserTyping(username));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const usersTyping = function* usersTyping({ rid }) {
|
||||||
|
while (true) {
|
||||||
|
const { _rid, username, typing } = yield take(types.ROOM.SOMEONE_TYPING);
|
||||||
|
if (_rid === rid) {
|
||||||
|
yield (typing ? put(addUserTyping(username)) : put(removeUserTyping(username)));
|
||||||
|
if (typing) {
|
||||||
|
fork(cancelTyping, username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const watchRoomOpen = function* watchRoomOpen({ room }) {
|
||||||
|
const auth = yield select(state => state.login.isAuthenticated);
|
||||||
|
if (!auth) {
|
||||||
|
yield take(types.LOGIN.SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
const subscriptions = [];
|
||||||
|
yield put(messagesRequest({ rid: room.rid }));
|
||||||
|
|
||||||
|
const { open } = yield race({
|
||||||
|
messages: take(types.MESSAGES.SUCCESS),
|
||||||
|
open: take(types.ROOM.OPEN)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (open) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RocketChat.readMessages(room.rid);
|
||||||
|
subscriptions.push(RocketChat.subscribe('stream-room-messages', room.rid, false));
|
||||||
|
subscriptions.push(RocketChat.subscribe('stream-notify-room', `${ room.rid }/typing`, false));
|
||||||
|
const thread = yield fork(usersTyping, { rid: room.rid });
|
||||||
|
yield take(types.ROOM.OPEN);
|
||||||
|
cancel(thread);
|
||||||
|
subscriptions.forEach(sub => sub.stop());
|
||||||
|
};
|
||||||
|
|
||||||
|
const watchuserTyping = function* watchuserTyping({ status }) {
|
||||||
|
const auth = yield select(state => state.login.isAuthenticated);
|
||||||
|
if (!auth) {
|
||||||
|
yield take(types.LOGIN.SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
const room = yield select(state => state.room);
|
||||||
|
|
||||||
|
if (!room) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
yield RocketChat.emitTyping(room.rid, status);
|
||||||
|
|
||||||
|
if (status) {
|
||||||
|
yield call(delay, 5000);
|
||||||
|
yield RocketChat.emitTyping(room.rid, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const root = function* root() {
|
const root = function* root() {
|
||||||
yield takeEvery(types.LOGIN.SUCCESS, watchRoomsRequest);
|
yield takeLatest(types.ROOM.USER_TYPING, watchuserTyping);
|
||||||
|
yield takeLatest(types.LOGIN.SUCCESS, watchRoomsRequest);
|
||||||
|
yield takeLatest(types.ROOM.OPEN, watchRoomOpen);
|
||||||
};
|
};
|
||||||
export default root;
|
export default root;
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
|
|
||||||
import * as actions from '../actions';
|
import * as actions from '../actions';
|
||||||
import { messagesRequest } from '../actions/messages';
|
import { openRoom } from '../actions/room';
|
||||||
import realm from '../lib/realm';
|
import realm from '../lib/realm';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
import Message from '../containers/message';
|
import Message from '../containers/message';
|
||||||
|
@ -15,6 +15,7 @@ import KeyboardView from '../presentation/KeyboardView';
|
||||||
|
|
||||||
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1._id !== r2._id });
|
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1._id !== r2._id });
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
typing: { fontWeight: 'bold', paddingHorizontal: 15, height: 25 },
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: '#fff'
|
backgroundColor: '#fff'
|
||||||
|
@ -48,6 +49,8 @@ const styles = StyleSheet.create({
|
||||||
|
|
||||||
@connect(
|
@connect(
|
||||||
state => ({
|
state => ({
|
||||||
|
username: state.login.user.username,
|
||||||
|
usersTyping: state.room.usersTyping,
|
||||||
server: state.server.server,
|
server: state.server.server,
|
||||||
Site_Url: state.settings.Site_Url,
|
Site_Url: state.settings.Site_Url,
|
||||||
Message_TimeFormat: state.settings.Message_TimeFormat,
|
Message_TimeFormat: state.settings.Message_TimeFormat,
|
||||||
|
@ -55,20 +58,22 @@ const styles = StyleSheet.create({
|
||||||
}),
|
}),
|
||||||
dispatch => ({
|
dispatch => ({
|
||||||
actions: bindActionCreators(actions, dispatch),
|
actions: bindActionCreators(actions, dispatch),
|
||||||
getMessages: rid => dispatch(messagesRequest({ rid }))
|
openRoom: room => dispatch(openRoom(room))
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
export default class RoomView extends React.Component {
|
export default class RoomView extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
navigation: PropTypes.object.isRequired,
|
navigation: PropTypes.object.isRequired,
|
||||||
getMessages: PropTypes.func.isRequired,
|
openRoom: PropTypes.func.isRequired,
|
||||||
rid: PropTypes.string,
|
rid: PropTypes.string,
|
||||||
sid: PropTypes.string,
|
sid: PropTypes.string,
|
||||||
name: PropTypes.string,
|
name: PropTypes.string,
|
||||||
server: PropTypes.string,
|
server: PropTypes.string,
|
||||||
Site_Url: PropTypes.string,
|
Site_Url: PropTypes.string,
|
||||||
Message_TimeFormat: PropTypes.string,
|
Message_TimeFormat: PropTypes.string,
|
||||||
loading: PropTypes.bool
|
loading: PropTypes.bool,
|
||||||
|
usersTyping: PropTypes.array,
|
||||||
|
username: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -100,7 +105,7 @@ export default class RoomView extends React.Component {
|
||||||
realm.objectForPrimaryKey('subscriptions', this.sid).name
|
realm.objectForPrimaryKey('subscriptions', this.sid).name
|
||||||
});
|
});
|
||||||
this.timer = setTimeout(() => this.setState({ slow: true }), 5000);
|
this.timer = setTimeout(() => this.setState({ slow: true }), 5000);
|
||||||
this.props.getMessages(this.rid);
|
this.props.openRoom({ rid: this.rid });
|
||||||
this.data.addListener(this.updateState);
|
this.data.addListener(this.updateState);
|
||||||
}
|
}
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -134,7 +139,12 @@ export default class RoomView extends React.Component {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
get usersTyping() {
|
||||||
|
const users = this.props.usersTyping.filter(_username => this.props.username !== _username);
|
||||||
|
return users.length ? `${ users.join(' ,') } ${ users.length > 1 ? 'are' : 'is' } typing` : null;
|
||||||
|
}
|
||||||
|
|
||||||
updateState = () => {
|
updateState = () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -189,8 +199,7 @@ export default class RoomView extends React.Component {
|
||||||
if (this.state.end) {
|
if (this.state.end) {
|
||||||
return <Text style={styles.loadingMore}>Start of conversation</Text>;
|
return <Text style={styles.loadingMore}>Start of conversation</Text>;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { height } = Dimensions.get('window');
|
const { height } = Dimensions.get('window');
|
||||||
return (
|
return (
|
||||||
|
@ -209,6 +218,7 @@ export default class RoomView extends React.Component {
|
||||||
/>
|
/>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
{this.renderFooter()}
|
{this.renderFooter()}
|
||||||
|
<Text style={styles.typing}>{this.usersTyping}</Text>
|
||||||
</KeyboardView>
|
</KeyboardView>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,22 +100,20 @@ export default class RoomsListView extends React.Component {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
dataSource: [],
|
dataSource: ds.cloneWithRows([]),
|
||||||
searchText: ''
|
searchText: ''
|
||||||
};
|
};
|
||||||
this.data = realm.objects('subscriptions').filtered('_server.id = $0', this.props.server).sorted('_updatedAt', true);
|
this.data = realm.objects('subscriptions').filtered('_server.id = $0', this.props.server).sorted('_updatedAt', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentDidMount() {
|
||||||
this.data.addListener(this.updateState);
|
this.data.addListener(this.updateState);
|
||||||
|
|
||||||
this.props.navigation.setParams({
|
this.props.navigation.setParams({
|
||||||
createChannel: () => this._createChannel()
|
createChannel: () => this._createChannel()
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setState({
|
this.updateState();
|
||||||
dataSource: ds.cloneWithRows(this.data)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(props) {
|
componentWillReceiveProps(props) {
|
||||||
|
|
|
@ -1853,8 +1853,7 @@
|
||||||
"babel-plugin-transform-remove-console": {
|
"babel-plugin-transform-remove-console": {
|
||||||
"version": "6.8.5",
|
"version": "6.8.5",
|
||||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.8.5.tgz",
|
"resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.8.5.tgz",
|
||||||
"integrity": "sha512-uuCKvtweCyIvvC8fi92EcWRtO2Kt5KMNMRK6BhpDXdeb3sxvGM7453RSmgeu4DlKns3OlvY9Ep5Q9m5a7RQAgg==",
|
"integrity": "sha512-uuCKvtweCyIvvC8fi92EcWRtO2Kt5KMNMRK6BhpDXdeb3sxvGM7453RSmgeu4DlKns3OlvY9Ep5Q9m5a7RQAgg=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"babel-plugin-transform-remove-debugger": {
|
"babel-plugin-transform-remove-debugger": {
|
||||||
"version": "6.8.5",
|
"version": "6.8.5",
|
||||||
|
|
Loading…
Reference in New Issue