Răsfoiți Sursa

Add an API for registering new types of chatboxes

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.
JC Brand 2 ani în urmă
părinte
comite
33937db5e8

+ 13 - 0
CHANGES.md

@@ -14,6 +14,19 @@
 - #3246: Badge color not responsive to dark theme
 - Fix a GIF rendering bug that causes a memory overflow
 
+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

+ 7 - 1
package-lock.json

@@ -13,7 +13,7 @@
       ],
       "dependencies": {
         "@converse/openpromise": "^0.0.1",
-        "@converse/skeletor": "^0.0.8",
+        "@converse/skeletor": "conversejs/skeletor#811e13b0a541e8511ba3978e49f45a1f83fd0239",
         "bootstrap": "^4.6.0",
         "bootstrap.native": "^2.0.27",
         "client-compress": "^2.2.2",
@@ -1837,8 +1837,14 @@
     },
     "node_modules/@converse/skeletor": {
       "version": "0.0.8",
+<<<<<<< HEAD
       "resolved": "https://registry.npmjs.org/@converse/skeletor/-/skeletor-0.0.8.tgz",
       "integrity": "sha512-8/wAenuk7QKOHaOsk89e5zFyQZz5HhsuqWBzrzDxmepiBVlRvnxjVdB6619IFyW0VWf0ezcm5Rl4JndUx2sbqg==",
+=======
+      "resolved": "git+ssh://git@github.com/conversejs/skeletor.git#811e13b0a541e8511ba3978e49f45a1f83fd0239",
+      "integrity": "sha512-geSpNFrBw5lB3P3AZsDVmrI4ShYWMzsAQgEmMTG7f41N0IrADP6FZIy896rrVZNddfc8xQwNAC/bMdrCcqKulQ==",
+      "license": "MIT",
+>>>>>>> a1da291f4 (Add an API for registering new types of chatboxes)
       "dependencies": {
         "@converse/localforage-getitems": "1.4.3",
         "lit-html": "^2.0.0-rc.2",

+ 1 - 1
package.json

@@ -113,7 +113,7 @@
   },
   "dependencies": {
     "@converse/openpromise": "^0.0.1",
-    "@converse/skeletor": "^0.0.8",
+    "@converse/skeletor": "conversejs/skeletor#811e13b0a541e8511ba3978e49f45a1f83fd0239",
     "bootstrap": "^4.6.0",
     "bootstrap.native": "^2.0.27",
     "client-compress": "^2.2.2",

+ 5 - 0
src/headless/plugins/chat/index.js

@@ -41,6 +41,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);

+ 41 - 6
src/headless/plugins/chatboxes/api.js

@@ -2,6 +2,10 @@ import _converse from '../../shared/_converse.js';
 import api from '../../shared/api/index.js';
 import { createChatBox } from './utils.js';
 
+const _chatBoxTypes = {};
+
+/** @typedef {import('@converse/skeletor').Model} Model */
+
 /**
  * The "chatboxes" namespace.
  *
@@ -10,10 +14,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');
@@ -25,8 +29,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');
@@ -38,5 +42,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];
+        }
     }
 }

+ 10 - 2
src/headless/plugins/chatboxes/chatboxes.js

@@ -4,11 +4,11 @@ import { Collection } from "@converse/skeletor/src/collection";
 import { initStorage } from '../../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
@@ -30,6 +30,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 - 0
src/headless/plugins/headlines/index.js

@@ -30,5 +30,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 - 0
src/headless/plugins/muc/index.js

@@ -183,6 +183,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,

+ 5 - 0
src/plugins/controlbox/index.js

@@ -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);