social_stream-presence 0.8.4 → 0.8.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. data/app/assets/javascripts/chat_interface_manager.js.erb +42 -132
  2. data/app/assets/javascripts/chat_persistence.js +84 -70
  3. data/app/assets/javascripts/chat_utilities.js +10 -33
  4. data/app/assets/javascripts/chat_window_manager.js +275 -217
  5. data/app/assets/javascripts/jquery.ui.chatbox.sstreampresence.js +9 -2
  6. data/app/assets/javascripts/notifications.js +191 -0
  7. data/app/assets/javascripts/social_stream-presence.js +1 -0
  8. data/app/assets/javascripts/videochat.js.erb +4 -24
  9. data/app/assets/javascripts/xmpp_client_management.js.erb +369 -47
  10. data/app/assets/stylesheets/chat.css.scss +1 -1
  11. data/app/views/chat/_contacts.html.erb +5 -5
  12. data/app/views/chat/_index.html.erb +10 -2
  13. data/config/locales/en.yml +9 -1
  14. data/config/locales/es.yml +9 -1
  15. data/ejabberd/ejabberd_files.zip +0 -0
  16. data/ejabberd/ejabberd_scripts/emanagement +132 -2
  17. data/ejabberd/installer.sh +1 -0
  18. data/ejabberd/mod_muc_admin/mod_muc_admin.beam +0 -0
  19. data/ejabberd/mod_muc_admin/mod_muc_admin.erl +871 -0
  20. data/ejabberd/mod_sspresence/mod_sspresence.beam +0 -0
  21. data/lib/social_stream-presence.rb +1 -1
  22. data/lib/social_stream/presence/engine.rb +6 -0
  23. data/lib/social_stream/presence/models/buddy_manager.rb +32 -26
  24. data/lib/social_stream/presence/models/group_manager.rb +51 -0
  25. data/lib/social_stream/presence/version.rb +1 -1
  26. data/lib/social_stream/presence/xmpp_server_order.rb +84 -10
  27. data/lib/tasks/presence/synchronize.rake +15 -0
  28. data/vendor/assets/javascripts/strophe.muc.js +934 -0
  29. metadata +9 -24
@@ -23,6 +23,7 @@
23
23
  offset: 0, // relative to right edge of the browser window
24
24
  width: 230, // width of the chatbox
25
25
  height: 400, // height of the chatbox
26
+ groupBox: false, //if a group Chatbox?
26
27
  video: 0, // height of the videoBox
27
28
  messageSent: function(id, user, msg){
28
29
  // override this
@@ -222,8 +223,7 @@
222
223
  'ui-chatbox-notify'
223
224
  )
224
225
  .click(function(event) {
225
- // anything?
226
- self.uiChatboxNotify.fadeOut();
226
+ onClickChatNotification(self.uiChatboxNotify)
227
227
  })
228
228
  .appendTo(uiChatboxContent),
229
229
 
@@ -328,6 +328,9 @@
328
328
  break;
329
329
  case "video":
330
330
  this._setVideo(value);
331
+ break;
332
+ case "groupBox":
333
+ this._setGroupBox(value);
331
334
  break;
332
335
  }
333
336
  }
@@ -346,6 +349,10 @@
346
349
  this.uiChatboxLog.height(height + "px");
347
350
  },
348
351
 
352
+ _setGroupBox: function(groupBox) {
353
+ this.uiChatboxLog.groupBox(groupBox);
354
+ },
355
+
349
356
  _setVideo: function(videoHeight) {
350
357
  this.uiVideobox.height(videoHeight + "px");
351
358
  if (videoHeight==0){
@@ -0,0 +1,191 @@
1
+ ////////////////////
2
+ //Chat Boxes Notifications
3
+ ////////////////////
4
+
5
+ function fadeInChatNotification(notification){
6
+ if(notification!=null){
7
+ notification.css("display","block");
8
+ notification.css("visibility","visible");
9
+ notification.fadeIn();
10
+ }
11
+ }
12
+
13
+ function showChatNotification(notification,type,msg){
14
+ notification.html("<p notification_type=\"" + type + "\" class=\"ui-chatbox-notify-text\">" + msg + "</p>");
15
+ fadeInChatNotification(notification);
16
+ }
17
+
18
+ function showChatNotificationForSlug(slug,type,msg){
19
+ var notification = $("#" + slug).parent().find("div.ui-chatbox-notify");
20
+ if(notification.length==1){
21
+ showChatNotification(notification,type,msg);
22
+ }
23
+ }
24
+
25
+ function showOfflineChatNotificationForSlug(slug){
26
+ var msg = I18n.t("chat.notify.guestOffline", {name: getNameFromSlug(slug)});
27
+ showChatNotificationForSlug(slug,"guestOffline",msg);
28
+ }
29
+
30
+ function showVideoChatNotificationForSlug(slug,msg){
31
+ showChatNotificationForSlug(slug,"videochat",msg);
32
+ }
33
+
34
+ function showVideoChatNotificationForSlugClientIssue(slug){
35
+ var msg = I18n.t("chat.notify.videochat.clientIssue", {name: getNameFromSlug(slug)});
36
+ showVideoChatNotificationForSlug(slug,msg);
37
+ }
38
+
39
+ function showVideoChatNotificationForSlugClientOffline(slug){
40
+ var msg = I18n.t("chat.notify.videochat.offline", {name: getNameFromSlug(slug)});
41
+ showVideoChatNotificationForSlug(slug,msg);
42
+ }
43
+
44
+ function fadeOutChatNotification(notification){
45
+ if(notification!=null){
46
+ notification.fadeOut();
47
+ notification.css("display","none");
48
+ notification.css("visibility","hidden");
49
+ }
50
+ }
51
+
52
+ function hideChatNotificationForSlug(slug){
53
+ var notification = getChatNotificationForSlug(slug);
54
+ fadeOutChatNotification(notification);
55
+ }
56
+
57
+ function updateNotificationsAfterUserDisconnect(){
58
+ var notification = $("div.ui-chatbox-notify");
59
+ var msg = I18n.t('chat.notify.offline');
60
+ showChatNotification(notification,"userOffline",msg);
61
+ }
62
+
63
+ function hideAllNotifications(){
64
+ var notification = $("div.ui-chatbox-notify");
65
+ fadeOutChatNotification(notification);
66
+ }
67
+
68
+ function updateAllNotifications(){
69
+ hideAllNotifications();
70
+ if(disconnectionFlag){
71
+ updateNotificationsAfterUserDisconnect();
72
+ } else {
73
+ //Notification for offline contacts
74
+ $.each(getAllDisconnectedSlugsWithChatBoxes(), function(index, value) {
75
+ if(!isSlugGroup(value)){
76
+ showOfflineChatNotificationForSlug(value)
77
+ }
78
+ });
79
+ }
80
+ }
81
+
82
+ function getChatNotificationForSlug(slug){
83
+ var chatBox = getChatBoxForSlug(slug)
84
+ if(chatBox!=null){
85
+ var notification = chatBox.parent().find("div.ui-chatbox-notify");
86
+ if (notification.length == 1) {
87
+ return notification;
88
+ }
89
+ }
90
+ return null;
91
+ }
92
+
93
+ function getNotificationType(notification){
94
+ return $(notification).find("p").attr("notification_type");
95
+ }
96
+
97
+ function addTextToNotification(notification,txt,type,name){
98
+ var new_p = document.createElement('p')
99
+ $(new_p).attr("class","ui-chatbox-notify-text")
100
+ $(new_p).attr("notification_type",type)
101
+ $(new_p).html(txt)
102
+ if(name!=null){
103
+ $(new_p).attr("name",name)
104
+ }
105
+ $(notification).append(new_p)
106
+ fadeInChatNotification(notification)
107
+ }
108
+
109
+ function removeTextFromNotification(notification,name){
110
+ var p = $(notification).find("p.ui-chatbox-notify-text[name=" + name + "]")
111
+ if (p!=null){
112
+ p.remove()
113
+ var empty = ($(notification).find("p").length==0)
114
+ if (empty){
115
+ fadeOutChatNotification(notification)
116
+ }
117
+ }
118
+ }
119
+
120
+ function removeAllTextsFromNotification(notification){
121
+ var p = $(notification).find("p.ui-chatbox-notify-text")
122
+ if (p!=null){
123
+ p.remove()
124
+ var empty = ($(notification).find("p").length==0)
125
+ if (empty){
126
+ fadeOutChatNotification(notification)
127
+ }
128
+ }
129
+ }
130
+
131
+ function addTextToNotificationForSlug(slug,txt,type,name){
132
+ var notification = getChatNotificationForSlug(slug);
133
+ if(notification!=null){
134
+ addTextToNotification(notification,txt,type,name)
135
+ }
136
+ }
137
+
138
+ function removeTextFromNotificationForSlug(slug,name){
139
+ var notification = getChatNotificationForSlug(slug);
140
+ if(notification!=null){
141
+ removeTextFromNotification(notification,name)
142
+ }
143
+ }
144
+
145
+ function removeAllTextsFromNotificationForSlug(slug){
146
+ var notification = getChatNotificationForSlug(slug);
147
+ if(notification!=null){
148
+ removeAllTextsFromNotification(notification)
149
+ }
150
+ }
151
+
152
+
153
+ ////////////////////////
154
+ // Group notifications
155
+ ///////////////////////
156
+
157
+ function addNickToNotificationInGroup(roomName,nick){
158
+ if(isSlugGroup(roomName)){
159
+ addTextToNotificationForSlug(roomName,nick,"roomNotification",nick)
160
+ }
161
+ }
162
+
163
+ function removeNickFromNotificationInGroup(roomName,nick){
164
+ if(isSlugGroup(roomName)){
165
+ removeTextFromNotificationForSlug(roomName,nick)
166
+ }
167
+ }
168
+
169
+ function initialNotificationInGroup(roomName,msg){
170
+ removeAllTextsFromNotificationForSlug(roomName);
171
+ addTextToNotificationForSlug(roomName,msg,"roomNotification","Initial_Notification")
172
+ }
173
+
174
+ function changeInitialNotificationInGroup(roomName,msg){
175
+ var notification = getChatNotificationForSlug(roomName);
176
+ if(notification!=null){
177
+ $(notification).find("p.ui-chatbox-notify-text[name=" + "Initial_Notification" + "]").html(msg)
178
+ }
179
+ }
180
+
181
+
182
+ ////////////////////
183
+ //Events
184
+ ////////////////////
185
+
186
+ function onClickChatNotification(notification){
187
+ if (getNotificationType(notification)=="roomNotification"){
188
+ return;
189
+ }
190
+ fadeOutChatNotification(notification)
191
+ }
@@ -1,5 +1,6 @@
1
1
  //= require jquery
2
2
  //= require strophe
3
+ //= require strophe.muc
3
4
  //= require jquery.tools.tooltip
4
5
  //= require jquery.ui.chatbox.sstreampresence
5
6
  //= require jquery.flexselect.sstreampresence
@@ -3,7 +3,6 @@
3
3
  ////////////////////
4
4
  var opentok_apiKey = '<%=SocialStream::Presence.opentok_api_key%>';
5
5
 
6
-
7
6
  //Correspondence between slugs and session ids
8
7
  var slugOfSession = new Array();
9
8
  //slugOfSession['session_id'] = "slug";
@@ -11,7 +10,6 @@ var slugOfSession = new Array();
11
10
  ////////////////////
12
11
  //Videochat button actions
13
12
  ////////////////////
14
-
15
13
  function clickVideoChatButton(slug){
16
14
  var videoBoxVisibility = toggleVideoBoxForSlug(slug);
17
15
 
@@ -28,7 +26,6 @@ function closeVideoChatWindow(slug){
28
26
  return;
29
27
  }
30
28
 
31
-
32
29
  //Single variable for all slugs.
33
30
  var reconnectAttemptsVideo = 1;
34
31
 
@@ -87,7 +84,6 @@ function openVideoChatWindow(slug){
87
84
  }
88
85
 
89
86
 
90
-
91
87
  ////////////////////
92
88
  //Session establishment
93
89
  ////////////////////
@@ -134,7 +130,6 @@ function requestSessionIDAndTokenForVideoChat(slug){
134
130
  });
135
131
  }
136
132
 
137
-
138
133
  //VideoChat Session: Step 3
139
134
  function sendVideoChatRequestToUser(slug){
140
135
  contactsInfo[slug].videoChatStatus="waiting";
@@ -202,7 +197,6 @@ function closeVideoSession(slug){
202
197
  /////////////
203
198
  // Videochat interface functions
204
199
  ////////////
205
-
206
200
  function clientInfoReceivedTrigger(slug){
207
201
  //Check for videochat request
208
202
  if ((slug in contactsInfo)&&(contactsInfo[slug].videoChatStatus="negotiating")){
@@ -214,7 +208,6 @@ function showNotificationOnVideoBox(slug,msg){
214
208
  setVideoBoxContent(slug,"<p class=\"video-info\"> " + msg +" </p>");
215
209
  }
216
210
 
217
-
218
211
  function updateInterfaceAfterVideoRequestReceived(slug){
219
212
 
220
213
  if (contactsInfo[slug].videoChatStatus!="disconnected"){
@@ -224,13 +217,8 @@ function updateInterfaceAfterVideoRequestReceived(slug){
224
217
  contactsInfo[slug].videoChatStatus="pending";
225
218
  }
226
219
 
227
- var jid = slug+"@"+contactsInfo[slug].domain
228
-
229
- //Show chatbox
230
- if (createChatBox(slug, getNameFromSlug(slug), jid, user_name, user_jid)) {
231
- } else {
232
- getChatBoxForSlug(slug).chatbox("option", "boxManager").toggleBox(true);
233
- };
220
+ //Show or create chatbox
221
+ createBuddyChatBox(slug);
234
222
 
235
223
  var chatBox = getChatBoxForSlug(slug);
236
224
 
@@ -241,7 +229,6 @@ function updateInterfaceAfterVideoRequestReceived(slug){
241
229
  toggleVideoBoxForSlug(slug,true);
242
230
  }
243
231
 
244
-
245
232
  function showInvitationInVideoBox(slug){
246
233
  var title = "<p class=\"video-info\">" + I18n.t("chat.videochat.call", {name: getNameFromSlug(slug)}) + " </p>";
247
234
  var msg = title + "<p class=\"video-request\"> <a class=\"videoChatButton\" slug=\""+slug+"\" value=\"yes\">" + I18n.t("chat.videochat.accept") + "</a> -"
@@ -337,18 +324,17 @@ function clickVideoChangeChatButton(slug){
337
324
  togglePublisherDivOnVideoChat(slug);
338
325
  }
339
326
 
327
+
328
+
340
329
  ////////////////
341
330
  /// Tokbox management
342
331
  ////////////////
343
-
344
332
  var OPENTOK_PUBLISHER_WIDTH = 235;
345
333
  var OPENTOK_PUBLISHER_HEIGHT = 145;
346
334
 
347
335
  var OPENTOK_SUBSCRIBER_WIDTH = 235;
348
336
  var OPENTOK_SUBSCRIBER_HEIGHT = 145;
349
337
 
350
-
351
-
352
338
  function initVideoCallWith(slug){
353
339
  if (TB.checkSystemRequirements() != TB.HAS_REQUIREMENTS) {
354
340
  showNotificationOnVideoBox(slug,I18n.t('chat.videochat.requirements'));
@@ -365,7 +351,6 @@ function initVideoCallWith(slug){
365
351
  }
366
352
  }
367
353
 
368
-
369
354
  function sessionConnectedHandler(event) {
370
355
  if (event.target.sessionId in slugOfSession){
371
356
  var slug = slugOfSession[event.target.sessionId];
@@ -400,7 +385,6 @@ function sessionConnectedHandler(event) {
400
385
  }
401
386
  }
402
387
 
403
-
404
388
  function sessionDisconnectedHandler(event) {
405
389
  // This signals that the user was disconnected from the Session. Any subscribers and publishers
406
390
  // will automatically be removed. This default behaviour can be prevented using event.preventDefault()
@@ -410,7 +394,6 @@ function sessionDisconnectedHandler(event) {
410
394
  contactsInfo[slug].videoChatStatus="disconnected";
411
395
  }
412
396
 
413
-
414
397
  function streamCreatedHandler(event) {
415
398
  var slug = slugOfSession[event.target.sessionId];
416
399
  subscribeToStreams(event.streams,slug);
@@ -420,11 +403,9 @@ function streamDestroyedHandler(event) {
420
403
  // This signals that a stream was destroyed. Any Subscribers will automatically be removed.
421
404
  // This default behaviour can be prevented using event.preventDefault()
422
405
  var slug = slugOfSession[event.target.sessionId];
423
- log("streamDestroyedHandler: se destruyo el stream de " + slug)
424
406
  closeVideoSession(slug);
425
407
  }
426
408
 
427
-
428
409
  function subscribeToStreams(streams,slug) {
429
410
  var session = contactsInfo[slug].session
430
411
 
@@ -452,7 +433,6 @@ function subscribeToStreams(streams,slug) {
452
433
  }
453
434
  }
454
435
 
455
-
456
436
  function accessAllowed(event){
457
437
  var slug = event.target.replacedDivId.split("&")[1];
458
438
  togglePublisherDivOnVideoChat(slug);
@@ -33,7 +33,7 @@ statusIcons['away'] = "away";
33
33
  statusIcons['xa'] = "away";
34
34
  statusIcons['dnd'] = "dnd";
35
35
 
36
- //Contact information
36
+ //Contacts information
37
37
  var contactsInfo = new Array();
38
38
  //contactsInfo['slug'] = "[Object chatContact]";
39
39
 
@@ -43,6 +43,8 @@ function chatContact(domain,resource,client,version) {
43
43
  this.resource=resource
44
44
  this.client=client;
45
45
  this.version=version;
46
+
47
+ //Videochat params
46
48
  //Sender: disconnected, negotiating , connecting , waiting, establishing, connected
47
49
  //Receiver: disconnected , pending , establishing, connected
48
50
  this.videoChatStatus = "disconnected";
@@ -53,6 +55,18 @@ function chatContact(domain,resource,client,version) {
53
55
  this.publisher=null;
54
56
  }
55
57
 
58
+ //Rooms information
59
+ var roomsInfo = new Array();
60
+ //roomsInfo['groupSlug'] = "[Object chatRoom]";
61
+
62
+ //Manage room information
63
+ function chatRoom() {
64
+ this.occupants=[];
65
+ this.joined = false;
66
+ this.affiliation = "none";
67
+ this.role = "none";
68
+ }
69
+
56
70
 
57
71
  //IQsIDs
58
72
  var iqStanzaID = new Array();
@@ -60,6 +74,8 @@ iqStanzaID['cinfo'] = "versionID";
60
74
  iqStanzaID['videochatRequest'] = "videochatRequestID";
61
75
  iqStanzaID['videochatRequestCancel'] = "videochatRequestCancelID";
62
76
 
77
+
78
+
63
79
  ////////////////////
64
80
  //Connect functions
65
81
  ////////////////////
@@ -67,7 +83,6 @@ iqStanzaID['videochatRequestCancel'] = "videochatRequestCancelID";
67
83
  function connectToChat(user_jid,cookie,password){
68
84
 
69
85
  if (isUserConnected()){
70
- log("USer already connected")
71
86
  return true;
72
87
  }
73
88
 
@@ -82,7 +97,6 @@ function connectToChat(user_jid,cookie,password){
82
97
  }
83
98
  }
84
99
 
85
-
86
100
  function isStropheConnected(){
87
101
  if((strophe_connection!=null)&&(strophe_connection.connected)){
88
102
  return true;
@@ -106,7 +120,6 @@ function connectToServerWithCookie(user_jid, cookie){
106
120
  return true;
107
121
  }
108
122
 
109
-
110
123
  //Password: Get from chatPassword param if exists, instead try to get from sessionStorage.
111
124
  function connectToServerWithPassword(user_jid, chatPassword){
112
125
 
@@ -224,7 +237,8 @@ function onConnect(status) {
224
237
  log('Strophe is disconnected.');
225
238
  disconnectionFlag = true;
226
239
  clearTimeout(awayTimer);
227
- updateInterfaceAfterUsersDisconnect();
240
+ updateInterfaceAfterUserDisconnect();
241
+ updateRoomsInfoAfterUserDisconnect();
228
242
  reconnectTimer = setTimeout ("onReconnect()", 5000);
229
243
  } else if (status == Strophe.Status.CONNECTED) {
230
244
  //AFTER CONNECT ACTIONS
@@ -234,7 +248,8 @@ function onConnect(status) {
234
248
  clearTimeout(reconnectTimer);
235
249
 
236
250
  //addHandler:(callback, namespace to match, stanza name, stanza type, stanza id , stanza from, options)
237
- strophe_connection.addHandler(onMessage, null, 'message', null, null, null);
251
+ strophe_connection.addHandler(onMessage, null, 'message', 'chat', null, null);
252
+ strophe_connection.addHandler(onRoomMessage, null, 'message', 'groupchat', null, null);
238
253
  strophe_connection.addHandler(onPresence, null, 'presence', null, null, null);
239
254
  strophe_connection.addHandler(onIQStanza,null, "iq", null, null);
240
255
 
@@ -274,7 +289,6 @@ function onReconnect(){
274
289
  }
275
290
  }
276
291
 
277
-
278
292
  function disconnectStrophe(){
279
293
  userStatus = "offline";
280
294
  setStatusWidgetTitle("offline");
@@ -289,18 +303,24 @@ function disconnectStrophe(){
289
303
  ////////
290
304
  //Manage Message stanzas
291
305
  ///////
306
+
307
+ //Chat messages handler
292
308
  function onMessage(msg) {
293
- var to = msg.getAttribute('to');
294
309
  var from = msg.getAttribute('from');
295
310
  var type = msg.getAttribute('type');
296
311
  var elems = msg.getElementsByTagName('body');
297
312
 
298
313
  if (type == "chat" && elems.length > 0) {
299
314
  var body = elems[0];
300
- var from_slug = from.split("@")[0];
301
- var from_jid = from_slug + "@" + domain;
302
-
303
- putReceivedMessageOnChatWindow(from_jid,from_slug,body,null)
315
+ var msg = Strophe.getText(body);
316
+ var from_slug = getSlugFromJid(from)
317
+
318
+ if(isChatRoomJid(from)){
319
+ return
320
+ } else {
321
+ var from_slug = getSlugFromJid(from)
322
+ afterReceivedChatMessage(from_slug,msg,null)
323
+ }
304
324
  }
305
325
 
306
326
  // we must return true to keep the handler alive.
@@ -313,35 +333,38 @@ function onMessage(msg) {
313
333
  //Manage Presence stanzas
314
334
  ///////
315
335
  function onPresence(presence) {
316
-
317
- log(presence)
318
-
319
- //Check presence stanza type
320
- var ptype = $(presence).attr('type');
321
-
322
- switch (ptype){
323
- case undefined:
324
- processAvailablePresenceStanza(presence)
325
- break;
326
- case "available":
327
- processAvailablePresenceStanza(presence)
328
- break;
329
- case "unavailable":
330
- processUnavailablePresenceStanza(presence)
331
- break;
332
- default :
333
- //Stanza type not recognize
334
- processAvailablePresenceStanza(presence)
335
- }
336
-
337
- return true;
338
- }
336
+ if (isChatRoomJid($(presence).attr('from'))){
337
+ return onRoomPresence(presence);
338
+ } else {
339
+ return onBuddyPresence(presence);
340
+ }
341
+ }
339
342
 
343
+ function onBuddyPresence(presence){
344
+ var ptype = $(presence).attr('type');
345
+
346
+ switch (ptype){
347
+ case undefined:
348
+ processAvailablePresenceStanza(presence)
349
+ break;
350
+ case "available":
351
+ processAvailablePresenceStanza(presence)
352
+ break;
353
+ case "unavailable":
354
+ processUnavailablePresenceStanza(presence)
355
+ break;
356
+ default :
357
+ //Stanza type not recognize
358
+ processAvailablePresenceStanza(presence)
359
+ }
360
+
361
+ return true;
362
+ }
340
363
 
341
364
  function processAvailablePresenceStanza(presence){
342
365
  var from = $(presence).attr('from');
343
366
  var slug = from.split("@")[0];
344
-
367
+
345
368
  if (slug != user_slug) {
346
369
  storeContactInformation(presence);
347
370
  if (getConnectionBoxFromSlug(slug)!=null){
@@ -359,7 +382,7 @@ function processAvailablePresenceStanza(presence){
359
382
  function processUnavailablePresenceStanza(presence){
360
383
  var from = $(presence).attr('from');
361
384
  var slug = from.split("@")[0];
362
-
385
+
363
386
  if (slug != user_slug) {
364
387
  if (getConnectionBoxFromSlug(slug)!=null){
365
388
  updateInterfaceAfterPresenceStanza(slug,false)
@@ -383,6 +406,12 @@ function storeContactInformation(stanza){
383
406
  }
384
407
  }
385
408
 
409
+ function storeRoomInformation(roomName){
410
+ if (!(roomName in roomsInfo)) {
411
+ var room = new chatRoom();
412
+ roomsInfo[roomName]=room;
413
+ }
414
+ }
386
415
 
387
416
 
388
417
  ////////
@@ -404,7 +433,7 @@ function onIQStanza(iq){
404
433
  if(type=="get"){
405
434
  return handleGetIQStanza(iq,from,slug);
406
435
  } else if(type="result"){
407
- return handleResultIQStanza(iq,from,slug)
436
+ return handleResultIQStanza(iq,from,slug);
408
437
  }
409
438
 
410
439
  return true;
@@ -437,18 +466,16 @@ function handleGetIQStanza(iq,jid,slug){
437
466
 
438
467
  //Case 2: Request videochat
439
468
  if(iqID==iqStanzaID['videochatRequest']){
440
- handleGetVideochatIQStanza(jid,iqID,iq,slug)
469
+ handleGetVideochatIQStanza(jid,iqID,iq,slug);
441
470
  return true;
442
471
  }
443
472
 
444
- //Case: Default behaviour
473
+ //Case 3: Default behaviour
445
474
  sendIQEmpty(jid,iqID);
446
475
 
447
476
  return true;
448
477
  }
449
478
 
450
-
451
-
452
479
  function handleGetVideochatIQStanza(jid,iqID,iq,slug){
453
480
  storeContactInformation(iq);
454
481
  var queryTag = iq.getElementsByTagName('query');
@@ -466,7 +493,7 @@ function handleGetVideochatIQStanza(jid,iqID,iq,slug){
466
493
  }
467
494
  }
468
495
 
469
- //Send error stanza
496
+ //Send empty stanza
470
497
  sendIQEmpty(jid,iqID);
471
498
  }
472
499
 
@@ -477,7 +504,6 @@ function handleGetVideochatIQStanza(jid,iqID,iq,slug){
477
504
  function handleResultIQStanza(iq,jid,slug){
478
505
  var iqID = iq.getAttribute("id");
479
506
 
480
-
481
507
  if (iqID==iqStanzaID['cinfo']){
482
508
  return handleIQResultWithClientInfo(iq,slug);
483
509
  }
@@ -588,7 +614,6 @@ function sendIQStanzaToRequestVideochat(slug){
588
614
  }
589
615
 
590
616
 
591
-
592
617
  ///////
593
618
  //SEND STANZAS: RESULT
594
619
  ///////
@@ -636,11 +661,24 @@ function sendIQStanzaToCancelVideochat(slug){
636
661
  }
637
662
 
638
663
 
639
-
640
664
  ////////
641
665
  //Send Message stanzas
642
666
  ///////
643
- function sendChatMessage(from,to,text){
667
+ function sendChatMessage(guest_slug,msg){
668
+ rotatePriority(guest_slug);
669
+ if (isSlugGroup(guest_slug)){
670
+ var guest_jid = getRoomJidFromRoomName(guest_slug)
671
+ return sendGroupMessageToRoom(guest_jid,msg);
672
+ } else {
673
+ var headerMessage = getParsedName(user_name,true);
674
+ getChatBoxForSlug(guest_slug).chatbox("option", "boxManager").addMsg(headerMessage, getParsedContent(msg,true));
675
+ var guest_jid = getJidFromSlug(guest_slug)
676
+ return sendChatMessageToBuddy(guest_jid,msg);
677
+ }
678
+ }
679
+
680
+ function sendChatMessageToBuddy(to,text){
681
+ var from = user_jid
644
682
  var type = "chat";
645
683
  var body= $build("body");
646
684
  body.t(text);
@@ -671,3 +709,287 @@ function sendStatus(status){
671
709
  setStatusWidgetTitle(status);
672
710
  }
673
711
  }
712
+
713
+
714
+ ////////
715
+ //MUC management
716
+ ///////
717
+
718
+ var muc_host = "conference";
719
+
720
+ function joinRoom(roomName){
721
+ return strophe_connection.muc.join(getRoomJidFromRoomName(roomName), getRoomNickFromUserName(), null, null, null, null)
722
+ }
723
+
724
+ function leaveRoom(roomName){
725
+ return strophe_connection.muc.leave(getRoomJidFromRoomName(roomName), getRoomNickFromUserName(), null, null)
726
+ }
727
+
728
+ function sendGroupMessageToRoomWithName(roomName,msg){
729
+ return sendMessageToRoom(getRoomJidFromRoomName(roomName),msg)
730
+ }
731
+
732
+ function sendGroupMessageToRoom(roomJid,msg){
733
+ return strophe_connection.muc.message(roomJid, null, msg, null, "groupchat")
734
+ }
735
+
736
+ function sendPrivateMessageToRoomUser(roomName,userNick,msg){
737
+ return strophe_connection.muc.message(getRoomJidFromRoomName(roomName), userNick, msg, null, "chat")
738
+ }
739
+
740
+ function queryChatRoomOccupants(roomName){
741
+ return strophe_connection.muc.queryOccupants(getRoomJidFromRoomName(roomName), queryChatRoomOccupantsSuccess, queryChatRoomOccupantsFail)
742
+ }
743
+
744
+ function queryChatRoomOccupantsSuccess(iqResponse){
745
+ handleIQResultFromMucOccupantsRequest(iqResponse);
746
+ return true;
747
+ }
748
+
749
+ function queryChatRoomOccupantsFail(){
750
+ //log("queryChatRoomOccupantsFail")
751
+ return true;
752
+ }
753
+
754
+ function handleIQResultFromMucOccupantsRequest(iq){
755
+ var from = $(iq).attr('from');
756
+ var room_slug = getSlugFromJid(from)
757
+ var queryTag = iq.getElementsByTagName('query');
758
+
759
+ if (queryTag.length > 0) {
760
+ var queryElement = queryTag[0];
761
+ var occupants = queryElement.getElementsByTagName('item');
762
+ $.each(occupants, function(index, value) {
763
+ //List all occupants
764
+ var nick = $(value).attr("name");
765
+ if(roomsInfo[room_slug].occupants.indexOf(nick)==-1){
766
+ roomsInfo[room_slug].occupants.push(nick)
767
+ }
768
+ });
769
+ }
770
+ }
771
+
772
+ function accessRoom(roomName,open){
773
+ storeRoomInformation(roomName)
774
+ if(roomsInfo[roomName].joined==false){
775
+ joinRoom(roomName)
776
+ queryChatRoomOccupants(roomName)
777
+ }
778
+ if(!existsSlugChatBox(roomName)){
779
+ createGroupChatBox(roomName,open)
780
+ }
781
+ return true
782
+ }
783
+
784
+ function updateRoomsInfoAfterUserDisconnect(){
785
+ $.each(getAllSlugsWithVisibleGroupBoxes(), function(index, value) {
786
+ storeRoomInformation(value)
787
+ var room = new chatRoom();
788
+ roomsInfo[value]=room;
789
+ initialNotificationInGroup(value,I18n.t('chat.muc.offline'))
790
+ });
791
+ }
792
+
793
+ function getRoomJidFromRoomName(roomName){
794
+ return roomName + "@" + muc_host + "." + domain;
795
+ }
796
+
797
+ function getRoomNickFromUserName(){
798
+ return user_name.split(" ")[0];
799
+ }
800
+
801
+
802
+ ////////
803
+ //MUC Stanzas
804
+ ///////
805
+
806
+ //MUC Messages
807
+ function onRoomMessage(msg) {
808
+ //from=roomSlug@conference.domain/from_slug
809
+ var from = msg.getAttribute('from');
810
+ var type = msg.getAttribute('type');
811
+ var elems = msg.getElementsByTagName('body');
812
+
813
+ if (type == "groupchat" && elems.length > 0) {
814
+ var body = elems[0];
815
+ var user_nick = getNickFromChatRoomJid(from)
816
+ var msg = Strophe.getText(body);
817
+ afterReceivedGroupChatMessage(from,msg)
818
+ }
819
+ return true;
820
+ }
821
+
822
+
823
+ //MUC Presence stanzas
824
+ function onRoomPresence(presence) {
825
+ var from = $(presence).attr('from');
826
+ var to = $(presence).attr('to')
827
+ var nick = getNickFromChatRoomJid(from)
828
+ var ptype = $(presence).attr('type')
829
+
830
+ //Join or Leave room stanzas of self user
831
+ if((nick == getRoomNickFromUserName())&&(getSlugFromJid(to) == user_slug)){
832
+ switch (ptype){
833
+ case undefined:
834
+ processJoinRoomPresenceStanza(presence);
835
+ break;
836
+ case "available":
837
+ processJoinRoomPresenceStanza(presence);
838
+ break;
839
+ case "unavailable":
840
+ processLeaveRoomPresenceStanza(presence);
841
+ break;
842
+ }
843
+ return true;
844
+ }
845
+
846
+
847
+ //Rest of stanzas
848
+ switch (ptype){
849
+ case undefined:
850
+ processAvailableRoomPresenceStanza(presence)
851
+ break;
852
+ case "available":
853
+ processAvailableRoomPresenceStanza(presence)
854
+ break;
855
+ case "unavailable":
856
+ processUnavailableRoomPresenceStanza(presence)
857
+ break;
858
+ default :
859
+ //Stanza type not recognize
860
+ return true
861
+ }
862
+
863
+ return true
864
+ }
865
+
866
+
867
+ function processJoinRoomPresenceStanza(presence){
868
+ var from = $(presence).attr('from');
869
+ var room_slug = getSlugFromJid(from);
870
+ storeRoomInformation(room_slug);
871
+
872
+ var xElements = presence.getElementsByTagName('x');
873
+
874
+ if (xElements.length == 1) {
875
+ var xElement = xElements[0];
876
+ var items = xElement.getElementsByTagName('item');
877
+
878
+ $.each(items, function(index, value) {
879
+ var role = $(value).attr("role")
880
+ var affiliation = $(value).attr("affiliation")
881
+
882
+ roomsInfo[room_slug].affiliation = affiliation
883
+ roomsInfo[room_slug].role = role
884
+ if(roomsInfo[room_slug].joined == false){
885
+ roomsInfo[room_slug].joined = true
886
+ changeInitialNotificationInGroup(room_slug,I18n.t('chat.muc.occupants'))
887
+ }
888
+ });
889
+ }
890
+ }
891
+
892
+ function processLeaveRoomPresenceStanza(presence){
893
+ var from = $(presence).attr('from');
894
+ var room_slug = getSlugFromJid(from);
895
+ storeRoomInformation(room_slug);
896
+ roomsInfo[room_slug].affiliation = "none"
897
+ roomsInfo[room_slug].role = "none"
898
+ roomsInfo[room_slug].occupants = []
899
+ if(roomsInfo[room_slug].joined == true){
900
+ roomsInfo[room_slug].joined = false
901
+ changeInitialNotificationInGroup(room_slug,"")
902
+ }
903
+ }
904
+
905
+ function processAvailableRoomPresenceStanza(presence){
906
+ var from = $(presence).attr('from');
907
+ var nick = getNickFromChatRoomJid(from)
908
+ var room_slug = getSlugFromJid(from)
909
+
910
+ storeRoomInformation(room_slug)
911
+
912
+ if (roomsInfo[room_slug].occupants.indexOf(nick)==-1){
913
+ roomsInfo[room_slug].occupants.push(nick)
914
+ addNickToNotificationInGroup(room_slug,nick)
915
+ writeReceivedMessageOnChatWindow("",room_slug, I18n.t("chat.muc.join", {nick: nick}))
916
+ }
917
+ }
918
+
919
+ function processUnavailableRoomPresenceStanza(presence){
920
+ var from = $(presence).attr('from');
921
+ var nick = getNickFromChatRoomJid(from)
922
+ var room_slug = getSlugFromJid(from)
923
+
924
+ storeRoomInformation(room_slug)
925
+
926
+ if (roomsInfo[room_slug].occupants.indexOf(nick)!=-1){
927
+ roomsInfo[room_slug].occupants.splice(roomsInfo[room_slug].occupants.indexOf(nick),1)
928
+ removeNickFromNotificationInGroup(room_slug,nick)
929
+ writeReceivedMessageOnChatWindow("",room_slug,I18n.t("chat.muc.leave", {nick: nick}))
930
+ }
931
+ }
932
+
933
+
934
+
935
+ //////////////////
936
+ // Getters
937
+ //////////////////
938
+ function getSlugFromJid(jid){
939
+ return jid.split("@")[0];
940
+ }
941
+
942
+ function getDomainFromJid(jid){
943
+ return jid.split("@")[1].split("/")[0];
944
+ }
945
+
946
+ function isChatRoomJid(jid){
947
+ if ((getDomainFromJid(jid).split(".")[0])==muc_host){
948
+ return true;
949
+ }
950
+ return false;
951
+ }
952
+
953
+ function getNameFromSlug(slug){
954
+ var connectionBox = getConnectionBoxFromSlug(slug);
955
+
956
+ if(connectionBox!=null){
957
+ return $(connectionBox).attr("name");
958
+ }
959
+
960
+ var chatBox = getChatBoxForSlug(slug)
961
+ if(chatBox!=null){
962
+ return chatBox.attr("name");
963
+ }
964
+
965
+ //return rebuildNameFromSlug(slug)
966
+ return slug;
967
+ }
968
+
969
+ function rebuildNameFromSlug(slug){
970
+ var cname = slug.split("-");
971
+ var name = "";
972
+ for(i=0; i<cname.length; i++){
973
+ if (i!=0){
974
+ name = name + " ";
975
+ }
976
+ name = name + cname[i][0].toUpperCase() + cname[i].substring(1,cname[i].length);
977
+ }
978
+ return name;
979
+ }
980
+
981
+ function getNameFromJid(){
982
+ return getNameFromSlug(getSlugFromJid(jid));
983
+ }
984
+
985
+ function getJidFromSlug(slug){
986
+ return slug + "@" + domain;
987
+ }
988
+
989
+ function getNickFromChatRoomJid(jid){
990
+ return jid.split("/")[1];
991
+ }
992
+
993
+ function purgeNickFromChatRoomJid(jid){
994
+ return jid.split("/")[0];
995
+ }