- (
)
+
+ ()
diff --git a/addons/mail/static/src/web/messaging_menu/messaging_menu.js b/addons/mail/static/src/web/messaging_menu/messaging_menu.js
index 0b8c781d73c..e4bc9c47275 100644
--- a/addons/mail/static/src/web/messaging_menu/messaging_menu.js
+++ b/addons/mail/static/src/web/messaging_menu/messaging_menu.js
@@ -42,13 +42,13 @@ export class MessagingMenu extends Component {
}
beforeOpen() {
- this.messaging.fetchPreviews();
+ this.threadService.fetchPreviews();
if (
!this.store.discuss.inbox.isLoaded &&
this.store.discuss.inbox.status !== "loading" &&
this.store.discuss.inbox.counter !== this.store.discuss.inbox.messages.length
) {
- this.threadService.fetchMessages(this.store.discuss.inbox);
+ this.threadService.fetchNewMessages(this.store.discuss.inbox);
}
}
@@ -117,24 +117,22 @@ export class MessagingMenu extends Component {
if (a.correspondent === this.store.odoobot) {
return 1;
}
- if (!a.mostRecentNonTransientMessage?.datetime) {
+ if (!a.newestPersistentMessage?.datetime) {
return -1;
}
- if (!b.mostRecentNonTransientMessage?.datetime) {
+ if (!b.newestPersistentMessage?.datetime) {
return 1;
}
- return (
- b.mostRecentNonTransientMessage.datetime - a.mostRecentNonTransientMessage.datetime
- );
+ return b.newestPersistentMessage.datetime - a.newestPersistentMessage.datetime;
});
const previews = [];
for (const thread of threads) {
- const { mostRecentMsg, mostRecentNeedactionMsg } = thread;
+ const { newestMessage, newestNeedactionMessage } = thread;
if (thread.is_pinned) {
- const message = mostRecentMsg;
+ const message = newestMessage;
previews.push({
id: `preview-${thread.localId}`,
- count: this.threadService.localMessageUnreadCounter(thread),
+ count: thread.message_unread_counter,
imgUrl: thread.imgUrl,
hasMarkAsReadButton: this.threadService.isUnread(thread),
message,
@@ -142,8 +140,8 @@ export class MessagingMenu extends Component {
isNeedaction: false,
});
}
- if (mostRecentNeedactionMsg) {
- const message = mostRecentNeedactionMsg;
+ if (newestNeedactionMessage) {
+ const message = newestNeedactionMessage;
previews.push({
id: `preview-needaction-${thread.localId}`,
count: thread.needactionMessages.length,
diff --git a/addons/mail/static/src/web/thread_service_patch.js b/addons/mail/static/src/web/thread_service_patch.js
index e2665b4a7a5..f54cf2c8ec7 100644
--- a/addons/mail/static/src/web/thread_service_patch.js
+++ b/addons/mail/static/src/web/thread_service_patch.js
@@ -116,7 +116,8 @@ patch(ThreadService.prototype, "mail/web", {
res_id: thread.id,
model: thread.model,
};
- this.messageService.insert(tmpData);
+ const message = this.messageService.insert(tmpData);
+ thread.messages.push(message);
}
return thread;
},
diff --git a/addons/mail/static/tests/core/message_model_tests.js b/addons/mail/static/tests/core/message_model_tests.js
index eb2c07bd09a..9d73f0bb5d4 100644
--- a/addons/mail/static/tests/core/message_model_tests.js
+++ b/addons/mail/static/tests/core/message_model_tests.js
@@ -7,8 +7,6 @@ QUnit.module("message model test", {});
QUnit.test("Message model properties", async (assert) => {
const { env } = await start();
- /** @type {import("@mail/core/store_service").Store} */
- const store = env.services["mail.store"];
env.services["mail.thread"].insert({
id: 3,
model: "res.partner",
@@ -42,8 +40,6 @@ QUnit.test("Message model properties", async (assert) => {
"2019-05-05 10:00:00"
);
assert.strictEqual(message.id, 4000);
- assert.ok(store.discuss.inbox.messages.find((m) => m.id === message.id));
- assert.ok(store.discuss.starred.messages.find((m) => m.id === message.id));
assert.ok(message.attachments);
assert.strictEqual(message.attachments[0].name, "test.txt");
diff --git a/addons/mail/static/tests/discuss/discuss_tests.js b/addons/mail/static/tests/discuss/discuss_tests.js
index 8d0f615b2e9..1aaffe08d15 100644
--- a/addons/mail/static/tests/discuss/discuss_tests.js
+++ b/addons/mail/static/tests/discuss/discuss_tests.js
@@ -1557,7 +1557,6 @@ QUnit.test("new messages separator [REQUIRE FOCUS]", async (assert) => {
// this test requires several messages so that the last message is not
// visible. This is necessary in order to display 'new messages' and not
// remove from DOM right away from seeing last message.
- // AKU TODO: thread specific test
const pyEnv = await startServer();
const partnerId = pyEnv["res.partner"].create({ name: "Foreigner partner" });
const userId = pyEnv["res.users"].create({
diff --git a/addons/mail/static/tests/discuss/sidebar_tests.js b/addons/mail/static/tests/discuss/sidebar_tests.js
index 1cd0d8d063d..b8615ed53af 100644
--- a/addons/mail/static/tests/discuss/sidebar_tests.js
+++ b/addons/mail/static/tests/discuss/sidebar_tests.js
@@ -1155,7 +1155,7 @@ QUnit.test("Group unread counter up to date after mention is marked as seen", as
author_id: partnerId,
model: "mail.channel",
res_id: channelId,
- body: `@Mitchell Admin`,
+ body: "@Mitchell Admin",
needaction: true,
});
pyEnv["mail.notification"].create([
diff --git a/addons/mail/static/tests/helpers/mock_server/controllers/discuss.js b/addons/mail/static/tests/helpers/mock_server/controllers/discuss.js
index 117617725ed..585f1e6d640 100644
--- a/addons/mail/static/tests/helpers/mock_server/controllers/discuss.js
+++ b/addons/mail/static/tests/helpers/mock_server/controllers/discuss.js
@@ -40,8 +40,8 @@ patch(MockServer.prototype, "mail/controllers/discuss", {
return this._mockRouteMailAttachmentRemove(attachment_id);
}
if (route === "/mail/channel/messages") {
- const { channel_id, min_id, max_id, limit } = args;
- return this._mockRouteMailChannelMessages(channel_id, max_id, min_id, limit);
+ const { channel_id, after, before, limit } = args;
+ return this._mockRouteMailChannelMessages(channel_id, before, after, limit);
}
if (route === "/mail/channel/notify_typing") {
const id = args.channel_id;
@@ -60,15 +60,15 @@ patch(MockServer.prototype, "mail/controllers/discuss", {
return this._mockMailChannelLoadMoreMembers([channel_id], known_member_ids);
}
if (route === "/mail/history/messages") {
- const { min_id, max_id, limit } = args;
- return this._mockRouteMailMessageHistory(min_id, max_id, limit);
+ const { after, before, limit } = args;
+ return this._mockRouteMailMessageHistory(after, before, limit);
}
if (route === "/mail/init_messaging") {
return this._mockRouteMailInitMessaging();
}
if (route === "/mail/inbox/messages") {
- const { min_id, max_id, limit } = args;
- return this._mockRouteMailMessageInbox(min_id, max_id, limit);
+ const { after, before, limit } = args;
+ return this._mockRouteMailMessageInbox(after, before, limit);
}
if (route === "/mail/link_preview") {
return this._mockRouteMailLinkPreview(args.message_id);
@@ -142,8 +142,8 @@ patch(MockServer.prototype, "mail/controllers/discuss", {
return;
}
if (route === "/mail/starred/messages") {
- const { min_id, max_id, limit } = args;
- return this._mockRouteMailMessageStarredMessages(min_id, max_id, limit);
+ const { after, before, limit } = args;
+ return this._mockRouteMailMessageStarredMessages(after, before, limit);
}
if (route === "/mail/thread/data") {
return this._mockRouteMailThreadData(
@@ -153,12 +153,12 @@ patch(MockServer.prototype, "mail/controllers/discuss", {
);
}
if (route === "/mail/thread/messages") {
- const { min_id, max_id, limit, thread_model, thread_id } = args;
+ const { after, before, limit, thread_model, thread_id } = args;
return this._mockRouteMailThreadFetchMessages(
thread_model,
thread_id,
- max_id,
- min_id,
+ before,
+ after,
limit
);
}
@@ -191,17 +191,17 @@ patch(MockServer.prototype, "mail/controllers/discuss", {
* @private
* @param {integer} channel_id
* @param {integer} limit
- * @param {integer} max_id
- * @param {integer} min_id
+ * @param {integer} before
+ * @param {integer} after
* @returns {Object} list of messages
*/
- async _mockRouteMailChannelMessages(channel_id, max_id = false, min_id = false, limit = 30) {
+ async _mockRouteMailChannelMessages(channel_id, before = false, after = false, limit = 30) {
const domain = [
["res_id", "=", channel_id],
["model", "=", "mail.channel"],
["message_type", "!=", "user_notification"],
];
- const messages = this._mockMailMessage_MessageFetch(domain, max_id, min_id, limit);
+ const messages = this._mockMailMessage_MessageFetch(domain, before, after, limit);
this._mockMailMessageSetMessageDone(messages.map((message) => message.id));
return this._mockMailMessageMessageFormat(messages.map((message) => message.id));
},
@@ -297,9 +297,9 @@ patch(MockServer.prototype, "mail/controllers/discuss", {
* @private
* @returns {Object}
*/
- _mockRouteMailMessageHistory(min_id = false, max_id = false, limit = 30) {
+ _mockRouteMailMessageHistory(after = false, before = false, limit = 30) {
const domain = [["needaction", "=", false]];
- const messages = this._mockMailMessage_MessageFetch(domain, max_id, min_id, limit);
+ const messages = this._mockMailMessage_MessageFetch(domain, before, after, limit);
const messagesWithNotification = messages.filter((message) => {
const notifs = this.pyEnv["mail.notification"].searchRead([
["mail_message_id", "=", message.id],
@@ -319,9 +319,9 @@ patch(MockServer.prototype, "mail/controllers/discuss", {
* @private
* @returns {Object}
*/
- _mockRouteMailMessageInbox(min_id = false, max_id = false, limit = 30) {
+ _mockRouteMailMessageInbox(after = false, before = false, limit = 30) {
const domain = [["needaction", "=", true]];
- const messages = this._mockMailMessage_MessageFetch(domain, max_id, min_id, limit);
+ const messages = this._mockMailMessage_MessageFetch(domain, before, after, limit);
return this._mockMailMessageMessageFormat(messages.map((message) => message.id));
},
/**
@@ -330,9 +330,9 @@ patch(MockServer.prototype, "mail/controllers/discuss", {
* @private
* @returns {Object}
*/
- _mockRouteMailMessageStarredMessages(min_id = false, max_id = false, limit = 30) {
+ _mockRouteMailMessageStarredMessages(after = false, before = false, limit = 30) {
const domain = [["starred_partner_ids", "in", [this.currentPartnerId]]];
- const messages = this._mockMailMessage_MessageFetch(domain, max_id, min_id, limit);
+ const messages = this._mockMailMessage_MessageFetch(domain, before, after, limit);
return this._mockMailMessageMessageFormat(messages.map((message) => message.id));
},
/**
@@ -514,16 +514,16 @@ patch(MockServer.prototype, "mail/controllers/discuss", {
* @private
* @param {string} res_model
* @param {integer} res_id
- * @param {integer} max_id
- * @param {integer} min_id
+ * @param {integer} before
+ * @param {integer} after
* @param {integer} limit
* @returns {Object[]} list of messages
*/
async _mockRouteMailThreadFetchMessages(
res_model,
res_id,
- max_id = false,
- min_id = false,
+ before = false,
+ after = false,
limit = 30
) {
const domain = [
@@ -531,7 +531,7 @@ patch(MockServer.prototype, "mail/controllers/discuss", {
["model", "=", res_model],
["message_type", "!=", "user_notification"],
];
- const messages = this._mockMailMessage_MessageFetch(domain, max_id, min_id, limit);
+ const messages = this._mockMailMessage_MessageFetch(domain, before, after, limit);
this._mockMailMessageSetMessageDone(messages.map((message) => message.id));
return this._mockMailMessageMessageFormat(messages.map((message) => message.id));
},
diff --git a/addons/mail/static/tests/helpers/mock_server/models/mail_channel.js b/addons/mail/static/tests/helpers/mock_server/models/mail_channel.js
index 78a768ca24e..48147388210 100644
--- a/addons/mail/static/tests/helpers/mock_server/models/mail_channel.js
+++ b/addons/mail/static/tests/helpers/mock_server/models/mail_channel.js
@@ -552,7 +552,7 @@ patch(MockServer.prototype, "mail/models/mail_channel", {
});
Object.assign(channelData, {
custom_channel_name: memberOfCurrentUser.custom_channel_name,
- serverMessageUnreadCounter: memberOfCurrentUser.message_unread_counter,
+ message_unread_counter: memberOfCurrentUser.message_unread_counter,
});
if (memberOfCurrentUser.rtc_inviting_session_id) {
res["rtc_inviting_session"] = {
diff --git a/addons/mail/static/tests/helpers/mock_server/models/mail_message.js b/addons/mail/static/tests/helpers/mock_server/models/mail_message.js
index b2740820bd9..ee80556c3a4 100644
--- a/addons/mail/static/tests/helpers/mock_server/models/mail_message.js
+++ b/addons/mail/static/tests/helpers/mock_server/models/mail_message.js
@@ -134,17 +134,17 @@ patch(MockServer.prototype, "mail/models/mail_message", {
*
* @private
* @param {Array[]} domain
- * @param {integer} [max_id]
- * @param {integer} [min_id]
+ * @param {integer} [before]
+ * @param {integer} [after]
* @param {integer} [limit=30]
* @returns {Object[]}
*/
- _mockMailMessage_MessageFetch(domain, max_id, min_id, limit = 30) {
- if (max_id) {
- domain.push(["id", "<", max_id]);
+ _mockMailMessage_MessageFetch(domain, before, after, limit = 30) {
+ if (before) {
+ domain.push(["id", "<", before]);
}
- if (min_id) {
- domain.push(["id", ">", min_id]);
+ if (after) {
+ domain.push(["id", ">", after]);
}
const messages = this.getRecords("mail.message", domain);
// sorted from highest ID to lowest ID (i.e. from youngest to oldest)
diff --git a/addons/mail/static/tests/helpers/test_utils.js b/addons/mail/static/tests/helpers/test_utils.js
index 428995eb2c0..d1585713a9f 100644
--- a/addons/mail/static/tests/helpers/test_utils.js
+++ b/addons/mail/static/tests/helpers/test_utils.js
@@ -174,6 +174,11 @@ function getOpenDiscuss(webClient, { context = {}, params = {}, ...props } = {})
);
if (waitUntilMessagesLoaded) {
const messagesLoadedPromise = makeDeferred();
+ const store = webClient.env.services["mail.store"];
+ const thread = store.threads[store.discuss.threadLocalId];
+ if (thread.isLoaded) {
+ messagesLoadedPromise.resolve();
+ }
let loadMessageRoute = `/mail/${threadId}/messages`;
if (Number.isInteger(threadId)) {
loadMessageRoute = "/mail/channel/messages";
diff --git a/addons/mail/static/tests/message/message_tests.js b/addons/mail/static/tests/message/message_tests.js
index b786086a3c4..c1173f81a7b 100644
--- a/addons/mail/static/tests/message/message_tests.js
+++ b/addons/mail/static/tests/message/message_tests.js
@@ -1421,12 +1421,22 @@ QUnit.test("Can reply to chatter messages from history", async (assert) => {
QUnit.test("Mark as unread", async (assert) => {
const pyEnv = await startServer();
- const channelId = pyEnv["mail.channel"].create({ channel_type: "chat", name: "General" });
- pyEnv["mail.message"].create({
+ const channelId = pyEnv["mail.channel"].create({
+ channel_type: "chat",
+ name: "General",
+ });
+ const messageId = pyEnv["mail.message"].create({
model: "mail.channel",
res_id: channelId,
body: "Hello World!",
});
+ const [memberId] = pyEnv["mail.channel.member"].search([
+ ["channel_id", "=", channelId],
+ ["partner_id", "=", pyEnv.currentPartnerId],
+ ]);
+ pyEnv["mail.channel.member"].write([memberId], {
+ seen_message_id: messageId,
+ });
const { openDiscuss } = await start();
await openDiscuss(channelId);
await click("[title='Expand']");
diff --git a/addons/mail/static/tests/messaging_menu/messaging_menu_tests.js b/addons/mail/static/tests/messaging_menu/messaging_menu_tests.js
index 9702afcdaea..64a43d08303 100644
--- a/addons/mail/static/tests/messaging_menu/messaging_menu_tests.js
+++ b/addons/mail/static/tests/messaging_menu/messaging_menu_tests.js
@@ -837,7 +837,12 @@ QUnit.test(
async (assert) => {
const pyEnv = await startServer();
const partnerId = pyEnv["res.partner"].create({ name: "Partner1" });
- const channelId = pyEnv["mail.channel"].create({ name: "Test" });
+ const channelId = pyEnv["mail.channel"].create({
+ name: "Test",
+ channel_member_ids: [
+ [0, 0, { message_unread_counter: 2, partner_id: pyEnv.currentPartnerId }],
+ ],
+ });
const messageId = pyEnv["mail.message"].create({
author_id: partnerId,
body: "Message with needaction",
diff --git a/addons/mail/static/tests/thread/thread_tests.js b/addons/mail/static/tests/thread/thread_tests.js
index b2384d91450..f74d61f1988 100644
--- a/addons/mail/static/tests/thread/thread_tests.js
+++ b/addons/mail/static/tests/thread/thread_tests.js
@@ -880,6 +880,7 @@ QUnit.test(
async (assert) => {
const pyEnv = await startServer();
const channelId = pyEnv["mail.channel"].create({ name: "General" });
+ const partnerId = pyEnv["res.partner"].create({ name: "Demo" });
const { env, openDiscuss } = await start({
mockRPC(route, args) {
if (args.model === "mail.message" && args.method === "mark_all_as_read") {
@@ -896,6 +897,7 @@ QUnit.test(
await triggerEvents($(".o-mail-Composer-input")[0], null, ["blur", "focusout"]);
await click("button:contains(Inbox)");
const messageId = pyEnv["mail.message"].create({
+ author_id: partnerId,
body: "@Mitchel Admin",
needaction: true,
model: "mail.channel",
diff --git a/addons/test_discuss_full/tests/test_performance.py b/addons/test_discuss_full/tests/test_performance.py
index f40afd30b8b..3c276ab8d96 100644
--- a/addons/test_discuss_full/tests/test_performance.py
+++ b/addons/test_discuss_full/tests/test_performance.py
@@ -142,7 +142,7 @@ class TestDiscussFullPerformance(TransactionCase):
'custom_channel_name': False,
'id': self.channel_general.id,
'memberCount': len(self.group_user.users | self.user_root),
- 'serverMessageUnreadCounter': 5,
+ 'message_unread_counter': 5,
},
'create_uid': self.user_root.id,
'defaultDisplayMode': False,
@@ -191,7 +191,7 @@ class TestDiscussFullPerformance(TransactionCase):
'custom_channel_name': False,
'id': self.channel_channel_public_1.id,
'memberCount': 5,
- 'serverMessageUnreadCounter': 0,
+ 'message_unread_counter': 0,
},
'create_uid': self.env.user.id,
'defaultDisplayMode': False,
@@ -240,7 +240,7 @@ class TestDiscussFullPerformance(TransactionCase):
'custom_channel_name': False,
'id': self.channel_channel_public_2.id,
'memberCount': 5,
- 'serverMessageUnreadCounter': 0,
+ 'message_unread_counter': 0,
},
'create_uid': self.env.user.id,
'defaultDisplayMode': False,
@@ -289,7 +289,7 @@ class TestDiscussFullPerformance(TransactionCase):
'custom_channel_name': False,
'id': self.channel_channel_group_1.id,
'memberCount': 5,
- 'serverMessageUnreadCounter': 0,
+ 'message_unread_counter': 0,
},
'create_uid': self.env.user.id,
'defaultDisplayMode': False,
@@ -338,7 +338,7 @@ class TestDiscussFullPerformance(TransactionCase):
'custom_channel_name': False,
'id': self.channel_channel_group_2.id,
'memberCount': 5,
- 'serverMessageUnreadCounter': 0,
+ 'message_unread_counter': 0,
},
'create_uid': self.env.user.id,
'defaultDisplayMode': False,
@@ -409,7 +409,7 @@ class TestDiscussFullPerformance(TransactionCase):
'custom_channel_name': False,
'id': self.channel_group_1.id,
'memberCount': 2,
- 'serverMessageUnreadCounter': 0,
+ 'message_unread_counter': 0,
},
'create_uid': self.env.user.id,
'defaultDisplayMode': False,
@@ -494,7 +494,7 @@ class TestDiscussFullPerformance(TransactionCase):
'custom_channel_name': False,
'id': self.channel_chat_1.id,
'memberCount': 2,
- 'serverMessageUnreadCounter': 0,
+ 'message_unread_counter': 0,
},
'create_uid': self.env.user.id,
'defaultDisplayMode': False,
@@ -579,7 +579,7 @@ class TestDiscussFullPerformance(TransactionCase):
'custom_channel_name': False,
'id': self.channel_chat_2.id,
'memberCount': 2,
- 'serverMessageUnreadCounter': 0,
+ 'message_unread_counter': 0,
},
'create_uid': self.env.user.id,
'defaultDisplayMode': False,
@@ -664,7 +664,7 @@ class TestDiscussFullPerformance(TransactionCase):
'custom_channel_name': False,
'id': self.channel_chat_3.id,
'memberCount': 2,
- 'serverMessageUnreadCounter': 0,
+ 'message_unread_counter': 0,
},
'create_uid': self.env.user.id,
'defaultDisplayMode': False,
@@ -749,7 +749,7 @@ class TestDiscussFullPerformance(TransactionCase):
'custom_channel_name': False,
'id': self.channel_chat_4.id,
'memberCount': 2,
- 'serverMessageUnreadCounter': 0,
+ 'message_unread_counter': 0,
},
'create_uid': self.env.user.id,
'defaultDisplayMode': False,
@@ -828,7 +828,7 @@ class TestDiscussFullPerformance(TransactionCase):
'custom_channel_name': False,
'id': self.channel_livechat_1.id,
'memberCount': 2,
- 'serverMessageUnreadCounter': 0,
+ 'message_unread_counter': 0,
},
'create_uid': self.env.user.id,
'defaultDisplayMode': False,
@@ -907,7 +907,7 @@ class TestDiscussFullPerformance(TransactionCase):
'custom_channel_name': False,
'id': self.channel_livechat_2.id,
'memberCount': 2,
- 'serverMessageUnreadCounter': 0,
+ 'message_unread_counter': 0,
},
'create_uid': self.env.ref('base.public_user').id,
'defaultDisplayMode': False,