[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.
This commit is contained in:
Géry Debongnie
2016-01-20 14:41:34 +01:00
parent b395ade078
commit 8af3841cb2
3 changed files with 50 additions and 32 deletions
+12 -11
View File
@@ -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'){
@@ -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();
},
+28 -14
View File
@@ -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) {