From 8af3841cb25cee33fd503ebe692abb8f98d4840a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Wed, 20 Jan 2016 13:47:57 +0100 Subject: [PATCH] [FIX] mail: prevent mail to rejoin a channel that we just left 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. This commit prevents that situation to occur. For that, it needs to know the notifications received by the bus in one batch, not one at a time. --- addons/bus/static/src/js/bus.js | 23 +++++----- .../im_livechat/static/src/js/im_livechat.js | 17 ++++---- addons/mail/static/src/js/chat_manager.js | 42 ++++++++++++------- 3 files changed, 50 insertions(+), 32 deletions(-) diff --git a/addons/bus/static/src/js/bus.js b/addons/bus/static/src/js/bus.js index b36a620afb3..a8de43dd9fa 100644 --- a/addons/bus/static/src/js/bus.js +++ b/addons/bus/static/src/js/bus.js @@ -66,7 +66,7 @@ bus.Bus = Widget.extend({ } var data = {channels: self.channels, last: self.last, options: options}; session.rpc('/longpolling/poll', data, {shadow : true}).then(function(result) { - self._notification_receive(result); + self.on_notification(result); if(!self.stop){ self.poll(); } @@ -77,14 +77,15 @@ bus.Bus = Widget.extend({ setTimeout(_.bind(self.poll, self), bus.ERROR_DELAY + (Math.floor((Math.random()*20)+1)*1000)); }); }, - _notification_receive: function(notifications){ - _.each(notifications, this.on_notification); - }, - on_notification: function(notification) { - if (notification.id > this.last) { - this.last = notification.id; - } - this.trigger("notification", [notification.channel, notification.message]); + on_notification: function(notifications) { + var self = this; + var notifs = _.map(notifications, function (notif) { + if (notif.id > self.last) { + self.last = notif.id; + } + return [notif.channel, notif.message]; + }); + this.trigger("notification", notifs); }, add_channel: function(channel){ this.channels.push(channel); @@ -173,7 +174,7 @@ var CrossTabBus = bus.Bus.extend({ this._super.apply(this, arguments); } }, - _notification_receive: function(notifications){ + on_notification: function(notifications){ if(this.is_master) { // broadcast to other tabs var last = getItem('bus.last', -1); var max_id = Math.max(last, 0); @@ -199,7 +200,7 @@ var CrossTabBus = bus.Bus.extend({ // notifications changed if(e.key === 'bus.notification'){ var notifs = JSON.parse(value); - _.each(notifs, this.on_notification); + this.on_notification(notifs); } // update channels if(e.key === 'bus.channels'){ diff --git a/addons/im_livechat/static/src/js/im_livechat.js b/addons/im_livechat/static/src/js/im_livechat.js index a9302451a32..9ccb50c10f8 100644 --- a/addons/im_livechat/static/src/js/im_livechat.js +++ b/addons/im_livechat/static/src/js/im_livechat.js @@ -64,14 +64,17 @@ var LivechatButton = Widget.extend({ this.auto_popup_timeout = setTimeout(this.open_chat.bind(this), this.rule.auto_popup_timer*1000); } } - bus.on('notification', this, function (notification) { - if (this.channel && (notification[0] === this.channel.uuid)) { - this.add_message(notification[1]); - this.render_messages(); - if (this.chat_window.folded || !this.chat_window.thread.is_at_bottom()) { - this.chat_window.update_unread(this.chat_window.unread_msgs+1); + bus.on('notification', this, function (notifications) { + var self = this; + _.each(notifications, function (notification) { + if (self.channel && (notification[0] === self.channel.uuid)) { + self.add_message(notification[1]); + self.render_messages(); + if (self.chat_window.folded || !self.chat_window.thread.is_at_bottom()) { + self.chat_window.update_unread(self.chat_window.unread_msgs+1); + } } - } + }); }); return this._super(); }, diff --git a/addons/mail/static/src/js/chat_manager.js b/addons/mail/static/src/js/chat_manager.js index 17462d8f6d4..aff51c721cf 100644 --- a/addons/mail/static/src/js/chat_manager.js +++ b/addons/mail/static/src/js/chat_manager.js @@ -464,21 +464,35 @@ var channel_seen = _.throttle(function (channel) { // Notification handlers // --------------------------------------------------------------------------------- -function on_notification (notification) { - var model = notification[0][1]; - if (model === 'ir.needaction') { - // new message in the inbox - on_needaction_notification(notification[1]); - } else if (model === 'mail.channel') { - // new message in a channel - on_channel_notification(notification[1]); - } else if (model === 'res.partner') { - // channel joined/left, message marked as read/(un)starred, chat open/closed - on_partner_notification(notification[1]); - } else if (model === 'bus.presence') { - // update presence of users - on_presence_notification(notification[1]); +function on_notification (notifications) { + // 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. + var unsubscribed_notif = _.find(notifications, function (notif) { + return notif[1].info === "unsubscribe"; + }); + if (unsubscribed_notif) { + notifications = _.reject(notifications, function (notif) { + return notif[0][1] === "mail.channel" && notif[0][2] === unsubscribed_notif[1].id; + }); } + _.each(notifications, function (notification) { + var model = notification[0][1]; + if (model === 'ir.needaction') { + // new message in the inbox + on_needaction_notification(notification[1]); + } else if (model === 'mail.channel') { + // new message in a channel + on_channel_notification(notification[1]); + } else if (model === 'res.partner') { + // channel joined/left, message marked as read/(un)starred, chat open/closed + on_partner_notification(notification[1]); + } else if (model === 'bus.presence') { + // update presence of users + on_presence_notification(notification[1]); + } + }); } function on_needaction_notification (message) {