Commit f2ac9ef4 authored by JC Brand's avatar JC Brand

converse-muc: Support for XEP-0410 to check whether we're joined

parent 68d4a71c
# Changelog
## 5.0.0 (Unreleased)
- Support for XEP-0410 to check whether we're still present in a room
- Initial support for the [CredentialsContainer](https://developer.mozilla.org/en-US/docs/Web/API/CredentialsContainer) web API
- Allow for synchronous events. When a synchronous event is fired, Converse will
wait for all promises returned by the event's handlers to finish before continuing.
......
......@@ -13716,8 +13716,8 @@
}
},
"strophe.js": {
"version": "github:strophe/strophejs#bc8a6b62203a17ada6bd78945c993c6f7dccd1de",
"from": "github:strophe/strophejs#bc8a6b62203a17ada6bd78945c993c6f7dccd1de"
"version": "github:strophe/strophejs#c675bcfcf44527ba1cf844a1aaa68fe7003c6140",
"from": "github:strophe/strophejs#c675bcfcf44527ba1cf844a1aaa68fe7003c6140"
},
"style-loader": {
"version": "0.23.1",
......
......@@ -401,6 +401,11 @@ converse.plugins.add('converse-chatboxes', {
}
},
shouldShowErrorMessage () {
// Gets overridden in ChatRoom
return true;
},
/**
* If the passed in `message` stanza contains an
* [XEP-0308](https://xmpp.org/extensions/xep-0308.html#usecase)
......@@ -987,11 +992,10 @@ converse.plugins.add('converse-chatboxes', {
// We also ignore duplicate error messages.
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);
}
const should_show = await chatbox.shouldShowErrorMessage(message);
if (!should_show) {
return;
}
const attrs = await chatbox.getMessageAttributesFromStanza(message, message);
chatbox.messages.create(attrs);
......
......@@ -1350,7 +1350,7 @@ _converse.initialize = async function (settings, callback) {
}
} else if (reconnecting) {
this.autoLogin();
} else if (window.PasswordCredential) {
} else if (!isTestEnv() && window.PasswordCredential) {
const creds = await navigator.credentials.get({'password': true});
if (creds && creds.type == 'password' && u.isValidJID(creds.id)) {
setUserJID(creds.id);
......@@ -1514,7 +1514,7 @@ _converse.api = {
* @returns {string} The current user's full JID (Jabber ID)
* @example _converse.api.user.jid())
*/
'jid' () {
jid () {
return _converse.connection.jid;
},
......@@ -1577,19 +1577,20 @@ _converse.api = {
*/
_converse.api.trigger('logout');
},
/**
* Set and get the user's chat status, also called their *availability*.
*
* @namespace _converse.api.user.status
* @memberOf _converse.api.user
*/
'status': {
status: {
/** Return the current user's availability status.
*
* @method _converse.api.user.status.get
* @example _converse.api.user.status.get();
*/
'get' () {
get () {
return _converse.xmppstatus.get('status');
},
/**
......@@ -1602,7 +1603,7 @@ _converse.api = {
* @example this._converse.api.user.status.set('dnd');
* @example this._converse.api.user.status.set('dnd', 'In a meeting');
*/
'set' (value, message) {
set (value, message) {
const data = {'status': value};
if (!_.includes(Object.keys(_converse.STATUS_WEIGHTS), value)) {
throw new Error('Invalid availability value. See https://xmpp.org/rfcs/rfc3921.html#rfc.section.2.2.2.1');
......@@ -1626,7 +1627,7 @@ _converse.api = {
* @returns {string} The status message
* @example const message = _converse.api.user.status.message.get()
*/
'get' () {
get () {
return _converse.xmppstatus.get('status_message');
},
/**
......@@ -1634,7 +1635,7 @@ _converse.api = {
* @param {string} status The status message
* @example _converse.api.user.status.message.set('In a meeting');
*/
'set' (status) {
set (status) {
_converse.xmppstatus.save({'status_message': status});
}
}
......
......@@ -1224,9 +1224,66 @@ converse.plugins.add('converse-muc', {
return attrs;
},
/**
* Send a MUC-0410 MUC Self-Ping stanza to room to determine
* whether we're still joined.
* @async
* @private
* @method _converse.ChatRoom#isJoined
* @returns {Promise<boolean>}
*/
async isJoined () {
const ping = $iq({
'to': `${this.get('jid')}/${this.get('nick')}`,
'type': "get"
}).c("ping", {'xmlns': Strophe.NS.PING});
let result;
try {
result = await _converse.api.sendIQ(ping);
} catch (e) {
const sel = `error[type="cancel"] not-acceptable[xmlns="${Strophe.NS.STANZAS}"]`;
if (_.isElement(e) && sizzle(sel, e).length) {
return false;
}
}
return true;
},
/**
* Check whether we're still joined and re-join if not
* @async
* @private
* @method _converse.ChatRoom#rejoinIfNecessary
*/
async rejoinIfNecessary () {
const is_joined = await this.isJoined();
if (!is_joined) {
this.save('connection_status', converse.ROOMSTATUS.DISCONNECTED);
this.enterRoom();
return true;
}
},
/**
* @async
* @private
* @method _converse.ChatRoom#shouldShowErrorMessage
* @returns {Promise<boolean>}
*/
async shouldShowErrorMessage (stanza) {
if (sizzle(`not-acceptable[xmlns="${Strophe.NS.STANZAS}"]`, stanza).length) {
if (await this.rejoinIfNecessary()) {
return false;
}
}
return true;
},
getErrorMessage (stanza) {
if (sizzle(`forbidden[xmlns="${Strophe.NS.STANZAS}"]`, stanza).length) {
return __("Your message was not delivered because you're not allowed to send messages in this groupchat.");
} else if (sizzle(`not-acceptable[xmlns="${Strophe.NS.STANZAS}"]`, stanza).length) {
return __("Your message was not delivered because you're not present in the groupchat.");
} else {
return _converse.ChatBox.prototype.getErrorMessage.apply(this, arguments);
}
......
......@@ -29,7 +29,7 @@
"jed": "1.1.1",
"lodash": "^4.17.11",
"pluggable.js": "2.0.1",
"strophe.js": "strophe/strophejs#bc8a6b62203a17ada6bd78945c993c6f7dccd1de",
"strophe.js": "strophe/strophejs#c675bcfcf44527ba1cf844a1aaa68fe7003c6140",
"twemoji": "^11.0.1",
"urijs": "^1.19.1"
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment