Commit 1c125da767ba502b800bd58896ed1aaac828a092
Committed by
Joenio Costa
1 parent
c9fb1096
Exists in
master
and in
29 other branches
chat fixes and new features
* try to reconnect if connection fails * fix ordering * reconnect if connection is lost but user status is not offline * remove some anchors * keep track of buddies order on the client * tweak notification to work on chromium * respect async request order * focus on window when notification clicked * deal with window visibility * add chat-buttons * fix recent_conversations * fix sorting and join room on opening * remove obsolete code * adjusting indentation (sorry but I needed too...) * fix load_conversation * return identifier as key on avatars action * fix typo * add timeout to notification * deal properly with offline messages * fix notification sound * clear unread after loading conversation on background * ignore message from room * add unread messages counter on chat-label * as for notification permission as soon as the chat connects * add profile_info_action to open chat * using jid to save message instead of identifier * add profile_info_action to open chat * as for notification permission as soon as the chat connects * add unread messages counter on chat-label Squashed and Signed-off-by: Joenio Costa <joenio@colivre.coop.br>
Showing
21 changed files
with
1050 additions
and
817 deletions
Show diff stats
app/controllers/public/chat_controller.rb
... | ... | @@ -2,6 +2,7 @@ class ChatController < PublicController |
2 | 2 | |
3 | 3 | before_filter :login_required |
4 | 4 | before_filter :check_environment_feature |
5 | + before_filter :can_send_message, :only => :register_message | |
5 | 6 | |
6 | 7 | def start_session |
7 | 8 | login = user.jid |
... | ... | @@ -54,6 +55,16 @@ class ChatController < PublicController |
54 | 55 | end |
55 | 56 | end |
56 | 57 | |
58 | + def avatars | |
59 | + profiles = environment.profiles.where(:identifier => params[:profiles]) | |
60 | + avatar_map = profiles.inject({}) do |result, profile| | |
61 | + result[profile.identifier] = profile_icon(profile, :minor) | |
62 | + result | |
63 | + end | |
64 | + | |
65 | + render_json avatar_map | |
66 | + end | |
67 | + | |
57 | 68 | def update_presence_status |
58 | 69 | if request.xhr? |
59 | 70 | current_user.update_attributes({:chat_status_at => DateTime.now}.merge(params[:status] || {})) |
... | ... | @@ -62,11 +73,17 @@ class ChatController < PublicController |
62 | 73 | end |
63 | 74 | |
64 | 75 | def save_message |
65 | - to = environment.profiles.find_by_identifier(params[:to]) | |
66 | - body = params[:body] | |
67 | - | |
68 | - ChatMessage.create!(:to => to, :from => user, :body => body) | |
69 | - render :text => 'ok' | |
76 | + if request.post? | |
77 | + to = environment.profiles.where(:identifier => params[:to]).first | |
78 | + body = params[:body] | |
79 | + | |
80 | + begin | |
81 | + ChatMessage.create!(:to => to, :from => user, :body => body) | |
82 | + return render_json({:status => 0}) | |
83 | + rescue Exception => exception | |
84 | + return render_json({:status => 3, :message => exception.to_s, :backtrace => exception.backtrace}) | |
85 | + end | |
86 | + end | |
70 | 87 | end |
71 | 88 | |
72 | 89 | def recent_messages |
... | ... | @@ -90,8 +107,9 @@ class ChatController < PublicController |
90 | 107 | end |
91 | 108 | |
92 | 109 | def recent_conversations |
93 | - conversations_order = ActiveRecord::Base.connection.execute("select profiles.identifier from profiles inner join (select distinct r.id as id, MAX(r.created_at) as created_at from (select from_id, to_id, created_at, (case when from_id=#{user.id} then to_id else from_id end) as id from chat_messages where from_id=#{user.id} or to_id=#{user.id}) as r group by id order by created_at desc, id) as t on profiles.id=t.id order by t.created_at desc").entries.map {|e| e['identifier']} | |
94 | - render :json => {:order => conversations_order.reverse, :domain => environment.default_hostname.gsub('.','-')}.to_json | |
110 | + profiles = Profile.find_by_sql("select profiles.* from profiles inner join (select distinct r.id as id, MAX(r.created_at) as created_at from (select from_id, to_id, created_at, (case when from_id=#{user.id} then to_id else from_id end) as id from chat_messages where from_id=#{user.id} or to_id=#{user.id}) as r group by id order by created_at desc, id) as t on profiles.id=t.id order by t.created_at desc") | |
111 | + jids = profiles.map(&:jid).reverse | |
112 | + render :json => jids.to_json | |
95 | 113 | end |
96 | 114 | |
97 | 115 | #TODO Ideally this is done through roster table on ejabberd. |
... | ... | @@ -108,4 +126,14 @@ class ChatController < PublicController |
108 | 126 | end |
109 | 127 | end |
110 | 128 | |
129 | + def can_send_message | |
130 | + return render_json({:status => 1, :message => 'Missing parameters!'}) if params[:from].nil? || params[:to].nil? || params[:message].nil? | |
131 | + return render_json({:status => 2, :message => 'You can not send message as another user!'}) if params[:from] != user.jid | |
132 | + # TODO Maybe register the jid in a table someday to avoid this below | |
133 | + return render_json({:status => 3, :messsage => 'You can not send messages to strangers!'}) if user.friends.where(:identifier => params[:to].split('@').first).blank? | |
134 | + end | |
135 | + | |
136 | + def render_json(result) | |
137 | + render :text => result.to_json | |
138 | + end | |
111 | 139 | end | ... | ... |
app/helpers/chat_helper.rb
... | ... | @@ -9,12 +9,12 @@ module ChatHelper |
9 | 9 | avatar = profile_image(user, :portrait, :class => 'avatar') |
10 | 10 | content_tag('span', |
11 | 11 | link_to(avatar + content_tag('span', user.name) + ui_icon('ui-icon-triangle-1-s'), |
12 | - '#', | |
12 | + '', | |
13 | 13 | :onclick => 'toggleMenu(this); return false', |
14 | 14 | :class => icon_class + ' simplemenu-trigger' |
15 | 15 | ) + |
16 | 16 | content_tag('ul', |
17 | - links.map{|link| content_tag('li', link_to(link[1], '#', :class => link[0], :id => link[2], 'data-jid' => user.jid), :class => 'simplemenu-item') }.join("\n"), | |
17 | + links.map{|link| content_tag('li', link_to(link[1], '', :class => link[0], :id => link[2], 'data-jid' => user.jid), :class => 'simplemenu-item') }.join("\n"), | |
18 | 18 | :style => 'display: none; z-index: 100', |
19 | 19 | :class => 'simplemenu-submenu' |
20 | 20 | ), | ... | ... |
app/models/chat_message.rb
app/views/blocks/profile_info_actions/_community.html.erb
app/views/blocks/profile_info_actions/_enterprise.html.erb
... | ... | @@ -8,5 +8,5 @@ |
8 | 8 | <li><%= button(:'menu-mail', _('Send an e-mail'), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}, {:id => 'enterprise-contact-button'} ) %></li> |
9 | 9 | <% end %> |
10 | 10 | |
11 | - <li><%= report_abuse(profile, :button) %></li> | |
11 | + <%= render :partial => 'blocks/profile_info_actions/common' %> | |
12 | 12 | </ul> | ... | ... |
app/views/blocks/profile_info_actions/_person.html.erb
... | ... | @@ -11,6 +11,6 @@ |
11 | 11 | <li><%= button(:back, _('Send an e-mail'), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}) %></li> |
12 | 12 | <% end %> |
13 | 13 | |
14 | - <li><%= report_abuse(profile, :button) %></li> | |
14 | + <%= render :partial => 'blocks/profile_info_actions/common' %> | |
15 | 15 | <% end %> |
16 | 16 | </ul> | ... | ... |
app/views/chat/start_session_error.html.erb
1 | 1 | <p> |
2 | 2 | <%= ui_icon('ui-icon-alert') %> |
3 | -<%= _('Could not connect to chat') %>, <a id='chat-retry' href='#' data-jid='<%= user.jid %>'><%= _('try again') %></a>. | |
3 | +<%= _('Could not connect to chat') %>, <a id='chat-retry' href='' data-jid='<%= user.jid %>'><%= _('try again') %></a>. | |
4 | 4 | </p> | ... | ... |
app/views/shared/logged_in/xmpp_chat.html.erb
... | ... | @@ -7,13 +7,13 @@ |
7 | 7 | var $own_name = '<%= user.name %>'; |
8 | 8 | var $muc_domain = '<%= "conference.#{environment.default_hostname}" %>'; |
9 | 9 | var $bosh_service = '//<%= environment.default_hostname %>/http-bind'; |
10 | - var $user_unavailable_error = '<%= _("<strong>ooops!</strong> The message could not be sent because the user is not online") %>'; | |
10 | + var $user_unavailable_error = '<%= _("The user is not online now. He/She will receive these messages as soon as he/she gets online.") %>'; | |
11 | 11 | var $update_presence_status_every = <%= User.expires_chat_status_every.minutes %>; |
12 | 12 | var $presence = '<%= current_user.last_chat_status %>'; |
13 | 13 | </script> |
14 | 14 | |
15 | - | |
16 | 15 | <div id="chat-label"> |
16 | + <span id="unread-messages"></span> | |
17 | 17 | <span class="right-arrow">▶</span> |
18 | 18 | <span class="title"><%= _('Chat') %></span> |
19 | 19 | </div> |
... | ... | @@ -98,10 +98,5 @@ |
98 | 98 | </div> |
99 | 99 | </div> |
100 | 100 | </div> |
101 | - | |
102 | - <div class="error-message"> | |
103 | - <span class='error'>%{text}</span> | |
104 | - </div> | |
105 | - | |
106 | 101 | </div> |
107 | 102 | </div> | ... | ... |
... | ... | @@ -0,0 +1,8 @@ |
1 | +<% label_name = profile.person? ? _('Open chat') : _('Join chat room') %> | |
2 | +<% display = profile.person? ? profile.friends.include?(user) : profile.members.include?(user) %> | |
3 | + | |
4 | +<% if display %> | |
5 | + <li> | |
6 | + <%= button(:chat, label_name , {}, :class => 'open-conversation', 'data-jid' => profile.jid) %> | |
7 | + </li> | |
8 | +<% end %> | ... | ... |
db/migrate/20140820173129_create_chat_messages.rb
... | ... | @@ -0,0 +1,20 @@ |
1 | +class CreateChatMessages < ActiveRecord::Migration | |
2 | + def up | |
3 | + create_table :chat_messages do |t| | |
4 | + t.references :from | |
5 | + t.references :to | |
6 | + t.text :body | |
7 | + t.timestamps | |
8 | + end | |
9 | + add_index :chat_messages, :from_id | |
10 | + add_index :chat_messages, :to_id | |
11 | + add_index :chat_messages, :created_at | |
12 | + end | |
13 | + | |
14 | + def down | |
15 | + drop_table :chat_messages | |
16 | + remove_index :chat_messages, :from | |
17 | + remove_index :chat_messages, :to | |
18 | + remove_index :chat_messages, :created_at | |
19 | + end | |
20 | +end | ... | ... |
db/schema.rb
... | ... | @@ -245,13 +245,17 @@ ActiveRecord::Schema.define(:version => 20150513213939) do |
245 | 245 | end |
246 | 246 | |
247 | 247 | create_table "chat_messages", :force => true do |t| |
248 | - t.integer "to_id" | |
249 | 248 | t.integer "from_id" |
250 | - t.string "body" | |
249 | + t.integer "to_id" | |
250 | + t.text "body" | |
251 | 251 | t.datetime "created_at", :null => false |
252 | 252 | t.datetime "updated_at", :null => false |
253 | 253 | end |
254 | 254 | |
255 | + add_index "chat_messages", ["created_at"], :name => "index_chat_messages_on_created_at" | |
256 | + add_index "chat_messages", ["from_id"], :name => "index_chat_messages_on_from_id" | |
257 | + add_index "chat_messages", ["to_id"], :name => "index_chat_messages_on_to_id" | |
258 | + | |
255 | 259 | create_table "comments", :force => true do |t| |
256 | 260 | t.string "title" |
257 | 261 | t.text "body" | ... | ... |
debian/noosfero.install
debian/update-noosfero-apache
... | ... | @@ -18,9 +18,20 @@ if test -x /usr/share/noosfero/script/apacheconf; then |
18 | 18 | fi |
19 | 19 | |
20 | 20 | apache_site='/etc/apache2/sites-available/noosfero' |
21 | + apache_site_configs='/etc/noosfero/apache.d' | |
21 | 22 | if ! test -e "$apache_site"; then |
22 | 23 | echo "Generating apache virtual host ..." |
23 | 24 | cd /usr/share/noosfero && su noosfero -c "RAILS_ENV=production ./script/apacheconf virtualhosts" > "$apache_site" |
25 | + if ! test -d "$apache_site_configs"; then | |
26 | + echo "Creating noosfero site config folder ..." | |
27 | + mkdir $apache_site_configs | |
28 | + fi | |
29 | + else | |
30 | + pattern="Include \/etc\/noosfero\/apache\/virtualhost.conf" | |
31 | + include="Include \/etc\/noosfero\/apache.d\/*" | |
32 | + if ! cat $apache_site | grep "^ *$include" > /dev/null ; then | |
33 | + sed -i "s/.*$pattern.*/ $include\n&/" $apache_site | |
34 | + fi | |
24 | 35 | fi |
25 | 36 | |
26 | 37 | echo 'Noosfero Apache configuration updated.' | ... | ... |
public/javascripts/application.js
... | ... | @@ -1140,10 +1140,20 @@ function notifyMe(title, options) { |
1140 | 1140 | |
1141 | 1141 | // If the user is okay, let's create a notification |
1142 | 1142 | if (permission === "granted") { |
1143 | - notification = new Notification(title, options); | |
1143 | + notification = new Notification(title, options); | |
1144 | 1144 | } |
1145 | 1145 | }); |
1146 | 1146 | } |
1147 | + | |
1148 | + setTimeout(function() {notification.close()}, 5000); | |
1149 | + notification.onclick = function(){ | |
1150 | + notification.close(); | |
1151 | + // Chromium tweak | |
1152 | + window.open().close(); | |
1153 | + window.focus(); | |
1154 | + this.cancel(); | |
1155 | + }; | |
1156 | + | |
1147 | 1157 | return notification; |
1148 | 1158 | // At last, if the user already denied any notification, and you |
1149 | 1159 | // want to be respectful there is no need to bother them any more. | ... | ... |
public/javascripts/chat.js
1 | 1 | /* XMPP/Jabber Noosfero's client |
2 | 2 | |
3 | - XMPP Core: | |
4 | - http://xmpp.org/rfcs/rfc3920.html | |
3 | +XMPP Core: | |
4 | +http://xmpp.org/rfcs/rfc3920.html | |
5 | 5 | |
6 | - MUC support: | |
7 | - http://xmpp.org/extensions/xep-0045.html | |
6 | +MUC support: | |
7 | +http://xmpp.org/extensions/xep-0045.html | |
8 | 8 | |
9 | - Messages and presence: | |
10 | - http://xmpp.org/rfcs/rfc3921.html | |
9 | +Messages and presence: | |
10 | +http://xmpp.org/rfcs/rfc3921.html | |
11 | 11 | */ |
12 | 12 | |
13 | 13 | jQuery(function($) { |
14 | - // extending the current namespaces in Strophe.NS | |
15 | - Strophe.addNamespace('MUC_USER', 'http://jabber.org/protocol/muc#user'); | |
16 | - Strophe.addNamespace('MUC_OWNER', 'http://jabber.org/protocol/muc#owner'); | |
17 | - Strophe.addNamespace('CHAT_STATES', 'http://jabber.org/protocol/chatstates'); | |
18 | - Strophe.addNamespace('DATA_FORMS', 'jabber:x:data'); | |
19 | - | |
20 | - var Jabber = { | |
21 | - debug: true, | |
22 | - connection: null, | |
23 | - bosh_service: $bosh_service, | |
24 | - muc_domain: $muc_domain, | |
25 | - muc_supported: false, | |
26 | - presence_status: '', | |
27 | - conversation_prefix: 'conversation-', | |
28 | - jids: {}, | |
29 | - rooms: {}, | |
30 | - no_more_messages: {}, | |
31 | - | |
32 | - template: function(selector) { | |
33 | - return $('#chat #chat-templates '+selector).clone().html(); | |
34 | - }, | |
35 | - | |
36 | - jid_to_id: function (jid) { | |
37 | - return Strophe.getBareJidFromJid(jid).replace(/@/g, "-").replace(/\./g, "-"); | |
38 | - }, | |
39 | - | |
40 | - jid_of: function(jid_id) { | |
41 | - return Jabber.jids[jid_id].jid; | |
42 | - }, | |
43 | - name_of: function(jid_id) { | |
44 | - return Jabber.jids[jid_id].name; | |
45 | - }, | |
46 | - type_of: function(jid_id) { | |
47 | - return Jabber.jids[jid_id].type; | |
48 | - }, | |
49 | - unread_messages_of: function(jid_id, value) { | |
50 | - Jabber.jids[jid_id].unread_messages = (value == undefined ? Jabber.jids[jid_id].unread_messages : value); | |
51 | - return Jabber.jids[jid_id].unread_messages; | |
52 | - }, | |
53 | - | |
54 | - insert_or_update_user: function (list, item, jid, name, presence, template, type, remove_on_offline) { | |
55 | - var jid_id = Jabber.jid_to_id(jid); | |
56 | - var identifier = Strophe.getNodeFromJid(jid); | |
57 | - var html = template | |
58 | - .replace('%{jid_id}', jid_id) | |
59 | - .replace(/%{presence_status}/g, presence) | |
60 | - .replace('%{avatar}', getAvatar(identifier)) | |
61 | - .replace('%{name}', name); | |
62 | - | |
63 | - $(item).parent().remove(); | |
64 | - if(presence != 'offline' || !remove_on_offline) | |
65 | - $(list).append(html); | |
66 | - Jabber.jids[jid_id] = {jid: jid, name: name, type: type, presence: presence}; | |
67 | - }, | |
68 | - insert_or_update_group: function (jid, presence) { | |
69 | - var jid_id = Jabber.jid_to_id(jid); | |
70 | - var list = $('#buddy-list .buddies ul.'+presence); | |
71 | - var item = $('#' + jid_id); | |
72 | - presence = presence || ($(item).length > 0 ? $(item).parent('li').attr('class') : 'offline'); | |
73 | - log('adding or updating contact ' + jid + ' as ' + presence); | |
74 | - Jabber.insert_or_update_user(list, item, jid, Jabber.name_of(jid_id), presence, Jabber.template('.buddy-item'), 'groupchat'); | |
75 | - $("#chat-window .tab a[href='#"+ Jabber.conversation_prefix + jid_id +"']") | |
76 | - .removeClass() | |
77 | - .addClass('icon-menu-' + presence + '-11'); | |
78 | - }, | |
79 | - insert_or_update_contact: function (jid, name, presence) { | |
80 | - var jid_id = Jabber.jid_to_id(jid); | |
81 | - var item = $('#' + jid_id); | |
82 | - presence = presence || ($(item).length > 0 ? $(item).parent('li').attr('class') : 'offline'); | |
83 | - var list = $('#buddy-list .buddies ul' + (presence=='offline' ? '.offline' : '.online')); | |
84 | - | |
85 | - log('adding or updating contact ' + jid + ' as ' + presence); | |
86 | - Jabber.insert_or_update_user(list, item, jid, name, presence, Jabber.template('.buddy-item'), 'chat'); | |
87 | - $("#chat-window .tab a[href='#"+ Jabber.conversation_prefix + jid_id +"']") | |
88 | - .removeClass() | |
89 | - .addClass('icon-menu-' + presence + '-11'); | |
90 | - }, | |
91 | - insert_or_update_occupant: function (jid, name, presence, room_jid) { | |
92 | - log('adding or updating occupant ' + jid + ' as ' + presence); | |
93 | - var jid_id = Jabber.jid_to_id(jid); | |
94 | - var room_jid_id = Jabber.jid_to_id(room_jid); | |
95 | - var list = $('#' + Jabber.conversation_prefix + room_jid_id + ' .occupants ul'); | |
96 | - var item = $(list).find('a[data-id='+ jid_id +']'); | |
97 | - Jabber.insert_or_update_user(list, item, jid, name, presence, Jabber.template('.occupant-item'), 'chat', true); | |
98 | - if (Jabber.rooms[room_jid_id] === undefined) | |
99 | - Jabber.rooms[room_jid_id] = {}; | |
100 | - | |
101 | - var room = Jabber.rooms[room_jid_id]; | |
102 | - if(presence == 'offline') { | |
103 | - delete Jabber.rooms[room_jid_id][name]; | |
104 | - } | |
105 | - else { | |
106 | - Jabber.rooms[room_jid_id][name] = jid; | |
107 | - } | |
14 | + // extending the current namespaces in Strophe.NS | |
15 | + Strophe.addNamespace('MUC_USER', 'http://jabber.org/protocol/muc#user'); | |
16 | + Strophe.addNamespace('MUC_OWNER', 'http://jabber.org/protocol/muc#owner'); | |
17 | + Strophe.addNamespace('CHAT_STATES', 'http://jabber.org/protocol/chatstates'); | |
18 | + Strophe.addNamespace('DATA_FORMS', 'jabber:x:data'); | |
19 | + | |
20 | + var Jabber = { | |
21 | + debug: true, | |
22 | + connection: null, | |
23 | + bosh_service: $bosh_service, | |
24 | + muc_domain: $muc_domain, | |
25 | + muc_supported: false, | |
26 | + presence_status: '', | |
27 | + conversation_prefix: 'conversation-', | |
28 | + conversations_order: null, | |
29 | + notification_sound: new Audio('/sounds/receive.wav'), | |
30 | + window_visibility: null, | |
31 | + jids: {}, | |
32 | + rooms: {}, | |
33 | + no_more_messages: {}, | |
34 | + avatars: {}, | |
35 | + | |
36 | + template: function(selector) { | |
37 | + return $('#chat #chat-templates '+selector).clone().html(); | |
38 | + }, | |
39 | + | |
40 | + jid_to_id: function (jid) { | |
41 | + return Strophe.getBareJidFromJid(jid).replace(/@/g, "-").replace(/\./g, "-"); | |
42 | + }, | |
43 | + | |
44 | + jid_of: function(jid_id) { | |
45 | + return Jabber.jids[jid_id].jid; | |
46 | + }, | |
47 | + name_of: function(jid_id) { | |
48 | + return Jabber.jids[jid_id].name; | |
49 | + }, | |
50 | + type_of: function(jid_id) { | |
51 | + return Jabber.jids[jid_id].type; | |
52 | + }, | |
53 | + presence_of: function(jid_id) { | |
54 | + return Jabber.jids[jid_id].presence; | |
55 | + }, | |
56 | + unread_messages_of: function(jid_id, value) { | |
57 | + Jabber.jids[jid_id].unread_messages = (value == undefined ? Jabber.jids[jid_id].unread_messages : value); | |
58 | + return Jabber.jids[jid_id].unread_messages; | |
59 | + }, | |
60 | + | |
61 | + insert_or_update_user: function (list, item, jid, name, presence, template, type, remove_on_offline) { | |
62 | + var jid_id = Jabber.jid_to_id(jid); | |
63 | + var identifier = Strophe.getNodeFromJid(jid); | |
64 | + var html = template | |
65 | + .replace('%{jid_id}', jid_id) | |
66 | + .replace(/%{presence_status}/g, presence) | |
67 | + .replace('%{avatar}', getAvatar(identifier)) | |
68 | + .replace('%{name}', name); | |
69 | + | |
70 | + $(item).parent().remove(); | |
71 | + if(presence != 'offline' || !remove_on_offline){ | |
72 | + $(list).append(html); | |
73 | + sort_conversations(); | |
74 | + } | |
75 | + Jabber.jids[jid_id] = {jid: jid, name: name, type: type, presence: presence}; | |
76 | + }, | |
77 | + insert_or_update_group: function (jid, presence) { | |
78 | + var jid_id = Jabber.jid_to_id(jid); | |
79 | + var list = $('#buddy-list .buddies ul.'+presence); | |
80 | + var item = $('#' + jid_id); | |
81 | + presence = presence || ($(item).length > 0 ? $(item).parent('li').attr('class') : 'offline'); | |
82 | + log('adding or updating contact ' + jid + ' as ' + presence); | |
83 | + Jabber.insert_or_update_user(list, item, jid, Jabber.name_of(jid_id), presence, Jabber.template('.buddy-item'), 'groupchat'); | |
84 | + $("#chat-window .tab a[href='#"+ Jabber.conversation_prefix + jid_id +"']") | |
85 | + .removeClass() | |
86 | + .addClass('icon-menu-' + presence + '-11'); | |
87 | + }, | |
88 | + insert_or_update_contact: function (jid, name, presence) { | |
89 | + var jid_id = Jabber.jid_to_id(jid); | |
90 | + var item = $('#' + jid_id); | |
91 | + presence = presence || ($(item).length > 0 ? $(item).parent('li').attr('class') : 'offline'); | |
92 | + var list = $('#buddy-list .buddies ul' + (presence=='offline' ? '.offline' : '.online')); | |
93 | + | |
94 | + log('adding or updating contact ' + jid + ' as ' + presence); | |
95 | + Jabber.insert_or_update_user(list, item, jid, name, presence, Jabber.template('.buddy-item'), 'chat'); | |
96 | + $("#chat-window .tab a[href='#"+ Jabber.conversation_prefix + jid_id +"']") | |
97 | + .removeClass() | |
98 | + .addClass('icon-menu-' + presence + '-11'); | |
99 | + }, | |
100 | + insert_or_update_occupant: function (jid, name, presence, room_jid) { | |
101 | + log('adding or updating occupant ' + jid + ' as ' + presence); | |
102 | + var jid_id = Jabber.jid_to_id(jid); | |
103 | + var room_jid_id = Jabber.jid_to_id(room_jid); | |
104 | + var list = $('#' + Jabber.conversation_prefix + room_jid_id + ' .occupants ul'); | |
105 | + var item = $(list).find('a[data-id='+ jid_id +']'); | |
106 | + Jabber.insert_or_update_user(list, item, jid, name, presence, Jabber.template('.occupant-item'), 'chat', true); | |
107 | + if (Jabber.rooms[room_jid_id] === undefined) | |
108 | + Jabber.rooms[room_jid_id] = {}; | |
109 | + | |
110 | + var room = Jabber.rooms[room_jid_id]; | |
111 | + if(presence == 'offline') { | |
112 | + delete Jabber.rooms[room_jid_id][name]; | |
113 | + } | |
114 | + else { | |
115 | + Jabber.rooms[room_jid_id][name] = jid; | |
116 | + } | |
108 | 117 | |
109 | - list.parents('.occupants').find('.occupants-online').text(Object.keys(Jabber.rooms[room_jid_id]).length); | |
110 | - }, | |
111 | - | |
112 | - remove_contact: function(jid) { | |
113 | - var jid_id = Jabber.jid_to_id(jid) | |
114 | - log('Removing contact ' + jid); | |
115 | - $('#' + jid_id).parent('li').remove(); | |
116 | - }, | |
117 | - | |
118 | - render_body_message: function(body) { | |
119 | - body = body.replace(/\r?\n/g, '<br>'); | |
120 | - body = $().emoticon(body); | |
121 | - body = linkify(body, { | |
122 | - callback: function(text, href) { | |
123 | - return href ? '<a href="' + href + '" title="' + href + '" target="_blank">' + text + '</a>' : text; | |
124 | - } | |
125 | - }); | |
126 | - return body; | |
127 | - }, | |
118 | + list.parents('.occupants').find('.occupants-online').text(Object.keys(Jabber.rooms[room_jid_id]).length); | |
119 | + }, | |
120 | + | |
121 | + remove_contact: function(jid) { | |
122 | + var jid_id = Jabber.jid_to_id(jid) | |
123 | + log('Removing contact ' + jid); | |
124 | + $('#' + jid_id).parent('li').remove(); | |
125 | + }, | |
126 | + | |
127 | + render_body_message: function(body) { | |
128 | + body = body.replace(/\r?\n/g, '<br>'); | |
129 | + body = $().emoticon(body); | |
130 | + body = linkify(body, { | |
131 | + callback: function(text, href) { | |
132 | + return href ? '<a href="' + href + '" title="' + href + '" target="_blank">' + text + '</a>' : text; | |
133 | + } | |
134 | + }); | |
135 | + return body; | |
136 | + }, | |
128 | 137 | |
129 | - show_message: function (jid, name, body, who, identifier, time, offset) { | |
130 | - if(!offset) offset = 0; | |
131 | - if (body) { | |
132 | - body = Jabber.render_body_message(body); | |
133 | - var jid_id = Jabber.jid_to_id(jid); | |
134 | - var tab_id = '#' + Jabber.conversation_prefix + jid_id; | |
135 | - var history = $(tab_id).find('.history'); | |
138 | + show_message: function (jid, name, body, who, identifier, time, offset) { | |
139 | + if(!offset) offset = 0; | |
140 | + if (body) { | |
141 | + body = Jabber.render_body_message(body); | |
142 | + var jid_id = Jabber.jid_to_id(jid); | |
143 | + var tab_id = '#' + Jabber.conversation_prefix + jid_id; | |
144 | + var history = $(tab_id).find('.history'); | |
136 | 145 | |
137 | - var offset_container = history.find('.chat-offset-container-'+offset); | |
138 | - if(offset_container.length == 0) | |
139 | - offset_container = $('<div class="chat-offset-container-'+offset+'"></div>').prependTo(history); | |
146 | + var offset_container = history.find('.chat-offset-container-'+offset); | |
147 | + if(offset_container.length == 0) | |
148 | + offset_container = $('<div class="chat-offset-container-'+offset+'"></div>').prependTo(history); | |
140 | 149 | |
141 | - if (offset_container.find('.message:last').attr('data-who') == who) { | |
142 | - offset_container.find('.message:last .content').append('<p>' + body + '</p>'); | |
143 | - } | |
144 | - else { | |
145 | - if (time==undefined) { | |
146 | - time = new Date().toISOString(); | |
147 | - } | |
148 | - var message_html = Jabber.template('.message') | |
149 | - .replace('%{message}', body) | |
150 | - .replace(/%{who}/g, who) | |
151 | - .replace('%{time}', time) | |
152 | - .replace('%{name}', name) | |
153 | - .replace('%{avatar}', getAvatar(identifier)); | |
154 | - offset_container.append(message_html); | |
155 | - $(".message span.time").timeago(); | |
156 | - } | |
157 | - if(offset == 0) history.scrollTo({top:'100%', left:'0%'}); | |
158 | - else history.scrollTo(offset_container.height()); | |
159 | - if (who != "self") { | |
160 | - if ($(tab_id).find('.history:visible').length == 0) { | |
161 | - count_unread_messages(jid_id); | |
162 | - } | |
163 | - document.alert_title = name; | |
164 | - } | |
165 | - } | |
166 | - }, | |
167 | - | |
168 | - show_status: function(presence) { | |
169 | - log('changing my status to ' + presence); | |
170 | - $('#buddy-list .user-status .simplemenu-trigger') | |
171 | - .removeClass('icon-menu-chat') | |
172 | - .removeClass('icon-menu-offline') | |
173 | - .removeClass('icon-menu-dnd') | |
174 | - .addClass('icon-menu-' + (presence || 'offline')); | |
175 | - $('#buddy-list #user-status img.avatar').replaceWith(getMyAvatar()); | |
176 | - $.get('/chat/update_presence_status', { status: {chat_status: presence, last_chat_status: presence} }); | |
177 | - }, | |
178 | - | |
179 | - send_availability_status: function(presence) { | |
180 | - log('send availability status ' + presence); | |
181 | - Jabber.connection.send($pres().c('show').t(presence).up()); | |
182 | - Jabber.show_status(presence); | |
183 | - }, | |
184 | - | |
185 | - enter_room: function(jid, push) { | |
186 | - if(push == undefined) | |
187 | - push = true | |
188 | - var jid_id = Jabber.jid_to_id(jid); | |
189 | - var conversation_id = Jabber.conversation_prefix + jid_id; | |
190 | - var button = $('#' + conversation_id + ' .join'); | |
191 | - button.hide(); | |
192 | - button.siblings('.leave').show(); | |
193 | - Jabber.connection.send( | |
194 | - $pres({to: jid + '/' + $own_name}).c('x', {xmlns: Strophe.NS.MUC}).c('history', {maxchars: 0}) | |
195 | - ); | |
196 | - Jabber.insert_or_update_group(jid, 'online'); | |
150 | + if (offset_container.find('.message:last').attr('data-who') == who) { | |
151 | + offset_container.find('.message:last .content').append('<p>' + body + '</p>'); | |
152 | + } | |
153 | + else { | |
154 | + if (time==undefined) { | |
155 | + time = new Date().toISOString(); | |
156 | + } | |
157 | + var message_html = Jabber.template('.message') | |
158 | + .replace('%{message}', body) | |
159 | + .replace(/%{who}/g, who) | |
160 | + .replace('%{time}', time) | |
161 | + .replace('%{name}', name) | |
162 | + .replace('%{avatar}', getAvatar(identifier)); | |
163 | + offset_container.append(message_html); | |
164 | + $(".message span.time").timeago(); | |
165 | + } | |
166 | + if(offset == 0) history.scrollTo({top:'100%', left:'0%'}); | |
167 | + else history.scrollTo(offset_container.height()); | |
168 | + if (who != "self") { | |
169 | + if ($(tab_id).find('.history:visible').length == 0) { | |
170 | + count_unread_messages(jid_id); | |
171 | + } | |
172 | + document.alert_title = name; | |
173 | + } | |
174 | + } | |
175 | + }, | |
176 | + | |
177 | + show_status: function(presence) { | |
178 | + log('changing my status to ' + presence); | |
179 | + $('#buddy-list .user-status .simplemenu-trigger') | |
180 | + .removeClass('icon-menu-chat') | |
181 | + .removeClass('icon-menu-offline') | |
182 | + .removeClass('icon-menu-dnd') | |
183 | + .addClass('icon-menu-' + (presence || 'offline')); | |
184 | + $('#buddy-list #user-status img.avatar').replaceWith(getMyAvatar()); | |
185 | + $.get('/chat/update_presence_status', { status: {chat_status: presence, last_chat_status: presence} }); | |
186 | + }, | |
187 | + | |
188 | + send_availability_status: function(presence) { | |
189 | + log('send availability status ' + presence); | |
190 | + Jabber.connection.send($pres().c('show').t(presence).up()); | |
191 | + Jabber.show_status(presence); | |
192 | + }, | |
193 | + | |
194 | + enter_room: function(jid, push) { | |
195 | + if(push == undefined) | |
196 | + push = true | |
197 | + var jid_id = Jabber.jid_to_id(jid); | |
198 | + var conversation_id = Jabber.conversation_prefix + jid_id; | |
199 | + var button = $('#' + conversation_id + ' .join'); | |
200 | + button.hide(); | |
201 | + button.siblings('.leave').show(); | |
202 | + Jabber.connection.send( | |
203 | + $pres({to: jid + '/' + $own_name}).c('x', {xmlns: Strophe.NS.MUC}).c('history', {maxchars: 0}) | |
204 | + ); | |
205 | + Jabber.insert_or_update_group(jid, 'online'); | |
206 | + Jabber.update_chat_title(); | |
207 | + sort_conversations(); | |
208 | + if(push) | |
209 | + $.post('/chat/join', {room_id: jid}); | |
210 | + }, | |
211 | + | |
212 | + leave_room: function(jid, push) { | |
213 | + if(push == undefined) | |
214 | + push = true | |
215 | + var jid_id = Jabber.jid_to_id(jid); | |
216 | + var conversation_id = Jabber.conversation_prefix + jid_id; | |
217 | + var button = $('#' + conversation_id + ' .leave'); | |
218 | + button.hide(); | |
219 | + button.siblings('.join').show(); | |
220 | + Jabber.connection.send($pres({from: Jabber.connection.jid, to: jid + '/' + $own_name, type: 'unavailable'})) | |
221 | + Jabber.insert_or_update_group(jid, 'offline'); | |
222 | + sort_conversations(); | |
223 | + if(push) | |
224 | + $.post('/chat/leave', {room_id: jid}); | |
225 | + }, | |
226 | + | |
227 | + update_chat_title: function () { | |
228 | + var friends_online = $('#buddy-list #friends .buddy-list.online li').length; | |
229 | + $('#friends-online').text(friends_online); | |
230 | + var friends_offline = $('#buddy-list #friends .buddy-list.offline li').length; | |
231 | + $('#friends-offline').text(friends_offline); | |
232 | + var groups_online = $('#buddy-list #rooms .buddy-list li').length; | |
233 | + $('#groups-online').text(groups_online); | |
234 | + }, | |
235 | + | |
236 | + on_connect: function (status) { | |
237 | + switch (status) { | |
238 | + case Strophe.Status.CONNECTING: | |
239 | + log('connecting...'); | |
240 | + break; | |
241 | + case Strophe.Status.CONNFAIL: | |
242 | + log('failed to connect'); | |
243 | + setTimeout(function(){Jabber.connect()}, 10000); | |
244 | + break; | |
245 | + case Strophe.Status.DISCONNECTING: | |
246 | + log('disconnecting...'); | |
247 | + $('#buddy-list .toolbar').addClass('small-loading-dark'); | |
248 | + break; | |
249 | + case Strophe.Status.DISCONNECTED: | |
250 | + log('disconnected'); | |
251 | + $('#buddy-list ul.buddy-list, .occupants ul.occupant-list').html(''); | |
197 | 252 | Jabber.update_chat_title(); |
198 | - sort_conversations(); | |
199 | - if(push) | |
200 | - $.post('/chat/join', {room_id: jid}); | |
201 | - }, | |
202 | - | |
203 | - leave_room: function(jid, push) { | |
204 | - if(push == undefined) | |
205 | - push = true | |
253 | + $('#buddy-list .toolbar').removeClass('small-loading-dark'); | |
254 | + $('textarea').prop('disabled', 'disabled'); | |
255 | + if(Jabber.presence_status != 'offline') | |
256 | + Jabber.connect(); | |
257 | + break; | |
258 | + case Strophe.Status.CONNECTED: | |
259 | + log('connected'); | |
260 | + case Strophe.Status.ATTACHED: | |
261 | + log('XMPP/BOSH session attached'); | |
262 | + $('#buddy-list .toolbar').removeClass('small-loading-dark'); | |
263 | + $('textarea').prop('disabled', ''); | |
264 | + break; | |
265 | + } | |
266 | + }, | |
267 | + | |
268 | + on_roster: function (iq) { | |
269 | + log('receiving roster'); | |
270 | + var profiles = []; | |
271 | + var contacts_to_insert = {}; | |
272 | + var groups_to_insert = []; | |
273 | + | |
274 | + $(iq).find('item').each(function () { | |
275 | + var jid = $(this).attr('jid'); | |
276 | + profiles.push(getIdentifier(jid)); | |
277 | + var name = $(this).attr('name') || jid; | |
206 | 278 | var jid_id = Jabber.jid_to_id(jid); |
207 | - var conversation_id = Jabber.conversation_prefix + jid_id; | |
208 | - var button = $('#' + conversation_id + ' .leave'); | |
209 | - button.hide(); | |
210 | - button.siblings('.join').show(); | |
211 | - Jabber.connection.send($pres({from: Jabber.connection.jid, to: jid + '/' + $own_name, type: 'unavailable'})) | |
212 | - Jabber.insert_or_update_group(jid, 'offline'); | |
213 | - sort_conversations(); | |
214 | - if(push) | |
215 | - $.post('/chat/leave', {room_id: jid}); | |
216 | - }, | |
217 | - | |
218 | - update_chat_title: function () { | |
219 | - var friends_online = $('#buddy-list #friends .buddy-list.online li').length; | |
220 | - $('#friends-online').text(friends_online); | |
221 | - var friends_offline = $('#buddy-list #friends .buddy-list.offline li').length; | |
222 | - $('#friends-offline').text(friends_offline); | |
223 | - var groups_online = $('#buddy-list #rooms .buddy-list li').length; | |
224 | - $('#groups-online').text(groups_online); | |
225 | - }, | |
226 | - | |
227 | - on_connect: function (status) { | |
228 | - switch (status) { | |
229 | - case Strophe.Status.CONNECTING: | |
230 | - log('connecting...'); | |
231 | - break; | |
232 | - case Strophe.Status.CONNFAIL: | |
233 | - log('failed to connect'); | |
234 | - break; | |
235 | - case Strophe.Status.DISCONNECTING: | |
236 | - log('disconnecting...'); | |
237 | - $('#buddy-list .toolbar').addClass('small-loading-dark'); | |
238 | - break; | |
239 | - case Strophe.Status.DISCONNECTED: | |
240 | - log('disconnected'); | |
241 | - $('#buddy-list ul.buddy-list, .occupants ul.occupant-list').html(''); | |
242 | - Jabber.update_chat_title(); | |
243 | - $('#buddy-list .toolbar').removeClass('small-loading-dark'); | |
244 | - $('textarea').prop('disabled', 'disabled'); | |
245 | - break; | |
246 | - case Strophe.Status.CONNECTED: | |
247 | - log('connected'); | |
248 | - case Strophe.Status.ATTACHED: | |
249 | - log('XMPP/BOSH session attached'); | |
250 | - $('#buddy-list .toolbar').removeClass('small-loading-dark'); | |
251 | - $('textarea').prop('disabled', ''); | |
252 | - break; | |
253 | - } | |
254 | - }, | |
255 | - | |
256 | - on_roster: function (iq) { | |
257 | - log('receiving roster'); | |
258 | - $(iq).find('item').each(function () { | |
259 | - var jid = $(this).attr('jid'); | |
260 | - var name = $(this).attr('name') || jid; | |
261 | - var jid_id = Jabber.jid_to_id(jid); | |
262 | - Jabber.insert_or_update_contact(jid, name); | |
263 | - }); | |
264 | - //TODO Add groups through roster too... | |
265 | - $.ajax({ | |
266 | - url: '/chat/roster_groups', | |
267 | - dataType: 'json', | |
268 | - success: function(data){ | |
269 | - data.each(function(room){ | |
270 | - var jid_id = Jabber.jid_to_id(room.jid); | |
271 | - Jabber.jids[jid_id] = {jid: room.jid, name: room.name, type: 'groupchat'}; | |
272 | - //FIXME This must check on session if the user is inside the room... | |
273 | - Jabber.insert_or_update_group(room.jid, 'offline'); | |
279 | + contacts_to_insert[jid] = name; | |
280 | + }); | |
281 | + | |
282 | + //TODO Add groups through roster too... | |
283 | + $.ajax({ | |
284 | + url: '/chat/roster_groups', | |
285 | + dataType: 'json', | |
286 | + success: function(data){ | |
287 | + $(data).each(function(index, room){ | |
288 | + profiles.push(getIdentifier(room.jid)); | |
289 | + var jid_id = Jabber.jid_to_id(room.jid); | |
290 | + Jabber.jids[jid_id] = {jid: room.jid, name: room.name, type: 'groupchat'}; | |
291 | + //FIXME This must check on session if the user is inside the room... | |
292 | + groups_to_insert.push(room.jid); | |
293 | + | |
294 | + }); | |
295 | + $.getJSON('/chat/avatars', {profiles: profiles}, function(data) { | |
296 | + for(identifier in data) | |
297 | + Jabber.avatars[identifier] = data[identifier]; | |
298 | + | |
299 | + // Insert contacts | |
300 | + for(contact_jid in contacts_to_insert) | |
301 | + Jabber.insert_or_update_contact(contact_jid, contacts_to_insert[contact_jid]); | |
302 | + | |
303 | + // Insert groups | |
304 | + for (var i = 0; i < groups_to_insert.length; i++) | |
305 | + Jabber.insert_or_update_group(groups_to_insert[i], 'offline'); | |
306 | + | |
307 | + $.getJSON('/chat/recent_conversations', {}, function(data) { | |
308 | + Jabber.conversations_order = data; | |
309 | + sort_conversations(); | |
274 | 310 | }); |
275 | - }, | |
276 | - error: function(data, textStatus, jqXHR){ | |
277 | - console.log(data); | |
278 | - }, | |
279 | - }); | |
280 | - sort_conversations(); | |
281 | - // set up presence handler and send initial presence | |
282 | - Jabber.connection.addHandler(Jabber.on_presence, null, "presence"); | |
283 | - Jabber.send_availability_status(Jabber.presence_status); | |
284 | - load_defaults(); | |
285 | - }, | |
286 | - | |
287 | - // NOTE: cause Noosfero store's rosters in database based on friendship relation between people | |
288 | - // these event never occurs cause jabber service (ejabberd) didn't know when a roster was changed | |
289 | - on_roster_changed: function (iq) { | |
290 | - log('roster changed'); | |
291 | - $(iq).find('item').each(function () { | |
292 | - var sub = $(this).attr('subscription'); | |
293 | - var jid = $(this).attr('jid'); | |
294 | - var name = $(this).attr('name') || jid; | |
295 | - if (sub == 'remove') { | |
296 | - // contact is being removed | |
297 | - Jabber.remove_contact(jid); | |
298 | - } else { | |
299 | - // contact is being added or modified | |
300 | - Jabber.insert_or_update_contact(jid, name); | |
301 | - } | |
302 | - }); | |
303 | - return true; | |
304 | - }, | |
305 | - | |
306 | - parse: function (stanza) { | |
307 | - var result = {}; | |
308 | - if (Strophe.isTagEqual(stanza, 'presence')) { | |
309 | - result.from = $(stanza).attr('from'); | |
310 | - result.type = $(stanza).attr('type'); | |
311 | - if (result.type == 'unavailable') { | |
312 | - result.show = 'offline'; | |
313 | - } else { | |
314 | - var show = $(stanza).find("show").text(); | |
315 | - if (show === "" || show == "chat") { | |
316 | - result.show = 'chat'; | |
317 | - } | |
318 | - else if (show == "dnd" || show == "xa") { | |
319 | - result.show = 'dnd'; | |
320 | - } | |
321 | - else { | |
322 | - result.show = 'away'; | |
323 | - } | |
324 | - } | |
325 | - if ($(stanza).find('x[xmlns="'+ Strophe.NS.MUC_USER +'"]').length > 0) { | |
326 | - result.is_from_room = true; | |
327 | - result.from_user = $(stanza).find('x item').attr('jid'); | |
328 | - if ($(stanza).find('x item').attr('affiliation') == 'owner') { | |
329 | - result.awaiting_configuration = ($(stanza).find('x status').attr('code') == '201'); | |
330 | - } | |
331 | - } | |
311 | + | |
312 | + // set up presence handler and send initial presence | |
313 | + Jabber.connection.addHandler(Jabber.on_presence, null, "presence"); | |
314 | + Jabber.send_availability_status(Jabber.presence_status); | |
315 | + load_defaults(); | |
316 | + }); | |
317 | + }, | |
318 | + error: function(data, textStatus, jqXHR){ | |
319 | + console.log(data); | |
320 | + }, | |
321 | + }); | |
322 | + | |
323 | + }, | |
324 | + | |
325 | + // NOTE: cause Noosfero store's rosters in database based on friendship relation between people | |
326 | + // these event never occurs cause jabber service (ejabberd) didn't know when a roster was changed | |
327 | + on_roster_changed: function (iq) { | |
328 | + log('roster changed'); | |
329 | + $(iq).find('item').each(function () { | |
330 | + var sub = $(this).attr('subscription'); | |
331 | + var jid = $(this).attr('jid'); | |
332 | + var name = $(this).attr('name') || jid; | |
333 | + if (sub == 'remove') { | |
334 | + // contact is being removed | |
335 | + Jabber.remove_contact(jid); | |
336 | + } else { | |
337 | + // contact is being added or modified | |
338 | + Jabber.insert_or_update_contact(jid, name); | |
332 | 339 | } |
333 | - else if (Strophe.isTagEqual(stanza, 'message')) { | |
334 | - result.from = $(stanza).attr('from'); | |
335 | - result.body = $(stanza).find('body').text(); | |
336 | - if ($(stanza).find('error').length > 0) { | |
337 | - result.error = $(stanza).find('error text').text(); | |
338 | - if (!result.error && $(stanza).find('error').find('service-unavailable').length > 0) { | |
339 | - result.error = $user_unavailable_error; | |
340 | - } | |
341 | - } | |
340 | + }); | |
341 | + return true; | |
342 | + }, | |
343 | + | |
344 | + parse: function (stanza) { | |
345 | + var result = {}; | |
346 | + if (Strophe.isTagEqual(stanza, 'presence')) { | |
347 | + result.from = $(stanza).attr('from'); | |
348 | + result.type = $(stanza).attr('type'); | |
349 | + if (result.type == 'unavailable') { | |
350 | + result.show = 'offline'; | |
351 | + } else { | |
352 | + var show = $(stanza).find("show").text(); | |
353 | + if (show === "" || show == "chat") { | |
354 | + result.show = 'chat'; | |
355 | + } | |
356 | + else if (show == "dnd" || show == "xa") { | |
357 | + result.show = 'dnd'; | |
358 | + } | |
359 | + else { | |
360 | + result.show = 'away'; | |
361 | + } | |
342 | 362 | } |
343 | - return result; | |
344 | - }, | |
345 | - | |
346 | - on_presence: function (presence) { | |
347 | - presence = Jabber.parse(presence); | |
348 | - if (presence.type != 'error') { | |
349 | - if (presence.is_from_room) { | |
350 | - log('receiving room presence from ' + presence.from + ' as ' + presence.show); | |
351 | - var name = Strophe.getResourceFromJid(presence.from); | |
352 | - if (presence.from_user) { | |
353 | - Jabber.insert_or_update_occupant(presence.from_user, name, presence.show, presence.from); | |
354 | - } | |
355 | - else { | |
356 | - log('ooops! user jid not found in presence stanza'); | |
357 | - } | |
358 | - if (presence.awaiting_configuration) { | |
359 | - log('sending instant room configuration to ' + Strophe.getBareJidFromJid(presence.from)); | |
360 | - Jabber.connection.sendIQ( | |
361 | - $iq({type: 'set', to: Strophe.getBareJidFromJid(presence.from)}) | |
362 | - .c('query', {xmlns: Strophe.NS.MUC_OWNER}) | |
363 | - .c('x', {xmlns: Strophe.NS.DATA_FORMS, type: 'submit'}) | |
364 | - ); | |
365 | - } | |
366 | - } | |
367 | - else { | |
368 | - log('receiving contact presence from ' + presence.from + ' as ' + presence.show); | |
369 | - var jid = Strophe.getBareJidFromJid(presence.from); | |
370 | - if (jid != Jabber.connection.jid) { | |
371 | - var name = Jabber.name_of(Jabber.jid_to_id(jid)); | |
372 | - Jabber.insert_or_update_contact(jid, name, presence.show); | |
373 | - Jabber.update_chat_title(); | |
374 | - } | |
375 | - else { | |
376 | - // why server sends presence from myself to me? | |
377 | - log('ignoring presence from myself'); | |
378 | - if(presence.show=='offline') { | |
379 | - console.log(Jabber.presence_status); | |
380 | - Jabber.send_availability_status(Jabber.presence_status); | |
381 | - } | |
382 | - } | |
383 | - } | |
363 | + if ($(stanza).find('x[xmlns="'+ Strophe.NS.MUC_USER +'"]').length > 0) { | |
364 | + result.is_from_room = true; | |
365 | + result.from_user = $(stanza).find('x item').attr('jid'); | |
366 | + if ($(stanza).find('x item').attr('affiliation') == 'owner') { | |
367 | + result.awaiting_configuration = ($(stanza).find('x status').attr('code') == '201'); | |
368 | + } | |
384 | 369 | } |
385 | - return true; | |
386 | - }, | |
387 | - | |
388 | - on_private_message: function (message) { | |
389 | - message = Jabber.parse(message); | |
390 | - log('receiving message from ' + message.from); | |
391 | - var jid = Strophe.getBareJidFromJid(message.from); | |
392 | - var jid_id = Jabber.jid_to_id(jid); | |
393 | - var name = Jabber.name_of(jid_id); | |
394 | - create_conversation_tab(name, jid_id); | |
395 | - Jabber.show_message(jid, name, escape_html(message.body), 'other', Strophe.getNodeFromJid(jid)); | |
396 | - notifyMessage(message); | |
397 | - return true; | |
398 | - }, | |
399 | - | |
400 | - on_public_message: function (message) { | |
401 | - message = Jabber.parse(message); | |
402 | - log('receiving message from ' + message.from); | |
403 | - var name = Strophe.getResourceFromJid(message.from); | |
404 | - // is a message from the room itself | |
405 | - if (! name) { | |
406 | - Jabber.show_notice(Jabber.jid_to_id(message.from), message.body); | |
407 | - } | |
408 | - // is a message from another user, not mine | |
409 | - else if ($own_name != name) { | |
410 | - var jid = Jabber.rooms[Jabber.jid_to_id(message.from)][name]; | |
411 | - Jabber.show_message(message.from, name, escape_html(message.body), name, Strophe.getNodeFromJid(jid)); | |
370 | + } | |
371 | + else if (Strophe.isTagEqual(stanza, 'message')) { | |
372 | + result.from = $(stanza).attr('from'); | |
373 | + result.body = $(stanza).find('body').text(); | |
374 | + if ($(stanza).find('error').length > 0) { | |
375 | + result.error = $(stanza).find('error text').text(); | |
376 | + if (!result.error && $(stanza).find('error').find('service-unavailable').length > 0) { | |
377 | + result.error = $user_unavailable_error; | |
378 | + } | |
412 | 379 | } |
413 | - notifyMessage(message); | |
414 | - return true; | |
415 | - }, | |
416 | - | |
417 | - on_message_error: function (message) { | |
418 | - message = Jabber.parse(message) | |
419 | - var jid = Strophe.getBareJidFromJid(message.from); | |
420 | - log('Receiving error message from ' + jid); | |
421 | - var body = Jabber.template('.error-message').replace('%{text}', message.error); | |
422 | - Jabber.show_message(jid, Jabber.name_of(Jabber.jid_to_id(jid)), body, 'other', Strophe.getNodeFromJid(jid)); | |
423 | - return true; | |
424 | - }, | |
425 | - | |
426 | - on_muc_support: function(iq) { | |
427 | - if ($(iq).find('identity[category=conference]').length > 0 && $(iq).find('feature[var="'+ Strophe.NS.MUC +'"]').length > 0) { | |
428 | - var name = $(iq).find('identity[category=conference]').attr('name'); | |
429 | - log('muc support found with identity '+ name); | |
430 | - Jabber.muc_supported = true; | |
380 | + } | |
381 | + return result; | |
382 | + }, | |
383 | + | |
384 | + on_presence: function (presence) { | |
385 | + presence = Jabber.parse(presence); | |
386 | + if (presence.type != 'error') { | |
387 | + if (presence.is_from_room) { | |
388 | + log('receiving room presence from ' + presence.from + ' as ' + presence.show); | |
389 | + var name = Strophe.getResourceFromJid(presence.from); | |
390 | + if (presence.from_user) { | |
391 | + Jabber.insert_or_update_occupant(presence.from_user, name, presence.show, presence.from); | |
392 | + } | |
393 | + else { | |
394 | + log('ooops! user jid not found in presence stanza'); | |
395 | + } | |
396 | + if (presence.awaiting_configuration) { | |
397 | + log('sending instant room configuration to ' + Strophe.getBareJidFromJid(presence.from)); | |
398 | + Jabber.connection.sendIQ( | |
399 | + $iq({type: 'set', to: Strophe.getBareJidFromJid(presence.from)}) | |
400 | + .c('query', {xmlns: Strophe.NS.MUC_OWNER}) | |
401 | + .c('x', {xmlns: Strophe.NS.DATA_FORMS, type: 'submit'}) | |
402 | + ); | |
403 | + } | |
431 | 404 | } |
432 | 405 | else { |
433 | - log('muc support not found'); | |
406 | + log('receiving contact presence from ' + presence.from + ' as ' + presence.show); | |
407 | + var jid = Strophe.getBareJidFromJid(presence.from); | |
408 | + if (jid != Jabber.connection.jid) { | |
409 | + var jid_id = Jabber.jid_to_id(jid); | |
410 | + var name = Jabber.name_of(jid_id); | |
411 | + if(presence.show == 'chat') | |
412 | + Jabber.remove_notice(jid_id); | |
413 | + Jabber.insert_or_update_contact(jid, name, presence.show); | |
414 | + Jabber.update_chat_title(); | |
415 | + } | |
416 | + else { | |
417 | + // why server sends presence from myself to me? | |
418 | + log('ignoring presence from myself'); | |
419 | + if(presence.show=='offline') { | |
420 | + Jabber.send_availability_status(Jabber.presence_status); | |
421 | + } | |
422 | + } | |
434 | 423 | } |
435 | - }, | |
424 | + } | |
425 | + return true; | |
426 | + }, | |
436 | 427 | |
437 | - attach_connection: function(data) { | |
438 | - // create the connection and attach it | |
439 | - Jabber.connection = new Strophe.Connection(Jabber.bosh_service); | |
440 | - Jabber.connection.attach(data.jid, data.sid, data.rid, Jabber.on_connect); | |
428 | + on_private_message: function (message) { | |
429 | + message = Jabber.parse(message); | |
430 | + log('receiving message from ' + message.from); | |
431 | + var jid = Strophe.getBareJidFromJid(message.from); | |
432 | + var jid_id = Jabber.jid_to_id(jid); | |
433 | + var name = Jabber.name_of(jid_id); | |
434 | + create_conversation_tab(name, jid_id); | |
435 | + Jabber.show_message(jid, name, escape_html(message.body), 'other', Strophe.getNodeFromJid(jid)); | |
436 | + renew_conversation_order(jid); | |
437 | + notifyMessage(message); | |
438 | + return true; | |
439 | + }, | |
440 | + | |
441 | + on_public_message: function (message) { | |
442 | + message = Jabber.parse(message); | |
443 | + log('receiving message from ' + message.from); | |
444 | + var name = Strophe.getResourceFromJid(message.from); | |
445 | + // is a message from the room itself | |
446 | + if (! name) { | |
447 | + // FIXME Ignoring message from room for now. | |
448 | + // Jabber.show_notice(Jabber.jid_to_id(message.from), message.body); | |
449 | + } | |
450 | + // is a message from another user, not mine | |
451 | + else if ($own_name != name) { | |
452 | + var jid = Jabber.rooms[Jabber.jid_to_id(message.from)][name]; | |
453 | + Jabber.show_message(message.from, name, escape_html(message.body), name, Strophe.getNodeFromJid(jid)); | |
454 | + renew_conversation_order(jid); | |
455 | + notifyMessage(message); | |
456 | + } | |
457 | + return true; | |
458 | + }, | |
441 | 459 | |
442 | - // handle get roster list (buddy list) | |
443 | - Jabber.connection.sendIQ($iq({type: 'get'}).c('query', {xmlns: Strophe.NS.ROSTER}), Jabber.on_roster); | |
460 | + on_message_error: function (message) { | |
461 | + }, | |
444 | 462 | |
445 | - // handle presence updates in roster list | |
446 | - Jabber.connection.addHandler(Jabber.on_roster_changed, 'jabber:iq:roster', 'iq', 'set'); | |
463 | + on_muc_support: function(iq) { | |
464 | + if ($(iq).find('identity[category=conference]').length > 0 && $(iq).find('feature[var="'+ Strophe.NS.MUC +'"]').length > 0) { | |
465 | + var name = $(iq).find('identity[category=conference]').attr('name'); | |
466 | + log('muc support found with identity '+ name); | |
467 | + Jabber.muc_supported = true; | |
468 | + } | |
469 | + else { | |
470 | + log('muc support not found'); | |
471 | + } | |
472 | + }, | |
447 | 473 | |
448 | - // Handle messages | |
449 | - Jabber.connection.addHandler(Jabber.on_private_message, null, "message", "chat"); | |
474 | + attach_connection: function(data) { | |
475 | + // create the connection and attach it | |
476 | + Jabber.connection = new Strophe.Connection(Jabber.bosh_service); | |
477 | + Jabber.connection.attach(data.jid, data.sid, data.rid, Jabber.on_connect); | |
450 | 478 | |
451 | - // Handle conference messages | |
452 | - Jabber.connection.addHandler(Jabber.on_public_message, null, "message", "groupchat"); | |
479 | + // handle get roster list (buddy list) | |
480 | + Jabber.connection.sendIQ($iq({type: 'get'}).c('query', {xmlns: Strophe.NS.ROSTER}), Jabber.on_roster); | |
453 | 481 | |
454 | - // Handle message errors | |
455 | - Jabber.connection.addHandler(Jabber.on_message_error, null, "message", "error"); | |
482 | + // handle presence updates in roster list | |
483 | + Jabber.connection.addHandler(Jabber.on_roster_changed, 'jabber:iq:roster', 'iq', 'set'); | |
456 | 484 | |
457 | - // discovering MUC support | |
458 | - Jabber.connection.sendIQ( | |
459 | - $iq({type: 'get', from: Jabber.connection.jid, to: Jabber.muc_domain}) | |
460 | - .c('query', {xmlns: Strophe.NS.DISCO_INFO}), | |
461 | - Jabber.on_muc_support | |
462 | - ); | |
485 | + // Handle messages | |
486 | + Jabber.connection.addHandler(Jabber.on_private_message, null, "message", "chat"); | |
463 | 487 | |
464 | - // uncomment for extra debugging | |
465 | - //Strophe.log = function (lvl, msg) { log(msg); }; | |
466 | - }, | |
488 | + // Handle conference messages | |
489 | + Jabber.connection.addHandler(Jabber.on_public_message, null, "message", "groupchat"); | |
467 | 490 | |
468 | - connect: function() { | |
469 | - if (Jabber.connection && Jabber.connection.connected) { | |
470 | - Jabber.send_availability_status(Jabber.presence_status); | |
471 | - } | |
472 | - else { | |
473 | - log('starting XMPP/BOSH session...'); | |
474 | - $('#buddy-list .toolbar').removeClass('small-loading-dark').addClass('small-loading-dark'); | |
475 | - $('.dialog-error').hide(); | |
476 | - $.ajax({ | |
477 | - url: '/chat/start_session', | |
478 | - dataType: 'json', | |
479 | - success: function(data) { | |
480 | - Jabber.attach_connection(data) | |
481 | - }, | |
482 | - error: function(error) { | |
483 | - $('#buddy-list .toolbar').removeClass('small-loading-dark'); | |
484 | - $('#buddy-list .dialog-error') | |
485 | - .html(error.responseText) | |
486 | - .show('highlight') | |
487 | - .unbind('click') | |
488 | - .click(function() { $(this).hide('highlight'); }); | |
489 | - } | |
490 | - }); | |
491 | - } | |
492 | - }, | |
493 | - | |
494 | - deliver_message: function(jid, body) { | |
495 | - var type = Jabber.type_of(Jabber.jid_to_id(jid)); | |
496 | - var message = $msg({to: jid, from: Jabber.connection.jid, "type": type}) | |
497 | - .c('body').t(body).up() | |
498 | - .c('active', {xmlns: Strophe.NS.CHAT_STATES}); | |
499 | - Jabber.connection.send(message); | |
500 | - Jabber.show_message(jid, $own_name, escape_html(body), 'self', Strophe.getNodeFromJid(Jabber.connection.jid)); | |
501 | - move_conversation_to_the_top(jid); | |
502 | - }, | |
503 | - | |
504 | - is_a_room: function(jid_id) { | |
505 | - return Jabber.type_of(jid_id) == 'groupchat'; | |
506 | - }, | |
507 | - | |
508 | - show_notice: function(jid_id, msg) { | |
509 | - var tab_id = '#' + Jabber.conversation_prefix + jid_id; | |
510 | - var notice = $(tab_id).find('.history .notice'); | |
511 | - if (notice.length > 0) | |
512 | - notice.html(msg) | |
513 | - else | |
514 | - $(tab_id).find('.history').append("<span class='notice'>" + msg + "</span>"); | |
515 | - } | |
516 | - }; | |
517 | - | |
518 | - $('#chat-connect').live('click', function() { | |
519 | - Jabber.presence_status = 'chat'; | |
520 | - Jabber.connect(); | |
521 | - }); | |
522 | - | |
523 | - $('#chat-disconnect').click(function() { | |
524 | - disconnect(); | |
525 | - }); | |
526 | - | |
527 | - $('#chat-busy').click(function() { | |
528 | - Jabber.presence_status = 'dnd'; | |
529 | - Jabber.connect(); | |
530 | - }); | |
531 | - | |
532 | - $('#chat-retry').live('click', function() { | |
533 | - Jabber.presence_status = Jabber.presence_status || 'chat'; | |
534 | - Jabber.connect(); | |
535 | - }); | |
536 | - | |
537 | - $('.conversation textarea').live('keydown', function(e) { | |
538 | - if (e.keyCode == 13) { | |
539 | - var jid = $(this).attr('data-to'); | |
540 | - var body = $(this).val(); | |
541 | - body = body.stripScripts(); | |
542 | - save_message(jid, body); | |
543 | - Jabber.deliver_message(jid, body); | |
544 | - $(this).val(''); | |
545 | - return false; | |
546 | - } | |
547 | - }); | |
548 | - | |
549 | - function save_message(jid, body) { | |
550 | - $.post('/chat/save_message', { | |
551 | - to: getIdentifier(jid), | |
552 | - body: body | |
553 | - }); | |
554 | - } | |
491 | + // Handle message errors | |
492 | + Jabber.connection.addHandler(Jabber.on_message_error, null, "message", "error"); | |
555 | 493 | |
556 | - // open new conversation or change to already opened tab | |
557 | - $('#buddy-list .buddies li a').live('click', function() { | |
558 | - var jid_id = $(this).attr('id'); | |
559 | - var name = Jabber.name_of(jid_id); | |
560 | - var conversation = create_conversation_tab(name, jid_id); | |
561 | - | |
562 | - $('.conversation').hide(); | |
563 | - conversation.show(); | |
564 | - count_unread_messages(jid_id, true); | |
565 | - if(conversation.find('.chat-offset-container-0').length == 0) | |
566 | - recent_messages(Jabber.jid_of(jid_id)); | |
567 | - conversation.find('.conversation .input-div textarea.input').focus(); | |
568 | - $.post('/chat/tab', {tab_id: jid_id}); | |
569 | - }); | |
570 | - | |
571 | - // put name into text area when click in one occupant | |
572 | - $('.occupants .occupant-list li a').live('click', function() { | |
573 | - var jid_id = $(this).attr('data-id'); | |
574 | - var name = Jabber.name_of(jid_id); | |
575 | - var val = $('.conversation textarea:visible').val(); | |
576 | - $('.conversation textarea:visible').focus().val(val + name + ', '); | |
577 | - }); | |
494 | + // discovering MUC support | |
495 | + Jabber.connection.sendIQ( | |
496 | + $iq({type: 'get', from: Jabber.connection.jid, to: Jabber.muc_domain}) | |
497 | + .c('query', {xmlns: Strophe.NS.DISCO_INFO}), | |
498 | + Jabber.on_muc_support | |
499 | + ); | |
578 | 500 | |
579 | - $('#chat .conversation .history').live('click', function() { | |
580 | - $('.conversation textarea:visible').focus(); | |
581 | - }); | |
501 | + // uncomment for extra debugging | |
502 | + //Strophe.log = function (lvl, msg) { log(msg); }; | |
503 | + }, | |
582 | 504 | |
583 | - function toggle_chat_window() { | |
584 | - if(jQuery('#conversations .conversation').length == 0) jQuery('.buddies a').first().click(); | |
585 | - jQuery('#chat').toggleClass('opened'); | |
586 | - jQuery('#chat-label').toggleClass('opened'); | |
587 | - } | |
505 | + connect: function() { | |
506 | + if (Notification.permission !== "granted" && Notification.permission !== "denied") { | |
507 | + Notification.requestPermission(function (permission) { | |
508 | + if (!('permission' in Notification)) { | |
509 | + Notification.permission = permission; | |
510 | + } | |
511 | + }); | |
512 | + } | |
588 | 513 | |
589 | - function load_conversation(jid) { | |
590 | - var jid_id = Jabber.jid_to_id(jid); | |
591 | - var name = Jabber.name_of(jid_id); | |
592 | - if (jid) { | |
593 | - if (Strophe.getDomainFromJid(jid) == Jabber.muc_domain) { | |
594 | - if (Jabber.muc_supported) { | |
595 | - log('opening groupchat with ' + jid); | |
596 | - Jabber.jids[jid_id] = {jid: jid, name: name, type: 'groupchat'}; | |
597 | - var conversation = create_conversation_tab(name, jid_id); | |
598 | - Jabber.enter_room(jid); | |
599 | - recent_messages(jid); | |
600 | - return conversation; | |
601 | - } | |
602 | - } | |
603 | - else { | |
604 | - log('opening chat with ' + jid); | |
605 | - Jabber.jids[jid_id] = {jid: jid, name: name, type: 'friendchat'}; | |
606 | - var conversation = create_conversation_tab(name, jid_id); | |
607 | - recent_messages(jid); | |
608 | - return conversation; | |
609 | - } | |
514 | + if (Jabber.connection && Jabber.connection.connected) { | |
515 | + Jabber.send_availability_status(Jabber.presence_status); | |
610 | 516 | } |
611 | - } | |
612 | - | |
613 | - function open_conversation(jid) { | |
614 | - var conversation = load_conversation(jid); | |
615 | - var jid_id = $(this).attr('id'); | |
616 | - | |
617 | - $('.conversation').hide(); | |
618 | - conversation.show(); | |
619 | - count_unread_messages(jid_id, true); | |
620 | - if(conversation.find('.chat-offset-container-0').length == 0) | |
621 | - recent_messages(Jabber.jid_of(jid_id)); | |
622 | - conversation.find('.input').focus(); | |
623 | - $('#chat').addClass('opened'); | |
624 | - $('#chat-label').addClass('opened'); | |
625 | - $.post('/chat/tab', {tab_id: jid_id}); | |
626 | - } | |
627 | - | |
628 | - function create_conversation_tab(title, jid_id) { | |
629 | - var conversation_id = Jabber.conversation_prefix + jid_id; | |
630 | - var conversation = $('#' + conversation_id); | |
631 | - if (conversation.length > 0) { | |
632 | - return conversation; | |
517 | + else { | |
518 | + log('starting XMPP/BOSH session...'); | |
519 | + $('#buddy-list .toolbar').removeClass('small-loading-dark').addClass('small-loading-dark'); | |
520 | + $('.dialog-error').hide(); | |
521 | + $.ajax({ | |
522 | + url: '/chat/start_session', | |
523 | + dataType: 'json', | |
524 | + success: function(data) { | |
525 | + Jabber.attach_connection(data) | |
526 | + }, | |
527 | + error: function(error) { | |
528 | + $('#buddy-list .toolbar').removeClass('small-loading-dark'); | |
529 | + $('#buddy-list .dialog-error') | |
530 | + .html(error.responseText) | |
531 | + .show('highlight') | |
532 | + .unbind('click') | |
533 | + .click(function() { $(this).hide('highlight'); }); | |
534 | + } | |
535 | + }); | |
633 | 536 | } |
537 | + }, | |
634 | 538 | |
635 | - var jid = Jabber.jid_of(jid_id); | |
636 | - var identifier = getIdentifier(jid); | |
539 | + deliver_message: function(jid, body) { | |
540 | + var jid_id = Jabber.jid_to_id(jid); | |
541 | + var type = Jabber.type_of(jid_id); | |
542 | + var presence = Jabber.presence_of(jid_id); | |
543 | + var message = $msg({to: jid, from: Jabber.connection.jid, "type": type}) | |
544 | + .c('body').t(body).up() | |
545 | + .c('active', {xmlns: Strophe.NS.CHAT_STATES}); | |
546 | + Jabber.connection.send(message); | |
547 | + Jabber.show_message(jid, $own_name, escape_html(body), 'self', Strophe.getNodeFromJid(Jabber.connection.jid)); | |
548 | + save_message(jid, body); | |
549 | + renew_conversation_order(jid); | |
550 | + move_conversation_to_the_top(jid); | |
551 | + if (presence == 'offline') | |
552 | + Jabber.show_notice(jid_id, $user_unavailable_error); | |
553 | + }, | |
554 | + | |
555 | + is_a_room: function(jid_id) { | |
556 | + return Jabber.type_of(jid_id) == 'groupchat'; | |
557 | + }, | |
558 | + | |
559 | + show_notice: function(jid_id, msg) { | |
560 | + var tab_id = '#' + Jabber.conversation_prefix + jid_id; | |
561 | + var history = $(tab_id).find('.history'); | |
562 | + var notice = $(tab_id).find('.history .notice'); | |
563 | + if (notice.length > 0) | |
564 | + notice.html(msg) | |
565 | + else | |
566 | + $(tab_id).find('.history').append("<span class='notice'>" + msg + "</span>"); | |
567 | + history.scrollTo({top:'100%', left:'0%'}); | |
568 | + }, | |
569 | + | |
570 | + remove_notice: function(jid_id) { | |
571 | + var tab_id = '#' + Jabber.conversation_prefix + jid_id; | |
572 | + var notice = $(tab_id).find('.history .notice').remove(); | |
573 | + }, | |
574 | + }; | |
637 | 575 | |
638 | - var panel = $('#chat-templates .conversation').clone().appendTo($conversations).attr('id', conversation_id); | |
639 | - panel.find('.chat-target .avatar').replaceWith(getAvatar(identifier)); | |
640 | - panel.find('.chat-target .other-name').html(title); | |
641 | - $('#chat .history').perfectScrollbar(); | |
576 | + $('#chat-connect').live('click', function() { | |
577 | + Jabber.presence_status = 'chat'; | |
578 | + Jabber.connect(); | |
579 | + $('#chat .simplemenu-submenu').hide(); | |
580 | + return false; | |
581 | + }); | |
642 | 582 | |
643 | - panel.find('.history').scroll(function(){ | |
644 | - if($(this).scrollTop() == 0){ | |
645 | - var offset = panel.find('.message p').size(); | |
646 | - recent_messages(jid, offset); | |
647 | - } | |
648 | - }); | |
583 | + $('#chat-disconnect').click(function() { | |
584 | + disconnect(); | |
585 | + $('#chat .simplemenu-submenu').hide(); | |
586 | + return false; | |
587 | + }); | |
588 | + | |
589 | + $('#chat-busy').click(function() { | |
590 | + Jabber.presence_status = 'dnd'; | |
591 | + Jabber.connect(); | |
592 | + $('#chat .simplemenu-submenu').hide(); | |
593 | + return false; | |
594 | + }); | |
649 | 595 | |
650 | - var textarea = panel.find('textarea'); | |
651 | - textarea.attr('name', panel.id); | |
596 | + $('#chat-retry').live('click', function() { | |
597 | + Jabber.presence_status = Jabber.presence_status || 'chat'; | |
598 | + Jabber.connect(); | |
599 | + return false; | |
600 | + }); | |
601 | + | |
602 | + $('.conversation textarea').live('keydown', function(e) { | |
603 | + if (e.keyCode == 13) { | |
604 | + var jid = $(this).attr('data-to'); | |
605 | + var body = $(this).val(); | |
606 | + body = $('<div>'+ body +'</div>').find('script,noscript,style').remove().end().html(); | |
607 | + Jabber.deliver_message(jid, body); | |
608 | + $(this).val(''); | |
609 | + return false; | |
610 | + } | |
611 | + }); | |
652 | 612 | |
653 | - if (Jabber.is_a_room(jid_id)) { | |
654 | - panel.append(Jabber.template('.occupant-list-template')); | |
655 | - panel.find('.history').addClass('room'); | |
656 | - var room_actions = $('#chat-templates .room-action').clone(); | |
657 | - room_actions.data('jid', jid); | |
658 | - panel.find('.history').after(room_actions); | |
659 | - $('#chat .occupants .occupant-list').perfectScrollbar(); | |
613 | + function save_message(jid, body) { | |
614 | + $.post('/chat/save_message', { | |
615 | + to: getIdentifier(jid), | |
616 | + body: body | |
617 | + }, function(data){ | |
618 | + if(data.status > 0){ | |
619 | + console.log(data.message); | |
620 | + if(data.backtrace) console.log(data.backtrace); | |
660 | 621 | } |
661 | - textarea.attr('data-to', jid); | |
662 | - | |
663 | - return panel; | |
664 | - } | |
665 | - | |
666 | - function ensure_scroll(jid, offset) { | |
667 | - var jid_id = Jabber.jid_to_id(jid); | |
668 | - var history = jQuery('#conversation-'+jid_id+' .history'); | |
669 | - // Load more messages if was not enough to show the scroll | |
670 | - if(history.prop('scrollHeight') - history.prop('clientHeight') <= 0){ | |
671 | - var offset = history.find('.message p').size(); | |
672 | - recent_messages(jid, offset); | |
673 | - } | |
674 | - } | |
675 | - | |
676 | - function recent_messages(jid, offset) { | |
677 | - if (Jabber.no_more_messages[jid]) return; | |
678 | - | |
679 | - if(!offset) offset = 0; | |
680 | - start_fetching('.history'); | |
681 | - $.getJSON('/chat/recent_messages', {identifier: getIdentifier(jid), offset: offset}, function(data) { | |
682 | - // Register if no more messages returned and stop trying to load | |
683 | - // more messages in the future. | |
684 | - if(data.length == 0) | |
685 | - Jabber.no_more_messages[jid] = true; | |
686 | - | |
687 | - $.each(data, function(i, message) { | |
688 | - var body = message['body']; | |
689 | - var from = message['from']; | |
690 | - var to = message['to']; | |
691 | - var date = message['created_at']; | |
692 | - var who = from['id']==getCurrentIdentifier() ? 'self' : from['id'] | |
693 | - | |
694 | - Jabber.show_message(jid, from['name'], body, who, from['id'], date, offset); | |
695 | - }); | |
696 | - stop_fetching('.history'); | |
697 | - ensure_scroll(jid, offset); | |
698 | - }); | |
699 | - } | |
700 | - | |
701 | - function move_conversation_to_the_top(jid) { | |
702 | - id = Jabber.jid_to_id(jid); | |
703 | - var link = $('#'+id); | |
704 | - var li = link.closest('li'); | |
705 | - var ul = link.closest('ul'); | |
706 | - ul.prepend(li); | |
707 | - } | |
708 | - | |
709 | - function sort_conversations() { | |
710 | - $.getJSON('/chat/recent_conversations', {}, function(data) { | |
711 | - $.each(data['order'], function(i, identifier) { | |
712 | - move_conversation_to_the_top(identifier+'-'+data['domain']); | |
713 | - }) | |
714 | - }) | |
715 | - } | |
716 | - | |
717 | - function load_defaults() { | |
718 | - $.getJSON('/chat/my_session', {}, function(data) { | |
719 | - $.each(data.rooms, function(i, room_jid) { | |
720 | - $('#chat').trigger('opengroup', room_jid); | |
721 | - }) | |
722 | - | |
723 | - $('#'+data.tab_id).click(); | |
724 | - | |
725 | - if(data.status == 'opened') | |
726 | - toggle_chat_window(); | |
727 | - }) | |
728 | - } | |
729 | - | |
730 | - function count_unread_messages(jid_id, hide) { | |
731 | - var unread = $('.buddies #'+jid_id+ ' .unread-messages'); | |
732 | - if (hide) { | |
733 | - unread.hide(); | |
734 | - unread.siblings('img').show(); | |
735 | - Jabber.unread_messages_of(jid_id, 0); | |
736 | - unread.text(''); | |
622 | + }).fail(function(){ | |
623 | + console.log('500 - Internal server error.') | |
624 | + }); | |
625 | + } | |
626 | + | |
627 | + // open new conversation or change to already opened tab | |
628 | + $('#buddy-list .buddies li a').live('click', function() { | |
629 | + var jid = Jabber.jid_of($(this).attr('id')); | |
630 | + open_conversation(jid); | |
631 | + return false; | |
632 | + }); | |
633 | + | |
634 | + // put name into text area when click in one occupant | |
635 | + $('.occupants .occupant-list li a').live('click', function() { | |
636 | + var jid_id = $(this).attr('data-id'); | |
637 | + var name = Jabber.name_of(jid_id); | |
638 | + var val = $('.conversation textarea:visible').val(); | |
639 | + $('.conversation textarea:visible').focus().val(val + name + ', '); | |
640 | + return false; | |
641 | + }); | |
642 | + | |
643 | + $('#chat .conversation .history').live('click', function() { | |
644 | + $('.conversation textarea:visible').focus(); | |
645 | + }); | |
646 | + | |
647 | + function toggle_chat_window() { | |
648 | + if(jQuery('#conversations .conversation').length == 0) jQuery('.buddies a').first().click(); | |
649 | + jQuery('#chat').toggleClass('opened'); | |
650 | + jQuery('#chat-label').toggleClass('opened'); | |
651 | + } | |
652 | + | |
653 | + function load_conversation(jid) { | |
654 | + var jid_id = Jabber.jid_to_id(jid); | |
655 | + var name = Jabber.name_of(jid_id); | |
656 | + if (jid) { | |
657 | + if (Strophe.getDomainFromJid(jid) == Jabber.muc_domain) { | |
658 | + if (Jabber.muc_supported) { | |
659 | + log('opening groupchat with ' + jid); | |
660 | + Jabber.jids[jid_id] = {jid: jid, name: name, type: 'groupchat'}; | |
661 | + var conversation = create_conversation_tab(name, jid_id); | |
662 | + Jabber.enter_room(jid); | |
663 | + recent_messages(jid, 0, true); | |
664 | + return conversation; | |
665 | + } | |
737 | 666 | } |
738 | 667 | else { |
739 | - unread.siblings('img').hide(); | |
740 | - unread.css('display', 'inline-block'); | |
741 | - var unread_messages = Jabber.unread_messages_of(jid_id) || 0; | |
742 | - Jabber.unread_messages_of(jid_id, ++unread_messages); | |
743 | - unread.text(unread_messages); | |
744 | - } | |
745 | - update_total_unread_messages(); | |
746 | - } | |
747 | - | |
748 | - function update_total_unread_messages() { | |
749 | - var total_unread = $('#openchat .unread-messages'); | |
750 | - var sum = 0; | |
751 | - $('.buddies .unread-messages').each(function() { | |
752 | - sum += Number($(this).text()); | |
753 | - }); | |
754 | - if(sum>0) { | |
755 | - total_unread.text(sum); | |
756 | - } else { | |
757 | - total_unread.text(''); | |
668 | + log('opening chat with ' + jid); | |
669 | + Jabber.jids[jid_id] = {jid: jid, name: name, type: 'chat'}; | |
670 | + var conversation = create_conversation_tab(name, jid_id); | |
671 | + recent_messages(jid, 0, true); | |
672 | + return conversation; | |
758 | 673 | } |
759 | - } | |
674 | + } | |
675 | + } | |
676 | + | |
677 | + function open_conversation(jid) { | |
678 | + var conversation = load_conversation(jid); | |
679 | + var jid_id = Jabber.jid_to_id(jid); | |
680 | + | |
681 | + $('.conversation').hide(); | |
682 | + conversation.show(); | |
683 | + conversation.find('.input').focus(); | |
684 | + $('#chat').addClass('opened'); | |
685 | + $('#chat-label').addClass('opened'); | |
686 | + $.post('/chat/tab', {tab_id: jid_id}); | |
687 | + } | |
688 | + | |
689 | + function create_conversation_tab(title, jid_id) { | |
690 | + var conversation_id = Jabber.conversation_prefix + jid_id; | |
691 | + var conversation = $('#' + conversation_id); | |
692 | + if (conversation.length > 0) { | |
693 | + return conversation; | |
694 | + } | |
695 | + | |
696 | + var jid = Jabber.jid_of(jid_id); | |
697 | + var identifier = getIdentifier(jid); | |
760 | 698 | |
761 | - var $conversations = $('#chat-window #conversations'); | |
699 | + var panel = $('#chat-templates .conversation').clone().appendTo($conversations).attr('id', conversation_id); | |
700 | + panel.find('.chat-target .avatar').replaceWith(getAvatar(identifier)); | |
701 | + panel.find('.chat-target .other-name').html(title); | |
702 | + $('#chat .history').perfectScrollbar(); | |
762 | 703 | |
763 | - function log(msg) { | |
764 | - if(Jabber.debug && window.console && window.console.log) { | |
765 | - var time = new Date(); | |
766 | - window.console.log('['+ time.toTimeString() +'] ' + msg); | |
704 | + panel.find('.history').scroll(function(){ | |
705 | + if($(this).scrollTop() == 0){ | |
706 | + var offset = panel.find('.message p').size(); | |
707 | + recent_messages(jid, offset); | |
767 | 708 | } |
768 | - } | |
709 | + }); | |
710 | + | |
711 | + var textarea = panel.find('textarea'); | |
712 | + textarea.attr('name', panel.id); | |
713 | + | |
714 | + if (Jabber.is_a_room(jid_id)) { | |
715 | + panel.append(Jabber.template('.occupant-list-template')); | |
716 | + panel.find('.history').addClass('room'); | |
717 | + var room_actions = $('#chat-templates .room-action').clone(); | |
718 | + room_actions.data('jid', jid); | |
719 | + panel.find('.history').after(room_actions); | |
720 | + $('#chat .occupants .occupant-list').perfectScrollbar(); | |
721 | + } | |
722 | + textarea.attr('data-to', jid); | |
723 | + | |
724 | + return panel; | |
725 | + } | |
726 | + | |
727 | + function ensure_scroll(jid, offset) { | |
728 | + var jid_id = Jabber.jid_to_id(jid); | |
729 | + var history = jQuery('#conversation-'+jid_id+' .history'); | |
730 | + // Load more messages if was not enough to show the scroll | |
731 | + if(history.prop('scrollHeight') - history.prop('clientHeight') <= 0){ | |
732 | + var offset = history.find('.message p').size(); | |
733 | + recent_messages(jid, offset); | |
734 | + } | |
735 | + } | |
736 | + | |
737 | + function recent_messages(jid, offset, clear_unread) { | |
738 | + if (Jabber.no_more_messages[jid]) return; | |
739 | + | |
740 | + if(!offset) offset = 0; | |
741 | + start_fetching('.history'); | |
742 | + $.getJSON('/chat/recent_messages', {identifier: getIdentifier(jid), offset: offset}, function(data) { | |
743 | + // Register if no more messages returned and stop trying to load | |
744 | + // more messages in the future. | |
745 | + if(data.length == 0) | |
746 | + Jabber.no_more_messages[jid] = true; | |
747 | + | |
748 | + $.each(data, function(i, message) { | |
749 | + var body = message['body']; | |
750 | + var from = message['from']; | |
751 | + var to = message['to']; | |
752 | + var date = message['created_at']; | |
753 | + var who = from['id']==getCurrentIdentifier() ? 'self' : from['id'] | |
754 | + | |
755 | + Jabber.show_message(jid, from['name'], body, who, from['id'], date, offset); | |
756 | + }); | |
757 | + stop_fetching('.history'); | |
758 | + ensure_scroll(jid, offset); | |
769 | 759 | |
770 | - function escape_html(body) { | |
771 | - return body | |
772 | - .replace(/&/g, '&') | |
773 | - .replace(/</g, '<') | |
774 | - .replace(/>/g, '>'); | |
775 | - } | |
760 | + if(clear_unread){ | |
761 | + var jid_id = Jabber.jid_to_id(jid); | |
762 | + count_unread_messages(jid_id, true); | |
763 | + } | |
764 | + }); | |
765 | + } | |
766 | + | |
767 | + function move_conversation_to_the_top(jid) { | |
768 | + id = Jabber.jid_to_id(jid); | |
769 | + var link = $('#'+id); | |
770 | + var li = link.closest('li'); | |
771 | + var ul = link.closest('ul'); | |
772 | + ul.prepend(li); | |
773 | + } | |
774 | + | |
775 | + function renew_conversation_order(jid){ | |
776 | + var i = Jabber.conversations_order.indexOf(jid); | |
777 | + // Remove element from the list | |
778 | + if(i >= 0) { | |
779 | + var elem = Jabber.conversations_order[i]; | |
780 | + var a = Jabber.conversations_order.slice(0,i); | |
781 | + var b = Jabber.conversations_order.slice(i+1, Jabber.conversations_order.length); | |
782 | + Jabber.conversations_order = a.concat(b); | |
783 | + } else | |
784 | + var elem = jid; | |
785 | + | |
786 | + Jabber.conversations_order = Jabber.conversations_order.concat(elem); | |
787 | + } | |
788 | + | |
789 | + function sort_conversations() { | |
790 | + if(Jabber.conversations_order){ | |
791 | + for (var i = 0; i < Jabber.conversations_order.length; i++) | |
792 | + move_conversation_to_the_top(Jabber.conversations_order[i]); | |
793 | + } | |
794 | + } | |
795 | + | |
796 | + function load_defaults() { | |
797 | + $.getJSON('/chat/my_session', {}, function(data) { | |
798 | + $.each(data.rooms, function(i, room_jid) { | |
799 | + load_conversation(room_jid); | |
800 | + }) | |
801 | + | |
802 | + $('#'+data.tab_id).click(); | |
803 | + | |
804 | + if(data.status == 'opened') | |
805 | + toggle_chat_window(); | |
806 | + }) | |
807 | + } | |
808 | + | |
809 | + function count_unread_messages(jid_id, hide) { | |
810 | + var unread = $('.buddies #'+jid_id+ ' .unread-messages'); | |
811 | + if (hide) { | |
812 | + unread.hide(); | |
813 | + unread.siblings('img').show(); | |
814 | + Jabber.unread_messages_of(jid_id, 0); | |
815 | + unread.text(''); | |
816 | + } | |
817 | + else { | |
818 | + unread.siblings('img').hide(); | |
819 | + unread.css('display', 'inline-block'); | |
820 | + var unread_messages = Jabber.unread_messages_of(jid_id) || 0; | |
821 | + Jabber.unread_messages_of(jid_id, ++unread_messages); | |
822 | + unread.text(unread_messages); | |
823 | + } | |
824 | + update_total_unread_messages(); | |
825 | + } | |
826 | + | |
827 | + function update_total_unread_messages() { | |
828 | + var total_unread = $('#unread-messages'); | |
829 | + var sum = 0; | |
830 | + $('#chat .unread-messages').each(function() { | |
831 | + sum += Number($(this).text()); | |
832 | + }); | |
833 | + if(sum>0) { | |
834 | + total_unread.text(sum); | |
835 | + } else { | |
836 | + total_unread.text(''); | |
837 | + } | |
838 | + } | |
776 | 839 | |
777 | - function getCurrentIdentifier() { | |
778 | - return getIdentifier(Jabber.connection.jid); | |
779 | - } | |
840 | + var $conversations = $('#chat-window #conversations'); | |
780 | 841 | |
781 | - function getIdentifier(jid) { | |
782 | - return Strophe.getNodeFromJid(jid); | |
783 | - } | |
842 | + function log(msg) { | |
843 | + if(Jabber.debug && window.console && window.console.log) { | |
844 | + var time = new Date(); | |
845 | + window.console.log('['+ time.toTimeString() +'] ' + msg); | |
846 | + } | |
847 | + } | |
848 | + | |
849 | + function escape_html(body) { | |
850 | + return body | |
851 | + .replace(/&/g, '&') | |
852 | + .replace(/</g, '<') | |
853 | + .replace(/>/g, '>'); | |
854 | + } | |
855 | + | |
856 | + function getCurrentIdentifier() { | |
857 | + return getIdentifier(Jabber.connection.jid); | |
858 | + } | |
859 | + | |
860 | + function getIdentifier(jid) { | |
861 | + return Strophe.getNodeFromJid(jid); | |
862 | + } | |
863 | + | |
864 | + function getMyAvatar() { | |
865 | + return getAvatar(getCurrentIdentifier()); | |
866 | + } | |
867 | + | |
868 | + function getAvatar(identifier) { | |
869 | + if(Jabber.avatars[identifier]) | |
870 | + var src = Jabber.avatars[identifier]; | |
871 | + else | |
872 | + var src = "/chat/avatar/"+identifier; | |
873 | + | |
874 | + return '<img class="avatar" src="' + src + '">'; | |
875 | + } | |
876 | + | |
877 | + function disconnect() { | |
878 | + log('disconnect'); | |
879 | + if (Jabber.connection && Jabber.connection.connected) { | |
880 | + Jabber.connection.disconnect(); | |
881 | + } | |
882 | + Jabber.presence_status = 'offline'; | |
883 | + Jabber.show_status('offline'); | |
884 | + } | |
885 | + | |
886 | + function notifyMessage(message) { | |
887 | + var jid = Strophe.getBareJidFromJid(message.from); | |
888 | + var jid_id = Jabber.jid_to_id(jid); | |
889 | + var name = Jabber.name_of(jid_id); | |
890 | + var identifier = Strophe.getNodeFromJid(jid); | |
891 | + var avatar = "/chat/avatar/"+identifier | |
892 | + if(!$('#chat').hasClass('opened') || window.isHidden() || !Jabber.window_visibility) { | |
893 | + var options = {body: message.body, icon: avatar, tag: jid_id}; | |
894 | + $(notifyMe(name, options)).on('click', function(){ | |
895 | + open_conversation(jid); | |
896 | + }); | |
897 | + Jabber.notification_sound.play(); | |
898 | + } | |
899 | + } | |
784 | 900 | |
785 | - function getMyAvatar() { | |
786 | - return getAvatar(getCurrentIdentifier()); | |
787 | - } | |
901 | + $('.title-bar a').click(function() { | |
902 | + $(this).parents('.status-group').find('.buddies').toggle('fast'); | |
903 | + return false; | |
904 | + }); | |
905 | + $('#chat').on('click', '.occupants a', function() { | |
906 | + $(this).siblings('.occupant-list').toggle('fast'); | |
907 | + $(this).toggleClass('up'); | |
908 | + return false; | |
909 | + }); | |
788 | 910 | |
789 | - function getAvatar(identifier) { | |
790 | - return '<img class="avatar" src="/chat/avatar/' + identifier + '">'; | |
791 | - } | |
911 | + //restore connection if user was connected | |
912 | + if($presence=='' || $presence == 'chat') { | |
913 | + $('#chat-connect').trigger('click'); | |
914 | + } else if($presence == 'dnd') { | |
915 | + $('#chat-busy').trigger('click'); | |
916 | + } | |
792 | 917 | |
793 | - function disconnect() { | |
794 | - log('disconnect'); | |
795 | - if (Jabber.connection && Jabber.connection.connected) { | |
796 | - Jabber.connection.disconnect(); | |
797 | - } | |
798 | - Jabber.presence_status = 'offline'; | |
799 | - Jabber.show_status('offline'); | |
800 | - } | |
801 | - | |
802 | - function notifyMessage(message) { | |
803 | - var jid = Strophe.getBareJidFromJid(message.from); | |
804 | - var jid_id = Jabber.jid_to_id(jid); | |
805 | - var name = Jabber.name_of(jid_id); | |
806 | - var identifier = Strophe.getNodeFromJid(jid); | |
807 | - var avatar = "/chat/avatar/"+identifier | |
808 | - if(!$('#chat').hasClass('opened') || window.isHidden()) { | |
809 | - var options = {body: message.body, icon: avatar, tag: jid_id}; | |
810 | - console.log('Notify '+name); | |
811 | - $(notifyMe(name, options)).on('click', function(){ | |
812 | - open_conversation(jid); | |
813 | - }); | |
814 | - $.sound.play('/sounds/receive.wav'); | |
815 | - } | |
816 | - } | |
817 | - | |
818 | - $('.title-bar a').click(function() { | |
819 | - $(this).parents('.status-group').find('.buddies').toggle('fast'); | |
820 | - }); | |
821 | - $('#chat').on('click', '.occupants a', function() { | |
822 | - $(this).siblings('.occupant-list').toggle('fast'); | |
823 | - $(this).toggleClass('up'); | |
824 | - }); | |
825 | - | |
826 | - //restore connection if user was connected | |
827 | - if($presence=='' || $presence == 'chat') { | |
828 | - $('#chat-connect').trigger('click'); | |
829 | - } else if($presence == 'dnd') { | |
830 | - $('#chat-busy').trigger('click'); | |
831 | - } | |
832 | - | |
833 | - $('#chat #buddy-list .buddies').perfectScrollbar(); | |
918 | + $('#chat #buddy-list .buddies').perfectScrollbar(); | |
834 | 919 | |
835 | 920 | // custom css expression for a case-insensitive contains() |
836 | 921 | jQuery.expr[':'].Contains = function(a,i,m){ |
837 | - return (a.textContent || a.innerText || "").toUpperCase().indexOf(m[3].toUpperCase())>=0; | |
922 | + return (a.textContent || a.innerText || "").toUpperCase().indexOf(m[3].toUpperCase())>=0; | |
838 | 923 | }; |
839 | 924 | |
840 | 925 | $('#chat .search').change( function () { |
... | ... | @@ -856,6 +941,7 @@ jQuery(function($) { |
856 | 941 | |
857 | 942 | $('#chat .buddies a').live('click', function(){ |
858 | 943 | $('#chat .search').val('').change(); |
944 | + return false; | |
859 | 945 | }); |
860 | 946 | |
861 | 947 | $('#chat-label').click(function(){ |
... | ... | @@ -871,6 +957,14 @@ jQuery(function($) { |
871 | 957 | $('.room-action.leave').live('click', function(){ |
872 | 958 | var jid = $(this).data('jid'); |
873 | 959 | Jabber.leave_room(jid); |
960 | + return false; | |
961 | + }); | |
962 | + | |
963 | + $('.open-conversation').live('click', function(){ | |
964 | + open_conversation($(this).data('jid')); | |
965 | + return false; | |
874 | 966 | }); |
875 | 967 | |
968 | + window.onfocus = function() {Jabber.window_visibility = true}; | |
969 | + window.onblur = function() {Jabber.window_visibility = false}; | |
876 | 970 | }); | ... | ... |
public/stylesheets/chat.css
... | ... | @@ -201,6 +201,21 @@ |
201 | 201 | bottom: 132px; |
202 | 202 | } |
203 | 203 | |
204 | +#chat-label.opened #unread-messages, | |
205 | +#unread-messages:empty { | |
206 | + display: none; | |
207 | +} | |
208 | + | |
209 | +#unread-messages { | |
210 | + padding: 3px 5px; | |
211 | + background-color: #F57900; | |
212 | + border-radius: 5px; | |
213 | + margin-top: -10px; | |
214 | + margin-left: -30px; | |
215 | + position: absolute; | |
216 | + z-index: 1; | |
217 | +} | |
218 | + | |
204 | 219 | #chat .unread-messages { |
205 | 220 | height: 32px; |
206 | 221 | line-height: 32px; | ... | ... |
test/functional/chat_controller_test.rb
... | ... | @@ -95,6 +95,54 @@ class ChatControllerTest < ActionController::TestCase |
95 | 95 | assert_not_equal chat_status_at, @person.user.chat_status_at |
96 | 96 | end |
97 | 97 | |
98 | + should 'forbid to register a message without to' do | |
99 | + @controller.stubs(:current_user).returns(@person.user) | |
100 | + @request.stubs(:xhr?).returns(true) | |
101 | + | |
102 | + post :save_message, {:body =>'Hello!'} | |
103 | + assert ActiveSupport::JSON.decode(@response.body)['status'] == 1 | |
104 | + end | |
105 | + | |
106 | + should 'forbid to register a message without body' do | |
107 | + @controller.stubs(:current_user).returns(@person.user) | |
108 | + @request.stubs(:xhr?).returns(true) | |
109 | + | |
110 | + post :save_message, {:to =>'mary'} | |
111 | + assert ActiveSupport::JSON.decode(@response.body)['status'] == 1 | |
112 | + end | |
113 | + | |
114 | + should 'forbid user to register a message to a stranger' do | |
115 | + @controller.stubs(:current_user).returns(@person.user) | |
116 | + @request.stubs(:xhr?).returns(true) | |
117 | + | |
118 | + post :save_message, {:to =>'random', :body => 'Hello, stranger!'} | |
119 | + assert ActiveSupport::JSON.decode(@response.body)['status'] == 2 | |
120 | + end | |
121 | + | |
122 | + should 'register a message to a friend' do | |
123 | + @controller.stubs(:current_user).returns(@person.user) | |
124 | + friend = create_user('friend').person | |
125 | + @person.add_friend friend | |
126 | + @request.stubs(:xhr?).returns(true) | |
127 | + | |
128 | + assert_difference 'ChatMessage.count', 1 do | |
129 | + post :save_message, {:to => friend.identifier, :body => 'Hey! How is it going?'} | |
130 | + assert ActiveSupport::JSON.decode(@response.body)['status'] == 0 | |
131 | + end | |
132 | + end | |
133 | + | |
134 | + should 'register a message to a group' do | |
135 | + @controller.stubs(:current_user).returns(@person.user) | |
136 | + group = fast_create(Organization) | |
137 | + group.add_member(@person) | |
138 | + @request.stubs(:xhr?).returns(true) | |
139 | + | |
140 | + assert_difference 'ChatMessage.count', 1 do | |
141 | + post :save_message, {:to => group.identifier, :body => 'Hey! How is it going?'} | |
142 | + assert ActiveSupport::JSON.decode(@response.body)['status'] == 0 | |
143 | + end | |
144 | + end | |
145 | + | |
98 | 146 | should 'toggle chat status' do |
99 | 147 | login_as 'testuser' |
100 | 148 | ... | ... |
... | ... | @@ -0,0 +1,9 @@ |
1 | +require 'test_helper' | |
2 | + | |
3 | +class ChatMessageTest < ActiveSupport::TestCase | |
4 | + should 'create message' do | |
5 | + assert_difference 'ChatMessage.count', 1 do | |
6 | + ChatMessage.create!(:from => fast_create(Person), :to => fast_create(Person), :body => 'Hey! How are you?' ) | |
7 | + end | |
8 | + end | |
9 | +end | ... | ... |
-
mentioned in commit 0725f74d54984d10514911602276c4401f54cae4