[IMP] mail: prevent message loss during connection issue

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) <aku@odoo.com>
This commit is contained in:
Julien Giannone
2019-04-23 12:05:31 +00:00
parent 9b90d8727d
commit e5479fcfdb
4 changed files with 59 additions and 6 deletions
@@ -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();
});
});
},
/**
+3 -1
View File
@@ -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();
});
},
/**
@@ -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();
});
},
/**
+49 -1
View File
@@ -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();
});
});
});