diff options
Diffstat (limited to 'addons/mail/static/src/js/services/mail_notification_manager.js')
| -rw-r--r-- | addons/mail/static/src/js/services/mail_notification_manager.js | 597 |
1 files changed, 0 insertions, 597 deletions
diff --git a/addons/mail/static/src/js/services/mail_notification_manager.js b/addons/mail/static/src/js/services/mail_notification_manager.js deleted file mode 100644 index c7c5a03e6bf..00000000000 --- a/addons/mail/static/src/js/services/mail_notification_manager.js +++ /dev/null @@ -1,597 +0,0 @@ -odoo.define('mail.Manager.Notification', function (require) { -"use strict"; - -/** - * Mail Notification Manager - * - * This part of the mail manager is responsible for receiving notifications on - * the longpoll bus, which are data received from the server. - */ -var MailManager = require('mail.Manager'); -var MailFailure = require('mail.model.MailFailure'); - -const config = require('web.config'); -var core = require('web.core'); -var session = require('web.session'); - -var _t = core._t; - -MailManager.include({ - - //-------------------------------------------------------------------------- - // Private - //-------------------------------------------------------------------------- - - /** - * Remove channel notifications if there is an unsubscribe notification - * on this channel. - * - * @private - * @param {Object[]} notifications - * @returns {Object[]} notifications filtered of channel notifications - * matching unsubscribe notifs - */ - _filterNotificationsOnUnsubscribe: function (notifications) { - var unsubscribedNotif = _.find(notifications, function (notif) { - return notif[1].info === 'unsubscribe'; - }); - if (unsubscribedNotif) { - notifications = _.reject(notifications, function (notif) { - return notif[0][1] === 'mail.channel' && - notif[0][2] === unsubscribedNotif[1].id; - }); - } - return notifications; - }, - /** - * Called when receiving a notification on a channel (all members of a - * channel receive this notification) - * - * @private - * @param {Object} params - * @param {integer} [params.channelID] - * @param {Object} params.data - * @param {string} [params.data.info] if set, specify the type of data on - * this channel notification - */ - _handleChannelNotification: function (params) { - if (params.data && params.data.info === 'typing_status') { - this._handleChannelTypingNotification(params.channelID, params.data); - } else if (params.data && params.data.info === 'channel_fetched') { - this._handleChannelFetchedNotification(params.channelID, params.data); - } else if (params.data && params.data.info === 'channel_seen') { - this._handleChannelSeenNotification(params.channelID, params.data); - } else { - this._handleChannelMessageNotification(params.data); - } - }, - /** - * Called when a channel has been fetched, and the server responses with the - * last message fetched. Useful in order to track last message fetched. - * - * @private - * @param {integer} channelID - * @param {Object} data - * @param {string} data.info 'channel_fetched' - * @param {integer} data.last_message_id - * @param {integer} data.partner_id - */ - _handleChannelFetchedNotification: function (channelID, data) { - var channel = this.getChannel(channelID); - if (!channel) { - return; - } - if (channel.hasSeenFeature()) { - channel.updateSeenPartnersInfo(data); - } - }, - /** - * Called when a new or updated message is received on a channel - * - * @private - * @param {Object} messageData - * @param {integer[]} messageData.channel_ids channel IDs of this message - * (note that 'pending moderation' messages in moderated channels do not - * have the moderated channels in this array). - */ - _handleChannelMessageNotification: function (messageData) { - var self = this; - var def; - let notify = true; - if (messageData.channel_ids.length === 1) { - const channel = this.getChannel(messageData.channel_ids[0]); - // Message from mailing channel should not make a notification in Odoo for users - // with notification "Handled by Email", but web client should receive the message. - // Channel has been marked as read server-side in this case, so it should not display - // a notification by incrementing the unread counter. - notify = channel && (!channel.isMassMailing() || session.notification_type !== 'email'); - def = this.joinChannel(messageData.channel_ids[0], { autoswitch: false }); - } else { - def = Promise.resolve(); - } - def.then(function () { - // don't increment unread if channel wasn't in cache yet as - // its unread counter has just been fetched - return self.addMessage(messageData, { - showNotification: true, - incrementUnread: notify, - }); - }); - }, - /** - * Called when a channel has been seen, and the server responses with the - * last message seen. Useful in order to track last message seen. - * - * @private - * @param {integer} channelID - * @param {Object} data - * @param {string} data.info 'channel_seen' - * @param {integer} data.last_message_id - * @param {integer} data.partner_id - */ - _handleChannelSeenNotification: function (channelID, data) { - var channel = this.getChannel(channelID); - if (!channel) { - return; - } - if (channel.hasSeenFeature()) { - channel.updateSeenPartnersInfo(data); - } - if (session.partner_id !== data.partner_id) { - return; - } - channel.setLastSeenMessageID(data.last_message_id); - if (channel.hasUnreadMessages()) { - channel.resetUnreadCounter(); - } - }, - /** - * Called when someone starts or stops typing a message in a channel - * - * @private - * @param {integer} channelID - * @param {Object} typingData - * @param {boolean} typingData.is_typing - * @param {boolean} typingData.is_website_user - * @param {integer} typingData.partner_id - */ - _handleChannelTypingNotification: function (channelID, typingData) { - var isWebsiteUser = typingData.is_website_user; - var partnerID = typingData.partner_id; - if (partnerID === session.partner_id && !isWebsiteUser) { - return; // ignore typing notification of myself - } - var channel = this.getChannel(channelID); - if (!channel) { - return; - } - var typingID = { - isWebsiteUser: typingData.is_website_user, - partnerID: typingData.partner_id, - }; - if (typingData.is_typing) { - channel.registerTyping(typingID); - } else { - channel.unregisterTyping(typingID); - } - }, - /** - * On message becoming a need action (pinned to inbox) - * - * @private - * @param {Object} messageData - * @param {integer[]} messageData.channel_ids - */ - _handleNeedactionNotification: function (messageData) { - var self = this; - var inbox = this.getMailbox('inbox'); - this.addMessage(messageData, { - incrementUnread: true, - showNotification: true, - }).then(function (message) { - inbox.incrementMailboxCounter(); - _.each(message.getThreadIDs(), function (threadID) { - var channel = self.getChannel(threadID); - if (channel) { - channel.incrementNeedactionCounter(); - } - }); - self._mailBus.trigger('update_needaction', inbox.getMailboxCounter()); - }); - }, - /** - * Called when an activity record has been updated on the server - * - * @private - * @param {Object} data key, value to decide activity created or deleted - */ - _handlePartnerActivityUpdateNotification: function (data) { - this._mailBus.trigger('activity_updated', data); - }, - /** - * Called to open the channel in detach mode (minimized) even if no new message: - * - * @private - * @param {Object} channelData - * @param {integer} channelData.id - * @param {string} [channelData.info] - * @param {boolean} channelData.is_minimized - * @param {string} channelData.state - */ - _handlePartnerChannelMinimizeNotification: function (channelData) { - var self = this; - this._addChannel(channelData).then(function (channelID){ - self.getChannel(channelID).detach() - }); - }, - /** - * Called when receiving a channel state as a partner notification: - * - * - if it is a new channel, it means we have been invited to this channel - * - if it is an existing channel, it means the window state of the channel - * may have changed (as this state is stored server-side) - * - * @private - * @param {Object} channelData - * @param {integer} channelData.id - * @param {string} [channelData.info] - * @param {boolean} channelData.is_minimized - * @param {string} channelData.state - */ - _handlePartnerChannelNotification: function (channelData) { - if ( - (channelData.channel_type === 'channel') && - (channelData.state === 'open') - ) { - // invited to a new channel - this._addChannel(channelData, { autoswitch: false }); - if ( - !channelData.is_minimized && - channelData.info !== 'creation' - ) { - this.do_notify( - false, - _t("You have been invited to: ") + channelData.name); - } - } - // Prevent to open/close a channel on mobile when you open/close it on desktop. - if (!config.device.isMobile) { - const channel = this.getChannel(channelData.id); - if (channel && channelData.info !== 'join') { - channel.updateWindowState({ - folded: channelData.state === 'folded' ? true : false, - detached: channelData.is_minimized, - }); - } - } - }, - /** - * Called when receiving a multi_user_channel seen notification. Only - * the current user is notified. This must be handled as if this is a - * channel seen notification. - * - * Note that this is a 'res.partner' notification because only the current - * user is notified on channel seen. This is a consequence from disabling - * the seen feature on multi_user_channel, because we still need to get - * the last seen message ID in order to display the "New Messages" separator - * in Discuss. - * - * @private - * @param {Object} data - * @param {integer} data.channel_id - * @param {string} data.info 'channel_seen' - * @param {integer} data.last_message_id - * @param {integer} data.partner_id - */ - _handlePartnerChannnelSeenNotification: function (data) { - this._handleChannelSeenNotification(data.channel_id, data); - }, - /** - * Add or remove failure when receiving a failure update message - * - * @private - * @param {Object} datas - * @param {Object[]} datas.elements list of mail failure data - * @param {string} datas.elements[].message_id ID of related message that - * has a mail failure. - * @param {Array} datas.elements[].notifications list of notifications - * that is related to a mail failure. - * @param {string} datas.elements[].notifications[0] sending state of a mail - * failure (e.g. 'exception'). - */ - _handlePartnerMessageNotificationUpdateNotification(datas) { - var self = this; - _.each(datas.elements, function (data) { - var isNewFailure = _.some(data.notifications, function (notif) { - return notif[0] === 'exception' || notif[0] === 'bounce'; - }); - var matchedFailure = _.find(self._mailFailures, function (failure) { - return failure.getMessageID() === data.message_id; - }); - if (matchedFailure) { - var index = _.findIndex(self._mailFailures, matchedFailure); - if (isNewFailure) { - self._mailFailures[index] = new MailFailure(self, data); - } else { - self._mailFailures.splice(index, 1); - } - } else if (isNewFailure) { - self._mailFailures.push(new MailFailure(self, data)); - } - var message = _.find(self._messages, function (msg) { - return msg.getID() === data.message_id; - }); - if (message) { - message.setNotifications(data.notifications); - self._mailBus.trigger('update_message', message); - } - }); - this._mailBus.trigger('update_needaction', this.needactionCounter); - }, - /** - * Updates mailbox_inbox when a message has marked as read. - * - * @private - * @param {Object} data - * @param {integer[]} [data.channel_ids] - * @param {integer[]} [data.message_ids] - * @param {string} [data.type] - */ - _handlePartnerMarkAsReadNotification: function (data) { - var self = this; - var history = this.getMailbox('history'); - _.each(data.message_ids, function (messageID) { - var message = _.find(self._messages, function (msg) { - return msg.getID() === messageID; - }); - if (message) { - self._removeMessageFromThread('mailbox_inbox', message); - history.addMessage(message); - self._mailBus.trigger('update_message', message, data.type); - } - }); - if (data.channel_ids) { - _.each(data.channel_ids, function (channelID) { - var channel = self.getChannel(channelID); - if (channel) { - channel.decrementNeedactionCounter(data.message_ids.length, 0); - } - }); - } else { - // if no channel_ids specified, this is a 'mark all read' in inbox - _.each(this.getChannels(), function (channel) { - channel.resetNeedactionCounter(); - }); - } - var inbox = this.getMailbox('inbox'); - inbox.decrementMailboxCounter(data.message_ids.length); - this._mailBus.trigger('update_needaction', inbox.getMailboxCounter()); - }, - /** - * On receiving a message made by the current user, on a moderated channel, - * which is pending moderation. - * - * @private - * @param {Object} data - * @param {Object} data.message server-side data of the message - */ - _handlePartnerMessageAuthorNotification: function (data) { - this.addMessage(data.message); - }, - /** - * Notification to delete several messages locally - * Useful when a pending moderation message has been rejected, so that - * this message should not be displayed anymore. - * - * @private - * @param {Object} data - * @param {Object[]} [data.message_ids] IDs of messages to delete locally. - */ - _handlePartnerMessageDeletionNotification: function (data) { - var self = this; - _.each(data.message_ids, function (messageID) { - var message = self.getMessage(messageID); - if (message) { - message.setModerationStatus('rejected'); - } - }); - }, - /** - * On receiving a message pending moderation, and current user is moderator - * of such message. - * - * @param {Object} data notification data - * @param {Object} data.message data of message - */ - _handlePartnerMessageModeratorNotification: function (data) { - var self = this; - this.addMessage(data.message).then(function () { - self._mailBus.trigger('update_moderation_counter'); - }); - }, - /** - * On receiving a notification that is specific to a user - * - * @private - * @param {Object} data structure depending on the type - * @param {integer} data.id - */ - _handlePartnerNotification: function (data) { - if (data.info === 'unsubscribe') { - this._handlePartnerUnsubscribeNotification(data); - } else if (data.type === 'toggle_star') { - this._handlePartnerToggleStarNotification(data); - } else if (data.type === 'mark_as_read') { - this._handlePartnerMarkAsReadNotification(data); - } else if (data.type === 'moderator') { - this._handlePartnerMessageModeratorNotification(data); - } else if (data.type === 'author') { - this._handlePartnerMessageAuthorNotification(data); - } else if (data.type === 'deletion') { - this._handlePartnerMessageDeletionNotification(data); - } else if (data.info === 'transient_message') { - this._handlePartnerTransientMessageNotification(data); - } else if (data.type === 'activity_updated') { - this._handlePartnerActivityUpdateNotification(data); - } else if (data.type === 'message_notification_update') { - this._handlePartnerMessageNotificationUpdateNotification(data); - } else if (data.type === 'user_connection') { - this._handlePartnerUserConnectionNotification(data); - } else if (data.info === 'channel_seen') { - this._handlePartnerChannnelSeenNotification(data); - } else if (data.type === 'simple_notification') { - var title = _.escape(data.title), message = _.escape(data.message); - data.warning ? this.do_warn(title, message, data.sticky) : this.do_notify(title, message, data.sticky); - } else if (data.info === 'channel_minimize') { - this._handlePartnerChannelMinimizeNotification(data); - } else { - this._handlePartnerChannelNotification(data); - } - }, - /** - * On toggling on or off the star status of one or several messages. - * As the information is stored server-side, the web client must adapt - * itself from server's data on the messages. - * - * @private - * @param {Object} data - * @param {integer[]} data.message_ids IDs of messages that have a change - * of their starred status. - * @param {boolean} data.starred states whether the messages with id in - * `data.message_ids` have become either starred or unstarred - */ - _handlePartnerToggleStarNotification: function (data) { - var self = this; - var starred = this.getMailbox('starred'); - _.each(data.message_ids, function (messageID) { - var message = _.find(self._messages, function (msg) { - return msg.getID() === messageID; - }); - if (message) { - message.setStarred(data.starred); - if (!message.isStarred()) { - self._removeMessageFromThread('mailbox_starred', message); - } else { - self._addMessageToThreads(message, []); - var channelStarred = self.getMailbox('starred'); - channelStarred.invalidateCaches(); - } - self._mailBus.trigger('update_message', message); - } - }); - - if (data.starred) { - // increase starred counter if message is marked as star - starred.incrementMailboxCounter(data.message_ids.length); - } else { - // decrease starred counter if message is remove from starred - // if unstar_all then it will set to 0. - starred.decrementMailboxCounter(data.message_ids.length); - } - - this._mailBus.trigger('update_starred', starred.getMailboxCounter()); - }, - /** - * On receiving a transient message, i.e. a message which does not come from - * a member of the channel. Usually a log message, such as one generated - * from a command with ('/'). - * - * @private - * @param {Object} data - */ - _handlePartnerTransientMessageNotification: function (data) { - var lastMessage = _.last(this._messages); - data.id = (lastMessage ? lastMessage.getID() : 0) + 0.01; - data.author_id = this.getOdoobotID(); - this.addMessage(data); - }, - /** - * On receiving a unsubscribe from channel notification, confirm - * unsubscription from channel and adapt screen accordingly. - * - * @private - * @param {Object} data - * @param {Object} data.id ID of the unsubscribed channel - */ - _handlePartnerUnsubscribeNotification: function (data) { - var channel = this.getChannel(data.id); - if (channel) { - var message; - if (_.contains(['public', 'private'], channel.getType())) { - message = _.str.sprintf( - _t("You unsubscribed from <b>%s</b>."), - channel.getName() - ); - } else { - message = _.str.sprintf( - _t("You unpinned your conversation with <b>%s</b>."), - channel.getName() - ); - } - this._removeChannel(channel); - this._mailBus.trigger('unsubscribe_from_channel', data.id); - this.do_notify(false, message); - } - }, - /** - * Shows a popup to notify a user connection - * - * @private - * @param {Object} data - * @param {Object[]} data.partner_id id of the connected partner - * @param {string} data.title title to display on notification - * @param {Array} data.messages message to display on notification - */ - _handlePartnerUserConnectionNotification: function (data) { - var self = this; - var partnerID = data.partner_id; - this.call('bus_service', 'sendNotification', data.title, data.message, function ( ){ - self.call('mail_service', 'openDMChatWindowFromBlankThreadWindow', partnerID); - }); - }, - /** - * @override - * @private - */ - _listenOnBuses: function () { - this._super.apply(this, arguments); - this.call('bus_service', 'onNotification', this, this._onNotification); - }, - - //-------------------------------------------------------------------------- - // Handlers - //-------------------------------------------------------------------------- - - /** - * Notification handlers - * Sometimes, the web client receives unsubscribe notification and an extra - * notification on that channel. This is then followed by an attempt to - * rejoin the channel that we just left. The next few lines remove the - * extra notification to prevent that situation to occur. - * - * @private - * @param {Array} notifs - */ - _onNotification: function (notifs) { - var self = this; - notifs = this._filterNotificationsOnUnsubscribe(notifs); - _.each(notifs, function (notif) { - var model = notif[0][1]; - if (model === 'ir.needaction') { - self._handleNeedactionNotification(notif[1]); - } else if (model === 'mail.channel') { - // new message in a channel - self._handleChannelNotification({ - channelID: notif[0][2], - data: notif[1], - }); - } else if (model === 'res.partner') { - self._handlePartnerNotification(notif[1]); - } - }); - }, -}); - -return MailManager; - -}); |
