[REF] mail: change shape of store model records

In preparation of code cleaning of models in store.
Entries in store are allocated per model, using the model name.
Records of a model can be accessed from `store[ModelName].records`.

Part-of: odoo/odoo#133202
This commit is contained in:
Alexandre Kühn
2023-08-28 20:14:40 +00:00
parent 821e7b2cc9
commit 5a91d3e5c8
53 changed files with 247 additions and 203 deletions
@@ -31,7 +31,9 @@ patch(Composer.prototype, {
this.thread?.type === "livechat" &&
!this.env.inChatWindow &&
Object.values(this.store.discuss.livechat.threads).some((localId) => {
return localId !== this.thread.localId && this.store.threads[localId].isUnread;
return (
localId !== this.thread.localId && this.store.Thread.records[localId].isUnread
);
})
);
},
@@ -31,7 +31,7 @@ patch(SuggestionService.prototype, {
},
searchCannedResponseSuggestions(cleanedSearchTerm, sort) {
const cannedResponses = this.store.cannedResponses
const cannedResponses = this.store.CannedResponse.records
.filter((cannedResponse) => {
return cleanTerm(cannedResponse.name).includes(cleanedSearchTerm);
})
@@ -8,7 +8,7 @@ import { patch } from "@web/core/utils/patch";
patch(ThreadService.prototype, {
insert(data) {
const isUnknown = !(createLocalId(data.model, data.id) in this.store.threads);
const isUnknown = !(createLocalId(data.model, data.id) in this.store.Thread.records);
const thread = super.insert(data);
if (thread.type === "livechat") {
if (data?.channel) {
@@ -68,8 +68,8 @@ patch(ThreadService.prototype, {
super.sortChannels();
// Live chats are sorted by most recent interest date time in the sidebar.
this.store.discuss.livechat.threads.sort((localId_1, localId_2) => {
const thread1 = this.store.threads[localId_1];
const thread2 = this.store.threads[localId_2];
const thread1 = this.store.Thread.records[localId_1];
const thread2 = this.store.Thread.records[localId_2];
return thread2.lastInterestDateTime?.ts - thread1.lastInterestDateTime?.ts;
});
},
@@ -79,13 +79,13 @@ patch(ThreadService.prototype, {
*/
goToOldestUnreadLivechatThread() {
const oldestUnreadThread =
this.store.threads[
this.store.Thread.records[
Object.values(this.store.discuss.livechat.threads)
.filter((localId) => this.store.threads[localId].isUnread)
.filter((localId) => this.store.Thread.records[localId].isUnread)
.sort(
(localId_1, localId_2) =>
this.store.threads[localId_1].lastInterestDateTime?.ts -
this.store.threads[localId_2].lastInterestDateTime?.ts
this.store.Thread.records[localId_1].lastInterestDateTime?.ts -
this.store.Thread.records[localId_2].lastInterestDateTime?.ts
)[0]
];
if (!oldestUnreadThread) {
@@ -6,7 +6,9 @@ discussSidebarCategoriesRegistry.add(
"livechats",
{
predicate: (store) =>
store.discuss.livechat.threads.some((localId) => store.threads[localId]?.is_pinned),
store.discuss.livechat.threads.some(
(localId) => store.Thread.records[localId]?.is_pinned
),
value: (store) => store.discuss.livechat,
},
{ sequence: 20 }
@@ -58,7 +58,7 @@ export class AutopopupService {
*/
async shouldOpenChatWindow() {
const thread = await this.threadService.getLivechatThread();
return this.storeService.chatWindows.every((cw) => !cw.thread?.eq(thread));
return this.storeService.ChatWindow.records.every((cw) => !cw.thread?.eq(thread));
}
get allowAutoPopup() {
@@ -206,7 +206,7 @@ export class LivechatService {
* @returns {import("@mail/core/common/thread_model").Thread|undefined}
*/
get thread() {
return Object.values(this.store.threads).find(({ type }) => type === "livechat");
return Object.values(this.store.Thread.records).find(({ type }) => type === "livechat");
}
get visitorUid() {
@@ -60,7 +60,9 @@ patch(ThreadService.prototype, {
* @returns {Promise<import("@mail/core/common/message_model").Message}
*/
async post(thread, body, params) {
const chatWindow = this.store.chatWindows.find((c) => c.threadLocalId === thread.localId);
const chatWindow = this.store.ChatWindow.records.find(
(c) => c.threadLocalId === thread.localId
);
if (
this.livechatService.state !== SESSION_STATE.PERSISTED &&
thread.localId === this.livechatService.thread?.localId
@@ -109,7 +111,7 @@ patch(ThreadService.prototype, {
},
insert(data) {
const isUnknown = !(createLocalId(data.model, data.id) in this.store.threads);
const isUnknown = !(createLocalId(data.model, data.id) in this.store.Thread.records);
const thread = super.insert(...arguments);
if (thread.type === "livechat" && isUnknown) {
if (
@@ -36,7 +36,7 @@ export class LivechatButton extends Component {
this.livechatService.available &&
!this.livechatService.shouldRestoreSession &&
this.livechatService.state !== SESSION_STATE.CLOSED &&
this.store.chatWindows.length === 0
this.store.ChatWindow.records.length === 0
);
}
@@ -24,7 +24,7 @@ patch(MessagingMenu.prototype, {
*/
get tabs() {
const items = super.tabs;
const hasLivechats = Object.values(this.store.threads).some(
const hasLivechats = Object.values(this.store.Thread.records).some(
({ type }) => type === "livechat"
);
if (hasLivechats) {
@@ -28,7 +28,7 @@ export class Attachment extends Record {
/** @type {import("@mail/core/common/thread_model").Thread} */
get originThread() {
return this._store.threads[this.originThreadLocalId];
return this._store.Thread.records[this.originThreadLocalId];
}
get isDeletable() {
@@ -25,10 +25,10 @@ export class AttachmentService {
if (!("id" in data)) {
throw new Error("Cannot insert attachment: id is missing in data");
}
let attachment = this.store.attachments[data.id];
let attachment = this.store.Attachment.records[data.id];
if (!attachment) {
this.store.attachments[data.id] = new Attachment();
attachment = this.store.attachments[data.id];
this.store.Attachment.records[data.id] = new Attachment();
attachment = this.store.Attachment.records[data.id];
Object.assign(attachment, { _store: this.store, id: data.id });
}
this.update(attachment, data);
@@ -79,13 +79,13 @@ export class AttachmentService {
if (attachment.tmpUrl) {
URL.revokeObjectURL(attachment.tmpUrl);
}
delete this.store.attachments[attachment.id];
delete this.store.Attachment.records[attachment.id];
if (attachment.originThread) {
removeFromArrayWithPredicate(attachment.originThread.attachments, (att) =>
att.eq(attachment)
);
}
for (const message of Object.values(this.store.messages)) {
for (const message of Object.values(this.store.Message.records)) {
removeFromArrayWithPredicate(message.attachments, (att) => att.eq(attachment));
if (message.composer) {
removeFromArrayWithPredicate(message.composer.attachments, (att) =>
@@ -93,7 +93,7 @@ export class AttachmentService {
);
}
}
for (const thread of Object.values(this.store.threads)) {
for (const thread of Object.values(this.store.Thread.records)) {
removeFromArrayWithPredicate(thread.composer.attachments, (att) => att.eq(attachment));
}
}
@@ -85,7 +85,8 @@ export class AttachmentUploadService {
}
const threadId = parseInt(upload.data.get("thread_id"));
const threadModel = upload.data.get("thread_model");
const originThread = this.store.threads[createLocalId(threadModel, threadId)];
const originThread =
this.store.Thread.records[createLocalId(threadModel, threadId)];
const attachment = this.attachmentService.insert({
...response,
extension: upload.title.split(".").pop(),
@@ -100,7 +101,7 @@ export class AttachmentUploadService {
}
}
const def = this.deferredByAttachmentId.get(tmpId);
this.unlink(this.store.attachments[tmpId]);
this.unlink(this.store.Attachment.records[tmpId]);
if (def) {
def.resolve(attachment);
this.deferredByAttachmentId.delete(tmpId);
@@ -20,7 +20,7 @@ export class ChannelMember extends Record {
_store;
get persona() {
return this._store.personas[this.personaLocalId];
return this._store.Persona.records[this.personaLocalId];
}
set persona(persona) {
@@ -28,11 +28,11 @@ export class ChannelMember extends Record {
}
get rtcSession() {
return this._store.rtcSessions[this.rtcSessionId];
return this._store.RtcSession.records[this.rtcSessionId];
}
get thread() {
return this._store.threads[createLocalId("discuss.channel", this.threadId)];
return this._store.Thread.records[createLocalId("discuss.channel", this.threadId)];
}
/**
@@ -22,10 +22,10 @@ export class ChannelMemberService {
*/
insert(data) {
const memberData = Array.isArray(data) ? data[1] : data;
let member = this.store.channelMembers[memberData.id];
let member = this.store.ChannelMember.records[memberData.id];
if (!member) {
this.store.channelMembers[memberData.id] = new ChannelMember();
member = this.store.channelMembers[memberData.id];
this.store.ChannelMember.records[memberData.id] = new ChannelMember();
member = this.store.ChannelMember.records[memberData.id];
member._store = this.store;
}
this.update(member, data);
@@ -60,7 +60,7 @@ export class ChannelMemberService {
}
break;
case "unlink":
removeFromArray(this.store.channelMembers, member);
removeFromArray(this.store.ChannelMember.records, member);
// eslint-disable-next-line no-fallthrough
case "insert-and-unlink":
if (member.thread) {
@@ -30,7 +30,7 @@ export class ChatWindow extends Record {
}
get thread() {
return this._store.threads[this.threadLocalId];
return this._store.Thread.records[this.threadLocalId];
}
set thread(thread) {
@@ -45,7 +45,7 @@ export class ChatWindowService {
}
openNewMessage() {
if (this.store.chatWindows.some(({ thread }) => !thread)) {
if (this.store.ChatWindow.records.some(({ thread }) => !thread)) {
// New message chat window is already opened.
return;
}
@@ -53,18 +53,18 @@ export class ChatWindowService {
}
closeNewMessage() {
const newMessageChatWindow = this.store.chatWindows.find(({ thread }) => !thread);
const newMessageChatWindow = this.store.ChatWindow.records.find(({ thread }) => !thread);
if (newMessageChatWindow) {
this.close(newMessageChatWindow);
}
}
get visible() {
return this.store.chatWindows.filter((chatWindow) => !chatWindow.hidden);
return this.store.ChatWindow.records.filter((chatWindow) => !chatWindow.hidden);
}
get hidden() {
return this.store.chatWindows.filter((chatWindow) => chatWindow.hidden);
return this.store.ChatWindow.records.filter((chatWindow) => chatWindow.hidden);
}
get maxVisible() {
@@ -87,7 +87,7 @@ export class ChatWindowService {
* @returns {ChatWindow}
*/
insert(data = {}) {
const chatWindow = this.store.chatWindows.find(
const chatWindow = this.store.ChatWindow.records.find(
(c) => c.threadLocalId === data.thread?.localId
);
if (!chatWindow) {
@@ -95,28 +95,28 @@ export class ChatWindowService {
assignDefined(chatWindow, data);
let index;
if (!data.replaceNewMessageChatWindow) {
if (this.maxVisible <= this.store.chatWindows.length) {
if (this.maxVisible <= this.store.ChatWindow.records.length) {
const swaped = this.visible[this.visible.length - 1];
index = this.visible.length - 1;
this.hide(swaped);
} else {
index = this.store.chatWindows.length;
index = this.store.ChatWindow.records.length;
}
} else {
const newMessageChatWindowIndex = this.store.chatWindows.findIndex(
const newMessageChatWindowIndex = this.store.ChatWindow.records.findIndex(
(chatWindow) => !chatWindow.thread
);
index =
newMessageChatWindowIndex !== -1
? newMessageChatWindowIndex
: this.store.chatWindows.length;
: this.store.ChatWindow.records.length;
}
this.store.chatWindows.splice(
this.store.ChatWindow.records.splice(
index,
data.replaceNewMessageChatWindow ? 1 : 0,
chatWindow
);
return this.store.chatWindows[index]; // return reactive version
return this.store.ChatWindow.records[index]; // return reactive version
}
if (chatWindow.hidden) {
this.makeVisible(chatWindow);
@@ -156,21 +156,21 @@ export class ChatWindowService {
}
close(chatWindow, { escape = false } = {}) {
if (!chatWindow.hidden && this.maxVisible < this.store.chatWindows.length) {
if (!chatWindow.hidden && this.maxVisible < this.store.ChatWindow.records.length) {
const swaped = this.hidden[0];
swaped.hidden = false;
swaped.folded = false;
}
const index = this.store.chatWindows.findIndex((c) => c.eq(chatWindow));
const index = this.store.ChatWindow.records.findIndex((c) => c.eq(chatWindow));
if (index > -1) {
this.store.chatWindows.splice(index, 1);
this.store.ChatWindow.records.splice(index, 1);
}
const thread = chatWindow.thread;
if (thread) {
thread.state = "closed";
}
if (escape && this.store.chatWindows.length > 0) {
this.focus(this.store.chatWindows[index - 1]);
if (escape && this.store.ChatWindow.records.length > 0) {
this.focus(this.store.ChatWindow.records[index - 1]);
}
}
}
@@ -85,7 +85,7 @@ export class Discuss extends Component {
}
get thread() {
return this.store.threads[this.store.discuss.threadLocalId];
return this.store.Thread.records[this.store.discuss.threadLocalId];
}
async onFileUploaded(file) {
@@ -31,14 +31,14 @@ export class MailCoreCommon {
if (messageData) {
this.messageService.insert({ ...messageData });
}
const attachment = this.store.attachments[attachmentId];
const attachment = this.store.Attachment.records[attachmentId];
if (attachment) {
this.attachmentService.remove(attachment);
}
});
this.busService.subscribe("mail.link.preview/delete", (payload) => {
const { id, message_id } = payload;
const message = this.store.messages[message_id];
const message = this.store.Message.records[message_id];
if (message) {
removeFromArrayWithPredicate(
message.linkPreviews,
@@ -48,11 +48,11 @@ export class MailCoreCommon {
});
this.busService.subscribe("mail.message/delete", (payload) => {
for (const messageId of payload.message_ids) {
const message = this.store.messages[messageId];
const message = this.store.Message.records[messageId];
if (!message) {
continue;
}
delete this.store.messages[messageId];
delete this.store.Message.records[messageId];
if (message.originThread) {
removeFromArrayWithPredicate(message.originThread.messages, (msg) =>
msg.eq(message)
@@ -103,14 +103,14 @@ export class MailCoreCommon {
const { LinkPreview: linkPreviews } = payload;
if (linkPreviews) {
for (const linkPreview of linkPreviews) {
this.store.messages[linkPreview.message.id]?.linkPreviews.push(
this.store.Message.records[linkPreview.message.id]?.linkPreviews.push(
new LinkPreview(linkPreview)
);
}
}
const { Message: messageData } = payload;
if (messageData) {
const isStarred = this.store.messages[messageData.id]?.isStarred;
const isStarred = this.store.Message.records[messageData.id]?.isStarred;
const message = this.messageService.insert({
...messageData,
body: messageData.body ? markup(messageData.body) : messageData.body,
@@ -169,7 +169,7 @@ export class Message extends Record {
}
get originThread() {
return this._store.threads[createLocalId(this.resModel, this.resId)];
return this._store.Thread.records[createLocalId(this.resModel, this.resId)];
}
get resUrl() {
@@ -16,6 +16,6 @@ export class MessageReactions extends Record {
/** @type {import("@mail/core/common/persona_model").Persona[]} */
get personas() {
return this.personaLocalIds.map((localId) => this._store.personas[localId]);
return this.personaLocalIds.map((localId) => this._store.Persona.records[localId]);
}
}
@@ -82,7 +82,7 @@ export class MessageService {
* @returns {number}
*/
getLastMessageId() {
return Object.values(this.store.messages).reduce(
return Object.values(this.store.Message.records).reduce(
(lastMessageId, message) => Math.max(lastMessageId, message.id),
0
);
@@ -103,7 +103,7 @@ export class MessageService {
const rawMentionedPartnerIds = rawMentions.partnerIds || [];
const rawMentionedThreadIds = rawMentions.threadIds || [];
for (const partnerId of rawMentionedPartnerIds) {
const partner = this.store.personas[createLocalId("partner", partnerId)];
const partner = this.store.Persona.records[createLocalId("partner", partnerId)];
const index = body.indexOf(`@${partner.name}`);
if (index === -1) {
continue;
@@ -111,7 +111,7 @@ export class MessageService {
partners.push(partner);
}
for (const threadId of rawMentionedThreadIds) {
const thread = this.store.threads[createLocalId("discuss.channel", threadId)];
const thread = this.store.Thread.records[createLocalId("discuss.channel", threadId)];
const index = body.indexOf(`#${thread.displayName}`);
if (index === -1) {
continue;
@@ -222,13 +222,13 @@ export class MessageService {
id: data.res_id,
});
}
if (data.id in this.store.messages) {
message = this.store.messages[data.id];
if (data.id in this.store.Message.records) {
message = this.store.Message.records[data.id];
} else {
message = new Message();
message._store = this.store;
this.store.messages[data.id] = message;
message = this.store.messages[data.id];
this.store.Message.records[data.id] = message;
message = this.store.Message.records[data.id];
}
this.update(message, data);
// return reactive version
@@ -389,7 +389,7 @@ export class MessageService {
* @returns {MessageReactions}
*/
insertReactions(data) {
let reaction = this.store.messages[data.message.id]?.reactions.find(
let reaction = this.store.Message.records[data.message.id]?.reactions.find(
({ content }) => content === data.content
);
if (!reaction) {
@@ -434,10 +434,10 @@ export class MessageService {
* @returns {Notification}
*/
insertNotification(data) {
let notification = this.store.notifications[data.id];
let notification = this.store.Notification.records[data.id];
if (!notification) {
this.store.notifications[data.id] = new Notification(this.store, data);
notification = this.store.notifications[data.id];
this.store.Notification.records[data.id] = new Notification(this.store, data);
notification = this.store.Notification.records[data.id];
}
this.updateNotification(notification, data);
return notification;
@@ -474,7 +474,7 @@ export class MessageService {
}
insertNotificationGroups(data) {
let group = this.store.notificationGroups.find((group) => {
let group = this.store.NotificationGroup.records.find((group) => {
return (
group.resModel === data.resModel &&
group.type === data.type &&
@@ -486,7 +486,9 @@ export class MessageService {
}
this.updateNotificationGroup(group, data);
if (group.notifications.length === 0) {
removeFromArrayWithPredicate(this.store.notificationGroups, (gr) => gr.eq(group));
removeFromArrayWithPredicate(this.store.NotificationGroup.records, (gr) =>
gr.eq(group)
);
}
return group;
}
@@ -124,8 +124,8 @@ export class Messaging {
async searchPartners(searchStr = "", limit = 10) {
let partners = [];
const searchTerm = cleanTerm(searchStr);
for (const localId in this.store.personas) {
const persona = this.store.personas[localId];
for (const localId in this.store.Persona.records) {
const persona = this.store.Persona.records[localId];
if (persona.type !== "partner") {
continue;
}
@@ -161,10 +161,10 @@ export class Messaging {
}
insertCannedResponse(data) {
let cannedResponse = this.store.cannedResponses[data.id];
let cannedResponse = this.store.CannedResponse.records[data.id];
if (!cannedResponse) {
this.store.cannedResponses[data.id] = new CannedResponse();
cannedResponse = this.store.cannedResponses[data.id];
this.store.CannedResponse.records[data.id] = new CannedResponse();
cannedResponse = this.store.CannedResponse.records[data.id];
}
Object.assign(cannedResponse, {
id: data.id,
@@ -24,10 +24,10 @@ export class NotificationGroup extends Record {
constructor(store) {
super();
this._store = store;
this._store.notificationGroups.push(this);
this._store.NotificationGroup.records.push(this);
this.id = nextId++;
// return reactive
return store.notificationGroups.find((group) => group.eq(this));
return store.NotificationGroup.records.find((group) => group.eq(this));
}
get iconSrc() {
@@ -39,7 +39,7 @@ export class NotificationGroup extends Record {
}
get lastMessage() {
return this._store.messages[this.lastMessageId];
return this._store.Message.records[this.lastMessageId];
}
get datetime() {
@@ -29,7 +29,7 @@ export class Notification extends Record {
}
get message() {
return this._store.messages[this.messageId];
return this._store.Message.records[this.messageId];
}
get isFailure() {
@@ -36,16 +36,16 @@ export class PersonaService {
*/
insert(data) {
const localId = createLocalId(data.type, data.id);
let persona = this.store.personas[localId];
let persona = this.store.Persona.records[localId];
if (!persona) {
persona = new Persona();
persona._store = this.store;
persona.localId = localId;
this.store.personas[localId] = persona;
this.store.Persona.records[localId] = persona;
}
this.update(persona, data);
// return reactive version
return this.store.personas[localId];
return this.store.Persona.records[localId];
}
update(persona, data) {
@@ -68,7 +68,7 @@ export class PersonaService {
* @returns {[integer]}
*/
getRecentChatPartnerIds() {
return Object.values(this.store.threads)
return Object.values(this.store.Thread.records)
.filter((thread) => thread.type === "chat")
.sort((a, b) => {
if (!a.lastInterestDateTime && !b.lastInterestDateTime) {
@@ -9,6 +9,53 @@ import { registry } from "@web/core/registry";
import { debounce } from "@web/core/utils/timing";
export class Store {
Activity = {
/** @type {Object.<number, import("@mail/core/web/activity_model").Activity>} */
records: {},
};
Attachment = {
/** @type {Object.<number, import("@mail/core/common/attachment_model").Attachment>} */
records: {},
};
CannedResponse = {
records: [],
};
ChannelMember = {
/** @type {Object.<number, import("@mail/core/common/channel_member_model").ChannelMember>} */
records: {},
};
ChatWindow = {
/** @type {import("@mail/core/common/chat_window_model").ChatWindow[]} */
records: [],
};
Follower = {
/** @type {Object.<number, import("@mail/core/common/follower_model").Follower>} */
records: {},
};
Message = {
/** @type {Object.<number, import("@mail/core/common/message_model").Message>} */
records: {},
};
Notification = {
/** @type {Object.<number, import("@mail/core/common/notification_model").Notification>} */
records: {},
};
NotificationGroup = {
records: [],
};
Persona = {
/** @type {Object.<number, import("@mail/core/common/persona_model").Persona>} */
records: {},
};
RtcSession = {
/** @type {Object.<number, import("@mail/discuss/call/common/rtc_session_model").RtcSession>} */
records: {},
};
Thread = {
/** @type {Object.<string, import("@mail/core/common/thread_model").Thread>} */
records: {},
};
/**
* @param {import("@web/env").OdooEnv} env
*/
@@ -28,9 +75,9 @@ export class Store {
updateBusSubscription() {
const channelIds = [];
const ids = Object.keys(this.threads).sort(); // Ensure channels processed in same order.
const ids = Object.keys(this.Thread.records).sort(); // Ensure channels processed in same order.
for (const id of ids) {
const thread = this.threads[id];
const thread = this.Thread.records[id];
if (thread.model === "discuss.channel" && thread.hasSelfAsMember) {
channelIds.push(id);
}
@@ -77,25 +124,11 @@ export class Store {
*/
inPublicPage = false;
/** @type {Object.<number, import("@mail/core/common/channel_member_model").ChannelMember>} */
channelMembers = {};
companyName = "";
/** @type {Object.<number, import("@mail/core/common/notification_model").Notification>} */
notifications = {};
notificationGroups = [];
/** @type {Object.<number, import("@mail/core/common/follower_model").Follower>} */
followers = {};
/** @type {import("@mail/core/common/persona_model").Persona} */
odoobot = null;
odoobotOnboarding;
/** @type {Object.<number, import("@mail/core/common/persona_model").Persona>} */
personas = {};
/** @type {Object.<number, import("@mail/discuss/call/common/rtc_session_model").RtcSession>} */
rtcSessions = {};
users = {};
internalUserGroupId = null;
registeredImStatusPartners = null;
@@ -145,22 +178,8 @@ export class Store {
/** @type {import("@mail/core/common/thread_model").Thread} */
history: null,
};
cannedResponses = [];
/** @type {Object.<number, import("@mail/core/web/activity_model").Activity>} */
activities = {};
activityCounter = 0;
/** @type {Object.<number, import("@mail/core/common/attachment_model").Attachment>} */
attachments = {};
/** @type {import("@mail/core/common/chat_window_model").ChatWindow[]} */
chatWindows = [];
/** @type {Object.<number, import("@mail/core/common/message_model").Message>} */
messages = {};
/** @type {Object.<string, import("@mail/core/common/thread_model").Thread>} */
threads = {};
isMessagingReady = false;
}
@@ -173,12 +192,13 @@ export const storeService = {
*/
start(env, services) {
const res = reactive(new Store(env, services));
onChange(res, "threads", () => res.updateBusSubscription());
onChange(res.Thread, "records", () => res.updateBusSubscription());
services.ui.bus.addEventListener("resize", () => {
if (!services.ui.isSmall) {
res.discuss.activeTab = "all";
} else {
res.discuss.activeTab = res.threads[res.discuss.threadLocalId]?.type ?? "all";
res.discuss.activeTab =
res.Thread.records[res.discuss.threadLocalId]?.type ?? "all";
}
});
return res;
@@ -123,7 +123,7 @@ export class SuggestionService {
.map((member) => member.persona)
.filter((persona) => persona.type === "partner");
} else {
partners = Object.values(this.store.personas).filter(
partners = Object.values(this.store.Persona.records).filter(
(persona) => persona.type === "partner"
);
}
@@ -197,7 +197,7 @@ export class SuggestionService {
// channel.
threads = [thread];
} else {
threads = Object.values(this.store.threads);
threads = Object.values(this.store.Thread.records);
}
const suggestionList = threads.filter(
(thread) =>
+1 -1
View File
@@ -203,7 +203,7 @@ export class Thread extends Component {
const { oeType, oeId } = ev.target.dataset;
if (oeType === "highlight") {
await this.env.messageHighlight?.highlightMessage(
this.store.messages[Number(oeId)],
this.store.Message.records[Number(oeId)],
this.props.thread
);
}
@@ -25,6 +25,8 @@ export class ThreadIcon extends Component {
}
get chatPartner() {
return this.store.personas[createLocalId("partner", this.props.thread.chatPartnerId)];
return this.store.Persona.records[
createLocalId("partner", this.props.thread.chatPartnerId)
];
}
}
@@ -143,8 +143,8 @@ export class Thread extends Record {
type: data.type,
_store: store,
});
store.threads[this.localId] = this;
return store.threads[this.localId];
store.Thread.records[this.localId] = this;
return store.Thread.records[this.localId];
}
get accessRestrictedToGroupText() {
@@ -157,7 +157,7 @@ export class Thread extends Record {
}
get activeRtcSession() {
return this._store.rtcSessions[this.activeRtcSessionId];
return this._store.RtcSession.records[this.activeRtcSessionId];
}
set activeRtcSession(session) {
@@ -224,7 +224,8 @@ export class Thread extends Record {
if (this.type === "chat" && this.chatPartnerId) {
return (
this.customName ||
this._store.personas[createLocalId("partner", this.chatPartnerId)].nameOrDisplayName
this._store.Persona.records[createLocalId("partner", this.chatPartnerId)]
.nameOrDisplayName
);
}
if (this.type === "group" && !this.name) {
@@ -420,7 +421,7 @@ export class Thread extends Record {
}
get rtcInvitingSession() {
return this._store.rtcSessions[this.invitingRtcSessionId];
return this._store.RtcSession.records[this.invitingRtcSessionId];
}
get hasNeedactionMessages() {
@@ -428,7 +429,9 @@ export class Thread extends Record {
}
get videoCount() {
return Object.values(this.rtcSessions).filter((session) => session.videoStream).length;
return Object.values(this._store.RtcSession.records).filter(
(session) => session.videoStream
).length;
}
get lastInterestDateTime() {
@@ -451,6 +454,6 @@ export class Thread extends Record {
if (previousMessages.length === 0) {
return false;
}
return this._store.messages[Math.max(...previousMessages.map((m) => m.id))];
return this._store.Message.records[Math.max(...previousMessages.map((m) => m.id))];
}
}
@@ -348,7 +348,7 @@ export class ThreadService {
// This function is like fetchNewMessages but just for a single message at most on all pinned threads
fetchPreviews = memoize(async () => {
const ids = [];
for (const thread of Object.values(this.store.threads)) {
for (const thread of Object.values(this.store.Thread.records)) {
if (["channel", "group", "chat"].includes(thread.type)) {
ids.push(thread.id);
}
@@ -356,7 +356,8 @@ 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.threads[createLocalId("discuss.channel", preview.id)];
const thread =
this.store.Thread.records[createLocalId("discuss.channel", preview.id)];
const data = Object.assign(preview.last_message, {
body: markup(preview.last_message.body),
});
@@ -456,13 +457,13 @@ export class ThreadService {
sortChannels() {
this.store.discuss.channels.threads.sort((id1, id2) => {
const thread1 = this.store.threads[id1];
const thread2 = this.store.threads[id2];
const thread1 = this.store.Thread.records[id1];
const thread2 = this.store.Thread.records[id2];
return String.prototype.localeCompare.call(thread1.name, thread2.name);
});
this.store.discuss.chats.threads.sort((localId_1, localId_2) => {
const thread1 = this.store.threads[localId_1];
const thread2 = this.store.threads[localId_2];
const thread1 = this.store.Thread.records[localId_1];
const thread2 = this.store.Thread.records[localId_2];
return thread2.lastInterestDateTime.ts - thread1.lastInterestDateTime.ts;
});
}
@@ -547,7 +548,7 @@ export class ThreadService {
if (!partner) {
return;
}
return Object.values(this.store.threads).find(
return Object.values(this.store.Thread.records).find(
(thread) => thread.type === "chat" && thread.chatPartnerId === partner.id
);
}
@@ -649,7 +650,7 @@ export class ThreadService {
this.remove(channel);
this.setDiscussThread(
this.store.discuss.channels.threads[0]
? this.store.threads[this.store.discuss.channels.threads[0]]
? this.store.Thread.records[this.store.discuss.channels.threads[0]]
: this.store.discuss.inbox
);
}
@@ -679,7 +680,7 @@ export class ThreadService {
remove(thread) {
removeFromArray(this.store.discuss.chats.threads, thread.localId);
removeFromArray(this.store.discuss.channels.threads, thread.localId);
delete this.store.threads[thread.localId];
delete this.store.Thread.records[thread.localId];
}
/**
@@ -823,8 +824,8 @@ export class ThreadService {
throw new Error("Cannot insert thread: model is missing in data");
}
const localId = createLocalId(data.model, data.id);
if (localId in this.store.threads) {
const thread = this.store.threads[localId];
if (localId in this.store.Thread.records) {
const thread = this.store.Thread.records[localId];
this.update(thread, data);
return thread;
}
@@ -844,7 +845,7 @@ export class ThreadService {
this.update(thread, data);
this.insertComposer({ thread });
// return reactive version.
return this.store.threads[thread.localId];
return this.store.Thread.records[thread.localId];
}
/**
@@ -916,7 +917,7 @@ export class ThreadService {
tmpData.guestAuthor = this.store.self;
}
if (parentId) {
tmpData.parentMessage = this.store.messages[parentId];
tmpData.parentMessage = this.store.Message.records[parentId];
}
const prettyContent = await prettifyMessageContent(body, params.validMentions);
const { emojis } = await loadEmoji();
@@ -945,7 +946,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.messages[tmpMsg.id];
delete this.store.Message.records[tmpMsg.id];
}
if (!data) {
return;
@@ -955,7 +956,7 @@ export class ThreadService {
? markup(data.parentMessage.body)
: data.parentMessage.body;
}
if (data.id in this.store.messages) {
if (data.id in this.store.Message.records) {
data.temporary_id = null;
}
const message = this.messageService.insert(
@@ -1055,7 +1056,7 @@ export class ThreadService {
getDiscussSidebarCategoryCounter(categoryId) {
return this.store.discuss[categoryId].threads.reduce((acc, threadLocalId) => {
const channel = this.store.threads[threadLocalId];
const channel = this.store.Thread.records[threadLocalId];
if (categoryId === "channels") {
return channel.message_needaction_counter > 0 ? acc + 1 : acc;
} else {
@@ -41,7 +41,7 @@ export class ActivityListPopover extends Component {
get activities() {
/** @type {import("@mail/core/web/activity_model").Activity[]} */
const allActivities = Object.values(this.store.activities);
const allActivities = Object.values(this.store.Activity.records);
return allActivities
.filter((activity) => this.props.activityIds.includes(activity.id))
.sort(function (a, b) {
@@ -101,7 +101,7 @@ export class Activity extends Record {
id,
_store: store,
});
store.activities[id] = this;
return store.activities[id];
store.Activity.records[id] = this;
return store.Activity.records[id];
}
}
@@ -87,7 +87,7 @@ export class ActivityService {
* @returns {import("@mail/core/web/activity_model").Activity}
*/
insert(data, { broadcast = true } = {}) {
const activity = this.store.activities[data.id] ?? new Activity(this.store, data.id);
const activity = this.store.Activity.records[data.id] ?? new Activity(this.store, data.id);
if (data.request_partner_id) {
data.request_partner_id = data.request_partner_id[0];
}
@@ -102,7 +102,7 @@ export class ActivityService {
}
delete(activity, { broadcast = true } = {}) {
delete this.store.activities[activity.id];
delete this.store.Activity.records[activity.id];
if (broadcast) {
this.broadcastChannel?.postMessage({ type: "delete", payload: { id: activity.id } });
}
@@ -58,7 +58,7 @@ export class DiscussClientAction extends Component {
const activeThreadLocalId = createLocalId(model, id);
if (activeThreadLocalId !== this.store.discuss.threadLocalId) {
const thread =
this.store.threads[createLocalId(model, id)] ??
this.store.Thread.records[createLocalId(model, id)] ??
(await this.threadService.fetchChannel(parseInt(id)));
if (!thread.is_pinned) {
await this.threadService.pin(thread);
@@ -33,7 +33,7 @@ export class MailCoreWeb {
author: this.store.user,
})
);
this.store.notificationGroups.sort(
this.store.NotificationGroup.records.sort(
(n1, n2) => n2.lastMessage.id - n1.lastMessage.id
);
});
@@ -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.messages[messageId];
const message = this.store.Message.records[messageId];
if (!message) {
continue;
}
@@ -81,7 +81,8 @@ export class MessagingMenu extends Component {
get hasPreviews() {
return (
this.threads.length > 0 ||
(this.store.notificationGroups.length > 0 && this.store.discuss.activeTab === "all") ||
(this.store.NotificationGroup.records.length > 0 &&
this.store.discuss.activeTab === "all") ||
(this.notification.permission === "prompt" && this.store.discuss.activeTab === "all")
);
}
@@ -92,7 +93,7 @@ export class MessagingMenu extends Component {
displayName: _t("%s has a request", this.store.odoobot.name),
iconSrc: this.threadService.avatarUrl(this.store.odoobot),
partner: this.store.odoobot,
isLast: this.threads.length === 0 && this.store.notificationGroups.length === 0,
isLast: this.threads.length === 0 && this.store.NotificationGroup.records.length === 0,
isShown:
this.store.discuss.activeTab === "all" && this.notification.permission === "prompt",
};
@@ -100,7 +101,7 @@ export class MessagingMenu extends Component {
get threads() {
/** @type {import("@mail/core/common/thread_model").Thread[]} */
let threads = Object.values(this.store.threads).filter(
let threads = Object.values(this.store.Thread.records).filter(
(thread) =>
thread.is_pinned || (thread.hasNeedactionMessages && thread.type !== "mailbox")
);
@@ -239,7 +240,7 @@ export class MessagingMenu extends Component {
});
// Close the related chat window as having both the form view
// and the chat window does not look good.
this.store.chatWindows.find(({ thr }) => thr?.eq(thread))?.close();
this.store.ChatWindow.records.find(({ thr }) => thr?.eq(thread))?.close();
} else {
this.threadService.open(thread);
}
@@ -286,10 +287,10 @@ export class MessagingMenu extends Component {
if (
this.store.discuss.activeTab === "mailbox" &&
(!this.store.discuss.threadLocalId ||
this.store.threads[this.store.discuss.threadLocalId].type !== "mailbox")
this.store.Thread.records[this.store.discuss.threadLocalId].type !== "mailbox")
) {
this.threadService.setDiscussThread(
Object.values(this.store.threads).find((thread) => thread.id === "inbox")
Object.values(this.store.Thread.records).find((thread) => thread.id === "inbox")
);
}
if (this.store.discuss.activeTab !== "mailbox") {
@@ -300,10 +301,10 @@ export class MessagingMenu extends Component {
get counter() {
let value =
this.store.discuss.inbox.counter +
Object.values(this.store.threads).filter(
Object.values(this.store.Thread.records).filter(
(thread) => thread.is_pinned && thread.message_unread_counter > 0
).length +
Object.values(this.store.notificationGroups).reduce(
Object.values(this.store.NotificationGroup.records).reduce(
(acc, ng) => acc + parseInt(Object.values(ng.notifications).length),
0
);
@@ -15,7 +15,7 @@
</t>
<t t-name="mail.MessagingMenu.content">
<t t-set="failures" t-value="store.notificationGroups"/>
<t t-set="failures" t-value="store.NotificationGroup.records"/>
<div class="o-mail-MessagingMenu d-flex flex-column flex-grow-1" t-att-class="{ 'overflow-auto w-100 mh-100': ui.isSmall }">
<div class="o-mail-MessagingMenu-header" t-att-class="{'flex-row-reverse text-uppercase': ui.isSmall, 'border-bottom d-flex flex-shrink-0 p-2': !env.inDiscussApp }">
<t t-if="!ui.isSmall">
@@ -9,7 +9,7 @@ patch(Thread.prototype, {
* @returns {import("@mail/core/web/activity_model").Activity[]}
*/
get activities() {
return Object.values(this._store.activities)
return Object.values(this._store.Activity.records)
.filter((activity) => {
return activity.res_model === this.model && activity.res_id === this.id;
})
@@ -105,12 +105,12 @@ patch(ThreadService.prototype, {
},
getThread(resModel, resId) {
const localId = createLocalId(resModel, resId);
if (localId in this.store.threads) {
if (localId in this.store.Thread.records) {
if (resId === false) {
return this.store.threads[localId];
return this.store.Thread.records[localId];
}
// to force a reload
this.store.threads[localId].status = "new";
this.store.Thread.records[localId].status = "new";
}
const thread = this.insert({
id: resId,
@@ -138,10 +138,10 @@ patch(ThreadService.prototype, {
* @returns {import("@mail/core/common/follower_model").Follower}
*/
insertFollower(data) {
let follower = this.store.followers[data.id];
let follower = this.store.Follower.records[data.id];
if (!follower) {
this.store.followers[data.id] = new Follower();
follower = this.store.followers[data.id];
this.store.Follower.records[data.id] = new Follower();
follower = this.store.Follower.records[data.id];
}
Object.assign(follower, {
followedThread: data.followedThread,
@@ -179,7 +179,9 @@ patch(ThreadService.prototype, {
thread.suggestedRecipients = recipients;
},
async leaveChannel(channel) {
const chatWindow = this.store.chatWindows.find((c) => c.threadLocalId === channel.localId);
const chatWindow = this.store.ChatWindow.records.find(
(c) => c.threadLocalId === channel.localId
);
if (chatWindow) {
this.chatWindowService.close(chatWindow);
}
@@ -234,10 +236,12 @@ patch(ThreadService.prototype, {
} else {
thread.followers.delete(follower);
}
delete this.store.followers[follower.id];
delete this.store.Follower.records[follower.id];
},
unpin(thread) {
const chatWindow = this.store.chatWindows.find((c) => c.threadLocalId === thread.localId);
const chatWindow = this.store.ChatWindow.records.find(
(c) => c.threadLocalId === thread.localId
);
if (chatWindow) {
this.chatWindowService.close(chatWindow);
}
@@ -256,7 +260,7 @@ patch(ThreadService.prototype, {
this.chatWindowService.notifyState(chatWindow);
},
getRecentChannels() {
return Object.values(this.store.threads)
return Object.values(this.store.Thread.records)
.filter((thread) => thread.model === "discuss.channel")
.sort((a, b) => {
if (!a.lastInterestDateTime && !b.lastInterestDateTime) {
@@ -91,7 +91,7 @@ export class Call extends Component {
for (const memberId of this.props.thread.invitedMemberIds) {
invitationCards.push({
key: "member_" + memberId,
member: this.store.channelMembers[memberId],
member: this.store.ChannelMember.records[memberId],
});
}
}
@@ -5,7 +5,7 @@
<div class="o-discuss-CallInvitations position-absolute top-0 end-0 d-flex flex-column p-2">
<t t-if="rtc.ringingThreads">
<t t-foreach="rtc.ringingThreads" t-as="threadLocalId" t-key="threadLocalId">
<t t-set="thread" t-value="store.threads[threadLocalId]"/>
<t t-set="thread" t-value="store.Thread.records[threadLocalId]"/>
<CallInvitation t-if="thread" thread="thread"/>
</t>
</t>
@@ -782,7 +782,7 @@ export class Rtc {
this.state.logs.clear();
this.state.channel = channel;
this.onThreadUpdate(this.state.channel, { rtcSessions, invitedMembers });
this.state.selfSession = this.store.rtcSessions[sessionId];
this.state.selfSession = this.store.RtcSession.records[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);
@@ -1004,7 +1004,7 @@ export class Rtc {
}
clear() {
for (const session of Object.values(this.store.rtcSessions)) {
for (const session of Object.values(this.store.RtcSession.records)) {
this.disconnect(session);
}
for (const timeoutId of this.state.recoverTimeouts.values()) {
@@ -1406,8 +1406,8 @@ export class Rtc {
*/
insertSession(data) {
let session;
if (this.store.rtcSessions[data.id]) {
session = this.store.rtcSessions[data.id];
if (this.store.RtcSession.records[data.id]) {
session = this.store.RtcSession.records[data.id];
} else {
session = new RtcSession();
session._store = this.store;
@@ -1427,25 +1427,25 @@ export class Rtc {
channelMemberRecord.thread.rtcSessions[session.id] = session;
}
}
this.store.rtcSessions[session.id] = session;
this.store.RtcSession.records[session.id] = session;
// return reactive version
return this.store.rtcSessions[session.id];
return this.store.RtcSession.records[session.id];
}
/**
* @param {import("@mail/discuss/call/common/rtc_session_model").id} id
*/
deleteSession(id) {
const session = this.store.rtcSessions[id];
const session = this.store.RtcSession.records[id];
if (session) {
if (this.state.selfSession && session.eq(this.state.selfSession)) {
this.endCall();
}
delete this.store.threads[createLocalId("discuss.channel", session.channelId)]
delete this.store.Thread.records[createLocalId("discuss.channel", session.channelId)]
?.rtcSessions[id];
this.disconnect(session);
}
delete this.store.rtcSessions[id];
delete this.store.RtcSession.records[id];
}
/**
@@ -1507,7 +1507,7 @@ export class Rtc {
}
updateRtcSessions(channelId, sessionsData, command) {
const channel = this.store.threads[createLocalId("discuss.channel", channelId)];
const channel = this.store.Thread.records[createLocalId("discuss.channel", channelId)];
if (!channel) {
return;
}
@@ -45,11 +45,11 @@ export class RtcSession extends Record {
logStep;
get channelMember() {
return this._store.channelMembers[this.channelMemberId];
return this._store.ChannelMember.records[this.channelMemberId];
}
get channel() {
return this._store.threads[createLocalId("discuss.channel", this.channelId)];
return this._store.Thread.records[createLocalId("discuss.channel", this.channelId)];
}
get isMute() {
@@ -133,7 +133,7 @@ export class ChannelInvitation extends Component {
return _t("Invite");
}
if (this.state.selectedPartners.length === 1) {
const alreadyChat = Object.values(this.store.threads).some(
const alreadyChat = Object.values(this.store.Thread.records).some(
(thread) => thread.chatPartnerId === this.state.selectedPartners[0].id
);
if (alreadyChat) {
@@ -51,7 +51,7 @@ export class DiscussCoreCommon {
});
this.busService.subscribe("discuss.channel/last_interest_dt_changed", (payload) => {
const { id, last_interest_dt } = payload;
const channel = this.store.threads[createLocalId("discuss.channel", id)];
const channel = this.store.Thread.records[createLocalId("discuss.channel", id)];
if (channel) {
this.threadService.update(channel, { last_interest_dt });
if (channel.type !== "channel") {
@@ -98,7 +98,7 @@ export class DiscussCoreCommon {
});
this.busService.subscribe("discuss.channel/transient_message", (payload) => {
const channel =
this.store.threads[createLocalId("discuss.channel", payload.res_id)];
this.store.Thread.records[createLocalId("discuss.channel", payload.res_id)];
const message = this.messageService.createTransient(
Object.assign(payload, { body: markup(payload.body) })
);
@@ -106,7 +106,8 @@ export class DiscussCoreCommon {
channel.transientMessages.push(message);
});
this.busService.subscribe("discuss.channel/unpin", (payload) => {
const thread = this.store.threads[createLocalId("discuss.channel", payload.id)];
const thread =
this.store.Thread.records[createLocalId("discuss.channel", payload.id)];
if (thread) {
thread.is_pinned = false;
this.notificationService.add(
@@ -117,7 +118,8 @@ export class DiscussCoreCommon {
});
this.busService.subscribe("discuss.channel.member/fetched", (payload) => {
const { channel_id, last_message_id, partner_id } = payload;
const channel = this.store.threads[createLocalId("discuss.channel", channel_id)];
const channel =
this.store.Thread.records[createLocalId("discuss.channel", channel_id)];
if (channel) {
const seenInfo = channel.seenInfos.find(
(seenInfo) => seenInfo.partner.id === partner_id
@@ -129,7 +131,8 @@ export class DiscussCoreCommon {
});
this.busService.subscribe("discuss.channel.member/seen", (payload) => {
const { channel_id, last_message_id, partner_id } = payload;
const channel = this.store.threads[createLocalId("discuss.channel", channel_id)];
const channel =
this.store.Thread.records[createLocalId("discuss.channel", channel_id)];
if (!channel) {
// for example seen from another browser, the current one has no
// knowledge of the channel
@@ -214,7 +217,7 @@ export class DiscussCoreCommon {
async _handleNotificationNewMessage(notif) {
const { id, message: messageData } = notif.payload;
let channel = this.store.threads[createLocalId("discuss.channel", id)];
let channel = this.store.Thread.records[createLocalId("discuss.channel", id)];
if (!channel || !channel.type) {
const [channelData] = await this.rpc("/discuss/channel/info", { channel_id: id });
channel = this.threadService.insert({
@@ -227,7 +230,7 @@ export class DiscussCoreCommon {
this.threadService.pin(channel);
}
removeFromArrayWithPredicate(channel.messages, ({ id }) => id === messageData.temporary_id);
delete this.store.messages[messageData.temporary_id];
delete this.store.Message.records[messageData.temporary_id];
messageData.temporary_id = null;
if ("parentMessage" in messageData && messageData.parentMessage.body) {
messageData.parentMessage.body = markup(messageData.parentMessage.body);
@@ -234,7 +234,7 @@ export class ChannelSelector extends Component {
get tagsList() {
const res = [];
for (const partnerId of this.state.selectedPartners) {
const partner = this.store.personas[createLocalId("partner", partnerId)];
const partner = this.store.Persona.records[createLocalId("partner", partnerId)];
res.push({
id: partner.id,
text: partner.name,
@@ -87,11 +87,11 @@ export class DiscussCoreWeb {
this.busService.subscribe("mail.record/insert", async (payload) => {
if (payload.Thread) {
const data = payload.Thread;
const thread = this.store.threads[createLocalId(data.model, data.id)];
const thread = this.store.Thread.records[createLocalId(data.model, data.id)];
if (data.serverFoldState && thread && data.serverFoldState !== thread.state) {
thread.state = data.serverFoldState;
if (thread.state === "closed") {
const chatWindow = this.store.chatWindows.find(
const chatWindow = this.store.ChatWindow.records.find(
(chatWindow) => chatWindow.threadLocalId === thread.localId
);
if (chatWindow) {
@@ -82,7 +82,7 @@ export class DiscussSidebarCategories extends Component {
filteredThreads(category) {
return category.threads.filter((threadLocalId) => {
const thread = this.store.threads[threadLocalId];
const thread = this.store.Thread.records[threadLocalId];
return (
(thread.is_pinned || thread.group_based_subscription) &&
(!this.state.quickSearchVal || thread.name.includes(this.state.quickSearchVal))
@@ -92,7 +92,7 @@ export class DiscussSidebarCategories extends Component {
get hasQuickSearch() {
return (
Object.values(this.store.threads).filter(
Object.values(this.store.Thread.records).filter(
(thread) => thread.is_pinned && thread.model === "discuss.channel"
).length > 19
);
@@ -31,12 +31,12 @@
<ChannelSelector category="category" onValidate.bind="stopEditing" autofocus="true"/>
</div>
<t t-foreach="filteredThreads(category)" t-as="threadLocalId" t-key="threadLocalId" t-call="mail.DiscussSidebarChannel">
<t t-set="thread" t-value="store.threads[threadLocalId]"/>
<t t-set="thread" t-value="store.Thread.records[threadLocalId]"/>
</t>
</t>
<t t-elif="category.threads.includes(store.discuss.threadLocalId)" t-call="mail.DiscussSidebarChannel">
<t t-set="threadLocalId" t-value="store.discuss.threadLocalId"/>
<t t-set="thread" t-value="store.threads[threadLocalId]"/>
<t t-set="thread" t-value="store.Thread.records[threadLocalId]"/>
</t>
</t>
@@ -174,7 +174,8 @@ QUnit.test("Channel member count update after user left", async (assert) => {
});
const { env, openDiscuss } = await start();
openDiscuss(channelId);
const thread = env.services["mail.store"].threads[createLocalId("discuss.channel", channelId)];
const thread =
env.services["mail.store"].Thread.records[createLocalId("discuss.channel", channelId)];
assert.strictEqual(thread.memberCount, 2);
await pyEnv.withUser(userId, () =>
env.services.orm.call("discuss.channel", "action_unfollow", [channelId])
@@ -93,7 +93,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"].personas[createLocalId("partner", partnerId)];
const persona = env.services["mail.store"].Persona.records[createLocalId("partner", partnerId)];
assert.ok(persona);
assert.ok(persona.im_status === "online");
});
@@ -112,7 +112,7 @@ 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];
const thread = store.Thread.records[store.discuss.threadLocalId];
if (thread.isLoaded) {
messagesLoadedPromise.resolve();
}