Skip to content

Commit

Permalink
[FIX] mail: opening chat with deleted new message should mark as read
Browse files Browse the repository at this point in the history
Before this commit, when a user of in chat posted a message and
deleted it, all other users kept the chat as unread.

Steps to reproduce:
- Connect as Admin and March Demo
- Send a message to Admin as Demo in DM chat
- Demo deletes this message
- Marc opens the chat
=> the unread counter is 1 and cannot be removed

This happens because when a message is deleted, there's still a
trace of it but the message is empty. However, empty messages could
not be candidate of setting the last message being seing by a member,
thus members were unable to mark the chat as read until someone else
posted a newer message (and did not delete it).

This commit fixes the issue by taking empty messages into account for
setting last message message of member, which allow to mark thread as
read even when newer messages have been deleted.

opw-3764410

closes #158943

Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
  • Loading branch information
alexkuhn committed Mar 25, 2024
1 parent 751fe52 commit 0aae1ae
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 6 deletions.
20 changes: 16 additions & 4 deletions addons/mail/static/src/core/common/thread_model.js
Original file line number Diff line number Diff line change
Expand Up @@ -456,13 +456,25 @@ export class Thread extends Record {
return [...this.messages].reverse().find((msg) => Number.isInteger(msg.id));
}

newestPersistentNotEmptyOfAllMessage = Record.one("Message", {
newestPersistentAllMessages = Record.many("Message", {
compute() {
const allPersistentMessages = this.allMessages.filter(
(message) => Number.isInteger(message.id) && !message.isEmpty
const allPersistentMessages = this.allMessages.filter((message) =>
Number.isInteger(message.id)
);
allPersistentMessages.sort((m1, m2) => m2.id - m1.id);
return allPersistentMessages[0];
return allPersistentMessages;
},
});

newestPersistentOfAllMessage = Record.one("Message", {
compute() {
return this.newestPersistentAllMessages[0];
},
});

newestPersistentNotEmptyOfAllMessage = Record.one("Message", {
compute() {
return this.newestPersistentAllMessages.find((message) => !message.isEmpty);
},
});

Expand Down
4 changes: 2 additions & 2 deletions addons/mail/static/src/core/common/thread_service.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export class ThreadService {
* @param {import("models").Thread} thread
*/
markAsRead(thread) {
const newestPersistentMessage = thread.newestPersistentNotEmptyOfAllMessage;
const newestPersistentMessage = thread.newestPersistentOfAllMessage;
if (!newestPersistentMessage && !thread.isLoaded) {
thread.isLoadedDeferred
.then(() => new Promise(setTimeout))
Expand Down Expand Up @@ -132,7 +132,7 @@ export class ThreadService {
}
}

updateSeen(thread, lastSeenId = thread.newestPersistentNotEmptyOfAllMessage?.id) {
updateSeen(thread, lastSeenId = thread.newestPersistentOfAllMessage?.id) {
const lastReadIndex = thread.messages.findIndex((message) => message.id === lastSeenId);
let newNeedactionCounter = 0;
let newUnreadCounter = 0;
Expand Down
38 changes: 38 additions & 0 deletions addons/mail/static/tests/discuss_app/discuss_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -2056,3 +2056,41 @@ QUnit.test("Newly created chat should be at the top of the direct message list",
before: [".o-mail-DiscussSidebar-item", { text: "Albert" }],
});
});

QUnit.test("Read of unread chat where new message is deleted should mark as read.", async () => {
const pyEnv = await startServer();
const partnerId = pyEnv["res.partner"].create({ name: "Marc Demo" });
const channelId = pyEnv["discuss.channel"].create({
channel_member_ids: [
Command.create({ partner_id: pyEnv.currentPartnerId }),
Command.create({ partner_id: partnerId }),
],
channel_type: "chat",
});
const messageId = pyEnv["mail.message"].create({
author_id: partnerId,
body: "Heyo",
model: "discuss.channel",
res_id: channelId,
message_type: "comment",
});
const [memberId] = pyEnv["discuss.channel.member"].search([
["channel_id", "=", channelId],
["partner_id", "=", pyEnv.currentPartnerId],
]);
pyEnv["discuss.channel.member"].write([memberId], {
seen_message_id: messageId,
message_unread_counter: 1,
});
const { env, openDiscuss } = await start();
await openDiscuss();
await contains("button", { text: "Marc Demo", contains: [".badge", { text: "1" }] });
// simulate deleted message
await env.services.rpc("/mail/message/update_content", {
message_id: messageId,
body: "",
attachment_ids: [],
});
await click("button", { text: "Marc Demo" });
await contains("button", { text: "Marc Demo", contains: [".badge", { count: 0 }] });
});

0 comments on commit 0aae1ae

Please sign in to comment.