Rocket.Chat.ReactNative/app/sagas/rooms.js

170 lines
4.8 KiB
JavaScript
Raw Normal View History

import { Alert } from 'react-native';
import { put, call, takeLatest, take, select, race, fork, cancel, takeEvery } from 'redux-saga/effects';
2017-11-21 16:55:32 +00:00
import { delay } from 'redux-saga';
import { FOREGROUND, BACKGROUND } from 'redux-enhancer-react-native-appstate';
2017-08-17 02:06:22 +00:00
import * as types from '../actions/actionsTypes';
import { roomsSuccess, roomsFailure } from '../actions/rooms';
import { addUserTyping, removeUserTyping, setLastOpen } from '../actions/room';
2017-11-20 22:18:00 +00:00
import { messagesRequest } from '../actions/messages';
2017-08-17 02:06:22 +00:00
import RocketChat from '../lib/rocketchat';
import database from '../lib/realm';
import * as NavigationService from '../containers/routes/NavigationService';
const leaveRoom = rid => RocketChat.leaveRoom(rid);
const eraseRoom = rid => RocketChat.eraseRoom(rid);
2017-08-17 02:06:22 +00:00
const getRooms = function* getRooms() {
return yield RocketChat.getRooms();
};
2017-08-17 02:06:22 +00:00
const watchRoomsRequest = function* watchRoomsRequest() {
try {
yield call(getRooms);
yield put(roomsSuccess());
} catch (err) {
yield put(roomsFailure(err.status));
2017-08-17 02:06:22 +00:00
}
};
2017-11-21 16:55:32 +00:00
const cancelTyping = function* cancelTyping(username) {
while (true) {
const { typing, timeout } = yield race({
2017-11-21 17:09:22 +00:00
typing: take(types.ROOM.SOMEONE_TYPING),
timeout: call(delay, 5000)
2017-11-21 16:55:32 +00:00
});
if (timeout || (typing.username === username && !typing.typing)) {
return yield put(removeUserTyping(username));
}
}
};
const usersTyping = function* usersTyping({ rid }) {
2017-11-20 22:18:00 +00:00
while (true) {
2017-11-21 17:09:22 +00:00
const { _rid, username, typing } = yield take(types.ROOM.SOMEONE_TYPING);
2017-11-20 22:18:00 +00:00
if (_rid === rid) {
2017-11-21 16:55:32 +00:00
yield (typing ? put(addUserTyping(username)) : put(removeUserTyping(username)));
if (typing) {
yield fork(cancelTyping, username);
2017-11-21 16:55:32 +00:00
}
2017-11-20 22:18:00 +00:00
}
}
};
const handleMessageReceived = function* handleMessageReceived({ message }) {
const room = yield select(state => state.room);
if (message.rid === room.rid) {
database.write(() => {
database.create('messages', message, true);
});
RocketChat.readMessages(room.rid);
}
};
2017-11-20 22:18:00 +00:00
2017-11-21 16:55:32 +00:00
const watchRoomOpen = function* watchRoomOpen({ room }) {
2017-11-20 22:18:00 +00:00
const auth = yield select(state => state.login.isAuthenticated);
if (!auth) {
yield take(types.LOGIN.SUCCESS);
}
2017-11-21 16:55:32 +00:00
2017-11-21 16:55:32 +00:00
yield put(messagesRequest({ rid: room.rid }));
2017-11-20 22:18:00 +00:00
const { open } = yield race({
messages: take(types.MESSAGES.SUCCESS),
2017-11-21 16:55:32 +00:00
open: take(types.ROOM.OPEN)
2017-11-20 22:18:00 +00:00
});
if (open) {
return;
}
2017-11-21 16:55:32 +00:00
RocketChat.readMessages(room.rid);
const subscriptions = yield Promise.all([RocketChat.subscribe('stream-room-messages', room.rid, false), RocketChat.subscribe('stream-notify-room', `${ room.rid }/typing`, false)]);
2017-11-21 16:55:32 +00:00
const thread = yield fork(usersTyping, { rid: room.rid });
yield race({
open: take(types.ROOM.OPEN),
close: take(types.ROOM.CLOSE)
});
2017-11-20 22:18:00 +00:00
cancel(thread);
subscriptions.forEach((sub) => {
sub.unsubscribe().catch(e => alert(e));
});
2017-11-20 22:18:00 +00:00
};
2017-11-21 17:09:22 +00:00
const watchuserTyping = function* watchuserTyping({ status }) {
2017-11-21 16:55:32 +00:00
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);
}
};
2017-11-20 22:18:00 +00:00
const updateRoom = function* updateRoom() {
const room = yield select(state => state.room);
if (!room || !room.rid) {
return;
}
yield put(messagesRequest({ rid: room.rid }));
};
const updateLastOpen = function* updateLastOpen() {
yield put(setLastOpen());
};
const goRoomsListAndDelete = function* goRoomsListAndDelete(rid) {
NavigationService.goRoomsList();
yield delay(1000);
database.write(() => {
const messages = database.objects('messages').filtered('rid = $0', rid);
database.delete(messages);
const subscription = database.objects('subscriptions').filtered('rid = $0', rid);
database.delete(subscription);
});
};
const handleLeaveRoom = function* handleLeaveRoom({ rid }) {
try {
yield call(leaveRoom, rid);
yield goRoomsListAndDelete(rid);
} catch (e) {
if (e.error === 'error-you-are-last-owner') {
Alert.alert('You are the last owner. Please set new owner before leaving the room.');
} else {
Alert.alert('Something happened when leaving room!');
}
}
};
const handleEraseRoom = function* handleEraseRoom({ rid }) {
try {
yield call(eraseRoom, rid);
yield goRoomsListAndDelete(rid);
} catch (e) {
Alert.alert('Something happened when erasing room!');
}
};
const root = function* root() {
2017-11-21 17:09:22 +00:00
yield takeLatest(types.ROOM.USER_TYPING, watchuserTyping);
2017-11-20 22:18:00 +00:00
yield takeLatest(types.LOGIN.SUCCESS, watchRoomsRequest);
2017-11-21 16:55:32 +00:00
yield takeLatest(types.ROOM.OPEN, watchRoomOpen);
yield takeEvery(types.ROOM.MESSAGE_RECEIVED, handleMessageReceived);
yield takeLatest(FOREGROUND, updateRoom);
yield takeLatest(FOREGROUND, watchRoomsRequest);
yield takeLatest(BACKGROUND, updateLastOpen);
yield takeLatest(types.ROOM.LEAVE, handleLeaveRoom);
yield takeLatest(types.ROOM.ERASE, handleEraseRoom);
};
export default root;