diff --git a/addons/mail/static/src/js/services/mail_window_manager.js b/addons/mail/static/src/js/services/mail_window_manager.js index de614ba705f..79ea668e55e 100644 --- a/addons/mail/static/src/js/services/mail_window_manager.js +++ b/addons/mail/static/src/js/services/mail_window_manager.js @@ -641,7 +641,7 @@ MailManager.include({ */ _onNewChannel: function (channel) { if (channel.isDetached()) { - this.openThreadWindow(channel.getID(), { keepFoldState: true }); + this.openThreadWindow(channel.getID(), { keepFoldState: true, passively: true }); } else { this._closeThreadWindow(channel.getID()); } diff --git a/addons/mail/static/src/js/thread_windows/abstract_thread_window.js b/addons/mail/static/src/js/thread_windows/abstract_thread_window.js index 8a8bf3a0077..801a8166787 100644 --- a/addons/mail/static/src/js/thread_windows/abstract_thread_window.js +++ b/addons/mail/static/src/js/thread_windows/abstract_thread_window.js @@ -349,6 +349,16 @@ var AbstractThreadWindow = Widget.extend({ } return this._thread.getID(); }, + /** + * Tells whether there is focus on this thread. Note that a thread that has + * the focus means the input has focus. + * + * @private + * @returns {boolean} + */ + _hasFocus: function () { + return this.$input.is(':focus'); + }, /** * Post a message on this thread window, and auto-scroll to the bottom of * the thread. diff --git a/addons/mail/static/src/js/thread_windows/thread_window.js b/addons/mail/static/src/js/thread_windows/thread_window.js index 20c0965205e..86cb3419eb9 100644 --- a/addons/mail/static/src/js/thread_windows/thread_window.js +++ b/addons/mail/static/src/js/thread_windows/thread_window.js @@ -164,11 +164,11 @@ var ThreadWindow = AbstractThreadWindow.extend({ * should scroll to the bottom if it was at the bottom before update * @param {boolean} [options.passively=false] if set, this thread window * becomes passive, so that it is marked as read only when the focus is - * on it. + * on it. Ignore this option if the focus is already on the thread window. */ update: function (options) { var self = this; - if (options.passively) { + if (options.passively && !this._hasFocus()) { this._setPassive(); } var bottomVisible = !this.isFolded() && diff --git a/addons/mail/static/tests/thread_window/basic_thread_window_tests.js b/addons/mail/static/tests/thread_window/basic_thread_window_tests.js index 347682e68df..f05fd367697 100644 --- a/addons/mail/static/tests/thread_window/basic_thread_window_tests.js +++ b/addons/mail/static/tests/thread_window/basic_thread_window_tests.js @@ -235,6 +235,124 @@ QUnit.test('do not increase unread counter when receiving message with myself as parent.destroy(); }); +QUnit.test('do not increment unread counter with focus on thread window', function (assert) { + // 'hard' focus means that the user has clicked on the thread window in + // order to set the focus on it. + assert.expect(2); + + var parent = this.createParent({ + data: this.data, + services: this.services, + session: { partner_id: 3 } + }); + + // get channel instance to link to thread window + var channel = parent.call('mail_service', 'getChannel', 1); + channel.detach(); + + assert.strictEqual(channel.getUnreadCounter(), 0, + "thread should have unread counter to 0 initially"); + + // hard focus on thread window composer + $('.o_composer_text_field').click(); + + // simulate receiving message from someone else + var messageData = { + author_id: [5, "Someone else"], + body: "

Test message

", + id: 2, + model: 'mail.channel', + res_id: 1, + channel_ids: [1], + }; + var notification = [[false, 'mail.channel', 1], messageData]; + parent.call('bus_service', 'trigger', 'notification', [notification]); + + assert.strictEqual(channel.getUnreadCounter(), 0, + "thread should not have incremented its unread counter after receiving the message"); + + parent.destroy(); +}); + +QUnit.test('do not mark as read the newly open thread window from received message', function (assert) { + assert.expect(5); + + this.data['mail.channel'] = { + fields: { + name: { + string: "Name", + type: "char", + required: true, + }, + channel_type: { + string: "Channel Type", + type: "selection", + }, + channel_message_ids: { + string: "Messages", + type: "many2many", + relation: 'mail.message' + }, + message_unread_counter: { + string: "Amount of Unread Messages", + type: "integer" + }, + }, + records: [{ + id: 2, + name: "DM", + channel_type: "chat", + message_unread_counter: 0, + }], + }; + + var parent = this.createParent({ + data: this.data, + services: this.services, + session: { partner_id: 3 }, + mockRPC: function (route, args) { + if (args.method === 'channel_join_and_get_info') { + this.data['mail.channel'].records[0].state = 'open'; + this.data['mail.channel'].records[0].is_minimized = true; + return $.when(this.data['mail.channel'].records[0]); + } + return this._super.apply(this, arguments); + }, + }); + + assert.strictEqual($('.o_thread_window').length, 0, + "no thread window should be open initially"); + + // simulate receiving message from someone else in DM + var messageData = { + author_id: [5, "Someone else"], + body: "

Test message

", + id: 2, + model: 'mail.channel', + res_id: 1, + channel_ids: [2], + }; + var notification = [[false, 'mail.channel', 1], messageData]; + // Unread counter is obtained from fetched channel data, because this is + // a new message from a new channel. + this.data['mail.channel'].records[0].message_unread_counter++; + parent.call('bus_service', 'trigger', 'notification', [notification]); + + var $threadWindow = $('.o_thread_window'); + assert.strictEqual($threadWindow.length, 1, + "a thread window should be open after receiving a new message on a new DM chat"); + assert.strictEqual($threadWindow.data('thread-id'), 2, + "open thread window should be related to DM chat"); + assert.strictEqual($threadWindow.find('.o_thread_window_title').text().replace(/\s/g, ''), '#DM(1)', + "open DM chat window should have one unread message"); + + $threadWindow.find('.o_thread_composer').click(); + assert.strictEqual($threadWindow.find('.o_thread_window_title').text().replace(/\s/g, ''), '#DM', + "open DM chat window should have message marked as read on composer focus"); + + parent.destroy(); +}); + }); }); });