[FIX] Unread not going away when receiving a message from inside a room (#194)

* Fix Unread inside Room
This commit is contained in:
Martin Schoeler 2018-01-15 16:44:20 -02:00 committed by Guilherme Gazzo
parent a0cfe3b8c3
commit ec1782e504
8 changed files with 88 additions and 20 deletions

View File

@ -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,

View File

@ -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
};
}

View File

@ -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;
}); });
} }
} }

View File

@ -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('/');

View File

@ -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 {

View File

@ -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;

View File

@ -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) {

View File

@ -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,