docs: Discourage usage of overrides and add hook to example plugin
This commit is contained in:
parent
eb29d962f5
commit
990aefc6cb
|
@ -23,7 +23,7 @@ to fix a bug or to add new functionality.
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
setup_dev_environment
|
setup_dev_environment
|
||||||
plugin_development
|
plugin_development
|
||||||
api/index
|
api/index
|
||||||
testing
|
testing
|
||||||
|
|
|
@ -16,7 +16,7 @@ and is itself composed out of plugins.
|
||||||
There are only a few files that are included in the default build of Converse
|
There are only a few files that are included in the default build of Converse
|
||||||
which aren't plugins.
|
which aren't plugins.
|
||||||
|
|
||||||
An important one is `converse-core.js <https://github.com/conversejs/converse.js/blob/master/src/headless/converse-core.js>`_,
|
An important one is `core.js <https://github.com/conversejs/.js/blob/master/src/headless/core.js>`_,
|
||||||
which is responsible for bootstrapping the plugin architecture,
|
which is responsible for bootstrapping the plugin architecture,
|
||||||
setting up and maintaining the connection to the XMPP
|
setting up and maintaining the connection to the XMPP
|
||||||
server and declaring the public (`window.converse </docs/html/api/converse.html>`_) and protected (`_converse.api </docs/html/api/-_converse.api.html>`_) APIs.
|
server and declaring the public (`window.converse </docs/html/api/converse.html>`_) and protected (`_converse.api </docs/html/api/-_converse.api.html>`_) APIs.
|
||||||
|
@ -180,11 +180,59 @@ The code for it could look something like this:
|
||||||
These dependencies are closured so that they don't pollute the global
|
These dependencies are closured so that they don't pollute the global
|
||||||
namespace, that's why you need to access them in such a way inside the module.
|
namespace, that's why you need to access them in such a way inside the module.
|
||||||
|
|
||||||
Overrides
|
Overriding templates
|
||||||
---------
|
--------------------
|
||||||
|
|
||||||
|
Converse uses `lit-html <https://lit-html.polymer-project.org/guide>`_
|
||||||
|
templates and templates are imported as separate files.
|
||||||
|
|
||||||
|
It's possible to configure your module bundler (e.g. Webpack) in such as way that a
|
||||||
|
different file is loaded when a template is imported.
|
||||||
|
|
||||||
|
This allows you to create your own templates that are used instead of the ones
|
||||||
|
that would have originally been imported.
|
||||||
|
|
||||||
|
With Webpack (which Converse uses internally), you can specify an
|
||||||
|
``alias`` for the template you want to override. This alias then points to your
|
||||||
|
own custom template.
|
||||||
|
|
||||||
|
For example, in your webpack config file, you could add the following to the
|
||||||
|
``config`` object that gets exported:
|
||||||
|
|
||||||
|
.. code-block:: javascript
|
||||||
|
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.js'],
|
||||||
|
modules: [
|
||||||
|
path.join(__dirname, 'node_modules'),
|
||||||
|
path.join(__dirname, 'node_modules/converse.js/src')
|
||||||
|
],
|
||||||
|
alias: {
|
||||||
|
'plugins/profile/templates/profile.js$': path.resolve(__dirname, 'templates/custom-profile.js')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
This will override the template that gets imported at the path ``plugins/profile/templates/profile.js``
|
||||||
|
with your own template at the path ``templates/custom-profile.js`` (relative to your webpack config file).
|
||||||
|
|
||||||
|
|
||||||
|
Object and class Overrides
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
.. note:: Using the `overrides` feature from pluggable.js is discouraged. It's
|
||||||
|
much better to use events, promises and `hooks`_ to modify the behaviour of
|
||||||
|
Converse.
|
||||||
|
|
||||||
|
The pluggable.js `overrides` will only work on objects and classes that are
|
||||||
|
set as attributes on the `_converse` object, which doesn't apply to many
|
||||||
|
newer classes and objects, such as the web components. For these clasess,
|
||||||
|
overrides won't work at all.
|
||||||
|
|
||||||
|
This section is left here for completeness, because in some special cases
|
||||||
|
overrides are still used.
|
||||||
|
|
||||||
Plugins can override core code or code from other plugins. You can specify
|
Plugins can override core code or code from other plugins. You can specify
|
||||||
overrides in the object passed to ``converse.plugins.add``.
|
overrides in the object passed to ``converse.plugins.add``.
|
||||||
|
|
||||||
In an override you can still call the overridden function, by calling
|
In an override you can still call the overridden function, by calling
|
||||||
``this.__super__.methodName.apply(this, arguments);`` where ``methodName`` is
|
``this.__super__.methodName.apply(this, arguments);`` where ``methodName`` is
|
||||||
|
@ -242,7 +290,7 @@ monkey patching which pollutes the call stack and can make your code fragile
|
||||||
and prone to bugs when Converse gets updated. Too much use of ``overrides``
|
and prone to bugs when Converse gets updated. Too much use of ``overrides``
|
||||||
is therefore a "code smell" which should ideally be avoided.
|
is therefore a "code smell" which should ideally be avoided.
|
||||||
|
|
||||||
A better approach is to listen to the events emitted by Converse, and to add
|
A better approach is to use the events and `hooks`_ emitted by Converse, and to add
|
||||||
your code in event handlers. This is however not always possible, in which case
|
your code in event handlers. This is however not always possible, in which case
|
||||||
the overrides are a powerful tool.
|
the overrides are a powerful tool.
|
||||||
|
|
||||||
|
@ -260,40 +308,6 @@ For example:
|
||||||
Object.assign(_converse.ChatBoxView.prototype, { doSomething });
|
Object.assign(_converse.ChatBoxView.prototype, { doSomething });
|
||||||
|
|
||||||
|
|
||||||
Overriding a template
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Converse uses `lit-html <https://lit-html.polymer-project.org/guide>`_
|
|
||||||
templates.
|
|
||||||
|
|
||||||
It's not possible to override a template with the plugin's ``overrides``
|
|
||||||
feature, instead you should configure a new path to your own template via your
|
|
||||||
module bundler.
|
|
||||||
|
|
||||||
For example, with Webpack (which Converse uses internall), you can specify an
|
|
||||||
``alias`` for the template you want to override. This alias then points to your
|
|
||||||
own custom template.
|
|
||||||
|
|
||||||
For example, in your webpack config file, you could add the following to the
|
|
||||||
``config`` object that gets exported:
|
|
||||||
|
|
||||||
.. code-block:: javascript
|
|
||||||
|
|
||||||
resolve: {
|
|
||||||
extensions: ['.js'],
|
|
||||||
modules: [
|
|
||||||
path.join(__dirname, 'node_modules'),
|
|
||||||
path.join(__dirname, 'node_modules/converse.js/src')
|
|
||||||
],
|
|
||||||
alias: {
|
|
||||||
'plugins/profile/templates/profile.js$': path.resolve(__dirname, 'templates/custom-profile.js')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
This will override the template that gets imported at the path ``plugins/profile/templates/profile.js``
|
|
||||||
with your own template at the path ``templates/custom-profile.js`` (relative to
|
|
||||||
your webpack config file).
|
|
||||||
|
|
||||||
|
|
||||||
.. _`dependencies`:
|
.. _`dependencies`:
|
||||||
|
|
||||||
|
@ -515,8 +529,8 @@ The `Actions <https://github.com/conversejs/community-plugins/tree/master/packag
|
||||||
``like`` or ``dislike`` to chat messages.
|
``like`` or ``dislike`` to chat messages.
|
||||||
|
|
||||||
|
|
||||||
A full example plugin
|
An example plugin
|
||||||
---------------------
|
-----------------
|
||||||
|
|
||||||
Below follows a documented example of a plugin. This is the same code that gets
|
Below follows a documented example of a plugin. This is the same code that gets
|
||||||
generated by `generator-conversejs <https://github.com/jcbrand/generator-conversejs>`_.
|
generated by `generator-conversejs <https://github.com/jcbrand/generator-conversejs>`_.
|
||||||
|
@ -590,8 +604,8 @@ generated by `generator-conversejs <https://github.com/jcbrand/generator-convers
|
||||||
* _converse.api.promises.add('myPromise');
|
* _converse.api.promises.add('myPromise');
|
||||||
*
|
*
|
||||||
* Your plugin should then, when appropriate, resolve the
|
* Your plugin should then, when appropriate, resolve the
|
||||||
* promise by calling `_converse.api.emit`, which will also
|
* promise by calling `_converse.api.trigger`, which will also
|
||||||
* emit an event with the same name as the promise.
|
* trigger an event with the same name as the promise.
|
||||||
* For example:
|
* For example:
|
||||||
*
|
*
|
||||||
* _converse.api.trigger('operationCompleted');
|
* _converse.api.trigger('operationCompleted');
|
||||||
|
@ -605,53 +619,22 @@ generated by `generator-conversejs <https://github.com/jcbrand/generator-convers
|
||||||
*
|
*
|
||||||
* _converse.api.waitUntil('operationCompleted', function { ... });
|
* _converse.api.waitUntil('operationCompleted', function { ... });
|
||||||
*/
|
*/
|
||||||
},
|
|
||||||
|
|
||||||
/* If you want to override some function or a model or
|
|
||||||
* view defined elsewhere in Converse, then you do that under
|
/* In your plugin, you can also listen for hooks.
|
||||||
* the "overrides" namespace.
|
* Hooks allow you to add or modify data and properties used by
|
||||||
*/
|
* Converse.
|
||||||
overrides: {
|
*
|
||||||
/* For example, the private *_converse* object has a
|
* For example, the getToolbarButtons hook allows you to add new buttons to the chat toolbar.
|
||||||
* method "onConnected". You can override that method as follows:
|
* https://conversejs.org/docs/html/api/-_converse.html#event:getToolbarButtons
|
||||||
*/
|
*/
|
||||||
onConnected: function () {
|
api.listen.on('getToolbarButtons', (toolbar_el, buttons) => {
|
||||||
// Overrides the onConnected method in Converse
|
buttons.push(html`
|
||||||
|
<button class="my-button" @click=${alert('hello world!')}>
|
||||||
// Top-level functions in "overrides" are bound to the
|
<converse-icon class="fa fa-eye" size="1em" color="blue"></converse-icon>
|
||||||
// inner "_converse" object.
|
</button>
|
||||||
const _converse = this;
|
`);
|
||||||
|
return buttons;
|
||||||
// Your custom code can come here ...
|
});
|
||||||
|
|
||||||
// You can access the original function being overridden
|
|
||||||
// via the __super__ attribute.
|
|
||||||
// Make sure to pass on the arguments supplied to this
|
|
||||||
// function and also to apply the proper "this" object.
|
|
||||||
_converse.__super__.onConnected.apply(this, arguments);
|
|
||||||
|
|
||||||
// Your custom code can come here ...
|
|
||||||
},
|
|
||||||
|
|
||||||
/* Override Converse's XMPPStatus model so that we can override the
|
|
||||||
* function that sends out the presence stanza.
|
|
||||||
*/
|
|
||||||
XMPPStatus: {
|
|
||||||
sendPresence: function (type, status_message, jid) {
|
|
||||||
// The "_converse" object is available via the __super__
|
|
||||||
// attribute.
|
|
||||||
const _converse = this.__super__._converse;
|
|
||||||
|
|
||||||
// Custom code can come here ...
|
|
||||||
|
|
||||||
// You can call the original overridden method, by
|
|
||||||
// accessing it via the __super__ attribute.
|
|
||||||
// When calling it, you need to apply the proper
|
|
||||||
// context as reference by the "this" variable.
|
|
||||||
this.__super__.sendPresence.apply(this, arguments);
|
|
||||||
|
|
||||||
// Custom code can come here ...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue