Browse Source

Updates #1069

Highlight the currently open groupchat in the sidebar (in singleton mode).
JC Brand 7 years ago
parent
commit
58ee1460fe

+ 35 - 11
css/converse.css

@@ -8277,14 +8277,25 @@ body.reset {
       background-color: #eff4f7; }
       #conversejs .list-container .items-list .available-chatroom:hover .remove-bookmark,
       #conversejs .list-container .items-list .available-chatroom:hover .add-bookmark,
+      #conversejs .list-container .items-list .available-chatroom:hover .close-room,
       #conversejs .list-container .items-list .available-chatroom:hover .room-info,
       #conversejs .list-container .items-list .open-headline:hover .remove-bookmark,
       #conversejs .list-container .items-list .open-headline:hover .add-bookmark,
+      #conversejs .list-container .items-list .open-headline:hover .close-room,
       #conversejs .list-container .items-list .open-headline:hover .room-info,
       #conversejs .list-container .items-list .open-chatroom:hover .remove-bookmark,
       #conversejs .list-container .items-list .open-chatroom:hover .add-bookmark,
+      #conversejs .list-container .items-list .open-chatroom:hover .close-room,
       #conversejs .list-container .items-list .open-chatroom:hover .room-info {
         display: block !important; }
+    #conversejs .list-container .items-list .available-chatroom.open,
+    #conversejs .list-container .items-list .open-headline.open,
+    #conversejs .list-container .items-list .open-chatroom.open {
+      background-color: #578EA9; }
+      #conversejs .list-container .items-list .available-chatroom.open a,
+      #conversejs .list-container .items-list .open-headline.open a,
+      #conversejs .list-container .items-list .open-chatroom.open a {
+        color: white !important; }
     #conversejs .list-container .items-list .available-chatroom.unread-msgs .msgs-indicator,
     #conversejs .list-container .items-list .open-headline.unread-msgs .msgs-indicator,
     #conversejs .list-container .items-list .open-chatroom.unread-msgs .msgs-indicator {
@@ -8302,20 +8313,24 @@ body.reset {
     #conversejs .list-container .items-list .open-headline a:hover,
     #conversejs .list-container .items-list .open-chatroom a:hover {
       color: #206485; }
-    #conversejs .list-container .items-list .available-chatroom a.remove-bookmark, #conversejs .list-container .items-list .available-chatroom a.add-bookmark, #conversejs .list-container .items-list .available-chatroom a.room-info,
+    #conversejs .list-container .items-list .available-chatroom a.remove-bookmark, #conversejs .list-container .items-list .available-chatroom a.add-bookmark, #conversejs .list-container .items-list .available-chatroom a.close-room, #conversejs .list-container .items-list .available-chatroom a.room-info,
     #conversejs .list-container .items-list .open-headline a.remove-bookmark,
     #conversejs .list-container .items-list .open-headline a.add-bookmark,
+    #conversejs .list-container .items-list .open-headline a.close-room,
     #conversejs .list-container .items-list .open-headline a.room-info,
     #conversejs .list-container .items-list .open-chatroom a.remove-bookmark,
     #conversejs .list-container .items-list .open-chatroom a.add-bookmark,
+    #conversejs .list-container .items-list .open-chatroom a.close-room,
     #conversejs .list-container .items-list .open-chatroom a.room-info {
       display: none; }
-      #conversejs .list-container .items-list .available-chatroom a.remove-bookmark:before, #conversejs .list-container .items-list .available-chatroom a.add-bookmark:before, #conversejs .list-container .items-list .available-chatroom a.room-info:before,
+      #conversejs .list-container .items-list .available-chatroom a.remove-bookmark:before, #conversejs .list-container .items-list .available-chatroom a.add-bookmark:before, #conversejs .list-container .items-list .available-chatroom a.close-room:before, #conversejs .list-container .items-list .available-chatroom a.room-info:before,
       #conversejs .list-container .items-list .open-headline a.remove-bookmark:before,
       #conversejs .list-container .items-list .open-headline a.add-bookmark:before,
+      #conversejs .list-container .items-list .open-headline a.close-room:before,
       #conversejs .list-container .items-list .open-headline a.room-info:before,
       #conversejs .list-container .items-list .open-chatroom a.remove-bookmark:before,
       #conversejs .list-container .items-list .open-chatroom a.add-bookmark:before,
+      #conversejs .list-container .items-list .open-chatroom a.close-room:before,
       #conversejs .list-container .items-list .open-chatroom a.room-info:before {
         font-size: 15px; }
     #conversejs .list-container .items-list .available-chatroom a.open-room,
@@ -8333,33 +8348,42 @@ body.reset {
       width: 85%; }
     #conversejs .list-container .items-list .available-chatroom .add-bookmark,
     #conversejs .list-container .items-list .available-chatroom .remove-bookmark,
-    #conversejs .list-container .items-list .available-chatroom .remove-bookmark,
+    #conversejs .list-container .items-list .available-chatroom .close-room,
+    #conversejs .list-container .items-list .available-chatroom .room-info,
     #conversejs .list-container .items-list .open-headline .add-bookmark,
     #conversejs .list-container .items-list .open-headline .remove-bookmark,
-    #conversejs .list-container .items-list .open-headline .remove-bookmark,
+    #conversejs .list-container .items-list .open-headline .close-room,
+    #conversejs .list-container .items-list .open-headline .room-info,
     #conversejs .list-container .items-list .open-chatroom .add-bookmark,
     #conversejs .list-container .items-list .open-chatroom .remove-bookmark,
-    #conversejs .list-container .items-list .open-chatroom .remove-bookmark {
+    #conversejs .list-container .items-list .open-chatroom .close-room,
+    #conversejs .list-container .items-list .open-chatroom .room-info {
       color: #A8ABA1; }
       #conversejs .list-container .items-list .available-chatroom .add-bookmark.button-on,
       #conversejs .list-container .items-list .available-chatroom .remove-bookmark.button-on,
-      #conversejs .list-container .items-list .available-chatroom .remove-bookmark.button-on,
+      #conversejs .list-container .items-list .available-chatroom .close-room.button-on,
+      #conversejs .list-container .items-list .available-chatroom .room-info.button-on,
       #conversejs .list-container .items-list .open-headline .add-bookmark.button-on,
       #conversejs .list-container .items-list .open-headline .remove-bookmark.button-on,
-      #conversejs .list-container .items-list .open-headline .remove-bookmark.button-on,
+      #conversejs .list-container .items-list .open-headline .close-room.button-on,
+      #conversejs .list-container .items-list .open-headline .room-info.button-on,
       #conversejs .list-container .items-list .open-chatroom .add-bookmark.button-on,
       #conversejs .list-container .items-list .open-chatroom .remove-bookmark.button-on,
-      #conversejs .list-container .items-list .open-chatroom .remove-bookmark.button-on {
+      #conversejs .list-container .items-list .open-chatroom .close-room.button-on,
+      #conversejs .list-container .items-list .open-chatroom .room-info.button-on {
         color: #578EA9; }
         #conversejs .list-container .items-list .available-chatroom .add-bookmark.button-on:hover,
         #conversejs .list-container .items-list .available-chatroom .remove-bookmark.button-on:hover,
-        #conversejs .list-container .items-list .available-chatroom .remove-bookmark.button-on:hover,
+        #conversejs .list-container .items-list .available-chatroom .close-room.button-on:hover,
+        #conversejs .list-container .items-list .available-chatroom .room-info.button-on:hover,
         #conversejs .list-container .items-list .open-headline .add-bookmark.button-on:hover,
         #conversejs .list-container .items-list .open-headline .remove-bookmark.button-on:hover,
-        #conversejs .list-container .items-list .open-headline .remove-bookmark.button-on:hover,
+        #conversejs .list-container .items-list .open-headline .close-room.button-on:hover,
+        #conversejs .list-container .items-list .open-headline .room-info.button-on:hover,
         #conversejs .list-container .items-list .open-chatroom .add-bookmark.button-on:hover,
         #conversejs .list-container .items-list .open-chatroom .remove-bookmark.button-on:hover,
-        #conversejs .list-container .items-list .open-chatroom .remove-bookmark.button-on:hover {
+        #conversejs .list-container .items-list .open-chatroom .close-room.button-on:hover,
+        #conversejs .list-container .items-list .open-chatroom .room-info.button-on:hover {
           color: #206485; }
 
 #conversejs #converse-roster {

+ 39 - 19
dist/converse.js

@@ -71413,6 +71413,10 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
     }
   };
 
+  _converse.isSingleton = function () {
+    return _.includes(['mobile', 'fullscreen', 'embedded'], _converse.view_mode);
+  };
+
   _converse.router = new Backbone.Router();
 
   _converse.initialize = function (settings, callback) {
@@ -80671,7 +80675,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
      *
      * NB: These plugins need to have already been loaded via require.js.
      */
-    dependencies: ["converse-controlbox", "converse-muc", "converse-bookmarks"],
+    dependencies: ["converse-singleton", "converse-controlbox", "converse-muc", "converse-bookmarks"],
 
     initialize() {
       /* The initialize function gets called as soon as the plugin is
@@ -80697,6 +80701,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
 
           _converse.chatboxes.on('add', this.onChatBoxAdded, this);
 
+          _converse.chatboxes.on('change:hidden', this.onChatBoxChanged, this);
+
           _converse.chatboxes.on('change:bookmarked', this.onChatBoxChanged, this);
 
           _converse.chatboxes.on('change:name', this.onChatBoxChanged, this);
@@ -80743,13 +80749,14 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
       });
       _converse.RoomsListElementView = Backbone.VDOMView.extend({
         events: {
-          'click a.room-info': 'showRoomDetailsModal'
+          'click .room-info': 'showRoomDetailsModal'
         },
 
         initialize() {
           this.model.on('destroy', this.remove, this);
           this.model.on('remove', this.remove, this);
           this.model.on('change:bookmarked', this.render, this);
+          this.model.on('change:hidden', this.render, this);
           this.model.on('change:name', this.render, this);
           this.model.on('change:num_unread', this.render, this);
           this.model.on('change:num_unread_general', this.render, this);
@@ -80762,6 +80769,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
             // supported by the XMPP server. So we can use it
             // as a check for support (other ways of checking are async).
             'allow_bookmarks': _converse.allow_bookmarks && _converse.bookmarks,
+            'currently_open': _converse.isSingleton() && !this.model.get('hidden'),
             'info_leave_room': __('Leave this groupchat'),
             'info_remove_bookmark': __('Unbookmark this groupchat'),
             'info_add_bookmark': __('Bookmark this groupchat'),
@@ -83084,7 +83092,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
             return true;
           }
 
-          if (_.includes(['mobile', 'fullscreen', 'embedded'], _converse.view_mode)) {
+          if (_converse.isSingleton()) {
             const any_chats_visible = _converse.chatboxes.filter(cb => cb.get('id') != 'controlbox').filter(cb => !cb.get('hidden')).length > 0;
 
             if (any_chats_visible) {
@@ -83099,7 +83107,9 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
 
         createChatBox(jid, attrs) {
           /* Make sure new chat boxes are hidden by default. */
-          if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
+          const _converse = this.__super__._converse;
+
+          if (_converse.isSingleton()) {
             attrs = attrs || {};
             attrs.hidden = true;
           }
@@ -83110,7 +83120,9 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
       },
       ChatBoxView: {
         shouldShowOnTextMessage() {
-          if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
+          const _converse = this.__super__._converse;
+
+          if (_converse.isSingleton()) {
             return false;
           } else {
             return this.__super__.shouldShowOnTextMessage.apply(this, arguments);
@@ -83122,7 +83134,9 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
            * time. So before opening a chat, we make sure all other
            * chats are hidden.
            */
-          if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
+          const _converse = this.__super__._converse;
+
+          if (_converse.isSingleton()) {
             _.each(this.__super__._converse.chatboxviews.xget(this.model.get('id')), hideChat);
 
             this.model.set('hidden', false);
@@ -83134,7 +83148,9 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
       },
       ChatRoomView: {
         show(focus) {
-          if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
+          const _converse = this.__super__._converse;
+
+          if (_converse.isSingleton()) {
             _.each(this.__super__._converse.chatboxviews.xget(this.model.get('id')), hideChat);
 
             this.model.set('hidden', false);
@@ -86138,11 +86154,15 @@ var _ = {escape:__webpack_require__(/*! ./node_modules/lodash/escape.js */ "./no
 module.exports = function(o) {
 var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
 function print() { __p += __j.call(arguments, '') }
-__p += '<!-- src/templates/rooms_list_item.html -->\n<div class="list-item controlbox-padded available-chatroom d-flex flex-row ';
+__p += '<!-- src/templates/rooms_list_item.html -->\n<div class="list-item controlbox-padded available-chatroom d-flex flex-row\n    ';
+ if (o.currently_open) { ;
+__p += ' open ';
+ } ;
+__p += '\n    ';
  if (o.num_unread_general) { ;
 __p += ' unread-msgs ';
  } ;
-__p += '" data-room-jid="' +
+__p += '"\n    data-room-jid="' +
 __e(o.jid) +
 '">\n';
  if (o.num_unread) { ;
@@ -86156,15 +86176,9 @@ __e(o.jid) +
 __e(o.open_title) +
 '" href="#">' +
 __e(o.name || o.jid) +
-'</a>\n\n<a class="right close-room icon-leave"\n   data-room-jid="' +
-__e(o.jid) +
-'"\n   data-room-name="' +
-__e(o.name || o.jid) +
-'"\n   title="' +
-__e(o.info_leave_room) +
-'" href="#">&nbsp;</a>\n\n';
+'</a>\n\n';
  if (o.allow_bookmarks) { ;
-__p += '\n<a class="fa align-self-center ';
+__p += '\n<a class="fa ';
  if (o.bookmarked) { ;
 __p += ' fa-bookmark remove-bookmark button-on ';
  } else { ;
@@ -86186,11 +86200,17 @@ __e(o.info_add_bookmark) +
  } ;
 __p += '"\n   href="#">&nbsp;</a>\n';
  } ;
-__p += '\n<a class="room-info fa fa-info-circle align-self-center" data-room-jid="' +
+__p += '\n<a class="room-info fa fa-info-circle" data-room-jid="' +
 __e(o.jid) +
 '"\n   title="' +
 __e(o.info_title) +
-'" href="#">&nbsp;</a>\n</div>\n';
+'" href="#">&nbsp;</a>\n\n<a class="fa fa-times close-room"\n   data-room-jid="' +
+__e(o.jid) +
+'"\n   data-room-name="' +
+__e(o.name || o.jid) +
+'"\n   title="' +
+__e(o.info_leave_room) +
+'" href="#">&nbsp;</a>\n\n</div>\n';
 return __p
 };
 

+ 1 - 1
mockup/user-panel.html

@@ -37,7 +37,7 @@
     </div>
     <div class="list-container rooms-list-container">
         <div class="rooms-list items-list">
-            <div class="controlbox-padded list-item available-chatroom d-flex flex-row">
+            <div class="controlbox-padded list-item available-chatroom d-flex flex-row open">
                 <a class="open-room available-room w-100" data-room-jid="public@conference.test.com" title="Click to open this room" href="chatroom.html">Capulet's orchard</a>
                 <!-- <span class="badge badge-info msgs-indicator">1</span> -->
                 <a href="#"

+ 10 - 1
sass/_roomslist.scss

@@ -34,10 +34,17 @@
                     background-color: lighten($controlbox-head-color, 45%);
                     .remove-bookmark,
                     .add-bookmark,
+                    .close-room,
                     .room-info {
                         display: block !important;
                     }
                 }
+                &.open {
+                    background-color: $controlbox-head-color;
+                    a {
+                        color: white !important;
+                    }
+                }
                 &.unread-msgs {
                     .msgs-indicator {
                         border-radius: 10%;
@@ -55,6 +62,7 @@
                     }
                     &.remove-bookmark,
                     &.add-bookmark,
+                    &.close-room,
                     &.room-info {
                         display: none;
                         &:before {
@@ -75,7 +83,8 @@
                 }
                 .add-bookmark,
                 .remove-bookmark,
-                .remove-bookmark {
+                .close-room,
+                .room-info {
                     &.button-on {
                         color: $link-color;
                         &:hover {

+ 32 - 1
spec/roomslist.js

@@ -54,7 +54,38 @@
         ));
     });
 
-    describe("A room shown in the groupchats list", function () {
+    describe("A groupchat shown in the groupchats list", function () {
+
+        it("is highlighted if its currently open", mock.initConverseWithPromises(
+            null, ['rosterGroupsFetched'],
+            { whitelisted_plugins: ['converse-roomslist'],
+              allow_bookmarks: false // Makes testing easier, otherwise we
+                                     // have to mock stanza traffic.
+            }, function (done, _converse) {
+
+            spyOn(_converse, 'isSingleton').and.callFake(function () {
+                return true;
+            });
+
+            test_utils.openControlBox();
+            _converse.api.rooms.open('coven@chat.shakespeare.lit', {'nick': 'some1'});
+            let room_els = _converse.rooms_list_view.el.querySelectorAll(".available-chatroom");
+            expect(room_els.length).toBe(1);
+
+            let item = room_els[0];
+            expect(u.hasClass('open', item)).toBe(true);
+            expect(item.textContent.trim()).toBe('coven@chat.shakespeare.lit');
+
+            _converse.api.rooms.open('balcony@chat.shakespeare.lit', {'nick': 'some1'});
+            room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room");
+            expect(room_els.length).toBe(2);
+
+            room_els = _converse.rooms_list_view.el.querySelectorAll(".available-chatroom.open");
+            expect(room_els.length).toBe(1);
+            item = room_els[0];
+            expect(item.textContent.trim()).toBe('balcony@chat.shakespeare.lit');
+            done();
+        }));
 
         it("has an info icon which opens a details modal when clicked", mock.initConverseWithPromises(
             null, ['rosterGroupsFetched'],

+ 4 - 0
src/converse-core.js

@@ -295,6 +295,10 @@
         }
     };
 
+    _converse.isSingleton = function () {
+        return _.includes(['mobile', 'fullscreen', 'embedded'], _converse.view_mode);
+    }
+
     _converse.router = new Backbone.Router();
 
 

+ 5 - 2
src/converse-roomslist.js

@@ -33,7 +33,7 @@
          *
          * NB: These plugins need to have already been loaded via require.js.
          */
-        dependencies: ["converse-controlbox", "converse-muc", "converse-bookmarks"],
+        dependencies: ["converse-singleton", "converse-controlbox", "converse-muc", "converse-bookmarks"],
 
         initialize () {
             /* The initialize function gets called as soon as the plugin is
@@ -58,6 +58,7 @@
                     this.browserStorage = new Backbone.BrowserStorage[_converse.storage](
                         b64_sha1(`converse.open-rooms-{_converse.bare_jid}`));
                     _converse.chatboxes.on('add', this.onChatBoxAdded, this);
+                    _converse.chatboxes.on('change:hidden', this.onChatBoxChanged, this);
                     _converse.chatboxes.on('change:bookmarked', this.onChatBoxChanged, this);
                     _converse.chatboxes.on('change:name', this.onChatBoxChanged, this);
                     _converse.chatboxes.on('change:num_unread', this.onChatBoxChanged, this);
@@ -98,13 +99,14 @@
 
             _converse.RoomsListElementView = Backbone.VDOMView.extend({
                 events: {
-                    'click a.room-info': 'showRoomDetailsModal'
+                    'click .room-info': 'showRoomDetailsModal'
                 },
 
                 initialize () {
                     this.model.on('destroy', this.remove, this);
                     this.model.on('remove', this.remove, this);
                     this.model.on('change:bookmarked', this.render, this);
+                    this.model.on('change:hidden', this.render, this);
                     this.model.on('change:name', this.render, this);
                     this.model.on('change:num_unread', this.render, this);
                     this.model.on('change:num_unread_general', this.render, this);
@@ -118,6 +120,7 @@
                             // supported by the XMPP server. So we can use it
                             // as a check for support (other ways of checking are async).
                             'allow_bookmarks': _converse.allow_bookmarks && _converse.bookmarks,
+                            'currently_open': _converse.isSingleton() && !this.model.get('hidden'),
                             'info_leave_room': __('Leave this groupchat'),
                             'info_remove_bookmark': __('Unbookmark this groupchat'),
                             'info_add_bookmark': __('Bookmark this groupchat'),

+ 9 - 5
src/converse-singleton.js

@@ -50,7 +50,7 @@
                     if (chatbox.get('id') === 'controlbox') {
                         return true;
                     }
-                    if (_.includes(['mobile', 'fullscreen', 'embedded'], _converse.view_mode)) {
+                    if (_converse.isSingleton()) {
                         const any_chats_visible = _converse.chatboxes
                             .filter((cb) => cb.get('id') != 'controlbox')
                             .filter((cb) => !cb.get('hidden')).length > 0;
@@ -67,7 +67,8 @@
 
                 createChatBox (jid, attrs) {
                     /* Make sure new chat boxes are hidden by default. */
-                    if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
+                    const { _converse } = this.__super__;
+                    if (_converse.isSingleton()) {
                         attrs = attrs || {};
                         attrs.hidden = true;
                     }
@@ -77,7 +78,8 @@
 
             ChatBoxView: {
                 shouldShowOnTextMessage () {
-                    if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
+                    const { _converse } = this.__super__;
+                    if (_converse.isSingleton()) {
                         return false;
                     } else { 
                         return this.__super__.shouldShowOnTextMessage.apply(this, arguments);
@@ -89,7 +91,8 @@
                      * time. So before opening a chat, we make sure all other
                      * chats are hidden.
                      */
-                    if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
+                    const { _converse } = this.__super__;
+                    if (_converse.isSingleton()) {
                         _.each(this.__super__._converse.chatboxviews.xget(this.model.get('id')), hideChat);
                         this.model.set('hidden', false);
                     }
@@ -99,7 +102,8 @@
 
             ChatRoomView: {
                 show (focus) {
-                    if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
+                    const { _converse } = this.__super__;
+                    if (_converse.isSingleton()) {
                         _.each(this.__super__._converse.chatboxviews.xget(this.model.get('id')), hideChat);
                         this.model.set('hidden', false);
                     }

+ 12 - 8
src/templates/rooms_list_item.html

@@ -1,4 +1,7 @@
-<div class="list-item controlbox-padded available-chatroom d-flex flex-row {[ if (o.num_unread_general) { ]} unread-msgs {[ } ]}" data-room-jid="{{{o.jid}}}">
+<div class="list-item controlbox-padded available-chatroom d-flex flex-row
+    {[ if (o.currently_open) { ]} open {[ } ]}
+    {[ if (o.num_unread_general) { ]} unread-msgs {[ } ]}"
+    data-room-jid="{{{o.jid}}}">
 {[ if (o.num_unread) { ]}
     <span class="msgs-indicator badge badge-info">{{{ o.num_unread }}}</span>
 {[ } ]}
@@ -6,17 +9,18 @@
     data-room-jid="{{{o.jid}}}"
     title="{{{o.open_title}}}" href="#">{{{o.name || o.jid}}}</a>
 
-<a class="right close-room icon-leave"
-   data-room-jid="{{{o.jid}}}"
-   data-room-name="{{{o.name || o.jid}}}"
-   title="{{{o.info_leave_room}}}" href="#">&nbsp;</a>
-
 {[ if (o.allow_bookmarks) { ]}
-<a class="fa align-self-center {[ if (o.bookmarked) { ]} fa-bookmark remove-bookmark button-on {[ } else { ]} add-bookmark fa-bookmark-o {[ } ]}"
+<a class="fa {[ if (o.bookmarked) { ]} fa-bookmark remove-bookmark button-on {[ } else { ]} add-bookmark fa-bookmark-o {[ } ]}"
    data-room-jid="{{{o.jid}}}" data-bookmark-name="{{{o.name}}}"
    title="{[ if (o.bookmarked) { ]} {{{o.info_remove_bookmark}}} {[ } else { ]} {{{o.info_add_bookmark}}} {[ } ]}"
    href="#">&nbsp;</a>
 {[ } ]}
-<a class="room-info fa fa-info-circle align-self-center" data-room-jid="{{{o.jid}}}"
+<a class="room-info fa fa-info-circle" data-room-jid="{{{o.jid}}}"
    title="{{{o.info_title}}}" href="#">&nbsp;</a>
+
+<a class="fa fa-times close-room"
+   data-room-jid="{{{o.jid}}}"
+   data-room-name="{{{o.name || o.jid}}}"
+   title="{{{o.info_leave_room}}}" href="#">&nbsp;</a>
+
 </div>