vines 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,48 @@
1
+ class Filter
2
+ constructor: (options) ->
3
+ @list = options.list
4
+ @icon = options.icon
5
+ @form = options.form
6
+ @attrs = options.attrs
7
+ @open = options.open
8
+ @close = options.close
9
+ this.draw()
10
+
11
+ draw: ->
12
+ $(@icon).addClass 'filter-button'
13
+ form = $('<form class="filter-form" style="display:none;"></form>').appendTo @form
14
+ text = $('<input class="filter-text" type="search" placeholder="Filter" results="5"/>').appendTo form
15
+
16
+ new Button @icon, ICONS.search,
17
+ scale: 0.5
18
+ translation: '-8 -8'
19
+
20
+ form.submit -> false
21
+ text.keyup => this.filter(text)
22
+ text.change => this.filter(text)
23
+ text.click => this.filter(text)
24
+ $(@icon).click =>
25
+ if form.is ':hidden'
26
+ this.filter(text)
27
+ form.show()
28
+ this.open() if this.open
29
+ else
30
+ form.hide()
31
+ form[0].reset()
32
+ this.filter(text)
33
+ this.close() if this.close
34
+
35
+ filter: (input) ->
36
+ text = input.val().toLowerCase()
37
+ if text == ''
38
+ $('li', @list).show()
39
+ return
40
+
41
+ test = (node, attr) ->
42
+ val = (node.attr(attr) || '').toLowerCase()
43
+ val.indexOf(text) != -1
44
+
45
+ $('li', @list).each (ix, node) =>
46
+ node = $ node
47
+ matches = (true for attr in @attrs when test node, attr)
48
+ if matches.length > 0 then node.show() else node.hide()
@@ -20,7 +20,7 @@ class Session
20
20
  callback true
21
21
  this.findRoster =>
22
22
  this.notify('roster')
23
- @xmpp.send $pres().tree()
23
+ @xmpp.send $('<presence/>').get 0
24
24
  this.findCards()
25
25
 
26
26
  disconnect: -> @xmpp.disconnect()
@@ -44,6 +44,8 @@ class Session
44
44
 
45
45
  bareJid: -> @xmpp.jid.split('/')[0]
46
46
 
47
+ uniqueId: -> @xmpp.getUniqueId()
48
+
47
49
  avatar: (jid) ->
48
50
  card = this.loadCard(jid)
49
51
  if card && card.photo
@@ -73,8 +75,12 @@ class Session
73
75
 
74
76
  findCard: (jid, callback) ->
75
77
  return unless jid
76
-
77
- handler = (result) ->
78
+ node = this.xml """
79
+ <iq id="#{this.uniqueId()}" to="#{jid}" type="get">
80
+ <vCard xmlns="vcard-temp"/>
81
+ </iq>
82
+ """
83
+ this.sendIQ node, (result) ->
78
84
  card = $('vCard', result)
79
85
  photo = $('PHOTO', card)
80
86
  type = $('TYPE', photo).text()
@@ -86,74 +92,81 @@ class Session
86
92
  vcard = jid: jid, photo: photo, retrieved: new Date()
87
93
  callback if card.size() > 0 then vcard else null
88
94
 
89
- iq = $iq(type: 'get', to: jid, id: @xmpp.getUniqueId())
90
- .c('vCard', xmlns: 'vcard-temp').up()
91
-
92
- @xmpp.sendIQ iq, handler, handler, 5000
93
-
94
95
  parseRoster: (node) ->
95
96
  $('item', node).map(-> new Contact this ).get()
96
97
 
97
98
  findRoster: (callback) ->
98
- handler = (result) =>
99
+ node = $("""
100
+ <iq id='#{this.uniqueId()}' type="get">
101
+ <query xmlns="jabber:iq:roster"/>
102
+ </iq>
103
+ """)
104
+ this.sendIQ node.get(0), (result) =>
99
105
  contacts = this.parseRoster(result)
100
106
  @roster[contact.jid] = contact for contact in contacts
101
107
  callback()
102
108
 
103
- iq = $iq(type: 'get', id: @xmpp.getUniqueId())
104
- .c('query', xmlns: 'jabber:iq:roster').up()
105
-
106
- @xmpp.sendIQ iq, handler, handler, 5000
107
-
108
109
  sendMessage: (jid, message) ->
109
- stanza = $msg(to: jid, from: @xmpp.jid, type: 'chat')
110
- .c('body').t(message).up()
111
- @xmpp.send stanza.tree()
110
+ node = this.xml """
111
+ <message id="#{this.uniqueId()}" to="#{jid}" type="chat">
112
+ <body></body>
113
+ </message>
114
+ """
115
+ $('body', node).text message
116
+ @xmpp.send node
112
117
 
113
118
  sendPresence: (away, status) ->
114
- stanza = $pres()
119
+ node = $ '<presence/>'
115
120
  if away
116
- stanza.c('show').t('xa').up()
117
- stanza.c('status').t status if status != 'Away'
121
+ node.append $('<show>xa</show>')
122
+ node.append $('<status/>').text status if status != 'Away'
118
123
  else
119
- stanza.c('status').t status if status != 'Available'
120
- @xmpp.send stanza.tree()
124
+ node.append $('<status/>').text status if status != 'Available'
125
+ @xmpp.send node.get 0
126
+
127
+ sendIQ: (node, callback) ->
128
+ @xmpp.sendIQ node, callback, callback, 5000
121
129
 
122
130
  updateContact: (contact, add) ->
123
- iq = $iq(type: 'set', id: @xmpp.getUniqueId())
124
- .c('query', xmlns: 'jabber:iq:roster')
125
- .c('item', jid: contact.jid, name: contact.name)
126
- iq.c('group', group).up() for group in contact.groups
127
- @xmpp.send iq.up().tree()
128
- @xmpp.send $pres(type: 'subscribe', to: contact.jid).tree() if add
131
+ node = $("""
132
+ <iq id="#{this.uniqueId()}" type="set">
133
+ <query xmlns="jabber:iq:roster">
134
+ <item name="" jid="#{contact.jid}"/>
135
+ </query>
136
+ </iq>
137
+ """)
138
+ $('item', node).attr 'name', contact.name
139
+ for group in contact.groups
140
+ $('item', node).append $('<group></group>').text group
141
+ @xmpp.send node.get 0
142
+ this.sendSubscribe(contact.jid) if add
129
143
 
130
144
  removeContact: (jid) ->
131
- iq = $iq(type: 'set', id: @xmpp.getUniqueId())
132
- .c('query', xmlns: 'jabber:iq:roster')
133
- .c('item', jid: jid, subscription: 'remove')
134
- .up().up()
135
- @xmpp.send iq.tree()
145
+ node = $("""
146
+ <iq id="#{this.uniqueId()}" type="set">
147
+ <query xmlns="jabber:iq:roster">
148
+ <item jid="#{jid}" subscription="remove"/>
149
+ </query>
150
+ </iq>
151
+ """)
152
+ @xmpp.send node.get 0
136
153
 
137
154
  sendSubscribe: (jid) ->
138
- @xmpp.send $pres(
139
- type: 'subscribe'
140
- to: jid
141
- id: @xmpp.getUniqueId()
142
- ).tree()
155
+ @xmpp.send this.presence jid, 'subscribe'
143
156
 
144
157
  sendSubscribed: (jid) ->
145
- @xmpp.send $pres(
146
- type: 'subscribed'
147
- to: jid
148
- id: @xmpp.getUniqueId()
149
- ).tree()
158
+ @xmpp.send this.presence jid, 'subscribed'
150
159
 
151
160
  sendUnsubscribed: (jid) ->
152
- @xmpp.send $pres(
153
- type: 'unsubscribed'
154
- to: jid
155
- id: @xmpp.getUniqueId()
156
- ).tree()
161
+ @xmpp.send this.presence jid, 'unsubscribed'
162
+
163
+ presence: (to, type) ->
164
+ $("""
165
+ <presence
166
+ id="#{this.uniqueId()}"
167
+ to="#{to}"
168
+ type="#{type}"/>
169
+ """).get 0
157
170
 
158
171
  handleIq: (node) ->
159
172
  node = $(node)
@@ -209,3 +222,5 @@ class Session
209
222
 
210
223
  notify: (type, obj) ->
211
224
  callback(obj) for callback in (@listeners[type] || [])
225
+
226
+ xml: (xml) -> $.parseXML(xml).documentElement
@@ -0,0 +1,103 @@
1
+ class Transfer
2
+ constructor: (options) ->
3
+ @session = options.session
4
+ @file = options.file
5
+ @to = options.to
6
+ @progress = options.progress
7
+ @complete = options.complete
8
+ @chunks = new Chunks(@file)
9
+ @opened = false
10
+ @closed = false
11
+ @sid = @session.uniqueId()
12
+ @seq = 0
13
+ @sent = 0
14
+
15
+ start: ->
16
+ node = $("""
17
+ <iq id="#{@session.uniqueId()}" to="#{@to}" type="set">
18
+ <si xmlns="http://jabber.org/protocol/si" id="#{@session.uniqueId()}" profile="http://jabber.org/protocol/si/profile/file-transfer">
19
+ <file xmlns="http://jabber.org/protocol/si/profile/file-transfer" name="" size="#{@file.size}"/>
20
+ <feature xmlns="http://jabber.org/protocol/feature-neg">
21
+ <x xmlns="jabber:x:data" type="form">
22
+ <field var="stream-method" type="list-single">
23
+ <option><value>http://jabber.org/protocol/ibb</value></option>
24
+ </field>
25
+ </x>
26
+ </feature>
27
+ </si>
28
+ </iq>
29
+ """)
30
+ $('file', node).attr 'name', @file.name
31
+
32
+ callback = (result) =>
33
+ methods = $('si feature x field[var="stream-method"] value', result)
34
+ ok = (true for m in methods when $(m).text() == 'http://jabber.org/protocol/ibb').length > 0
35
+ this.open() if ok
36
+
37
+ @session.sendIQ node.get(0), callback
38
+
39
+ open: ->
40
+ node = $("""
41
+ <iq id="#{@session.uniqueId()}" to="#{@to}" type="set">
42
+ <open xmlns="http://jabber.org/protocol/ibb" sid="#{@sid}" block-size="4096"/>
43
+ </iq>
44
+ """)
45
+ callback = (result) =>
46
+ if this.ok result
47
+ @opened = true
48
+ @chunks.start => this.sendChunk()
49
+ @session.sendIQ node.get(0), callback
50
+
51
+ sendChunk: ->
52
+ return if @closed
53
+ unless chunk = @chunks.chunk()
54
+ this.close()
55
+ return
56
+
57
+ node = $("""
58
+ <iq id="#{@session.uniqueId()}" to="#{@to}" type="set">
59
+ <data xmlns="http://jabber.org/protocol/ibb" sid="#{@sid}" seq="#{@seq++}">#{chunk}</data>
60
+ </iq>
61
+ """)
62
+ @seq = 0 if @seq > 65535
63
+ callback = (result) =>
64
+ return unless this.ok result
65
+ pct = Math.ceil ++@sent / @chunks.total * 100
66
+ this.progress pct
67
+ this.sendChunk()
68
+ @session.sendIQ node.get(0), callback
69
+
70
+ close: ->
71
+ return if @closed
72
+ @closed = true
73
+ node = $("""
74
+ <iq id="#{@session.uniqueId()}" to="#{@to}" type="set">
75
+ <close xmlns="http://jabber.org/protocol/ibb" sid="#{@sid}"/>
76
+ </iq>
77
+ """)
78
+ @session.sendIQ node.get(0), ->
79
+ this.complete()
80
+
81
+ stop: ->
82
+ if @opened
83
+ this.close()
84
+ else
85
+ this.complete()
86
+
87
+ ok: (result) -> $(result).attr('type') == 'result'
88
+
89
+ class Chunks
90
+ constructor: (@file) ->
91
+ @chunks = []
92
+ @total = 0
93
+
94
+ chunk: -> @chunks.shift()
95
+
96
+ start: (callback) ->
97
+ reader = new FileReader()
98
+ reader.onload = (event) =>
99
+ data = btoa event.target.result
100
+ @chunks = (chunk for chunk in data.split /(.{1,4096})/ when chunk)
101
+ @total = @chunks.length
102
+ callback()
103
+ reader.readAsBinaryString @file