Commit 60f433d1 authored by JC Brand's avatar JC Brand

Initial work on managing a room's member's list.

parent 8b286a1a
......@@ -202,6 +202,8 @@
this.occupantsview.chatroomview = this;
this.render().$el.hide();
this.occupantsview.model.fetch({add:true});
_.each(['member', 'owner', 'admin'], this.fetchMembersList.bind(this));
this.join(null, {'maxstanzas': converse.muc_history_max_stanzas});
this.fetchMessages().insertIntoDOM();
// XXX: adding the event below to the events map above doesn't work.
......@@ -254,6 +256,54 @@
converse.ChatBoxView.prototype.close.apply(this, arguments);
},
updateMembersList: function () {
/* Update the room's member-lists by sending a delta of
* changed memberships (for all affiliations).
*/
var iq = $iq({'to':this.model.get('jid'), 'type':'set', 'from':converse.connection.jid})
.c("query", {'xmlns': Strophe.NS.MUC_ADMIN});
this.occupantsview.model.each(function (occupant) {
var affiliation = occupant.get('affiliation');
iq.c('item', {
'affiliation': affiliation !== 'none' ? affiliation : 'member',
'jid': Strophe.getBareJidFromJid(occupant.get('jid'))
});
});
return converse.connection.sendIQ(
iq.tree(),
this.onMembersListChanged.bind(this),
this.onMembersListChangedError.bind(this)
);
},
fetchMembersList: function (affiliation) {
/* Fetch the member-list for a particular affiliation.
*
* Unfortunately it doesn't seem to work when trying to
* fetch a list for all affiliations, so we need to fetch
* them one by one.
*/
var iq = $iq({
'to': this.model.get('jid'),
'type': "get",
'from': converse.connection.jid
}).c("query", {'xmlns': Strophe.NS.MUC_ADMIN})
.c("item", {'affiliation': affiliation});
return converse.connection.sendIQ(
iq.tree(),
this.occupantsview.updateOccupantsOnMembersList.bind(this.occupantsview),
_.bind(this.onMembersListError, this, affiliation)
);
},
onMembersListError: function (affiliation, iq) {
if (iq.getElementsByTagName('forbidden').length) {
converse.log("You are forbidden from retrieving the "+affiliation+"-list for "+this.model.get('jid'));
} else {
converse.log("Could not retrieve "+affiliation+"-list for "+this.model.get('jid'), "error");
}
},
toggleOccupants: function (ev, preserve_state) {
if (ev) {
ev.preventDefault();
......@@ -617,7 +667,15 @@
},
onConfigSaved: function (stanza) {
// TODO: provide feedback
// this.updateMembersList();
},
onMembersListChanged: function (stanza) {
converse.log("The membership-list for "+this.model.get('jid')+" has been succesfully updated");
},
onMembersListChangedError: function (stanza) {
this.showStatusNotification(__("An error occurred while trying to update the members list."));
},
onErrorConfigSaved: function (stanza) {
......@@ -926,25 +984,36 @@
}
});
converse.ChatRoomOccupant = Backbone.Model;
converse.ChatRoomOccupant = Backbone.Model.extend({
initialize: function () {
this.set({'id': converse.connection.getUniqueId()});
}
});
converse.ChatRoomOccupantView = Backbone.View.extend({
tagName: 'li',
initialize: function () {
this.model.on('add', this.render, this);
this.model.on('change', this.render, this);
this.model.on('destroy', this.destroy, this);
},
render: function () {
var $new = converse.templates.occupant(
_.extend(
this.model.toJSON(), {
'desc_moderator': __('This user is a moderator'),
'desc_occupant': __('This user can send messages in this room'),
'desc_visitor': __('This user can NOT send messages in this room')
})
var new_el = converse.templates.occupant(
_.extend({
'nick': this.model.get('jid') || '',
'role': null,
'desc_moderator': __('This user is a moderator'),
'desc_occupant': __('This user can send messages in this room'),
'desc_visitor': __('This user can NOT send messages in this room')
}, this.model.toJSON())
);
this.$el.replaceWith($new);
this.setElement($new, true);
var $parents = this.$el.parents();
if ($parents.length) {
this.$el.replaceWith(new_el);
this.setElement($parents.first().children('#'+this.model.get('id')), true);
this.delegateEvents();
} else {
this.$el.replaceWith(new_el);
this.setElement(new_el, true);
}
return this;
},
......@@ -980,9 +1049,9 @@
},
onOccupantAdded: function (item) {
var view = this.get(item.get('id'));
var view = this.get(item.get('jid'));
if (!view) {
view = this.add(item.get('id'), new converse.ChatRoomOccupantView({model: item}));
view = this.add(item.get('jid'), new converse.ChatRoomOccupantView({model: item}));
} else {
delete view.model; // Remove ref to old model to help garbage collection
view.model = item;
......@@ -994,7 +1063,6 @@
parsePresence: function (pres) {
var id = Strophe.getResourceFromJid(pres.getAttribute("from"));
var data = {
id: id,
nick: id,
type: pres.getAttribute("type"),
states: []
......@@ -1030,25 +1098,70 @@
},
updateOccupantsOnPresence: function (pres) {
var occupant;
var occupant, attributes;
var data = this.parsePresence(pres);
if (data.type === 'error') {
return true;
}
// If we have a JID, we use that to look up the user,
// otherwise we use the nick. We don't always have both,
// but should have at least one or the other.
var jid = Strophe.getBareJidFromJid(data.jid);
if (jid !== null) {
occupant = this.model.where({'jid': jid}).pop();
} else {
occupant = this.model.where({'nick': data.nick}).pop();
}
switch (data.type) {
case 'error':
return true;
case 'unavailable':
occupant = this.model.get(data.id);
if (occupant) { occupant.destroy(); }
if (occupant) {
occupant[0].destroy();
}
break;
default:
occupant = this.model.get(data.id);
attributes = _.extend(data, {
'jid': jid ? jid : undefined,
'resource': data.jid ? Strophe.getResourceFromJid(data.jid) : undefined,
'online': true
});
if (occupant) {
occupant.save(data);
occupant.save(attributes);
} else {
this.model.create(data);
this.model.create(attributes);
}
}
},
updateOccupantsOnMembersList: function (iq) {
/* <iq from='coven@chat.shakespeare.lit'
id='member3'
to='crone1@shakespeare.lit/desktop'
type='result'>
<query xmlns='http://jabber.org/protocol/muc#admin'>
<item affiliation='member'
jid='hag66@shakespeare.lit'
nick='thirdwitch'
role='participant'/>
</query>
</iq>
*/
_.each($(iq).find('query item'), function (item) {
var jid = item.getAttribute('jid');
var occupant = this.model.where({'jid': jid}).pop();
var data = {
'jid': item.getAttribute('jid'),
'affiliation': item.getAttribute('affiliation')
};
if (occupant) {
occupant.save(data);
} else {
this.model.create(data);
}
}.bind(this));
return;
},
initInviteWidget: function () {
var $el = this.$('input.invited-contact');
$el.typeahead({
......
<li class="{{role}}"
<li class="{{role}}" id="{{id}}"
{[ if (role === "moderator") { ]}
title="{{desc_moderator}}"
{[ } ]}
......
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