Browse Source

muc-views: Update ListChatRoomsModal to make better use of lit-html

JC Brand 5 years ago
parent
commit
f68f577b71

+ 42 - 62
src/converse-muc-views.js

@@ -14,25 +14,24 @@ import { render } from "lit-html";
 import { __ } from '@converse/headless/i18n';
 import converse from "@converse/headless/converse-core";
 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";
 import tpl_chatroom_destroyed from "templates/chatroom_destroyed.html";
 import tpl_chatroom_details_modal from "templates/chatroom_details_modal.js";
 import tpl_chatroom_disconnect from "templates/chatroom_disconnect.html";
-import tpl_muc_config_form from "templates/muc_config_form.js";
 import tpl_chatroom_head from "templates/chatroom_head.js";
-import tpl_muc_invite_modal from "templates/muc_invite_modal.js";
 import tpl_chatroom_nickname_form from "templates/chatroom_nickname_form.html";
-import tpl_muc_password_form from "templates/muc_password_form.js";
-import tpl_muc_sidebar from "templates/muc_sidebar.js";
 import tpl_info from "templates/info.html";
 import tpl_list_chatrooms_modal from "templates/list_chatrooms_modal.js";
 import tpl_moderator_tools_modal from "templates/moderator_tools_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_item from "templates/room_item.html";
 import tpl_room_panel from "templates/room_panel.html";
-import tpl_rooms_results from "templates/rooms_results.html";
 import tpl_spinner from "templates/spinner.html";
 import xss from "xss/dist/xss";
 
@@ -408,15 +407,10 @@ converse.plugins.add('converse-muc-views', {
         _converse.ListChatRoomsModal = BootstrapModal.extend({
             id: "list-chatrooms-modal",
 
-            events: {
-                'submit form': 'showRooms',
-                'click a.room-info': 'toggleRoomInfo',
-                'change input[name=nick]': 'setNick',
-                'change input[name=server]': 'setDomainFromEvent',
-                'click .open-room': 'openRoom'
-            },
-
             initialize () {
+                this.items = [];
+                this.loading_items = false;
+
                 BootstrapModal.prototype.initialize.apply(this, arguments);
                 if (_converse.muc_domain && !this.model.get('muc_domain')) {
                     this.model.save('muc_domain', _converse.muc_domain);
@@ -426,10 +420,17 @@ converse.plugins.add('converse-muc-views', {
 
             toHTML () {
                 const muc_domain = this.model.get('muc_domain') || _converse.muc_domain;
-                return tpl_list_chatrooms_modal(Object.assign(this.model.toJSON(), {
-                    'show_form': !_converse.locked_muc_domain,
-                    'server_placeholder': muc_domain ? muc_domain : __('conference.example.org')
-                }));
+                return tpl_list_chatrooms_modal(
+                    Object.assign(this.model.toJSON(), {
+                        'show_form': !_converse.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 () {
@@ -457,59 +458,35 @@ converse.plugins.add('converse-muc-views', {
             },
 
             onDomainChange () {
-                if (_converse.auto_list_rooms) {
-                    this.updateRoomsList();
-                }
-            },
-
-            roomStanzaItemToHTMLElement (groupchat) {
-                const name = Strophe.unescapeNode(groupchat.getAttribute('name') || groupchat.getAttribute('jid'));
-                const div = document.createElement('div');
-                div.innerHTML = tpl_room_item({
-                    'name': Strophe.xmlunescape(name),
-                    'jid': groupchat.getAttribute('jid'),
-                    'open_title': __('Click to open this groupchat'),
-                    'info_title': __('Show more information on this groupchat')
-                });
-                return div.firstElementChild;
-            },
-
-            removeSpinner () {
-                sizzle('.spinner', this.el).forEach(u.removeElement);
-            },
-
-            informNoRoomsFound () {
-                const chatrooms_el = this.el.querySelector('.available-chatrooms');
-                chatrooms_el.innerHTML = tpl_rooms_results({'feedback_text': __('No groupchats found')});
-                const input_el = this.el.querySelector('input[name="server"]');
-                input_el.classList.remove('hidden')
-                this.removeSpinner();
+                _converse.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) {
-                /* Handle the IQ stanza returned from the server, containing
-                 * all its public groupchats.
-                 */
-                const available_chatrooms = this.el.querySelector('.available-chatrooms');
-                const rooms = sizzle('query item', iq);
+                const rooms = iq ? sizzle('query item', iq) : [];
                 if (rooms.length) {
-                    available_chatrooms.innerHTML = tpl_rooms_results({'feedback_text': __('Groupchats found:')});
-                    const fragment = document.createDocumentFragment();
-                    rooms.map(this.roomStanzaItemToHTMLElement)
-                         .filter(r => r)
-                         .forEach(child => fragment.appendChild(child));
-
-                    available_chatrooms.appendChild(fragment);
-                    this.removeSpinner();
+                    this.model.set({'feedback_text': __('Groupchats found')}, {'silent': true});
+                    this.items = rooms.map(st.getAttributes);
+                    this.loading_items = false;
+                    this.render();
                 } else {
-                    this.informNoRoomsFound();
+                    this.model.set('feedback_text', __('No groupchats found'));
                 }
                 return true;
             },
 
+            /**
+             * Send an IQ stanza to the server asking for all groupchats
+             * @private
+             * @method _converse.ChatRoomView#updateRoomsList
+             */
             updateRoomsList () {
-                /* Send an IQ stanza to the server asking for all groupchats
-                 */
                 const iq = $iq({
                     'to': this.model.get('muc_domain'),
                     'from': _converse.connection.jid,
@@ -517,11 +494,14 @@ converse.plugins.add('converse-muc-views', {
                 }).c("query", {xmlns: Strophe.NS.DISCO_ITEMS});
                 api.sendIQ(iq)
                     .then(iq => this.onRoomsFound(iq))
-                    .catch(() => this.informNoRoomsFound())
+                    .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();

+ 14 - 0
src/headless/utils/stanza.js

@@ -128,6 +128,20 @@ const stanza_utils = {
         return !!sizzle(`result[xmlns="${Strophe.NS.MAM}"]`, original_stanza).pop();
     },
 
+    /**
+     * Returns an object containing all attribute names and values for a particular element.
+     * @private
+     * @method stanza_utils#getAttributes
+     * @param { XMLElement } stanza
+     * @returns { Object }
+     */
+    getAttributes (stanza) {
+        return stanza.getAttributeNames().reduce((acc, name) => {
+            acc[name] = Strophe.xmlunescape(stanza.getAttribute(name))
+            return acc;
+        }, {});
+    },
+
     /**
      * Extract the XEP-0359 stanza IDs from the passed in stanza
      * and return a map containing them.

+ 1 - 1
src/templates/bookmarks_list.js

@@ -12,7 +12,7 @@ const bookmark_item = (o) => html`
     <div class="list-item controlbox-padded room-item available-chatroom d-flex flex-row ${ (o.is_hidden(o.bm)) ? 'hidden' : ''}" data-room-jid="${o.bm.get('jid')}">
         <a class="list-item-link open-room w-100" data-room-jid="${o.bm.get('jid')}"
            title="${open_title}"
-          @click=${o.openRoom}>${o.bm.getDisplayName()}</a>
+           @click=${o.openRoom}>${o.bm.getDisplayName()}</a>
 
         <a class="list-item-action remove-bookmark fa fa-bookmark align-self-center ${ o.bm.get('bookmarked') ? 'button-on' : '' }"
            data-room-jid="${o.bm.get('jid')}"

+ 39 - 6
src/templates/list_chatrooms_modal.js

@@ -1,23 +1,52 @@
-import { html } from "lit-html";
 import { __ } from '@converse/headless/i18n';
+import { html } from "lit-html";
+import { repeat } from 'lit-html/directives/repeat.js';
 import { modal_close_button, modal_header_close_button } from "./buttons"
+import spinner from "./spinner.js";
 
+const i18n_info_title = __('Show more information on this groupchat');
 const i18n_list_chatrooms = __('Query for Groupchats');
-const i18n_server_address = __('Server address');
+const i18n_open_title = __('Click to open this groupchat');
 const i18n_query = __('Show groupchats');
-
+const i18n_server_address = __('Server address');
 
 const form = (o) => html`
-    <form class="converse-form list-chatrooms">
+    <form class="converse-form list-chatrooms"
+          @submit=${o.submitForm}>
         <div class="form-group">
             <label for="chatroom">${i18n_server_address}:</label>
-            <input type="text" value="${o.muc_domain}" required="required" name="server" class="form-control" placeholder="${o.server_placeholder}"/>
+            <input type="text"
+                   @change=${o.setDomainFromEvent}
+                   value="${o.muc_domain}"
+                   required="required"
+                   name="server"
+                   class="form-control"
+                   placeholder="${o.server_placeholder}"/>
         </div>
         <input type="submit" class="btn btn-primary" name="list" value="${i18n_query}"/>
     </form>
 `;
 
 
+const tpl_item = (o, item) => html`
+    <li class="room-item list-group-item">
+        <div class="available-chatroom d-flex flex-row">
+            <a class="open-room available-room w-100"
+               @click=${o.openRoom}
+               data-room-jid="${item.jid}"
+               data-room-name="${item.name}"
+               title="${i18n_open_title}"
+               href="#">${item.name || item.jid}</a>
+            <a class="right room-info icon-room-info"
+               @click=${o.toggleRoomInfo}
+               data-room-jid="${item.jid}"
+               title="${i18n_info_title}"
+               href="#"></a>
+        </div>
+    </li>
+`;
+
+
 export default (o) => html`
     <div class="modal-dialog" role="document">
         <div class="modal-content">
@@ -28,7 +57,11 @@ export default (o) => html`
             <div class="modal-body d-flex flex-column">
                 <span class="modal-alert"></span>
                 ${o.show_form ? form(o) : '' }
-                <ul class="available-chatrooms list-group"></ul>
+                <ul class="available-chatrooms list-group">
+                    ${ o.loading_items ? html`<li class="list-group-item"> ${spinner()} </li>` : '' }
+                    ${ o.items.length ? html`<li class="list-group-item active">${ o.feedback_text }:</li>` : '' }
+                    ${repeat(o.items, item => item.jid, item => tpl_item(o, item))}
+                </ul>
             </div>
             <div class="modal-footer">${modal_close_button}</div>
         </div>

+ 0 - 12
src/templates/room_item.html

@@ -1,12 +0,0 @@
-<li class="room-item list-group-item">
-  <div class="available-chatroom d-flex flex-row">
-    <a class="open-room available-room w-100"
-       data-room-jid="{{{o.jid}}}"
-       data-room-name="{{{o.name}}}"
-       title="{{{o.open_title}}}"
-       href="#">{{{o.name}}}</a>
-    <a class="right room-info icon-room-info"
-       data-room-jid="{{{o.jid}}}"
-       title="{{{o.info_title}}}" href="#"></a>
-  </div>
-</li>

+ 0 - 1
src/templates/rooms_results.html

@@ -1 +0,0 @@
-<li class="list-group-item active">{{{ o.feedback_text }}}</li>