Commit 2526d804 authored by JC Brand's avatar JC Brand

Change `api.disco.supports` to resolve to a Boolean

Also add a new API method `api.disco.features.get` for the use-case
where you still want the feature object to be returned.
parent 9f1ee118
......@@ -11,6 +11,7 @@
- Message deduplication bugfixes and improvements
- Continuously retry (in 2s intervals) to fetch login credentials (via [credentials_url](https://conversejs.org/docs/html/configuration.html#credentials-url)) in case of failure
- Replace `moment` with [DayJS](https://github.com/iamkun/dayjs).
- New API method [\_converse.api.disco.features.get](https://conversejs.org/docs/html/api/-_converse.api.disco.features.html#.get)
- #1296: `embedded` view mode shows `chatbox-navback` arrow in header
- #1532: Converse reloads on enter pressed in the filter box
- #1550: Legitimate carbons being blocked due to erroneous forgery check
......@@ -19,6 +20,8 @@
- **Breaking changes**:
- Rename `muc_disable_moderator_commands` to [muc_disable_slash_commands](https://conversejs.org/docs/html/configuration.html#muc-disable-slash-commands).
- `_converse.api.archive.query` now returns a Promise instead of accepting a callback functions.
- `_converse.api.disco.supports` now returns a Promise which resolves to a Boolean instead of an Array.
### API changes
......
This diff is collapsed.
......@@ -57,7 +57,7 @@
'var': 'http://jabber.org/protocol/disco#items'});
_converse.connection._dataRecv(test_utils.createRequest(stanza));
const entities = await _converse.api.disco.entities.get();
let entities = await _converse.api.disco.entities.get();
expect(entities.length).toBe(2);
expect(_.includes(entities.pluck('jid'), 'localhost')).toBe(true);
expect(_.includes(entities.pluck('jid'), 'dummy@localhost')).toBe(true);
......@@ -85,7 +85,7 @@
stanza = _.find(IQ_stanzas, function (iq) {
return iq.nodeTree.querySelector('iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#items"]');
});
var items_IQ_id = IQ_ids[IQ_stanzas.indexOf(stanza)];
const items_IQ_id = IQ_ids[IQ_stanzas.indexOf(stanza)];
stanza = $iq({
'type': 'result',
'from': 'localhost',
......@@ -155,17 +155,15 @@
.c('value').t('5242880');
_converse.connection._dataRecv(test_utils.createRequest(stanza));
_converse.api.disco.entities.get().then(function (entities) {
expect(entities.get('localhost').items.get('upload.localhost').identities.where({'category': 'store'}).length).toBe(1);
_converse.api.disco.supports(Strophe.NS.HTTPUPLOAD, _converse.domain).then(
function (result) {
expect(result.length).toBe(1);
expect(result[0].get('jid')).toBe('upload.localhost');
expect(result[0].dataforms.where({'FORM_TYPE': {value: "urn:xmpp:http:upload:0", type: "hidden"}}).length).toBe(1);
done();
}
);
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
entities = await _converse.api.disco.entities.get();
expect(entities.get('localhost').items.get('upload.localhost').identities.where({'category': 'store'}).length).toBe(1);
const supported = await _converse.api.disco.supports(Strophe.NS.HTTPUPLOAD, _converse.domain);
expect(supported).toBe(true);
const features = await _converse.api.disco.features.get(Strophe.NS.HTTPUPLOAD, _converse.domain);
expect(features.length).toBe(1);
expect(features[0].get('jid')).toBe('upload.localhost');
expect(features[0].dataforms.where({'FORM_TYPE': {value: "urn:xmpp:http:upload:0", type: "hidden"}}).length).toBe(1);
done();
}));
});
......@@ -553,7 +551,7 @@
_converse.connection._dataRecv(test_utils.createRequest(stanza));
entities = await _converse.api.disco.entities.get();
expect(entities.get('localhost').items.get('upload.localhost').identities.where({'category': 'store'}).length).toBe(1);
const result = await _converse.api.disco.supports(Strophe.NS.HTTPUPLOAD, _converse.domain);
await _converse.api.disco.supports(Strophe.NS.HTTPUPLOAD, _converse.domain);
test_utils.createContacts(_converse, 'current');
_converse.api.trigger('rosterContactsFetched');
......
......@@ -356,7 +356,7 @@ converse.plugins.add('converse-bookmarks', {
onBookmarksReceivedError (deferred, iq) {
window.sessionStorage.setItem(this.fetched_flag, true);
_converse.log('Error while fetching bookmarks', Strophe.LogLevel.WARN);
_converse.log('Error while fetching bookmarks', Strophe.LogLevel.ERROR);
_converse.log(iq.outerHTML, Strophe.LogLevel.DEBUG);
if (!_.isNil(deferred)) {
if (iq.querySelector('error[type="cancel"] item-not-found')) {
......@@ -552,8 +552,7 @@ converse.plugins.add('converse-bookmarks', {
if (_converse.allow_public_bookmarks) {
return !!identity;
} else {
const supported = await _converse.api.disco.supports(Strophe.NS.PUBSUB+'#publish-options', _converse.bare_jid);
return !!supported.length;
return _converse.api.disco.supports(Strophe.NS.PUBSUB+'#publish-options', _converse.bare_jid);
}
}
......
......@@ -461,8 +461,7 @@ converse.plugins.add('converse-chatview', {
},
async addFileUploadButton (options) {
const result = await _converse.api.disco.supports(Strophe.NS.HTTPUPLOAD, _converse.domain);
if (result.length) {
if (await _converse.api.disco.supports(Strophe.NS.HTTPUPLOAD, _converse.domain)) {
this.el.querySelector('.chat-toolbar').insertAdjacentHTML(
'beforeend',
tpl_toolbar_fileupload({'tooltip_upload_file': __('Choose a file to send')}));
......@@ -483,10 +482,11 @@ converse.plugins.add('converse-chatview', {
}
const results = await Promise.all(
this.model.presence.resources.map(
res => _converse.api.disco.supports(Strophe.NS.SPOILER, `${contact_jid}/${res.get('name')}`)
r => _converse.api.disco.supports(Strophe.NS.SPOILER, `${contact_jid}/${r.get('name')}`)
)
);
if (_.filter(results, 'length').length) {
const all_resources_support_spolers = results.reduce((acc, val) => (acc && val), true);
if (all_resources_support_spolers) {
const html = tpl_spoiler_button(this.model.toJSON());
if (_converse.visible_toolbar_buttons.emoji) {
this.el.querySelector('.toggle-smiley').insertAdjacentHTML('afterEnd', html);
......
......@@ -39,9 +39,11 @@ converse.plugins.add('converse-mam-views', {
/* Fetches messages that might have been archived *after*
* the last archived message in our local cache.
*/
if (this.disable_mam) { return; }
const { _converse } = this.__super__,
most_recent_msg = u.getMostRecentMessage(this.model);
if (this.disable_mam) {
return;
}
const { _converse } = this.__super__;
const most_recent_msg = u.getMostRecentMessage(this.model);
if (_.isNil(most_recent_msg)) {
this.fetchArchivedMessages();
......@@ -94,8 +96,7 @@ converse.plugins.add('converse-mam-views', {
mam_jid = _converse.bare_jid;
message_handler = _converse.chatboxes.onMessage.bind(_converse.chatboxes)
}
const supported = await _converse.api.disco.supports(Strophe.NS.MAM, mam_jid);
if (!supported.length) {
if (!(await _converse.api.disco.supports(Strophe.NS.MAM, mam_jid))) {
return;
}
this.addSpinner();
......
......@@ -34,8 +34,7 @@ converse.plugins.add('converse-push', {
if (!push_app_server.jid) {
return;
}
const result = await _converse.api.disco.supports(Strophe.NS.PUSH, domain || _converse.bare_jid)
if (!result.length) {
if (!(await _converse.api.disco.supports(Strophe.NS.PUSH, domain || _converse.bare_jid))) {
return _converse.log(
`Not disabling push app server "${push_app_server.jid}", no disco support from your server.`,
Strophe.LogLevel.WARN
......@@ -74,7 +73,7 @@ converse.plugins.add('converse-push', {
_converse.api.disco.supports(Strophe.NS.PUSH, push_app_server.jid),
_converse.api.disco.supports(Strophe.NS.PUSH, domain)
]);
if (!result[0].length && !result[1].length) {
if (!result[0] && !result[1]) {
return _converse.log(
`Not enabling push app server "${push_app_server.jid}", no disco support from your server.`,
Strophe.LogLevel.WARN
......
......@@ -383,8 +383,7 @@ converse.plugins.add('converse-chatboxes', {
return false;
}
const by_jid = stanza_id.getAttribute('by');
const result = await _converse.api.disco.supports(Strophe.NS.SID, by_jid);
if (!result.length) {
if (!(await _converse.api.disco.supports(Strophe.NS.SID, by_jid))) {
return false;
}
const query = {};
......@@ -607,9 +606,8 @@ converse.plugins.add('converse-chatboxes', {
async sendFiles (files) {
const result = await _converse.api.disco.supports(Strophe.NS.HTTPUPLOAD, _converse.domain),
item = result.pop();
const result = await _converse.api.disco.features.get(Strophe.NS.HTTPUPLOAD, _converse.domain);
const item = result.pop();
if (!item) {
this.messages.create({
'message': __("Sorry, looks like file upload is not supported by your server."),
......@@ -617,7 +615,6 @@ converse.plugins.add('converse-chatboxes', {
});
return;
}
const data = item.dataforms.where({'FORM_TYPE': {'value': Strophe.NS.HTTPUPLOAD, 'type': "hidden"}}).pop(),
max_file_size = window.parseInt(_.get(data, 'attributes.max-file-size.value')),
slot_request_url = _.get(item, 'id');
......
......@@ -550,6 +550,44 @@ converse.plugins.add('converse-disco', {
}
},
/**
* @namespace _converse.api.disco.features
* @memberOf _converse.api.disco
*/
'features': {
/**
* Return a given feature of a disco entity
*
* @method _converse.api.disco.features.get
* @param {string} feature The feature that might be
* supported. In the XML stanza, this is the `var`
* attribute of the `<feature>` element. For
* example: `http://jabber.org/protocol/muc`
* @param {string} jid The JID of the entity
* (and its associated items) which should be queried
* @returns {promise} A promise which resolves with a list containing
* _converse.Entity instances representing the entity
* itself or those items associated with the entity if
* they support the given feature.
* @example
* _converse.api.disco.features.get(Strophe.NS.MAM, _converse.bare_jid);
*/
async 'get' (feature, jid) {
if (_.isNil(jid)) {
throw new TypeError('You need to provide an entity JID');
}
await _converse.api.waitUntil('discoInitialized');
let entity = await _converse.api.disco.entities.get(jid, true);
entity = await entity.waitUntilFeaturesDiscovered;
const promises = _.concat(
entity.items.map(item => item.hasFeature(feature)),
entity.hasFeature(feature)
);
const result = await Promise.all(promises);
return f.filter(f.isObject, result);
},
},
/**
* Used to determine whether an entity supports a given feature.
*
......@@ -560,40 +598,17 @@ converse.plugins.add('converse-disco', {
* example: `http://jabber.org/protocol/muc`
* @param {string} jid The JID of the entity
* (and its associated items) which should be queried
* @returns {promise} A promise which resolves with a list containing
* _converse.Entity instances representing the entity
* itself or those items associated with the entity if
* they support the given feature.
*
* @returns {promise} A promise which resolves with `true` or `false`.
* @example
* _converse.api.disco.supports(Strophe.NS.MAM, _converse.bare_jid)
* .then(value => {
* // `value` is a map with two keys, `supported` and `feature`.
* if (value.supported) {
* // The feature is supported
* } else {
* // The feature is not supported
* }
* }).catch(() => {
* _converse.log(
* "Error or timeout while checking for feature support",
* Strophe.LogLevel.ERROR
* );
* });
* if (await _converse.api.disco.supports(Strophe.NS.MAM, _converse.bare_jid)) {
* // The feature is supported
* } else {
* // The feature is not supported
* }
*/
async 'supports' (feature, jid) {
if (_.isNil(jid)) {
throw new TypeError('api.disco.supports: You need to provide an entity JID');
}
await _converse.api.waitUntil('discoInitialized');
let entity = await _converse.api.disco.entities.get(jid, true);
entity = await entity.waitUntilFeaturesDiscovered;
const promises = _.concat(
entity.items.map(item => item.hasFeature(feature)),
entity.hasFeature(feature)
);
const result = await Promise.all(promises);
return f.filter(f.isObject, result);
const features = await _converse.api.disco.features.get(feature, jid);
return features.length > 0;
},
/**
......
......@@ -41,7 +41,7 @@ converse.plugins.add('converse-mam', {
}
const by_jid = stanza.getAttribute('from') || this.get('jid');
const supported = await _converse.api.disco.supports(Strophe.NS.MAM, by_jid);
if (!supported.length) {
if (!supported) {
return null;
}
const query = {};
......@@ -341,11 +341,9 @@ converse.plugins.add('converse-mam', {
const jid = attrs.to || _converse.bare_jid;
const supported = await _converse.api.disco.supports(Strophe.NS.MAM, jid);
if (!supported.length) {
if (!supported) {
_converse.log(`Did not fetch MAM archive for ${jid} because it doesn't support ${Strophe.NS.MAM}`);
return {
'messages': []
};
return {'messages': []};
}
const queryid = _converse.connection.getUniqueId();
......
......@@ -236,8 +236,7 @@ converse.plugins.add('converse-muc', {
_converse.auto_register_muc_nickname &&
!this.get('reserved_nick')) {
const result = await _converse.api.disco.supports(Strophe.NS.MUC_REGISTER, this.get('jid'));
if (result.length) {
if (await _converse.api.disco.supports(Strophe.NS.MUC_REGISTER, this.get('jid'))) {
this.registerNickname()
}
}
......
......@@ -59,8 +59,7 @@ converse.plugins.add('converse-pubsub', {
if (options) {
jid = jid || _converse.bare_jid;
const result = await _converse.api.disco.supports(Strophe.NS.PUBSUB + '#publish-options', jid);
if (result.length) {
if (await _converse.api.disco.supports(Strophe.NS.PUBSUB + '#publish-options', jid)) {
stanza.c('publish-options')
.c('x', {'xmlns': Strophe.NS.XFORM, 'type': 'submit'})
.c('field', {'var': 'FORM_TYPE', 'type': 'hidden'})
......
......@@ -33599,9 +33599,8 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
}
const by_jid = stanza_id.getAttribute('by');
const result = await _converse.api.disco.supports(Strophe.NS.SID, by_jid);
if (!result.length) {
if (!(await _converse.api.disco.supports(Strophe.NS.SID, by_jid))) {
return false;
}
......@@ -33887,8 +33886,8 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
},
async sendFiles(files) {
const result = await _converse.api.disco.supports(Strophe.NS.HTTPUPLOAD, _converse.domain),
item = result.pop();
const result = await _converse.api.disco.features.get(Strophe.NS.HTTPUPLOAD, _converse.domain);
const item = result.pop();
if (!item) {
this.messages.create({
......@@ -37310,6 +37309,45 @@ _converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins.add('converse-dis
},
/**
* @namespace _converse.api.disco.features
* @memberOf _converse.api.disco
*/
'features': {
/**
* Return a given feature of a disco entity
*
* @method _converse.api.disco.features.get
* @param {string} feature The feature that might be
* supported. In the XML stanza, this is the `var`
* attribute of the `<feature>` element. For
* example: `http://jabber.org/protocol/muc`
* @param {string} jid The JID of the entity
* (and its associated items) which should be queried
* @returns {promise} A promise which resolves with a list containing
* _converse.Entity instances representing the entity
* itself or those items associated with the entity if
* they support the given feature.
* @example
* _converse.api.disco.features.get(Strophe.NS.MAM, _converse.bare_jid);
*/
async 'get'(feature, jid) {
if (_.isNil(jid)) {
throw new TypeError('You need to provide an entity JID');
}
await _converse.api.waitUntil('discoInitialized');
let entity = await _converse.api.disco.entities.get(jid, true);
entity = await entity.waitUntilFeaturesDiscovered;
const promises = _.concat(entity.items.map(item => item.hasFeature(feature)), entity.hasFeature(feature));
const result = await Promise.all(promises);
return f.filter(f.isObject, result);
}
},
/**
* Used to determine whether an entity supports a given feature.
*
......@@ -37320,40 +37358,17 @@ _converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins.add('converse-dis
* example: `http://jabber.org/protocol/muc`
* @param {string} jid The JID of the entity
* (and its associated items) which should be queried
* @returns {promise} A promise which resolves with a list containing
* _converse.Entity instances representing the entity
* itself or those items associated with the entity if
* they support the given feature.
*
* @returns {promise} A promise which resolves with `true` or `false`.
* @example
* _converse.api.disco.supports(Strophe.NS.MAM, _converse.bare_jid)
* .then(value => {
* // `value` is a map with two keys, `supported` and `feature`.
* if (value.supported) {
* // The feature is supported
* } else {
* // The feature is not supported
* }
* }).catch(() => {
* _converse.log(
* "Error or timeout while checking for feature support",
* Strophe.LogLevel.ERROR
* );
* });
* if (await _converse.api.disco.supports(Strophe.NS.MAM, _converse.bare_jid)) {
* // The feature is supported
* } else {
* // The feature is not supported
* }
*/
async 'supports'(feature, jid) {
if (_.isNil(jid)) {
throw new TypeError('api.disco.supports: You need to provide an entity JID');
}
await _converse.api.waitUntil('discoInitialized');
let entity = await _converse.api.disco.entities.get(jid, true);
entity = await entity.waitUntilFeaturesDiscovered;
const promises = _.concat(entity.items.map(item => item.hasFeature(feature)), entity.hasFeature(feature));
const result = await Promise.all(promises);
return f.filter(f.isObject, result);
const features = await _converse.api.disco.features.get(feature, jid);
return features.length > 0;
},
/**
......@@ -37524,7 +37539,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
const by_jid = stanza.getAttribute('from') || this.get('jid');
const supported = await _converse.api.disco.supports(Strophe.NS.MAM, by_jid);
if (!supported.length) {
if (!supported) {
return null;
}
......@@ -37847,7 +37862,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
const jid = attrs.to || _converse.bare_jid;
const supported = await _converse.api.disco.supports(Strophe.NS.MAM, jid);
if (!supported.length) {
if (!supported) {
_converse.log(`Did not fetch MAM archive for ${jid} because it doesn't support ${Strophe.NS.MAM}`);
return {
......@@ -38214,9 +38229,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_3__["default"].plugins.add('converse-muc
async onConnectionStatusChanged() {
if (this.get('connection_status') === _converse_core__WEBPACK_IMPORTED_MODULE_3__["default"].ROOMSTATUS.ENTERED && _converse.auto_register_muc_nickname && !this.get('reserved_nick')) {
const result = await _converse.api.disco.supports(Strophe.NS.MUC_REGISTER, this.get('jid'));
if (result.length) {
if (await _converse.api.disco.supports(Strophe.NS.MUC_REGISTER, this.get('jid'))) {
this.registerNickname();
}
}
......@@ -40078,9 +40091,8 @@ _converse_core__WEBPACK_IMPORTED_MODULE_1__["default"].plugins.add('converse-pub
if (options) {
jid = jid || _converse.bare_jid;
const result = await _converse.api.disco.supports(Strophe.NS.PUBSUB + '#publish-options', jid);
if (result.length) {
if (await _converse.api.disco.supports(Strophe.NS.PUBSUB + '#publish-options', jid)) {
stanza.c('publish-options').c('x', {
'xmlns': Strophe.NS.XFORM,
'type': 'submit'
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