Browse code

Zmena a upload avataru

Cinan Rakosnik authored on 16/05/2013 at 15:28:35
Showing 7 changed files
... ...
@@ -10,6 +10,7 @@ gem 'xmpp4r', '~> 0.5'
10 10
 gem 'thin', '~> 1.5.0'
11 11
 gem 'websocket-rails', '~> 0.4.3'
12 12
 gem 'bcrypt-ruby'
13
+gem 'rmagick', '~> 2.13.2'
13 14
 
14 15
 # Gems used only for assets and not required
15 16
 # in production environments by default.
... ...
@@ -200,6 +200,7 @@ GEM
200 200
     rdoc (3.12.2)
201 201
       json (~> 1.4)
202 202
     redis (3.0.3)
203
+    rmagick (2.13.2)
203 204
     rspec-core (2.13.1)
204 205
     rspec-expectations (2.13.0)
205 206
       diff-lcs (>= 1.1.3, < 2.0)
... ...
@@ -287,6 +288,7 @@ DEPENDENCIES
287 287
   phantomjs-binaries
288 288
   rails (~> 3.2.11)
289 289
   rails-backbone
290
+  rmagick (~> 2.13.2)
290 291
   rspec-rails
291 292
   sass-rails (~> 3.2.3)
292 293
   spork
... ...
@@ -107,9 +107,12 @@ this.App =
107 107
     updateMyStatus: (message, state)->
108 108
       App.Com.trigger(event: 'app.roster.updateMyStatus', data: {message: message, state: state})
109 109
 
110
-    updateMyVcard: (name, avatar) ->
110
+    updateMyVcardName: (name) ->
111 111
       App.Com.trigger(event: 'app.roster.updateMyVcard', data: {name: name})
112 112
 
113
+    updateMyVcardAvatar: (imageBase64) ->
114
+      App.Com.trigger(event: 'app.roster.updateMyVcard', data: {avatar: imageBase64})
115
+
113 116
     removeContactRemote: (contact, client) ->
114 117
       App.Com.trigger(event: 'app.roster.removeContact', data: {jid: contact, client: client})
115 118
 
... ...
@@ -1,6 +1,7 @@
1 1
 .user
2 2
   .avatar.bigger{ title: "#{@jid}" }
3 3
     %img{ src: "#{@avatar || 'assets/avatar.png'}", alt: I18n.t('chat.roster.avatar_alt') }
4
+    %input.hidden{ type: 'file', name: 'avatar', accept: 'image/png,image/jpeg,image/pjpeg,image/gif,image/webp'}
4 5
     .change-avatar.hidden
5 6
       .background
6 7
       %p change
... ...
@@ -14,8 +14,11 @@ class Xmpp.Views.Contacts.MeView extends Backbone.View
14 14
     'click .js-change-state': (e) -> @openChangeState(e)
15 15
     'click .js-state-clickable': (e) -> @confirmChangeState(e)
16 16
 
17
+    #avatar change events:
17 18
     'mouseover .avatar': -> $('.change-avatar').show()
18 19
     'mouseout .avatar': -> $('.change-avatar').hide()
20
+    'click .change-avatar': -> $('input[name=avatar]').click()
21
+    'change input[name=avatar]': 'uploadAvatar'
19 22
 
20 23
   initialize: () ->
21 24
     _.bindAll(this)
... ...
@@ -70,7 +73,7 @@ class Xmpp.Views.Contacts.MeView extends Backbone.View
70 70
       $this.removeClass('editing')
71 71
 
72 72
     $this.blur()
73
-    App.Com.updateMyVcard(@_getName())
73
+    App.Com.updateMyVcardName(@_getName())
74 74
     @model.set('name', @_getName())
75 75
 
76 76
   openChangeState: (e) ->
... ...
@@ -95,6 +98,14 @@ class Xmpp.Views.Contacts.MeView extends Backbone.View
95 95
 
96 96
     App.Com.updateMyStatus(@_getStatusMessage(), @_getState())
97 97
 
98
+  uploadAvatar: (e) ->
99
+    fr = new FileReader;
100
+    fr.onloadend = ->
101
+      App.Models.me.set(avatar: fr.result)
102
+      App.Com.updateMyVcardAvatar(fr.result)
103
+
104
+    fr.readAsDataURL(e.target.files[0]);
105
+
98 106
   _getStatusMessage: ->
99 107
     if $('.js-edit-status').hasClass('empty')
100 108
       return ''
... ...
@@ -149,6 +149,7 @@
149 149
 
150 150
       img {
151 151
         height: 46px;
152
+        max-width: 46px;
152 153
       }
153 154
 
154 155
       .change-avatar {
... ...
@@ -1,6 +1,7 @@
1 1
 class WsRosterController < WsController
2 2
     require 'xmpp4r/roster'
3 3
     require 'xmpp4r/vcard'
4
+    require 'RMagick'
4 5
 
5 6
     def initialize
6 7
         super
... ...
@@ -170,9 +171,33 @@ class WsRosterController < WsController
170 170
 
171 171
     def me_update_vcard
172 172
         connection_store[:clients].each do |client|
173
-            my_vcard = Jabber::Vcard::Helper.get(client)
174
-            my_vcard['FN'] = my_vcard['NICKNAME'] = message[:name]
175
-            Jabber::Vcard::Helper.set(client, my_vcard)
173
+            Thread.new do
174
+                my_vcard = Jabber::Vcard::Helper.get(client)
175
+
176
+                if message[:name]
177
+                    my_vcard['FN'] = my_vcard['NICKNAME'] = message[:name]
178
+                end
179
+
180
+                if message[:avatar]
181
+                    begin
182
+                        im = Magick::Image::read_inline(message[:avatar]).first
183
+
184
+                        type = im.format.downcase
185
+                        allowed_types = %w(png jpeg pjpeg gif webp)
186
+                        return unless allowed_types.include? type
187
+
188
+                        im.resize_to_fit! 128,128
189
+                        base64 = Base64.encode64(im.to_blob)
190
+
191
+                        my_vcard['PHOTO/TYPE'] = 'image/' + type
192
+                        my_vcard['PHOTO/BINVAL'] = base64
193
+                    rescue
194
+                        # ignored
195
+                    end
196
+                end
197
+
198
+                Jabber::Vcard::Helper.set(client, my_vcard)
199
+            end
176 200
         end
177 201
     end
178 202