From e5479fcfdb76bdbf9301fb140d873483bafdb9e4 Mon Sep 17 00:00:00 2001 From: Julien Giannone Date: Thu, 4 Apr 2019 09:09:57 +0000 Subject: [PATCH] [IMP] mail: prevent message loss during connection issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before the changes, when a message was posted (on Discuss or in the chat window), the composer was cleared directly as it didn't wait for the rpc response. If there was latency or a connection loss, the message disappeared from the composer but took time to appear in the content window or didn't appear at all and was lost. Now, the composer waits for the rpc response and then is cleared. Task #1957856 closes odoo/odoo#32422 Signed-off-by: Alexandre Kühn (aku) --- .../static/src/js/composers/basic_composer.js | 7 +-- addons/mail/static/src/js/discuss.js | 4 +- .../thread_windows/abstract_thread_window.js | 4 +- addons/mail/static/tests/discuss_tests.js | 50 ++++++++++++++++++- 4 files changed, 59 insertions(+), 6 deletions(-) diff --git a/addons/mail/static/src/js/composers/basic_composer.js b/addons/mail/static/src/js/composers/basic_composer.js index 72936152ae5..c84296d55d1 100644 --- a/addons/mail/static/src/js/composers/basic_composer.js +++ b/addons/mail/static/src/js/composers/basic_composer.js @@ -510,9 +510,10 @@ var BasicComposer = Widget.extend({ clearTimeout(this._cannedTimeout); var self = this; this._preprocessMessage().then(function (message) { - self.trigger('post_message', message); - self._clearComposerOnSend(); - self.$input.focus(); + self.trigger('post_message', message, function() { + self._clearComposerOnSend(); + self.$input.focus(); + }); }); }, /** diff --git a/addons/mail/static/src/js/discuss.js b/addons/mail/static/src/js/discuss.js index 4e88434f86d..8acd52d99c2 100644 --- a/addons/mail/static/src/js/discuss.js +++ b/addons/mail/static/src/js/discuss.js @@ -1461,8 +1461,9 @@ var Discuss = AbstractAction.extend({ /** * @private * @param {Object} messageData + * @param {Function} callback */ - _onPostMessage: function (messageData) { + _onPostMessage: function (messageData, callback) { var self = this; var options = {}; if (this._selectedMessage) { @@ -1483,6 +1484,7 @@ var Discuss = AbstractAction.extend({ } else { self._threadWidget.scrollToBottom(); } + callback(); }); }, /** 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 f09b78b8d3f..0af2d1080db 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 @@ -394,8 +394,9 @@ var AbstractThreadWindow = Widget.extend({ * * @private * @param {Object} messageData + * @param {Function} callback */ - _postMessage: function (messageData) { + _postMessage: function (messageData, callback) { var self = this; if (!this.hasThread()) { return; @@ -403,6 +404,7 @@ var AbstractThreadWindow = Widget.extend({ this._thread.postMessage(messageData) .then(function () { self._threadWidget.scrollToBottom(); + callback(); }); }, /** diff --git a/addons/mail/static/tests/discuss_tests.js b/addons/mail/static/tests/discuss_tests.js index f25c7082648..daf34b4a5be 100644 --- a/addons/mail/static/tests/discuss_tests.js +++ b/addons/mail/static/tests/discuss_tests.js @@ -3,7 +3,6 @@ odoo.define('mail.discuss_test', function (require) { var mailTestUtils = require('mail.testUtils'); -var concurrency = require('web.concurrency'); var testUtils = require('web.test_utils'); var createDiscuss = mailTestUtils.createDiscuss; @@ -1491,5 +1490,54 @@ QUnit.test('custom-named DM conversation', async function (assert) { discuss.destroy(); }); +QUnit.test('input not cleared on unresolved message_post rpc', async function (assert) { + assert.expect(2); + + // Promise to simulate late server response on message post + var messagePostPromise = testUtils.makeTestPromise(); + + this.data.initMessaging = { + channel_slots: { + channel_channel: [{ + id: 1, + channel_type: "channel", + name: "general", + }], + }, + }; + + var discuss = await createDiscuss({ + id: 1, + context: {}, + params: {}, + data: this.data, + services: this.services, + mockRPC: function (route, args) { + if (args.method === 'message_post') { + return messagePostPromise; + } + return this._super.apply(this, arguments); + }, + }); + + // Click on channel 'general' + var $general = discuss.$('.o_mail_discuss_sidebar').find('.o_mail_discuss_item[data-thread-id=1]'); + await testUtils.dom.click($general); + + // Type message + var $input = discuss.$('textarea.o_composer_text_field').first(); + $input.focus(); + $input.val('test message'); + + // Send message + await testUtils.fields.triggerKeydown($input, 'enter'); + assert.strictEqual($input.val(), 'test message', "composer should not be cleared on send without server response"); + + // Simulate server response + messagePostPromise.resolve(); + await testUtils.nextTick(); + assert.strictEqual($input.val(), '', "composer should be cleared on send after server response"); + discuss.destroy(); +}); }); });