From 06c4b25e7c9749e41a88e37714a9a7cef6577602 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Fri, 2 Nov 2012 17:10:22 +0100 Subject: [PATCH] Initial implementation of chat. --- .../app/controllers/login.js.coffee | 2 +- .../app/controllers/logout.js.coffee | 2 +- .../app/controllers/navigation.js.coffee | 4 +-- .../javascripts/app/lib/app/auth.js.coffee | 7 ++-- .../app/lib/app/websocket.js.coffee | 36 ++++++++++++++++++- app/assets/stylesheets/zzz.css | 5 +++ app/views/init/index.html.erb | 1 + lib/web_socket.rb | 8 +++++ script/websocket-server.rb | 27 ++++++++++++-- 9 files changed, 80 insertions(+), 12 deletions(-) diff --git a/app/assets/javascripts/app/controllers/login.js.coffee b/app/assets/javascripts/app/controllers/login.js.coffee index 929ad4fbb..a857ea406 100644 --- a/app/assets/javascripts/app/controllers/login.js.coffee +++ b/app/assets/javascripts/app/controllers/login.js.coffee @@ -86,7 +86,7 @@ class Index extends App.Controller App[key].refresh( value, options: { clear: true } ) # rebuild navbar with user data - App.Event.trigger 'navrebuild', data.session + App.Event.trigger 'ajax:auth', data.session # update websocked auth info App.WebSocket.auth() diff --git a/app/assets/javascripts/app/controllers/logout.js.coffee b/app/assets/javascripts/app/controllers/logout.js.coffee index 6dae57c5e..a0f141065 100644 --- a/app/assets/javascripts/app/controllers/logout.js.coffee +++ b/app/assets/javascripts/app/controllers/logout.js.coffee @@ -15,7 +15,7 @@ class Index extends Spine.Controller @log 'Session', window.Session window.Session = {} @log 'Session', window.Session - App.Event.trigger 'navrebuild' + App.Event.trigger 'ajax:auth' # redirect to login @navigate 'login' diff --git a/app/assets/javascripts/app/controllers/navigation.js.coffee b/app/assets/javascripts/app/controllers/navigation.js.coffee index 1dd40047e..7f9de4fb1 100644 --- a/app/assets/javascripts/app/controllers/navigation.js.coffee +++ b/app/assets/javascripts/app/controllers/navigation.js.coffee @@ -11,8 +11,8 @@ class App.Navigation extends App.Controller @update(arguments[0]) # rebuild nav bar with given user data - App.Event.bind 'navrebuild', (user) => - @log 'navbarrebuild', user + App.Event.bind 'ajax:auth', (user) => + @log 'navbar rebuild', user if !_.isEmpty( user ) cache = App.Store.get( 'navupdate_ticket_overview' ) diff --git a/app/assets/javascripts/app/lib/app/auth.js.coffee b/app/assets/javascripts/app/lib/app/auth.js.coffee index 5beec7d18..2849cdf67 100644 --- a/app/assets/javascripts/app/lib/app/auth.js.coffee +++ b/app/assets/javascripts/app/lib/app/auth.js.coffee @@ -45,7 +45,7 @@ class App.Auth App.WebSocket.auth() # rebuild navbar with new navbar items - App.Event.trigger 'navrebuild' + App.Event.trigger 'ajax:auth' return false; @@ -69,10 +69,7 @@ class App.Auth App.Collection.reset( type: key, data: value ) # rebuild navbar with new navbar items - App.Event.trigger 'navrebuild', data.session - - # rebuild navbar with updated ticket count of overviews - App.Event.trigger 'navupdate_remote' + App.Event.trigger 'ajax:auth', data.session error: (xhr, statusText, error) => console.log 'loginCheck:error'#, error, statusText, xhr.statusCode diff --git a/app/assets/javascripts/app/lib/app/websocket.js.coffee b/app/assets/javascripts/app/lib/app/websocket.js.coffee index 69e66c13b..d2dd32d14 100644 --- a/app/assets/javascripts/app/lib/app/websocket.js.coffee +++ b/app/assets/javascripts/app/lib/app/websocket.js.coffee @@ -19,10 +19,15 @@ class App.WebSocket @connect() _instance.auth(args) + @_spool: -> + _instance.spool() + # The actual Singleton class class _Singleton extends App.Controller queue: [] - supported: true + supported: true + lastSpoolMessage: undefined + connectionEstablished: false constructor: (@args) -> @@ -30,6 +35,11 @@ class _Singleton extends App.Controller App.Event.bind 'ws:send', (data) => @send(data) + # get spool messages after successful ws login + App.Event.bind( 'ws:login', (data) => + @spool() + ) + # inital connect @connect() @@ -58,6 +68,23 @@ class _Singleton extends App.Controller } @send(data) + spool: => + + # build data to send to server + data = + action: 'spool' + if @lastSpoolMessage + data['timestamp'] = @lastSpoolMessage + @log 'spool', data + # ask for spool messages + App.Event.trigger( + 'ws:send' + data + ) + + # set timestamp to get spool messages later + @lastSpoolMessage = Math.round( +new Date()/1000 ) + close: => return if !@supported @@ -103,6 +130,8 @@ class _Singleton extends App.Controller @ws.onopen = => console.log( 'onopen' ) + @connectionEstablished = true + # close error message show up (because try so connect again) if exists @clearDelay('websocket-no-connection-try-reconnect') if @error @@ -149,6 +178,11 @@ class _Singleton extends App.Controller @ws.onclose = (e) => console.log( 'onclose', e ) + # set timestamp to get spool messages later + if @connectionEstablished + @lastSpoolMessage = Math.round( +new Date()/1000 ) + @connectionEstablished = false + # show error message, first try to reconnect if !@error message = => diff --git a/app/assets/stylesheets/zzz.css b/app/assets/stylesheets/zzz.css index 8dae86ea0..69a1bf212 100644 --- a/app/assets/stylesheets/zzz.css +++ b/app/assets/stylesheets/zzz.css @@ -330,3 +330,8 @@ footer { text-shadow: 0 1px 0 #fff; opacity: 0.9; } + +.well-demand { + padding: 8px 15px 0px 15px +} +} diff --git a/app/views/init/index.html.erb b/app/views/init/index.html.erb index 55ee85ddf..1521aa669 100644 --- a/app/views/init/index.html.erb +++ b/app/views/init/index.html.erb @@ -3,6 +3,7 @@
+
diff --git a/lib/web_socket.rb b/lib/web_socket.rb index fec035043..28312e4af 100644 --- a/lib/web_socket.rb +++ b/lib/web_socket.rb @@ -12,6 +12,14 @@ module Session user = { :id => session['id'] } file.puts Marshal.dump(user) } + + # send update to browser + if session['id'] + self.transaction( client_id, { + :event => 'ws:login', + :data => { :success => true }, + }) + end end def self.get( client_id ) diff --git a/script/websocket-server.rb b/script/websocket-server.rb index 1984d442c..13bbcf6b6 100644 --- a/script/websocket-server.rb +++ b/script/websocket-server.rb @@ -44,6 +44,7 @@ puts "Starting websocket server on #{ @options[:b] }:#{ @options[:p] } (secure:# #puts options.inspect @clients = {} +@spool = [] EventMachine.run { EventMachine::WebSocket.start( :host => @options[:b], :port => @options[:p], :secure => @options[:s], :tls_options => tls_options ) do |ws| @@ -89,6 +90,27 @@ EventMachine.run { # check if connection already exists next if !@clients[client_id] + # spool messages for new connects + if data['spool'] + meta = { + :msg => msg, + :timestamp => Time.now.to_i, + } + @spool.push meta + end + + # get spool messages + if data['action'] == 'spool' + @spool.each { |message| + puts message.inspect + puts data['timestamp'] + if !data['timestamp'] || data['timestamp'] < message[:timestamp] + puts "send spool msg to #{client_id} #{ message[:msg] }" + @clients[client_id][:websocket].send( "[#{ message[:msg] }]" ) + end + } + end + # get session if data['action'] == 'login' @clients[client_id][:session] = data['session'] @@ -103,6 +125,7 @@ EventMachine.run { elsif data['action'] == 'broadcast' @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}]" ) end } @@ -137,7 +160,7 @@ EventMachine.run { } } - EventMachine.add_periodic_timer(0.2) { + EventMachine.add_periodic_timer(0.4) { next if @clients.size == 0 log 'debug', "checking for data..." @clients.each { |client_id, client| @@ -164,7 +187,7 @@ EventMachine.run { end } } - + def log( level, data, client_id = '-' ) if !@options[:d] return if level == 'debug'