Commit 17e0e70e authored by JC Brand's avatar JC Brand

Support for XEP-0203 delayed delivery of presence stanzas

parent 40605607
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
* Templates are no longer stored as attributes on the `_converse` object. * Templates are no longer stored as attributes on the `_converse` object.
If you need a particular template, use `require` to load it. If you need a particular template, use `require` to load it.
- Better support for delayed delivery of presence stanzas (XEP-0203). [jcbrand]
- The chat room `description` is now shown in the heading, not the `subject`. - The chat room `description` is now shown in the heading, not the `subject`.
[jcbrand] [jcbrand]
- Chat room features are shown in the sidebar. [jcbrand] - Chat room features are shown in the sidebar. [jcbrand]
......
This diff is collapsed.
...@@ -177,6 +177,7 @@ ...@@ -177,6 +177,7 @@
Strophe.addNamespace('NICK', 'http://jabber.org/protocol/nick'); Strophe.addNamespace('NICK', 'http://jabber.org/protocol/nick');
Strophe.addNamespace('HINTS', 'urn:xmpp:hints'); Strophe.addNamespace('HINTS', 'urn:xmpp:hints');
Strophe.addNamespace('PUBSUB', 'http://jabber.org/protocol/pubsub'); Strophe.addNamespace('PUBSUB', 'http://jabber.org/protocol/pubsub');
Strophe.addNamespace('DELAY', 'urn:xmpp:delay');
// Instance level constants // Instance level constants
this.TIMEOUTS = { // Set as module attr so that we can override in tests. this.TIMEOUTS = { // Set as module attr so that we can override in tests.
...@@ -855,22 +856,44 @@ ...@@ -855,22 +856,44 @@
return this; return this;
}, },
addResource: function (resource, priority, chat_status) { addResource: function (presence) {
var resources = this.get('resources'); /* Adds a new resource and it's associated attributes as taken
if (!_.isObject(resources)) { resources = {}; } * from the passed in presence stanza.
*
* Also updates the contact's chat_status if the presence has
* higher priority (and is newer).
*/
var jid = presence.getAttribute('from'),
chat_status = _.propertyOf(presence.querySelector('show'))('textContent') || 'online',
resource = Strophe.getResourceFromJid(jid),
priority = _.propertyOf(presence.querySelector('priority'))('textContent') || 0,
delay = presence.querySelector('delay[xmlns="'+Strophe.NS.DELAY+'"]'),
timestamp = _.isNull(delay) ? moment().format() : moment(delay.getAttribute('stamp')).format();
priority = _.isNaN(parseInt(priority, 10)) ? 0 : parseInt(priority, 10);
var resources = _.isObject(this.get('resources')) ? this.get('resources') : {};
resources[resource] = { resources[resource] = {
'priority': _.isNaN(parseInt(priority, 10)) ? 0 : parseInt(priority, 10), 'priority': priority,
'status': chat_status, 'status': chat_status,
'timestamp': moment().format() 'timestamp': timestamp
}; };
this.set({'resources': resources}); var changed = {'resources': resources};
var hpr = this.getHighestPriorityResource();
if (priority == hpr.priority && timestamp == hpr.timestamp) {
// Only set the chat status if this is the newest resource
// with the highest priority
changed.chat_status = chat_status;
}
this.save(changed);
return resources; return resources;
}, },
removeResource: function (resource) { removeResource: function (resource) {
/* Remove the passed in resource from the contact's resources /* Remove the passed in resource from the contact's resources map.
* map. *
* Return the amount of resources left over. * Also recomputes the chat_status given that there's one less
* resource.
*/ */
var resources = this.get('resources'); var resources = this.get('resources');
if (!_.isObject(resources)) { if (!_.isObject(resources)) {
...@@ -878,13 +901,15 @@ ...@@ -878,13 +901,15 @@
} else { } else {
delete resources[resource]; delete resources[resource];
} }
this.save({'resources': resources}); this.save({
return _.size(resources); 'resources': resources,
'chat_status': _.propertyOf(
this.getHighestPriorityResource())('status') || 'offline'
});
}, },
getHighestPriorityStatus: function () { getHighestPriorityResource: function () {
/* Return the chat status assigned to the resource with the /* Return the resource with the highest priority.
* highest priority.
* *
* If multiple resources have the same priority, take the * If multiple resources have the same priority, take the
* newest one. * newest one.
...@@ -897,10 +922,9 @@ ...@@ -897,10 +922,9 @@
_.reverse _.reverse
)(resources)[0]; )(resources)[0];
if (!_.isUndefined(val)) { if (!_.isUndefined(val)) {
return val.status; return val;
} }
} }
return 'offline';
}, },
removeFromRoster: function (callback) { removeFromRoster: function (callback) {
...@@ -1225,7 +1249,6 @@ ...@@ -1225,7 +1249,6 @@
resource = Strophe.getResourceFromJid(jid), resource = Strophe.getResourceFromJid(jid),
chat_status = _.propertyOf(presence.querySelector('show'))('textContent') || 'online', chat_status = _.propertyOf(presence.querySelector('show'))('textContent') || 'online',
status_message = _.propertyOf(presence.querySelector('status'))('textContent'), status_message = _.propertyOf(presence.querySelector('status'))('textContent'),
priority = _.propertyOf(presence.querySelector('priority'))('textContent') || 0,
contact = this.get(bare_jid); contact = this.get(bare_jid);
if (this.isSelf(bare_jid)) { if (this.isSelf(bare_jid)) {
...@@ -1258,14 +1281,9 @@ ...@@ -1258,14 +1281,9 @@
this.handleIncomingSubscription(presence); this.handleIncomingSubscription(presence);
} else if (presence_type === 'unavailable' && contact) { } else if (presence_type === 'unavailable' && contact) {
contact.removeResource(resource); contact.removeResource(resource);
contact.save({'chat_status': contact.getHighestPriorityStatus()}); } else if (contact) {
} else if (contact) { // presence_type is undefined // presence_type is undefined
var resources = contact.addResource(resource, priority, chat_status); contact.addResource(presence);
if (priority >= _.flow(_.values, _.partial(_.map, _, 'priority'), _.max)(resources)) {
// Only save if it's the resource with the highest
// priority
contact.save({'chat_status': chat_status});
}
} }
} }
}); });
......
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