Browse Source

Move the MUC list modal to its own file

JC Brand 5 years ago
parent
commit
1898e7865d
5 changed files with 205 additions and 194 deletions
  1. 1 1
      karma.conf.js
  2. 3 4
      spec/muc.js
  3. 1 1
      spec/muclist.js
  4. 8 188
      src/converse-muc-views.js
  5. 192 0
      src/modals/muc-list.js

+ 1 - 1
karma.conf.js

@@ -26,7 +26,7 @@ module.exports = function(config) {
 
       { pattern: "spec/spoilers.js", type: 'module' },
       { pattern: "spec/emojis.js", type: 'module' },
-      { pattern: "spec/roomslist.js", type: 'module' },
+      { pattern: "spec/muclist.js", type: 'module' },
       { pattern: "spec/utils.js", type: 'module' },
       { pattern: "spec/converse.js", type: 'module' },
       { pattern: "spec/bookmarks.js", type: 'module' },

+ 3 - 4
spec/muc.js

@@ -12,7 +12,6 @@ const u = converse.env.utils;
 
 describe("Groupchats", function () {
 
-
     describe("The \"rooms\" API", function () {
 
         it("has a method 'close' which closes rooms by JID or all rooms when called with no arguments",
@@ -4862,7 +4861,7 @@ describe("Groupchats", function () {
             const roomspanel = _converse.chatboxviews.get('controlbox').roomspanel;
             roomspanel.el.querySelector('.show-list-muc-modal').click();
             mock.closeControlBox(_converse);
-            const modal = roomspanel.list_rooms_modal;
+            const modal = roomspanel.muc_list_modal;
             await u.waitUntil(() => u.isVisible(modal.el), 1000);
             spyOn(_converse.ChatRoom.prototype, 'getDiscoInfo').and.callFake(() => Promise.resolve());
             roomspanel.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
@@ -4939,7 +4938,7 @@ describe("Groupchats", function () {
             const roomspanel = _converse.chatboxviews.get('controlbox').roomspanel;
             roomspanel.el.querySelector('.show-list-muc-modal').click();
             mock.closeControlBox(_converse);
-            const modal = roomspanel.list_rooms_modal;
+            const modal = roomspanel.muc_list_modal;
             await u.waitUntil(() => u.isVisible(modal.el), 1000);
             const server_input = modal.el.querySelector('input[name="server"]');
             expect(server_input.value).toBe('muc.example.org');
@@ -4956,7 +4955,7 @@ describe("Groupchats", function () {
             const roomspanel = _converse.chatboxviews.get('controlbox').roomspanel;
             roomspanel.el.querySelector('.show-list-muc-modal').click();
             mock.closeControlBox(_converse);
-            const modal = roomspanel.list_rooms_modal;
+            const modal = roomspanel.muc_list_modal;
             await u.waitUntil(() => u.isVisible(modal.el), 1000);
             spyOn(_converse.ChatRoom.prototype, 'getDiscoInfo').and.callFake(() => Promise.resolve());
             roomspanel.delegateEvents(); // We need to rebind all events otherwise our spy won't be called

+ 1 - 1
spec/roomslist.js → spec/muclist.js

@@ -1,4 +1,4 @@
-/* global mock */
+/* global mock, converse */
 
 describe("A list of open groupchats", function () {
 

+ 8 - 188
src/converse-muc-views.js

@@ -6,10 +6,10 @@
  */
 import "@converse/headless/utils/muc";
 import "converse-modal";
+import MUCListModal from 'modals/muc-list.js';
 import ModeratorToolsModal from "./modals/moderator-tools.js";
 import RoomDetailsModal from 'modals/muc-details.js';
 import log from "@converse/headless/log";
-import st from "@converse/headless/utils/stanza";
 import tpl_add_chatroom_modal from "templates/add_chatroom_modal.js";
 import tpl_chatroom from "templates/chatroom.js";
 import tpl_chatroom_bottom_panel from "templates/chatroom_bottom_panel.html";
@@ -17,12 +17,10 @@ import tpl_chatroom_destroyed from "templates/chatroom_destroyed.html";
 import tpl_chatroom_disconnect from "templates/chatroom_disconnect.html";
 import tpl_chatroom_head from "templates/chatroom_head.js";
 import tpl_chatroom_nickname_form from "templates/chatroom_nickname_form.html";
-import tpl_list_chatrooms_modal from "templates/list_chatrooms_modal.js";
 import tpl_muc_config_form from "templates/muc_config_form.js";
 import tpl_muc_invite_modal from "templates/muc_invite_modal.js";
 import tpl_muc_password_form from "templates/muc_password_form.js";
 import tpl_muc_sidebar from "templates/muc_sidebar.js";
-import tpl_room_description from "templates/room_description.html";
 import tpl_room_panel from "templates/room_panel.html";
 import tpl_spinner from "templates/spinner.html";
 import { BootstrapModal } from "./converse-modal.js";
@@ -30,10 +28,10 @@ import { Model } from '@converse/skeletor/src/model.js';
 import { View } from '@converse/skeletor/src/view.js';
 import { __ } from '@converse/headless/i18n';
 import { api, converse } from "@converse/headless/converse-core";
-import { debounce, head, isString, isUndefined } from "lodash-es";
+import { debounce, isString, isUndefined } from "lodash-es";
 import { render } from "lit-html";
 
-const { Strophe, sizzle, $iq, $pres } = converse.env;
+const { Strophe, sizzle, $pres } = converse.env;
 const u = converse.env.utils;
 
 const OWNER_COMMANDS = ['owner'];
@@ -151,184 +149,6 @@ converse.plugins.add('converse-muc-views', {
             Object.assign(_converse.ControlBoxView.prototype, viewWithRoomsPanel);
         }
 
-        /* Insert groupchat info (based on returned #disco IQ stanza)
-         * @function insertRoomInfo
-         * @param { HTMLElement } el - The HTML DOM element that contains the info.
-         * @param { XMLElement } stanza - The IQ stanza containing the groupchat info.
-         */
-        function insertRoomInfo (el, stanza) {
-            // All MUC features found here: https://xmpp.org/registrar/disco-features.html
-            el.querySelector('span.spinner').remove();
-            el.querySelector('a.room-info').classList.add('selected');
-            el.insertAdjacentHTML(
-                'beforeEnd',
-                tpl_room_description({
-                    'jid': stanza.getAttribute('from'),
-                    'desc': head(sizzle('field[var="muc#roominfo_description"] value', stanza))?.textContent,
-                    'occ': head(sizzle('field[var="muc#roominfo_occupants"] value', stanza))?.textContent,
-                    'hidden': sizzle('feature[var="muc_hidden"]', stanza).length,
-                    'membersonly': sizzle('feature[var="muc_membersonly"]', stanza).length,
-                    'moderated': sizzle('feature[var="muc_moderated"]', stanza).length,
-                    'nonanonymous': sizzle('feature[var="muc_nonanonymous"]', stanza).length,
-                    'open': sizzle('feature[var="muc_open"]', stanza).length,
-                    'passwordprotected': sizzle('feature[var="muc_passwordprotected"]', stanza).length,
-                    'persistent': sizzle('feature[var="muc_persistent"]', stanza).length,
-                    'publicroom': sizzle('feature[var="muc_publicroom"]', stanza).length,
-                    'semianonymous': sizzle('feature[var="muc_semianonymous"]', stanza).length,
-                    'temporary': sizzle('feature[var="muc_temporary"]', stanza).length,
-                    'unmoderated': sizzle('feature[var="muc_unmoderated"]', stanza).length,
-                    'label_desc': __('Description:'),
-                    'label_jid': __('Groupchat Address (JID):'),
-                    'label_occ': __('Participants:'),
-                    'label_features': __('Features:'),
-                    'label_requires_auth': __('Requires authentication'),
-                    'label_hidden': __('Hidden'),
-                    'label_requires_invite': __('Requires an invitation'),
-                    'label_moderated': __('Moderated'),
-                    'label_non_anon': __('Non-anonymous'),
-                    'label_open_room': __('Open'),
-                    'label_permanent_room': __('Permanent'),
-                    'label_public': __('Public'),
-                    'label_semi_anon':  __('Semi-anonymous'),
-                    'label_temp_room':  __('Temporary'),
-                    'label_unmoderated': __('Unmoderated')
-                }));
-        }
-
-        /**
-         * Show/hide extra information about a groupchat in a listing.
-         * @function toggleRoomInfo
-         * @param { Event }
-         */
-        function toggleRoomInfo (ev) {
-            const parent_el = u.ancestor(ev.target, '.room-item');
-            const div_el = parent_el.querySelector('div.room-info');
-            if (div_el) {
-                u.slideIn(div_el).then(u.removeElement)
-                parent_el.querySelector('a.room-info').classList.remove('selected');
-            } else {
-                parent_el.insertAdjacentHTML('beforeend', tpl_spinner());
-                api.disco.info(ev.target.getAttribute('data-room-jid'), null)
-                    .then(stanza => insertRoomInfo(parent_el, stanza))
-                    .catch(e => log.error(e));
-            }
-        }
-
-
-        _converse.ListChatRoomsModal = BootstrapModal.extend({
-            id: "list-chatrooms-modal",
-
-            initialize () {
-                this.items = [];
-                this.loading_items = false;
-
-                BootstrapModal.prototype.initialize.apply(this, arguments);
-                if (api.settings.get('muc_domain') && !this.model.get('muc_domain')) {
-                    this.model.save('muc_domain', api.settings.get('muc_domain'));
-                }
-                this.listenTo(this.model, 'change:muc_domain', this.onDomainChange);
-            },
-
-            toHTML () {
-                const muc_domain = this.model.get('muc_domain') || api.settings.get('muc_domain');
-                return tpl_list_chatrooms_modal(
-                    Object.assign(this.model.toJSON(), {
-                        'show_form': !api.settings.get('locked_muc_domain'),
-                        'server_placeholder': muc_domain ? muc_domain : __('conference.example.org'),
-                        'items': this.items,
-                        'loading_items': this.loading_items,
-                        'openRoom': ev => this.openRoom(ev),
-                        'setDomainFromEvent': ev => this.setDomainFromEvent(ev),
-                        'submitForm': ev => this.showRooms(ev),
-                        'toggleRoomInfo': ev => this.toggleRoomInfo(ev)
-                    }));
-            },
-
-            afterRender () {
-                if (api.settings.get('locked_muc_domain')) {
-                    this.updateRoomsList();
-                } else {
-                    this.el.addEventListener('shown.bs.modal',
-                        () => this.el.querySelector('input[name="server"]').focus(),
-                        false
-                    );
-                }
-            },
-
-            openRoom (ev) {
-                ev.preventDefault();
-                const jid = ev.target.getAttribute('data-room-jid');
-                const name = ev.target.getAttribute('data-room-name');
-                this.modal.hide();
-                api.rooms.open(jid, {'name': name}, true);
-            },
-
-            toggleRoomInfo (ev) {
-                ev.preventDefault();
-                toggleRoomInfo(ev);
-            },
-
-            onDomainChange () {
-                api.settings.get('auto_list_rooms') && this.updateRoomsList();
-            },
-
-            /**
-             * Handle the IQ stanza returned from the server, containing
-             * all its public groupchats.
-             * @private
-             * @method _converse.ChatRoomView#onRoomsFound
-             * @param { HTMLElement } iq
-             */
-            onRoomsFound (iq) {
-                this.loading_items = false;
-                const rooms = iq ? sizzle('query item', iq) : [];
-                if (rooms.length) {
-                    this.model.set({'feedback_text': __('Groupchats found')}, {'silent': true});
-                    this.items = rooms.map(st.getAttributes);
-                } else {
-                    this.items = [];
-                    this.model.set({'feedback_text': __('No groupchats found')}, {'silent': true});
-                }
-                this.render();
-                return true;
-            },
-
-            /**
-             * Send an IQ stanza to the server asking for all groupchats
-             * @private
-             * @method _converse.ChatRoomView#updateRoomsList
-             */
-            updateRoomsList () {
-                const iq = $iq({
-                    'to': this.model.get('muc_domain'),
-                    'from': _converse.connection.jid,
-                    'type': "get"
-                }).c("query", {xmlns: Strophe.NS.DISCO_ITEMS});
-                api.sendIQ(iq)
-                    .then(iq => this.onRoomsFound(iq))
-                    .catch(() => this.onRoomsFound())
-            },
-
-            showRooms (ev) {
-                ev.preventDefault();
-                this.loading_items = true;
-                this.render();
-
-                const data = new FormData(ev.target);
-                this.model.setDomain(data.get('server'));
-                this.updateRoomsList();
-            },
-
-            setDomainFromEvent (ev) {
-                this.model.setDomain(ev.target.value);
-            },
-
-            setNick (ev) {
-                this.model.save({nick: ev.target.value});
-            }
-        });
-
-
         _converse.AddChatRoomModal = BootstrapModal.extend({
             id: 'add-chatroom-modal',
 
@@ -1716,7 +1536,7 @@ converse.plugins.add('converse-muc-views', {
             id: 'chatrooms',
             events: {
                 'click a.controlbox-heading__btn.show-add-muc-modal': 'showAddRoomModal',
-                'click a.controlbox-heading__btn.show-list-muc-modal': 'showListRoomsModal'
+                'click a.controlbox-heading__btn.show-list-muc-modal': 'showMUCListModal'
             },
 
             render () {
@@ -1735,11 +1555,11 @@ converse.plugins.add('converse-muc-views', {
                 this.add_room_modal.show(ev);
             },
 
-            showListRoomsModal(ev) {
-                if (this.list_rooms_modal === undefined) {
-                    this.list_rooms_modal = new _converse.ListChatRoomsModal({'model': this.model});
+            showMUCListModal(ev) {
+                if (this.muc_list_modal === undefined) {
+                    this.muc_list_modal = new MUCListModal({'model': this.model});
                 }
-                this.list_rooms_modal.show(ev);
+                this.muc_list_modal.show(ev);
             }
         });
 

+ 192 - 0
src/modals/muc-list.js

@@ -0,0 +1,192 @@
+import log from "@converse/headless/log";
+import sizzle from 'sizzle';
+import st from "@converse/headless/utils/stanza";
+import tpl_list_chatrooms_modal from "templates/list_chatrooms_modal.js";
+import tpl_room_description from "templates/room_description.html";
+import tpl_spinner from "templates/spinner.html";
+import { BootstrapModal } from "../converse-modal.js";
+import { Strophe, $iq } from 'strophe.js/src/strophe';
+import { __ } from '@converse/headless/i18n';
+import { _converse, api, converse } from "@converse/headless/converse-core";
+import { head } from "lodash-es";
+
+const u = converse.env.utils;
+
+
+/* Insert groupchat info (based on returned #disco IQ stanza)
+ * @function insertRoomInfo
+ * @param { HTMLElement } el - The HTML DOM element that contains the info.
+ * @param { XMLElement } stanza - The IQ stanza containing the groupchat info.
+ */
+function insertRoomInfo (el, stanza) {
+    // All MUC features found here: https://xmpp.org/registrar/disco-features.html
+    el.querySelector('span.spinner').remove();
+    el.querySelector('a.room-info').classList.add('selected');
+    el.insertAdjacentHTML(
+        'beforeEnd',
+        tpl_room_description({
+            'jid': stanza.getAttribute('from'),
+            'desc': head(sizzle('field[var="muc#roominfo_description"] value', stanza))?.textContent,
+            'occ': head(sizzle('field[var="muc#roominfo_occupants"] value', stanza))?.textContent,
+            'hidden': sizzle('feature[var="muc_hidden"]', stanza).length,
+            'membersonly': sizzle('feature[var="muc_membersonly"]', stanza).length,
+            'moderated': sizzle('feature[var="muc_moderated"]', stanza).length,
+            'nonanonymous': sizzle('feature[var="muc_nonanonymous"]', stanza).length,
+            'open': sizzle('feature[var="muc_open"]', stanza).length,
+            'passwordprotected': sizzle('feature[var="muc_passwordprotected"]', stanza).length,
+            'persistent': sizzle('feature[var="muc_persistent"]', stanza).length,
+            'publicroom': sizzle('feature[var="muc_publicroom"]', stanza).length,
+            'semianonymous': sizzle('feature[var="muc_semianonymous"]', stanza).length,
+            'temporary': sizzle('feature[var="muc_temporary"]', stanza).length,
+            'unmoderated': sizzle('feature[var="muc_unmoderated"]', stanza).length,
+            'label_desc': __('Description:'),
+            'label_jid': __('Groupchat Address (JID):'),
+            'label_occ': __('Participants:'),
+            'label_features': __('Features:'),
+            'label_requires_auth': __('Requires authentication'),
+            'label_hidden': __('Hidden'),
+            'label_requires_invite': __('Requires an invitation'),
+            'label_moderated': __('Moderated'),
+            'label_non_anon': __('Non-anonymous'),
+            'label_open_room': __('Open'),
+            'label_permanent_room': __('Permanent'),
+            'label_public': __('Public'),
+            'label_semi_anon':  __('Semi-anonymous'),
+            'label_temp_room':  __('Temporary'),
+            'label_unmoderated': __('Unmoderated')
+        }));
+}
+
+
+/**
+ * Show/hide extra information about a groupchat in a listing.
+ * @function toggleRoomInfo
+ * @param { Event }
+ */
+function toggleRoomInfo (ev) {
+    const parent_el = u.ancestor(ev.target, '.room-item');
+    const div_el = parent_el.querySelector('div.room-info');
+    if (div_el) {
+        u.slideIn(div_el).then(u.removeElement)
+        parent_el.querySelector('a.room-info').classList.remove('selected');
+    } else {
+        parent_el.insertAdjacentHTML('beforeend', tpl_spinner());
+        api.disco.info(ev.target.getAttribute('data-room-jid'), null)
+            .then(stanza => insertRoomInfo(parent_el, stanza))
+            .catch(e => log.error(e));
+    }
+}
+
+
+export default BootstrapModal.extend({
+    id: "list-chatrooms-modal",
+
+    initialize () {
+        this.items = [];
+        this.loading_items = false;
+
+        BootstrapModal.prototype.initialize.apply(this, arguments);
+        if (api.settings.get('muc_domain') && !this.model.get('muc_domain')) {
+            this.model.save('muc_domain', api.settings.get('muc_domain'));
+        }
+        this.listenTo(this.model, 'change:muc_domain', this.onDomainChange);
+    },
+
+    toHTML () {
+        const muc_domain = this.model.get('muc_domain') || api.settings.get('muc_domain');
+        return tpl_list_chatrooms_modal(
+            Object.assign(this.model.toJSON(), {
+                'show_form': !api.settings.get('locked_muc_domain'),
+                'server_placeholder': muc_domain ? muc_domain : __('conference.example.org'),
+                'items': this.items,
+                'loading_items': this.loading_items,
+                'openRoom': ev => this.openRoom(ev),
+                'setDomainFromEvent': ev => this.setDomainFromEvent(ev),
+                'submitForm': ev => this.showRooms(ev),
+                'toggleRoomInfo': ev => this.toggleRoomInfo(ev)
+            }));
+    },
+
+    afterRender () {
+        if (api.settings.get('locked_muc_domain')) {
+            this.updateRoomsList();
+        } else {
+            this.el.addEventListener('shown.bs.modal',
+                () => this.el.querySelector('input[name="server"]').focus(),
+                false
+            );
+        }
+    },
+
+    openRoom (ev) {
+        ev.preventDefault();
+        const jid = ev.target.getAttribute('data-room-jid');
+        const name = ev.target.getAttribute('data-room-name');
+        this.modal.hide();
+        api.rooms.open(jid, {'name': name}, true);
+    },
+
+    toggleRoomInfo (ev) {
+        ev.preventDefault();
+        toggleRoomInfo(ev);
+    },
+
+    onDomainChange () {
+        api.settings.get('auto_list_rooms') && this.updateRoomsList();
+    },
+
+    /**
+     * Handle the IQ stanza returned from the server, containing
+     * all its public groupchats.
+     * @private
+     * @method _converse.ChatRoomView#onRoomsFound
+     * @param { HTMLElement } iq
+     */
+    onRoomsFound (iq) {
+        this.loading_items = false;
+        const rooms = iq ? sizzle('query item', iq) : [];
+        if (rooms.length) {
+            this.model.set({'feedback_text': __('Groupchats found')}, {'silent': true});
+            this.items = rooms.map(st.getAttributes);
+        } else {
+            this.items = [];
+            this.model.set({'feedback_text': __('No groupchats found')}, {'silent': true});
+        }
+        this.render();
+        return true;
+    },
+
+    /**
+     * Send an IQ stanza to the server asking for all groupchats
+     * @private
+     * @method _converse.ChatRoomView#updateRoomsList
+     */
+    updateRoomsList () {
+        const iq = $iq({
+            'to': this.model.get('muc_domain'),
+            'from': _converse.connection.jid,
+            'type': "get"
+        }).c("query", {xmlns: Strophe.NS.DISCO_ITEMS});
+        api.sendIQ(iq)
+            .then(iq => this.onRoomsFound(iq))
+            .catch(() => this.onRoomsFound())
+    },
+
+    showRooms (ev) {
+        ev.preventDefault();
+        this.loading_items = true;
+        this.render();
+
+        const data = new FormData(ev.target);
+        this.model.setDomain(data.get('server'));
+        this.updateRoomsList();
+    },
+
+    setDomainFromEvent (ev) {
+        this.model.setDomain(ev.target.value);
+    },
+
+    setNick (ev) {
+        this.model.save({nick: ev.target.value});
+    }
+});