Anton Shestakov <av6@dwimlabs.net>, Thu, 07 Apr 2016 22:56:16 +0800
index: check if roster has the item before removing it
Sometimes we get events from contacts that are not in user's roster, trying to
remove such contacts used to fail before this patch.
js/contacts.js
Permissions: -rw-r--r--
// Generated by CoffeeScript 1.10.0 var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; Tram.Contact = (function(superClass) { extend(Contact, superClass); return Contact.__super__.constructor.apply(this, arguments); Contact.prototype.idAttribute = 'jid'; Contact.prototype.optimizeSide = 96; Contact.prototype.optimizeThreshold = 10000; Contact.prototype.defaults = { Contact.prototype.initialize = function() { this.on('add change:avatar', this.optimizeAvatar); this.on('add change:fullname change:nickname change:bjid', function() { return this.set('d/handle', this.get('fullname') || this.get('nickname') || this.get('bjid')); return this.on('add change:type change:presence change:callstate', function() { if (this.get('type') === 'self') { return this.unset('d/actions'); if (this.get('presence') === 'subscribe') { return this.set('d/actions', ['authorize', 'unauthorize']); if (this.get('presence') !== 'unavailable') { switch (this.get('callstate')) { actions.push('wait', 'hang-up'); actions.push('accept', 'decline'); return this.set('d/actions', actions); Contact.prototype.optimizeAvatar = function() { avatar = this.get('avatar'); if (!((avatar != null ? avatar.mime : void 0) && (avatar != null ? avatar.data : void 0))) { return this.unset('avatar/url'); data = "data:" + avatar.mime + ";base64," + avatar.data; if (data.length < this.optimizeThreshold) { return this.set('avatar/url', data); img.addEventListener('load', (function(_this) { var canvas, ctx, mime, optimized, ratio; if (img.width < _this.optimizeSide && img.height < _this.optimizeSide) { return _this.set('avatar/url', data); ratio = Math.min(_this.optimizeSide / img.width, _this.optimizeSide / img.height); canvas = document.createElement('canvas'); canvas.height = Math.round(img.height * ratio); canvas.width = Math.round(img.width * ratio); ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0, canvas.width, canvas.height); if (avatar.mime === 'image/jpeg') { optimized = canvas.toDataURL(mime); if (img.src.length < optimized.length) { return _this.set('avatar/url', data); return _this.set('avatar/url', optimized); Tram.Contacts = (function(superClass) { extend(Contacts, superClass); return Contacts.__super__.constructor.apply(this, arguments); Contacts.prototype.model = Tram.Contact; Contacts.prototype.comparator = function(model) { if (model.get('presence') === 'unavailable') { } else if (model.get('presence') === 'subscribe') { } else if (model.get('type') === 'self') { Contacts.prototype.initialize = function() { return this.on('change:presence change:type', this.sort); Tram.AvatarView = (function(superClass) { extend(AvatarView, superClass); this.getColors = bind(this.getColors, this); return AvatarView.__super__.constructor.apply(this, arguments); AvatarView.prototype.tagName = 'div'; AvatarView.prototype.className = 'vignette'; AvatarView.prototype.template = $('#avatar-template').html(); AvatarView.prototype.colors = Tram.colors.avatar; AvatarView.prototype.getColors = function(hash) { ci = hash % this.colors.length; return "color: white; background: " + this.colors[ci] + ";"; AvatarView.prototype.render = function() { this.$el.html(this.template); this.rivet = rivets.bind(this.el, { AvatarView.prototype.remove = function() { return AvatarView.__super__.remove.apply(this, arguments); Tram.ContactView = (function(superClass) { extend(ContactView, superClass); this.getPipColor = bind(this.getPipColor, this); return ContactView.__super__.constructor.apply(this, arguments); ContactView.prototype.tagName = 'li'; ContactView.prototype.className = 'contact'; ContactView.prototype.template = $('#contact-template').html(); ContactView.prototype.colors = Tram.colors.show; ContactView.prototype.events = { 'click [data-chat]': function() { return this.model.trigger('action/chat'); 'click [data-authorize]': function() { return this.model.trigger('action/authorize'); 'click [data-unauthorize]': function() { return this.model.trigger('action/unauthorize'); 'click [data-call]': function(event) { return this.model.trigger('action/call', event.currentTarget.getAttribute('data-call')); 'click [data-accept]': function(event) { return this.model.trigger('action/accept', event.currentTarget.getAttribute('data-accept')); 'click [data-decline]': function() { return this.model.trigger('action/decline'); 'click [data-hang-up]': function() { return this.model.trigger('action/hangup'); 'click [data-remove]': function() { return this.model.trigger('action/remove'); ContactView.prototype.initialize = function() { this.$el.attr('data-jid', this.model.get('jid')); this.$el.html(this.template); this.$avatarColumn = this.$('.avatar-column'); ContactView.prototype.bind = function() {}; ContactView.prototype.getPipColor = function(show) { return "background: " + (this.colors[show] || this.colors['default']) + ";"; ContactView.prototype.render = function() { this.rivet = rivets.bind(this.el, { av = new Tram.AvatarView({ this.$avatarColumn.prepend(av.render().el); ContactView.prototype.remove = function() { return ContactView.__super__.remove.apply(this, arguments); Tram.ContactsApp = (function(superClass) { extend(ContactsApp, superClass); return ContactsApp.__super__.constructor.apply(this, arguments); ContactsApp.prototype.initialize = function() { this.listenTo(this.collection, 'add', this.onAdd); this.listenTo(this.collection, 'remove', this.onRemove); return this.listenTo(this.collection, 'sort', this.onSort); ContactsApp.prototype.onAdd = function(model, collection) { mi = collection.indexOf(model); model.view = new Tram.ContactView({ el = model.view.render().el; return this.$el.prepend(el); return this.$el.children().eq(mi - 1).after(el); ContactsApp.prototype.onRemove = function(model) { return (ref = model.view) != null ? ref.remove() : void 0; ContactsApp.prototype.onSort = function(collection, options) { return collection.each((function(_this) { return _this.$el.append(model.view.el); //# sourceMappingURL=contacts.js.map