[FIX] Rooms list not being updated on some cases (#2765)

* Request subscriptions on RoomsListView.constructor

* Removes opened rooms from last message persisting

* Change server reducer

* Prevent undefined ids causing query error
This commit is contained in:
Diego Mello 2021-01-13 11:16:00 -03:00 committed by GitHub
parent 3b4f4574fe
commit 7f0abe1713
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 45 additions and 36 deletions

View File

@ -1,11 +1,12 @@
import { SERVER } from './actionsTypes'; import { SERVER } from './actionsTypes';
export function selectServerRequest(server, version, fetchVersion = true) { export function selectServerRequest(server, version, fetchVersion = true, changeServer = false) {
return { return {
type: SERVER.SELECT_REQUEST, type: SERVER.SELECT_REQUEST,
server, server,
version, version,
fetchVersion fetchVersion,
changeServer
}; };
} }

View File

@ -8,7 +8,8 @@ const initialState = {
version: null, version: null,
loading: true, loading: true,
adding: false, adding: false,
previousServer: null previousServer: null,
changingServer: false
}; };
@ -34,7 +35,8 @@ export default function server(state = initialState, action) {
version: action.version, version: action.version,
connecting: true, connecting: true,
connected: false, connected: false,
loading: true loading: true,
changingServer: action.changeServer
}; };
case SERVER.SELECT_SUCCESS: case SERVER.SELECT_SUCCESS:
return { return {
@ -43,14 +45,16 @@ export default function server(state = initialState, action) {
version: action.version, version: action.version,
connecting: false, connecting: false,
connected: true, connected: true,
loading: false loading: false,
changingServer: false
}; };
case SERVER.SELECT_FAILURE: case SERVER.SELECT_FAILURE:
return { return {
...state, ...state,
connecting: false, connecting: false,
connected: false, connected: false,
loading: false loading: false,
changingServer: false
}; };
case SERVER.INIT_ADD: case SERVER.INIT_ADD:
return { return {

View File

@ -61,10 +61,16 @@ const handleRoomsRequest = function* handleRoomsRequest({ params }) {
const subsToCreate = subscriptions.filter(i1 => !existingSubs.find(i2 => i1._id === i2._id)); const subsToCreate = subscriptions.filter(i1 => !existingSubs.find(i2 => i1._id === i2._id));
const subsToDelete = existingSubs.filter(i1 => !subscriptions.find(i2 => i1._id === i2._id)); const subsToDelete = existingSubs.filter(i1 => !subscriptions.find(i2 => i1._id === i2._id));
const openedRooms = yield select(state => state.room.rooms);
const lastMessages = subscriptions const lastMessages = subscriptions
/** Checks for opened rooms and filter them out.
* It prevents this process to try persisting the same last message on the room messages fetch.
* This race condition is easy to reproduce on push notification tap.
*/
.filter(sub => !openedRooms.includes(sub.rid))
.map(sub => sub.lastMessage && buildMessage(sub.lastMessage)) .map(sub => sub.lastMessage && buildMessage(sub.lastMessage))
.filter(lm => lm); .filter(lm => lm);
const lastMessagesIds = lastMessages.map(lm => lm._id); const lastMessagesIds = lastMessages.map(lm => lm._id).filter(lm => lm);
const existingMessages = yield messagesCollection.query(Q.where('id', Q.oneOf(lastMessagesIds))).fetch(); const existingMessages = yield messagesCollection.query(Q.where('id', Q.oneOf(lastMessagesIds))).fetch();
const messagesToUpdate = existingMessages.filter(i1 => lastMessages.find(i2 => i1.id === i2._id)); const messagesToUpdate = existingMessages.filter(i1 => lastMessages.find(i2 => i1.id === i2._id));
const messagesToCreate = lastMessages.filter(i1 => !existingMessages.find(i2 => i1._id === i2.id)); const messagesToCreate = lastMessages.filter(i1 => !existingMessages.find(i2 => i1._id === i2.id));

View File

@ -313,7 +313,7 @@ const mapStateToProps = state => ({
const mapDispatchToProps = dispatch => ({ const mapDispatchToProps = dispatch => ({
toggleServerDropdown: () => dispatch(toggleServerDropdownAction()), toggleServerDropdown: () => dispatch(toggleServerDropdownAction()),
selectServerRequest: server => dispatch(selectServerRequestAction(server)), selectServerRequest: server => dispatch(selectServerRequestAction(server, null, null, true)),
appStart: params => dispatch(appStartAction(params)), appStart: params => dispatch(appStartAction(params)),
initAdd: previousServer => dispatch(serverInitAddAction(previousServer)) initAdd: previousServer => dispatch(serverInitAddAction(previousServer))
}); });

View File

@ -117,6 +117,7 @@ class RoomsListView extends React.Component {
}), }),
server: PropTypes.string, server: PropTypes.string,
searchText: PropTypes.string, searchText: PropTypes.string,
changingServer: PropTypes.bool,
loadingServer: PropTypes.bool, loadingServer: PropTypes.bool,
showServerDropdown: PropTypes.bool, showServerDropdown: PropTypes.bool,
showSortDropdown: PropTypes.bool, showSortDropdown: PropTypes.bool,
@ -150,8 +151,8 @@ class RoomsListView extends React.Component {
console.time(`${ this.constructor.name } init`); console.time(`${ this.constructor.name } init`);
console.time(`${ this.constructor.name } mount`); console.time(`${ this.constructor.name } mount`);
this.gotSubscriptions = false;
this.animated = false; this.animated = false;
this.mounted = false;
this.count = 0; this.count = 0;
this.state = { this.state = {
searching: false, searching: false,
@ -162,24 +163,14 @@ class RoomsListView extends React.Component {
item: {} item: {}
}; };
this.setHeader(); this.setHeader();
this.getSubscriptions();
} }
componentDidMount() { componentDidMount() {
const { const {
navigation, closeServerDropdown, appState navigation, closeServerDropdown
} = this.props; } = this.props;
this.mounted = true;
/**
* - When didMount is triggered and appState is foreground,
* it means the user is logging in and selectServer has ran, so we can getSubscriptions
*
* - When didMount is triggered and appState is background,
* it means the user has resumed the app, so selectServer needs to be triggered,
* which is going to change server and getSubscriptions will be triggered by componentWillReceiveProps
*/
if (appState === 'foreground') {
this.getSubscriptions();
}
if (isTablet) { if (isTablet) {
EventEmitter.addEventListener(KEY_COMMAND, this.handleCommands); EventEmitter.addEventListener(KEY_COMMAND, this.handleCommands);
@ -206,17 +197,17 @@ class RoomsListView extends React.Component {
} }
UNSAFE_componentWillReceiveProps(nextProps) { UNSAFE_componentWillReceiveProps(nextProps) {
const { loadingServer, searchText, server } = this.props; const {
loadingServer, searchText, server, changingServer
} = this.props;
if (nextProps.server && loadingServer !== nextProps.loadingServer) { // when the server is changed
if (nextProps.loadingServer) { if (server !== nextProps.server && loadingServer !== nextProps.loadingServer && nextProps.loadingServer) {
this.setState({ loading: true }); this.setState({ loading: true });
} else {
this.getSubscriptions();
}
} }
if (server && server !== nextProps.server) { // when the server is changing and stopped loading
this.gotSubscriptions = false; if (changingServer && loadingServer !== nextProps.loadingServer && !nextProps.loadingServer) {
this.getSubscriptions();
} }
if (searchText !== nextProps.searchText) { if (searchText !== nextProps.searchText) {
this.search(nextProps.searchText); this.search(nextProps.searchText);
@ -508,11 +499,17 @@ class RoomsListView extends React.Component {
tempChats = chats; tempChats = chats;
} }
this.internalSetState({ if (this.mounted) {
chats: tempChats, this.internalSetState({
chatsUpdate, chats: tempChats,
loading: false chatsUpdate,
}); loading: false
});
} else {
this.state.chats = tempChats;
this.state.chatsUpdate = chatsUpdate;
this.state.loading = false;
}
}); });
} }
@ -1023,6 +1020,7 @@ const mapStateToProps = state => ({
user: getUserSelector(state), user: getUserSelector(state),
isMasterDetail: state.app.isMasterDetail, isMasterDetail: state.app.isMasterDetail,
server: state.server.server, server: state.server.server,
changingServer: state.server.changingServer,
connected: state.server.connected, connected: state.server.connected,
searchText: state.rooms.searchText, searchText: state.rooms.searchText,
loadingServer: state.server.loading, loadingServer: state.server.loading,