Updates #2781
Only send presence status update when a MUC is entered, and when joining a MUC, include the `<show>` element.
This commit is contained in:
parent
20cd90855f
commit
beb220f188
@ -11,6 +11,7 @@
|
|||||||
- #2733: Fix OMEMO race condition related to automatic reconnection and SMACKS
|
- #2733: Fix OMEMO race condition related to automatic reconnection and SMACKS
|
||||||
- #2733: Wait for decrypted/parsed message before queuing to UI
|
- #2733: Wait for decrypted/parsed message before queuing to UI
|
||||||
- #2751: Media not rendered when Converse runs in a browser extension
|
- #2751: Media not rendered when Converse runs in a browser extension
|
||||||
|
- #2781: Flashing error when connecting to a room
|
||||||
- #2786: Fix webpack configuration not working on Windows OS
|
- #2786: Fix webpack configuration not working on Windows OS
|
||||||
- #2788: `TypeError` when trying to use `@converse/headless`
|
- #2788: `TypeError` when trying to use `@converse/headless`
|
||||||
- #2789: Implement new hook `parseMessageForCommands` for plugins to add custom commands
|
- #2789: Implement new hook `parseMessageForCommands` for plugins to add custom commands
|
||||||
|
@ -175,7 +175,7 @@ const ChatRoomMixin = {
|
|||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
api.send(await this.constructPresence(password));
|
api.send(await this.constructJoinPresence(password));
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -191,7 +191,7 @@ const ChatRoomMixin = {
|
|||||||
return this.join();
|
return this.join();
|
||||||
},
|
},
|
||||||
|
|
||||||
async constructPresence (password) {
|
async constructJoinPresence (password) {
|
||||||
let stanza = $pres({
|
let stanza = $pres({
|
||||||
'id': getUniqueId(),
|
'id': getUniqueId(),
|
||||||
'from': _converse.connection.jid,
|
'from': _converse.connection.jid,
|
||||||
@ -205,6 +205,17 @@ const ChatRoomMixin = {
|
|||||||
if (password) {
|
if (password) {
|
||||||
stanza.cnode(Strophe.xmlElement('password', [], password));
|
stanza.cnode(Strophe.xmlElement('password', [], password));
|
||||||
}
|
}
|
||||||
|
stanza.up(); // Go one level up, out of the `x` element.
|
||||||
|
|
||||||
|
const status = _converse.xmppstatus.get('status');
|
||||||
|
if (['away', 'chat', 'dnd', 'online', 'xa'].includes(status)) {
|
||||||
|
stanza.c('show').t(status).up();
|
||||||
|
}
|
||||||
|
const status_message = _converse.xmppstatus.get('status_message');
|
||||||
|
if (status_message) {
|
||||||
|
stanza.c('status').t(status_message).up();
|
||||||
|
}
|
||||||
|
|
||||||
stanza = await api.hook('constructedMUCPresence', null, stanza);
|
stanza = await api.hook('constructedMUCPresence', null, stanza);
|
||||||
return stanza;
|
return stanza;
|
||||||
},
|
},
|
||||||
@ -271,10 +282,9 @@ const ChatRoomMixin = {
|
|||||||
if (conn_status === roomstatus.ENTERED &&
|
if (conn_status === roomstatus.ENTERED &&
|
||||||
api.settings.get('muc_subscribe_to_rai') &&
|
api.settings.get('muc_subscribe_to_rai') &&
|
||||||
this.getOwnAffiliation() !== 'none') {
|
this.getOwnAffiliation() !== 'none') {
|
||||||
if (conn_status !== roomstatus.DISCONNECTED && conn_status !== roomstatus.CLOSING) {
|
|
||||||
this.sendMarkerForLastMessage('received', true);
|
this.sendMarkerForLastMessage('received', true);
|
||||||
await this.leave();
|
await this.leave();
|
||||||
}
|
|
||||||
this.enableRAI();
|
this.enableRAI();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -869,7 +879,7 @@ const ChatRoomMixin = {
|
|||||||
await new Promise(resolve =>
|
await new Promise(resolve =>
|
||||||
this.features.destroy({
|
this.features.destroy({
|
||||||
'success': resolve,
|
'success': resolve,
|
||||||
'error': (m, e) => { log.error(e); resolve(); }
|
'error': (_, e) => { log.error(e); resolve(); }
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -878,7 +888,7 @@ const ChatRoomMixin = {
|
|||||||
if (disco_entity) {
|
if (disco_entity) {
|
||||||
await new Promise(resolve => disco_entity.destroy({
|
await new Promise(resolve => disco_entity.destroy({
|
||||||
'success': resolve,
|
'success': resolve,
|
||||||
'error': (m, e) => { log.error(e); resolve(); }
|
'error': (_, e) => { log.error(e); resolve(); }
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
u.safeSave(this.session, { 'connection_status': converse.ROOMSTATUS.DISCONNECTED });
|
u.safeSave(this.session, { 'connection_status': converse.ROOMSTATUS.DISCONNECTED });
|
||||||
@ -899,7 +909,7 @@ const ChatRoomMixin = {
|
|||||||
await new Promise(resolve =>
|
await new Promise(resolve =>
|
||||||
this.session.destroy({
|
this.session.destroy({
|
||||||
'success': resolve,
|
'success': resolve,
|
||||||
'error': (m, e) => { log.error(e); resolve(); }
|
'error': (_, e) => { log.error(e); resolve(); }
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
return _converse.ChatBox.prototype.close.call(this);
|
return _converse.ChatBox.prototype.close.call(this);
|
||||||
@ -1918,14 +1928,19 @@ const ChatRoomMixin = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When sending a status update presence (i.e. based on the `<show>`
|
* Sends a status update presence (i.e. based on the `<show>` element)
|
||||||
* element), we need to first make sure that the MUC is connected,
|
|
||||||
* otherwise we will get an error from the MUC service.
|
|
||||||
* @method _converse.ChatRoom#sendStatusPresence
|
* @method _converse.ChatRoom#sendStatusPresence
|
||||||
|
* @param { String } type
|
||||||
|
* @param { String } [status] - An optional status message
|
||||||
|
* @param { Element[]|Strophe.Builder[]|Element|Strophe.Builder } [child_nodes]
|
||||||
|
* Nodes(s) to be added as child nodes of the `presence` XML element.
|
||||||
*/
|
*/
|
||||||
async sendStatusPresence (presence) {
|
async sendStatusPresence (type, status, child_nodes) {
|
||||||
await this.rejoinIfNecessary();
|
if (this.session.get('connection_status') === converse.ROOMSTATUS.ENTERED) {
|
||||||
api.send(presence);
|
const presence = await _converse.xmppstatus.constructPresence(type, this.getRoomJIDAndNick(), status);
|
||||||
|
child_nodes?.map(c => c?.tree() ?? c).forEach(c => presence.cnode(c).up());
|
||||||
|
api.send(presence);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,7 +37,59 @@ describe("Groupchats", function () {
|
|||||||
expect(model.get('num_unread')).toBe(0);
|
expect(model.get('num_unread')).toBe(0);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe("An groupchat", function () {
|
describe("A groupchat", function () {
|
||||||
|
|
||||||
|
it("sends the user status when joining and when it changes",
|
||||||
|
mock.initConverse(['statusInitialized'], {}, async function (_converse) {
|
||||||
|
|
||||||
|
const muc_jid = 'coven@chat.shakespeare.lit';
|
||||||
|
_converse.xmppstatus.set('status', 'away');
|
||||||
|
|
||||||
|
const sent_stanzas = _converse.connection.sent_stanzas;
|
||||||
|
while (sent_stanzas.length) sent_stanzas.pop();
|
||||||
|
|
||||||
|
const muc = await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
|
||||||
|
|
||||||
|
let pres = await u.waitUntil(() => sent_stanzas.filter(s => s.nodeName === 'presence').pop());
|
||||||
|
expect(Strophe.serialize(pres)).toBe(
|
||||||
|
`<presence from="${_converse.jid}" id="${pres.getAttribute('id')}" to="${muc_jid}/romeo" xmlns="jabber:client">`+
|
||||||
|
`<x xmlns="http://jabber.org/protocol/muc"><history maxstanzas="0"/></x>`+
|
||||||
|
`<show>away</show>`+
|
||||||
|
`<c hash="sha-1" node="https://conversejs.org" ver="TfHz9vOOfqIG0Z9lW5CuPaWGnrQ=" xmlns="http://jabber.org/protocol/caps"/>`+
|
||||||
|
`</presence>`);
|
||||||
|
|
||||||
|
expect(muc.getOwnOccupant().get('show')).toBe('away');
|
||||||
|
|
||||||
|
while (sent_stanzas.length) sent_stanzas.pop();
|
||||||
|
|
||||||
|
_converse.xmppstatus.set('status', 'xa');
|
||||||
|
pres = await u.waitUntil(() => sent_stanzas.filter(s => s.nodeName === 'presence').pop());
|
||||||
|
expect(Strophe.serialize(pres)).toBe(
|
||||||
|
`<presence to="${muc_jid}/romeo" xmlns="jabber:client">`+
|
||||||
|
`<show>xa</show>`+
|
||||||
|
`<priority>0</priority>`+
|
||||||
|
`<c hash="sha-1" node="https://conversejs.org" ver="TfHz9vOOfqIG0Z9lW5CuPaWGnrQ=" xmlns="http://jabber.org/protocol/caps"/>`+
|
||||||
|
`</presence>`)
|
||||||
|
|
||||||
|
_converse.xmppstatus.set('status', 'dnd');
|
||||||
|
_converse.xmppstatus.set('status_message', 'Do not disturb');
|
||||||
|
while (sent_stanzas.length) sent_stanzas.pop();
|
||||||
|
|
||||||
|
const muc2_jid = 'cave@chat.shakespeare.lit';
|
||||||
|
const muc2 = await mock.openAndEnterChatRoom(_converse, muc2_jid, 'romeo');
|
||||||
|
|
||||||
|
pres = await u.waitUntil(() => sent_stanzas.filter(s => s.nodeName === 'presence').pop());
|
||||||
|
expect(Strophe.serialize(pres)).toBe(
|
||||||
|
`<presence from="${_converse.jid}" id="${pres.getAttribute('id')}" to="${muc2_jid}/romeo" xmlns="jabber:client">`+
|
||||||
|
`<x xmlns="http://jabber.org/protocol/muc"><history maxstanzas="0"/></x>`+
|
||||||
|
`<show>dnd</show>`+
|
||||||
|
`<status>Do not disturb</status>`+
|
||||||
|
`<c hash="sha-1" node="https://conversejs.org" ver="TfHz9vOOfqIG0Z9lW5CuPaWGnrQ=" xmlns="http://jabber.org/protocol/caps"/>`+
|
||||||
|
`</presence>`);
|
||||||
|
|
||||||
|
expect(muc2.getOwnOccupant().get('show')).toBe('dnd');
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
it("reconnects when no-acceptable error is returned when sending a message",
|
it("reconnects when no-acceptable error is returned when sending a message",
|
||||||
mock.initConverse([], {}, async function (_converse) {
|
mock.initConverse([], {}, async function (_converse) {
|
||||||
@ -87,6 +139,7 @@ describe("Groupchats", function () {
|
|||||||
expect(Strophe.serialize(pres)).toBe(
|
expect(Strophe.serialize(pres)).toBe(
|
||||||
`<presence from="${_converse.jid}" id="${pres.getAttribute('id')}" to="coven@chat.shakespeare.lit/romeo" xmlns="jabber:client">`+
|
`<presence from="${_converse.jid}" id="${pres.getAttribute('id')}" to="coven@chat.shakespeare.lit/romeo" xmlns="jabber:client">`+
|
||||||
`<x xmlns="http://jabber.org/protocol/muc"><history maxstanzas="0"/></x>`+
|
`<x xmlns="http://jabber.org/protocol/muc"><history maxstanzas="0"/></x>`+
|
||||||
|
`<show>online</show>`+
|
||||||
`<c hash="sha-1" node="https://conversejs.org" ver="TfHz9vOOfqIG0Z9lW5CuPaWGnrQ=" xmlns="http://jabber.org/protocol/caps"/>`+
|
`<c hash="sha-1" node="https://conversejs.org" ver="TfHz9vOOfqIG0Z9lW5CuPaWGnrQ=" xmlns="http://jabber.org/protocol/caps"/>`+
|
||||||
`</presence>`);
|
`</presence>`);
|
||||||
}));
|
}));
|
||||||
|
@ -21,18 +21,14 @@ export default {
|
|||||||
if (child_nodes && !Array.isArray(child_nodes)) {
|
if (child_nodes && !Array.isArray(child_nodes)) {
|
||||||
child_nodes = [child_nodes];
|
child_nodes = [child_nodes];
|
||||||
}
|
}
|
||||||
const model= _converse.xmppstatus
|
const model = _converse.xmppstatus
|
||||||
const presence = await model.constructPresence(type, to, status);
|
const presence = await model.constructPresence(type, to, status);
|
||||||
child_nodes?.map(c => c?.tree() ?? c).forEach(c => presence.cnode(c).up());
|
child_nodes?.map(c => c?.tree() ?? c).forEach(c => presence.cnode(c).up());
|
||||||
api.send(presence);
|
api.send(presence);
|
||||||
|
|
||||||
if (['away', 'chat', 'dnd', 'online', 'xa', undefined].includes(type)) {
|
if (['away', 'chat', 'dnd', 'online', 'xa', undefined].includes(type)) {
|
||||||
const mucs = await api.rooms.get();
|
const mucs = await api.rooms.get();
|
||||||
mucs.forEach(async muc => {
|
mucs.forEach(muc => muc.sendStatusPresence(type, status, child_nodes));
|
||||||
const presence = await model.constructPresence(type, muc.getRoomJIDAndNick(), status);
|
|
||||||
child_nodes?.map(c => c?.tree() ?? c).forEach(c => presence.cnode(c).up());
|
|
||||||
muc.sendStatusPresence(presence);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -292,7 +292,11 @@ async function receiveOwnMUCPresence (_converse, muc_jid, nick, affiliation='own
|
|||||||
id: u.getUniqueId()
|
id: u.getUniqueId()
|
||||||
}).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
|
}).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
|
||||||
.c('item').attrs({ affiliation, role, 'jid': _converse.bare_jid }).up()
|
.c('item').attrs({ affiliation, role, 'jid': _converse.bare_jid }).up()
|
||||||
.c('status').attrs({code:'110'});
|
.c('status').attrs({code:'110'}).up().up()
|
||||||
|
|
||||||
|
if (_converse.xmppstatus.get('status')) {
|
||||||
|
presence.c('show').t(_converse.xmppstatus.get('status'));
|
||||||
|
}
|
||||||
_converse.connection._dataRecv(createRequest(presence));
|
_converse.connection._dataRecv(createRequest(presence));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user