Skip to content

Commit

Permalink
Add an API for registring new types of chatboxes
Browse files Browse the repository at this point in the history
Previously the `overrides` functionality of `pluggable.js` was used to
`override` the `model` function on the `ChatBoxes` collection, so that
different types of chatboxes could be created (e.g. MUC, ChatBox, Feed).

This has been replaced with a registry, `api.chatboxes.registry`.

Use `api.chatboxes.registry.add(type, model)` to add a new type of chatbox to
the collection.

Then when `api.chatboxes.create(attrs, options)` is called, the right type of
chatbox will be created if `attrs.type` is the `type` in the registry.
  • Loading branch information
jcbrand committed Aug 2, 2023
1 parent 75c5d2a commit c31f237
Show file tree
Hide file tree
Showing 10 changed files with 89 additions and 13 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"callback-return": "off",
"camelcase": "off",
"capitalized-comments": "off",
"class-methods-use-this": "error",
"class-methods-use-this": "off",
"comma-dangle": "off",
"comma-spacing": "off",
"comma-style": "off",
Expand Down
13 changes: 13 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,19 @@ Breaking changes:
- Remove the old `_converse.BootstrapModal` in favor of `_converse.BaseModal`
which is a web component.

Adding more types of chats:
Previously the `overrides` functionality of `pluggable.js` was used to
`override` the `model` function on the `ChatBoxes` collection, so that
different types of chatboxes could be created (e.g. MUC, ChatBox, Feed).

This has been replaced with a registry, `api.chatboxes.registry`.

Use `api.chatboxes.registry.add(type, model)` to add a new type of chatbox to
the collection.

Then when `api.chatboxes.create(attrs, options)` is called, the right type of
chatbox will be created if `attrs.type` is the `type` in the registry.

## 10.1.5 (2023-06-29)

- #3209: Fix error when importing the `converse` global with bootstrap modal API
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@
},
"dependencies": {
"@converse/openpromise": "^0.0.1",
"@converse/skeletor": "conversejs/skeletor#33a1aba275a5604729918e6cb0c7f7899433a677",
"@converse/skeletor": "conversejs/skeletor#811e13b0a541e8511ba3978e49f45a1f83fd0239",
"bootstrap": "^4.6.0",
"bootstrap.native": "^2.0.27",
"client-compress": "^2.2.2",
Expand Down
5 changes: 5 additions & 0 deletions src/headless/plugins/chat/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ converse.plugins.add('converse-chat', {
Object.assign(_converse, { ChatBox, Message, Messages, handleMessageStanza });
Object.assign(api, chat_api);

api.chatboxes.registry.add(
_converse.PRIVATE_CHAT_TYPE,
ChatBox
);

_converse.router.route('converse/chat?jid=:jid', openChat);

api.listen.on('chatBoxesFetched', autoJoinChats);
Expand Down
47 changes: 41 additions & 6 deletions src/headless/plugins/chatboxes/api.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { _converse, api } from "../../index.js";
import { createChatBox } from './utils.js';

const _chatBoxTypes = {};

/** @typedef {import('@converse/skeletor').Model} Model */

/**
* The "chatboxes" namespace.
*
Expand All @@ -9,10 +13,10 @@ import { createChatBox } from './utils.js';
*/
export default {
/**
* @method api.chats.create
* @param { String|String[] } jids - A JID or array of JIDs
* @param { Object } [attrs] An object containing configuration attributes
* @param { Model } model - The type of chatbox that should be created
* @method api.chatboxes.create
* @param {string|string[]} jids - A JID or array of JIDs
* @param {Object} attrs An object containing configuration attributes
* @param {Model} model - The type of chatbox that should be created
*/
async create (jids=[], attrs={}, model) {
await api.waitUntil('chatBoxesFetched');
Expand All @@ -24,8 +28,8 @@ export default {
},

/**
* @method api.chats.get
* @param { String|String[] } jids - A JID or array of JIDs
* @method api.chatboxes.get
* @param {string|string[]} jids - A JID or array of JIDs
*/
async get (jids) {
await api.waitUntil('chatBoxesFetched');
Expand All @@ -37,5 +41,36 @@ export default {
jids = jids.map(j => j.toLowerCase());
return _converse.chatboxes.models.filter(m => jids.includes(m.get('jid')));
}
},

/**
* The "chatboxes" registry.
* Allows you to register more chatbox types that can be created via
* `api.chatboxes.create`.
* @namespace api.chatboxes.registry
* @memberOf api.chatboxes
*/
registry: {
/**
* @method api.chatboxes.registry.add
* Add another type of chatbox that can be added to this collection.
* This is used in the `createModel` function to determine what type of
* chatbox class to instantiate (e.g. ChatBox, MUC, Feed etc.) based on the
* passed in attributes.
* @param {string} type - The type name
* @param {Model} model - The model which will be instantiated for the given type name.
*/
add(type, model) {
_chatBoxTypes[type] = model;
},

/**
* @method api.chatboxes.registry.get
* @param {string} type - The type name
* @return {Model} model - The model which will be instantiated for the given type name.
*/
get(type) {
return _chatBoxTypes[type];
}
}
}
12 changes: 10 additions & 2 deletions src/headless/plugins/chatboxes/chatboxes.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { _converse, api } from "../../index.js";
import { initStorage } from '@converse/headless/utils/storage.js';

class ChatBoxes extends Collection {
get comparator () { // eslint-disable-line class-methods-use-this
get comparator () {
return 'time_opened';
}

onChatBoxesFetched (collection) { // eslint-disable-line class-methods-use-this
onChatBoxesFetched (collection) {
collection.filter(c => !c.isValid()).forEach(c => c.destroy());
/**
* Triggered once all chat boxes have been recreated from the browser cache
Expand All @@ -29,6 +29,14 @@ class ChatBoxes extends Collection {
'success': c => this.onChatBoxesFetched(c)
});
}

createModel (attrs, options) {
if (!attrs.type) {
throw new Error("You need to specify a type of chatbox to be created");
}
const ChatBox = api.chatboxes.registry.get(attrs.type);
return new ChatBox(attrs, options);
}
}

export default ChatBoxes;
5 changes: 5 additions & 0 deletions src/headless/plugins/headlines/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,10 @@ converse.plugins.add('converse-headlines', {
api.listen.on('reconnected', registerHeadlineHandler);

Object.assign(api, headlines_api);

api.chatboxes.registry.add(
_converse.HEADLINES_TYPE,
HeadlinesFeed
);
}
});
5 changes: 5 additions & 0 deletions src/headless/plugins/muc/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,11 @@ converse.plugins.add('converse-muc', {
_converse.ChatRoomOccupants = ChatRoomOccupants;
_converse.ChatRoomOccupant = ChatRoomOccupant;

api.chatboxes.registry.add(
_converse.CHATROOMS_TYPE,
MUC
);

Object.assign(_converse, {
getDefaultMUCNickname,
isInfoVisible,
Expand Down
5 changes: 5 additions & 0 deletions src/plugins/controlbox/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ converse.plugins.add('converse-controlbox', {
_converse.ControlBox = ControlBox;
_converse.ControlBoxToggle = ControlBoxToggle;

api.chatboxes.registry.add(
_converse.CONTROLBOX_TYPE,
ControlBox
);

api.listen.on('chatBoxesFetched', onChatBoxesFetched);
api.listen.on('clearSession', clearSession);
api.listen.on('will-reconnect', disconnect);
Expand Down

0 comments on commit c31f237

Please sign in to comment.