Commit ac643ae6 authored by JC Brand's avatar JC Brand

Refactor views to use Backbone.OrderedListView

parent 102f39ed
......@@ -73,21 +73,25 @@
spyOn(_converse.chatboxviews, 'trimChats');
expect($("#conversejs .chatbox").length).toBe(1); // Controlbox is open
var online_contacts = _converse.rosterview.$el.find('.roster-group .current-xmpp-contact a.open-chat');
expect(online_contacts.length).toBe(15);
for (i=0; i<online_contacts.length; i++) {
$el = $(online_contacts[i]);
jid = $el.text().trim().replace(/ /g,'.').toLowerCase() + '@localhost';
$el.click();
chatboxview = _converse.chatboxviews.get(jid);
expect(_converse.chatboxes.length).toEqual(i+2);
expect(_converse.chatboxviews.trimChats).toHaveBeenCalled();
// Check that new chat boxes are created to the left of the
// controlbox (but to the right of all existing chat boxes)
expect($("#conversejs .chatbox").length).toBe(i+2);
expect($("#conversejs .chatbox")[1].id).toBe(chatboxview.model.get('box_id'));
}
done();
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group li').length;
}, 700).then(function () {
var online_contacts = _converse.rosterview.$el.find('.roster-group .current-xmpp-contact a.open-chat');
expect(online_contacts.length).toBe(15);
for (i=0; i<online_contacts.length; i++) {
$el = $(online_contacts[i]);
jid = $el.text().trim().replace(/ /g,'.').toLowerCase() + '@localhost';
$el.click();
chatboxview = _converse.chatboxviews.get(jid);
expect(_converse.chatboxes.length).toEqual(i+2);
expect(_converse.chatboxviews.trimChats).toHaveBeenCalled();
// Check that new chat boxes are created to the left of the
// controlbox (but to the right of all existing chat boxes)
expect($("#conversejs .chatbox").length).toBe(i+2);
expect($("#conversejs .chatbox")[1].id).toBe(chatboxview.model.get('box_id'));
}
done();
});
}));
it("can be trimmed to conserve space",
......@@ -109,10 +113,10 @@
spyOn(trimmed_chatboxes, 'removeChat').and.callThrough();
expect($("#conversejs .chatbox").length).toBe(1); // Controlbox is open
_converse.rosterview.update(); // XXX: Hack to make sure $roster element is attaced.
_converse.rosterview.update(); // XXX: Hack to make sure $roster element is attached.
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length;
}, 300).then(function () {
return _converse.rosterview.$el.find('.roster-group li').length;
}, 700).then(function () {
// Test that they can be maximized again
var online_contacts = _converse.rosterview.$el.find('.roster-group .current-xmpp-contact a.open-chat');
expect(online_contacts.length).toBe(15);
......@@ -836,10 +840,9 @@
}).c('body').t('Message: '+i).up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
}
test_utils.waitUntil(function () {
return chatboxview.$content.scrollTop();
}, 1000)
.then(function () {
return test_utils.waitUntil(function () {
return chatboxview.$content.scrollTop();
}, 1000).then(function () {
return test_utils.waitUntil(function () {
return !chatboxview.model.get('auto_scrolled');
}, 500);
......@@ -872,7 +875,7 @@
chatboxview.$content.scrollTop(chatboxview.$content[0].scrollHeight);
return test_utils.waitUntil(function () {
return !chatboxview.$('.new-msgs-indicator').is(':visible');
}, 500);
}, 700);
}).then(done);
}));
......@@ -1541,7 +1544,7 @@
view.model.maximize();
return test_utils.waitUntil(function () {
return view.model.get('chat_state') === 'active';
}, 500);
}, 700);
}).then(function () {
expect(_converse.connection.send).toHaveBeenCalled();
var calls = _.filter(_converse.connection.send.calls.all(), function (call) {
......@@ -1693,9 +1696,8 @@
test_utils.openControlBox();
test_utils.openContactsPanel(_converse);
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length;
}, 300)
.then(function () {
return _converse.rosterview.$el.find('.roster-group li').length;
}, 700).then(function () {
_converse.TIMEOUTS.PAUSED = 200; // Make the timeout shorter so that we can test
contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
......@@ -1715,7 +1717,7 @@
return test_utils.waitUntil(function () {
return view.model.get('chat_state') === 'paused';
}, 500);
}).then(function () {
}).then(function () {
expect(_converse.connection.send).toHaveBeenCalled();
var calls = _.filter(_converse.connection.send.calls.all(), function (call) {
return call.args[0] instanceof Strophe.Builder;
......
......@@ -182,14 +182,14 @@
var promise = test_utils.waitUntil(function () {
return $roster.find('li:visible').length === 15;
}, 500).then(function (contacts) {
}, 600).then(function (contacts) {
expect($roster.find('ul.roster-group-contacts:visible').length).toBe(5);
$filter.val("candice");
$filter.trigger('keydown');
return test_utils.waitUntil(function () {
return $roster.find('li:visible').length === 1;
}, 500);
}, 600);
}).then(function (contacts) {
// Only one roster contact is now visible
expect($roster.find('li:visible').length).toBe(1);
......@@ -203,7 +203,7 @@
$filter.trigger('keydown');
return test_utils.waitUntil(function () {
return $roster.find('li:visible').length === 5;
}, 500)
}, 600)
}).then(function (contacts) {
// Five roster contact is now visible
expect($roster.find('li:visible').length).toBe(5);
......@@ -220,7 +220,7 @@
$filter.trigger('keydown');
return test_utils.waitUntil(function () {
return $roster.find('li:visible').length === 0;
}, 500)
}, 600)
}).then(function () {
expect($roster.find('ul.roster-group-contacts:visible a.group-toggle').length).toBe(0);
$filter = _converse.rosterview.$('.roster-filter');
......@@ -228,7 +228,7 @@
$filter.trigger('keydown');
return test_utils.waitUntil(function () {
return $roster.find('li:visible').length === 15;
}, 500)
}, 600)
}).then(function () {
expect($roster.find('ul.roster-group-contacts:visible').length).toBe(5);
_converse.roster_groups = false;
......@@ -253,14 +253,14 @@
$type.val('groups');
test_utils.waitUntil(function () {
return $roster.find('li:visible').length === 15;
}, 500).then(function () {
}, 600).then(function () {
expect($roster.find('div.roster-group:visible a.group-toggle').length).toBe(5);
$filter.val("colleagues");
$filter.trigger('keydown');
return test_utils.waitUntil(function () {
return $roster.find('div.roster-group:not(.collapsed) a.group-toggle').length === 1;
}, 500);
}, 600);
}).then(function () {
expect(_.trim($roster.find('div.roster-group:not(.collapsed) a').eq(0).text())).toBe('colleagues');
expect($roster.find('div.roster-group:not(.collapsed) li:visible').length).toBe(3);
......@@ -281,7 +281,7 @@
$filter.trigger('keydown');
return test_utils.waitUntil(function () {
return $roster.find('div.roster-group.collapsed a.group-toggle').length === 0;
}, 500);
}, 600);
}).then(function () {
expect($roster.find('div.roster-group:not(collapsed)').length).toBe(5);
expect($roster.find('div.roster-group:not(collapsed) li').length).toBe(15);
......@@ -418,8 +418,8 @@
});
}
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('li:visible').length;
}, 500).then(function () {
return _converse.rosterview.$el.find('li:visible').length === 30;
}, 600).then(function () {
// Check that usernames appear alphabetically per group
_.each(groups, function (name) {
var $contacts = _converse.rosterview.$('.roster-group[data-group="'+name+'"] li');
......@@ -528,7 +528,7 @@
_addContacts(_converse);
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('li').length;
}, 500).then(function () {
}, 700).then(function () {
expect(_converse.rosterview.$el.is(':visible')).toEqual(true);
expect(_converse.rosterview.update).toHaveBeenCalled();
expect(_converse.rosterview.$el.find('li:visible').length).toBe(3);
......@@ -575,13 +575,12 @@
});
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')").length;
}, 500)
.then(function () {
}, 700).then(function () {
_converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')")
.parent().siblings('.remove-xmpp-contact').click();
return test_utils.waitUntil(function () {
return _converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')").length === 0
}, 500)
}, 700)
}).then(function () {
expect(window.confirm).toHaveBeenCalled();
expect(_converse.connection.sendIQ).toHaveBeenCalled();
......@@ -609,9 +608,9 @@
if (typeof callback === "function") { return callback(); }
});
test_utils.waitUntil(function () {
return _converse.rosterview.get('Pending contacts').$el.is(':visible');
}, 500)
.then(function () {
var $pending_contacts = _converse.rosterview.get('Pending contacts').$el;
return $pending_contacts.is(':visible') && $pending_contacts.find('li:visible').length;
}, 700).then(function () {
_converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')")
.parent().siblings('.remove-xmpp-contact').click();
expect(window.confirm).toHaveBeenCalled();
......@@ -644,6 +643,7 @@
function (done, _converse) {
var i, t;
test_utils.openControlBox();
spyOn(_converse, 'emit');
spyOn(_converse.rosterview, 'update').and.callThrough();
for (i=0; i<mock.pend_names.length; i++) {
......@@ -655,18 +655,25 @@
});
expect(_converse.rosterview.update).toHaveBeenCalled();
}
// Check that they are sorted alphabetically
t = _.reduce(_converse.rosterview.get('Pending contacts').$el.find('.pending-xmpp-contact span'), function (result, value) {
return result + _.trim(value.textContent);
}, '');
expect(t).toEqual(mock.pend_names.slice(0,i+1).sort().join(''));
done();
return test_utils.waitUntil(function () {
return _converse.rosterview.get('Pending contacts').$el.find('li:visible').length;
}, 700).then(function () {
// Check that they are sorted alphabetically
t = _.reduce(_converse.rosterview.get('Pending contacts').$el.find('.pending-xmpp-contact span'),
function (result, value) {
return result + _.trim(value.textContent);
}, '');
expect(t).toEqual(mock.pend_names.slice(0,i+1).sort().join(''));
done();
});
}));
});
describe("Existing Contacts", function () {
var _addContacts = function (_converse) {
test_utils.createContacts(_converse, 'current').openControlBox().openContactsPanel(_converse);
test_utils.createContacts(_converse, 'current')
.openControlBox()
.openContactsPanel(_converse);
};
it("can be collapsed under their own header",
......@@ -717,6 +724,7 @@
null, ['rosterGroupsFetched'], {},
function (done, _converse) {
test_utils.openControlBox();
spyOn(_converse.rosterview, 'update').and.callThrough();
for (var i=0; i<mock.cur_names.length; i++) {
_converse.roster.create({
......@@ -729,11 +737,13 @@
}
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('li').length;
}).then(function () {
}, 600).then(function () {
// Check that they are sorted alphabetically
var t = _.reduce(_converse.rosterview.$('.roster-group').find('.current-xmpp-contact.offline a.open-chat'), function (result, value) {
return result + _.trim(value.textContent);
}, '');
var t = _.reduce(_converse.rosterview.$('.roster-group')
.find('.current-xmpp-contact.offline a.open-chat'),
function (result, value) {
return result + _.trim(value.textContent);
}, '');
expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
done();
});
......@@ -781,9 +791,8 @@
fullname: name
});
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length;
}, 500)
.then(function () {
return _converse.rosterview.$el.find('.roster-group li').length;
}, 700).then(function () {
spyOn(window, 'confirm').and.returnValue(true);
spyOn(contact, 'removeFromRoster');
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback) {
......@@ -808,9 +817,8 @@
_addContacts(_converse);
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length;
}, 500)
.then(function () {
return _converse.rosterview.$el.find('.roster-group li').length;
}, 700).then(function () {
var jid, t;
spyOn(_converse, 'emit');
spyOn(_converse.rosterview, 'update').and.callThrough();
......@@ -836,9 +844,8 @@
_addContacts(_converse);
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length;
}, 500)
.then(function () {
return _converse.rosterview.$el.find('.roster-group li').length;
}, 700).then(function () {
var jid, t;
spyOn(_converse, 'emit');
spyOn(_converse.rosterview, 'update').and.callThrough();
......@@ -865,9 +872,8 @@
_addContacts(_converse);
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length;
}, 500)
.then(function () {
return _converse.rosterview.$el.find('.roster-group li').length;
}, 700).then(function () {
var jid, t;
spyOn(_converse, 'emit');
spyOn(_converse.rosterview, 'update').and.callThrough();
......@@ -894,9 +900,8 @@
_addContacts(_converse);
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length;
}, 500)
.then(function () {
return _converse.rosterview.$el.find('.roster-group li').length;
}, 700).then(function () {
var jid, t;
spyOn(_converse, 'emit');
spyOn(_converse.rosterview, 'update').and.callThrough();
......@@ -923,7 +928,7 @@
_addContacts(_converse);
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length;
return _converse.rosterview.$el.find('.roster-group li').length;
}, 500)
.then(function () {
var jid, t;
......@@ -952,8 +957,8 @@
_addContacts(_converse);
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length;
}, 500).then(function () {
return _converse.rosterview.$el.find('.roster-group li').length;
}, 700).then(function () {
var i, jid;
for (i=0; i<3; i++) {
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
......@@ -1071,13 +1076,17 @@
fullname: mock.req_names[i]
});
}
expect(_converse.rosterview.update).toHaveBeenCalled();
// Check that they are sorted alphabetically
children = _converse.rosterview.get('Contact requests').$el.find('.requesting-xmpp-contact span');
names = [];
children.each(addName);
expect(names.join('')).toEqual(mock.req_names.slice(0,mock.req_names.length+1).sort().join(''));
done();
test_utils.waitUntil(function () {
return _converse.rosterview.get('Contact requests').$el.find('li').length;
}, 700).then(function () {
expect(_converse.rosterview.update).toHaveBeenCalled();
// Check that they are sorted alphabetically
children = _converse.rosterview.get('Contact requests').$el.find('.requesting-xmpp-contact span');
names = [];
children.each(addName);
expect(names.join('')).toEqual(mock.req_names.slice(0,mock.req_names.length+1).sort().join(''));
done();
});
}));
it("do not have a header if there aren't any",
......@@ -1096,9 +1105,8 @@
fullname: name
});
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length;
}, 500)
.then(function () {
return _converse.rosterview.$el.find('.roster-group li').length;
}, 700).then(function () {
expect(_converse.rosterview.get('Contact requests').$el.is(':visible')).toEqual(true);
_converse.rosterview.$el.find(".req-contact-name:contains('"+name+"')")
.parent().siblings('.request-actions')
......@@ -1116,8 +1124,8 @@
test_utils.createContacts(_converse, 'requesting').openControlBox();
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length;
}, 500).then(function () {
return _converse.rosterview.$el.find('.roster-group li').length;
}, 700).then(function () {
checkHeaderToggling.apply(
_converse,
[_converse.rosterview.get('Contact requests').$el]
......@@ -1132,9 +1140,8 @@
test_utils.createContacts(_converse, 'requesting').openControlBox();
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length;
}, 500)
.then(function () {
return _converse.rosterview.$el.find('.roster-group li').length;
}, 700).then(function () {
// TODO: Testing can be more thorough here, the user is
// actually not accepted/authorized because of
// mock_connection.
......@@ -1161,9 +1168,8 @@
test_utils.createContacts(_converse, 'requesting').openControlBox();
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length;
}, 500)
.then(function () {
return _converse.rosterview.$el.find('.roster-group li').length;
}, 700).then(function () {
_converse.rosterview.update(); // XXX: Hack to make sure $roster element is attaced.
var name = mock.req_names.sort()[1];
var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
......@@ -1193,7 +1199,7 @@
_converse.connection._dataRecv(test_utils.createRequest(stanza));
test_utils.waitUntil(function () {
return $('a:contains("Contact requests")').length;
}).then(function () {
}, 700).then(function () {
expect(_converse.roster.pluck('jid').length).toBe(1);
expect(_.includes(_converse.roster.pluck('jid'), 'data@enterprise')).toBeTruthy();
// Taken from the spec
......@@ -1265,9 +1271,8 @@
test_utils.createContacts(_converse, 'all').openControlBox();
test_utils.openContactsPanel(_converse);
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length;
}, 500)
.then(function () {
return _converse.rosterview.$el.find('.roster-group li').length;
}, 700).then(function () {
var jid, name, i;
for (i=0; i<mock.cur_names.length; i++) {
name = mock.cur_names[i];
......@@ -1324,8 +1329,8 @@
fullname: mock.pend_names[0]
});
test_utils.waitUntil(function () {
return _converse.rosterview.$el.find('.roster-group').length;
}, 500).then(function () {
return _converse.rosterview.$el.find('.roster-group li').length;
}, 700).then(function () {
// Checking that only one entry is created because both JID is same (Case sensitive check)
expect(_converse.rosterview.$el.find('li:visible').length).toBe(1);
expect(_converse.rosterview.update).toHaveBeenCalled();
......
......@@ -228,11 +228,11 @@
expect(_converse.roster.updateContact).toHaveBeenCalled();
// Check that the user is now properly shown as a pending
// contact in the roster.
var $header = $('a:contains("Pending contacts")');
return test_utils.waitUntil(function () {
return $('a:contains("Pending contacts")').length && $header.is(":visible");
}, 300);
var $header = $('a:contains("Pending contacts")');
var $contacts = $header.parent().find('li');
return $contacts.length;
}, 600);
}).then(function () {
var $header = $('a:contains("Pending contacts")');
var $contacts = $header.parent().find('li');
......@@ -297,10 +297,16 @@
// The contact should now be visible as an existing
// contact (but still offline).
$header = $('a:contains("My contacts")');
return test_utils.waitUntil(function () {
var $header = $('a:contains("My contacts")');
var $contacts = $header.parent().find('li');
return $contacts.length;
}, 600);
}).then(function () {
var $header = $('a:contains("My contacts")');
expect($header.length).toBe(1);
expect($header.is(":visible")).toBeTruthy();
$contacts = $header.parent().find('li');
var $contacts = $header.parent().find('li');
expect($contacts.length).toBe(1);
// Check that it has the right classes and text
expect($contacts.hasClass('to')).toBeTruthy();
......@@ -482,10 +488,12 @@
sent_IQ = iq;
IQ_id = sendIQ.bind(this)(iq, callback, errback);
});
return test_utils.waitUntil(function () {
var $header = $('a:contains("My contacts")');
var $contacts = $header.parent().find('li');
return $contacts.length;
}, 600).then(function () {
test_utils.waitUntil(function () {
return $('a:contains("My contacts")').length;
}).then(function () {
var $header = $('a:contains("My contacts")');
// remove the first user
$($header.parent().find('li .remove-xmpp-contact').get(0)).click();
......@@ -547,9 +555,11 @@
'xmlns': Strophe.NS.NICK,
}).t('Clint Contact');
_converse.connection._dataRecv(test_utils.createRequest(stanza));
test_utils.waitUntil(function () {
return $('a:contains("Contact requests")').length;
}).then(function () {
return test_utils.waitUntil(function () {
var $header = $('a:contains("Contact requests")');
var $contacts = $header.parent().find('li');
return $contacts.length;
}, 600).then(function () {
expect(_converse.emit).toHaveBeenCalledWith('contactRequest', jasmine.any(Object));
var $header = $('a:contains("Contact requests")');
expect($header.length).toBe(1);
......
......@@ -22,6 +22,7 @@ require.config({
"backbone.browserStorage": "node_modules/backbone.browserStorage/backbone.browserStorage",
"backbone.noconflict": "src/backbone.noconflict",
"backbone.overview": "node_modules/backbone.overview/backbone.overview",
"backbone.orderedlistview": "node_modules/backbone.overview/backbone.orderedlistview",
"backbone.vdomview": "node_modules/backbone.vdomview/backbone.vdomview",
"emojione": "node_modules/emojione/lib/js/emojione",
"es6-promise": "node_modules/es6-promise/dist/es6-promise.auto",
......
......@@ -16,8 +16,7 @@
"strophe",
"pluggable",
"backbone.noconflict",
"backbone.browserStorage",
"backbone.overview",
"backbone.browserStorage"
], factory);
}(this, function (sizzle, Promise, _, polyfill, i18n, utils, moment, Strophe, pluggable, Backbone) {
......
......@@ -37,6 +37,8 @@
"awesomplete",
"converse-chatview",
"converse-disco",
"backbone.overview",
"backbone.orderedlistview",
"backbone.vdomview"
], factory);
}(this, function (
......@@ -2213,16 +2215,17 @@
},
});
_converse.ChatRoomOccupantsView = Backbone.Overview.extend({
_converse.ChatRoomOccupantsView = Backbone.OrderedListView.extend({
tagName: 'div',
className: 'occupants',
listItems: 'model',
sortEvent: 'change:role',
listSelector: '.occupant-list',
ItemView: _converse.ChatRoomOccupantView,
initialize () {
this.model.on("add", this.onOccupantAdded, this);
this.model.on("change:role", (occupant) => {
this.model.sort();
this.positionOccupant(occupant);
});
Backbone.OrderedListView.prototype.initialize.apply(this, arguments);
this.chatroomview = this.model.chatroomview;
this.chatroomview.model.on('change:open', this.renderInviteWidget, this);
......@@ -2247,9 +2250,7 @@
this.model.fetch({
'add': true,
'silent': true,
'success': () => {
this.model.each(this.onOccupantAdded.bind(this));
}
'success': this.sortAndPositionAllItems.bind(this)
});
},
......@@ -2353,57 +2354,12 @@
this.debouncedRenderRoomFeatures();
},
setOccupantsHeight () {
const el = this.el.querySelector('.chatroom-features');
this.el.querySelector('.occupant-list').style.cssText =
`height: calc(100% - ${el.offsetHeight}px - 5em);`;
},
positionOccupant (occupant) {
/* Positions an occupant correctly in the list of
* occupants.
*
* IMPORTANT: there's an important implicit assumption being
* made here. And that is that initially this method gets called
* for each occupant in the right positional order.
*
* In other words, it gets called for the 0th, then the
* 1st, then the 2nd, 3rd and so on.
*
* That's why we call it in the "success" handler after
* fetching the occupants, so that we know we have ALL of
* them and that they're sorted.
*/
const view = this.get(occupant.get('id'));
view.render();
const list = this.el.querySelector('.occupant-list');
const index = this.model.indexOf(view.model);
if (index === 0) {
list.insertAdjacentElement('afterbegin', view.el);
} else if (index === (this.model.length-1)) {
list.insertAdjacentElement('beforeend', view.el);
} else {
const neighbour_el = list.querySelector('li:nth-child('+index+')');
neighbour_el.insertAdjacentElement('afterend', view.el);
}
return view;
},
onOccupantAdded (item) {
let view = this.get(item.get('id'));
if (!view) {
view = this.add(
item.get('id'),
new _converse.ChatRoomOccupantView({model: item})
);
} else {
view.model = item;
view.initialize();
}
this.positionOccupant(item);
},
parsePresence (pres) {
const id = Strophe.getResourceFromJid(pres.getAttribute("from"));
const data = {
......
......@@ -285,8 +285,12 @@
this.model.on("reset", this.reset, this);
_converse.on('rosterGroupsFetched', this.positionFetchedGroups, this);
_converse.on('rosterContactsFetched', () => {
_converse.roster.each(this.onContactAdded.bind(this));
_converse.roster.each((contact) => {
this.addRosterContact(contact, {'silent': true});
});
this.update();
this.updateFilter();
this.trigger('rosterContactsFetchedAndProcessed');
});
this.createRosterFilter();
},
......@@ -474,11 +478,11 @@
return this.model.create({name, id: b64_sha1(name)});
},
addContactToGroup (contact, name) {
this.getGroup(name).contacts.add(contact);
addContactToGroup (contact, name, options) {
this.getGroup(name).contacts.add(contact, options);
},
addExistingContact (contact) {
addExistingContact (contact, options) {
let groups;
if (_converse.roster_groups) {
groups = contact.get('groups');
......@@ -488,17 +492,17 @@
} else {
groups = [HEADER_CURRENT_CONTACTS];
}
_.each(groups, _.bind(this.addContactToGroup, this, contact));
_.each(groups, _.bind(this.addContactToGroup, this, contact, _, options));
},
addRosterContact (contact) {
addRosterContact (contact, options) {
if (contact.get('subscription') === 'both' || contact.get('subscription') === 'to') {
this.addExistingContact(contact);
this.addExistingContact(contact, options);
} else {
if ((contact.get('ask') === 'subscribe') || (contact.get('subscription') === 'from')) {
this.addContactToGroup(contact, HEADER_PENDING_CONTACTS);
this.addContactToGroup(contact, HEADER_PENDING_CONTACTS, options);
} else if (contact.get('requesting') === true) {
this.addContactToGroup(contact, HEADER_REQUESTING_CONTACTS);
this.addContactToGroup(contact, HEADER_REQUESTING_CONTACTS, options);
}
}
return this;
......@@ -670,22 +674,34 @@
});
_converse.RosterGroupView = Backbone.Overview.extend({
_converse.RosterGroupView = Backbone.OrderedListView.extend({
tagName: 'div',
className: 'roster-group',
events: {
"click a.group-toggle": "toggle"
},
listItems: 'model.contacts',
sortEvent: 'change:chat_status',
listSelector: '.roster-group-contacts',
ItemView: _converse.RosterContactView,
initialize () {
this.sortEventually = _.debounce(this.sortAndPositionAll, 500);
this.model.contacts.on("add", this.onContactAdded, this);
Backbone.OrderedListView.prototype.initialize.apply(this, arguments);
this.model.contacts.on("change:subscription", this.onContactSubscriptionChange, this);
this.model.contacts.on("change:requesting", this.onContactRequestChange, this);
this.model.contacts.on("change:chat_status", this.sortEventually, this);
this.model.contacts.on("destroy", this.onRemove, this);
this.model.contacts.on("remove", this.onRemove, this);
_converse.roster.on('change:groups', this.onContactGroupChange, this);
// This event gets triggered once *all* contacts (i.e. not
// just this group's) have been fetched from browser
// storage or the XMPP server and once they've been
// assigned to their various groups.
_converse.rosterview.on(
'rosterContactsFetchedAndProcessed',
this.sortAndPositionAllItems.bind(this)
);
},
render () {
......@@ -700,49 +716,19 @@
return this;
},
createContactView (contact) {
const contact_view = new _converse.RosterContactView({model: contact});
this.add(contact.get('id'), contact_view);
contact_view.render();
return contact_view;
},
onContactAdded (contact) {
const contact_view = this.positionContact(contact);
createItemView (contact) {
const contact_view =
Backbone.OrderedListView.prototype.createItemView.apply(this, arguments);
if (contact_view.mayBeShown()) {
if (this.model.get('state') === _converse.CLOSED) {
u.hideElement(contact_view.el);
u.showElement(this.el);
} else {
u.showElement(contact_view.el);
u.showElement(this.el);
}
u.showElement(this.el);
}
},
positionContact (contact) {
/* Place the contact's DOM element in the correct alphabetical
* position amongst the other contacts in this group.
*/
const view = this.get(contact.get('id')) || this.createContactView(contact);
const list = this.contacts_el;
const index = this.model.contacts.indexOf(contact);
if (index === 0) {
list.insertAdjacentElement('afterbegin', view.el);
} else if (index === (this.model.contacts.length-1)) {
list.insertAdjacentElement('beforeend', view.el);
} else {
const neighbour_el = list.querySelector('li:nth-child('+index+')');
neighbour_el.insertAdjacentElement('afterend', view.el);
}
return view;
},
sortAndPositionAll () {
this.model.contacts.sort();
this.model.contacts.each(this.positionContact.bind(this));
},
show () {
u.showElement(this.el);
_.each(this.getAll(), (contact_view) => {
......@@ -851,7 +837,7 @@
if (in_this_group && !in_this_overview) {
this.model.contacts.remove(cid);
} else if (!in_this_group && in_this_overview) {
this.onContactAdded(contact);
this.items.trigger('add', contact);
}
},
......
......@@ -106,6 +106,7 @@
'bosh_service_url': 'localhost',
'connection': connection,
'animate': false,
'use_emojione': false,
'no_trimming': true,
'auto_login': true,
'jid': 'dummy@localhost',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment