diff --git a/addons/calendar/static/src/models/activity.js b/addons/calendar/static/src/models/activity.js index fcab393591a..cabb00a2873 100644 --- a/addons/calendar/static/src/models/activity.js +++ b/addons/calendar/static/src/models/activity.js @@ -30,11 +30,14 @@ patchRecordMethods('Activity', { if (!this.calendar_event_id){ await this._super(); } else { - await this.async(() => this.messaging.rpc({ + await this.messaging.rpc({ model: 'mail.activity', method: 'unlink_w_meeting', args: [[this.id]], - })); + }); + if (!this.exists()) { + return; + } this.delete(); } }, @@ -47,11 +50,11 @@ patchRecordMethods('Activity', { if (!this.calendar_event_id){ this._super(); } else { - const action = await this.async(() => this.messaging.rpc({ + const action = await this.messaging.rpc({ model: 'mail.activity', method: 'action_create_calendar_event', args: [[this.id]], - })); + }); this.env.bus.trigger('do-action', { action }); diff --git a/addons/hr/static/src/models/employee.js b/addons/hr/static/src/models/employee.js index 48e59741ef9..8d394e2e07b 100644 --- a/addons/hr/static/src/models/employee.js +++ b/addons/hr/static/src/models/employee.js @@ -104,7 +104,10 @@ registerModel({ */ async getChat() { if (!this.user && !this.hasCheckedUser) { - await this.async(() => this.checkIsUser()); + await this.checkIsUser(); + } + if (!this.exists()) { + return; } // prevent chatting with non-users if (!this.user) { @@ -126,11 +129,17 @@ registerModel({ * @returns {Thread|undefined} */ async openChat(options) { - const chat = await this.async(() => this.getChat()); + const chat = await this.getChat(); + if (!this.exists()) { + return; + } if (!chat) { return; } - await this.async(() => chat.open(options)); + await chat.open(options); + if (!this.exists()) { + return; + } return chat; }, /** diff --git a/addons/hr/static/src/models/partner.js b/addons/hr/static/src/models/partner.js index db2de354622..bfefc547829 100644 --- a/addons/hr/static/src/models/partner.js +++ b/addons/hr/static/src/models/partner.js @@ -11,11 +11,14 @@ addRecordMethods('Partner', { * applicable. */ async checkIsEmployee() { - await this.async(() => this.messaging.models['Employee'].performRpcSearchRead({ + await this.messaging.models['Employee'].performRpcSearchRead({ context: { active_test: false }, domain: [['user_partner_id', '=', this.id]], fields: ['user_id', 'user_partner_id'], - })); + }); + if (!this.exists()) { + return; + } this.update({ hasCheckedEmployee: true }); }, }); @@ -31,7 +34,10 @@ patchRecordMethods('Partner', { // limitation of patch, `this._super` becomes unavailable after `await` const _super = this._super.bind(this, ...arguments); if (!this.employee && !this.hasCheckedEmployee) { - await this.async(() => this.checkIsEmployee()); + await this.checkIsEmployee(); + } + if (!this.exists()) { + return; } if (this.employee) { return this.employee.openProfile(); diff --git a/addons/mail/static/src/model/model_errors.js b/addons/mail/static/src/model/model_errors.js deleted file mode 100644 index 4089d612186..00000000000 --- a/addons/mail/static/src/model/model_errors.js +++ /dev/null @@ -1,15 +0,0 @@ -/** @odoo-module **/ - -export class RecordDeletedError extends Error { - - /** - * @override - * @param {string} recordLocalId local id of record that has been deleted - * @param {...any} args - */ - constructor(recordLocalId, ...args) { - super(...args); - this.recordLocalId = recordLocalId; - this.name = 'RecordDeletedError'; - } -} diff --git a/addons/mail/static/src/models/activity.js b/addons/mail/static/src/models/activity.js index ff9efa813aa..2a3fbc77a73 100644 --- a/addons/mail/static/src/models/activity.js +++ b/addons/mail/static/src/models/activity.js @@ -106,11 +106,14 @@ registerModel({ * Delete the record from database and locally. */ async deleteServerRecord() { - await this.async(() => this.messaging.rpc({ + await this.messaging.rpc({ model: 'mail.activity', method: 'unlink', args: [[this.id]], - })); + }); + if (!this.exists()) { + return; + } this.delete(); }, /** @@ -167,7 +170,8 @@ registerModel({ */ async markAsDone({ attachments = [], feedback = false }) { const attachmentIds = attachments.map(attachment => attachment.id); - await this.async(() => this.messaging.rpc({ + const thread = this.thread; + await this.messaging.rpc({ model: 'mail.activity', method: 'action_feedback', args: [[this.id]], @@ -175,8 +179,13 @@ registerModel({ attachment_ids: attachmentIds, feedback, }, - })); - this.thread.fetchData(['attachments', 'messages']); + }); + if (thread.exists()) { + thread.fetchData(['attachments', 'messages']); + } + if (!this.exists()) { + return; + } this.delete(); }, /** @@ -185,15 +194,19 @@ registerModel({ * @returns {Object} */ async markAsDoneAndScheduleNext({ feedback }) { - const action = await this.async(() => this.messaging.rpc({ + const thread = this.thread; + const action = await this.messaging.rpc({ model: 'mail.activity', method: 'action_feedback_schedule_next', args: [[this.id]], kwargs: { feedback }, - })); - this.thread.fetchData(['activities', 'attachments', 'messages']); - const thread = this.thread; - this.delete(); + }); + if (thread.exists()) { + thread.fetchData(['activities', 'attachments', 'messages']); + } + if (this.exists()) { + this.delete(); + } if (!action) { return; } @@ -201,6 +214,9 @@ registerModel({ action, options: { on_close: () => { + if (!thread.exists()) { + return; + } thread.fetchData(['activities']); }, }, diff --git a/addons/mail/static/src/models/attachment.js b/addons/mail/static/src/models/attachment.js index 795509549fc..cb6d643647c 100644 --- a/addons/mail/static/src/models/attachment.js +++ b/addons/mail/static/src/models/attachment.js @@ -77,19 +77,24 @@ registerModel({ if (!this.isUploading) { this.update({ isUnlinkPending: true }); try { - await this.async(() => this.messaging.rpc({ + await this.messaging.rpc({ route: `/mail/attachment/delete`, params: { access_token: this.accessToken, attachment_id: this.id, }, - }, { shadow: true })); + }, { shadow: true }); } finally { - this.update({ isUnlinkPending: false }); + if (this.exists()) { + this.update({ isUnlinkPending: false }); + } } } else if (this.uploadingAbortController) { this.uploadingAbortController.abort(); } + if (!this.exists()) { + return; + } this.delete(); }, /** diff --git a/addons/mail/static/src/models/channel_invitation_form.js b/addons/mail/static/src/models/channel_invitation_form.js index d852f898019..32c20d9955f 100644 --- a/addons/mail/static/src/models/channel_invitation_form.js +++ b/addons/mail/static/src/models/channel_invitation_form.js @@ -40,12 +40,14 @@ registerModel({ * A smoother transfer would be moving the RTC sessions from one channel to * the other (server-side too), but it would be considerably more complex. */ - await this.async(() => channel.toggleCall({ + await channel.toggleCall({ startWithVideo: !!this.thread.rtc.videoTrack, videoType: this.thread.rtc.sendUserVideo ? 'user-video' : 'display', - })); + }); + } + if (channel.exists()) { + channel.open(); } - channel.open(); } else { await this.messaging.rpc(({ model: 'mail.channel', diff --git a/addons/mail/static/src/models/composer_view.js b/addons/mail/static/src/models/composer_view.js index 3a88d060a5e..189b0197b41 100644 --- a/addons/mail/static/src/models/composer_view.js +++ b/addons/mail/static/src/models/composer_view.js @@ -1301,7 +1301,7 @@ registerModel({ } const model = this.messaging.models[this.suggestionModelName]; const searchTerm = this.suggestionSearchTerm; - await this.async(() => model.fetchSuggestions(searchTerm, { thread: this.composer.activeThread })); + await model.fetchSuggestions(searchTerm, { thread: this.composer.activeThread }); if (!this.exists()) { return; } diff --git a/addons/mail/static/src/models/discuss.js b/addons/mail/static/src/models/discuss.js index f06a1225c53..4bec19bc910 100644 --- a/addons/mail/static/src/models/discuss.js +++ b/addons/mail/static/src/models/discuss.js @@ -40,12 +40,10 @@ registerModel({ const name = this.addingChannelValue; this.clearIsAddingItem(); if (ui.item.special) { - const channel = await this.async(() => - this.messaging.models['Thread'].performRpcCreateChannel({ - name, - privacy: ui.item.special === 'private' ? 'private' : 'groups', - }) - ); + const channel = await this.messaging.models['Thread'].performRpcCreateChannel({ + name, + privacy: ui.item.special === 'private' ? 'private' : 'groups', + }); channel.open(); } else { const channel = this.messaging.models['Thread'].insert({ diff --git a/addons/mail/static/src/models/follower.js b/addons/mail/static/src/models/follower.js index 6d1aa0f98c6..bee335a6d1f 100644 --- a/addons/mail/static/src/models/follower.js +++ b/addons/mail/static/src/models/follower.js @@ -79,14 +79,19 @@ registerModel({ async remove() { const partner_ids = []; partner_ids.push(this.partner.id); - await this.async(() => this.messaging.rpc({ + const followedThread = this.followedThread; + await this.messaging.rpc({ model: this.followedThread.model, method: 'message_unsubscribe', args: [[this.followedThread.id], partner_ids] - })); - const followedThread = this.followedThread; + }); + if (followedThread.exists()) { + followedThread.fetchData(['suggestedRecipients']); + } + if (!this.exists()) { + return; + } this.delete(); - followedThread.fetchData(['suggestedRecipients']); }, /** * @param {FollowerSubtype} subtype @@ -100,10 +105,13 @@ registerModel({ * Show (editable) list of subtypes of this follower. */ async showSubtypes() { - const subtypesData = await this.async(() => this.messaging.rpc({ + const subtypesData = await this.messaging.rpc({ route: '/mail/read_subscription_data', params: { follower_id: this.id }, - })); + }); + if (!this.exists()) { + return; + } this.update({ subtypes: clear() }); for (const data of subtypesData) { const subtype = this.messaging.models['FollowerSubtype'].insert( @@ -139,12 +147,15 @@ registerModel({ if (this.partner) { kwargs.partner_ids = [this.partner.id]; } - await this.async(() => this.messaging.rpc({ + await this.messaging.rpc({ model: this.followedThread.model, method: 'message_subscribe', args: [[this.followedThread.id]], kwargs, - })); + }); + if (!this.exists()) { + return; + } this.messaging.notify({ type: 'success', message: this.env._t("The subscription preferences were successfully applied."), diff --git a/addons/mail/static/src/models/mail_template.js b/addons/mail/static/src/models/mail_template.js index ab5664b78be..a44d6936126 100644 --- a/addons/mail/static/src/models/mail_template.js +++ b/addons/mail/static/src/models/mail_template.js @@ -38,12 +38,15 @@ registerModel({ * @param {Activity} activity */ async send(activity) { - await this.async(() => this.messaging.rpc({ + const thread = activity.thread; + await this.messaging.rpc({ model: activity.thread.model, method: 'activity_send_mail', args: [[activity.thread.id], this.id], - })); - activity.thread.fetchData(['attachments', 'messages']); + }); + if (thread.exists()) { + thread.fetchData(['attachments', 'messages']); + } }, }, fields: { diff --git a/addons/mail/static/src/models/message.js b/addons/mail/static/src/models/message.js index 2a7321d711c..5032b7dd817 100644 --- a/addons/mail/static/src/models/message.js +++ b/addons/mail/static/src/models/message.js @@ -223,11 +223,11 @@ registerModel({ * partner Inbox. */ async markAsRead() { - await this.async(() => this.messaging.rpc({ + await this.messaging.rpc({ model: 'mail.message', method: 'set_message_done', args: [[this.id]] - })); + }); }, /** * Opens the view that allows to resend the message in case of failure. @@ -267,11 +267,11 @@ registerModel({ * Toggle the starred status of the provided message. */ async toggleStar() { - await this.async(() => this.messaging.rpc({ + await this.messaging.rpc({ model: 'mail.message', method: 'toggle_message_starred', args: [[this.id]] - })); + }); }, /** * Updates the message's content. diff --git a/addons/mail/static/src/models/messaging.js b/addons/mail/static/src/models/messaging.js index 90d46e44f7b..eecf3fc16f7 100644 --- a/addons/mail/static/src/models/messaging.js +++ b/addons/mail/static/src/models/messaging.js @@ -80,11 +80,14 @@ registerModel({ * @returns {Thread|undefined} */ async openChat(person, options) { - const chat = await this.async(() => this.getChat(person)); - if (!chat) { + const chat = await this.getChat(person); + if (!this.exists() || !chat) { + return; + } + await chat.open(options); + if (!this.exists()) { return; } - await this.async(() => chat.open(options)); return chat; }, /** @@ -129,9 +132,11 @@ registerModel({ if (model === 'mail.channel') { let channel = this.messaging.models['Thread'].findFromIdentifyingData({ id, model: 'mail.channel' }); if (!channel) { - channel = (await this.async(() => - this.messaging.models['Thread'].performRpcChannelInfo({ ids: [id] }) - ))[0]; + const res = await this.messaging.models['Thread'].performRpcChannelInfo({ ids: [id] }); + if (!this.exists()) { + return; + } + channel = res[0]; } if (!channel) { this.messaging.notify({ diff --git a/addons/mail/static/src/models/messaging_initializer.js b/addons/mail/static/src/models/messaging_initializer.js index 27cce32d89b..3b971063a2d 100644 --- a/addons/mail/static/src/models/messaging_initializer.js +++ b/addons/mail/static/src/models/messaging_initializer.js @@ -35,10 +35,16 @@ registerModel({ }); this.messaging.device.start(); const discuss = this.messaging.discuss; - const data = await this.async(() => this.messaging.rpc({ + const data = await this.messaging.rpc({ route: '/mail/init_messaging', - }, { shadow: true })); - await this.async(() => this._init(data)); + }, { shadow: true }); + if (!this.exists()) { + return; + } + await this._init(data); + if (!this.exists()) { + return; + } if (discuss.discussView) { discuss.openInitThread(); } @@ -110,7 +116,10 @@ registerModel({ this._initCommands(); } // channels when the rest of messaging is ready - await this.async(() => this._initChannels(channels)); + await this._initChannels(channels); + if (!this.exists()) { + return; + } discuss.update({ menu_id }); // company related data this.messaging.update({ companyName }); diff --git a/addons/mail/static/src/models/messaging_notification_handler.js b/addons/mail/static/src/models/messaging_notification_handler.js index 3cf98438dc3..ad8cceaf9f3 100644 --- a/addons/mail/static/src/models/messaging_notification_handler.js +++ b/addons/mail/static/src/models/messaging_notification_handler.js @@ -124,7 +124,7 @@ registerModel({ } } }); - await this.async(() => Promise.all(proms)); + await Promise.all(proms); }, /** * @abstract @@ -244,9 +244,11 @@ registerModel({ // "required" by the rest of the code and is necessary for some // features such as chat windows. if (!channel) { - channel = (await this.async(() => - this.messaging.models['Thread'].performRpcChannelInfo({ ids: [channelId] }) - ))[0]; + const res = await this.messaging.models['Thread'].performRpcChannelInfo({ ids: [channelId] }); + if (!this.exists()) { + return; + } + channel = res[0]; } if (!channel.isPinned) { channel.pin(); @@ -656,8 +658,8 @@ registerModel({ const message = sprintf(this.env._t('%s connected'), username); const title = this.env._t("This is their first connection. Wish them luck."); this.env.services['bus_service'].sendNotification({ message, title, type: 'info' }); - const chat = await this.async(() => this.messaging.getChat({ partnerId })); - if (!chat || this.messaging.device.isSmall) { + const chat = await this.messaging.getChat({ partnerId }); + if (!this.exists() || !chat || this.messaging.device.isSmall) { return; } this.messaging.chatWindowManager.openThread(chat); diff --git a/addons/mail/static/src/models/partner.js b/addons/mail/static/src/models/partner.js index fe77d81f405..7b31f96c490 100644 --- a/addons/mail/static/src/models/partner.js +++ b/addons/mail/static/src/models/partner.js @@ -299,14 +299,17 @@ registerModel({ * applicable. */ async checkIsUser() { - const userIds = await this.async(() => this.messaging.rpc({ + const userIds = await this.messaging.rpc({ model: 'res.users', method: 'search', args: [[['partner_id', '=', this.id]]], kwargs: { context: { active_test: false }, }, - }, { shadow: true })); + }, { shadow: true }); + if (!this.exists()) { + return; + } this.update({ hasCheckedUser: true }); if (userIds.length > 0) { this.update({ user: insert({ id: userIds[0] }) }); @@ -321,7 +324,10 @@ registerModel({ */ async getChat() { if (!this.user && !this.hasCheckedUser) { - await this.async(() => this.checkIsUser()); + await this.checkIsUser(); + if (!this.exists()) { + return; + } } // prevent chatting with non-users if (!this.user) { @@ -343,11 +349,14 @@ registerModel({ * @returns {Thread|undefined} */ async openChat(options) { - const chat = await this.async(() => this.getChat()); - if (!chat) { + const chat = await this.getChat(); + if (!this.exists() || !chat) { + return; + } + await chat.open(options); + if (!this.exists()) { return; } - await this.async(() => chat.open(options)); return chat; }, /** diff --git a/addons/mail/static/src/models/record.js b/addons/mail/static/src/models/record.js index 25531417b18..a2f202c359d 100644 --- a/addons/mail/static/src/models/record.js +++ b/addons/mail/static/src/models/record.js @@ -1,7 +1,6 @@ /** @odoo-module **/ import { registerModel } from '@mail/model/model_core'; -import { RecordDeletedError } from '@mail/model/model_errors'; import { one } from '@mail/model/model_field'; import { insertAndReplace } from '@mail/model/model_field_command'; @@ -147,35 +146,6 @@ registerModel({ }, }, recordMethods: { - /** - * Perform an async function and wait until it is done. If the record - * is deleted, it raises a RecordDeletedError. - * - * @param {function} func an async function - * @throws {RecordDeletedError} in case the current record is not alive - * at the end of async function call, whether it's resolved or - * rejected. - * @throws {any} forwards any error in case the current record is still - * alive at the end of rejected async function call. - * @returns {any} result of resolved async function. - */ - async async(func) { - return new Promise((resolve, reject) => { - Promise.resolve(func()).then(result => { - if (this.exists()) { - resolve(result); - } else { - reject(new RecordDeletedError(this.localId)); - } - }).catch(error => { - if (this.exists()) { - reject(error); - } else { - reject(new RecordDeletedError(this.localId)); - } - }); - }); - }, /** * This method deletes this record. */ diff --git a/addons/mail/static/src/models/rtc.js b/addons/mail/static/src/models/rtc.js index dd1bfb82170..86825516f6c 100644 --- a/addons/mail/static/src/models/rtc.js +++ b/addons/mail/static/src/models/rtc.js @@ -263,14 +263,20 @@ registerModel({ } audioTrack.addEventListener('ended', async () => { // this mostly happens when the user retracts microphone permission. - await this.async(() => this.updateLocalAudioTrack(false)); + await this.updateLocalAudioTrack(false); + if (!this.exists()) { + return; + } this.currentRtcSession.updateAndBroadcast({ isSelfMuted: true }); - await this.async(() => this._updateLocalAudioTrackEnabledState()); + await this._updateLocalAudioTrackEnabledState(); }); this.currentRtcSession.updateAndBroadcast({ isSelfMuted: false }); audioTrack.enabled = !this.currentRtcSession.isMute && this.currentRtcSession.isTalking; this.update({ audioTrack }); - await this.async(() => this.updateVoiceActivation()); + await this.updateVoiceActivation(); + if (!this.exists()) { + return; + } for (const rtcSession of this.connectedRtcSessions) { await this._updateRemoteTrack(rtcSession.rtcPeerConnection.peerConnection, 'audio', { token: rtcSession.id }); } @@ -1014,9 +1020,7 @@ registerModel({ const videoTrack = videoStream ? videoStream.getVideoTracks()[0] : undefined; if (videoTrack) { videoTrack.addEventListener('ended', async () => { - await this.async(() => - this._toggleVideoBroadcast({ force: false, type }) - ); + await this._toggleVideoBroadcast({ force: false, type }); }); } this.update({ diff --git a/addons/mail/static/src/models/thread.js b/addons/mail/static/src/models/thread.js index bb3cd4bdc57..20754fb064d 100644 --- a/addons/mail/static/src/models/thread.js +++ b/addons/mail/static/src/models/thread.js @@ -34,11 +34,11 @@ registerModel({ */ this._currentPartnerInactiveTypingTimer = new Timer( this.messaging, - () => this.async(() => { + () => { if (this.messaging.currentPartner) { return this._onCurrentPartnerInactiveTypingTimeout(); } - }), + }, 5 * 1000 ); /** @@ -67,7 +67,7 @@ registerModel({ */ this._currentPartnerLongTypingTimer = new Timer( this.messaging, - () => this.async(() => this._onCurrentPartnerLongTypingTimeout()), + () => this._onCurrentPartnerLongTypingTimeout(), 50 * 1000 ); /** @@ -104,7 +104,9 @@ registerModel({ */ this._throttleNotifyCurrentPartnerTypingStatus = throttle( this.messaging, - ({ isTyping }) => this.async(() => this._notifyCurrentPartnerTypingStatus({ isTyping })), + ({ isTyping }) => { + this._notifyCurrentPartnerTypingStatus({ isTyping }); + }, 2.5 * 1000 ); }, @@ -669,24 +671,27 @@ registerModel({ * Add current user to provided thread's followers. */ async follow() { - await this.async(() => this.messaging.rpc({ + await this.messaging.rpc({ model: this.model, method: 'message_subscribe', args: [[this.id]], kwargs: { partner_ids: [this.messaging.currentPartner.id], }, - })); + }); + if (!this.exists()) { + return; + } this.fetchData(['followers', 'suggestedRecipients']); }, /** * Performs the rpc to leave the rtc call of the channel. */ async performRpcLeaveCall() { - await this.async(() => this.messaging.rpc({ + await this.messaging.rpc({ route: '/mail/rtc/channel/leave_call', params: { channel_id: this.id }, - }, { shadow: true })); + }, { shadow: true }); }, /** * Leaves the current call if there is one, joins the call if the user was @@ -723,13 +728,13 @@ registerModel({ }); return; } - const { rtcSessions, iceServers, sessionId, invitedPartners, invitedGuests } = await this.async(() => this.messaging.rpc({ + const { rtcSessions, iceServers, sessionId, invitedPartners, invitedGuests } = await this.messaging.rpc({ route: '/mail/rtc/channel/join_call', params: { channel_id: this.id, check_rtc_session_ids: this.rtcSessions.map(rtcSession => rtcSession.id), }, - }, { shadow: true })); + }, { shadow: true }); if (!this.exists()) { return; } @@ -740,13 +745,16 @@ registerModel({ invitedGuests, invitedPartners, }); - await this.async(() => this.messaging.rtc.initSession({ + await this.messaging.rtc.initSession({ currentSessionId: sessionId, iceServers, startWithAudio: true, startWithVideo, videoType, - })); + }); + if (!this.exists()) { + return; + } this.messaging.soundEffects.channelJoin.play(); }, /** @@ -810,11 +818,11 @@ registerModel({ * Mark the specified conversation as fetched. */ async markAsFetched() { - await this.async(() => this.messaging.rpc({ + await this.messaging.rpc({ model: 'mail.channel', method: 'channel_fetched', args: [[this.id]], - }, { shadow: true })); + }, { shadow: true }); }, /** * Mark the specified conversation as read/seen. @@ -847,9 +855,7 @@ registerModel({ * Marks as read all needaction messages with this thread as origin. */ async markNeedactionMessagesAsOriginThreadAsRead() { - await this.async(() => - this.messaging.models['Message'].markAsRead(this.needactionMessagesAsOriginThread) - ); + await this.messaging.models['Message'].markAsRead(this.needactionMessagesAsOriginThread); }, /** * Notifies the server of new fold state. Useful for initial, @@ -1007,7 +1013,7 @@ registerModel({ registerOtherMemberTypingMember(partner) { const timer = new Timer( this.messaging, - () => this.async(() => this._onOtherMemberLongTypingTimeout(partner)), + () => this._onOtherMemberLongTypingTimeout(partner), 60 * 1000 ); this._otherMembersLongTypingTimers.set(partner, timer); @@ -1057,7 +1063,7 @@ registerModel({ const currentPartnerFollower = this.followers.find( follower => follower.partner === this.messaging.currentPartner ); - await this.async(() => currentPartnerFollower.remove()); + await currentPartnerFollower.remove(); }, /** * Unpin this thread and notify server of the change. @@ -1096,9 +1102,7 @@ registerModel({ if (immediateNotify) { this._throttleNotifyCurrentPartnerTypingStatus.clear(); } - await this.async( - () => this._throttleNotifyCurrentPartnerTypingStatus({ isTyping: false }) - ); + await this._throttleNotifyCurrentPartnerTypingStatus({ isTyping: false }); }, /** * Called to unregister an other member partner that is no longer typing @@ -1694,12 +1698,15 @@ registerModel({ isTyping !== this._currentPartnerLastNotifiedIsTyping ) { if (this.model === 'mail.channel') { - await this.async(() => this.messaging.rpc({ + await this.messaging.rpc({ model: 'mail.channel', method: 'notify_typing', args: [this.id], kwargs: { is_typing: isTyping }, - }, { shadow: true })); + }, { shadow: true }); + if (!this.exists()) { + return; + } } if (isTyping && this._currentPartnerLongTypingTimer.isRunning) { this._currentPartnerLongTypingTimer.reset(); @@ -1773,8 +1780,11 @@ registerModel({ action, options: { on_close: async () => { - await this.async(() => this.fetchData(['followers'])); - this.env.bus.trigger('Thread:promptAddFollower-closed'); + if (!this.exists()) { + return; + } + await this.fetchData(['followers']); + this.env.bus.trigger('Thread:promptAddFollower-closed'); }, }, }); @@ -1841,7 +1851,7 @@ registerModel({ * @private */ async _onCurrentPartnerInactiveTypingTimeout() { - await this.async(() => this.unregisterCurrentPartnerIsTyping()); + await this.unregisterCurrentPartnerIsTyping(); }, /** * Called when current partner has been typing for a very long time. @@ -1852,9 +1862,7 @@ registerModel({ async _onCurrentPartnerLongTypingTimeout() { this._forceNotifyNextCurrentPartnerTypingStatus = true; this._throttleNotifyCurrentPartnerTypingStatus.clear(); - await this.async( - () => this._throttleNotifyCurrentPartnerTypingStatus({ isTyping: true }) - ); + await this._throttleNotifyCurrentPartnerTypingStatus({ isTyping: true }); }, /** * @private diff --git a/addons/mail/static/src/models/thread_view.js b/addons/mail/static/src/models/thread_view.js index 20637f8043a..e62a932cba3 100644 --- a/addons/mail/static/src/models/thread_view.js +++ b/addons/mail/static/src/models/thread_view.js @@ -1,7 +1,6 @@ /** @odoo-module **/ import { registerModel } from '@mail/model/model_core'; -import { RecordDeletedError } from '@mail/model/model_errors'; import { attr, many, one } from '@mail/model/model_field'; import { clear, insertAndReplace, replace } from '@mail/model/model_field_command'; import { OnChange } from '@mail/model/model_onchange'; @@ -240,12 +239,7 @@ registerModel({ if (this.messaging.currentGuest) { return; } - this.thread.markAsSeen(this.thread.lastNonTransientMessage).catch(e => { - // prevent crash when executing compute during destroy - if (!(e instanceof RecordDeletedError)) { - throw e; - } - }); + this.thread.markAsSeen(this.thread.lastNonTransientMessage); }, /** * @private @@ -275,11 +269,13 @@ registerModel({ if (this.threadCache && this.threadCache.isLoading) { if (!this.isLoading && !this.isPreparingLoading) { this.update({ isPreparingLoading: true }); - this.async(() => - new Promise(resolve => { + (new Promise(resolve => { this.update({ loaderTimeout: this.messaging.browser.setTimeout(resolve, this.messaging.loadingBaseDelayDuration) }); } )).then(() => { + if (!this.exists()) { + return; + } const isLoading = this.threadCache ? this.threadCache.isLoading : false; diff --git a/addons/mail/static/src/models/user.js b/addons/mail/static/src/models/user.js index 488d5542027..776c9f7150a 100644 --- a/addons/mail/static/src/models/user.js +++ b/addons/mail/static/src/models/user.js @@ -74,7 +74,10 @@ registerModel({ */ async getChat() { if (!this.partner) { - await this.async(() => this.fetchPartner()); + await this.fetchPartner(); + if (!this.exists()) { + return; + } } if (!this.partner) { // This user has been deleted from the server or never existed: @@ -97,11 +100,12 @@ registerModel({ if (!chat || !chat.isPinned) { // if chat is not pinned then it has to be pinned client-side // and server-side, which is a side effect of following rpc - chat = await this.async(() => - this.messaging.models['Thread'].performRpcCreateChat({ - partnerIds: [this.partner.id], - }) - ); + chat = await this.messaging.models['Thread'].performRpcCreateChat({ + partnerIds: [this.partner.id], + }); + if (!this.exists()) { + return; + } } if (!chat) { this.messaging.notify({ @@ -121,11 +125,14 @@ registerModel({ * @returns {Thread|undefined} */ async openChat(options) { - const chat = await this.async(() => this.getChat()); - if (!chat) { + const chat = await this.getChat(); + if (!this.exists() || !chat) { + return; + } + await chat.open(options); + if (!this.exists() || !chat.exists()) { return; } - await this.async(() => chat.open(options)); return chat; }, /** @@ -137,7 +144,10 @@ registerModel({ */ async openProfile() { if (!this.partner) { - await this.async(() => this.fetchPartner()); + await this.fetchPartner(); + if (!this.exists()) { + return; + } } if (!this.partner) { // This user has been deleted from the server or never existed: diff --git a/addons/snailmail/static/src/models/message.js b/addons/snailmail/static/src/models/message.js index f5c540ad889..0c9d599e69d 100644 --- a/addons/snailmail/static/src/models/message.js +++ b/addons/snailmail/static/src/models/message.js @@ -12,11 +12,11 @@ addRecordMethods('Message', { */ async cancelLetter() { // the result will come from longpolling: message_notification_update - await this.async(() => this.messaging.rpc({ + await this.messaging.rpc({ model: 'mail.message', method: 'cancel_letter', args: [[this.id]], - })); + }); }, /** * Opens the action about 'snailmail.letter' format error. @@ -35,11 +35,11 @@ addRecordMethods('Message', { * Opens the action about 'snailmail.letter' missing fields. */ async openMissingFieldsLetterAction() { - const letterIds = await this.async(() => this.messaging.rpc({ + const letterIds = await this.messaging.rpc({ model: 'snailmail.letter', method: 'search', args: [[['message_id', '=', this.id]]], - })); + }); this.env.bus.trigger('do-action', { action: 'snailmail.snailmail_letter_missing_required_fields_action', options: { @@ -54,10 +54,10 @@ addRecordMethods('Message', { */ async resendLetter() { // the result will come from longpolling: message_notification_update - await this.async(() => this.messaging.rpc({ + await this.messaging.rpc({ model: 'mail.message', method: 'send_letter', args: [[this.id]], - })); + }); }, }); diff --git a/addons/snailmail/static/src/models/messaging.js b/addons/snailmail/static/src/models/messaging.js index 7bfe167ded2..c28dc9c4e99 100644 --- a/addons/snailmail/static/src/models/messaging.js +++ b/addons/snailmail/static/src/models/messaging.js @@ -7,21 +7,27 @@ import '@mail/models/messaging'; addRecordMethods('Messaging', { async fetchSnailmailCreditsUrl() { - const snailmail_credits_url = await this.async(() => this.messaging.rpc({ + const snailmail_credits_url = await this.messaging.rpc({ model: 'iap.account', method: 'get_credits_url', args: ['snailmail'], - })); + }); + if (!this.exists()) { + return; + } this.update({ snailmail_credits_url, }); }, async fetchSnailmailCreditsUrlTrial() { - const snailmail_credits_url_trial = await this.async(() => this.messaging.rpc({ + const snailmail_credits_url_trial = await this.messaging.rpc({ model: 'iap.account', method: 'get_credits_url', args: ['snailmail', '', 0, true], - })); + }); + if (!this.exists()) { + return; + } this.update({ snailmail_credits_url_trial, });