diff --git a/addons/im_livechat/static/src/core/thread_model_patch.js b/addons/im_livechat/static/src/core/thread_model_patch.js index 669c8e16c0a..04799d2887e 100644 --- a/addons/im_livechat/static/src/core/thread_model_patch.js +++ b/addons/im_livechat/static/src/core/thread_model_patch.js @@ -2,13 +2,13 @@ import { DEFAULT_AVATAR } from "@mail/core/common/persona_service"; import { Thread } from "@mail/core/common/thread_model"; -import { assignDefined, createLocalId } from "@mail/utils/common/misc"; +import { assignDefined } from "@mail/utils/common/misc"; import { patch } from "@web/core/utils/patch"; patch(Thread, { insert(data) { - const isUnknown = !(createLocalId(data.model, data.id) in this.records); + const isUnknown = !this.get(data); const thread = super.insert(data); if (thread.type === "livechat") { if (data?.channel) { diff --git a/addons/im_livechat/static/src/embed/core/thread_model_patch.js b/addons/im_livechat/static/src/embed/core/thread_model_patch.js index f31bf185fd8..ced9c32999e 100644 --- a/addons/im_livechat/static/src/embed/core/thread_model_patch.js +++ b/addons/im_livechat/static/src/embed/core/thread_model_patch.js @@ -1,7 +1,7 @@ /* @odoo-module */ import { Thread } from "@mail/core/common/thread_model"; -import { createLocalId, onChange } from "@mail/utils/common/misc"; +import { onChange } from "@mail/utils/common/misc"; import { patch } from "@web/core/utils/patch"; import { session } from "@web/session"; @@ -9,7 +9,7 @@ import { SESSION_STATE } from "./livechat_service"; patch(Thread, { insert(data) { - const isUnknown = !(createLocalId(data.model, data.id) in this.records); + const isUnknown = !this.get(data); const thread = super.insert(...arguments); const livechatService = this.env.services["im_livechat.livechat"]; const chatbotService = this.env.services["im_livechat.chatbot"]; diff --git a/addons/mail/static/src/core/common/attachment_model.js b/addons/mail/static/src/core/common/attachment_model.js index 6c23af992c6..25964f353f2 100644 --- a/addons/mail/static/src/core/common/attachment_model.js +++ b/addons/mail/static/src/core/common/attachment_model.js @@ -7,6 +7,7 @@ import { deserializeDateTime } from "@web/core/l10n/dates"; import { url } from "@web/core/utils/urls"; export class Attachment extends Record { + static id = "id"; /** @type {Object.} */ static records = {}; @@ -18,10 +19,11 @@ export class Attachment extends Record { if (!("id" in data)) { throw new Error("Cannot insert attachment: id is missing in data"); } - let attachment = this.records[data.id]; + let attachment = this.get(data); if (!attachment) { - this.records[data.id] = new Attachment(); - attachment = this.records[data.id]; + attachment = this.new(data); + this.records[attachment.localId] = attachment; + attachment = this.records[attachment.localId]; Object.assign(attachment, { _store: this.store, id: data.id }); } this.env.services["mail.attachment"].update(attachment, data); diff --git a/addons/mail/static/src/core/common/attachment_service.js b/addons/mail/static/src/core/common/attachment_service.js index 73f06033f03..9611b26c421 100644 --- a/addons/mail/static/src/core/common/attachment_service.js +++ b/addons/mail/static/src/core/common/attachment_service.js @@ -1,7 +1,7 @@ /* @odoo-module */ import { removeFromArrayWithPredicate } from "@mail/utils/common/arrays"; -import { assignDefined, createLocalId } from "@mail/utils/common/misc"; +import { assignDefined } from "@mail/utils/common/misc"; import { registry } from "@web/core/registry"; @@ -46,7 +46,7 @@ export class AttachmentService { model: threadData.model, id: threadData.id, }); - attachment.originThreadLocalId = createLocalId(threadData.model, threadData.id); + attachment.originThreadLocalId = this.store.Thread.localId(threadData); const thread = attachment.originThread; if (attachment.notIn(thread.attachments)) { thread.attachments.push(attachment); @@ -64,7 +64,7 @@ export class AttachmentService { if (attachment.tmpUrl) { URL.revokeObjectURL(attachment.tmpUrl); } - delete this.store.Attachment.records[attachment.id]; + delete this.store.Attachment.records[attachment.localId]; if (attachment.originThread) { removeFromArrayWithPredicate(attachment.originThread.attachments, (att) => att.eq(attachment) diff --git a/addons/mail/static/src/core/common/attachment_upload_service.js b/addons/mail/static/src/core/common/attachment_upload_service.js index df7768eb319..4fb09eec865 100644 --- a/addons/mail/static/src/core/common/attachment_upload_service.js +++ b/addons/mail/static/src/core/common/attachment_upload_service.js @@ -1,6 +1,5 @@ /* @odoo-module */ -import { createLocalId } from "@mail/utils/common/misc"; import { _t } from "@web/core/l10n/translation"; import { registry } from "@web/core/registry"; import { Deferred } from "@web/core/utils/concurrency"; @@ -83,8 +82,7 @@ export class AttachmentUploadService { } const threadId = parseInt(upload.data.get("thread_id")); const threadModel = upload.data.get("thread_model"); - const originThread = - this.store.Thread.records[createLocalId(threadModel, threadId)]; + const originThread = this.store.Thread.get({ model: threadModel, id: threadId }); const attachment = this.store.Attachment.insert({ ...response, extension: upload.title.split(".").pop(), @@ -99,7 +97,7 @@ export class AttachmentUploadService { } } const def = this.deferredByAttachmentId.get(tmpId); - this.unlink(this.store.Attachment.records[tmpId]); + this.unlink(this.store.Attachment.get(tmpId)); if (def) { def.resolve(attachment); this.deferredByAttachmentId.delete(tmpId); diff --git a/addons/mail/static/src/core/common/canned_response_model.js b/addons/mail/static/src/core/common/canned_response_model.js index 5c9f858e25e..07cbc1e4456 100644 --- a/addons/mail/static/src/core/common/canned_response_model.js +++ b/addons/mail/static/src/core/common/canned_response_model.js @@ -3,6 +3,7 @@ import { Record } from "@mail/core/common/record"; export class CannedResponse extends Record { + static id = "id"; /** @type {Object.} */ static records = {}; /** @@ -10,10 +11,11 @@ export class CannedResponse extends Record { * @returns {CannedResponse} */ static insert(data) { - let cannedResponse = this.records[data.id]; + let cannedResponse = this.get(data); if (!cannedResponse) { - this.records[data.id] = new CannedResponse(); - cannedResponse = this.records[data.id]; + cannedResponse = this.new(data); + this.records[cannedResponse.localId] = cannedResponse; + cannedResponse = this.records[cannedResponse.localId]; } Object.assign(cannedResponse, { id: data.id, diff --git a/addons/mail/static/src/core/common/channel_member_model.js b/addons/mail/static/src/core/common/channel_member_model.js index 4cddfb0f6cc..1e4532db078 100644 --- a/addons/mail/static/src/core/common/channel_member_model.js +++ b/addons/mail/static/src/core/common/channel_member_model.js @@ -1,7 +1,6 @@ /* @odoo-module */ import { Record } from "@mail/core/common/record"; -import { createLocalId } from "@mail/utils/common/misc"; /** * @class ChannelMember @@ -11,6 +10,7 @@ import { createLocalId } from "@mail/utils/common/misc"; * @property {number} threadId */ export class ChannelMember extends Record { + static id = "id"; /** @type {Object.} */ static records = {}; /** @@ -19,10 +19,11 @@ export class ChannelMember extends Record { */ static insert(data) { const memberData = Array.isArray(data) ? data[1] : data; - let member = this.records[memberData.id]; + let member = this.get(memberData); if (!member) { - this.records[memberData.id] = new ChannelMember(); - member = this.records[memberData.id]; + member = this.new(memberData); + this.records[member.localId] = member; + member = this.records[member.localId]; member._store = this.store; } this.env.services["discuss.channel.member"].update(member, data); @@ -46,11 +47,11 @@ export class ChannelMember extends Record { } get rtcSession() { - return this._store.RtcSession.records[this.rtcSessionId]; + return this._store.RtcSession.get(this.rtcSessionId); } get thread() { - return this._store.Thread.records[createLocalId("discuss.channel", this.threadId)]; + return this._store.Thread.get({ model: "discuss.channel", id: this.threadId }); } /** diff --git a/addons/mail/static/src/core/common/chat_window_model.js b/addons/mail/static/src/core/common/chat_window_model.js index f18eac7b3f8..5b16ede3bac 100644 --- a/addons/mail/static/src/core/common/chat_window_model.js +++ b/addons/mail/static/src/core/common/chat_window_model.js @@ -8,6 +8,7 @@ import { _t } from "@web/core/l10n/translation"; /** @typedef {{ thread?: import("@mail/core/common/thread_model").Thread, folded?: boolean, replaceNewMessageChatWindow?: boolean }} ChatWindowData */ export class ChatWindow extends Record { + static id = "threadLocalId"; /** @type {ChatWindow[]} */ static records = []; /** @@ -17,7 +18,7 @@ export class ChatWindow extends Record { static insert(data = {}) { const chatWindow = this.records.find((c) => c.threadLocalId === data.thread?.localId); if (!chatWindow) { - const chatWindow = new ChatWindow(); + const chatWindow = this.new(data); Object.assign(chatWindow, { thread: data.thread, _store: this.store, diff --git a/addons/mail/static/src/core/common/composer.js b/addons/mail/static/src/core/common/composer.js index f746ea28b9a..8cf6ddd3281 100644 --- a/addons/mail/static/src/core/common/composer.js +++ b/addons/mail/static/src/core/common/composer.js @@ -554,8 +554,9 @@ export class Composer extends Component { * @param {postData} postData Message meta data info */ async _sendMessage(value, postData) { + const thread = this.props.composer.thread; await this.threadService.post(this.thread, value, postData); - if (this.props.composer.thread.type === "mailbox") { + if (thread.type === "mailbox") { this.notifySendFromMailbox(); } this.suggestion?.clearRawMentions(); diff --git a/addons/mail/static/src/core/common/composer_model.js b/addons/mail/static/src/core/common/composer_model.js index 259e681e95e..ab73449bab5 100644 --- a/addons/mail/static/src/core/common/composer_model.js +++ b/addons/mail/static/src/core/common/composer_model.js @@ -1,12 +1,13 @@ /* @odoo-module */ -import { Record } from "@mail/core/common/record"; +import { OR, Record } from "@mail/core/common/record"; /** * @typedef {{partnerIds: Set, threadIds: Set}} RawMentions */ export class Composer extends Record { + static id = OR("threadLocalId", "messageLocalId"); /** * @param {Object} data * @returns {Composer} @@ -18,7 +19,7 @@ export class Composer extends Record { } let composer = (thread ?? message)?.composer; if (!composer) { - composer = new Composer(); + composer = this.new(data); const { message, thread } = data; if (thread) { composer.thread = thread; @@ -51,8 +52,8 @@ export class Composer extends Record { /** @type {import("@mail/core/common/attachment_model").Attachment[]} */ attachments = []; - /** @type {import("@mail/core/common/message_model").Message} */ - message; + /** @type {import("@mail/core/common/message_model").Message.localId} */ + messageLocalId; /** @type {RawMentions} */ rawMentions = { partnerIds: new Set(), @@ -62,8 +63,8 @@ export class Composer extends Record { cannedResponseIds = new Set(); /** @type {string} */ textInputContent; - /** @type {import("@mail/core/common/thread_model").Thread */ - thread; + /** @type {import("@mail/core/common/thread_model").Thread.localId} */ + threadLocalId; /** @type {{ start: number, end: number, direction: "forward" | "backward" | "none"}}*/ selection = { start: 0, @@ -75,6 +76,26 @@ export class Composer extends Record { /** @type {import("@mail/core/common/store_service").Store} */ _store; isFocused = false; + + /** @type {import("@mail/core/common/message_model").Message} */ + get message() { + return this._store.Message.records[this.messageLocalId]; + } + + /** @param {import("@mail/core/common/message_model").Message} */ + set message(newMessage) { + this.messageLocalId = newMessage?.localId; + } + + /** @type {import("@mail/core/common/thread_model").Thread} */ + get thread() { + return this._store.Thread.records[this.threadLocalId]; + } + + /** @param {import("@mail/core/common/thread_model").Thread} */ + set thread(newThread) { + this.threadLocalId = newThread?.localId; + } } Composer.register(); diff --git a/addons/mail/static/src/core/common/follower_model.js b/addons/mail/static/src/core/common/follower_model.js index c38277d3305..fa0c0243f29 100644 --- a/addons/mail/static/src/core/common/follower_model.js +++ b/addons/mail/static/src/core/common/follower_model.js @@ -11,6 +11,7 @@ import { Record } from "@mail/core/common/record"; */ export class Follower extends Record { + static id = "id"; /** @type {Object.} */ static records = {}; /** @@ -18,10 +19,11 @@ export class Follower extends Record { * @returns {Follower} */ static insert(data) { - let follower = this.records[data.id]; + let follower = this.get(data); if (!follower) { - this.records[data.id] = new Follower(); - follower = this.records[data.id]; + follower = this.new(data); + this.records[follower.localId] = follower; + follower = this.records[follower.localId]; } Object.assign(follower, { followedThread: data.followedThread, diff --git a/addons/mail/static/src/core/common/link_preview_model.js b/addons/mail/static/src/core/common/link_preview_model.js index 7cf03e28b70..696810e37df 100644 --- a/addons/mail/static/src/core/common/link_preview_model.js +++ b/addons/mail/static/src/core/common/link_preview_model.js @@ -3,6 +3,7 @@ import { Record } from "@mail/core/common/record"; export class LinkPreview extends Record { + static id = "id"; /** * @param {Object} data * @returns {LinkPreview} @@ -12,9 +13,9 @@ export class LinkPreview extends Record { if (linkPreview) { return Object.assign(linkPreview, data); } - linkPreview = new LinkPreview(); + linkPreview = this.new(data); Object.assign(linkPreview, data); - this.store.Message.records[data.message.id]?.linkPreviews.push(linkPreview); + this.store.Message.get(data.message.id)?.linkPreviews.push(linkPreview); return linkPreview; } diff --git a/addons/mail/static/src/core/common/mail_core_common_service.js b/addons/mail/static/src/core/common/mail_core_common_service.js index 6609961bf52..7551a29e42a 100644 --- a/addons/mail/static/src/core/common/mail_core_common_service.js +++ b/addons/mail/static/src/core/common/mail_core_common_service.js @@ -28,14 +28,14 @@ export class MailCoreCommon { if (messageData) { this.store.Message.insert({ ...messageData }); } - const attachment = this.store.Attachment.records[attachmentId]; + const attachment = this.store.Attachment.get(attachmentId); if (attachment) { this.attachmentService.remove(attachment); } }); this.busService.subscribe("mail.link.preview/delete", (payload) => { const { id, message_id } = payload; - const message = this.store.Message.records[message_id]; + const message = this.store.Message.get(message_id); if (message) { removeFromArrayWithPredicate( message.linkPreviews, @@ -45,11 +45,11 @@ export class MailCoreCommon { }); this.busService.subscribe("mail.message/delete", (payload) => { for (const messageId of payload.message_ids) { - const message = this.store.Message.records[messageId]; + const message = this.store.Message.get(messageId); if (!message) { continue; } - delete this.store.Message.records[messageId]; + delete this.store.Message.records[this.store.Message.localId(messageId)]; if (message.originThread) { removeFromArrayWithPredicate(message.originThread.messages, (msg) => msg.eq(message) @@ -100,14 +100,14 @@ export class MailCoreCommon { const { LinkPreview: linkPreviews } = payload; if (linkPreviews) { for (const linkPreview of linkPreviews) { - this.store.Message.records[linkPreview.message.id]?.linkPreviews.push( + this.store.Message.get(linkPreview.message.id)?.linkPreviews.push( this.store.LinkPreview.insert(linkPreview) ); } } const { Message: messageData } = payload; if (messageData) { - const isStarred = this.store.Message.records[messageData.id]?.isStarred; + const isStarred = this.store.Message.get(messageData.id)?.isStarred; const message = this.store.Message.insert({ ...messageData, body: messageData.body ? markup(messageData.body) : messageData.body, diff --git a/addons/mail/static/src/core/common/message_model.js b/addons/mail/static/src/core/common/message_model.js index a80995b6837..62963c68320 100644 --- a/addons/mail/static/src/core/common/message_model.js +++ b/addons/mail/static/src/core/common/message_model.js @@ -2,7 +2,6 @@ import { Record } from "@mail/core/common/record"; import { htmlToTextContentInline } from "@mail/utils/common/format"; -import { createLocalId } from "@mail/utils/common/misc"; import { toRaw } from "@odoo/owl"; @@ -14,6 +13,7 @@ import { url } from "@web/core/utils/urls"; const { DateTime } = luxon; export class Message extends Record { + static id = "id"; /** @type {Object.} */ static records = {}; /** @@ -28,13 +28,12 @@ export class Message extends Record { id: data.res_id, }); } - if (data.id in this.records) { - message = this.records[data.id]; - } else { - message = new Message(); + message = this.get(data); + if (!message) { + message = this.new(data); message._store = this.store; - this.records[data.id] = message; - message = this.records[data.id]; + this.records[message.localId] = message; + message = this.records[message.localId]; } this.env.services["mail.message"].update(message, data); // return reactive version @@ -196,7 +195,7 @@ export class Message extends Record { } get originThread() { - return this._store.Thread.records[createLocalId(this.resModel, this.resId)]; + return this._store.Thread.get({ model: this.resModel, id: this.resId }); } get resUrl() { diff --git a/addons/mail/static/src/core/common/message_reactions_model.js b/addons/mail/static/src/core/common/message_reactions_model.js index 6374cc386cf..9944108b4bb 100644 --- a/addons/mail/static/src/core/common/message_reactions_model.js +++ b/addons/mail/static/src/core/common/message_reactions_model.js @@ -1,18 +1,19 @@ /* @odoo-module */ -import { Record } from "@mail/core/common/record"; +import { AND, Record } from "@mail/core/common/record"; export class MessageReactions extends Record { + static id = AND("messageId", "content"); /** * @param {Object} data * @returns {MessageReactions} */ static insert(data) { - let reaction = this.store.Message.records[data.message.id]?.reactions.find( + let reaction = this.store.Message.get(data.message.id)?.reactions.find( ({ content }) => content === data.content ); if (!reaction) { - reaction = new MessageReactions(); + reaction = this.new(data); reaction._store = this.store; } const personasToUnlink = new Set(); diff --git a/addons/mail/static/src/core/common/message_service.js b/addons/mail/static/src/core/common/message_service.js index 738418ad20a..ea0db47998b 100644 --- a/addons/mail/static/src/core/common/message_service.js +++ b/addons/mail/static/src/core/common/message_service.js @@ -2,7 +2,7 @@ import { removeFromArrayWithPredicate, replaceArrayWithCompare } from "@mail/utils/common/arrays"; import { convertBrToLineBreak, prettifyMessageContent } from "@mail/utils/common/format"; -import { assignDefined, createLocalId } from "@mail/utils/common/misc"; +import { assignDefined } from "@mail/utils/common/misc"; import { markup } from "@odoo/owl"; @@ -96,7 +96,7 @@ export class MessageService { const rawMentionedPartnerIds = rawMentions.partnerIds || []; const rawMentionedThreadIds = rawMentions.threadIds || []; for (const partnerId of rawMentionedPartnerIds) { - const partner = this.store.Persona.records[createLocalId("partner", partnerId)]; + const partner = this.store.Persona.get({ type: "partner", id: partnerId }); const index = body.indexOf(`@${partner.name}`); if (index === -1) { continue; @@ -104,7 +104,7 @@ export class MessageService { partners.push(partner); } for (const threadId of rawMentionedThreadIds) { - const thread = this.store.Thread.records[createLocalId("discuss.channel", threadId)]; + const thread = this.store.Thread.get({ model: "discuss.channel", id: threadId }); const index = body.indexOf(`#${thread.displayName}`); if (index === -1) { continue; diff --git a/addons/mail/static/src/core/common/notification_group_model.js b/addons/mail/static/src/core/common/notification_group_model.js index 731cc6135e7..716afd79a7c 100644 --- a/addons/mail/static/src/core/common/notification_group_model.js +++ b/addons/mail/static/src/core/common/notification_group_model.js @@ -7,6 +7,7 @@ import { _t } from "@web/core/l10n/translation"; let nextId = 1; export class NotificationGroup extends Record { + static id = "id"; /** @type {NotificationGroup[]} */ static records = []; /** @@ -22,10 +23,10 @@ export class NotificationGroup extends Record { ); }); if (!group) { - group = new NotificationGroup(); - group._store = this.store; + const id = nextId++; + group = this.new({ id }); + Object.assign(group, { id, _store: this.store }); this.store.NotificationGroup.records.push(group); - group.id = nextId++; // return reactive group = this.store.NotificationGroup.records.find((g) => g.eq(group)); } @@ -60,7 +61,7 @@ export class NotificationGroup extends Record { } get lastMessage() { - return this._store.Message.records[this.lastMessageId]; + return this._store.Message.get(this.lastMessageId); } get datetime() { diff --git a/addons/mail/static/src/core/common/notification_model.js b/addons/mail/static/src/core/common/notification_model.js index 954e3448a4d..d2a92d7e744 100644 --- a/addons/mail/static/src/core/common/notification_model.js +++ b/addons/mail/static/src/core/common/notification_model.js @@ -5,6 +5,7 @@ import { Record } from "@mail/core/common/record"; import { _t } from "@web/core/l10n/translation"; export class Notification extends Record { + static id = "id"; /** @type {Object.} */ static records = {}; /** @@ -12,15 +13,15 @@ export class Notification extends Record { * @returns {Notification} */ static insert(data) { - let notification = this.records[data.id]; + let notification = this.get(data); if (!notification) { - notification = new Notification(); - this.records[data.id] = notification; + notification = this.new(data); + this.records[notification.localId] = notification; Object.assign(notification, { id: data.id, _store: this.store, }); - notification = this.records[data.id]; + notification = this.records[notification.localId]; } this.env.services["mail.message"].updateNotification(notification, data); return notification; @@ -42,7 +43,7 @@ export class Notification extends Record { _store; get message() { - return this._store.Message.records[this.messageId]; + return this._store.Message.get(this.messageId); } get isFailure() { diff --git a/addons/mail/static/src/core/common/persona_model.js b/addons/mail/static/src/core/common/persona_model.js index 1e0fc073621..ac791c11685 100644 --- a/addons/mail/static/src/core/common/persona_model.js +++ b/addons/mail/static/src/core/common/persona_model.js @@ -1,7 +1,6 @@ /* @odoo-module */ -import { Record } from "@mail/core/common/record"; -import { createLocalId } from "@mail/utils/common/misc"; +import { AND, Record } from "@mail/core/common/record"; /** * @typedef {'offline' | 'bot' | 'online' | 'away' | 'im_partner' | undefined} ImStatus @@ -14,6 +13,7 @@ import { createLocalId } from "@mail/utils/common/misc"; */ export class Persona extends Record { + static id = AND("type", "id"); /** @type {Object.} */ static records = {}; /** @@ -21,17 +21,16 @@ export class Persona extends Record { * @returns {Persona} */ static insert(data) { - const localId = createLocalId(data.type, data.id); - let persona = this.records[localId]; + let persona = this.get(data); if (!persona) { - persona = new Persona(); + persona = this.new(data); persona._store = this.store; - persona.localId = localId; - this.records[localId] = persona; + this.records[persona.localId] = persona; + persona = this.records[persona.localId]; } this.env.services["mail.persona"].update(persona, data); // return reactive version - return this.records[localId]; + return persona; } /** @type {string} */ diff --git a/addons/mail/static/src/core/common/record.js b/addons/mail/static/src/core/common/record.js index c5189b2859e..01bc2a8b665 100644 --- a/addons/mail/static/src/core/common/record.js +++ b/addons/mail/static/src/core/common/record.js @@ -5,11 +5,71 @@ import { registry } from "@web/core/registry"; export const modelRegistry = registry.category("discuss.model"); +const OR_SYM = Symbol("or"); +const AND_SYM = Symbol("and"); + +export function AND(...args) { + return [AND_SYM, ...args]; +} +export function OR(...args) { + return [OR_SYM, ...args]; +} + export class Record { + static id; static records = {}; + static get(data) { + return this.records[this.localId(data)]; + } + static modelFromLocalId(localId) { + return localId.split(",")[0]; + } static register() { modelRegistry.add(this.name, this); } + static localId(data) { + let idStr; + if (typeof data === "object") { + idStr = this._localId(this.id, data); + } else { + idStr = data; // non-object data => single id + } + return `${this.name},${idStr}`; + } + static _localId(expr, data, { brackets = false } = {}) { + if (!Array.isArray(expr)) { + return data[expr]; + } + const vals = []; + for (let i = 1; i < expr.length; i++) { + vals.push(this._localId(expr[i], data, { brackets: true })); + } + let res = vals.join(expr[0] === OR_SYM ? " OR " : " AND "); + if (brackets) { + res = `(${res})`; + } + return res; + } + /** + * Technical attribute, DO NOT USE in business code. + * This class is almost equivalent to current class of model, + * except this is a function, so we can new() it, whereas + * `this` is not, because it's an object. + * (in order to comply with OWL reactivity) + * + * @type {typeof Record} + */ + static Class; + /** + * This method is almost equivalent to new Class, except that it properly + * setup relational fields of model with get/set, @see Class + * + * @returns {Record} + */ + static new(data) { + const obj = new this.Class(); + return Object.assign(obj, { localId: this.localId(data) }); + } /** * @param {Object} data @@ -29,6 +89,9 @@ export class Record { /** @param {Record[]} list */ in(list) { + if (!list) { + return false; + } return list.some((record) => record.eq(this)); } diff --git a/addons/mail/static/src/core/common/store_service.js b/addons/mail/static/src/core/common/store_service.js index eda06a5e0a7..c6ab8ef2156 100644 --- a/addons/mail/static/src/core/common/store_service.js +++ b/addons/mail/static/src/core/common/store_service.js @@ -187,6 +187,7 @@ export const storeService = { // work-around: make an object whose prototype is the class, so that static props become // instance props. const entry = Object.assign(Object.create(Model), { env, store: res }); + entry.Class = Model; entry.records = JSON.parse(JSON.stringify(Model.records)); res[name] = entry; } diff --git a/addons/mail/static/src/core/common/thread.js b/addons/mail/static/src/core/common/thread.js index 8184c5023ce..6b30b468667 100644 --- a/addons/mail/static/src/core/common/thread.js +++ b/addons/mail/static/src/core/common/thread.js @@ -202,7 +202,7 @@ export class Thread extends Component { const { oeType, oeId } = ev.target.dataset; if (oeType === "highlight") { await this.env.messageHighlight?.highlightMessage( - this.store.Message.records[Number(oeId)], + this.store.Message.get(Number(oeId)), this.props.thread ); } diff --git a/addons/mail/static/src/core/common/thread_icon.js b/addons/mail/static/src/core/common/thread_icon.js index c5723935ed7..a7267c85ba0 100644 --- a/addons/mail/static/src/core/common/thread_icon.js +++ b/addons/mail/static/src/core/common/thread_icon.js @@ -1,7 +1,5 @@ /* @odoo-module */ -import { createLocalId } from "@mail/utils/common/misc"; - import { useService } from "@web/core/utils/hooks"; import { Component, useState } from "@odoo/owl"; @@ -26,8 +24,6 @@ export class ThreadIcon extends Component { } get chatPartner() { - return this.store.Persona.records[ - createLocalId("partner", this.props.thread.chatPartnerId) - ]; + return this.store.Persona.get({ type: "partner", id: this.props.thread.chatPartnerId }); } } diff --git a/addons/mail/static/src/core/common/thread_model.js b/addons/mail/static/src/core/common/thread_model.js index 363a2c64ed6..df7945d45e8 100644 --- a/addons/mail/static/src/core/common/thread_model.js +++ b/addons/mail/static/src/core/common/thread_model.js @@ -1,8 +1,8 @@ /* @odoo-module */ -import { Record } from "@mail/core/common/record"; +import { AND, Record } from "@mail/core/common/record"; import { ScrollPosition } from "@mail/core/common/scroll_position"; -import { createLocalId, onChange } from "@mail/utils/common/misc"; +import { onChange } from "@mail/utils/common/misc"; import { deserializeDateTime } from "@web/core/l10n/dates"; import { _t } from "@web/core/l10n/translation"; @@ -22,8 +22,20 @@ import { Deferred } from "@web/core/utils/concurrency"; */ export class Thread extends Record { + static id = AND("model", "id"); /** @type {Object.} */ static records = {}; + /** + * @param {Thread.localId} localId + * @returns {string} + */ + static localIdToActiveId(localId) { + if (!localId) { + return undefined; + } + // Transform "Thread, AND " to "_"" + return localId.split(",").slice(1).join("_").replace(" AND ", "_"); + } /** * @param {Object} data * @returns {Thread} @@ -35,13 +47,12 @@ export class Thread extends Record { if (!("model" in data)) { throw new Error("Cannot insert thread: model is missing in data"); } - const localId = createLocalId(data.model, data.id); - if (localId in this.records) { - const thread = this.records[localId]; + let thread = this.get(data); + if (thread) { this.env.services["mail.thread"].update(thread, data); return thread; } - let thread = new Thread(); + thread = this.new(data); Object.assign(thread, { id: data.id, model: data.model, @@ -192,7 +203,7 @@ export class Thread extends Record { } get activeRtcSession() { - return this._store.RtcSession.records[this.activeRtcSessionId]; + return this._store.RtcSession.get(this.activeRtcSessionId); } set activeRtcSession(session) { @@ -263,7 +274,7 @@ export class Thread extends Record { if (this.type === "chat" && this.chatPartnerId) { return ( this.customName || - this._store.Persona.records[createLocalId("partner", this.chatPartnerId)] + this._store.Persona.get({ type: "partner", id: this.chatPartnerId }) .nameOrDisplayName ); } @@ -329,10 +340,6 @@ export class Thread extends Record { return null; } - get localId() { - return createLocalId(this.model, this.id); - } - get needactionCounter() { return this.isChatChannel ? this.message_unread_counter : this.message_needaction_counter; } @@ -460,7 +467,7 @@ export class Thread extends Record { } get rtcInvitingSession() { - return this._store.RtcSession.records[this.invitingRtcSessionId]; + return this._store.RtcSession.get(this.invitingRtcSessionId); } get hasNeedactionMessages() { @@ -493,7 +500,7 @@ export class Thread extends Record { if (previousMessages.length === 0) { return false; } - return this._store.Message.records[Math.max(...previousMessages.map((m) => m.id))]; + return this._store.Message.get(Math.max(...previousMessages.map((m) => m.id))); } } diff --git a/addons/mail/static/src/core/common/thread_service.js b/addons/mail/static/src/core/common/thread_service.js index 2303664b8c4..ab561942e13 100644 --- a/addons/mail/static/src/core/common/thread_service.js +++ b/addons/mail/static/src/core/common/thread_service.js @@ -8,7 +8,7 @@ import { replaceArrayWithCompare, } from "@mail/utils/common/arrays"; import { prettifyMessageContent } from "@mail/utils/common/format"; -import { assignDefined, createLocalId, nullifyClearCommands } from "@mail/utils/common/misc"; +import { assignDefined, nullifyClearCommands } from "@mail/utils/common/misc"; import { markup } from "@odoo/owl"; @@ -340,8 +340,7 @@ export class ThreadService { if (ids.length) { const previews = await this.orm.call("discuss.channel", "channel_fetch_preview", [ids]); for (const preview of previews) { - const thread = - this.store.Thread.records[createLocalId("discuss.channel", preview.id)]; + const thread = this.store.Thread.get({ model: "discuss.channel", id: preview.id }); const data = Object.assign(preview.last_message, { body: markup(preview.last_message.body), }); @@ -836,7 +835,7 @@ export class ThreadService { tmpData.guestAuthor = this.store.self; } if (parentId) { - tmpData.parentMessage = this.store.Message.records[parentId]; + tmpData.parentMessage = this.store.Message.get(parentId); } const prettyContent = await prettifyMessageContent(body, params.validMentions); const { emojis } = await loadEmoji(); @@ -865,7 +864,7 @@ export class ThreadService { const data = await this.rpc(this.getMessagePostRoute(thread), params); if (thread.type !== "chatter") { removeFromArrayWithPredicate(thread.messages, (msg) => msg.eq(tmpMsg)); - delete this.store.Message.records[tmpMsg.id]; + delete this.store.Message.records[this.store.Message.localId(tmpMsg.id)]; } if (!data) { return; diff --git a/addons/mail/static/src/core/web/activity_model.js b/addons/mail/static/src/core/web/activity_model.js index 62e7c09bc23..ec2f9d0e3b7 100644 --- a/addons/mail/static/src/core/web/activity_model.js +++ b/addons/mail/static/src/core/web/activity_model.js @@ -34,6 +34,7 @@ import { assignDefined } from "@mail/utils/common/misc"; */ export class Activity extends Record { + static id = "id"; /** @type {Object.} */ static records = {}; @@ -44,16 +45,16 @@ export class Activity extends Record { * @returns {Activity} */ static insert(data, { broadcast = true } = {}) { - let activity = this.records[data.id]; + let activity = this.get(data); if (!activity) { - activity = new Activity(); + activity = this.new(data); Object.assign(activity, { id: data.id, _store: this.store, }); - this.store.Activity.records[data.id] = activity; + this.records[activity.localId] = activity; // return reactive - activity = this.store.Activity.records[data.id]; + activity = this.records[activity.localId]; } if (data.request_partner_id) { data.request_partner_id = data.request_partner_id[0]; diff --git a/addons/mail/static/src/core/web/activity_service.js b/addons/mail/static/src/core/web/activity_service.js index 1cee861c51a..4c72353a497 100644 --- a/addons/mail/static/src/core/web/activity_service.js +++ b/addons/mail/static/src/core/web/activity_service.js @@ -78,7 +78,7 @@ export class ActivityService { } delete(activity, { broadcast = true } = {}) { - delete this.store.Activity.records[activity.id]; + delete this.store.Activity.records[this.store.Activity.localId(activity.id)]; if (broadcast) { this.broadcastChannel?.postMessage({ type: "delete", payload: { id: activity.id } }); } diff --git a/addons/mail/static/src/core/web/discuss_client_action.js b/addons/mail/static/src/core/web/discuss_client_action.js index 5ac0894d256..c2ab5cfc51d 100644 --- a/addons/mail/static/src/core/web/discuss_client_action.js +++ b/addons/mail/static/src/core/web/discuss_client_action.js @@ -6,7 +6,6 @@ import { Component, onWillStart, onWillUpdateProps, useState } from "@odoo/owl"; import { registry } from "@web/core/registry"; import { useService } from "@web/core/utils/hooks"; -import { createLocalId } from "@mail/utils/common/misc"; /** * @typedef {Object} Props @@ -45,7 +44,7 @@ export class DiscussClientAction extends Component { const rawActiveId = props.action.context.active_id ?? props.action.params?.active_id ?? - this.store.discuss.threadLocalId?.replace(",", "_") ?? + this.store.Thread.localIdToActiveId(this.store.discuss.threadLocalId) ?? "mail.box_inbox"; const activeId = typeof rawActiveId === "number" ? `discuss.channel_${rawActiveId}` : rawActiveId; @@ -54,10 +53,10 @@ export class DiscussClientAction extends Component { // legacy format (sent in old emails, shared links, ...) model = "discuss.channel"; } - const activeThreadLocalId = createLocalId(model, id); + const activeThreadLocalId = this.store.Thread.localId({ model, id }); if (activeThreadLocalId !== this.store.discuss.threadLocalId) { const thread = - this.store.Thread.records[createLocalId(model, id)] ?? + this.store.Thread.get({ model, id }) ?? (await this.threadService.fetchChannel(parseInt(id))); if (!thread.is_pinned) { await this.threadService.pin(thread); diff --git a/addons/mail/static/src/core/web/mail_core_web_service.js b/addons/mail/static/src/core/web/mail_core_web_service.js index 598a1aa271d..3ed0116d621 100644 --- a/addons/mail/static/src/core/web/mail_core_web_service.js +++ b/addons/mail/static/src/core/web/mail_core_web_service.js @@ -92,7 +92,7 @@ export class MailCoreWeb { // Furthermore, server should not send back all messageIds marked as read // but something like last read messageId or something like that. // (just imagine you mark 1000 messages as read ... ) - const message = this.store.Message.records[messageId]; + const message = this.store.Message.get(messageId); if (!message) { continue; } diff --git a/addons/mail/static/src/core/web/messaging_menu.js b/addons/mail/static/src/core/web/messaging_menu.js index b135451e731..ee61ce18190 100644 --- a/addons/mail/static/src/core/web/messaging_menu.js +++ b/addons/mail/static/src/core/web/messaging_menu.js @@ -3,7 +3,6 @@ import { ImStatus } from "@mail/core/common/im_status"; import { NotificationItem } from "@mail/core/web/notification_item"; import { onExternalClick } from "@mail/utils/common/hooks"; -import { createLocalId } from "@mail/utils/common/misc"; import { Component, useState } from "@odoo/owl"; @@ -64,10 +63,6 @@ export class MessagingMenu extends Component { } } - createLocalId(...args) { - return createLocalId(...args); - } - /** * @param {'chat' | 'group'} tab * @returns Thread types matching the given tab. diff --git a/addons/mail/static/src/core/web/thread_service_patch.js b/addons/mail/static/src/core/web/thread_service_patch.js index 10ecff6ced0..8168d8adc76 100644 --- a/addons/mail/static/src/core/web/thread_service_patch.js +++ b/addons/mail/static/src/core/web/thread_service_patch.js @@ -2,7 +2,6 @@ import { ThreadService, threadService } from "@mail/core/common/thread_service"; import { parseEmail } from "@mail/js/utils"; -import { createLocalId } from "@mail/utils/common/misc"; import { markup } from "@odoo/owl"; @@ -102,15 +101,15 @@ patch(ThreadService.prototype, { return result; }, getThread(resModel, resId) { - const localId = createLocalId(resModel, resId); - if (localId in this.store.Thread.records) { + let thread = this.store.Thread.get({ model: resModel, id: resId }); + if (thread) { if (resId === false) { - return this.store.Thread.records[localId]; + return thread; } // to force a reload - this.store.Thread.records[localId].status = "new"; + thread.status = "new"; } - const thread = this.store.Thread.insert({ + thread = this.store.Thread.insert({ id: resId, model: resModel, type: "chatter", @@ -215,7 +214,7 @@ patch(ThreadService.prototype, { } else { thread.followers.delete(follower); } - delete this.store.Follower.records[follower.id]; + delete this.store.Follower.records[this.store.Follower.localId(follower.id)]; }, unpin(thread) { const chatWindow = this.store.ChatWindow.records.find( diff --git a/addons/mail/static/src/discuss/call/common/call.js b/addons/mail/static/src/discuss/call/common/call.js index ded249267d4..72f2d4f6f33 100644 --- a/addons/mail/static/src/discuss/call/common/call.js +++ b/addons/mail/static/src/discuss/call/common/call.js @@ -88,7 +88,7 @@ export class Call extends Component { for (const memberId of this.props.thread.invitedMemberIds) { invitationCards.push({ key: "member_" + memberId, - member: this.store.ChannelMember.records[memberId], + member: this.store.ChannelMember.get(memberId), }); } } diff --git a/addons/mail/static/src/discuss/call/common/rtc_service.js b/addons/mail/static/src/discuss/call/common/rtc_service.js index f8cc429580d..6549014f750 100644 --- a/addons/mail/static/src/discuss/call/common/rtc_service.js +++ b/addons/mail/static/src/discuss/call/common/rtc_service.js @@ -3,7 +3,7 @@ import { BlurManager } from "@mail/discuss/call/common/blur_manager"; import { monitorAudio } from "@mail/discuss/call/common/media_monitoring"; import { removeFromArray } from "@mail/utils/common/arrays"; -import { closeStream, createLocalId, onChange } from "@mail/utils/common/misc"; +import { closeStream, onChange } from "@mail/utils/common/misc"; import { reactive } from "@odoo/owl"; @@ -771,7 +771,7 @@ export class Rtc { this.state.logs.clear(); this.state.channel = channel; this.onThreadUpdate(this.state.channel, { rtcSessions, invitedMembers }); - this.state.selfSession = this.store.RtcSession.records[sessionId]; + this.state.selfSession = this.store.RtcSession.get(sessionId); this.state.iceServers = iceServers || DEFAULT_ICE_SERVERS; this.state.logs.set("channelId", this.state.channel?.id); this.state.logs.set("selfSessionId", this.state.selfSession?.id); @@ -1393,16 +1393,16 @@ export class Rtc { * @param {import("@mail/discuss/call/common/rtc_session_model").id} id */ deleteSession(id) { - const session = this.store.RtcSession.records[id]; + const session = this.store.RtcSession.get(id); if (session) { if (this.state.selfSession && session.eq(this.state.selfSession)) { this.endCall(); } - delete this.store.Thread.records[createLocalId("discuss.channel", session.channelId)] + delete this.store.Thread.get({ model: "discuss.channel", id: session.channelId }) ?.rtcSessions[id]; this.disconnect(session); } - delete this.store.RtcSession.records[id]; + delete this.store.RtcSession.records[this.store.RtcSession.localId(id)]; } /** @@ -1464,7 +1464,7 @@ export class Rtc { } updateRtcSessions(channelId, sessionsData, command) { - const channel = this.store.Thread.records[createLocalId("discuss.channel", channelId)]; + const channel = this.store.Thread.get({ model: "discuss.channel", id: channelId }); if (!channel) { return; } diff --git a/addons/mail/static/src/discuss/call/common/rtc_session_model.js b/addons/mail/static/src/discuss/call/common/rtc_session_model.js index 7b58bfd64dc..d8754923653 100644 --- a/addons/mail/static/src/discuss/call/common/rtc_session_model.js +++ b/addons/mail/static/src/discuss/call/common/rtc_session_model.js @@ -1,9 +1,9 @@ /* @odoo-module */ import { Record } from "@mail/core/common/record"; -import { createLocalId } from "@mail/utils/common/misc"; export class RtcSession extends Record { + static id = "id"; /** @type {Object.} */ static records = {}; /** @@ -11,11 +11,9 @@ export class RtcSession extends Record { * @returns {number, RtcSession} */ static insert(data) { - let session; - if (this.records[data.id]) { - session = this.records[data.id]; - } else { - session = new RtcSession(); + let session = this.get(data); + if (!session) { + session = this.new(data); session._store = this.store; } const { channelMember, ...remainingData } = data; @@ -33,9 +31,9 @@ export class RtcSession extends Record { channelMemberRecord.thread.rtcSessions[session.id] = session; } } - this.records[session.id] = session; + this.records[session.localId] = session; // return reactive version - return this.records[session.id]; + return this.records[session.localId]; } // Server data @@ -79,11 +77,11 @@ export class RtcSession extends Record { logStep; get channelMember() { - return this._store.ChannelMember.records[this.channelMemberId]; + return this._store.ChannelMember.get(this.channelMemberId); } get channel() { - return this._store.Thread.records[createLocalId("discuss.channel", this.channelId)]; + return this._store.Thread.get({ model: "discuss.channel", id: this.channelId }); } get isMute() { diff --git a/addons/mail/static/src/discuss/core/common/discuss_core_common_service.js b/addons/mail/static/src/discuss/core/common/discuss_core_common_service.js index 2bb92d0d546..97019173964 100644 --- a/addons/mail/static/src/discuss/core/common/discuss_core_common_service.js +++ b/addons/mail/static/src/discuss/core/common/discuss_core_common_service.js @@ -1,7 +1,6 @@ /* @odoo-module */ import { removeFromArrayWithPredicate } from "@mail/utils/common/arrays"; -import { createLocalId } from "@mail/utils/common/misc"; import { markup, reactive } from "@odoo/owl"; @@ -50,7 +49,7 @@ export class DiscussCoreCommon { }); this.busService.subscribe("discuss.channel/last_interest_dt_changed", (payload) => { const { id, last_interest_dt } = payload; - const channel = this.store.Thread.records[createLocalId("discuss.channel", id)]; + const channel = this.store.Thread.get({ model: "discuss.channel", id }); if (channel) { this.threadService.update(channel, { last_interest_dt }); if (channel.type !== "channel") { @@ -96,8 +95,10 @@ export class DiscussCoreCommon { } }); this.busService.subscribe("discuss.channel/transient_message", (payload) => { - const channel = - this.store.Thread.records[createLocalId("discuss.channel", payload.res_id)]; + const channel = this.store.Thread.get({ + model: "discuss.channel", + id: payload.res_id, + }); const message = this.messageService.createTransient( Object.assign(payload, { body: markup(payload.body) }) ); @@ -105,8 +106,7 @@ export class DiscussCoreCommon { channel.transientMessages.push(message); }); this.busService.subscribe("discuss.channel/unpin", (payload) => { - const thread = - this.store.Thread.records[createLocalId("discuss.channel", payload.id)]; + const thread = this.store.Thread.get({ model: "discuss.channel", id: payload.id }); if (thread) { thread.is_pinned = false; this.notificationService.add( @@ -117,8 +117,7 @@ export class DiscussCoreCommon { }); this.busService.subscribe("discuss.channel.member/fetched", (payload) => { const { channel_id, last_message_id, partner_id } = payload; - const channel = - this.store.Thread.records[createLocalId("discuss.channel", channel_id)]; + const channel = this.store.Thread.get({ model: "discuss.channel", id: channel_id }); if (channel) { const seenInfo = channel.seenInfos.find( (seenInfo) => seenInfo.partner.id === partner_id @@ -130,8 +129,7 @@ export class DiscussCoreCommon { }); this.busService.subscribe("discuss.channel.member/seen", (payload) => { const { channel_id, last_message_id, partner_id } = payload; - const channel = - this.store.Thread.records[createLocalId("discuss.channel", channel_id)]; + const channel = this.store.Thread.get({ model: "discuss.channel", id: channel_id }); if (!channel) { // for example seen from another browser, the current one has no // knowledge of the channel @@ -216,7 +214,7 @@ export class DiscussCoreCommon { async _handleNotificationNewMessage(notif) { const { id, message: messageData } = notif.payload; - let channel = this.store.Thread.records[createLocalId("discuss.channel", id)]; + let channel = this.store.Thread.get({ model: "discuss.channel", id }); if (!channel || !channel.type) { const [channelData] = await this.rpc("/discuss/channel/info", { channel_id: id }); channel = this.store.Thread.insert({ @@ -229,7 +227,7 @@ export class DiscussCoreCommon { this.threadService.pin(channel); } removeFromArrayWithPredicate(channel.messages, ({ id }) => id === messageData.temporary_id); - delete this.store.Message.records[messageData.temporary_id]; + delete this.store.Message.records[this.store.Message.localId(messageData.temporary_id)]; messageData.temporary_id = null; if ("parentMessage" in messageData && messageData.parentMessage.body) { messageData.parentMessage.body = markup(messageData.parentMessage.body); diff --git a/addons/mail/static/src/discuss/core/web/channel_selector.js b/addons/mail/static/src/discuss/core/web/channel_selector.js index f7434c96b6b..f6358cd69e0 100644 --- a/addons/mail/static/src/discuss/core/web/channel_selector.js +++ b/addons/mail/static/src/discuss/core/web/channel_selector.js @@ -2,7 +2,6 @@ import { NavigableList } from "@mail/core/common/navigable_list"; import { cleanTerm } from "@mail/utils/common/format"; -import { createLocalId } from "@mail/utils/common/misc"; import { Component, onMounted, useEffect, useRef, useState } from "@odoo/owl"; @@ -231,7 +230,7 @@ export class ChannelSelector extends Component { get tagsList() { const res = []; for (const partnerId of this.state.selectedPartners) { - const partner = this.store.Persona.records[createLocalId("partner", partnerId)]; + const partner = this.store.Persona.get({ type: "partner", id: partnerId }); res.push({ id: partner.id, text: partner.name, diff --git a/addons/mail/static/src/discuss/core/web/discuss_core_web_service.js b/addons/mail/static/src/discuss/core/web/discuss_core_web_service.js index 87af64b1274..af9a855930c 100644 --- a/addons/mail/static/src/discuss/core/web/discuss_core_web_service.js +++ b/addons/mail/static/src/discuss/core/web/discuss_core_web_service.js @@ -1,6 +1,5 @@ /* @odoo-module */ -import { createLocalId } from "@mail/utils/common/misc"; import { reactive } from "@odoo/owl"; import { _t } from "@web/core/l10n/translation"; @@ -87,7 +86,7 @@ export class DiscussCoreWeb { this.busService.subscribe("mail.record/insert", async (payload) => { if (payload.Thread) { const data = payload.Thread; - const thread = this.store.Thread.records[createLocalId(data.model, data.id)]; + const thread = this.store.Thread.get(data); if (data.serverFoldState && thread && data.serverFoldState !== thread.state) { thread.state = data.serverFoldState; if (thread.state === "closed") { diff --git a/addons/mail/static/src/utils/common/misc.js b/addons/mail/static/src/utils/common/misc.js index 92cdbba480d..f536bc0b39a 100644 --- a/addons/mail/static/src/utils/common/misc.js +++ b/addons/mail/static/src/utils/common/misc.js @@ -2,10 +2,6 @@ import { reactive } from "@odoo/owl"; -export function createLocalId(...args) { - return args.join(","); -} - export function nullifyClearCommands(data) { for (const key in data) { if (!Array.isArray(data[key])) { diff --git a/addons/mail/static/tests/discuss/core/channel_member_list_tests.js b/addons/mail/static/tests/discuss/core/channel_member_list_tests.js index 2f5502c5002..6a02bc5248e 100644 --- a/addons/mail/static/tests/discuss/core/channel_member_list_tests.js +++ b/addons/mail/static/tests/discuss/core/channel_member_list_tests.js @@ -1,6 +1,5 @@ /* @odoo-module */ -import { createLocalId } from "@mail/utils/common/misc"; import { Command } from "@mail/../tests/helpers/command"; import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils"; @@ -174,8 +173,10 @@ QUnit.test("Channel member count update after user left", async (assert) => { }); const { env, openDiscuss } = await start(); openDiscuss(channelId); - const thread = - env.services["mail.store"].Thread.records[createLocalId("discuss.channel", channelId)]; + const thread = env.services["mail.store"].Thread.get({ + model: "discuss.channel", + id: channelId, + }); assert.strictEqual(thread.memberCount, 2); await pyEnv.withUser(userId, () => env.services.orm.call("discuss.channel", "action_unfollow", [channelId]) diff --git a/addons/mail/static/tests/discuss_app/im_status_tests.js b/addons/mail/static/tests/discuss_app/im_status_tests.js index 2cba00149df..88d6ddae50e 100644 --- a/addons/mail/static/tests/discuss_app/im_status_tests.js +++ b/addons/mail/static/tests/discuss_app/im_status_tests.js @@ -2,7 +2,6 @@ import { UPDATE_BUS_PRESENCE_DELAY } from "@bus/im_status_service"; -import { createLocalId } from "@mail/utils/common/misc"; import { Command } from "@mail/../tests/helpers/command"; import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils"; @@ -93,7 +92,7 @@ QUnit.test("Can handle im_status of unknown partner", async (assert) => { Partner: { im_status: "online", id: partnerId }, }); await nextTick(); - const persona = env.services["mail.store"].Persona.records[createLocalId("partner", partnerId)]; + const persona = env.services["mail.store"].Persona.get({ type: "partner", id: partnerId }); assert.ok(persona); assert.ok(persona.im_status === "online"); });