fix: do not return updated messages from markAllRead if not needed

pull/2560/head
Audric Ackermann 3 years ago
parent ff37deebc0
commit e3006ae157

@ -493,9 +493,13 @@ async function getUnreadByConversation(conversationId: string): Promise<MessageC
} }
async function markAllAsReadByConversationNoExpiration( async function markAllAsReadByConversationNoExpiration(
conversationId: string conversationId: string,
returnMessagesUpdated: boolean // for performances reason we do not return them because usually they are not needed
): Promise<Array<number>> { ): Promise<Array<number>> {
const messagesIds = await channels.markAllAsReadByConversationNoExpiration(conversationId); const messagesIds = await channels.markAllAsReadByConversationNoExpiration(
conversationId,
returnMessagesUpdated
);
return messagesIds; return messagesIds;
} }

@ -254,11 +254,7 @@ export function showLeaveGroupByConvoId(conversationId: string) {
export function showInviteContactByConvoId(conversationId: string) { export function showInviteContactByConvoId(conversationId: string) {
window.inboxStore?.dispatch(updateInviteContactModal({ conversationId })); window.inboxStore?.dispatch(updateInviteContactModal({ conversationId }));
} }
export async function onMarkAllReadByConvoId(conversationId: string) {
const conversation = getConversationController().get(conversationId);
await conversation.markReadBouncy(Date.now());
}
export function showAddModeratorsByConvoId(conversationId: string) { export function showAddModeratorsByConvoId(conversationId: string) {
window.inboxStore?.dispatch(updateAddModeratorsModal({ conversationId })); window.inboxStore?.dispatch(updateAddModeratorsModal({ conversationId }));

@ -32,6 +32,7 @@ import {
actions as conversationActions, actions as conversationActions,
conversationChanged, conversationChanged,
conversationsChanged, conversationsChanged,
markConversationFullyRead,
MessageModelPropsWithoutConvoProps, MessageModelPropsWithoutConvoProps,
ReduxConversationType, ReduxConversationType,
} from '../state/ducks/conversations'; } from '../state/ducks/conversations';
@ -1231,27 +1232,38 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
* Send read receipt if needed. * Send read receipt if needed.
*/ */
public async markAllAsRead() { public async markAllAsRead() {
if (this.isOpenGroupV2()) { /**
* when marking all as read, there is a bunch of things we need to do.
* - we need to update all the messages in the DB not read yet for that conversation
* - we need to send the read receipts if there is one needed for those messages
* - we need to trigger a change on the redux store, so those messages are read AND mark the whole convo as read.
* - we need to remove any notifications related to this conversation ID.
*
*
* (if there is an expireTimer, we do it the slow way, handling each message separately)
*/
const expireTimerSet = !!this.get('expireTimer');
if (this.isOpenGroupV2() || !expireTimerSet) {
// for opengroups, we batch everything as there is no expiration timer to take care (and potentially a lot of messages) // for opengroups, we batch everything as there is no expiration timer to take care (and potentially a lot of messages)
await Data.markAllAsReadByConversationNoExpiration(this.id); const isOpenGroup = this.isOpenGroupV2();
// if this is an opengroup there is no need to send read receipt, and so no need to fetch messages updated.
const allReadMessages = await Data.markAllAsReadByConversationNoExpiration(
this.id,
!isOpenGroup
);
this.set({ mentionedUs: false, unreadCount: 0 }); this.set({ mentionedUs: false, unreadCount: 0 });
await this.commit(); await this.commit();
return; if (!this.isOpenGroupV2() && allReadMessages.length) {
}
// if the conversation has no expiration timer, we can also batch everything, but we also need to send read receipts potentially
// so we grab them from the db
if (!this.get('expireTimer')) {
const allReadMessages = await Data.markAllAsReadByConversationNoExpiration(this.id);
this.set({ mentionedUs: false, unreadCount: 0 });
await this.commit();
if (allReadMessages.length) {
await this.sendReadReceiptsIfNeeded(uniq(allReadMessages)); await this.sendReadReceiptsIfNeeded(uniq(allReadMessages));
} }
Notifications.clearByConversationID(this.id);
window.inboxStore?.dispatch(markConversationFullyRead(this.id));
return; return;
} }
// otherwise, do it the slow way
await this.markReadBouncy(Date.now()); await this.markReadBouncy(Date.now());
} }

@ -1117,18 +1117,23 @@ function getUnreadByConversation(conversationId: string) {
* Warning: This does not start expiration timer * Warning: This does not start expiration timer
*/ */
function markAllAsReadByConversationNoExpiration( function markAllAsReadByConversationNoExpiration(
conversationId: string conversationId: string,
): Array<{ id: string; timestamp: number }> { returnMessagesUpdated: boolean
const messagesUnreadBefore = assertGlobalInstance() ): Array<number> {
.prepare( let toReturn: Array<number> = [];
`SELECT json FROM ${MESSAGES_TABLE} WHERE if (returnMessagesUpdated) {
unread = $unread AND const messagesUnreadBefore = assertGlobalInstance()
conversationId = $conversationId;` .prepare(
) `SELECT json FROM ${MESSAGES_TABLE} WHERE
.all({ unread = $unread AND
unread: 1, conversationId = $conversationId;`
conversationId, )
}); .all({
unread: 1,
conversationId,
});
toReturn = compact(messagesUnreadBefore.map(row => jsonToObject(row.json).sent_at));
}
assertGlobalInstance() assertGlobalInstance()
.prepare( .prepare(
@ -1142,7 +1147,7 @@ function markAllAsReadByConversationNoExpiration(
conversationId, conversationId,
}); });
return compact(messagesUnreadBefore.map(row => jsonToObject(row.json).sent_at)); return toReturn;
} }
function getUnreadCountByConversation(conversationId: string) { function getUnreadCountByConversation(conversationId: string) {

@ -699,11 +699,23 @@ const conversationsSlice = createSlice({
return state; return state;
} }
let updatedMessages = state.messages;
// if some are unread, mark them as read
if (state.messages.some(m => m.propsForMessage.isUnread)) {
updatedMessages = state.messages.map(m => ({
...m,
propsForMessage: { ...m.propsForMessage, isUnread: false },
}));
}
// keep the unread visible just like in other apps. It will be shown until the user changes convo // keep the unread visible just like in other apps. It will be shown until the user changes convo
return { return {
...state, ...state,
shouldHighlightMessage: false, shouldHighlightMessage: false,
firstUnreadMessageId: undefined, firstUnreadMessageId: undefined,
messages: updatedMessages,
}; };
}, },
/** /**

Loading…
Cancel
Save