diff --git a/dist/converse.js b/dist/converse.js index 5d3856eb4..ffa8b9fd1 100644 --- a/dist/converse.js +++ b/dist/converse.js @@ -71399,14 +71399,16 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha const id = message.getAttribute('id'); if (id) { - const msg = chatbox.messages.findWhere({ + const msgs = chatbox.messages.where({ 'msgid': id }); - if (!msg) { - // This error refers to a message not included in our store. + if (!msgs.length || msgs.filter(m => m.get('type') === 'error').length) { + // If the error refers to a message not included in our store. // We assume that this was a CSI message (which we don't store). // See https://github.com/conversejs/converse.js/issues/1317 + // + // We also ignore duplicate error messages. return; } } else { diff --git a/spec/messages.js b/spec/messages.js index 163aad72b..6364bf701 100644 --- a/spec/messages.js +++ b/spec/messages.js @@ -1564,8 +1564,8 @@ */ let stanza = $msg({ 'to': _converse.connection.jid, - 'type':'error', - 'id':'82bc02ce-9651-4336-baf0-fa04762ed8d2', + 'type': 'error', + 'id': '82bc02ce-9651-4336-baf0-fa04762ed8d2', 'from': sender_jid }) .c('error', {'type': 'cancel'}) @@ -1577,8 +1577,8 @@ expect(chat_content.querySelector('.chat-error').textContent).toEqual(error_txt); stanza = $msg({ 'to': _converse.connection.jid, - 'type':'error', - 'id':'some-other-unused-id', + 'type': 'error', + 'id': '6fcdeee3-000f-4ce8-a17e-9ce28f0ae104', 'from': sender_jid }) .c('error', {'type': 'cancel'}) @@ -1589,12 +1589,11 @@ await test_utils.waitUntil(() => view.model.messages.length > 1); expect(chat_content.querySelectorAll('.chat-error').length).toEqual(2); - // If the last message is already an error message, - // then we don't render it another time. + // We don't render duplicates stanza = $msg({ 'to': _converse.connection.jid, 'type':'error', - 'id':'another-unused-id', + 'id': '6fcdeee3-000f-4ce8-a17e-9ce28f0ae104', 'from': sender_jid }) .c('error', {'type': 'cancel'}) @@ -1604,11 +1603,28 @@ _converse.connection._dataRecv(test_utils.createRequest(stanza)); await test_utils.waitUntil(() => view.model.messages.length > 2); expect(chat_content.querySelectorAll('.chat-error').length).toEqual(2); + + // We send another message, for which an error will + // not be received, to test that errors appear + // after the relevant message. + msg_text = 'This message will be sent, and also receive an error'; + message = view.model.messages.create({ + 'msgid': 'another-id', + 'fullname': fullname, + 'sender': 'me', + 'time': moment().format(), + 'message': msg_text + }); + view.model.sendMessage(message); + await new Promise((resolve, reject) => view.once('messageInserted', resolve)); + msg_txt = sizzle('.chat-msg:last .chat-msg__text', chat_content).pop().textContent; + expect(msg_txt).toEqual(msg_text); + // A different error message will however render stanza = $msg({ 'to': _converse.connection.jid, 'type':'error', - 'id':'another-id', + 'id': 'another-id', 'from': sender_jid }) .c('error', {'type': 'cancel'}) diff --git a/src/headless/converse-chatboxes.js b/src/headless/converse-chatboxes.js index 987e15900..567b9429e 100644 --- a/src/headless/converse-chatboxes.js +++ b/src/headless/converse-chatboxes.js @@ -671,11 +671,13 @@ converse.plugins.add('converse-chatboxes', { } const id = message.getAttribute('id'); if (id) { - const msg = chatbox.messages.findWhere({'msgid': id}); - if (!msg) { - // This error refers to a message not included in our store. + const msgs = chatbox.messages.where({'msgid': id}); + if (!msgs.length || msgs.filter(m => m.get('type') === 'error').length) { + // If the error refers to a message not included in our store. // We assume that this was a CSI message (which we don't store). // See https://github.com/conversejs/converse.js/issues/1317 + // + // We also ignore duplicate error messages. return; } } else {