diff --git a/app/assets/javascripts/app/controllers/chat_widget.js.coffee b/app/assets/javascripts/app/controllers/chat_widget.js.coffee index 66a4ec478..cbd4d67e4 100644 --- a/app/assets/javascripts/app/controllers/chat_widget.js.coffee +++ b/app/assets/javascripts/app/controllers/chat_widget.js.coffee @@ -2,7 +2,7 @@ $ = jQuery.sub() class App.ChatWidget extends App.Controller events: - 'submit #chat_form': 'newMessage' + 'submit #chat_form': 'submitMessage' 'focusin [name=chat_message]': 'focusIn' 'focusout [name=chat_message]': 'focusOut' 'click .close': 'toggle' @@ -24,15 +24,22 @@ class App.ChatWidget extends App.Controller @start() start: => - @focus = false - @isShown = false + @focus = false + @isShown = false + @newMessage = false @render() + @hide() @interval @position, 200, 'chat-widget' App.Event.bind( 'chat:message' (e) => + + # show new message info + @newMessage = true + + # remember messages @messageLog.push e # chump max message count @@ -46,43 +53,72 @@ class App.ChatWidget extends App.Controller App.Event.bind( 'chat:window_toggle' (e) => - if e.user_id is Session['id'] - if e.show - @show() - else - @hide() + if e.show + @show() + else + @hide() + ) + + App.Event.bind( + 'chat:message_new' + (e) => + @el.find('div.well').removeClass('alert-success') ) toggle: (e) => e.preventDefault() - if @el.find('#chat_content').hasClass('hide') + if !@el.find('#chat_content').is(':visible') @show() App.Event.trigger( 'ws:send' action: 'broadcast' event: 'chat:window_toggle' + recipient: + user_id: [ Session['id'] ] data: - user_id: Session['id'] show: true ) else @hide() App.Event.trigger( 'ws:send' - action: 'broadcast' - event: 'chat:window_toggle' + action: 'broadcast' + event: 'chat:window_toggle' + recipient: + user_id: [ Session['id'] ] data: - user_id: Session['id'] show: false ) + @newMessage = false show: => @isShown = true - @el.find('#chat_content').removeClass('hide') + if @newMessage + @el.find('div.well').addClass('alert-success') + @delay( => + @el.find('div.well').removeClass('alert-success') + @log 'DELAY rm' + + App.Event.trigger( + 'ws:send' + action: 'broadcast' + recipient: + user_id: [ Session['id'] ] + event: 'chat:message_new' + spool: true + data: + show: true + ) + + 2000 + 'chat-message-new' + ) + @el.find('#chat_content').show(100) + @newMessage = false hide: => @isShown = false - @el.find('#chat_content').addClass('hide') + @el.find('#chat_content').hide(100) focusIn: => @focus = true @@ -100,16 +136,26 @@ class App.ChatWidget extends App.Controller message.nick = 'me' # insert data + shown = false + if @isShown + shown = true @html App.view('chat_widget')( messages: @messageLog + isShown: shown ) document.getElementById('chat_log_container').scrollTop = 10000 + + # focus in input box if @focus @el.find('[name=chat_message]').focus() + + # show or not show window if @isShown @show() else @hide() + if @newMessage + @el.find('div.well').addClass('alert-success') position: => chatHeigth = $(@el).find('div').height() @@ -127,7 +173,7 @@ class App.ChatWidget extends App.Controller @el.offset( left: width, top: heigth ) @el.css( width: '200px' ) - newMessage: (e) -> + submitMessage: (e) -> e.preventDefault() message = $(e.target).find('[name=chat_message]').val() if message @@ -138,6 +184,7 @@ class App.ChatWidget extends App.Controller @messageLog.push msg $(e.target).find('[name=chat_message]').val('') + App.Event.trigger( 'ws:send' action: 'broadcast' diff --git a/app/assets/javascripts/app/views/chat_widget.jst.eco b/app/assets/javascripts/app/views/chat_widget.jst.eco index 016229ca9..a57e620da 100644 --- a/app/assets/javascripts/app/views/chat_widget.jst.eco +++ b/app/assets/javascripts/app/views/chat_widget.jst.eco @@ -1,6 +1,6 @@

<%- @T('Chat') %>×

-
+
class="hide"<% end %>>
<% for message in @messages: %>
<%= message.nick %>: <%- @L( message.message ) %>
diff --git a/script/websocket-server.rb b/script/websocket-server.rb index 469efce3a..08515421e 100644 --- a/script/websocket-server.rb +++ b/script/websocket-server.rb @@ -93,8 +93,9 @@ EventMachine.run { # spool messages for new connects if data['spool'] meta = { - :msg => msg, - :timestamp => Time.now.to_i, + :msg => msg, + :msg_object => data, + :timestamp => Time.now.to_i, } @spool.push meta end @@ -102,9 +103,25 @@ EventMachine.run { # get spool messages if data['action'] == 'spool' @spool.each { |message| + + # only send not already now messages if !data['timestamp'] || data['timestamp'] < message[:timestamp] - puts "send spool msg to #{client_id} #{ message[:msg] }" - @clients[client_id][:websocket].send( "[#{ message[:msg] }]" ) + + # spool to recipient list + if message[:msg_object]['recipient'] && message[:msg_object]['recipient']['user_id'] + message[:msg_object]['recipient']['user_id'].each { |user_id| + if @clients[client_id][:session]['id'] == user_id + log 'notice', "send spool to (user_id=#{user_id})", client_id + @clients[client_id][:websocket].send( "[#{ message[:msg] }]" ) + end + } + + # spool every client + else + log 'notice', "send spool", client_id + @clients[client_id][:websocket].send( "[#{ message[:msg] }]" ) + end + end } end @@ -121,10 +138,24 @@ EventMachine.run { # broadcast elsif data['action'] == 'broadcast' + + # list all current clients @clients.each { |local_client_id, local_client| if local_client_id != client_id - puts "send broadcast to #{local_client_id} #{msg}" - local_client[:websocket].send( "[#{msg}]" ) + + # broadcast to recipient list + if data['recipient'] && data['recipient']['user_id'] + data['recipient']['user_id'].each { |user_id| + if local_client[:session]['id'] == user_id + log 'notice', "send broadcast to (user_id=#{user_id})", local_client_id + local_client[:websocket].send( "[#{msg}]" ) + end + } + # broadcast every client + else + log 'notice', "send broadcast", local_client_id + local_client[:websocket].send( "[#{msg}]" ) + end end } end @@ -168,7 +199,7 @@ EventMachine.run { queue = Session.queue( client_id ) if queue && queue[0] # log "send " + queue.inspect, client_id - log 'debug', "send data to client", client_id + log 'notice', "send data to client", client_id client[:websocket].send( queue.to_json ) end rescue => e