diff --git a/CHANGES.md b/CHANGES.md
index cefec9ec7..4f155e0bc 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -4,6 +4,7 @@
- Bugfix: MUC commands were being ignored
- Bugfix: Multiple rooms shown active in the rooms list
+- Bugfix: Don't open chats when receiving messages without a `body`
- UI: Always show the OMEMO lock icon (grayed out if not available).
- Use `publish-options` with `pubsub#access_model` set to `open` when publishing OMEMO public keys and devices
- Add a new `converse-pubsub` plugin, for generic PubSub operations
diff --git a/dist/converse.js b/dist/converse.js
index 687d2b9d7..ea1d84dd8 100644
--- a/dist/converse.js
+++ b/dist/converse.js
@@ -62401,7 +62401,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
'fullname': _.get(_converse.api.contacts.get(contact_jid), 'attributes.fullname') // Get chat box, but only create a new one when the message has a body.
};
- const has_body = sizzle(`body, encrypted[xmlns="${Strophe.NS.OMEMO}"]`).length > 0;
+ const has_body = sizzle(`body, encrypted[xmlns="${Strophe.NS.OMEMO}"]`, stanza).length > 0;
const chatbox = this.getChatBox(contact_jid, attrs, has_body);
if (chatbox && !chatbox.handleMessageCorrection(stanza) && !chatbox.handleReceipt(stanza)) {
diff --git a/spec/chatbox.js b/spec/chatbox.js
index bb0be237f..8472c24ee 100644
--- a/spec/chatbox.js
+++ b/spec/chatbox.js
@@ -140,6 +140,44 @@
done();
}));
+ it("opens when a new message is received", mock.initConverseWithPromises(
+ null, ['rosterGroupsFetched'], {'allow_non_roster_messaging': true},
+ async function (done, _converse) {
+
+ const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
+ const stanza = Strophe.xmlHtmlNode(
+ ""+
+ " Hey\nHave you heard the news?"+
+ "").firstChild;
+
+ const message_promise = new Promise(resolve => _converse.api.listen.on('message', resolve));
+ _converse.connection._dataRecv(test_utils.createRequest(stanza));
+ await test_utils.waitUntil(() => message_promise);
+ expect(_converse.chatboxviews.keys().length).toBe(2);
+ done();
+ }));
+
+ it("doesn't open when a message without body is received", mock.initConverseWithPromises(
+ null, ['rosterGroupsFetched'], {},
+ async function (done, _converse) {
+
+ test_utils.createContacts(_converse, 'current', 1);
+ const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
+ const stanza = Strophe.xmlHtmlNode(`
+
+
+ `).firstChild;
+ const message_promise = new Promise(resolve => _converse.api.listen.on('message', resolve))
+ _converse.connection._dataRecv(test_utils.createRequest(stanza));
+ await test_utils.waitUntil(() => message_promise);
+ expect(_converse.chatboxviews.keys().length).toBe(1);
+ done();
+ }));
+
it("can be trimmed to conserve space",
mock.initConverseWithPromises(null, ['rosterGroupsFetched'], {},
async function (done, _converse) {
diff --git a/src/headless/converse-chatboxes.js b/src/headless/converse-chatboxes.js
index 4bd98bfc9..b70de796f 100644
--- a/src/headless/converse-chatboxes.js
+++ b/src/headless/converse-chatboxes.js
@@ -809,7 +809,7 @@ converse.plugins.add('converse-chatboxes', {
'fullname': _.get(_converse.api.contacts.get(contact_jid), 'attributes.fullname')
}
// Get chat box, but only create a new one when the message has a body.
- const has_body = sizzle(`body, encrypted[xmlns="${Strophe.NS.OMEMO}"]`).length > 0;
+ const has_body = sizzle(`body, encrypted[xmlns="${Strophe.NS.OMEMO}"]`, stanza).length > 0;
const chatbox = this.getChatBox(contact_jid, attrs, has_body);
if (chatbox && !chatbox.handleMessageCorrection(stanza) && !chatbox.handleReceipt(stanza)) {
const msgid = stanza.getAttribute('id'),