Browse Source

Better service discovery support

Features are saved to localStorage so that service discovery doesn't have to
happen during every request.
JC Brand 12 years ago
parent
commit
e389913444
2 changed files with 62 additions and 38 deletions
  1. 56 33
      converse.js
  2. 6 5
      index.html

+ 56 - 33
converse.js

@@ -718,11 +718,10 @@
             this.on('update-rooms-list', function (ev) {
                 this.updateRoomsList();
             });
-            this.trigger('update-rooms-list');
         },
 
         updateRoomsList: function () {
-            converse.connection.muc.listRooms(converse.muc_domain, $.proxy(function (iq) {
+            converse.connection.muc.listRooms(this.muc_domain, $.proxy(function (iq) {
                 var name, jid, i,
                     rooms = $(iq).find('query').find('item'),
                     rooms_length = rooms.length,
@@ -752,7 +751,7 @@
                 name = input.val().trim().toLowerCase();
                 input.val(''); // Clear the input
                 if (name) {
-                    jid = Strophe.escapeNode(name) + '@' + converse.muc_domain;
+                    jid = Strophe.escapeNode(name) + '@' + this.muc_domain;
                 } else {
                     return;
                 }
@@ -780,8 +779,16 @@
         initialize: function () {
             this.$el.appendTo(converse.chatboxesview.$el);
             this.model.on('change', $.proxy(function (item, changed) {
+                var i;
                 if (_.has(item.changed, 'connected')) {
                     this.render();
+                    converse.features.on('add', $.proxy(this.featureAdded, this));
+                    // Features could have been added before the controlbox was
+                    // initialized. Currently we're only interested in MUC
+                    var feature = converse.features.findWhere({'var': 'http://jabber.org/protocol/muc'});
+                    if (feature) {
+                        this.featureAdded(feature);
+                    }
                 }
                 if (_.has(item.changed, 'visible')) {
                     if (item.changed.visible === true) {
@@ -789,7 +796,6 @@
                     }
                 }
             }, this));
-
             this.model.on('show', this.show, this);
             this.model.on('destroy', this.hide, this);
             this.model.on('hide', this.hide, this);
@@ -798,6 +804,17 @@
             }
         },
 
+        featureAdded: function (feature) {
+            if (feature.get('var') == 'http://jabber.org/protocol/muc') {
+                if (!this.roomspanel) {
+                    this.roomspanel = new converse.RoomsPanel();
+                    this.roomspanel.muc_domain = feature.get('from');
+                    this.roomspanel.$parent = this.$el;
+                    this.roomspanel.render().trigger('update-rooms-list');
+                }
+            }
+        },
+
         template: _.template(
             '<div class="chat-head oc-chat-head">'+
                 '<ul id="controlbox-tabs"></ul>'+
@@ -839,15 +856,6 @@
                 this.contactspanel.render();
             }
             return this;
-        },
-
-        addRoomsPanel: function () {
-            // XXX: We might to ensure that render was already called
-            if (!this.roomspanel) {
-                this.roomspanel = new converse.RoomsPanel();
-                this.roomspanel.$parent = this.$el;
-                this.roomspanel.render();
-            }
         }
     });
 
@@ -1848,34 +1856,50 @@
         }
     });
 
-    converse.ServiceDiscovery = Backbone.Model.extend({
+    converse.Feature = Backbone.Model.extend();
+    converse.Features = Backbone.Collection.extend({
+        /* This collection stores Feature Models, representing features
+         * provided by available XMPP entities (e.g. servers)
+         *
+         * See XEP-0030 for more details: http://xmpp.org/extensions/xep-0030.html
+         */
+        model: converse.Feature,
         initialize: function () {
-            converse.connection.disco.info(converse.domain, null, this.onInfo, this.onError);
-            converse.connection.disco.items(converse.domain, null, $.proxy(this.onItems, this), $.proxy(this.onError, this));
+            this.localStorage = new Backbone.LocalStorage(
+                hex_sha1('converse.features'+converse.bare_jid));
+            if (this.localStorage.records.length === 0) {
+                // localStorage is empty, so we've likely never queried this
+                // domain for features yet
+                converse.connection.disco.info(converse.domain, null, this.onInfo, this.onError);
+                converse.connection.disco.items(converse.domain, null, $.proxy(this.onItems, this), $.proxy(this.onError, this));
+            } else {
+                this.fetch({add:true});
+            }
         },
 
         onItems: function (stanza) {
-            var that = this;
-            $(stanza).find('query item').each(function () {
-                converse.connection.disco.info($(this).attr('jid'), null, that.onInfo, that.onError);
-            });
+            $(stanza).find('query item').each($.proxy(function (idx, item) {
+                converse.connection.disco.info(
+                    $(item).attr('jid'),
+                    null,
+                    $.proxy(this.onInfo, this),
+                    $.proxy(this.onError, this));
+            }, this));
         },
 
         onInfo: function (stanza) {
             var $stanza = $(stanza);
-            if ($(stanza).find('identity[category=conference][type=text]').length < 1) {
+            if (($stanza.find('identity[category=server][type=im]').length === 0) &&
+                ($stanza.find('identity[category=conference][type=text]').length === 0)) {
                 // This isn't an IM server component
                 return;
             }
-            $stanza.find('feature').each(function (idx, feature) {
-                if ($(this).attr('var') == 'http://jabber.org/protocol/muc') {
-                    // This component supports MUC
-                    converse.muc_domain = $stanza.attr('from');
-                    // XXX: It would probably make sense to refactor a
-                    // controlbox to be a Collection of Panel objects
-                    converse.chatboxesview.views.controlbox.addRoomsPanel();
-                }
-            });
+            $stanza.find('feature').each($.proxy(function (idx, feature) {
+                this.create({
+                    'var': $(feature).attr('var'),
+                    'from': $stanza.attr('from')
+                });
+            }, this));
         },
 
         onError: function (stanza) {
@@ -1975,6 +1999,7 @@
                 template.find('form').append(this.bosh_url_input);
             }
             this.$parent.find('#controlbox-panes').append(this.$el.html(template));
+            this.$el.find('input#jid').focus();
             return this;
         }
     });
@@ -2018,9 +2043,7 @@
         this.connection.xmlOutput = function (body) { console.log(body); };
         this.bare_jid = Strophe.getBareJidFromJid(this.connection.jid);
         this.domain = Strophe.getDomainFromJid(this.connection.jid);
-
-        // Sevice discovery
-        this.disco = new this.ServiceDiscovery();
+        this.features = new this.Features();
 
         // Set up the roster
         this.roster = new this.RosterItems();

+ 6 - 5
index.html

@@ -43,18 +43,19 @@
 
     <h2>Features</h2>
     <ul>
-        <li>Single and multi-user chat</li>
+        <li>Single-user chat</li>
+        <li>Multi-user chat in chatrooms (<a href="http://xmpp.org/extensions/xep-0045.html">XEP 45</a>)</li>
+        <li>vCard support (<a href="http://xmpp.org/extensions/xep-0054.html">XEP 54</a>)</li>
+        <li>Service discovery (<a href="http://xmpp.org/extensions/xep-0030.html">XEP 30</a>)</li>
         <li>Contact rosters</li>
         <li>Manually or automically subscribe to other contacts</li>
-        <li>Roster item exchange (<a href="http://xmpp.org/extensions/tmp/xep-0144-1.1.html">XEP 144</a>)</li>
         <li>Accept or decline contact requests</li>
+        <li>Roster item exchange (<a href="http://xmpp.org/extensions/tmp/xep-0144-1.1.html">XEP 144</a>)</li>
         <li>Chat statuses (online, busy, away, offline)</li>
         <li>Custom status messages</li>
         <li>Typing notifications</li>
         <li>Third person messages (/me )</li>
-        <li>Multi-user chat in chatrooms (<a href="http://xmpp.org/extensions/xep-0045.html">XEP 45</a>)</li>
         <li>Chatroom Topics</li>
-        <li>vCard support (<a href="http://xmpp.org/extensions/xep-0054.html">XEP 54</a>)</li>
     </ul>
 
     <h2>CMS Integration</h2>
@@ -76,7 +77,7 @@
 
     <h2>Demo</h2>
     <p><a href="#" class="chat toggle-online-users">Click this link</a> or click the link on the bottom right corner of this page.</a></p>
-    <p>
+    <pbraries/strophe.js>
         You can log in with any existing federated Jabber/XMPP account, or create a new one at any of these providers:
         <ul>
             <li><a href="http://jabber.org" target="_blank">jabber.org</a></li>