瀏覽代碼

Merge branch 'master' into gh-pages

Conflicts:
	index.html
JC Brand 12 年之前
父節點
當前提交
1f772f4691
共有 10 個文件被更改,包括 625 次插入109 次删除
  1. 7 0
      CHANGES.rst
  2. 3 4
      Gruntfile.js
  3. 111 95
      converse.js
  4. 0 0
      converse.min.css
  5. 0 0
      converse.min.js
  6. 3 3
      index.html
  7. 486 0
      locale/en/LC_MESSAGES/converse.po
  8. 1 1
      package.json
  9. 13 4
      spec/MainSpec.js
  10. 1 2
      tests_main.js

+ 7 - 0
CHANGES.rst

@@ -1,6 +1,13 @@
 Changelog
 =========
 
+0.5.1 (Unreleased)
+------------------
+
+- #13, #14: Messages sent between to GTalk accounts weren't being received. [jcbrand]
+- #32: Default status was offline when user didn't have contacts. [jcbrand]
+- Attach panels to the DOM upon initialize. [jcbrand]
+
 0.5.0 (2013-07-30)
 ------------------
 

+ 3 - 4
Gruntfile.js

@@ -25,7 +25,7 @@ module.exports = function(grunt) {
                         "*/"
             },
             minify: {
-                dest: 'converse-'+cfg.version+'.min.css',
+                dest: 'converse.min.css',
                 src: ['converse.css']
             }
         },
@@ -34,7 +34,7 @@ module.exports = function(grunt) {
                 options: {
                     baseUrl: ".",
                     name: "main",
-                    out: "converse-"+cfg.version+".min.js",
+                    out: "converse.min.js",
                     paths: {
                         "require": "components/requirejs/require",
                         "jquery": "components/jquery/jquery",
@@ -106,8 +106,7 @@ module.exports = function(grunt) {
         });
     });
 
-    // TODO: update CHANGES.txt with release date
-    grunt.registerTask('release', 'Create a new release', ['requirejs', 'cssmin']);
+    grunt.registerTask('minify', 'Create a new release', ['requirejs', 'cssmin']);
 
     grunt.registerTask('check', 'Perform all checks (e.g. before releasing)', function () {
         grunt.task.run('jshint', 'test');

+ 111 - 95
converse.js

@@ -381,7 +381,7 @@
                         return;
                     }
                 }
-                var message = $msg({from: converse.bare_jid, to: bare_jid, type: 'chat', id: timestamp})
+                var message = $msg({from: converse.connection.jid, to: bare_jid, type: 'chat', id: timestamp})
                     .c('body').t(text).up()
                     .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'});
                 // Forward the message, so that other connected resources are also aware of it.
@@ -628,15 +628,20 @@
                 '<li>'
             ),
 
+            initialize: function (cfg) {
+                cfg.$parent.append(this.$el);
+                this.$tabs = cfg.$parent.parent().find('#controlbox-tabs');
+            },
+
             render: function () {
                 var markup;
-                this.$parent.find('#controlbox-tabs').append(this.tab_template());
-                this.$parent.find('#controlbox-panes').append(this.$el.html(this.template()));
+                this.$tabs.append(this.tab_template());
                 if (converse.xhr_user_search) {
                     markup = this.search_contact_template();
                 } else {
                     markup = this.add_contact_template();
                 }
+                this.$el.html(this.template());
                 this.$el.find('.search-xmpp ul').append(markup);
                 this.$el.append(converse.rosterview.$el);
                 return this;
@@ -788,18 +793,15 @@
                 '</form>'+
                 '<dl id="available-chatrooms"></dl>'),
 
-            render: function () {
-                this.$parent.find('#controlbox-tabs').append(this.tab_template());
-                this.$parent.find('#controlbox-panes').append(
+            initialize: function (cfg) {
+                cfg.$parent.append(
                     this.$el.html(
                         this.template({
                             server_input_type: converse.hide_muc_server && 'hidden' || 'text'
                         })
                     ).hide());
-                return this;
-            },
+                this.$tabs = cfg.$parent.parent().find('#controlbox-tabs');
 
-            initialize: function () {
                 this.on('update-rooms-list', function (ev) {
                     this.updateRoomsList();
                 });
@@ -814,6 +816,11 @@
                 }, this));
             },
 
+            render: function () {
+                this.$tabs.append(this.tab_template());
+                return this;
+            },
+
             informNoRoomsFound: function () {
                 var $available_chatrooms = this.$el.find('#available-chatrooms');
                 // # For translators: %1$s is a variable and will be replaced with the XMPP server name
@@ -1030,35 +1037,18 @@
             },
 
             render: function () {
-                this.$el.html(this.template(this.model.toJSON()));
                 if ((!converse.prebind) && (!converse.connection)) {
                     // Add login panel if the user still has to authenticate
-                    this.loginpanel = new converse.LoginPanel();
-                    this.loginpanel.$parent = this.$el;
+                    this.$el.html(this.template(this.model.toJSON()));
+                    this.loginpanel = new converse.LoginPanel({'$parent': this.$el.find('#controlbox-panes')});
                     this.loginpanel.render();
-                } else {
-                    this.contactspanel = new converse.ContactsPanel();
-                    this.contactspanel.$parent = this.$el;
+                } else if (!this.contactspanel) {
+                    this.$el.html(this.template(this.model.toJSON()));
+                    this.contactspanel = new converse.ContactsPanel({'$parent': this.$el.find('#controlbox-panes')});
                     this.contactspanel.render();
-                    converse.xmppstatus = new converse.XMPPStatus();
-                    converse.xmppstatus.localStorage = new Backbone.LocalStorage(
-                        hex_sha1('converse.xmppstatus-'+converse.bare_jid));
-                    converse.xmppstatus.fetch({
-                        success: function (xmppstatus, resp) {
-                            if (!xmppstatus.get('fullname')) {
-                                converse.getVCard(
-                                    null, // No 'to' attr when getting one's own vCard
-                                    function (jid, fullname, image, image_type, url) {
-                                        converse.xmppstatus.save({'fullname': fullname});
-                                    }
-                                );
-                            }
-                        }
-                    });
                     converse.xmppstatusview = new converse.XMPPStatusView({'model': converse.xmppstatus});
                     converse.xmppstatusview.render();
-                    this.roomspanel = new converse.RoomsPanel();
-                    this.roomspanel.$parent = this.$el;
+                    this.roomspanel = new converse.RoomsPanel({'$parent': this.$el.find('#controlbox-panes')});
                     this.roomspanel.render();
                 }
                 return this;
@@ -2024,7 +2014,7 @@
                     item;
 
                 if (this.isSelf(bare_jid)) {
-                    if ((converse.connection.jid !== jid)&&(presence_type !== 'unavailabe')) {
+                    if ((converse.connection.jid !== jid)&&(presence_type !== 'unavailable')) {
                         // Another resource has changed it's status, we'll update ours as well.
                         // FIXME: We should ideally differentiate between converse.js using
                         // resources and other resources (i.e Pidgin etc.)
@@ -2122,8 +2112,20 @@
                 this.model.on("destroy", function (item) { this.removeRosterItem(item); }, this);
 
                 this.$el.hide().html(this.template());
-                this.model.fetch({add: true}); // Get the cached roster items from localstorage
-                // XXX: is this necessary? this.initialSort();
+                this.model.fetch({
+                    add: true,
+                    success: function (model, resp, options) {
+                        if (resp.length === 0) {
+                            // The presence stanza is sent out once all
+                            // roster contacts have been added and rendered.
+                            // See RosterView's render method.
+                            //
+                            // If there aren't any roster contacts, we still
+                            // want to send a presence stanza, so we do it here.
+                            converse.xmppstatus.sendPresence();
+                        }
+                    },
+                }); // Get the cached roster items from localstorage
             },
 
             updateChatBox: function (item, changed) {
@@ -2190,9 +2192,8 @@
                         // options where all of the items are offline and now we can show the rosterView
                         item.set('sorted', true);
                         this.initialSort();
-                        this.$el.show(function () {
-                            converse.xmppstatus.initStatus();
-                        });
+                        this.$el.show();
+                        converse.xmppstatus.sendPresence();
                     }
                 }
                 // Hide the headings if there are no contacts under them
@@ -2223,22 +2224,24 @@
         this.XMPPStatus = Backbone.Model.extend({
             initialize: function () {
                 this.set({
-                    'status' : this.get('status'),
-                    'status_message' : this.get('status_message'),
-                    'fullname' : this.get('fullname')
+                    'status' : this.get('status') || 'online',
                 });
-            },
-
-            initStatus: function () {
-                var stat = this.get('status');
-                if (stat === undefined) {
-                    stat = 'online';
-                    this.save({status: stat});
-                }
-                this.sendPresence(stat);
+                this.on('change', $.proxy(function () {
+                    if (this.get('fullname') === undefined) {
+                        converse.getVCard(
+                            null, // No 'to' attr when getting one's own vCard
+                            $.proxy(function (jid, fullname, image, image_type, url) {
+                                this.save({'fullname': fullname});
+                            }, this)
+                        );
+                    }
+                }, this));
             },
 
             sendPresence: function (type) {
+                if (type === undefined) {
+                    type = this.get('status') || 'online';
+                }
                 var status_message = this.get('status_message'),
                     presence;
                 // Most of these presence types are actually not explicitly sent,
@@ -2385,7 +2388,7 @@
                 this.$el.html(this.choose_template());
                 this.$el.find('#fancy-xmpp-status-select')
                         .html(this.status_template({
-                            'status_message': __("I am %1$s", this.getPrettyStatus(chat_status)),
+                            'status_message': this.model.get('status_message') || __("I am %1$s", this.getPrettyStatus(chat_status)),
                             'chat_status': chat_status
                             }));
                 // iterate through all the <option> elements and add option values
@@ -2506,6 +2509,17 @@
                 }, this));
             },
 
+            initialize: function (cfg) {
+                cfg.$parent.append(this.$el.html(this.template()));
+                this.$tabs = cfg.$parent.parent().find('#controlbox-tabs');
+            },
+
+            render: function () {
+                this.$tabs.append(this.tab_template());
+                this.$el.find('input#jid').focus();
+                return this;
+            },
+
             authenticate: function (ev) {
                 ev.preventDefault();
                 var $form = $(ev.target),
@@ -2537,19 +2551,8 @@
             },
 
             remove: function () {
-                this.$parent.find('#controlbox-tabs').empty();
-                this.$parent.find('#controlbox-panes').empty();
-            },
-
-            render: function () {
-                this.$parent.find('#controlbox-tabs').append(this.tab_template());
-                var template = this.template();
-                if (! this.bosh_url_input) {
-                    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;
+                this.$tabs.empty();
+                this.$el.parent().empty();
             }
         });
 
@@ -2590,14 +2593,15 @@
             }
         };
 
-        this.onConnected = function (connection) {
-            this.connection = connection;
-            this.connection.xmlInput = function (body) { console.log(body); };
-            this.connection.xmlOutput = function (body) { console.log(body); };
-            this.bare_jid = Strophe.getBareJidFromJid(this.connection.jid);
-            this.domain = Strophe.getDomainFromJid(this.connection.jid);
-            this.features = new this.Features();
+        this.initStatus = function (callback) {
+            this.xmppstatus = new this.XMPPStatus();
+            var id = hex_sha1('converse.xmppstatus-'+this.bare_jid);
+            this.xmppstatus.id = id; // This appears to be necessary for backbone.localStorage
+            this.xmppstatus.localStorage = new Backbone.LocalStorage(id);
+            this.xmppstatus.fetch({success: callback, error: callback});
+        };
 
+        this.initRoster = function () {
             // Set up the roster
             this.roster = new this.RosterItems();
             this.roster.localStorage = new Backbone.LocalStorage(
@@ -2606,33 +2610,45 @@
                 $.proxy(this.roster.rosterHandler, this.roster),
                 null, 'presence', null);
             this.rosterview = new this.RosterView({'model':this.roster});
+        }
 
-            this.chatboxes.onConnected();
-
-            this.connection.addHandler(
-                $.proxy(this.roster.subscribeToSuggestedItems, this.roster),
-                'http://jabber.org/protocol/rosterx', 'message', null);
-
-            this.connection.roster.get($.proxy(function (a) {
-                this.connection.addHandler(
-                        $.proxy(function (presence) {
-                            this.presenceHandler(presence);
-                            return true;
-                        }, this.roster), null, 'presence', null);
+        this.onConnected = function (connection, callback) {
+            this.connection = connection;
+            this.connection.xmlInput = function (body) { console.log(body); };
+            this.connection.xmlOutput = function (body) { console.log(body); };
+            this.bare_jid = Strophe.getBareJidFromJid(this.connection.jid);
+            this.domain = Strophe.getDomainFromJid(this.connection.jid);
+            this.features = new this.Features();
+            this.initStatus($.proxy(function () {
+                this.initRoster();
+                this.chatboxes.onConnected();
                 this.connection.addHandler(
-                        $.proxy(function (message) {
-                            this.chatboxes.messageReceived(message);
-                            return true;
-                        }, this), null, 'message', 'chat');
-            }, this));
-
-            $(window).on("blur focus", $.proxy(function(e) {
-                if ((this.windowState != e.type) && (e.type == 'focus')) {
-                    converse.clearMsgCounter();
+                    $.proxy(this.roster.subscribeToSuggestedItems, this.roster),
+                    'http://jabber.org/protocol/rosterx', 'message', null);
+
+                this.connection.roster.get($.proxy(function (a) {
+                    this.connection.addHandler(
+                            $.proxy(function (presence) {
+                                this.presenceHandler(presence);
+                                return true;
+                            }, this.roster), null, 'presence', null);
+                    this.connection.addHandler(
+                            $.proxy(function (message) {
+                                this.chatboxes.messageReceived(message);
+                                return true;
+                            }, this), null, 'message', 'chat');
+                }, this));
+                $(window).on("blur focus", $.proxy(function(e) {
+                    if ((this.windowState != e.type) && (e.type == 'focus')) {
+                        converse.clearMsgCounter();
+                    }
+                    this.windowState = e.type;
+                },this));
+                this.giveFeedback(__('Online Contacts'));
+                if (callback) {
+                    callback();
                 }
-                this.windowState = e.type;
-            },this));
-            this.giveFeedback(__('Online Contacts'));
+            }, this));
         };
 
         // This is the end of the initialize method.

+ 0 - 0
converse-0.5.0.min.css → converse.min.css


文件差異過大導致無法顯示
+ 0 - 0
converse.min.js


+ 3 - 3
index.html

@@ -5,9 +5,9 @@
     <meta http-equiv="X-UA-Compatible" content="chrome=1" />
     <meta name="description" content="Converse.js: Open Source Browser-Based Instant Messaging" />
     <link rel="stylesheet" type="text/css" media="screen" href="stylesheets/stylesheet.css">
-    <link rel="stylesheet" type="text/css" media="screen" href="converse-0.5.0.min.css">
-    <script src="converse-0.5.0.min.js"></script>
-    <!-- For development: <script data-main="main" src="Libraries/require-jquery.js"></script> -->
+    <link rel="stylesheet" type="text/css" media="screen" href="converse.min.css">
+    <script src="converse.min.js"></script>
+    <!-- For development <script data-main="main" src="components/requirejs/require.js"></script> -->
     <title>Converse.js</title>
 </head>
 

+ 486 - 0
locale/en/LC_MESSAGES/converse.po

@@ -0,0 +1,486 @@
+# English translations for Converse.js package.
+# Copyright (C) 2013 Jan-Carel Brand
+# This file is distributed under the same license as the Converse.js package.
+# JC Brand <jc@opkode.com>, 2013.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Converse.js 0.4\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-06-01 23:03+0200\n"
+"PO-Revision-Date: 2013-08-01 14:11+0200\n"
+"Last-Translator: JC Brand <jc@opkode.com>\n"
+"Language-Team: English\n"
+"Language: en\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ASCII\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: converse.js:397 converse.js:1128
+msgid "Show this menu"
+msgstr "Show this menu"
+
+#: converse.js:398 converse.js:1129
+msgid "Write in the third person"
+msgstr "Write in the third person"
+
+#: converse.js:399 converse.js:1133
+msgid "Remove messages"
+msgstr "Remove messages"
+
+#: converse.js:539
+msgid "Personal message"
+msgstr "Personal message"
+
+#: converse.js:613
+msgid "Contacts"
+msgstr "Contacts"
+
+#: converse.js:618
+msgid "Online"
+msgstr "Online"
+
+#: converse.js:619
+msgid "Busy"
+msgstr "Busy"
+
+#: converse.js:620
+msgid "Away"
+msgstr "Away"
+
+#: converse.js:621
+msgid "Offline"
+msgstr "Offline"
+
+#: converse.js:628
+msgid "Click to add new chat contacts"
+msgstr "Click to add new chat contacts"
+
+#: converse.js:628
+msgid "Add a contact"
+msgstr "Add a contact"
+
+#: converse.js:637
+msgid "Contact username"
+msgstr "Contact username"
+
+#: converse.js:638
+msgid "Add"
+msgstr "Add"
+
+#: converse.js:646
+msgid "Contact name"
+msgstr "Contact name"
+
+#: converse.js:647
+msgid "Search"
+msgstr "Search"
+
+#: converse.js:682
+msgid "No users found"
+msgstr "No users found"
+
+#: converse.js:689
+msgid "Click to add as a chat contact"
+msgstr "Click to add as a chat contact"
+
+#: converse.js:753
+msgid "Click to open this room"
+msgstr "Click to open this room"
+
+#: converse.js:755
+msgid "Show more information on this room"
+msgstr "Show more information on this room"
+
+#: converse.js:760
+msgid "Description:"
+msgstr "Description:"
+
+#: converse.js:761
+msgid "Occupants:"
+msgstr "Occupants:"
+
+#: converse.js:762
+msgid "Features:"
+msgstr "Features:"
+
+#: converse.js:764
+msgid "Requires authentication"
+msgstr "Requires authentication"
+
+#: converse.js:767
+msgid "Hidden"
+msgstr "Hidden"
+
+#: converse.js:770
+msgid "Requires an invitation"
+msgstr "Requires an invitation"
+
+#: converse.js:773
+msgid "Moderated"
+msgstr "Moderated"
+
+#: converse.js:776
+msgid "Non-anonymous"
+msgstr "Non-anonymous"
+
+#: converse.js:779
+msgid "Open room"
+msgstr "Open room"
+
+#: converse.js:782
+msgid "Permanent room"
+msgstr "Permanent room"
+
+#: converse.js:785
+msgid "Public"
+msgstr "Public"
+
+#: converse.js:788
+msgid "Semi-anonymous"
+msgstr "Semi-anonymous"
+
+#: converse.js:791
+msgid "Temporary room"
+msgstr "Temporary room"
+
+#: converse.js:794
+msgid "Unmoderated"
+msgstr "Unmoderated"
+
+#: converse.js:800
+msgid "Rooms"
+msgstr "Rooms"
+
+#: converse.js:804
+msgid "Room name"
+msgstr "Room name"
+
+#: converse.js:805
+msgid "Nickname"
+msgstr "Nickname"
+
+#: converse.js:806
+msgid "Server"
+msgstr "Server"
+
+#: converse.js:807
+msgid "Join"
+msgstr "Join"
+
+#: converse.js:808
+msgid "Show rooms"
+msgstr "Show rooms"
+
+#. For translators: %1$s is a variable and will be replaced with the XMPP server name
+#: converse.js:841
+msgid "No rooms on %1$s"
+msgstr "No rooms on %1$s"
+
+#. For translators: %1$s is a variable and will be
+#. replaced with the XMPP server name
+#: converse.js:856
+msgid "Rooms on %1$s"
+msgstr "Rooms on %1$s"
+
+#: converse.js:1130
+msgid "Set chatroom topic"
+msgstr "Set chatroom topic"
+
+#: converse.js:1131
+msgid "Kick user from chatroom"
+msgstr "Kick user from chatroom"
+
+#: converse.js:1132
+msgid "Ban user from chatroom"
+msgstr "Ban user from chatroom"
+
+#: converse.js:1159
+msgid "Message"
+msgstr "Message"
+
+#: converse.js:1273 converse.js:2318
+msgid "Save"
+msgstr "Save"
+
+#: converse.js:1274
+msgid "Cancel"
+msgstr "Cancel"
+
+#: converse.js:1321
+msgid "An error occurred while trying to save the form."
+msgstr "An error occurred while trying to save the form."
+
+#: converse.js:1367
+msgid "This chatroom requires a password"
+msgstr "This chatroom requires a password"
+
+#: converse.js:1368
+msgid "Password: "
+msgstr "Password: "
+
+#: converse.js:1369
+msgid "Submit"
+msgstr "Submit"
+
+#: converse.js:1383
+msgid "This room is not anonymous"
+msgstr "This room is not anonymous"
+
+#: converse.js:1384
+msgid "This room now shows unavailable members"
+msgstr "This room now shows unavailable members"
+
+#: converse.js:1385
+msgid "This room does not show unavailable members"
+msgstr "This room does not show unavailable members"
+
+#: converse.js:1386
+msgid "Non-privacy-related room configuration has changed"
+msgstr "Non-privacy-related room configuration has changed"
+
+#: converse.js:1387
+msgid "Room logging is now enabled"
+msgstr "Room logging is now enabled"
+
+#: converse.js:1388
+msgid "Room logging is now disabled"
+msgstr "Room logging is now disabled"
+
+#: converse.js:1389
+msgid "This room is now non-anonymous"
+msgstr "This room is now non-anonymous"
+
+#: converse.js:1390
+msgid "This room is now semi-anonymous"
+msgstr "This room is now semi-anonymous"
+
+#: converse.js:1391
+msgid "This room is now fully-anonymous"
+msgstr "This room is now fully-anonymous"
+
+#: converse.js:1392
+msgid "A new room has been created"
+msgstr "A new room has been created"
+
+#: converse.js:1393
+msgid "Your nickname has been changed"
+msgstr "Your nickname has been changed"
+
+#. For translations: %1$s will be replaced with the user's nickname
+#. Don't translate "strong"
+#. Example: <strong>jcbrand</strong> has been banned
+#: converse.js:1400
+msgid "<strong>%1$s</strong> has been banned"
+msgstr "<strong>%1$s</strong> has been banned"
+
+#. For translations: %1$s will be replaced with the user's nickname
+#. Don't translate "strong"
+#. Example: <strong>jcbrand</strong> has been kicked out
+#: converse.js:1404
+msgid "<strong>%1$s</strong> has been kicked out"
+msgstr "<strong>%1$s</strong> has been kicked out"
+
+#. For translations: %1$s will be replaced with the user's nickname
+#. Don't translate "strong"
+#. Example: <strong>jcbrand</strong> has been removed because of an affiliasion change
+#: converse.js:1408
+msgid "<strong>%1$s</strong> has been removed because of an affiliation change"
+msgstr ""
+"<strong>%1$s</strong> has been removed because of an affiliation change"
+
+#. For translations: %1$s will be replaced with the user's nickname
+#. Don't translate "strong"
+#. Example: <strong>jcbrand</strong> has been removed for not being a member
+#: converse.js:1412
+msgid "<strong>%1$s</strong> has been removed for not being a member"
+msgstr "<strong>%1$s</strong> has been removed for not being a member"
+
+#: converse.js:1416 converse.js:1478
+msgid "You have been banned from this room"
+msgstr "You have been banned from this room"
+
+#: converse.js:1417
+msgid "You have been kicked from this room"
+msgstr "You have been kicked from this room"
+
+#: converse.js:1418
+msgid "You have been removed from this room because of an affiliation change"
+msgstr "You have been removed from this room because of an affiliation change"
+
+#: converse.js:1419
+msgid ""
+"You have been removed from this room because the room has changed to members-"
+"only and you're not a member"
+msgstr ""
+"You have been removed from this room because the room has changed to members-"
+"only and you're not a member"
+
+#: converse.js:1420
+msgid ""
+"You have been removed from this room because the MUC (Multi-user chat) "
+"service is being shut down."
+msgstr ""
+"You have been removed from this room because the MUC (Multi-user chat) "
+"service is being shut down."
+
+#: converse.js:1476
+msgid "You are not on the member list of this room"
+msgstr "You are not on the member list of this room"
+
+#: converse.js:1482
+msgid "No nickname was specified"
+msgstr "No nickname was specified"
+
+#: converse.js:1486
+msgid "You are not allowed to create new rooms"
+msgstr "You are not allowed to create new rooms"
+
+#: converse.js:1488
+msgid "Your nickname doesn't conform to this room's policies"
+msgstr "Your nickname doesn't conform to this room's policies"
+
+#: converse.js:1490
+msgid "Your nickname is already taken"
+msgstr "Your nickname is already taken"
+
+#: converse.js:1492
+msgid "This room does not (yet) exist"
+msgstr "This room does not (yet) exist"
+
+#: converse.js:1494
+msgid "This room has reached it's maximum number of occupants"
+msgstr "This room has reached it's maximum number of occupants"
+
+#. For translators: the %1$s and %2$s parts will get replaced by the user and topic text respectively
+#. Example: Topic set by JC Brand to: Hello World!
+#: converse.js:1571
+msgid "Topic set by %1$s to: %2$s"
+msgstr "Topic set by %1$s to: %2$s"
+
+#: converse.js:1587
+msgid "This user is a moderator"
+msgstr "This user is a moderator"
+
+#: converse.js:1590
+msgid "This user can send messages in this room"
+msgstr "This user can send messages in this room"
+
+#: converse.js:1593
+msgid "This user can NOT send messages in this room"
+msgstr "This user can NOT send messages in this room"
+
+#: converse.js:1796
+msgid "Click to chat with this contact"
+msgstr "Click to chat with this contact"
+
+#: converse.js:1797 converse.js:1801
+msgid "Click to remove this contact"
+msgstr "Click to remove this contact"
+
+#: converse.js:2163
+msgid "Contact requests"
+msgstr "Contact requests"
+
+#: converse.js:2164
+msgid "My contacts"
+msgstr "My contacts"
+
+#: converse.js:2165
+msgid "Pending contacts"
+msgstr "Pending contacts"
+
+#: converse.js:2317
+msgid "Custom status"
+msgstr "Custom status"
+
+#: converse.js:2323
+msgid "Click to change your chat status"
+msgstr "Click to change your chat status"
+
+#: converse.js:2326
+msgid "Click here to write a custom status message"
+msgstr "Click here to write a custom status message"
+
+#: converse.js:2355 converse.js:2363
+msgid "online"
+msgstr "online"
+
+#: converse.js:2357
+msgid "busy"
+msgstr "busy"
+
+#: converse.js:2359
+msgid "away for long"
+msgstr "away for long"
+
+#: converse.js:2361
+msgid "away"
+msgstr "away"
+
+#. For translators: the %1$s part gets replaced with the status
+#. Example, I am online
+#: converse.js:2375 converse.js:2409
+msgid "I am %1$s"
+msgstr "I am %1$s"
+
+#: converse.js:2480
+msgid "Sign in"
+msgstr "Sign in"
+
+#: converse.js:2483
+msgid "XMPP/Jabber Username:"
+msgstr "XMPP/Jabber Username:"
+
+#: converse.js:2485
+msgid "Password:"
+msgstr "Password:"
+
+#: converse.js:2487
+msgid "Log In"
+msgstr "Log In"
+
+#: converse.js:2491
+msgid "BOSH Service URL:"
+msgstr "BOSH Service URL:"
+
+#: converse.js:2503
+msgid "Connected"
+msgstr "Connected"
+
+#: converse.js:2507
+msgid "Disconnected"
+msgstr "Disconnected"
+
+#: converse.js:2511
+msgid "Error"
+msgstr "Error"
+
+#: converse.js:2513
+msgid "Connecting"
+msgstr "Connecting"
+
+#: converse.js:2516
+msgid "Connection Failed"
+msgstr "Connection Failed"
+
+#: converse.js:2518
+msgid "Authenticating"
+msgstr "Authenticating"
+
+#: converse.js:2521
+msgid "Authentication Failed"
+msgstr "Authentication Failed"
+
+#: converse.js:2523
+msgid "Disconnecting"
+msgstr "Disconnecting"
+
+#: converse.js:2525
+msgid "Attached"
+msgstr "Attached"
+
+#: converse.js:2656
+msgid "Online Contacts"
+msgstr "Online Contacts"

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "converse.js",
-  "version": "0.5.0",
+  "version": "0.5.1",
   "description": "Browser based XMPP instant messaging client",
   "main": "main.js",
   "directories": {

+ 13 - 4
spec/MainSpec.js

@@ -56,6 +56,12 @@
             it("can be opened by clicking a DOM element with class 'toggle-online-users'", open_controlbox);
 
             describe("The Status Widget", $.proxy(function () {
+                it("shows the user's chat status, which is online by default", $.proxy(function () {
+                    var view = this.xmppstatusview;
+                    expect(view.$el.find('a.choose-xmpp-status').hasClass('online')).toBe(true);
+                    expect(view.$el.find('a.choose-xmpp-status').attr('data-value')).toBe('I am online');
+                }, converse));
+
                 it("can be used to set the current user's chat status", $.proxy(function () {
                     var view = this.xmppstatusview;
                     spyOn(view, 'toggleOptions').andCallThrough();
@@ -64,25 +70,26 @@
                     runs(function () {
                         view.$el.find('a.choose-xmpp-status').click();
                         expect(view.toggleOptions).toHaveBeenCalled();
-                        expect(view.$el.find('a.choose-xmpp-status').hasClass('online')).toBe(false);
                     });
                     waits(250);
                     runs(function () {
                         spyOn(view, 'updateStatusUI').andCallThrough();
                         view.initialize(); // Rebind events for spy
-                        view.$el.find('.dropdown dd ul li a').first().click();
+                        $(view.$el.find('.dropdown dd ul li a')[1]).click();
                         expect(view.setStatus).toHaveBeenCalled();
                     });
                     waits(250);
                     runs($.proxy(function () {
                         expect(view.updateStatusUI).toHaveBeenCalled();
-                        expect(view.$el.find('a.choose-xmpp-status').hasClass('online')).toBe(true);
-                        expect(view.$el.find('a.choose-xmpp-status').attr('data-value')).toBe('I am online');
+                        expect(view.$el.find('a.choose-xmpp-status').hasClass('online')).toBe(false);
+                        expect(view.$el.find('a.choose-xmpp-status').hasClass('dnd')).toBe(true);
+                        expect(view.$el.find('a.choose-xmpp-status').attr('data-value')).toBe('I am busy');
                     }, converse));
                 }, converse));
 
                 it("can be used to set a custom status message", $.proxy(function () {
                     var view = this.xmppstatusview;
+                    this.xmppstatus.save({'status': 'online'});
                     spyOn(view, 'setStatusMessage').andCallThrough();
                     spyOn(view, 'renderStatusChangeForm').andCallThrough();
                     view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
@@ -120,6 +127,7 @@
                 it("can be added to the roster and they will be sorted alphabetically", $.proxy(function () {
                     var i, t, is_last;
                     spyOn(this.rosterview, 'render').andCallThrough();
+                    spyOn(this.xmppstatus, 'sendPresence');
                     for (i=0; i<pend_names.length; i++) {
                         is_last = i===(pend_names.length-1);
                         this.roster.create({
@@ -133,6 +141,7 @@
                         // the last contact has been added.
                         if (is_last) {
                             expect(this.rosterview.$el.is(':visible')).toEqual(true);
+                            expect(this.xmppstatus.sendPresence).toHaveBeenCalled();
                         } else {
                             expect(this.rosterview.$el.is(':visible')).toEqual(false);
                         }

+ 1 - 2
tests_main.js

@@ -75,7 +75,6 @@ require([
         auto_subscribe: false,
         animate: false
     });
-    converse.onConnected(mock_connection);
 
     // Jasmine stuff
     var jasmineEnv = jasmine.getEnv();
@@ -93,5 +92,5 @@ require([
         };
         jasmineEnv.updateInterval = 200;
     }
-    jasmineEnv.execute();
+    converse.onConnected(mock_connection, $.proxy(jasmineEnv.execute, jasmineEnv));
 });

部分文件因文件數量過多而無法顯示