diff --git a/CHANGES.md b/CHANGES.md
index 609306610..08e2b3b77 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -15,6 +15,7 @@
- #1306 added option `notification_delay`
- #1312 Error `unrecognized expression` in Safari
- #1316 show version info in login dialog
+- #1317 Don't show errors for CSI messages
- #1318 added values 'on' and 'off' for 'trusted' option which removes the "This is a trusted device" checkbox from the login form
- #1319 Implement sending of presences according to XEP-0319: Last User Interaction in Presence
diff --git a/dist/converse.js b/dist/converse.js
index ba78980a3..5d3856eb4 100644
--- a/dist/converse.js
+++ b/dist/converse.js
@@ -71131,6 +71131,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
*/
if (_converse.send_chat_state_notifications && this.get('chat_state')) {
_converse.api.send($msg({
+ 'id': _converse.connection.getUniqueId(),
'to': this.get('jid'),
'type': 'chat'
}).c(this.get('chat_state'), {
@@ -71395,6 +71396,27 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
return true;
}
+ 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.
+ // We assume that this was a CSI message (which we don't store).
+ // See https://github.com/conversejs/converse.js/issues/1317
+ return;
+ }
+ } else {
+ // An error message without id likely means that we
+ // sent a message without id (which shouldn't happen).
+ _converse.log('Received an error message without id attribute!', Strophe.LogLevel.ERROR);
+
+ _converse.log(message, Strophe.LogLevel.ERROR);
+ }
+
chatbox.createMessage(message, message);
return true;
},
diff --git a/spec/messages.js b/spec/messages.js
index 5a18f6411..163aad72b 100644
--- a/spec/messages.js
+++ b/spec/messages.js
@@ -1620,6 +1620,44 @@
expect(chat_content.querySelectorAll('.chat-error').length).toEqual(3);
done();
}));
+
+ it("will not show to the user an error message for a CSI message",
+ mock.initConverseWithPromises(
+ null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
+ async function (done, _converse) {
+
+ // See #1317
+ // https://github.com/conversejs/converse.js/issues/1317
+ test_utils.createContacts(_converse, 'current');
+ _converse.emit('rosterContactsFetched');
+ test_utils.openControlBox();
+
+ const contact_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost';
+ await test_utils.openChatBoxFor(_converse, contact_jid);
+
+ const messages = _converse.connection.sent_stanzas.filter(s => s.nodeName === 'message');
+ expect(messages.length).toBe(1);
+ expect(Strophe.serialize(messages[0])).toBe(
+ ``+
+ ``+
+ ``+
+ ``+
+ ``);
+
+ const stanza = $msg({
+ 'from': contact_jid,
+ 'type': 'error',
+ 'id': messages[0].getAttribute('id')
+ }).c('error', {'type': 'cancel', 'code': '503'})
+ .c('service-unavailable', { 'xmlns': 'urn:ietf:params:xml:ns:xmpp-stanzas' }).up()
+ .c('text', { 'xmlns': 'urn:ietf:params:xml:ns:xmpp-stanzas' })
+ .t('User session not found')
+ _converse.connection._dataRecv(test_utils.createRequest(stanza));
+ const view = _converse.chatboxviews.get(contact_jid);
+ const chat_content = view.el.querySelector('.chat-content');
+ expect(chat_content.querySelectorAll('.chat-error').length).toEqual(0);
+ done();
+ }));
});
diff --git a/src/converse-message-view.js b/src/converse-message-view.js
index 8cd942206..16e1cae10 100644
--- a/src/converse-message-view.js
+++ b/src/converse-message-view.js
@@ -168,10 +168,10 @@ converse.plugins.add('converse-message-view', {
renderErrorMessage () {
const moment_time = moment(this.model.get('time')),
msg = u.stringToElement(
- tpl_info(_.extend(this.model.toJSON(), {
- 'extra_classes': 'chat-error',
- 'isodate': moment_time.format()
- })));
+ tpl_info(_.extend(this.model.toJSON(), {
+ 'extra_classes': 'chat-error',
+ 'isodate': moment_time.format()
+ })));
return this.replaceElement(msg);
},
diff --git a/src/headless/converse-chatboxes.js b/src/headless/converse-chatboxes.js
index cf69d0db7..987e15900 100644
--- a/src/headless/converse-chatboxes.js
+++ b/src/headless/converse-chatboxes.js
@@ -427,10 +427,13 @@ converse.plugins.add('converse-chatboxes', {
*/
if (_converse.send_chat_state_notifications && this.get('chat_state')) {
_converse.api.send(
- $msg({'to':this.get('jid'), 'type': 'chat'})
- .c(this.get('chat_state'), {'xmlns': Strophe.NS.CHATSTATES}).up()
- .c('no-store', {'xmlns': Strophe.NS.HINTS}).up()
- .c('no-permanent-store', {'xmlns': Strophe.NS.HINTS})
+ $msg({
+ 'id': _converse.connection.getUniqueId(),
+ 'to': this.get('jid'),
+ 'type': 'chat'
+ }).c(this.get('chat_state'), {'xmlns': Strophe.NS.CHATSTATES}).up()
+ .c('no-store', {'xmlns': Strophe.NS.HINTS}).up()
+ .c('no-permanent-store', {'xmlns': Strophe.NS.HINTS})
);
}
},
@@ -666,6 +669,21 @@ converse.plugins.add('converse-chatboxes', {
if (!chatbox) {
return true;
}
+ 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.
+ // We assume that this was a CSI message (which we don't store).
+ // See https://github.com/conversejs/converse.js/issues/1317
+ return;
+ }
+ } else {
+ // An error message without id likely means that we
+ // sent a message without id (which shouldn't happen).
+ _converse.log('Received an error message without id attribute!', Strophe.LogLevel.ERROR);
+ _converse.log(message, Strophe.LogLevel.ERROR);
+ }
chatbox.createMessage(message, message);
return true;
},
diff --git a/tests/mock.js b/tests/mock.js
index 191fabfe7..5ff6a2c03 100644
--- a/tests/mock.js
+++ b/tests/mock.js
@@ -111,17 +111,29 @@
mock.mock_connection = function () { // eslint-disable-line wrap-iife
return function () {
Strophe.Bosh.prototype._processRequest = function () {}; // Don't attempt to send out stanzas
- var c = new Strophe.Connection('jasmine tests');
- var sendIQ = c.sendIQ;
+ const c = new Strophe.Connection('jasmine tests');
+ const sendIQ = c.sendIQ;
c.IQ_stanzas = [];
c.IQ_ids = [];
c.sendIQ = function (iq, callback, errback) {
this.IQ_stanzas.push(iq);
- var id = sendIQ.bind(this)(iq, callback, errback);
+ const id = sendIQ.bind(this)(iq, callback, errback);
this.IQ_ids.push(id);
return id;
}
+
+ const send = c.send;
+ c.sent_stanzas = [];
+ c.send = function (stanza) {
+ if (_.isElement(stanza)) {
+ this.sent_stanzas.push(stanza);
+ } else {
+ this.sent_stanzas.push(stanza.nodeTree);
+ }
+ return send.apply(this, arguments);
+ }
+
c.features = Strophe.xmlHtmlNode(
''+
''+