JC Brand пре 7 година
родитељ
комит
4e508cfe88

+ 17 - 18
css/converse.css

@@ -4993,8 +4993,7 @@ body.reset {
   #conversejs .centered {
   #conversejs .centered {
     text-align: center;
     text-align: center;
     display: block;
     display: block;
-    margin: 0;
-    padding: 10% 0; }
+    margin: 0; }
   #conversejs .hor_centered {
   #conversejs .hor_centered {
     text-align: center;
     text-align: center;
     display: block;
     display: block;
@@ -5653,6 +5652,22 @@ body.reset {
   color: #A8ABA1; }
   color: #A8ABA1; }
 #conversejs .set-xmpp-status .fa-times-circle, #conversejs .xmpp-status .fa-times-circle, #conversejs .roster-contacts .fa-times-circle {
 #conversejs .set-xmpp-status .fa-times-circle, #conversejs .xmpp-status .fa-times-circle, #conversejs .roster-contacts .fa-times-circle {
   color: #A8ABA1; }
   color: #A8ABA1; }
+#conversejs .room-info {
+  font-size: 12px;
+  font-style: normal;
+  font-weight: normal; }
+  #conversejs .room-info li.room-info {
+    display: block;
+    margin-left: 5px; }
+  #conversejs .room-info p.room-info {
+    line-height: 16px;
+    margin: 0;
+    display: block;
+    white-space: normal; }
+#conversejs div.room-info {
+  padding: 0.3em 0;
+  clear: left;
+  width: 100%; }
 #conversejs #converse-modals .set-xmpp-status {
 #conversejs #converse-modals .set-xmpp-status {
   margin: 1em; }
   margin: 1em; }
   #conversejs #converse-modals .set-xmpp-status .custom-control-label {
   #conversejs #converse-modals .set-xmpp-status .custom-control-label {
@@ -5795,22 +5810,6 @@ body.reset {
     #conversejs #controlbox #chatrooms .rooms-list-container .rooms-list {
     #conversejs #controlbox #chatrooms .rooms-list-container .rooms-list {
       margin: 0.5em 0;
       margin: 0.5em 0;
       text-align: left; }
       text-align: left; }
-      #conversejs #controlbox #chatrooms .rooms-list-container .rooms-list .room-info {
-        font-size: 12px;
-        font-style: normal;
-        font-weight: normal; }
-        #conversejs #controlbox #chatrooms .rooms-list-container .rooms-list .room-info li.room-info {
-          display: block;
-          margin-left: 5px; }
-        #conversejs #controlbox #chatrooms .rooms-list-container .rooms-list .room-info p.room-info {
-          line-height: 16px;
-          margin: 0;
-          display: block;
-          white-space: normal; }
-      #conversejs #controlbox #chatrooms .rooms-list-container .rooms-list div.room-info {
-        padding: 0.3em 0;
-        clear: left;
-        width: 100%; }
       #conversejs #controlbox #chatrooms .rooms-list-container .rooms-list .available-chatroom,
       #conversejs #controlbox #chatrooms .rooms-list-container .rooms-list .available-chatroom,
       #conversejs #controlbox #chatrooms .rooms-list-container .rooms-list .open-chatroom {
       #conversejs #controlbox #chatrooms .rooms-list-container .rooms-list .open-chatroom {
         border: none;
         border: none;

+ 17 - 18
css/inverse.css

@@ -4993,8 +4993,7 @@ body.reset {
   #conversejs .centered {
   #conversejs .centered {
     text-align: center;
     text-align: center;
     display: block;
     display: block;
-    margin: 0;
-    padding: 10% 0; }
+    margin: 0; }
   #conversejs .hor_centered {
   #conversejs .hor_centered {
     text-align: center;
     text-align: center;
     display: block;
     display: block;
@@ -5725,6 +5724,22 @@ body {
   color: #A8ABA1; }
   color: #A8ABA1; }
 #conversejs .set-xmpp-status .fa-times-circle, #conversejs .xmpp-status .fa-times-circle, #conversejs .roster-contacts .fa-times-circle {
 #conversejs .set-xmpp-status .fa-times-circle, #conversejs .xmpp-status .fa-times-circle, #conversejs .roster-contacts .fa-times-circle {
   color: #A8ABA1; }
   color: #A8ABA1; }
+#conversejs .room-info {
+  font-size: 14px;
+  font-style: normal;
+  font-weight: normal; }
+  #conversejs .room-info li.room-info {
+    display: block;
+    margin-left: 5px; }
+  #conversejs .room-info p.room-info {
+    line-height: 22px;
+    margin: 0;
+    display: block;
+    white-space: normal; }
+#conversejs div.room-info {
+  padding: 0.3em 0;
+  clear: left;
+  width: 100%; }
 #conversejs #converse-modals .set-xmpp-status {
 #conversejs #converse-modals .set-xmpp-status {
   margin: 1em; }
   margin: 1em; }
   #conversejs #converse-modals .set-xmpp-status .custom-control-label {
   #conversejs #converse-modals .set-xmpp-status .custom-control-label {
@@ -5867,22 +5882,6 @@ body {
     #conversejs #controlbox #chatrooms .rooms-list-container .rooms-list {
     #conversejs #controlbox #chatrooms .rooms-list-container .rooms-list {
       margin: 0.5em 0;
       margin: 0.5em 0;
       text-align: left; }
       text-align: left; }
-      #conversejs #controlbox #chatrooms .rooms-list-container .rooms-list .room-info {
-        font-size: 14px;
-        font-style: normal;
-        font-weight: normal; }
-        #conversejs #controlbox #chatrooms .rooms-list-container .rooms-list .room-info li.room-info {
-          display: block;
-          margin-left: 5px; }
-        #conversejs #controlbox #chatrooms .rooms-list-container .rooms-list .room-info p.room-info {
-          line-height: 22px;
-          margin: 0;
-          display: block;
-          white-space: normal; }
-      #conversejs #controlbox #chatrooms .rooms-list-container .rooms-list div.room-info {
-        padding: 0.3em 0;
-        clear: left;
-        width: 100%; }
       #conversejs #controlbox #chatrooms .rooms-list-container .rooms-list .available-chatroom,
       #conversejs #controlbox #chatrooms .rooms-list-container .rooms-list .available-chatroom,
       #conversejs #controlbox #chatrooms .rooms-list-container .rooms-list .open-chatroom {
       #conversejs #controlbox #chatrooms .rooms-list-container .rooms-list .open-chatroom {
         border: none;
         border: none;

+ 21 - 20
sass/_controlbox.scss

@@ -18,6 +18,27 @@
         }
         }
     }
     }
 
 
+    .room-info {
+        font-size: $font-size-small;
+        font-style: normal;
+        font-weight: normal;
+
+        li.room-info {
+            display: block;
+            margin-left: 5px;
+        }
+        p.room-info {
+            line-height: $line-height;
+            margin: 0;
+            display: block;
+            white-space: normal;
+        }
+    }
+    div.room-info {
+        padding: 0.3em 0;
+        clear: left;
+        width: 100%;
+    }
 
 
     #converse-modals {
     #converse-modals {
         .set-xmpp-status {
         .set-xmpp-status {
@@ -225,26 +246,6 @@
                     margin: 0.5em 0;
                     margin: 0.5em 0;
                     text-align: left;
                     text-align: left;
 
 
-                    .room-info {
-                        font-size: $font-size-small;
-                        font-style: normal;
-                        font-weight: normal;
-                        li.room-info {
-                            display: block;
-                            margin-left: 5px;
-                        }
-                        p.room-info {
-                            line-height: $line-height;
-                            margin: 0;
-                            display: block;
-                            white-space: normal;
-                        }
-                    }
-                    div.room-info {
-                        padding: 0.3em 0;
-                        clear: left;
-                        width: 100%;
-                    }
 
 
                     .available-chatroom,
                     .available-chatroom,
                     .open-chatroom {
                     .open-chatroom {

+ 0 - 1
sass/_core.scss

@@ -303,7 +303,6 @@ body.reset {
         text-align: center;
         text-align: center;
         display: block;
         display: block;
         margin: 0;
         margin: 0;
-        padding: 10% 0;
     }
     }
     .hor_centered {
     .hor_centered {
         text-align: center;
         text-align: center;

+ 224 - 186
src/converse-muc-views.js

@@ -26,6 +26,7 @@
         "tpl!chatroom_sidebar",
         "tpl!chatroom_sidebar",
         "tpl!chatroom_toolbar",
         "tpl!chatroom_toolbar",
         "tpl!info",
         "tpl!info",
+        "tpl!list_chatrooms_modal",
         "tpl!occupant",
         "tpl!occupant",
         "tpl!room_description",
         "tpl!room_description",
         "tpl!room_item",
         "tpl!room_item",
@@ -50,6 +51,7 @@
     tpl_chatroom_sidebar,
     tpl_chatroom_sidebar,
     tpl_chatroom_toolbar,
     tpl_chatroom_toolbar,
     tpl_info,
     tpl_info,
+    tpl_list_chatrooms_modal,
     tpl_occupant,
     tpl_occupant,
     tpl_room_description,
     tpl_room_description,
     tpl_room_item,
     tpl_room_item,
@@ -78,7 +80,6 @@
         'unmoderated': 'moderated'
         'unmoderated': 'moderated'
     };
     };
 
 
-
     converse.plugins.add('converse-muc-views', {
     converse.plugins.add('converse-muc-views', {
         /* Dependencies are other plugins which might be
         /* Dependencies are other plugins which might be
          * overridden or relied upon, and therefore need to be loaded before
          * overridden or relied upon, and therefore need to be loaded before
@@ -150,6 +151,212 @@
             _converse.api.promises.add(['roomsPanelRendered']);
             _converse.api.promises.add(['roomsPanelRendered']);
 
 
 
 
+            function insertRoomInfo (el, stanza) {
+                /* Insert room info (based on returned #disco IQ stanza)
+                 *
+                 * Parameters:
+                 *  (HTMLElement) el: The HTML DOM element that should
+                 *      contain the info.
+                 *  (XMLElement) stanza: The IQ stanza containing the room
+                 *      info.
+                 */
+                // All MUC features found here: http://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': _.get(_.head(sizzle('field[var="muc#roominfo_description"] value', stanza)), 'textContent'),
+                        'occ': _.get(_.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': __('Room Address (JID):'),
+                        'label_occ': __('Occupants:'),
+                        '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 room'),
+                        'label_permanent_room': __('Permanent room'),
+                        'label_public': __('Public'),
+                        'label_semi_anon':  __('Semi-anonymous'),
+                        'label_temp_room':  __('Temporary room'),
+                        'label_unmoderated': __('Unmoderated')
+                    }));
+            }
+
+            function toggleRoomInfo (ev) {
+                /* Show/hide extra information about a room in a listing. */
+                const parent_el = u.ancestor(ev.target, '.room-item'),
+                        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());
+                    _converse.connection.disco.info(
+                        ev.target.getAttribute('data-room-jid'),
+                        null,
+                        _.partial(insertRoomInfo, parent_el)
+                    );
+                }
+            }
+
+            
+            _converse.ListChatRoomsModal = Backbone.VDOMView.extend({
+                events: {
+                    'submit form': 'showRooms',
+                    'click a.room-info': 'toggleRoomInfo',
+                    'change input[name=nick]': 'setNick',
+                    'change input[name=server]': 'setDomain',
+                    'click .open-room': 'openRoom'
+                },
+
+                initialize () {
+                    this.render().insertIntoDOM();
+                    this.modal = new bootstrap.Modal(this.el, {
+                        backdrop: 'static',
+                        keyboard: true
+                    });
+                    this.model.on('change:muc_domain', this.onDomainChange, this);
+                },
+
+                toHTML () {
+                    return tpl_list_chatrooms_modal(_.extend(this.model.toJSON(), {
+                        'heading_list_chatrooms': __('Query for Chatrooms'),
+                        'label_server_address': __('Server address'),
+                        'label_query': __('Show rooms'),
+                        'server_placeholder': __('conference.example.org')
+                    }));
+                },
+
+                insertIntoDOM () {
+                    const container_el = _converse.chatboxviews.el.querySelector('#converse-modals');
+                    container_el.insertAdjacentElement('beforeEnd', this.el);
+                },
+
+                show () {
+                    this.render();
+                    this.modal.show();
+                },
+
+                openRoom (ev) {
+                    ev.preventDefault();
+                    const jid = ev.target.getAttribute('data-room-jid');
+                    this.modal.hide();
+                    _converse.api.rooms.open(jid);
+                },
+
+                toggleRoomInfo (ev) {
+                    ev.preventDefault();
+                    toggleRoomInfo(ev);
+                },
+
+                onDomainChange (model) {
+                    if (_converse.auto_list_rooms) {
+                        this.updateRoomsList();
+                    }
+                },
+
+                roomStanzaItemToHTMLElement (room) {
+                    const name = Strophe.unescapeNode(
+                        room.getAttribute('name') ||
+                            room.getAttribute('jid')
+                    );
+                    const div = document.createElement('div');
+                    div.innerHTML = tpl_room_item({
+                        'name': name,
+                        'jid': room.getAttribute('jid'),
+                        'open_title': __('Click to open this room'),
+                        'info_title': __('Show more information on this room')
+                    });
+                    return div.firstChild;
+                },
+
+                removeSpinner () {
+                    _.each(this.el.querySelectorAll('span.spinner'),
+                        (el) => el.parentNode.removeChild(el)
+                    );
+                },
+
+                informNoRoomsFound () {
+                    const chatrooms_el = this.el.querySelector('.available-chatrooms');
+                    chatrooms_el.innerHTML = tpl_rooms_results({
+                        'feedback_text': __('No rooms found')
+                    });
+                    const input_el = this.el.querySelector('input#show-rooms');
+                    input_el.classList.remove('hidden')
+                    this.removeSpinner();
+                },
+
+                onRoomsFound (iq) {
+                    /* Handle the IQ stanza returned from the server, containing
+                     * all its public rooms.
+                     */
+                    const available_chatrooms = this.el.querySelector('.available-chatrooms');
+                    this.rooms = iq.querySelectorAll('query item');
+                    if (this.rooms.length) {
+                        // For translators: %1$s is a variable and will be
+                        // replaced with the XMPP server name
+                        available_chatrooms.innerHTML = tpl_rooms_results({
+                            'feedback_text': __('Rooms found')
+                        });
+                        const fragment = document.createDocumentFragment();
+                        const children = _.reject(_.map(this.rooms, this.roomStanzaItemToHTMLElement), _.isNil)
+                        _.each(children, (child) => fragment.appendChild(child));
+                        available_chatrooms.appendChild(fragment);
+                        this.removeSpinner();
+                    } else {
+                        this.informNoRoomsFound();
+                    }
+                    return true;
+                },
+
+                updateRoomsList () {
+                    /* Send an IQ stanza to the server asking for all rooms
+                     */
+                    _converse.connection.sendIQ(
+                        $iq({
+                            to: this.model.get('muc_domain'),
+                            from: _converse.connection.jid,
+                            type: "get"
+                        }).c("query", {xmlns: Strophe.NS.DISCO_ITEMS}),
+                        this.onRoomsFound.bind(this),
+                        this.informNoRoomsFound.bind(this),
+                        5000
+                    );
+                },
+
+                showRooms (ev) {
+                    ev.preventDefault();
+                    const data = new FormData(ev.target);
+                    this.model.save('muc_domain', data.get('server'));
+                    this.updateRoomsList();
+                },
+
+                setDomain (ev) {
+                    this.model.save({muc_domain: ev.target.value});
+                },
+
+                setNick (ev) {
+                    this.model.save({nick: ev.target.value});
+                }
+            });
+
+
             _converse.AddChatRoomModal = Backbone.VDOMView.extend({
             _converse.AddChatRoomModal = Backbone.VDOMView.extend({
                 events: {
                 events: {
                     'submit form.add-chatroom': 'openChatRoom'
                     'submit form.add-chatroom': 'openChatRoom'
@@ -161,14 +368,15 @@
                         backdrop: 'static',
                         backdrop: 'static',
                         keyboard: true
                         keyboard: true
                     });
                     });
-                    this.model.on('change:muc_domain', this.render, this);
                 },
                 },
 
 
                 toHTML () {
                 toHTML () {
                     return tpl_add_chatroom_modal(_.extend(this.model.toJSON(), {
                     return tpl_add_chatroom_modal(_.extend(this.model.toJSON(), {
                         'heading_new_chatroom': __('Enter a new Chatroom'),
                         'heading_new_chatroom': __('Enter a new Chatroom'),
                         'label_room_address': __('Room address'),
                         'label_room_address': __('Room address'),
-                        'label_nickname': __('Optional nickname')
+                        'label_nickname': __('Optional nickname'),
+                        'chatroom_placeholder': __('name@conference.example.org'),
+                        'label_join': __('Join'),
                     }));
                     }));
                 },
                 },
 
 
@@ -2002,207 +2210,37 @@
                 id: 'chatrooms',
                 id: 'chatrooms',
                 events: {
                 events: {
                     'click a.chatbox-btn.fa-users': 'showAddRoomModal',
                     'click a.chatbox-btn.fa-users': 'showAddRoomModal',
-                    'change input[name=nick]': 'setNick',
-                    'change input[name=server]': 'setDomain',
-                    'click a.room-info': 'toggleRoomInfo',
-                    'click input#show-rooms': 'showRooms',
+                    'click a.chatbox-btn.fa-list-ul': 'showListRoomsModal',
+                    'click a.room-info': 'toggleRoomInfo'
                 },
                 },
 
 
                 initialize (cfg) {
                 initialize (cfg) {
                     this.add_room_modal = new _converse.AddChatRoomModal({'model': this.model});
                     this.add_room_modal = new _converse.AddChatRoomModal({'model': this.model});
-                    this.model.on('change:muc_domain', this.onDomainChange, this);
-                    this.model.on('change:nick', this.onNickChange, this);
+                    this.list_rooms_modal = new _converse.ListChatRoomsModal({'model': this.model});
                 },
                 },
 
 
                 render () {
                 render () {
                     this.el.innerHTML = tpl_room_panel({
                     this.el.innerHTML = tpl_room_panel({
                         'heading_chatrooms': __('Chatrooms'),
                         'heading_chatrooms': __('Chatrooms'),
-                        'title_new_room': __('Click to add a new room')
+                        'title_new_room': __('Add a new room'),
+                        'title_list_rooms': __('Query for rooms')
                     });
                     });
                     return this;
                     return this;
                 },
                 },
 
 
-                showAddRoomModal (ev) {
-                    ev.preventDefault();
-                    this.add_room_modal.show();
-                },
-
-
-                onDomainChange (model) {
-                    if (_converse.auto_list_rooms) {
-                        this.updateRoomsList();
-                    }
-                },
-
-                onNickChange (model) {
-                    const nick = this.el.querySelector('input.new-chatroom-nick');
-                    if (!_.isNull(nick)) {
-                        nick.value = model.get('nick');
-                    }
-                },
-
-                removeSpinner () {
-                    _.each(this.el.querySelectorAll('span.spinner'),
-                        (el) => el.parentNode.removeChild(el)
-                    );
-                },
-
-                informNoRoomsFound () {
-                    const chatrooms_el = this.el.querySelector('#available-chatrooms');
-                    chatrooms_el.innerHTML = tpl_rooms_results({
-                        'feedback_text': __('No rooms found')
-                    });
-                    const input_el = this.el.querySelector('input#show-rooms');
-                    input_el.classList.remove('hidden')
-                    this.removeSpinner();
-                },
-
-                roomStanzaItemToHTMLElement (room) {
-                    const name = Strophe.unescapeNode(
-                        room.getAttribute('name') ||
-                            room.getAttribute('jid')
-                    );
-                    const div = document.createElement('div');
-                    div.innerHTML = tpl_room_item({
-                        'name': name,
-                        'jid': room.getAttribute('jid'),
-                        'open_title': __('Click to open this room'),
-                        'info_title': __('Show more information on this room')
-                    });
-                    return div.firstChild;
-                },
-
-                onRoomsFound (iq) {
-                    /* Handle the IQ stanza returned from the server, containing
-                     * all its public rooms.
-                     */
-                    const available_chatrooms = this.el.querySelector('#available-chatrooms');
-                    this.rooms = iq.querySelectorAll('query item');
-                    if (this.rooms.length) {
-                        // For translators: %1$s is a variable and will be
-                        // replaced with the XMPP server name
-                        available_chatrooms.innerHTML = tpl_rooms_results({
-                            'feedback_text': __('Rooms found')
-                        });
-                        const fragment = document.createDocumentFragment();
-                        const children = _.reject(_.map(this.rooms, this.roomStanzaItemToHTMLElement), _.isNil)
-                        _.each(children, (child) => fragment.appendChild(child));
-                        available_chatrooms.appendChild(fragment);
-                        const input_el = this.el.querySelector('input#show-rooms');
-                        input_el.classList.remove('hidden')
-                        this.removeSpinner();
-                    } else {
-                        this.informNoRoomsFound();
-                    }
-                    return true;
-                },
-
-                updateRoomsList () {
-                    /* Send an IQ stanza to the server asking for all rooms
-                     */
-                    _converse.connection.sendIQ(
-                        $iq({
-                            to: this.model.get('muc_domain'),
-                            from: _converse.connection.jid,
-                            type: "get"
-                        }).c("query", {xmlns: Strophe.NS.DISCO_ITEMS}),
-                        this.onRoomsFound.bind(this),
-                        this.informNoRoomsFound.bind(this),
-                        5000
-                    );
-                },
-
-                showRooms () {
-                    const chatrooms_el = this.el.querySelector('#available-chatrooms');
-                    const server_el = this.el.querySelector('input.new-chatroom-server');
-                    const server = server_el.value;
-                    if (!server) {
-                        server_el.classList.add('error');
-                        return;
-                    }
-                    this.el.querySelector('input.new-chatroom-name').classList.remove('error');
-                    server_el.classList.remove('error');
-                    chatrooms_el.innerHTML = '';
-
-                    const input_el = this.el.querySelector('input#show-rooms');
-                    input_el.classList.add('hidden')
-                    input_el.insertAdjacentHTML('afterend', tpl_spinner());
-
-                    this.model.save({muc_domain: server});
-                    this.updateRoomsList();
-                },
-
-                insertRoomInfo (el, stanza) {
-                    /* Insert room info (based on returned #disco IQ stanza)
-                     *
-                     * Parameters:
-                     *  (HTMLElement) el: The HTML DOM element that should
-                     *      contain the info.
-                     *  (XMLElement) stanza: The IQ stanza containing the room
-                     *      info.
-                     */
-                    // All MUC features found here: http://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': _.get(_.head(sizzle('field[var="muc#roominfo_description"] value', stanza)), 'textContent'),
-                            'occ': _.get(_.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': __('Room Address (JID):'),
-                            'label_occ': __('Occupants:'),
-                            '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 room'),
-                            'label_permanent_room': __('Permanent room'),
-                            'label_public': __('Public'),
-                            'label_semi_anon':  __('Semi-anonymous'),
-                            'label_temp_room':  __('Temporary room'),
-                            'label_unmoderated': __('Unmoderated')
-                        }));
-                },
-
                 toggleRoomInfo (ev) {
                 toggleRoomInfo (ev) {
-                    /* Show/hide extra information about a room in the listing.
-                     */
-                    const parent_el = u.ancestor(ev.target, '.room-item'),
-                          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());
-                        _converse.connection.disco.info(
-                            ev.target.getAttribute('data-room-jid'),
-                            null,
-                            _.partial(this.insertRoomInfo, parent_el)
-                        );
-                    }
+                    ev.preventDefault();
+                    toggleRoomInfo(ev);
                 },
                 },
 
 
-                setDomain (ev) {
-                    this.model.save({muc_domain: ev.target.value});
+                showAddRoomModal (ev) {
+                    ev.preventDefault();
+                    this.add_room_modal.show();
                 },
                 },
 
 
-                setNick (ev) {
-                    this.model.save({nick: ev.target.value});
+                showListRoomsModal(ev) {
+                    ev.preventDefault();
+                    this.list_rooms_modal.show();
                 }
                 }
             });
             });
 
 

+ 4 - 4
src/templates/add_chatroom_modal.html

@@ -11,14 +11,14 @@
             <div class="modal-body">
             <div class="modal-body">
                 <form class="converse-form add-chatroom">
                 <form class="converse-form add-chatroom">
                     <div class="form-group">
                     <div class="form-group">
-                        <label for="chatroom">{{{o.label_room_address}}}:</label>
-                        <input type="text" required="required" name="chatroom" class="form-control" placeholder="name@conference.example.org">
+                        <label for="server">{{{o.label_room_address}}}:</label>
+                        <input type="text" value="{{{o.muc_domain}}}" required="required" name="chatroom" class="form-control" placeholder="{{{o.chatroom_placeholder}}}">
                     </div>
                     </div>
                     <div class="form-group">
                     <div class="form-group">
                         <label for="chatroom">{{{o.label_nickname}}}:</label>
                         <label for="chatroom">{{{o.label_nickname}}}:</label>
-                        <input type="text" name="nickname" class="form-control">
+                        <input type="text" name="nickname" value="{{{o.nick}}}" class="form-control">
                     </div>
                     </div>
-                    <input type="submit" class="btn btn-primary" name="join" value="Join">
+                    <input type="submit" class="btn btn-primary" name="join" value="{{{o.label_join}}}">
                 </form>
                 </form>
             </div>
             </div>
         </div>
         </div>

+ 23 - 0
src/templates/list_chatrooms_modal.html

@@ -0,0 +1,23 @@
+<div class="modal fade" id="list-chatrooms-modal" tabindex="-1" role="dialog" aria-labelledby="chatroomsModalLabel" aria-hidden="true">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title"
+                    id="chatroomsModalLabel">{{{o.heading_list_chatrooms}}}</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <form class="converse-form add-chatroom">
+                    <div class="form-group">
+                        <label for="chatroom">{{{o.label_server_address}}}:</label>
+                        <input type="text" value="{{{o.muc_domain}}}" required="required" name="server" class="form-control" placeholder="{{{o.server_placeholder}}}">
+                    </div>
+                    <input type="submit" class="btn btn-primary" name="join" value="{{{o.label_query}}}">
+                </form>
+                <ul class="available-chatrooms list-group"></ul>
+            </div>
+        </div>
+    </div>
+</div>

+ 3 - 3
src/templates/room_item.html

@@ -1,6 +1,6 @@
-<div class="room-item">
+<li class="room-item list-group-item">
   <div class="available-chatroom d-flex flex-row">
   <div class="available-chatroom d-flex flex-row">
-    <a class="open-room available-room"
+    <a class="open-room available-room w-100"
        data-room-jid="{{{o.jid}}}"
        data-room-jid="{{{o.jid}}}"
        title="{{{o.open_title}}}"
        title="{{{o.open_title}}}"
        href="#">{{{o.name}}}</a>
        href="#">{{{o.name}}}</a>
@@ -8,4 +8,4 @@
        data-room-jid="{{{o.jid}}}"
        data-room-jid="{{{o.jid}}}"
        title="{{{o.info_title}}}" href="#">&nbsp;</a>
        title="{{{o.info_title}}}" href="#">&nbsp;</a>
   </div>
   </div>
-</div>
+</li>

+ 1 - 0
src/templates/room_panel.html

@@ -1,6 +1,7 @@
 <!-- <div id="chatrooms"> -->
 <!-- <div id="chatrooms"> -->
 <div class="d-flex">
 <div class="d-flex">
     <span class="w-100">{{{o.heading_chatrooms}}}</span>
     <span class="w-100">{{{o.heading_chatrooms}}}</span>
+    <a class="chatbox-btn fa fa-list-ul" title="{{{o.title_list_rooms}}}" data-toggle="modal" data-target="#list-chatrooms-modal"></a>
     <a class="chatbox-btn fa fa-users" title="{{{o.title_new_room}}}" data-toggle="modal" data-target="#chatroomsModal"></a>
     <a class="chatbox-btn fa fa-users" title="{{{o.title_new_room}}}" data-toggle="modal" data-target="#chatroomsModal"></a>
 </div>
 </div>
 <div class="list-container open-rooms-list rooms-list-container"></div>
 <div class="list-container open-rooms-list rooms-list-container"></div>

+ 1 - 1
src/templates/rooms_results.html

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