Jelajahi Sumber

Add, test and document an API method for setting the user's status.

fixes #367
JC Brand 10 tahun lalu
induk
melakukan
b47069b4f6
8 mengubah file dengan 275 tambahan dan 78 penghapusan
  1. 0 5
      Gemfile.lock
  2. 41 9
      converse.js
  3. 2 0
      css/converse.css
  4. 3 2
      docs/CHANGES.rst
  5. 9 0
      docs/source/_static/style.css
  6. 168 62
      docs/source/development.rst
  7. 1 0
      sass/_core.scss
  8. 51 0
      spec/converse.js

+ 0 - 5
Gemfile.lock

@@ -1,17 +1,12 @@
 GEM
   remote: https://rubygems.org/
   specs:
-    bourbon (4.2.3)
-      sass (~> 3.4)
-      thor
     sass (3.4.14)
-    thor (0.19.1)
 
 PLATFORMS
   ruby
 
 DEPENDENCIES
-  bourbon
   sass (~> 3.3)
 
 BUNDLED WITH

+ 41 - 9
converse.js

@@ -139,6 +139,16 @@
         }
     };
 
+    var STATUS_WEIGHTS = {
+        'offline':      6,
+        'unavailable':  5,
+        'xa':           4,
+        'away':         3,
+        'dnd':          2,
+        'chat':         1, // We currently don't differentiate between "chat" and "online"
+        'online':       1
+    };
+
     converse.initialize = function (settings, callback) {
         "use strict";
         var converse = this;
@@ -195,14 +205,6 @@
             ENTER: 13,
             FORWARD_SLASH: 47
         };
-        var STATUS_WEIGHTS = {
-            'offline':      6,
-            'unavailable':  5,
-            'xa':           4,
-            'away':         3,
-            'dnd':          2,
-            'online':       1
-        };
 
         var PRETTY_CONNECTION_STATUS = {
             0: 'ERROR',
@@ -4241,8 +4243,9 @@
                     contact = this.get(bare_jid);
                 if (this.isSelf(bare_jid)) {
                     if ((converse.connection.jid !== jid)&&(presence_type !== 'unavailable')) {
-                        // Another resource has changed it's status, we'll update ours as well.
+                        // Another resource has changed its status, we'll update ours as well.
                         converse.xmppstatus.save({'status': chat_status});
+                        if (status_message.length) { converse.xmppstatus.save({'status_message': status_message}); }
                     }
                     return;
                 } else if (($presence.find('x').attr('xmlns') || '').indexOf(Strophe.NS.MUC) === 0) {
@@ -5938,9 +5941,38 @@
               converse.connection.disconnect();
         },
         'account': {
+            // XXX: Deprecated, will be removed with next non-minor release
+            'logout': function () {
+                converse.logOut();
+            }
+        },
+        'user': {
             'logout': function () {
                 converse.logOut();
             },
+            'status': {
+                'get': function () {
+                    return converse.xmppstatus.get('status');
+                },
+                'set': function (value, message) {
+                    var data = {'status': value};
+                    if (!_.contains(_.keys(STATUS_WEIGHTS), value)) {
+                        throw new Error('Invalid availability value. See https://xmpp.org/rfcs/rfc3921.html#rfc.section.2.2.2.1');
+                    }
+                    if (typeof message == "string") {
+                        data.status_message = message;
+                    }
+                    converse.xmppstatus.save(data);
+                },
+                'message': {
+                    'get': function () {
+                        return converse.xmppstatus.get('status_message');
+                    },
+                    'set': function (stat) {
+                        converse.xmppstatus.save({'status_message': stat});
+                    }
+                }
+            },
         },
         'settings': {
             'get': function (key) {

+ 2 - 0
css/converse.css

@@ -223,6 +223,8 @@
     content: "\e01f"; }
   #conversejs .icon-online:before {
     content: "\25fc"; }
+  #conversejs .icon-chat:before {
+    content: "\25fc"; }
   #conversejs .icon-opened:before {
     content: "\25bc"; }
   #conversejs .icon-pencil:before {

+ 3 - 2
docs/CHANGES.rst

@@ -4,7 +4,8 @@ Changelog
 0.9.4 (Unreleased)
 ------------------
 
-* #144 Add Ping funcionnality and Pong Handler [thierrytiti]
+* #144 Add Ping functionality and Pong handler [thierrytiti]
+* #367 API methods for changing chat status (online, busy, away etc.) and status message [jcbrand]
 * #389 Allow login panel placeholders and roster item 'Name' translations. [gbonvehi]
 * #394 Option to allow chatting with pending contacts [thierrytiti]
 * #396 Add automatic Away mode and XEP-0352 support [thierrytiti]
@@ -31,7 +32,7 @@ Changelog
 * CSS: Fonts Path: editabable $font-path via sass/variables.scss [thierrytiti]
 * Add offline pretty status to enable translation [thierrytiti]
 * With keepalive, don't send out a presence stanza on each page load [jcbrand]
-* Chat boxes returned by the API now have an ``is_chatroom`` attribute [jcbrand]
+* Chat boxes returned by the API now have an `is_chatroom` attribute [jcbrand]
 
 0.9.3 (2015-05-01)
 ------------------

+ 9 - 0
docs/source/_static/style.css

@@ -6,6 +6,15 @@ h1 {
     font-size: 50px;
 }
 
+h4 {
+    font-weight: bold;
+}
+
+h5 {
+    font-size: 16px;
+    font-weight: bold;
+}
+
 .navbar-brand {
     padding-top: 7px;
 }

+ 168 - 62
docs/source/development.rst

@@ -203,9 +203,77 @@ Example:
         });
 
 
-"contacts" grouping
+The "user" grouping
 -------------------
 
+This grouping collects API functions related to the current logged in user.
+
+logout
+~~~~~~
+
+Log the user out of the current XMPP session.
+
+.. code-block:: javascript 
+
+    converse.user.logout();
+
+
+The "status" sub-grouping
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set and get the user's chat status, also called their *availability*.
+
+get
+^^^
+
+Return the current user's availability status:
+
+.. code-block:: javascript 
+
+    converse.user.status.get(); // Returns for example "dnd"
+
+set
+^^^
+
+The user's status can be set to one of the following values:
+
+* **away**
+* **dnd**
+* **offline**
+* **online**
+* **unavailable**
+* **xa**
+
+For example:
+
+.. code-block:: javascript 
+
+    converse.user.status.set('dnd');
+
+Because the user's availability is often set together with a custom status
+message, this method also allows you to pass in a status message as a
+second parameter:
+
+.. code-block:: javascript 
+
+    converse.user.status.set('dnd', 'In a meeting');
+
+The "message" sub-grouping
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The ``user.status.message`` sub-grouping exposes methods for setting and
+retrieving the user's custom status message.
+
+.. code-block:: javascript 
+
+    converse.user.status.message.set('In a meeting');
+
+    converse.user.status.message.get(); // Returns "In a meeting"
+
+
+The "contacts" grouping
+-----------------------
+
 get
 ~~~
 
@@ -213,68 +281,78 @@ This method is used to retrieve roster contacts.
 
 To get a single roster contact, call the method with the contact's JID (Jabber ID):
 
+.. code-block:: javascript
+
     converse.contacts.get('buddy@example.com')
 
-To get multiple contacts, pass in an array of JIDs::
+To get multiple contacts, pass in an array of JIDs:
+
+.. code-block:: javascript
 
     converse.contacts.get(['buddy1@example.com', 'buddy2@example.com'])
 
-To return all contacts, simply call ``get`` without any parameters::
+To return all contacts, simply call ``get`` without any parameters:
+
+.. code-block:: javascript
 
     converse.contacts.get()
 
 
 The returned roster contact objects have these attributes:
 
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| Attribute      |                                                                                                                                      |
-+================+======================================================================================================================================+
-| ask            | If ask === 'subscribe', then we have asked this person to be our chat buddy.                                                         |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| fullname       | The person's full name.                                                                                                              |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| jid            | The person's Jabber/XMPP username.                                                                                                   |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| requesting     | If true, then this person is asking to be our chat buddy.                                                                            |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| subscription   | The subscription state between the current user and this chat buddy. Can be `none`, `to`, `from` or `both`.                          |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| id             | A unique id, same as the jid.                                                                                                        |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| chat_status    | The person's chat status. Can be `online`, `offline`, `busy`, `xa` (extended away) or `away`.                                        |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| user_id        | The user id part of the JID (the part before the `@`).                                                                               |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| resources      | The known resources for this chat buddy. Each resource denotes a separate and connected chat client.                                 |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| groups         | The roster groups in which this chat buddy was placed.                                                                               |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| status         | Their human readable custom status message.                                                                                          |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| image_type     | The image's file type.                                                                                                               |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| image          | The Base64 encoded image data.                                                                                                       |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| url            | The buddy's website URL, as specified in their VCard data.                                                                           |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| vcard_updated  | When last the buddy's VCard was updated.                                                                                             |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
++----------------+-----------------------------------------------------------------------------------------------------------------+
+| Attribute      |                                                                                                                 |
++================+=================================================================================================================+
+| ask            | If ask === 'subscribe', then we have asked this person to be our chat buddy.                                    |
++----------------+-----------------------------------------------------------------------------------------------------------------+
+| fullname       | The person's full name.                                                                                         |
++----------------+-----------------------------------------------------------------------------------------------------------------+
+| jid            | The person's Jabber/XMPP username.                                                                              |
++----------------+-----------------------------------------------------------------------------------------------------------------+
+| requesting     | If true, then this person is asking to be our chat buddy.                                                       |
++----------------+-----------------------------------------------------------------------------------------------------------------+
+| subscription   | The subscription state between the current user and this chat buddy. Can be `none`, `to`, `from` or `both`.     |
++----------------+-----------------------------------------------------------------------------------------------------------------+
+| id             | A unique id, same as the jid.                                                                                   |
++----------------+-----------------------------------------------------------------------------------------------------------------+
+| chat_status    | The person's chat status. Can be `online`, `offline`, `busy`, `xa` (extended away) or `away`.                   |
++----------------+-----------------------------------------------------------------------------------------------------------------+
+| user_id        | The user id part of the JID (the part before the `@`).                                                          |
++----------------+-----------------------------------------------------------------------------------------------------------------+
+| resources      | The known resources for this chat buddy. Each resource denotes a separate and connected chat client.            |
++----------------+-----------------------------------------------------------------------------------------------------------------+
+| groups         | The roster groups in which this chat buddy was placed.                                                          |
++----------------+-----------------------------------------------------------------------------------------------------------------+
+| status         | Their human readable custom status message.                                                                     |
++----------------+-----------------------------------------------------------------------------------------------------------------+
+| image_type     | The image's file type.                                                                                          |
++----------------+-----------------------------------------------------------------------------------------------------------------+
+| image          | The Base64 encoded image data.                                                                                  |
++----------------+-----------------------------------------------------------------------------------------------------------------+
+| url            | The buddy's website URL, as specified in their VCard data.                                                      |
++----------------+-----------------------------------------------------------------------------------------------------------------+
+| vcard_updated  | When last the buddy's VCard was updated.                                                                        |
++----------------+-----------------------------------------------------------------------------------------------------------------+
 
 add
 ~~~
 
 Add a contact.
 
-Provide the JID of the contact you want to add::
+Provide the JID of the contact you want to add:
+
+    .. code-block:: javascript
 
     converse.contacts.add('buddy@example.com')
     
-You may also provide the fullname. If not present, we use the jid as fullname::
+You may also provide the fullname. If not present, we use the jid as fullname:
+
+    .. code-block:: javascript
 
     converse.contacts.add('buddy@example.com', 'Buddy')
 
-"chats" grouping
-----------------
+The "chats" grouping
+--------------------
 
 get
 ~~~
@@ -282,11 +360,15 @@ get
 Returns an object representing a chat box.
 
 To return a single chat box, provide the JID of the contact you're chatting
-with in that chat box::
+with in that chat box:
+
+    .. code-block:: javascript
 
     converse.chats.get('buddy@example.com')
 
-To return an array of chat boxes, provide an array of JIDs::
+To return an array of chat boxes, provide an array of JIDs:
+
+    .. code-block:: javascript
 
     converse.chats.get(['buddy1@example.com', 'buddy2@example.com'])
 
@@ -299,11 +381,15 @@ open
 
 Opens a chat box and returns an object representing a chat box.
 
-To open a single chat box, provide the JID of the contact::
+To open a single chat box, provide the JID of the contact:
+
+    .. code-block:: javascript
 
     converse.chats.open('buddy@example.com')
 
-To return an array of chat boxes, provide an array of JIDs::
+To return an array of chat boxes, provide an array of JIDs:
+
+    .. code-block:: javascript
 
     converse.chats.open(['buddy1@example.com', 'buddy2@example.com'])
 
@@ -340,8 +426,8 @@ To return an array of chat boxes, provide an array of JIDs::
 | url         | The URL of the chat box heading.                    |
 +-------------+-----------------------------------------------------+
 
-"rooms" grouping
-----------------
+The "rooms" grouping
+--------------------
 
 get
 ~~~
@@ -356,39 +442,51 @@ open
 Opens a multi user chat box and returns an object representing it.
 Similar to chats.get API
 
-To open a single multi user chat box, provide the JID of the room::
+To open a single multi user chat box, provide the JID of the room:
+
+    .. code-block:: javascript
 
     converse.rooms.open('group@muc.example.com')
 
-To return an array of rooms, provide an array of room JIDs::
+To return an array of rooms, provide an array of room JIDs:
+
+    .. code-block:: javascript
 
     converse.rooms.open(['group1@muc.example.com', 'group2@muc.example.com'])
 
-To setup a custom nickname when joining the room, provide the optional nick argument::
+To setup a custom nickname when joining the room, provide the optional nick argument:
+
+    .. code-block:: javascript
 
     converse.rooms.open('group@muc.example.com', 'mycustomnick')
 
 
-"settings" grouping
--------------------
+The "settings" grouping
+-----------------------
 
 This grouping allows you to get or set the configuration settings of converse.js.
 
 get(key)
 ~~~~~~~~
 
-Returns the value of a configuration settings. For example::
+Returns the value of a configuration settings. For example:
+
+.. code-block:: javascript
 
     converse.settings.get("play_sounds"); // default value returned would be false;
 
 set(key, value) or set(object)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Set one or many configuration settings. For example::
+Set one or many configuration settings. For example:
+
+.. code-block:: javascript
 
     converse.settings.set("play_sounds", true);
 
-or ::
+or :
+
+.. code-block:: javascript
 
     converse.settings.set({
         "play_sounds", true,
@@ -399,20 +497,22 @@ Note, this is not an alternative to calling ``converse.initialize``, which still
 to be called. Generally, you'd use this method after converse.js is already
 running and you want to change the configuration on-the-fly.
 
-"tokens" grouping
------------------
+The "tokens" grouping
+---------------------
 
 get
 ~~~
 
 Returns a token, either the RID or SID token depending on what's asked for.
 
-Example::
+Example:
+
+    .. code-block:: javascript
 
     converse.tokens.get('rid')
 
-"listen" grouping
------------------
+The "listen" grouping
+---------------------
 
 Converse.js emits events to which you can subscribe from your own Javascript.
 
@@ -430,7 +530,9 @@ grouping:
     * ``eventName`` is the event name as a string.
     * ``callback`` is the callback method to be called when the event is emitted.
 
-    For example::
+    For example:
+
+    .. code-block:: javascript
 
         converse.listen.on('message', function (event, messageXML) { ... });
 
@@ -444,7 +546,9 @@ grouping:
     * ``eventName`` is the event name as a string.
     * ``callback`` is the callback method to be called when the event is emitted.
 
-    For example::
+    For example:
+
+    .. code-block:: javascript
 
         converse.listen.once('message', function (event, messageXML) { ... });
 
@@ -457,7 +561,9 @@ grouping:
     * ``eventName`` is the event name as a string.
     * ``callback`` refers to the function that is to be no longer executed.
 
-    For example::
+    For example:
+
+    .. code-block:: javascript
 
         converse.listen.not('message', function (event, messageXML) { ... });
 

+ 1 - 0
sass/_core.scss

@@ -192,6 +192,7 @@
   .icon-notebook:before           { content: "\2710"; }
   .icon-notification:before       { content: "\e01f"; }
   .icon-online:before             { content: "\25fc"; }
+  .icon-chat:before               { content: "\25fc"; }
   .icon-opened:before             { content: "\25bc"; }
   .icon-pencil:before             { content: "\270e"; }
   .icon-phone-hang-up:before      { content: "\260e"; }

+ 51 - 0
spec/converse.js

@@ -130,6 +130,57 @@
             });
         });
 
+        describe("The \"user\" grouping", function () {
+
+            describe("The \"status\" API", function () {
+                beforeEach(function () {
+                    test_utils.closeAllChatBoxes();
+                    test_utils.clearBrowserStorage();
+                    converse.rosterview.model.reset();
+                });
+
+                it("has a method for getting the user's availability", function () {
+                    converse.xmppstatus.set('status', 'online');
+                    expect(converse_api.user.status.get()).toBe('online');
+                    converse.xmppstatus.set('status', 'dnd');
+                    expect(converse_api.user.status.get()).toBe('dnd');
+                });
+
+                it("has a method for setting the user's availability", function () {
+                    converse_api.user.status.set('away');
+                    expect(converse.xmppstatus.get('status')).toBe('away');
+                    converse_api.user.status.set('dnd');
+                    expect(converse.xmppstatus.get('status')).toBe('dnd');
+                    converse_api.user.status.set('xa');
+                    expect(converse.xmppstatus.get('status')).toBe('xa');
+                    converse_api.user.status.set('chat');
+                    expect(converse.xmppstatus.get('status')).toBe('chat');
+                    expect(_.partial(converse_api.user.status.set, 'invalid')).toThrow(
+                        new Error('Invalid availability value. See https://xmpp.org/rfcs/rfc3921.html#rfc.section.2.2.2.1')
+                    );
+                });
+
+                it("allows setting the status message as well", function () {
+                    converse_api.user.status.set('away', "I'm in a meeting");
+                    expect(converse.xmppstatus.get('status')).toBe('away');
+                    expect(converse.xmppstatus.get('status_message')).toBe("I'm in a meeting");
+                });
+
+                it("has a method for getting the user's status message", function () {
+                    converse.xmppstatus.set('status_message', undefined);
+                    expect(converse_api.user.status.message.get()).toBe(undefined);
+                    converse.xmppstatus.set('status_message', "I'm in a meeting");
+                    expect(converse_api.user.status.message.get()).toBe("I'm in a meeting");
+                });
+
+                it("has a method for setting the user's status message", function () {
+                    converse.xmppstatus.set('status_message', undefined);
+                    converse_api.user.status.message.set("I'm in a meeting");
+                    expect(converse.xmppstatus.get('status_message')).toBe("I'm in a meeting");
+                });
+            });
+        });
+
         describe("The \"tokens\" API", $.proxy(function () {
             beforeEach(function () {
                 test_utils.closeAllChatBoxes();