112:f4a4878c99a3
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.

next change 143:2afd675fcaa4
previous change 111:b2e3a00a9691

coffee/contacts.coffee

Permissions: -rw-r--r--

Other formats: Feeds:
class Tram.Contact extends Backbone.Model
idAttribute: 'jid'
optimizeSide: 96
optimizeThreshold: 10000
defaults:
presence: 'unavailable'
show: 'offline'
initialize: ->
@on('add change:avatar', @optimizeAvatar)
@on 'add change:fullname change:nickname change:bjid', ->
@set('d/handle', @get('fullname') or @get('nickname') or @get('bjid'))
@on 'add change:type change:presence change:callstate', ->
if @get('type') is 'self' then return @unset('d/actions')
if @get('presence') is 'subscribe' then return @set('d/actions', ['authorize', 'unauthorize'])
actions = ['remove']
if @get('presence') isnt 'unavailable'
switch @get 'callstate'
when 'established'
actions.push('hang-up')
when 'outgoing'
actions.push('wait', 'hang-up')
when 'incoming'
actions.push('accept', 'decline')
else
actions.push('call')
@set('d/actions', actions)
optimizeAvatar: ->
avatar = @get('avatar')
if not (avatar?.mime and avatar?.data)
return @unset('avatar/url')
data = "data:#{ avatar.mime };base64,#{ avatar.data }"
if data.length < @optimizeThreshold
return @set('avatar/url', data)
img = new Image()
img.addEventListener 'load', =>
if img.width < @optimizeSide and img.height < @optimizeSide
return @set('avatar/url', data)
ratio = Math.min(@optimizeSide / img.width, @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)
mime = 'image/png'
if avatar.mime is 'image/jpeg'
mime = avatar.mime
optimized = canvas.toDataURL(mime)
if img.src.length < optimized.length
@set('avatar/url', data)
else
@set('avatar/url', optimized)
img.src = data
class Tram.Contacts extends Backbone.Collection
model: Tram.Contact
comparator: (model) ->
if model.get('presence') is 'unavailable'
return 2
else if model.get('presence') is 'subscribe'
return 1
else if model.get('type') is 'self'
return -1
else
return 0
initialize: ->
@on('change:presence change:type', @sort)
class Tram.AvatarView extends Backbone.View
tagName: 'div'
className: 'vignette'
template: $('#avatar-template').html()
colors: Tram.colors.avatar
getColors: (hash) =>
ci = hash % @colors.length
"color: white; background: #{ @colors[ci] };"
render: ->
@$el.html(@template)
@rivet = rivets.bind(@el, model: @model, view: this)
@
remove: ->
@rivet.unbind()
super
class Tram.ContactView extends Backbone.View
tagName: 'li'
className: 'contact'
template: $('#contact-template').html()
colors: Tram.colors.show
events:
'click [data-chat]': -> @model.trigger('action/chat')
'click [data-authorize]': -> @model.trigger('action/authorize')
'click [data-unauthorize]': -> @model.trigger('action/unauthorize')
'click [data-call]': (event) -> @model.trigger('action/call', event.currentTarget.getAttribute('data-call'))
'click [data-accept]': (event) -> @model.trigger('action/accept', event.currentTarget.getAttribute('data-accept'))
'click [data-decline]': -> @model.trigger('action/decline')
'click [data-hang-up]': -> @model.trigger('action/hangup')
'click [data-remove]': -> @model.trigger('action/remove')
initialize: ->
@$el.attr('data-jid', @model.get('jid'))
@$el.html(@template)
@$avatarColumn = @$('.avatar-column')
@bind()
bind: ->
getPipColor: (show) =>
"background: #{ @colors[show] || @colors['default'] };"
render: ->
@rivet = rivets.bind(@el, model: @model, view: this)
av = new Tram.AvatarView(model: @model)
@$avatarColumn.prepend(av.render().el)
@
remove: ->
@rivet.unbind()
super
class Tram.ContactsApp extends Backbone.View
initialize: ->
@listenTo(@collection, 'add', @onAdd)
@listenTo(@collection, 'remove', @onRemove)
@listenTo(@collection, 'sort', @onSort)
onAdd: (model, collection) ->
mi = collection.indexOf(model)
model.view = new Tram.ContactView(model: model)
el = model.view.render().el
if mi is 0
@$el.prepend(el)
else
@$el.children().eq(mi - 1).after(el)
onRemove: (model) ->
model.view?.remove()
onSort: (collection, options) ->
if not options.add
collection.each (model) =>
model.view.$el.detach()
@$el.append(model.view.el)