Get the correct unread count for a conversation

This commit is contained in:
Josh Perez 2021-05-10 14:49:13 -04:00 committed by GitHub
parent c68d65ea0b
commit 887b2c1db1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 14 deletions

View File

@ -3975,11 +3975,19 @@ export class ConversationModel extends window.Backbone
sendReadReceipts: true,
}
): Promise<void> {
const unreadCount = await markConversationRead(
const markedUnread = await markConversationRead(
this.attributes,
newestUnreadId,
options
);
if (!markedUnread) {
return;
}
const unreadCount = await window.Signal.Data.getUnreadCountForConversation(
this.id
);
this.set({ unreadCount });
window.Signal.Data.updateConversation(this.attributes);
}

View File

@ -167,6 +167,7 @@ const dataInterface: ClientInterface = {
saveMessages,
removeMessage,
removeMessages,
getUnreadCountForConversation,
getUnreadByConversationAndMarkRead,
getUnreadReactionsAndMarkRead,
markReactionAsRead,
@ -1046,6 +1047,10 @@ async function getMessageBySender(
return new Message(messages[0]);
}
async function getUnreadCountForConversation(conversationId: string) {
return channels.getUnreadCountForConversation(conversationId);
}
async function getUnreadByConversationAndMarkRead(
conversationId: string,
newestUnreadId: number,

View File

@ -343,6 +343,7 @@ export type ServerInterface = DataInterface & {
getNextTapToViewMessageToAgeOut: () => Promise<MessageType | undefined>;
getOutgoingWithoutExpiresAt: () => Promise<Array<MessageType>>;
getTapToViewMessagesNeedingErase: () => Promise<Array<MessageType>>;
getUnreadCountForConversation: (conversationId: string) => Promise<number>;
getUnreadByConversationAndMarkRead: (
conversationId: string,
newestUnreadId: number,
@ -486,6 +487,7 @@ export type ClientInterface = DataInterface & {
getTapToViewMessagesNeedingErase: (options: {
MessageCollection: typeof MessageModelCollectionType;
}) => Promise<MessageModelCollectionType>;
getUnreadCountForConversation: (conversationId: string) => Promise<number>;
getUnreadByConversationAndMarkRead: (
conversationId: string,
newestUnreadId: number,

View File

@ -157,6 +157,7 @@ const dataInterface: ServerInterface = {
saveMessages,
removeMessage,
removeMessages,
getUnreadCountForConversation,
getUnreadByConversationAndMarkRead,
getUnreadReactionsAndMarkRead,
markReactionAsRead,
@ -3092,6 +3093,24 @@ function updateExpirationTimers(
);
}
async function getUnreadCountForConversation(
conversationId: string
): Promise<number> {
const db = getInstance();
const row = db
.prepare<Query>(
`
SELECT COUNT(*) AS unreadCount FROM messages
WHERE unread = 1 AND
conversationId = $conversationId
`
)
.get({
conversationId,
});
return row.unreadCount;
}
async function getUnreadByConversationAndMarkRead(
conversationId: string,
newestUnreadId: number,
@ -3118,6 +3137,10 @@ async function getUnreadByConversationAndMarkRead(
newestUnreadId,
});
if (!rows.length) {
return [];
}
const messagesWithExpireTimer: Map<
string,
{

View File

@ -11,7 +11,7 @@ export async function markConversationRead(
options: { readAt?: number; sendReadReceipts: boolean } = {
sendReadReceipts: true,
}
): Promise<number> {
): Promise<boolean> {
const { id: conversationId } = conversationAttrs;
window.Whisper.Notifications.removeBy({ conversationId });
@ -27,6 +27,10 @@ export async function markConversationRead(
),
]);
if (!unreadMessages.length && !unreadReactions.length) {
return false;
}
const unreadReactionSyncData = new Map<
string,
{
@ -67,22 +71,13 @@ export async function markConversationRead(
});
// Some messages we're marking read are local notifications with no sender
const messagesWithSenderId = allReadMessagesSync.filter(syncMessage =>
Boolean(syncMessage.senderId)
);
const incomingUnreadMessages = unreadMessages.filter(
message => message.type === 'incoming'
);
const unreadCount =
incomingUnreadMessages.length - messagesWithSenderId.length;
// If a message has errors, we don't want to send anything out about it.
// read syncs - let's wait for a client that really understands the message
// to mark it read. we'll mark our local error read locally, though.
// read receipts - here we can run into infinite loops, where each time the
// conversation is viewed, another error message shows up for the contact
const unreadMessagesSyncData = messagesWithSenderId.filter(
item => !item.hasErrors
const unreadMessagesSyncData = allReadMessagesSync.filter(
item => Boolean(item.senderId) && !item.hasErrors
);
const readSyncs = [
@ -107,5 +102,5 @@ export async function markConversationRead(
await sendReadReceiptsFor(conversationAttrs, unreadMessagesSyncData);
}
return unreadCount;
return true;
}