Sfoglia il codice sorgente

Update to latest backbone.overview which debounces sorting on `add` event

JC Brand 6 anni fa
parent
commit
98215deb21
9 ha cambiato i file con 95 aggiunte e 32 eliminazioni
  1. 1 1
      .eslintrc.json
  2. 2 2
      package-lock.json
  3. 1 1
      package.json
  4. 7 2
      spec/bookmarks.js
  5. 1 1
      spec/chatbox.js
  6. 28 14
      spec/muc.js
  7. 32 1
      spec/profiling.js
  8. 18 7
      spec/roomslist.js
  9. 5 3
      src/converse-rosterview.js

+ 1 - 1
.eslintrc.json

@@ -24,7 +24,7 @@
             "ignoreMethods": [
                 "assign", "every", "keys", "find", "endsWith", "startsWith", "filter",
                 "reduce", "isArray", "create", "map", "replace", "some", "toLower",
-                "split", "trim", "forEach", "toUpperCase", "includes", "values"
+                "split", "trim", "forEach", "toUpperCase", "includes", "values", "padStart"
             ]
         }],
         "lodash/import-scope": "off",

+ 2 - 2
package-lock.json

@@ -2673,8 +2673,8 @@
       "dev": true
     },
     "backbone.overview": {
-      "version": "github:jcbrand/Backbone.Overview#b3e759127d859c90e8e21700a9a5714a3b828f0a",
-      "from": "github:jcbrand/Backbone.Overview#b3e759127d859c90e8e21700a9a5714a3b828f0a",
+      "version": "github:jcbrand/Backbone.Overview#d83d0fc0e40aaf3fb5b4db81576b0eba46d6739a",
+      "from": "github:jcbrand/Backbone.Overview#d83d0fc0e40aaf3fb5b4db81576b0eba46d6739a",
       "dev": true,
       "requires": {
         "lodash": "^4.17.11"

+ 1 - 1
package.json

@@ -57,7 +57,7 @@
     "@fortawesome/fontawesome-free": "5.3.1",
     "babel-loader": "^8.0.4",
     "backbone.nativeview": "conversejs/Backbone.NativeView#5997c8197ca594e6b8469447f28310c78bd1d95e",
-    "backbone.overview": "jcbrand/Backbone.Overview#b3e759127d859c90e8e21700a9a5714a3b828f0a",
+    "backbone.overview": "jcbrand/Backbone.Overview#d83d0fc0e40aaf3fb5b4db81576b0eba46d6739a",
     "backbone.vdomview": "^1.0.1",
     "bootstrap": "^4.0.0",
     "bootstrap.native": "^2.0.26",

+ 7 - 2
spec/bookmarks.js

@@ -661,12 +661,14 @@
             { hide_open_bookmarks: true },
             async function (done, _converse) {
 
+            test_utils.openControlBox();
             const jid = 'room@conference.example.org';
             await test_utils.waitUntilDiscoConfirmed(
                 _converse, _converse.bare_jid,
                 [{'category': 'pubsub', 'type': 'pep'}],
                 ['http://jabber.org/protocol/pubsub#publish-options']
             );
+            await test_utils.waitUntil(() => _converse.bookmarks);
             // XXX Create bookmarks view here, otherwise we need to mock stanza
             // traffic for it to get created.
             _converse.bookmarksview = new _converse.BookmarksView(
@@ -682,13 +684,16 @@
                 'nick': ' Othello'
             });
             expect(_converse.bookmarks.length).toBe(1);
-            const room_els = _converse.bookmarksview.el.querySelectorAll(".open-room");
+
+            const bmarks_view = _converse.bookmarksview;
+            await test_utils.waitUntil(() => bmarks_view.el.querySelectorAll(".open-room").length, 500);
+            const room_els = bmarks_view.el.querySelectorAll(".open-room");
             expect(room_els.length).toBe(1);
 
-            // Check that it disappears once the room is opened
             const bookmark = _converse.bookmarksview.el.querySelector(".open-room");
             bookmark.click();
             await test_utils.waitUntil(() => _converse.chatboxviews.get(jid));
+
             expect(u.hasClass('hidden', _converse.bookmarksview.el.querySelector(".available-chatroom"))).toBeTruthy();
             // Check that it reappears once the room is closed
             const view = _converse.chatboxviews.get(jid);

+ 1 - 1
spec/chatbox.js

@@ -1467,7 +1467,7 @@
                 _converse.chatboxes.onMessage(msgFactory());
                 await test_utils.waitUntil(() => chatbox.messages.length > 1);
                 expect(select_msgs_indicator().textContent).toBe('2');
-                view.maximize();
+                view.model.maximize();
                 expect(select_msgs_indicator()).toBeUndefined();
                 done();
             }));

+ 28 - 14
spec/muc.js

@@ -1484,8 +1484,8 @@
                 var name;
                 const view = _converse.chatboxviews.get('lounge@montague.lit');
                 const occupants = view.el.querySelector('.occupant-list');
-                var presence, role, jid, model;
-                for (var i=0; i<mock.chatroom_names.length; i++) {
+                var presence, role, jid;
+                for (let i=0; i<mock.chatroom_names.length; i++) {
                     name = mock.chatroom_names[i];
                     role = mock.chatroom_roles[name].role;
                     // See example 21 https://xmpp.org/extensions/xep-0045.html#enter-pres
@@ -1500,15 +1500,20 @@
                         role: role
                     });
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
-                    expect(occupants.querySelectorAll('li').length).toBe(2+i);
-                    model = view.model.occupants.where({'nick': name})[0];
-                    const index = view.model.occupants.indexOf(model);
-                    expect(occupants.querySelectorAll('li .occupant-nick')[index].textContent.trim()).toBe(mock.chatroom_names[i]);
                 }
 
+                await test_utils.waitUntil(() => occupants.querySelectorAll('li').length > 2, 500);
+                expect(occupants.querySelectorAll('li').length).toBe(1+mock.chatroom_names.length);
+
+                mock.chatroom_names.forEach(name => {
+                    const model = view.model.occupants.findWhere({'nick': name});
+                    const index = view.model.occupants.indexOf(model);
+                    expect(occupants.querySelectorAll('li .occupant-nick')[index].textContent.trim()).toBe(name);
+                });
+
                 // Test users leaving the groupchat
                 // https://xmpp.org/extensions/xep-0045.html#exit
-                for (i=mock.chatroom_names.length-1; i>-1; i--) {
+                for (let i=mock.chatroom_names.length-1; i>-1; i--) {
                     name = mock.chatroom_names[i];
                     role = mock.chatroom_roles[name].role;
                     // See example 21 https://xmpp.org/extensions/xep-0045.html#enter-pres
@@ -1554,12 +1559,17 @@
                     }).up()
                     .c('status').attrs({code:'110'}).nodeTree;
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
-                    expect(occupants.querySelectorAll('li').length).toBe(2+i);
-                    model = view.model.occupants.where({'nick': name})[0];
-                    const index = view.model.occupants.indexOf(model);
-                    expect(occupants.querySelectorAll('li .occupant-nick')[index].textContent.trim()).toBe(mock.chatroom_names[i]);
                 }
 
+                await test_utils.waitUntil(() => occupants.querySelectorAll('li').length > 1, 500);
+                expect(occupants.querySelectorAll('li').length).toBe(1+mock.chatroom_names.length);
+
+                mock.chatroom_names.forEach(name => {
+                    const model = view.model.occupants.findWhere({'nick': name});
+                    const index = view.model.occupants.indexOf(model);
+                    expect(occupants.querySelectorAll('li .occupant-nick')[index].textContent.trim()).toBe(name);
+                });
+
                 // Test users leaving the groupchat
                 // https://xmpp.org/extensions/xep-0045.html#exit
                 for (i=mock.chatroom_names.length-1; i>-1; i--) {
@@ -1607,6 +1617,7 @@
 
                 _converse.connection._dataRecv(test_utils.createRequest(presence));
                 const view = _converse.chatboxviews.get('lounge@montague.lit');
+                await test_utils.waitUntil(() => view.el.querySelectorAll('li .occupant-nick').length, 500);
                 const occupants = view.el.querySelector('.occupant-list').querySelectorAll('li .occupant-nick');
                 expect(occupants.length).toBe(2);
                 expect(occupants[0].textContent.trim()).toBe("&lt;img src=&quot;x&quot; onerror=&quot;alert(123)&quot;/&gt;");
@@ -1622,7 +1633,8 @@
                 const view = _converse.chatboxviews.get('lounge@montague.lit');
                 let contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@montague.lit';
 
-                let occupants = view.el.querySelector('.occupant-list').querySelectorAll('li');
+                await test_utils.waitUntil(() => view.el.querySelectorAll('.occupant-list li').length, 500);
+                let occupants = view.el.querySelectorAll('.occupant-list li');
                 expect(occupants.length).toBe(1);
                 expect(occupants[0].querySelector('.occupant-nick').textContent.trim()).toBe("romeo");
                 expect(occupants[0].querySelectorAll('.badge').length).toBe(2);
@@ -1641,6 +1653,7 @@
                 .c('status').attrs({code:'110'}).nodeTree;
 
                 _converse.connection._dataRecv(test_utils.createRequest(presence));
+                await test_utils.waitUntil(() => view.el.querySelectorAll('.occupant-list li').length > 1, 500);
                 occupants = view.el.querySelectorAll('.occupant-list li');
                 expect(occupants.length).toBe(2);
                 expect(occupants[0].querySelector('.occupant-nick').textContent.trim()).toBe("moderatorman");
@@ -1665,6 +1678,7 @@
                 .c('status').attrs({code:'110'}).nodeTree;
                 _converse.connection._dataRecv(test_utils.createRequest(presence));
 
+                await test_utils.waitUntil(() => view.el.querySelectorAll('.occupant-list li').length > 2, 500);
                 occupants = view.el.querySelector('.occupant-list').querySelectorAll('li');
                 expect(occupants.length).toBe(3);
                 expect(occupants[2].querySelector('.occupant-nick').textContent.trim()).toBe("visitorwoman");
@@ -2209,6 +2223,7 @@
                 expect(view.model.get('connection_status')).toBe(converse.ROOMSTATUS.ENTERED);
                 const chat_content = view.el.querySelector('.chat-content');
 
+                await test_utils.waitUntil(() => view.el.querySelectorAll('li .occupant-nick').length, 500);
                 let occupants = view.el.querySelector('.occupant-list');
                 expect(occupants.childNodes.length).toBe(1);
                 expect(occupants.firstElementChild.querySelector('.occupant-nick').textContent.trim()).toBe("oldnick");
@@ -2840,7 +2855,6 @@
                     async function (done, _converse) {
 
                 let iq_stanza;
-
                 await test_utils.openAndEnterChatRoom(_converse, 'lounge', 'muc.montague.lit', 'romeo');
                 const view = _converse.chatboxviews.get('lounge@muc.montague.lit');
                 /* We don't show join/leave messages for existing occupants. We
@@ -2973,7 +2987,7 @@
                     "id": iq_stanza.getAttribute("id")
                 }).c("query", {"xmlns": "http://jabber.org/protocol/muc#admin"})
                 _converse.connection._dataRecv(test_utils.createRequest(result));
-
+                await test_utils.waitUntil(() => view.el.querySelectorAll('.occupant').length, 500);
                 await test_utils.waitUntil(() => view.el.querySelectorAll('.badge').length > 1);
                 expect(view.model.occupants.length).toBe(2);
                 expect(view.el.querySelectorAll('.occupant').length).toBe(2);

+ 32 - 1
spec/profiling.js

@@ -3,9 +3,40 @@
 } (this, function (jasmine, mock, test_utils) {
     var _ = converse.env._;
     var $iq = converse.env.$iq;
+    var $pres = converse.env.$pres;
     var u = converse.env.utils;
 
     describe("Profiling", function() {
+
+        it("shows users currently present in the groupchat",
+            mock.initConverse(
+                null, ['rosterGroupsFetched'], {'muc_show_join_leave': false},
+                async function (done, _converse) {
+
+            test_utils.openControlBox();
+            await test_utils.openAndEnterChatRoom(_converse, 'lounge', 'montague.lit', 'romeo');
+            const view = _converse.chatboxviews.get('lounge@montague.lit'),
+                  occupants = view.el.querySelector('.occupant-list');
+            _.rangeRight(3000, 0).forEach(i => {
+                const name = `User ${i.toString().padStart(5, '0')}`;
+                const presence = $pres({
+                        'to': 'romeo@montague.lit/orchard',
+                        'from': 'lounge@montague.lit/'+name
+                }).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
+                .c('item').attrs({
+                    affiliation: 'none',
+                    jid: name.replace(/ /g,'.').toLowerCase() + '@montague.lit',
+                });
+                _converse.connection._dataRecv(test_utils.createRequest(presence));
+
+                // expect(occupants.querySelectorAll('li').length).toBe(1+i);
+                // const model = view.model.occupants.where({'nick': name})[0];
+                // const index = view.model.occupants.indexOf(model);
+                // expect(occupants.querySelectorAll('li .occupant-nick')[index].textContent.trim()).toBe(name);
+            });
+            done();
+        }));
+
         xit("adds hundreds of contacts to the roster",
                 mock.initConverse(
                     null, ['rosterGroupsFetched'], {},
@@ -54,7 +85,7 @@
                 mock.initConverse(
                     null, ['rosterGroupsFetched'], {},
                     function (done, _converse) {
-            
+
             // _converse.show_only_online_users = true;
             _converse.roster_groups = true;
             test_utils.openControlBox();

+ 18 - 7
spec/roomslist.js

@@ -20,10 +20,15 @@
 
             await test_utils.openChatRoom(_converse, 'room', 'conference.shakespeare.lit', 'JC');
             expect(_.isUndefined(_converse.rooms_list_view)).toBeFalsy();
-            let room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room");
+
+            const lview = _converse.rooms_list_view
+            await test_utils.waitUntil(() => lview.el.querySelectorAll(".open-room").length);
+            let room_els = lview.el.querySelectorAll(".open-room");
             expect(room_els.length).toBe(1);
             expect(room_els[0].innerText).toBe('room@conference.shakespeare.lit');
+
             await test_utils.openChatRoom(_converse, 'lounge', 'montague.lit', 'romeo');
+            await test_utils.waitUntil(() => lview.el.querySelectorAll(".open-room").length > 1);
             room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room");
             expect(room_els.length).toBe(2);
 
@@ -119,19 +124,23 @@
               allow_bookmarks: false // Makes testing easier, otherwise we have to mock stanza traffic.
             }, async function (done, _converse) {
 
-            let room_els, item;
+            let item;
             await _converse.api.rooms.open('coven@chat.shakespeare.lit', {'nick': 'some1'});
-            room_els = _converse.rooms_list_view.el.querySelectorAll(".available-chatroom");
+
+            const lview = _converse.rooms_list_view
+            await test_utils.waitUntil(() => lview.el.querySelectorAll(".open-room").length);
+            let room_els = lview.el.querySelectorAll(".available-chatroom");
             expect(room_els.length).toBe(1);
 
             item = room_els[0];
             expect(u.hasClass('open', item)).toBe(true);
             expect(item.textContent.trim()).toBe('coven@chat.shakespeare.lit');
             await _converse.api.rooms.open('balcony@chat.shakespeare.lit', {'nick': 'some1'});
-            room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room");
+            await test_utils.waitUntil(() => lview.el.querySelectorAll(".open-room").length > 1);
+            room_els = lview.el.querySelectorAll(".open-room");
             expect(room_els.length).toBe(2);
 
-            room_els = _converse.rooms_list_view.el.querySelectorAll(".available-chatroom.open");
+            room_els = lview.el.querySelectorAll(".available-chatroom.open");
             expect(room_els.length).toBe(1);
             item = room_els[0];
             expect(item.textContent.trim()).toBe('balcony@chat.shakespeare.lit');
@@ -258,9 +267,11 @@
             expect(_converse.chatboxes.length).toBe(1);
             await test_utils.openChatRoom(_converse, 'lounge', 'conference.shakespeare.lit', 'JC');
             expect(_converse.chatboxes.length).toBe(2);
-            var room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room");
+            const lview = _converse.rooms_list_view
+            await test_utils.waitUntil(() => lview.el.querySelectorAll(".open-room").length);
+            let room_els = lview.el.querySelectorAll(".open-room");
             expect(room_els.length).toBe(1);
-            var close_el = _converse.rooms_list_view.el.querySelector(".close-room");
+            const close_el = _converse.rooms_list_view.el.querySelector(".close-room");
             close_el.click();
             expect(window.confirm).toHaveBeenCalledWith(
                 'Are you sure you want to leave the groupchat lounge@conference.shakespeare.lit?');

+ 5 - 3
src/converse-rosterview.js

@@ -540,6 +540,7 @@ converse.plugins.add('converse-rosterview', {
                 "click a.group-toggle": "toggle"
             },
 
+            sortImmediatelyOnAdd: true,
             ItemView: _converse.RosterContactView,
             listItems: 'model.contacts',
             listSelector: '.roster-group-contacts',
@@ -558,7 +559,7 @@ converse.plugins.add('converse-rosterview', {
                 // assigned to their various groups.
                 _converse.rosterview.on(
                     'rosterContactsFetchedAndProcessed',
-                    this.sortAndPositionAllItems.bind(this)
+                    () => this.sortAndPositionAllItems()
                 );
             },
 
@@ -597,7 +598,7 @@ converse.plugins.add('converse-rosterview', {
                  */
                 let shown = 0;
                 const all_contact_views = this.getAll();
-                _.each(this.model.contacts.models, (contact) => {
+                this.model.contacts.forEach(contact => {
                     const contact_view = this.get(contact.get('id'));
                     if (_.includes(contacts, contact)) {
                         u.hideElement(contact_view.el);
@@ -730,6 +731,7 @@ converse.plugins.add('converse-rosterview', {
             listSelector: '.roster-contacts',
             sortEvent: null, // Groups are immutable, so they don't get re-sorted
             subviewIndex: 'name',
+            sortImmediatelyOnAdd: true,
 
             events: {
                 'click a.controlbox-heading__btn.add-contact': 'showAddContactModal',
@@ -758,7 +760,7 @@ converse.plugins.add('converse-rosterview', {
                 _converse.api.listen.on('rosterGroupsFetched', this.sortAndPositionAllItems.bind(this));
 
                 _converse.api.listen.on('rosterContactsFetched', () => {
-                    _converse.roster.each((contact) => this.addRosterContact(contact, {'silent': true}));
+                    _converse.roster.each(contact => this.addRosterContact(contact, {'silent': true}));
                     this.update();
                     this.updateFilter();
                     this.trigger('rosterContactsFetchedAndProcessed');