151:0178573216e3
Anton Shestakov <av6@dwimlabs.net>, Thu, 14 Apr 2016 02:05:24 +0800
index: remove offline contacts only when they change to being offline Since new contacts are currently added while they still have the default presence of 'unavailable', add event sees them as offline and throws them away immediately, before their presence could change to something else.

next change 186:92afb94559c4
previous change 143:2afd675fcaa4

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: ->
@listenTo(@model, 'remove', @remove)
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, '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)
onSort: (collection, options) ->
if not options.add
collection.each (model) =>
model.view.$el.detach()
@$el.append(model.view.el)