[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:
@@ -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) =>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user