[FIX] Unread not going away when receiving a message from inside a room (#194)
* Fix Unread inside Room
This commit is contained in:
parent
a0cfe3b8c3
commit
ec1782e504
|
@ -28,7 +28,7 @@ export const FORGOT_PASSWORD = createRequestTypes('FORGOT_PASSWORD', [
|
||||||
]);
|
]);
|
||||||
export const USER = createRequestTypes('USER', ['SET']);
|
export const USER = createRequestTypes('USER', ['SET']);
|
||||||
export const ROOMS = createRequestTypes('ROOMS', [...defaultTypes, 'SET_SEARCH']);
|
export const ROOMS = createRequestTypes('ROOMS', [...defaultTypes, 'SET_SEARCH']);
|
||||||
export const ROOM = createRequestTypes('ROOM', ['ADD_USER_TYPING', 'REMOVE_USER_TYPING', 'SOMEONE_TYPING', 'OPEN', 'USER_TYPING']);
|
export const ROOM = createRequestTypes('ROOM', ['ADD_USER_TYPING', 'REMOVE_USER_TYPING', 'SOMEONE_TYPING', 'OPEN', 'CLOSE', 'USER_TYPING', 'MESSAGE_RECEIVED', 'SET_LAST_OPEN']);
|
||||||
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,
|
||||||
|
|
|
@ -29,9 +29,29 @@ export function openRoom(room) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function closeRoom() {
|
||||||
|
return {
|
||||||
|
type: types.ROOM.CLOSE
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function userTyping(status = true) {
|
export function userTyping(status = true) {
|
||||||
return {
|
return {
|
||||||
type: types.ROOM.USER_TYPING,
|
type: types.ROOM.USER_TYPING,
|
||||||
status
|
status
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function roomMessageReceived(message) {
|
||||||
|
return {
|
||||||
|
type: types.ROOM.MESSAGE_RECEIVED,
|
||||||
|
message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setLastOpen(date = new Date()) {
|
||||||
|
return {
|
||||||
|
type: types.ROOM.SET_LAST_OPEN,
|
||||||
|
date
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -114,13 +114,14 @@ export default class Socket extends EventEmitter {
|
||||||
subscribe(name, ...params) {
|
subscribe(name, ...params) {
|
||||||
return this.send({
|
return this.send({
|
||||||
msg: 'sub', name, params
|
msg: 'sub', name, params
|
||||||
}).then((data) => {
|
}).then((id) => {
|
||||||
this.subscriptions[data.id] = {
|
const args = {
|
||||||
name,
|
name,
|
||||||
params,
|
params,
|
||||||
unsubscribe: () => this.unsubscribe(data.id)
|
unsubscribe: () => this.unsubscribe(id)
|
||||||
};
|
};
|
||||||
return this.subscriptions[data.id];
|
this.subscriptions[id] = args;
|
||||||
|
return args;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import settingsType from '../constants/settings';
|
||||||
import messagesStatus from '../constants/messagesStatus';
|
import messagesStatus from '../constants/messagesStatus';
|
||||||
import database from './realm';
|
import database from './realm';
|
||||||
import * as actions from '../actions';
|
import * as actions from '../actions';
|
||||||
import { someoneTyping } from '../actions/room';
|
import { someoneTyping, roomMessageReceived } from '../actions/room';
|
||||||
import { setUser } from '../actions/login';
|
import { setUser } from '../actions/login';
|
||||||
import { disconnect, disconnect_by_user, connectSuccess, connectFailure } from '../actions/connect';
|
import { disconnect, disconnect_by_user, connectSuccess, connectFailure } from '../actions/connect';
|
||||||
import { requestActiveUser } from '../actions/activeUsers';
|
import { requestActiveUser } from '../actions/activeUsers';
|
||||||
|
@ -98,10 +98,10 @@ const RocketChat = {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.ddp.on('stream-room-messages', ddpMessage => database.write(() => {
|
this.ddp.on('stream-room-messages', (ddpMessage) => {
|
||||||
const message = this._buildMessage(ddpMessage.fields.args[0]);
|
const message = this._buildMessage(ddpMessage.fields.args[0]);
|
||||||
database.create('messages', message, true);
|
return reduxStore.dispatch(roomMessageReceived(message));
|
||||||
}));
|
});
|
||||||
|
|
||||||
this.ddp.on('stream-notify-room', (ddpMessage) => {
|
this.ddp.on('stream-notify-room', (ddpMessage) => {
|
||||||
const [_rid, ev] = ddpMessage.fields.eventName.split('/');
|
const [_rid, ev] = ddpMessage.fields.eventName.split('/');
|
||||||
|
|
|
@ -9,7 +9,17 @@ export default function room(state = initialState, action) {
|
||||||
case types.ROOM.OPEN:
|
case types.ROOM.OPEN:
|
||||||
return {
|
return {
|
||||||
...initialState,
|
...initialState,
|
||||||
...action.room
|
...action.room,
|
||||||
|
lastOpen: new Date()
|
||||||
|
};
|
||||||
|
case types.ROOM.CLOSE:
|
||||||
|
return {
|
||||||
|
...initialState
|
||||||
|
};
|
||||||
|
case types.ROOM.SET_LAST_OPEN:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
lastOpen: action.date
|
||||||
};
|
};
|
||||||
case types.ROOM.ADD_USER_TYPING:
|
case types.ROOM.ADD_USER_TYPING:
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import { put, call, takeLatest, take, select, race, fork, cancel } from 'redux-saga/effects';
|
import { put, call, takeLatest, take, select, race, fork, cancel, takeEvery } from 'redux-saga/effects';
|
||||||
import { delay } from 'redux-saga';
|
import { delay } from 'redux-saga';
|
||||||
import { FOREGROUND } from 'redux-enhancer-react-native-appstate';
|
import { FOREGROUND, BACKGROUND } from 'redux-enhancer-react-native-appstate';
|
||||||
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 { addUserTyping, removeUserTyping, setLastOpen } from '../actions/room';
|
||||||
import { messagesRequest } from '../actions/messages';
|
import { messagesRequest } from '../actions/messages';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
|
import database from '../lib/realm';
|
||||||
|
|
||||||
const getRooms = function* getRooms() {
|
const getRooms = function* getRooms() {
|
||||||
return yield RocketChat.getRooms();
|
return yield RocketChat.getRooms();
|
||||||
|
@ -43,6 +44,17 @@ const usersTyping = function* usersTyping({ rid }) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const watchRoomOpen = function* watchRoomOpen({ room }) {
|
const watchRoomOpen = function* watchRoomOpen({ room }) {
|
||||||
const auth = yield select(state => state.login.isAuthenticated);
|
const auth = yield select(state => state.login.isAuthenticated);
|
||||||
|
@ -50,7 +62,7 @@ const watchRoomOpen = function* watchRoomOpen({ room }) {
|
||||||
yield take(types.LOGIN.SUCCESS);
|
yield take(types.LOGIN.SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
const subscriptions = [];
|
|
||||||
yield put(messagesRequest({ rid: room.rid }));
|
yield put(messagesRequest({ rid: room.rid }));
|
||||||
|
|
||||||
const { open } = yield race({
|
const { open } = yield race({
|
||||||
|
@ -62,12 +74,16 @@ const watchRoomOpen = function* watchRoomOpen({ room }) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RocketChat.readMessages(room.rid);
|
RocketChat.readMessages(room.rid);
|
||||||
subscriptions.push(RocketChat.subscribe('stream-room-messages', room.rid, false));
|
const subscriptions = yield Promise.all([RocketChat.subscribe('stream-room-messages', room.rid, false), RocketChat.subscribe('stream-notify-room', `${ room.rid }/typing`, false)]);
|
||||||
subscriptions.push(RocketChat.subscribe('stream-notify-room', `${ room.rid }/typing`, false));
|
|
||||||
const thread = yield fork(usersTyping, { rid: room.rid });
|
const thread = yield fork(usersTyping, { rid: room.rid });
|
||||||
yield take(types.ROOM.OPEN);
|
yield race({
|
||||||
|
open: take(types.ROOM.OPEN),
|
||||||
|
close: take(types.ROOM.CLOSE)
|
||||||
|
});
|
||||||
cancel(thread);
|
cancel(thread);
|
||||||
subscriptions.forEach(sub => sub.unsubscribe());
|
subscriptions.forEach((sub) => {
|
||||||
|
sub.unsubscribe().catch(e => alert(e));
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const watchuserTyping = function* watchuserTyping({ status }) {
|
const watchuserTyping = function* watchuserTyping({ status }) {
|
||||||
|
@ -96,11 +112,18 @@ const updateRoom = function* updateRoom() {
|
||||||
}
|
}
|
||||||
yield put(messagesRequest({ rid: room.rid }));
|
yield put(messagesRequest({ rid: room.rid }));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const updateLastOpen = function* updateLastOpen() {
|
||||||
|
yield put(setLastOpen());
|
||||||
|
};
|
||||||
|
|
||||||
const root = function* root() {
|
const root = function* root() {
|
||||||
yield takeLatest(types.ROOM.USER_TYPING, watchuserTyping);
|
yield takeLatest(types.ROOM.USER_TYPING, watchuserTyping);
|
||||||
yield takeLatest(types.LOGIN.SUCCESS, watchRoomsRequest);
|
yield takeLatest(types.LOGIN.SUCCESS, watchRoomsRequest);
|
||||||
yield takeLatest(types.ROOM.OPEN, watchRoomOpen);
|
yield takeLatest(types.ROOM.OPEN, watchRoomOpen);
|
||||||
|
yield takeEvery(types.ROOM.MESSAGE_RECEIVED, handleMessageReceived);
|
||||||
yield takeLatest(FOREGROUND, updateRoom);
|
yield takeLatest(FOREGROUND, updateRoom);
|
||||||
yield takeLatest(FOREGROUND, watchRoomsRequest);
|
yield takeLatest(FOREGROUND, watchRoomsRequest);
|
||||||
|
yield takeLatest(BACKGROUND, updateLastOpen);
|
||||||
};
|
};
|
||||||
export default root;
|
export default root;
|
||||||
|
|
|
@ -9,14 +9,18 @@ import realm from '../../../lib/realm';
|
||||||
import Avatar from '../../../containers/Avatar';
|
import Avatar from '../../../containers/Avatar';
|
||||||
import { STATUS_COLORS } from '../../../constants/colors';
|
import { STATUS_COLORS } from '../../../constants/colors';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
import { closeRoom } from '../../../actions/room';
|
||||||
|
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
user: state.login.user,
|
user: state.login.user,
|
||||||
baseUrl: state.settings.Site_Url || state.server ? state.server.server : '',
|
baseUrl: state.settings.Site_Url || state.server ? state.server.server : '',
|
||||||
activeUsers: state.activeUsers
|
activeUsers: state.activeUsers
|
||||||
|
}), dispatch => ({
|
||||||
|
close: () => dispatch(closeRoom())
|
||||||
}))
|
}))
|
||||||
export default class extends React.PureComponent {
|
export default class extends React.PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
close: PropTypes.func.isRequired,
|
||||||
navigation: PropTypes.object.isRequired,
|
navigation: PropTypes.object.isRequired,
|
||||||
user: PropTypes.object.isRequired,
|
user: PropTypes.object.isRequired,
|
||||||
baseUrl: PropTypes.string,
|
baseUrl: PropTypes.string,
|
||||||
|
@ -57,7 +61,15 @@ export default class extends React.PureComponent {
|
||||||
|
|
||||||
isDirect = () => this.state.room && this.state.room.t === 'd';
|
isDirect = () => this.state.room && this.state.room.t === 'd';
|
||||||
|
|
||||||
renderLeft = () => <HeaderBackButton onPress={() => this.props.navigation.goBack(null)} tintColor='#292E35' title='Back' titleStyle={{ display: 'none' }} />;
|
renderLeft = () => (<HeaderBackButton
|
||||||
|
onPress={() => {
|
||||||
|
this.props.close();
|
||||||
|
this.props.navigation.goBack(null);
|
||||||
|
}}
|
||||||
|
tintColor='#292E35'
|
||||||
|
title='Back'
|
||||||
|
titleStyle={{ display: 'none' }}
|
||||||
|
/>);
|
||||||
|
|
||||||
renderTitle() {
|
renderTitle() {
|
||||||
if (!this.state.roomName) {
|
if (!this.state.roomName) {
|
||||||
|
|
|
@ -32,7 +32,8 @@ const typing = () => <Typing />;
|
||||||
Site_Url: state.settings.Site_Url || state.server ? state.server.server : '',
|
Site_Url: state.settings.Site_Url || state.server ? state.server.server : '',
|
||||||
Message_TimeFormat: state.settings.Message_TimeFormat,
|
Message_TimeFormat: state.settings.Message_TimeFormat,
|
||||||
loading: state.messages.isFetching,
|
loading: state.messages.isFetching,
|
||||||
user: state.login.user
|
user: state.login.user,
|
||||||
|
lastOpened: state.room.lastOpen
|
||||||
}),
|
}),
|
||||||
dispatch => ({
|
dispatch => ({
|
||||||
actions: bindActionCreators(actions, dispatch),
|
actions: bindActionCreators(actions, dispatch),
|
||||||
|
@ -42,6 +43,7 @@ const typing = () => <Typing />;
|
||||||
)
|
)
|
||||||
export default class RoomView extends React.Component {
|
export default class RoomView extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
// lastOpened: PropTypes.instanceOf(Date),
|
||||||
navigation: PropTypes.object.isRequired,
|
navigation: PropTypes.object.isRequired,
|
||||||
openRoom: PropTypes.func.isRequired,
|
openRoom: PropTypes.func.isRequired,
|
||||||
user: PropTypes.object.isRequired,
|
user: PropTypes.object.isRequired,
|
||||||
|
|
Loading…
Reference in New Issue