293:6635f14613ba
Anton Shestakov <av6@dwimlabs.net>, Wed, 01 Nov 2017 00:50:57 +0800
Makefile: use file targets more, results in incremental building Less work to do when only some files get changed, but more work when building from scratch. But, multiple compilers can run in parallel.

next change 324:da4b66c14a44
previous change 279:01439ae590ed

coffee/contacts.coffee

Permissions: -rw-r--r--

Other formats: Feeds:
class Tram.Contact extends Backbone.Model
idAttribute: 'jid'
defaults:
presence: 'unavailable'
show: 'offline'
initialize: ->
@on 'add change:type change:presence change:callstate change:features', ->
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' and Tram.NS.WEBRTC in (@get('features') ? [])
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)
class Tram.Profile extends Backbone.Model
idAttribute: 'bjid'
optimizeSide: 96
optimizeThreshold: 10000
initialize: ->
@on('add change:avatar', @optimizeAvatar)
@on 'add change:fullname change:nickname', ->
@set('d/handle', @get('fullname') or @get('nickname') or @get('bjid'))
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.Profiles extends Backbone.Collection
model: Tram.Profile
class Tram.Entity extends Backbone.Model
defaults:
identities: []
features: []
class Tram.Entities extends Backbone.Collection
model: Tram.Entity
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
templateEl: $($('#avatar-template').html())
colors: Tram.colors.avatar
initialize: ->
@setElement(@templateEl.clone())
getColors: (hash) =>
ci = hash % @colors.length
"color: white; background: #{ @colors[ci] };"
render: ->
@rivet = rivets.bind(@el, contact: @model, view: @)
@
remove: ->
@rivet.unbind()
super
class Tram.ContactView extends Backbone.View
templateEl: $($('#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: ->
@setElement(@templateEl.clone())
@$avatarColumn = @$('.avatar-column')
@bind()
bind: ->
@listenTo(@model, 'remove', @remove)
getBorderColor: (show) =>
"border-left-color: #{ @colors[show] || @colors['default'] };"
getPipColor: (show) =>
"background: #{ @colors[show] || @colors['default'] };"
render: ->
@rivet = rivets.bind(@el, contact: @model, view: @)
@av = new Tram.AvatarView(model: @model)
@$avatarColumn.prepend(@av.render().el)
@
remove: ->
@av.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)