Commit f81a94ba authored by JC Brand's avatar JC Brand

Move `updateSettings` to the private API.

Also add an API method for exposing new promises.

Update the plugin and API documentation, specifically concerning the above
changes.
parent 857c5ccd
......@@ -2,23 +2,30 @@
## 3.1.0 (Unreleased)
- Support for [XMPP-0313 Message Archive Management](https://xmpp.org/extensions/xep-0313.html)
has been upgraded to version 2. [jcbrand]
### API changes
- Deprecate the `updateSettings` method in favour of
`_converse.settings.update`. [jcbrand]
- Add a new API method `_converse.promises.add` for exposing promises to be
used with `_converse.waitUntil`. [jcbrand]
- The `message` event now returns a data object with `stanza` and
`chatbox` attributes, instead of just the stanza. [jcbrand]
### New Plugins
- New non-core plugin `converse-singleton` which ensures that no more than
one chat is visible at any given time. Used in the mobile build:
`converse-mobile.js` and makes the unread messages counter possible there.
[jcbrand]
- New non-core plugin `converse-roomslist`, which shows a list of open rooms
in the `Rooms` tab of the control box. [jcbrand]
- Show unread messages for minimized chats. [jcbrand]
- New configuration setting for `converse-bookmarks`:
### New configuration settings
- New setting for `converse-bookmarks`:
[hide_open_bookmarks](https://conversejs.org/docs/html/configurations.html#hide-open-bookmarks)
It is meant to be set to `true` when using `converse-roomslist` so that open
rooms aren't listed twice (in the rooms list and the bookmarks list).
[jcbrand]
- API change: the `message` event now returns a data object with `stanza` and
`chatbox` attributes, instead of just the stanza. [jcbrand]
- Render nickname form when entering a room via invitation. [jcbrand]
### Github tickets resolved
- #567 Unreaded message count reset on page load [novokrest]
- #575 Logging out from converse.js doesn't clear the connection status from the
sessionStorage [jcbrand]
......@@ -30,6 +37,13 @@
- #890 Message carbons not sent out after reconnection [jcbrand]
- #894 Room affiliation lost when connection jid and room presence jid are of different case [Rayzen]
### Miscellaneous
- Support for [XMPP-0313 Message Archive Management](https://xmpp.org/extensions/xep-0313.html)
has been upgraded to version 2. [jcbrand]
- Show unread messages for minimized chats. [jcbrand]
- Render nickname form when entering a room via invitation. [jcbrand]
## 3.0.2 (2017-04-23)
*Dependency updates*:
......
......@@ -26,10 +26,10 @@ After you have configured *Converse.js*, you'll have to regenerate the minified
JS file so that it will include the new settings. Please refer to the
:ref:`minification` section for more info on how to do this.
.. _`configuration-variables`:
.. _`configuration-settings`:
Configuration variables
=======================
Configuration settings
======================
authentication
--------------
......
......@@ -55,6 +55,8 @@ can call them. Public methods therefore don't expose any sensitive or closured
data. To do that, you'll need to create a plugin, which has access to the
private API method.
.. _`initialize`:
initialize
----------
......@@ -63,7 +65,7 @@ initialize
Publich API method which initializes converse.js.
This method must always be called when using converse.js.
The `initialize` method takes a map of :ref:`configuration-variables`.
The `initialize` method takes a map of :ref:`configuration-settings`.
Example:
......@@ -133,6 +135,22 @@ that might be running in the page.
time-constriaints these limitations are ignored in the examples below. For
a fuller picture, refer to the section :ref:`events-API` as well.
emit
----
This method allows you to emit events, which can be listened to via
``_converse.api.listen.on`` or ``_converse.api.listen.once``.
For example:
.. code-block:: javascript
_converse.emit('foo-completed');
Additionally, if a promise has been registered under the same name
(via ``_converse.api.promises.add``), then that promise will also be resolved
when calling ``emit``.
send
----
......@@ -155,7 +173,6 @@ For example, to send a message stanza:
}
});
.. _`waituntil-grouping`:
waitUntil
......@@ -202,7 +219,7 @@ Converse.js supports the *Message Archive Management*
(`XEP-0313 <https://xmpp.org/extensions/xep-0313.html>`_) protocol,
through which it is able to query an XMPP server for archived messages.
See also the **message_archiving** option in the :ref:`configuration-variables` section, which you'll usually
See also the **message_archiving** option in the :ref:`configuration-settings` section, which you'll usually
want to in conjunction with this API.
query
......@@ -880,10 +897,101 @@ Lets you close open chat rooms. You can call this method without any arguments
to close all open chat rooms, or you can specify a single JID or an array of
JIDs.
.. _`promises-grouping`:
The **promises** grouping
-------------------------
Converse.js and its plugins emit various events which you can listen to via the
:refs:`listen-grouping`.
These events can also be turned into promises, and by default some already
are.
The core events, which are also promises are:
* cachedRoster
* chatBoxesFetched
* connected
* pluginsInitialized
* roster
* rosterContactsFetched
* rosterGroupsFetched
* rosterInitialized
* statusInitialized
The various plugins might also provide promises, and they do this by using the
``promises.add`` api method.
add(promises)
~~~~~~~~~~~~~
By calling ``promises.add``, a new promise is made available for other code or
plugins to depend on via the ``_converse.api.waitUntil`` method.
This method accepts either a string or list of strings which specify the
promise(s) to be added.
For example:
.. code-block:: javascript
converse.plugins.add('myplugin', {
initialize: function () {
this._converse.api.promises.add('foo-completed');
}
});
Generally, it's the responsibility of the plugin which adds the promise to
also resolve it.
This is done by calling ``_converse.api.emit``, which not only resolve the
promise, but also emit an event with the same name (which can be listened to
via ``_converse.api.listen``).
For example:
.. code-block:: javascript
_converse.api.emit('foo-completed');
The **settings** grouping
-------------------------
This grouping allows you to get or set the configuration settings of converse.js.
This grouping allows access to the configuration settings of converse.js.
.. _`settings-update`:
update(settings)
~~~~~~~~~~~~~~~~
Allows new configuration settings to be specified, or new default values for
existing configuration settings to be specified.
For example:
.. code-block:: javascript
converse.plugins.add('myplugin', {
initialize: function () {
this._converse.api.settings.update({
'enable_foo': true
});
}
});
The user can then override the default value of the configuration setting when
calling `converse.initialize`.
For example:
.. code-block:: javascript
converse.initialize({
'enable_foo': false
});
get(key)
~~~~~~~~
......
......@@ -126,7 +126,6 @@ Here's an example of the plugin shown above wrapped inside a UMD module:
});
Accessing 3rd party libraries
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......@@ -198,11 +197,36 @@ If the setting :ref:`strict_plugin_dependencies` is set to true,
an error will be raised if the plugin is not found, thereby making them
non-optional.
Extending converse.js's configuration settings
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Converse.js comes with various :ref:`configuration-settings`_ that can be used to
modify its functionality and behavior.
All configuration settings have default values which can be overridden when
`converse.initialize` (see :ref:`initialize`_) gets called.
Plugins often need their own additional configuration settings and you can add
these settings with the `_converse.api.settings.update` method (see
:ref:`settings-update`_).
Exposing promises
~~~~~~~~~~~~~~~~~
Converse.js has a ``waitUntil`` API method (see :ref:`waituntil-grouping`_)
which allows you to wait for various promises to resolve before executing a
piece of code.
You can add new promises for your plugin by calling
``_converse.api.promises.add`` (see :ref:`promises-grouping`_).
Generally, your plugin will then also be responsible for making sure these
promises are resolved. You do this by calling ``_converse.api.emit``, which not
only resolves the plugin but will also emit an event with the same name.
A full example plugin
---------------------
.. code-block:: javascript
(function (root, factory) {
......@@ -237,20 +261,58 @@ A full example plugin
// method on any plugin (if it exists) as soon as the plugin has
// been loaded.
var _converse = this._converse;
// Inside this method, you have access to the closured
// _converse object, from which you can get any configuration
// options that the user might have passed in via
// converse.initialize. These values are stored in the
// "user_settings" attribute.
// Let's assume the user might pass in a custom setting, like so:
// We can also specify new configuration settings for this
// plugin, or override the default values of existing
// configuration settings. This is done like so:
_converse.api.settings.update({
'initialize_message': 'Initialized', // New configuration setting
'auto_subscribe': true, // New default value for an
// existing "core" configuration setting
});
// The user can then pass in values for the configuration
// settings when `converse.initialize` gets called.
// For example:
//
// converse.initialize({
// "initialize_message": "My plugin has been initialized"
// });
//
// Then we can alert that message, like so:
alert(this._converse.user_settings.initialize_message);
// And the configuration setting is then available via the
// `user_settings` attribute:
// alert(this._converse.user_settings.initialize_message);
// Besides `_converse.api.settings.update`, there is also a
// `_converse.api.promises.add` method, which allows you to
// add new promises that your plugin is obligated to fulfill.
// This method takes a string or a list of strings which
// represent the promise names.
_converse.api.promises.add('operationCompleted');
// Your plugin should then, when appropriate, resolve the
// promise by calling `_converse.api.emit`, which will also
// emit an event with the same name as the promise.
// For example:
// _converse.api.emit('operationCompleted');
//
// Other plugins can then either listen for the event
// `operationCompleted` like so:
// `_converse.api.listen.on('operationCompleted', function { ... });`
//
// or they can wait for the promise to be fulfilled like so:
// `_converse.api.waitUntil('operationCompleted', function { ... });`
},
// Optional dependencies are other plugins which might be
......
......@@ -42,7 +42,7 @@ Initializing Converse.js
------------------------
You'll then need to initialize Converse.js with configuration settings relevant to your requirements.
Refer to the :ref:`configuration-variables` section for info on all the available configuration settings.
Refer to the :ref:`configuration-settings` section for info on all the available configuration settings.
To quickly get started, you can put the following Javascript code at the
bottom of your page (after the closing *</body>* element)::
......
......@@ -212,7 +212,7 @@ your authentication backend, since you could then configure your XMPP server to
use that as well.
To prebind you will require a BOSH-enabled XMPP server for converse.js to connect to
(see the :ref:`bosh-service-url` under :ref:`configuration-variables`)
(see the :ref:`bosh-service-url` under :ref:`configuration-settings`)
as well as a BOSH client in your web application (written for example in
Python, Ruby or PHP) that will set up an authenticated BOSH session, which
converse.js can then attach to.
......
......@@ -326,7 +326,7 @@
{'play_sounds': true},
function (_converse) {
expect(_.keys(_converse.api.settings)).toEqual(["get", "set"]);
expect(_.keys(_converse.api.settings)).toEqual(["update", "get", "set"]);
expect(_converse.api.settings.get("play_sounds")).toBe(true);
_converse.api.settings.set("play_sounds", false);
expect(_converse.api.settings.get("play_sounds")).toBe(false);
......
......@@ -194,10 +194,12 @@
// ====================================
// Refer to docs/source/configuration.rst for explanations of these
// configuration settings.
this.updateSettings({
_converse.api.settings.update({
allow_bookmarks: true,
hide_open_bookmarks: false
});
// Promises exposed by this plugin
_converse.api.promises.add('bookmarksInitialized');
_converse.Bookmark = Backbone.Model;
......
......@@ -76,7 +76,7 @@
var _converse = this._converse,
__ = _converse.__;
this.updateSettings({
_converse.api.settings.update({
chatview_avatar_height: 32,
chatview_avatar_width: 32,
show_toolbar: true,
......
......@@ -191,7 +191,7 @@
var _converse = this._converse,
__ = _converse.__;
this.updateSettings({
_converse.api.settings.update({
allow_logout: true,
default_domain: undefined,
show_controlbox_by_default: false,
......
......@@ -2154,15 +2154,6 @@
this.chatboxviews = new this.ChatBoxViews({model: this.chatboxes});
};
var updateSettings = function (settings) {
/* Helper method which gets put on the plugin and allows it to
* add more user-facing config settings to converse.js.
*/
utils.merge(_converse.default_settings, settings);
utils.merge(_converse, settings);
utils.applyUserSettings(_converse, settings, _converse.user_settings);
};
this.initPlugins = function () {
// If initialize gets called a second time (e.g. during tests), then we
// need to re-apply all plugins (for a new converse instance), and we
......@@ -2175,7 +2166,7 @@
_converse.whitelisted_plugins);
_converse.pluggable.initializePlugins({
'updateSettings': updateSettings,
'updateSettings': _converse.api.settings.update,
'_converse': _converse
}, whitelist, _converse.blacklisted_plugins);
_converse.emit('pluginsInitialized');
......@@ -2212,6 +2203,9 @@
_converse.connection.disconnect();
},
},
'emit': function () {
_converse.emit.apply(_converse, arguments);
},
'user': {
'jid': function () {
return _converse.connection.jid;
......@@ -2249,6 +2243,11 @@
},
},
'settings': {
'update': function (settings) {
utils.merge(_converse.default_settings, settings);
utils.merge(_converse, settings);
utils.applyUserSettings(_converse, settings, _converse.user_settings);
},
'get': function (key) {
if (_.includes(_.keys(_converse.default_settings), key)) {
return _converse[key];
......@@ -2264,6 +2263,14 @@
}
}
},
'promises': {
'add': function (promises) {
promises = _.isArray(promises) ? promises : [promises]
_.each(promises, function (promise) {
_converse.promises[promise] = new $.Deferred();
});
}
},
'contacts': {
'get': function (jids) {
var _transform = function (jid) {
......
......@@ -335,7 +335,7 @@
*/
var _converse = this._converse;
this.updateSettings({
_converse.api.settings.update({
allow_dragresize: true,
});
......
......@@ -97,7 +97,7 @@
},
initialize: function () {
this.updateSettings({
this._converse.api.settings.update({
chatview_avatar_height: 44,
chatview_avatar_width: 44,
hide_open_bookmarks: true,
......
......@@ -205,7 +205,7 @@
*/
var _converse = this._converse;
this.updateSettings({
_converse.api.settings.update({
archived_messages_page_size: '50',
message_archiving: undefined, // Supported values are 'always', 'never', 'roster' (https://xmpp.org/extensions/xep-0313.html#prefs)
message_archiving_timeout: 8000, // Time (in milliseconds) to wait before aborting MAM request
......
......@@ -312,7 +312,7 @@
_converse.templates.trimmed_chat = tpl_trimmed_chat;
_converse.templates.chats_panel = tpl_chats_panel;
this.updateSettings({
_converse.api.settings.update({
no_trimming: false, // Set to true for phantomjs tests (where browser apparently has no width)
});
......
......@@ -330,7 +330,7 @@
// ====================================
// Refer to docs/source/configuration.rst for explanations of these
// configuration settings.
this.updateSettings({
_converse.api.settings.update({
allow_muc: true,
allow_muc_invitations: true,
auto_join_on_invite: false,
......@@ -347,10 +347,7 @@
'toggle_occupants': true
},
});
_.extend(_converse.promises, {
'roomsPanelRendered': new $.Deferred()
});
_converse.api.promises.add('roomsPanelRendered');
_converse.openChatRoom = function (settings) {
/* Opens a chat room, making sure that certain attributes
......
......@@ -28,7 +28,7 @@
_converse.supports_html5_notification = "Notification" in window;
this.updateSettings({
_converse.api.settings.update({
notify_all_room_messages: false,
show_desktop_notifications: true,
show_chatstate_notifications: false,
......
......@@ -459,7 +459,7 @@
var _converse = this._converse,
__ = _converse.__;
this.updateSettings({
_converse.api.settings.update({
allow_otr: true,
cache_otr_key: false,
use_otr_by_default: false
......
......@@ -25,7 +25,7 @@
*/
var _converse = this._converse;
this.updateSettings({
_converse.api.settings.update({
ping_interval: 180 //in seconds
});
......
......@@ -112,7 +112,7 @@
_converse.templates.registration_form = tpl_registration_form;
_converse.templates.registration_request = tpl_registration_request;
this.updateSettings({
_converse.api.settings.update({
allow_registration: true,
domain_placeholder: __(" e.g. conversejs.org"), // Placeholder text shown in the domain input on the registration form
providers_link: 'https://xmpp.net/directory.php', // Link to XMPP providers shown on registration page
......
......@@ -75,7 +75,7 @@
__ = _converse.__,
___ = _converse.___;
this.updateSettings({
_converse.api.settings.update({
allow_chat_pending_contacts: true,
allow_contact_removal: true,
show_toolbar: true,
......
......@@ -56,7 +56,7 @@
* loaded by converse.js's plugin machinery.
*/
var _converse = this._converse;
this.updateSettings({
_converse.api.settings.update({
use_vcards: true,
});
......
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