Disco API refactoring
This came out of the desire to let `converse-muc` use the API to determine whether MUC is supported. However, we don't know the entity JID before hand and I couldn't think of a good way to query all current and future entities for a feature. So `converse-muc` still does it's own thing without the API, but some refactoring came as a result of attempting.
This commit is contained in:
parent
87213bf90a
commit
a6f2877ed9
|
@ -442,14 +442,19 @@ supports
|
|||
|
||||
Used to determine whether an entity supports a given feature.
|
||||
|
||||
Returns a `Promise` which, when resolved, returns a map/object with keys
|
||||
`supported` (a boolean) and `feature` which is a `Backbone.Model <http://backbonejs.org/#Model>`_.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
converse.plugins.add('myplugin', {
|
||||
initialize: function () {
|
||||
|
||||
_converse.api.disco.supports(_converse.bare_jid, Strophe.NS.MAM).then(
|
||||
function (supported) {
|
||||
if (supported) {
|
||||
function (value) {
|
||||
// `value` is a map with two keys, `supported` and `feature`.
|
||||
|
||||
if (value.supported) {
|
||||
// The feature is supported
|
||||
} else {
|
||||
// The feature is not supported
|
||||
|
|
|
@ -268,7 +268,7 @@
|
|||
.then(this.insertRoster.bind(this))
|
||||
.catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
|
||||
}
|
||||
_converse.emit('controlboxInitialized');
|
||||
_converse.emit('controlboxInitialized', this);
|
||||
},
|
||||
|
||||
render () {
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
define(["converse-core", "sizzle", "strophe.disco"], factory);
|
||||
}(this, function (converse, sizzle) {
|
||||
|
||||
const { Backbone, Promise, Strophe, b64_sha1, _ } = converse.env;
|
||||
const { Backbone, Promise, Strophe, b64_sha1, utils, _ } = converse.env;
|
||||
|
||||
converse.plugins.add('converse-disco', {
|
||||
|
||||
|
@ -49,6 +49,8 @@
|
|||
idAttribute: 'jid',
|
||||
|
||||
initialize () {
|
||||
this.waitUntilFeaturesDiscovered = utils.getResolveablePromise();
|
||||
|
||||
this.features = new Backbone.Collection();
|
||||
this.features.browserStorage = new Backbone.BrowserStorage[_converse.storage](
|
||||
b64_sha1(`converse.features-${this.get('jid')}`)
|
||||
|
@ -60,6 +62,36 @@
|
|||
b64_sha1(`converse.identities-${this.get('jid')}`)
|
||||
);
|
||||
this.fetchFeatures();
|
||||
|
||||
},
|
||||
|
||||
hasFeature (feature) {
|
||||
/* Returns a Promise which resolves with a map indicating
|
||||
* whether a given feature is supported.
|
||||
*
|
||||
* Parameters:
|
||||
* (String) feature - The feature that might be supported.
|
||||
*/
|
||||
const entity = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
function fulfillPromise () {
|
||||
const model = entity.features.findWhere({'var': feature });
|
||||
if (model) {
|
||||
resolve({
|
||||
'supported': true,
|
||||
'feature': model
|
||||
});
|
||||
} else {
|
||||
resolve({
|
||||
'supported': false,
|
||||
'feature': null
|
||||
});
|
||||
}
|
||||
}
|
||||
entity.waitUntilFeaturesDiscovered
|
||||
.then(fulfillPromise)
|
||||
.catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
|
||||
});
|
||||
},
|
||||
|
||||
onFeatureAdded (feature) {
|
||||
|
@ -70,7 +102,13 @@
|
|||
if (this.features.browserStorage.records.length === 0) {
|
||||
this.queryInfo();
|
||||
} else {
|
||||
this.features.fetch({add: true});
|
||||
this.features.fetch({
|
||||
add: true,
|
||||
success: () => {
|
||||
this.waitUntilFeaturesDiscovered.resolve();
|
||||
this.trigger('featuresDiscovered');
|
||||
}
|
||||
});
|
||||
this.identities.fetch({add: true});
|
||||
}
|
||||
},
|
||||
|
@ -105,6 +143,7 @@
|
|||
'from': stanza.getAttribute('from')
|
||||
});
|
||||
});
|
||||
this.waitUntilFeaturesDiscovered.resolve();
|
||||
this.trigger('featuresDiscovered');
|
||||
}
|
||||
});
|
||||
|
@ -182,36 +221,31 @@
|
|||
/* We extend the default converse.js API to add methods specific to service discovery */
|
||||
_.extend(_converse.api, {
|
||||
'disco': {
|
||||
'supports' (entity_jid, feature) {
|
||||
/* Returns a Promise which returns a boolean indicating
|
||||
* whether the feature is supported or by the given
|
||||
* entity or not.
|
||||
'entities': {
|
||||
'get' (entity_jid, create=false) {
|
||||
const entity = _converse.disco_entities.get(entity_jid);
|
||||
if (entity || !create) {
|
||||
return entity;
|
||||
}
|
||||
return _converse.disco_entities.create({'jid': entity_jid});
|
||||
}
|
||||
},
|
||||
|
||||
'supports' (feature, entity_jid) {
|
||||
/* Returns a Promise which resolves with a map indicating
|
||||
* whether a given feature is supported.
|
||||
*
|
||||
* Parameters:
|
||||
* (String) entity_jid - The JID of the entity which might support the feature.
|
||||
* (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'
|
||||
* (String) entity_jid - The JID of the entity which might support the feature.
|
||||
*/
|
||||
return _converse.api.waitUntil('discoInitialized').then(() =>
|
||||
new Promise((resolve, reject) => {
|
||||
function fulfillPromise (entity) {
|
||||
if (entity.features.findWhere({'var': feature})) {
|
||||
resolve(true);
|
||||
} else {
|
||||
resolve(false);
|
||||
}
|
||||
}
|
||||
let entity = _converse.disco_entities.get(entity_jid);
|
||||
if (_.isUndefined(entity)) {
|
||||
entity = _converse.disco_entities.create({'jid': entity_jid});
|
||||
entity.on('featuresDiscovered', _.partial(fulfillPromise, entity));
|
||||
} else {
|
||||
fulfillPromise(entity);
|
||||
}
|
||||
})
|
||||
);
|
||||
return _converse.api.waitUntil('discoInitialized').then(() => {
|
||||
const entity = _converse.api.disco.entities.get(entity_jid, true);
|
||||
return entity.hasFeature(feature);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -57,9 +57,9 @@
|
|||
const { _converse } = this.__super__;
|
||||
this.addSpinner();
|
||||
|
||||
_converse.api.disco.supports(_converse.bare_jid, Strophe.NS.MAM).then(
|
||||
(supported) => { // Success
|
||||
if (supported) {
|
||||
_converse.api.disco.supports(Strophe.NS.MAM, _converse.bare_jid).then(
|
||||
(result) => { // Success
|
||||
if (result.supported) {
|
||||
this.fetchArchivedMessages();
|
||||
} else {
|
||||
this.clearSpinner();
|
||||
|
|
|
@ -175,56 +175,6 @@
|
|||
}
|
||||
},
|
||||
|
||||
featureAdded (feature) {
|
||||
const { _converse } = this.__super__;
|
||||
if ((feature.get('var') === Strophe.NS.MUC) && (_converse.allow_muc)) {
|
||||
this.setMUCDomain(feature.get('from'));
|
||||
}
|
||||
},
|
||||
|
||||
getMUCDomainFromDisco () {
|
||||
/* Check whether service discovery for the user's domain
|
||||
* returned MUC information and use that to automatically
|
||||
* set the MUC domain for the "Rooms" panel of the
|
||||
* controlbox.
|
||||
*/
|
||||
const { _converse } = this.__super__;
|
||||
_converse.api.waitUntil('discoInitialized').then(() => {
|
||||
_converse.api.listen.on('serviceDiscovered', this.featureAdded, this);
|
||||
// Features could have been added before the controlbox was
|
||||
// initialized. We're only interested in MUC
|
||||
const entity = _converse.disco_entities[_converse.domain];
|
||||
if (!_.isUndefined(entity)) {
|
||||
const feature = entity.features.findWhere({'var': Strophe.NS.MUC });
|
||||
if (feature) {
|
||||
this.featureAdded(feature);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
onConnected () {
|
||||
const { _converse } = this.__super__;
|
||||
this.__super__.onConnected.apply(this, arguments);
|
||||
if (!this.model.get('connected')) {
|
||||
return;
|
||||
}
|
||||
if (_.isUndefined(_converse.muc_domain)) {
|
||||
this.getMUCDomainFromDisco();
|
||||
} else {
|
||||
this.setMUCDomain(_converse.muc_domain);
|
||||
}
|
||||
},
|
||||
|
||||
setMUCDomain (domain) {
|
||||
const { _converse } = this.__super__;
|
||||
_converse.muc_domain = domain;
|
||||
this.roomspanel.model.save({'muc_domain': domain});
|
||||
const $server= this.$el.find('input.new-chatroom-server');
|
||||
if (!$server.is(':focus')) {
|
||||
$server.val(this.roomspanel.model.get('muc_domain'));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
ChatBoxViews: {
|
||||
|
@ -2488,6 +2438,7 @@
|
|||
},
|
||||
|
||||
onDomainChange (model) {
|
||||
// TODO: Could instead use the vdom in render
|
||||
const $server = this.$el.find('input.new-chatroom-server');
|
||||
$server.val(model.get('muc_domain'));
|
||||
if (_converse.auto_list_rooms) {
|
||||
|
@ -2858,6 +2809,56 @@
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
function setMUCDomainFromDisco (controlboxview) {
|
||||
/* Check whether service discovery for the user's domain
|
||||
* returned MUC information and use that to automatically
|
||||
* set the MUC domain for the "Rooms" panel of the controlbox.
|
||||
*/
|
||||
function featureAdded (feature) {
|
||||
if ((feature.get('var') === Strophe.NS.MUC)) {
|
||||
setMUCDomain(feature.get('from'), controlboxview);
|
||||
}
|
||||
}
|
||||
|
||||
_converse.api.waitUntil('discoInitialized').then(() => {
|
||||
_converse.api.listen.on('serviceDiscovered', featureAdded);
|
||||
// Features could have been added before the controlbox was
|
||||
// initialized. We're only interested in MUC
|
||||
_converse.disco_entities.each((entity) => {
|
||||
const feature = entity.features.findWhere({'var': Strophe.NS.MUC });
|
||||
if (feature) {
|
||||
featureAdded(feature)
|
||||
}
|
||||
});
|
||||
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
||||
}
|
||||
|
||||
function setMUCDomain (domain, controlboxview) {
|
||||
_converse.muc_domain = domain;
|
||||
controlboxview.roomspanel.model.save({'muc_domain': domain});
|
||||
}
|
||||
|
||||
function fetchAndSetMUCDomain (controlboxview) {
|
||||
if (controlboxview.model.get('connected')) {
|
||||
if (!controlboxview.roomspanel.model.get('muc_domain')) {
|
||||
if (_.isUndefined(_converse.muc_domain)) {
|
||||
setMUCDomainFromDisco(controlboxview);
|
||||
} else {
|
||||
setMUCDomain(_converse.muc_domain, controlboxview);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_converse.on('controlboxInitialized', function (view) {
|
||||
if (!_converse.allow_muc) {
|
||||
return;
|
||||
}
|
||||
fetchAndSetMUCDomain(view);
|
||||
view.model.on('change:connected', _.partial(fetchAndSetMUCDomain, view));
|
||||
});
|
||||
|
||||
function disconnectChatRooms () {
|
||||
/* When disconnecting, or reconnecting, mark all chat rooms as
|
||||
* disconnected, so that they will be properly entered again
|
||||
|
|
Loading…
Reference in New Issue
Block a user