Merge pull request #3 from ichim-david/master
Optimize actions done in RosterView.
This commit is contained in:
commit
d7cb92c7af
165
converse.js
165
converse.js
@ -209,6 +209,7 @@
|
|||||||
if (msgs.length) {
|
if (msgs.length) {
|
||||||
return sjcl.decrypt(hex_sha1(this.get('own_jid')), msgs[msgs.length-1]);
|
return sjcl.decrypt(hex_sha1(this.get('own_jid')), msgs[msgs.length-1]);
|
||||||
}
|
}
|
||||||
|
return undefined;
|
||||||
},
|
},
|
||||||
|
|
||||||
clearMessages: function (jid) {
|
clearMessages: function (jid) {
|
||||||
@ -560,7 +561,7 @@
|
|||||||
'<a href="{{user_profile_url}}" class="user">' +
|
'<a href="{{user_profile_url}}" class="user">' +
|
||||||
'<img src="{{portrait_url}}" alt="Avatar of {{fullname}}" class="avatar" />' +
|
'<img src="{{portrait_url}}" alt="Avatar of {{fullname}}" class="avatar" />' +
|
||||||
'<div class="chat-title"> {{ fullname }} </div>' +
|
'<div class="chat-title"> {{ fullname }} </div>' +
|
||||||
'</a>' +
|
'</a>' +
|
||||||
'<p class="user-custom-message"><p/>' +
|
'<p class="user-custom-message"><p/>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<div class="chat-content"></div>' +
|
'<div class="chat-content"></div>' +
|
||||||
@ -688,7 +689,9 @@
|
|||||||
},
|
},
|
||||||
room_template: _.template(
|
room_template: _.template(
|
||||||
'<dd class="available-chatroom">' +
|
'<dd class="available-chatroom">' +
|
||||||
'<a class="open-room" room-jid="{{jid}}" title="Click to open this chatroom" href="#">' +
|
'<a class="open-room" data-room-jid="{{jid}}"' +
|
||||||
|
' title="Click to open this chatroom"' +
|
||||||
|
' href="#">' +
|
||||||
'{{name}}</a></dd>'),
|
'{{name}}</a></dd>'),
|
||||||
|
|
||||||
tab_template: _.template('<li><a class="s" href="#chatrooms">Rooms</a></li>'),
|
tab_template: _.template('<li><a class="s" href="#chatrooms">Rooms</a></li>'),
|
||||||
@ -738,7 +741,7 @@
|
|||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
var name, jid;
|
var name, jid;
|
||||||
if (ev.type === 'click') {
|
if (ev.type === 'click') {
|
||||||
jid = $(ev.target).attr('room-jid');
|
jid = $(ev.target).attr('data-room-jid');
|
||||||
} else {
|
} else {
|
||||||
name = $(ev.target).find('input.new-chatroom-name').val().trim().toLowerCase();
|
name = $(ev.target).find('input.new-chatroom-name').val().trim().toLowerCase();
|
||||||
if (name) {
|
if (name) {
|
||||||
@ -1159,12 +1162,13 @@
|
|||||||
view.messageReceived(message);
|
view.messageReceived(message);
|
||||||
xmppchat.roster.addResource(partner_jid, resource);
|
xmppchat.roster.addResource(partner_jid, resource);
|
||||||
}, this));
|
}, this));
|
||||||
return;
|
return undefined;
|
||||||
} else if (!view.isVisible()) {
|
} else if (!view.isVisible()) {
|
||||||
this.showChat(partner_jid);
|
this.showChat(partner_jid);
|
||||||
}
|
}
|
||||||
view.messageReceived(message);
|
view.messageReceived(message);
|
||||||
xmppchat.roster.addResource(partner_jid, resource);
|
xmppchat.roster.addResource(partner_jid, resource);
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize: function () {
|
initialize: function () {
|
||||||
@ -1186,7 +1190,7 @@
|
|||||||
|
|
||||||
// Add the roster
|
// Add the roster
|
||||||
xmppchat.roster = new xmppchat.RosterItems();
|
xmppchat.roster = new xmppchat.RosterItems();
|
||||||
xmppchat.rosterview = new xmppchat.RosterView({'model':xmppchat.roster}).render();
|
xmppchat.rosterview = new xmppchat.RosterView({'model':xmppchat.roster});
|
||||||
xmppchat.rosterview.$el.appendTo(controlbox.contactspanel.$el);
|
xmppchat.rosterview.$el.appendTo(controlbox.contactspanel.$el);
|
||||||
|
|
||||||
// Rebind events (necessary for click events on tabs inserted via the panels)
|
// Rebind events (necessary for click events on tabs inserted via the panels)
|
||||||
@ -1224,11 +1228,19 @@
|
|||||||
xmppchat.RosterItemView = Backbone.View.extend({
|
xmppchat.RosterItemView = Backbone.View.extend({
|
||||||
tagName: 'dd',
|
tagName: 'dd',
|
||||||
|
|
||||||
openChat: function () {
|
events: {
|
||||||
xmppchat.chatboxesview.openChat(this.model.get('jid'));
|
"click .accept-xmpp-request": "acceptRequest",
|
||||||
|
"click .decline-xmpp-request": "declineRequest",
|
||||||
|
"click .open-chat": "openChat",
|
||||||
|
"click .remove-xmpp-contact": "removeContact"
|
||||||
},
|
},
|
||||||
|
|
||||||
removeContact: function () {
|
openChat: function (ev) {
|
||||||
|
xmppchat.chatboxesview.openChat(this.model.get('jid'));
|
||||||
|
ev.preventDefault();
|
||||||
|
},
|
||||||
|
|
||||||
|
removeContact: function (ev) {
|
||||||
var that = this;
|
var that = this;
|
||||||
$("<span></span>").dialog({
|
$("<span></span>").dialog({
|
||||||
title: 'Are you sure you want to remove this contact?',
|
title: 'Are you sure you want to remove this contact?',
|
||||||
@ -1247,7 +1259,12 @@
|
|||||||
$(this).dialog( "close" );
|
$(this).dialog( "close" );
|
||||||
xmppchat.connection.roster.remove(bare_jid, function (iq) {
|
xmppchat.connection.roster.remove(bare_jid, function (iq) {
|
||||||
xmppchat.connection.roster.unauthorize(bare_jid);
|
xmppchat.connection.roster.unauthorize(bare_jid);
|
||||||
xmppchat.chatboxesview.controlbox.roster.remove(bare_jid);
|
// TODO inspect if chatboxes ever receives controlbox
|
||||||
|
if (xmppchat.chatboxesview.controlbox) {
|
||||||
|
xmppchat.chatboxesview.controlbox.roster.remove(bare_jid);
|
||||||
|
}
|
||||||
|
// remove model from view roster
|
||||||
|
xmppchat.rosterview.model.remove(bare_jid);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
"Cancel": function() {
|
"Cancel": function() {
|
||||||
@ -1255,20 +1272,23 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
ev.preventDefault();
|
||||||
},
|
},
|
||||||
|
|
||||||
acceptRequest: function () {
|
acceptRequest: function (ev) {
|
||||||
var jid = this.model.get('jid');
|
var jid = this.model.get('jid');
|
||||||
xmppchat.connection.roster.authorize(jid);
|
xmppchat.connection.roster.authorize(jid);
|
||||||
xmppchat.connection.roster.add(jid, this.model.get('fullname'), [], function (iq) {
|
xmppchat.connection.roster.add(jid, this.model.get('fullname'), [], function (iq) {
|
||||||
xmppchat.connection.roster.subscribe(jid);
|
xmppchat.connection.roster.subscribe(jid);
|
||||||
});
|
});
|
||||||
|
ev.preventDefault();
|
||||||
},
|
},
|
||||||
|
|
||||||
declineRequest: function () {
|
declineRequest: function (ev) {
|
||||||
var that = this;
|
var that = this;
|
||||||
xmppchat.connection.roster.unauthorize(this.model.get('jid'));
|
xmppchat.connection.roster.unauthorize(this.model.get('jid'));
|
||||||
that.trigger('decline-request', that.model);
|
that.trigger('decline-request', that.model);
|
||||||
|
ev.preventDefault();
|
||||||
},
|
},
|
||||||
|
|
||||||
template: _.template(
|
template: _.template(
|
||||||
@ -1299,29 +1319,12 @@
|
|||||||
} else if (ask === 'request') {
|
} else if (ask === 'request') {
|
||||||
this.$el.addClass('requesting-xmpp-contact');
|
this.$el.addClass('requesting-xmpp-contact');
|
||||||
this.$el.html(this.request_template(item.toJSON()));
|
this.$el.html(this.request_template(item.toJSON()));
|
||||||
this.$el.delegate('button.accept-xmpp-request', 'click', function (ev) {
|
|
||||||
ev.preventDefault();
|
|
||||||
that.acceptRequest();
|
|
||||||
});
|
|
||||||
this.$el.delegate('button.decline-xmpp-request', 'click', function (ev) {
|
|
||||||
ev.preventDefault();
|
|
||||||
that.declineRequest();
|
|
||||||
});
|
|
||||||
xmppchat.chatboxesview.openChat('controlbox');
|
xmppchat.chatboxesview.openChat('controlbox');
|
||||||
} else if (subscription === 'both') {
|
} else if (subscription === 'both' || subscription === 'to') {
|
||||||
this.$el.addClass('current-xmpp-contact');
|
this.$el.addClass('current-xmpp-contact');
|
||||||
this.$el.html(this.template(item.toJSON()));
|
this.$el.html(this.template(item.toJSON()));
|
||||||
this.$el.delegate('a.open-chat', 'click', function (ev) {
|
|
||||||
ev.preventDefault();
|
|
||||||
that.openChat();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event handlers
|
|
||||||
this.$el.delegate('a.remove-xmpp-contact','click', function (ev) {
|
|
||||||
ev.preventDefault();
|
|
||||||
that.removeContact();
|
|
||||||
});
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1388,8 +1391,9 @@
|
|||||||
return Backbone.Collection.prototype.get.call(this, id);
|
return Backbone.Collection.prototype.get.call(this, id);
|
||||||
},
|
},
|
||||||
|
|
||||||
addRosterItem: function (jid, subscription, ask, name) {
|
addRosterItem: function (jid, subscription, ask, name, options) {
|
||||||
var model = new xmppchat.RosterItem(jid, subscription, ask, name);
|
var model = new xmppchat.RosterItem(jid, subscription, ask, name);
|
||||||
|
model.options = options || {};
|
||||||
this.add(model);
|
this.add(model);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1437,6 +1441,7 @@
|
|||||||
if (item) {
|
if (item) {
|
||||||
return _.size(item.get('resources'));
|
return _.size(item.get('resources'));
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
getNumOnlineContacts: function () {
|
getNumOnlineContacts: function () {
|
||||||
@ -1450,14 +1455,23 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
rosterHandler: function (items) {
|
rosterHandler: function (items) {
|
||||||
var model, item;
|
var model, item, i, items_length = items.length,
|
||||||
for (var i=0; i<items.length; i++) {
|
last_item = items[items_length - 1],
|
||||||
|
options = {};
|
||||||
|
for (i=0; i<items_length; i+=1) {
|
||||||
item = items[i];
|
item = items[i];
|
||||||
model = this.getItem(item.jid);
|
model = this.getItem(item.jid);
|
||||||
if (!model) {
|
if (!model) {
|
||||||
this.addRosterItem(item.jid, item.subscription, item.ask, item.name);
|
if (item === last_item) {
|
||||||
|
options.isLast = true;
|
||||||
|
}
|
||||||
|
this.addRosterItem(item.jid, item.subscription, item.ask, item.name, options);
|
||||||
} else {
|
} else {
|
||||||
model.set({'subscription': item.subscription, 'ask': item.ask});
|
// only modify model attributes if they are different from the
|
||||||
|
// ones that were already set when the rosterItem was added
|
||||||
|
if (model.get('subscription') !== item.subscription || model.get('ask') !== item.ask) {
|
||||||
|
model.set({'subscription': item.subscription, 'ask': item.ask});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1580,38 +1594,40 @@
|
|||||||
this.model.remove(item.id);
|
this.model.remove(item.id);
|
||||||
}, this);
|
}, this);
|
||||||
}
|
}
|
||||||
this.render();
|
this.render(item);
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
this.model.on('change', function (item) {
|
this.model.on('change', function (item) {
|
||||||
this.render();
|
this.render(item);
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
this.model.on("remove", function (item) {
|
this.model.on("remove", function (item) {
|
||||||
|
// remove element from the rosterView instance
|
||||||
|
this.rosteritemviews[item.id].$el.remove();
|
||||||
|
|
||||||
delete this.rosteritemviews[item.id];
|
delete this.rosteritemviews[item.id];
|
||||||
this.render();
|
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
|
this.$el.hide();
|
||||||
|
this.$el.html(this.template());
|
||||||
},
|
},
|
||||||
|
|
||||||
template: _.template('<dt id="xmpp-contact-requests">Contact requests</dt>' +
|
template: _.template('<dt id="xmpp-contact-requests">Contact requests</dt>' +
|
||||||
'<dt id="xmpp-contacts">My contacts</dt>' +
|
'<dt id="xmpp-contacts">My contacts</dt>' +
|
||||||
'<dt id="pending-xmpp-contacts">Pending contacts</dt>'),
|
'<dt id="pending-xmpp-contacts">Pending contacts</dt>'),
|
||||||
|
|
||||||
render: function () {
|
render: function (item) {
|
||||||
this.$el.empty().html(this.template());
|
if (!item) {
|
||||||
var models = this.model.sort().models,
|
return this;
|
||||||
children = this.$el.children(),
|
}
|
||||||
$my_contacts = this.$el.find('#xmpp-contacts').hide(),
|
var $my_contacts = this.$el.find('#xmpp-contacts'),
|
||||||
$contact_requests = this.$el.find('#xmpp-contact-requests').hide(),
|
$contact_requests = this.$el.find('#xmpp-contact-requests'),
|
||||||
$pending_contacts = this.$el.find('#pending-xmpp-contacts').hide(),
|
$pending_contacts = this.$el.find('#pending-xmpp-contacts'),
|
||||||
$count, num;
|
$count, num, presence_change;
|
||||||
|
var user_id = Strophe.getNodeFromJid(item.id),
|
||||||
for (var i=0; i<models.length; i++) {
|
view = this.rosteritemviews[item.id],
|
||||||
var model = models[i],
|
ask = item.get('ask'),
|
||||||
user_id = Strophe.getNodeFromJid(model.id),
|
subscription = item.get('subscription'),
|
||||||
view = this.rosteritemviews[model.id],
|
|
||||||
ask = model.get('ask'),
|
|
||||||
subscription = model.get('subscription'),
|
|
||||||
crit = {order:'asc'};
|
crit = {order:'asc'};
|
||||||
|
|
||||||
if (ask === 'subscribe') {
|
if (ask === 'subscribe') {
|
||||||
@ -1620,20 +1636,46 @@
|
|||||||
} else if (ask === 'request') {
|
} else if (ask === 'request') {
|
||||||
$contact_requests.after(view.render().el);
|
$contact_requests.after(view.render().el);
|
||||||
$contact_requests.after($contact_requests.siblings('dd.requesting-xmpp-contact').tsort(crit));
|
$contact_requests.after($contact_requests.siblings('dd.requesting-xmpp-contact').tsort(crit));
|
||||||
} else if (subscription === 'both') {
|
} else if (subscription === 'both' || subscription === 'to') {
|
||||||
$my_contacts.after(view.render().el);
|
if (!item.options.sorted) {
|
||||||
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.offline').tsort('a', crit));
|
// this attribute will be true only after all of the elements have been added on the page
|
||||||
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.unavailable').tsort('a', crit));
|
// at this point all offline
|
||||||
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.away').tsort('a', crit));
|
$my_contacts.after(view.render().el);
|
||||||
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.busy').tsort('a', crit));
|
}
|
||||||
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.online').tsort('a', crit));
|
else {
|
||||||
|
// just by calling render will be enough to change the icon of the existing item without
|
||||||
|
// having to reinsert it and the sort will come from the presence change
|
||||||
|
view.render();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
presence_change = view.model.changed['presence_type'];
|
||||||
|
if (presence_change) {
|
||||||
|
// resort all items only if the model has changed it's presence_type as this render
|
||||||
|
// is also triggered when the resource is changed which always comes before the presence change
|
||||||
|
// therefore we avoid resorting when the change doesn't affect the position of the item
|
||||||
|
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.offline').tsort('a', crit));
|
||||||
|
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.unavailable').tsort('a', crit));
|
||||||
|
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.away').tsort('a', crit));
|
||||||
|
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.busy').tsort('a', crit));
|
||||||
|
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.online').tsort('a', crit));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.options.isLast && !item.options.sorted) {
|
||||||
|
// this will be true after all of the roster items have been added with the default
|
||||||
|
// options where all of the items are offline and now we can show the rosterView
|
||||||
|
item.options.sorted = true;
|
||||||
|
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.offline').tsort('a', crit));
|
||||||
|
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.unavailable').tsort('a', crit));
|
||||||
|
this.$el.show();
|
||||||
}
|
}
|
||||||
// Hide the headings if there are no contacts under them
|
// Hide the headings if there are no contacts under them
|
||||||
_.each([$my_contacts, $contact_requests, $pending_contacts], function (h) {
|
_.each([$my_contacts, $contact_requests, $pending_contacts], function (h) {
|
||||||
if (h.nextUntil('dt').length > 0) {
|
if (h.nextUntil('dt').length) {
|
||||||
h.show();
|
h.show();
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
h.hide();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
$count = $('#online-count');
|
$count = $('#online-count');
|
||||||
$count.text(this.model.getNumOnlineContacts());
|
$count.text(this.model.getNumOnlineContacts());
|
||||||
@ -1824,7 +1866,7 @@
|
|||||||
|
|
||||||
$(document).unbind('jarnxmpp.connected');
|
$(document).unbind('jarnxmpp.connected');
|
||||||
$(document).bind('jarnxmpp.connected', $.proxy(function (ev, connection) {
|
$(document).bind('jarnxmpp.connected', $.proxy(function (ev, connection) {
|
||||||
this.connection = connection
|
this.connection = connection;
|
||||||
// this.connection.xmlInput = function (body) { console.log(body); };
|
// this.connection.xmlInput = function (body) { console.log(body); };
|
||||||
// this.connection.xmlOutput = function (body) { console.log(body); };
|
// this.connection.xmlOutput = function (body) { console.log(body); };
|
||||||
this.connection.bare_jid = Strophe.getBareJidFromJid(this.connection.jid);
|
this.connection.bare_jid = Strophe.getBareJidFromJid(this.connection.jid);
|
||||||
@ -1883,4 +1925,3 @@
|
|||||||
|
|
||||||
return xmppchat;
|
return xmppchat;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -31,12 +31,12 @@
|
|||||||
xmppchat.rosterview = new xmppchat.RosterView({'model':xmppchat.roster});
|
xmppchat.rosterview = new xmppchat.RosterView({'model':xmppchat.roster});
|
||||||
// stub
|
// stub
|
||||||
xmppchat.chatboxesview = {openChat: function () {} };
|
xmppchat.chatboxesview = {openChat: function () {} };
|
||||||
// Hack to make sure there is an element.
|
|
||||||
xmppchat.rosterview.$el = $('<dl id="xmppchat-roster"></dl>');
|
|
||||||
xmppchat.rosterview.render();
|
xmppchat.rosterview.render();
|
||||||
|
|
||||||
|
// by default the dts are hidden from css class and only later they will be hidden
|
||||||
|
// by jQuery therefore for the first check we will see if visible instead of none
|
||||||
it("should hide the requesting contacts heading if there aren't any", function () {
|
it("should hide the requesting contacts heading if there aren't any", function () {
|
||||||
expect(xmppchat.rosterview.$el.find('dt#xmpp-contact-requests').css('display')).toEqual('none');
|
expect(xmppchat.rosterview.$el.find('dt#xmpp-contact-requests').is(':visible')).toEqual(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be able to add requesting contacts, and they should be sorted alphabetically", function () {
|
it("should be able to add requesting contacts, and they should be sorted alphabetically", function () {
|
||||||
|
Loading…
Reference in New Issue
Block a user