[FIX] mail: process result of init messaging asynchronously

Part of task-2308312

closes odoo/odoo#55562

X-original-commit: bdc2a9f516562c854837248e7d0898e5cfc8dec1
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
This commit is contained in:
Sébastien Theys
2020-08-06 13:27:38 +00:00
parent 7b51aaa1ca
commit bab2093109
4 changed files with 49 additions and 30 deletions
@@ -13,10 +13,13 @@ registerInstancePatchModel('mail.messaging_initializer', 'im_livechat/static/src
* @override
* @param {Object[]} [param0.channel_livechat=[]]
*/
_initChannels(initMessagingData) {
this._super(initMessagingData);
async _initChannels(initMessagingData) {
await this.async(() => this._super(initMessagingData));
const { channel_livechat = [] } = initMessagingData;
for (const data of channel_livechat) {
// there might be a lot of channels, insert each of them one by
// one asynchronously to avoid blocking the UI
await this.async(() => new Promise(resolve => setTimeout(resolve)));
this.env.models['mail.thread'].insert(
this.env.models['mail.thread'].convertData(data),
);
@@ -3,17 +3,19 @@
<t t-name="mail.ChatWindowManager" owl="1">
<div class="o_ChatWindowManager">
<!-- Note: DOM elements are ordered from left to right -->
<t t-if="env.messaging.chatWindowManager.hasHiddenChatWindows">
<ChatWindowHiddenMenu class="o_ChatWindowManager_hiddenMenu"/>
</t>
<t t-foreach="env.messaging.chatWindowManager.allOrderedVisible" t-as="chatWindow" t-key="chatWindow.localId">
<ChatWindow
chatWindowLocalId="chatWindow.localId"
hasCloseAsBackButton="env.messaging.device.isMobile"
isExpandable="!env.messaging.device.isMobile and !!chatWindow.thread"
isFullscreen="env.messaging.device.isMobile"
/>
<t t-if="env.messaging.isInitialized">
<!-- Note: DOM elements are ordered from left to right -->
<t t-if="env.messaging.chatWindowManager.hasHiddenChatWindows">
<ChatWindowHiddenMenu class="o_ChatWindowManager_hiddenMenu"/>
</t>
<t t-foreach="env.messaging.chatWindowManager.allOrderedVisible" t-as="chatWindow" t-key="chatWindow.localId">
<ChatWindow
chatWindowLocalId="chatWindow.localId"
hasCloseAsBackButton="env.messaging.device.isMobile"
isExpandable="!env.messaging.device.isMobile and !!chatWindow.thread"
isFullscreen="env.messaging.device.isMobile"
/>
</t>
</t>
</div>
</t>
@@ -50,7 +50,7 @@ function factory(dependencies) {
route: '/mail/init_messaging',
params: { context: context }
}));
this._init(data);
await this.async(() => this._init(data));
if (discuss.isOpen) {
discuss.openInitThread();
}
@@ -78,7 +78,7 @@ function factory(dependencies) {
* @param {Object[]} [param0.shortcodes=[]]
* @param {integer} [param0.starred_counter=0]
*/
_init({
async _init({
channel_slots,
commands = [],
is_moderator = false,
@@ -94,22 +94,28 @@ function factory(dependencies) {
starred_counter = 0
}) {
const discuss = this.messaging.discuss;
// partners first because the rest of the code relies on them
this._initPartners({
moderation_channel_ids,
partner_root,
public_partner,
});
this._initChannels(channel_slots);
this._initCommands(commands);
// mailboxes after partners and before other initializers that might
// manipulate threads or messages
this._initMailboxes({
is_moderator,
moderation_counter,
needaction_inbox_counter,
starred_counter,
});
this._initMailFailures(mail_failures);
// various suggestions in no particular order
this._initCannedResponses(shortcodes);
this._initMentionPartnerSuggestions(mention_partner_suggestions);
this._initCommands(commands);
await this.async(() => this._initMentionPartnerSuggestions(mention_partner_suggestions));
// channels when the rest of messaging is ready
await this.async(() => this._initChannels(channel_slots));
// failures after channels
this._initMailFailures(mail_failures);
discuss.update({ menu_id });
}
@@ -138,15 +144,20 @@ function factory(dependencies) {
* @param {Object[]} [param0.channel_direct_message=[]]
* @param {Object[]} [param0.channel_private_group=[]]
*/
_initChannels({
async _initChannels({
channel_channel = [],
channel_direct_message = [],
channel_private_group = [],
} = {}) {
const channelsData = channel_channel.concat(channel_direct_message, channel_private_group);
this.env.models['mail.thread'].insert(channelsData.map(
channelData => this.env.models['mail.thread'].convertData(channelData)
));
for (const channelData of channelsData) {
// there might be a lot of channels, insert each of them one by
// one asynchronously to avoid blocking the UI
await this.async(() => new Promise(resolve => setTimeout(resolve)));
this.env.models['mail.thread'].insert(
this.env.models['mail.thread'].convertData(channelData)
);
}
}
/**
@@ -221,9 +232,12 @@ function factory(dependencies) {
* @private
* @param {Object[]} mentionPartnerSuggestionsData
*/
_initMentionPartnerSuggestions(mentionPartnerSuggestionsData) {
async _initMentionPartnerSuggestions(mentionPartnerSuggestionsData) {
for (const suggestions of mentionPartnerSuggestionsData) {
for (const suggestion of suggestions) {
// there might be a lot of partners, insert each of them one
// by one asynchronously to avoid blocking the UI
await this.async(() => new Promise(resolve => setTimeout(resolve)));
const { email, id, name } = suggestion;
this.env.models['mail.partner'].insert({ email, id, name });
}
+6 -6
View File
@@ -66,9 +66,9 @@ function _useChatWindow(callbacks) {
destroy: prevDestroy,
} = callbacks;
return Object.assign({}, callbacks, {
mount: prevMount.concat(() => {
mount: prevMount.concat(async () => {
// trigger mounting of chat window manager
Component.env.services['chat_window']._onWebClientReady();
await Component.env.services['chat_window']._onWebClientReady();
}),
destroy: prevDestroy.concat(() => {
Component.env.services['chat_window'].destroy();
@@ -91,9 +91,9 @@ function _useDialog(callbacks) {
destroy: prevDestroy,
} = callbacks;
return Object.assign({}, callbacks, {
mount: prevMount.concat(() => {
mount: prevMount.concat(async () => {
// trigger mounting of dialog manager
Component.env.services['dialog']._onWebClientReady();
await Component.env.services['dialog']._onWebClientReady();
}),
destroy: prevDestroy.concat(() => {
Component.env.services['dialog'].destroy();
@@ -137,7 +137,7 @@ function _useDiscuss(callbacks) {
discussWidget = new DiscussWidget(widget, state.discussData);
await discussWidget.appendTo($(selector));
if (state.autoOpenDiscuss) {
discussWidget.on_attach_callback();
await discussWidget.on_attach_callback();
}
}),
return: prevReturn.concat(result => {
@@ -165,7 +165,7 @@ function _useMessagingMenu(callbacks) {
mount: prevMount.concat(async ({ selector, widget }) => {
messagingMenuWidget = new MessagingMenuWidget(widget, {});
await messagingMenuWidget.appendTo($(selector));
messagingMenuWidget.on_attach_callback();
await messagingMenuWidget.on_attach_callback();
}),
return: prevReturn.concat(result => {
Object.assign(result, { messagingMenuWidget });