Found more MUC stuff in core.

Move the Occupants views and models to converse-muc.js as well as some
MUC-specific config variables.
This commit is contained in:
JC Brand 2016-02-19 09:36:01 +00:00
parent 572d896676
commit 147a3c9e3e
3 changed files with 178 additions and 179 deletions

View File

@ -61,27 +61,6 @@
interpolate : /\{\{([\s\S]+?)\}\}/g
};
var contains = function (attr, query) {
return function (item) {
if (typeof attr === 'object') {
var value = false;
_.each(attr, function (a) {
value = value || item.get(a).toLowerCase().indexOf(query.toLowerCase()) !== -1;
});
return value;
} else if (typeof attr === 'string') {
return item.get(attr).toLowerCase().indexOf(query.toLowerCase()) !== -1;
} else {
throw new TypeError('contains: wrong attribute type. Must be string or array.');
}
};
};
contains.not = function (attr, query) {
return function (item) {
return !(contains(attr, query)(item));
};
};
var converse = {
plugins: {},
templates: templates,
@ -284,7 +263,6 @@
// Translation machinery
// ---------------------
var __ = utils.__.bind(this);
var ___ = utils.___;
// Default configuration values
// ----------------------------
@ -311,7 +289,6 @@
domain_placeholder: __(" e.g. conversejs.org"), // Placeholder text shown in the domain input on the registration form
expose_rid_and_sid: false,
forward_messages: false,
hide_muc_server: false,
hide_offline_users: false,
include_offline_state: false,
jid: undefined,
@ -319,7 +296,6 @@
locked_domain: undefined,
message_archiving: 'never', // Supported values are 'always', 'never', 'roster' (See https://xmpp.org/extensions/xep-0313.html#prefs )
message_carbons: false, // Support for XEP-280
muc_history_max_stanzas: undefined, // Takes an integer, limits the amount of messages to fetch from chat room's history
no_trimming: false, // Set to true for phantomjs tests (where browser apparently has no width)
password: undefined,
ping_interval: 180, //in seconds
@ -2156,158 +2132,6 @@
}
});
this.ChatRoomOccupant = Backbone.Model;
this.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')
})
);
this.$el.replaceWith($new);
this.setElement($new, true);
return this;
},
destroy: function () {
this.$el.remove();
}
});
this.ChatRoomOccupants = Backbone.Collection.extend({
model: converse.ChatRoomOccupant
});
this.ChatRoomOccupantsView = Backbone.Overview.extend({
tagName: 'div',
className: 'occupants',
initialize: function () {
this.model.on("add", this.onOccupantAdded, this);
},
render: function () {
this.$el.html(
converse.templates.chatroom_sidebar({
'label_invitation': __('Invite...'),
'label_occupants': __('Occupants')
})
);
return this.initInviteWidget();
},
onOccupantAdded: function (item) {
var view = this.get(item.get('id'));
if (!view) {
view = this.add(item.get('id'), new converse.ChatRoomOccupantView({model: item}));
} else {
delete view.model; // Remove ref to old model to help garbage collection
view.model = item;
view.initialize();
}
this.$('.occupant-list').append(view.render().$el);
},
parsePresence: function (pres) {
var id = Strophe.getResourceFromJid(pres.getAttribute("from"));
var data = {
id: id,
nick: id,
type: pres.getAttribute("type"),
states: []
};
_.each(pres.childNodes, function (child) {
switch (child.nodeName) {
case "status":
data.status = child.textContent || null;
break;
case "show":
data.show = child.textContent || null;
break;
case "x":
if (child.getAttribute("xmlns") === Strophe.NS.MUC_USER) {
_.each(child.childNodes, function (item) {
switch (item.nodeName) {
case "item":
data.affiliation = item.getAttribute("affiliation");
data.role = item.getAttribute("role");
data.jid = item.getAttribute("jid");
data.nick = item.getAttribute("nick") || data.nick;
break;
case "status":
if (item.getAttribute("code")) {
data.states.push(item.getAttribute("code"));
}
}
});
}
}
});
return data;
},
updateOccupantsOnPresence: function (pres) {
var occupant;
var data = this.parsePresence(pres);
switch (data.type) {
case 'error':
return true;
case 'unavailable':
occupant = this.model.get(data.id);
if (occupant) { occupant.destroy(); }
break;
default:
occupant = this.model.get(data.id);
if (occupant) {
occupant.save(data);
} else {
this.model.create(data);
}
}
},
initInviteWidget: function () {
var $el = this.$('input.invited-contact');
$el.typeahead({
minLength: 1,
highlight: true
}, {
name: 'contacts-dataset',
source: function (q, cb) {
var results = [];
_.each(converse.roster.filter(contains(['fullname', 'jid'], q)), function (n) {
results.push({value: n.get('fullname'), jid: n.get('jid')});
});
cb(results);
},
templates: {
suggestion: _.template('<p data-jid="{{jid}}">{{value}}</p>')
}
});
$el.on('typeahead:selected', function (ev, suggestion, dname) {
var reason = prompt(
__(___('You are about to invite %1$s to the chat room "%2$s". '), suggestion.value, this.model.get('id')) +
__("You may optionally include a message, explaining the reason for the invitation.")
);
if (reason !== null) {
this.chatroomview.directInvite(suggestion.jid, reason);
}
$(ev.target).typeahead('val', '');
}.bind(this));
return this;
}
});
this.ChatBoxes = Backbone.Collection.extend({
model: converse.ChatBox,
comparator: 'time_opened',
@ -3451,14 +3275,14 @@
this.showIfNecessary();
} else {
q = q.toLowerCase();
matches = this.model.contacts.filter(contains.not('fullname', q));
matches = this.model.contacts.filter(utils.contains.not('fullname', q));
if (matches.length === this.model.contacts.length) { // hide the whole group
this.hide();
} else {
_.each(matches, function (item) {
this.get(item.get('id')).$el.hide();
}.bind(this));
_.each(this.model.contacts.reject(contains.not('fullname', q)), function (item) {
_.each(this.model.contacts.reject(utils.contains.not('fullname', q)), function (item) {
this.get(item.get('id')).$el.show();
}.bind(this));
this.showIfNecessary();

View File

@ -199,7 +199,9 @@
// Configuration values for this plugin
var settings = {
allow_muc: true,
auto_join_on_invite: false // Auto-join chatroom on invite
auto_join_on_invite: false, // Auto-join chatroom on invite
hide_muc_server: false,
muc_history_max_stanzas: undefined, // Takes an integer, limits the amount of messages to fetch from chat room's history
};
_.extend(converse, settings);
_.extend(converse, _.pick(converse.user_settings, Object.keys(settings)));
@ -943,6 +945,157 @@
}
});
converse.ChatRoomOccupant = Backbone.Model;
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')
})
);
this.$el.replaceWith($new);
this.setElement($new, true);
return this;
},
destroy: function () {
this.$el.remove();
}
});
converse.ChatRoomOccupants = Backbone.Collection.extend({
model: converse.ChatRoomOccupant
});
converse.ChatRoomOccupantsView = Backbone.Overview.extend({
tagName: 'div',
className: 'occupants',
initialize: function () {
this.model.on("add", this.onOccupantAdded, this);
},
render: function () {
this.$el.html(
converse.templates.chatroom_sidebar({
'label_invitation': __('Invite...'),
'label_occupants': __('Occupants')
})
);
return this.initInviteWidget();
},
onOccupantAdded: function (item) {
var view = this.get(item.get('id'));
if (!view) {
view = this.add(item.get('id'), new converse.ChatRoomOccupantView({model: item}));
} else {
delete view.model; // Remove ref to old model to help garbage collection
view.model = item;
view.initialize();
}
this.$('.occupant-list').append(view.render().$el);
},
parsePresence: function (pres) {
var id = Strophe.getResourceFromJid(pres.getAttribute("from"));
var data = {
id: id,
nick: id,
type: pres.getAttribute("type"),
states: []
};
_.each(pres.childNodes, function (child) {
switch (child.nodeName) {
case "status":
data.status = child.textContent || null;
break;
case "show":
data.show = child.textContent || null;
break;
case "x":
if (child.getAttribute("xmlns") === Strophe.NS.MUC_USER) {
_.each(child.childNodes, function (item) {
switch (item.nodeName) {
case "item":
data.affiliation = item.getAttribute("affiliation");
data.role = item.getAttribute("role");
data.jid = item.getAttribute("jid");
data.nick = item.getAttribute("nick") || data.nick;
break;
case "status":
if (item.getAttribute("code")) {
data.states.push(item.getAttribute("code"));
}
}
});
}
}
});
return data;
},
updateOccupantsOnPresence: function (pres) {
var occupant;
var data = this.parsePresence(pres);
switch (data.type) {
case 'error':
return true;
case 'unavailable':
occupant = this.model.get(data.id);
if (occupant) { occupant.destroy(); }
break;
default:
occupant = this.model.get(data.id);
if (occupant) {
occupant.save(data);
} else {
this.model.create(data);
}
}
},
initInviteWidget: function () {
var $el = this.$('input.invited-contact');
$el.typeahead({
minLength: 1,
highlight: true
}, {
name: 'contacts-dataset',
source: function (q, cb) {
var results = [];
_.each(converse.roster.filter(utils.contains(['fullname', 'jid'], q)), function (n) {
results.push({value: n.get('fullname'), jid: n.get('jid')});
});
cb(results);
},
templates: {
suggestion: _.template('<p data-jid="{{jid}}">{{value}}</p>')
}
});
$el.on('typeahead:selected', function (ev, suggestion, dname) {
var reason = prompt(
__(___('You are about to invite %1$s to the chat room "%2$s". '), suggestion.value, this.model.get('id')) +
__("You may optionally include a message, explaining the reason for the invitation.")
);
if (reason !== null) {
this.chatroomview.directInvite(suggestion.jid, reason);
}
$(ev.target).typeahead('val', '');
}.bind(this));
return this;
}
});
converse.RoomsPanel = Backbone.View.extend({
/* Backbone View which renders the "Rooms" tab and accompanying
* panel in the control box.

View File

@ -146,6 +146,22 @@
}))[0];
},
contains: function (attr, query) {
return function (item) {
if (typeof attr === 'object') {
var value = false;
_.each(attr, function (a) {
value = value || item.get(a).toLowerCase().indexOf(query.toLowerCase()) !== -1;
});
return value;
} else if (typeof attr === 'string') {
return item.get(attr).toLowerCase().indexOf(query.toLowerCase()) !== -1;
} else {
throw new TypeError('contains: wrong attribute type. Must be string or array.');
}
};
},
xForm2webForm: function ($field, $stanza) {
/* Takes a field in XMPP XForm (XEP-004: Data Forms) format
* and turns it into a HTML DOM field.
@ -233,5 +249,11 @@
}
}
};
utils.contains.not = function (attr, query) {
return function (item) {
return !(utils.contains(attr, query)(item));
};
};
return utils;
}));