social_stream-presence 0.7.5 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,4 +4,5 @@
4
4
  //= require jquery.ui.chatbox.sstreampresence
5
5
  //= require jquery.flexselect.sstreampresence
6
6
  //= require liquidmetal
7
+ //= require TB.min
7
8
  //= require_tree .
@@ -0,0 +1,459 @@
1
+ ////////////////////
2
+ //Global constants
3
+ ////////////////////
4
+ var opentok_apiKey = '<%=SocialStream::Presence.opentok_api_key%>';
5
+
6
+
7
+ //Correspondence between slugs and session ids
8
+ var slugOfSession = new Array();
9
+ //slugOfSession['session_id'] = "slug";
10
+
11
+ ////////////////////
12
+ //Videochat button actions
13
+ ////////////////////
14
+
15
+ function clickVideoChatButton(slug){
16
+ var videoBoxVisibility = toggleVideoBoxForSlug(slug);
17
+
18
+ if (videoBoxVisibility) {
19
+ openVideoChatWindow(slug);
20
+ }
21
+ else {
22
+ closeVideoChatWindow(slug);
23
+ }
24
+ }
25
+
26
+ function closeVideoChatWindow(slug){
27
+ closeVideoSession(slug);
28
+ return;
29
+ }
30
+
31
+
32
+ //Single variable for all slugs.
33
+ var reconnectAttemptsVideo = 1;
34
+
35
+ function openVideoChatWindow(slug){
36
+
37
+ if (slug in contactsInfo) {
38
+ var connectionStatus = contactsInfo[slug].videoChatStatus;
39
+ } else {
40
+ var connectionStatus = null;
41
+ }
42
+
43
+ if (TB.checkSystemRequirements() != TB.HAS_REQUIREMENTS) {
44
+ showNotificationOnVideoBox(slug,I18n.t('chat.videochat.requirements'));
45
+ if(connectionStatus!=null){
46
+ contactsInfo[slug].videoChatStatus = "disconnected";
47
+ }
48
+ return;
49
+ }
50
+
51
+ if(! isUserConnected()){
52
+ showNotificationOnVideoBox(slug, I18n.t("chat.videochat.offline"));
53
+ if(connectionStatus!=null){
54
+ contactsInfo[slug].videoChatStatus = "disconnected";
55
+ }
56
+ return;
57
+ }
58
+
59
+ if(! isSlugChatConnected(slug)){
60
+ showNotificationOnVideoBox(slug, I18n.t("chat.videochat.guestOffline", {name: getNameFromSlug(slug)}));
61
+ if(connectionStatus!=null){
62
+ contactsInfo[slug].videoChatStatus = "disconnected";
63
+ }
64
+ return;
65
+ }
66
+
67
+ if(connectionStatus==null){
68
+ if(reconnectAttemptsVideo > 0){
69
+ reconnectAttemptsVideo--;
70
+ showNotificationOnVideoBox(slug,I18n.t('chat.videochat.connectingWait'));
71
+ setTimeout(function() { openVideoChatWindow(slug); }, 5000);
72
+ } else {
73
+ showNotificationOnVideoBox(slug,I18n.t('chat.videochat.unable'));
74
+ }
75
+ return;
76
+ } else {
77
+ reconnectAttemptsVideo = 1;
78
+ }
79
+
80
+ if(connectionStatus!="disconnected"){
81
+ return;
82
+ }
83
+
84
+ //connectionStatus=="disconnected"
85
+ //Start negotiation
86
+ negotiateVideoChatSession(slug);
87
+ }
88
+
89
+
90
+
91
+ ////////////////////
92
+ //Session establishment
93
+ ////////////////////
94
+
95
+ //VideoChat Session: Step 1
96
+ function negotiateVideoChatSession(slug){
97
+ showNotificationOnVideoBox(slug,I18n.t('chat.videochat.negotiating'));
98
+ contactsInfo[slug].videoChatStatus="negotiating";
99
+
100
+ if(contactsInfo[slug].version != null){
101
+ connectingVideoChatSession(slug);
102
+ return;
103
+ } else {
104
+ sendIQStanzaForRequestClientInfo(slug);
105
+ }
106
+ }
107
+
108
+ //VideoChat Session: Step 2
109
+ function connectingVideoChatSession(slug){
110
+ if (contactsInfo[slug].version == getJavascriptXMPPClientName()) {
111
+ contactsInfo[slug].videoChatStatus="connecting";
112
+ showNotificationOnVideoBox(slug,I18n.t('chat.videochat.connecting'));
113
+ requestSessionIDAndTokenForVideoChat(slug);
114
+ } else {
115
+ showNotificationOnVideoBox(slug,I18n.t("chat.videochat.clientIssue", {name: getNameFromSlug(slug)}));
116
+ contactsInfo[slug].videoChatStatus="disconnected";
117
+ }
118
+ }
119
+
120
+ function requestSessionIDAndTokenForVideoChat(slug){
121
+ $.post("/requestVideoChat.xml", { }, function(data){
122
+ var session = $(data).find("session");
123
+ if (session.length == 1) {
124
+ if (($(session).find("id").length == 1) && (($(session).find("user_token").length == 1)) && (($(session).find("guest_token").length == 1))) {
125
+ contactsInfo[slug].session_id = $(session).find("id").text();
126
+ contactsInfo[slug].user_token = $(session).find("user_token").text();
127
+ contactsInfo[slug].guest_token = $(session).find("guest_token").text();
128
+ sendVideoChatRequestToUser(slug);
129
+ return;
130
+ }
131
+ }
132
+ showNotificationOnVideoBox(slug, I18n.t('chat.videochat.serverIssue'));
133
+ contactsInfo[slug].videoChatStatus="disconnected";
134
+ });
135
+ }
136
+
137
+
138
+ //VideoChat Session: Step 3
139
+ function sendVideoChatRequestToUser(slug){
140
+ contactsInfo[slug].videoChatStatus="waiting";
141
+ showNotificationOnVideoBox(slug,I18n.t('chat.videochat.waiting'));
142
+ sendIQStanzaToRequestVideochat(slug);
143
+ }
144
+
145
+ //VideoChat Session: Step 4
146
+ function receiveVideoChatResponseFromUser(slug,response){
147
+
148
+ if(contactsInfo[slug].videoChatStatus!="waiting"){
149
+ return;
150
+ }
151
+
152
+ if(response=="yes"){
153
+ showNotificationOnVideoBox(slug,I18n.t('chat.videochat.establishing'));
154
+ contactsInfo[slug].videoChatStatus="establishing";
155
+ initVideoCallWith(slug);
156
+ } else if (response=="no"){
157
+ showNotificationOnVideoBox(slug,I18n.t("chat.videochat.rejected", {name: getNameFromSlug(slug)}));
158
+ contactsInfo[slug].videoChatStatus="disconnected";
159
+ } else {
160
+ showNotificationOnVideoBox(slug,I18n.t("chat.videochat.rejectedBusy", {name: getNameFromSlug(slug)}));
161
+ contactsInfo[slug].videoChatStatus="disconnected";
162
+ }
163
+ }
164
+
165
+ //Cancelation received
166
+ function receiveVideoChatCancelationFromUser(slug,response){
167
+ if(slug in contactsInfo){
168
+ if(contactsInfo[slug].videoChatStatus=="pending"){
169
+ showNotificationOnVideoBox(slug,I18n.t("chat.videochat.cancel", {name: getNameFromSlug(slug)}));
170
+ contactsInfo[slug].videoChatStatus="disconnected";
171
+ }
172
+ } else {
173
+ closeVideoSession(slug);
174
+ }
175
+ }
176
+
177
+ //VideoChat Session: Step 5
178
+ function closeVideoSession(slug){
179
+ if(slug in contactsInfo){
180
+ var connectionStatus = contactsInfo[slug].videoChatStatus;
181
+
182
+ if(connectionStatus=="connected"){
183
+ showNotificationOnVideoBox(slug,I18n.t('chat.videochat.disconnecting'));
184
+ //Close opentok session...
185
+ if(contactsInfo[slug].session.connected){
186
+ contactsInfo[slug].session.disconnect();
187
+ }
188
+ restoreChatBoxAfterVideoCall(slug);
189
+ } else if(connectionStatus=="waiting"){
190
+ sendIQStanzaToCancelVideochat(slug);
191
+ } else if(connectionStatus=="pending"){
192
+ sendIQStanzaToResponseVideochat(slug,"no");
193
+ }
194
+ contactsInfo[slug].videoChatStatus="disconnected";
195
+ }
196
+
197
+ toggleVideoBoxForSlug(slug,false);
198
+ }
199
+
200
+
201
+
202
+ /////////////
203
+ // Videochat interface functions
204
+ ////////////
205
+
206
+ function clientInfoReceivedTrigger(slug){
207
+ //Check for videochat request
208
+ if ((slug in contactsInfo)&&(contactsInfo[slug].videoChatStatus="negotiating")){
209
+ connectingVideoChatSession(slug);
210
+ }
211
+ }
212
+
213
+ function showNotificationOnVideoBox(slug,msg){
214
+ setVideoBoxContent(slug,"<p class=\"video-info\"> " + msg +" </p>");
215
+ }
216
+
217
+
218
+ function updateInterfaceAfterVideoRequestReceived(slug){
219
+
220
+ if (contactsInfo[slug].videoChatStatus!="disconnected"){
221
+ sendIQStanzaToResponseVideochat(slug,"busy");
222
+ return;
223
+ } else {
224
+ contactsInfo[slug].videoChatStatus="pending";
225
+ }
226
+
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
+ };
234
+
235
+ var chatBox = getChatBoxForSlug(slug);
236
+
237
+ //Show invitation message
238
+ showInvitationInVideoBox(slug);
239
+
240
+ //Show videobox
241
+ toggleVideoBoxForSlug(slug,true);
242
+ }
243
+
244
+
245
+ function showInvitationInVideoBox(slug){
246
+ var title = "<p class=\"video-info\">" + I18n.t("chat.videochat.call", {name: getNameFromSlug(slug)}) + " </p>";
247
+ var msg = title + "<p class=\"video-request\"> <a class=\"videoChatButton\" slug=\""+slug+"\" value=\"yes\">" + I18n.t("chat.videochat.accept") + "</a> -"
248
+ + " <a class=\"videoChatButton\" slug=\""+slug+"\" value=\"no\">" + I18n.t("chat.videochat.deny") + "</a> </p>";
249
+ setVideoBoxContent(slug,msg);
250
+ setVideochatRequestButtonsFunction();
251
+ }
252
+
253
+ function setVideochatRequestButtonsFunction(){
254
+ $(".videoChatButton").click(function(event) {
255
+ event.preventDefault();
256
+ var result = $(this).attr("value");
257
+ var slug = $(this).attr("slug");
258
+ sendIQStanzaToResponseVideochat(slug,result);
259
+
260
+ if(result=="yes"){
261
+ showNotificationOnVideoBox(slug,I18n.t('chat.videochat.establishing'));
262
+ contactsInfo[slug].videoChatStatus="establishing";
263
+ initVideoCallWith(slug);
264
+ } else {
265
+ contactsInfo[slug].videoChatStatus="disconnected";
266
+ closeVideoSession(slug);
267
+ }
268
+ });
269
+ }
270
+
271
+ function togglePublisherDivOnVideoChat(slug){
272
+ var publisherDiv = getPublisherVideoBoxForSlug(slug);
273
+ var chatBox = getChatBoxForSlug(slug);
274
+ var videoBox = getVideoBoxForSlug(slug);
275
+
276
+ if((chatBox==null)||(videoBox==null)||(publisherDiv==null)){
277
+ return;
278
+ }
279
+
280
+ var videoBoxVisibility = publisherDiv.css("z-index")!="-1";
281
+
282
+ var desp = OPENTOK_PUBLISHER_HEIGHT + 1;
283
+
284
+ var scrollHeight = $(chatBox)[0].scrollHeight;
285
+ var outerHeight = chatBox.outerHeight();
286
+ var diff = scrollHeight - chatBox.scrollTop() - outerHeight;
287
+ var scrollMov = 145;
288
+
289
+ if (! videoBoxVisibility){
290
+ //Show publisher div
291
+ publisherDiv.css("z-index","100");
292
+ //Resize windows
293
+ chatBox.css("height",chatBox.height() - desp );
294
+ videoBox.css("height",videoBox.height() + desp );
295
+ chatBox.scrollTop(chatBox.scrollTop() + scrollMov);
296
+ } else {
297
+ //Hide publisher div
298
+ publisherDiv.css("z-index","-1");
299
+ //Resize windows
300
+ chatBox.css("height",chatBox.height() + desp );
301
+ videoBox.css("height",videoBox.height() - desp );
302
+ if(diff < desp){
303
+ chatBox.scrollTop(chatBox.scrollTop() - diff);
304
+ } else {
305
+ chatBox.scrollTop(chatBox.scrollTop() - scrollMov);
306
+ }
307
+ }
308
+ }
309
+
310
+ function restoreChatBoxAfterVideoCall(slug){
311
+ //Original dimensions
312
+ showNotificationOnVideoBox(slug,I18n.t('chat.videochat.disconnected'));
313
+ $(getChatBoxButtonForSlug(slug,"videoChange")).find("span").hide();
314
+ toggleVideoBoxForSlug(slug,false);
315
+ var chatBox = getChatBoxForSlug(slug);
316
+ chatBox.height(chatBoxHeight);
317
+ }
318
+
319
+ function checkVideocallFeature(){
320
+ if (opentok_apiKey=="default"){
321
+ //Hide videochat buttons
322
+
323
+ //Changing Tooltip CSS class by JQuery
324
+ var ss = document.styleSheets;
325
+ for (var i=0; i<ss.length; i++) {
326
+ var rules = ss[i].cssRules || ss[i].rules;
327
+ for (var j=0; j<rules.length; j++) {
328
+ if (rules[j].selectorText === ".chat-videothick") {
329
+ rules[j].style.display = 'none'
330
+ }
331
+ }
332
+ }
333
+ }
334
+ }
335
+
336
+ function clickVideoChangeChatButton(slug){
337
+ togglePublisherDivOnVideoChat(slug);
338
+ }
339
+
340
+ ////////////////
341
+ /// Tokbox management
342
+ ////////////////
343
+
344
+ var OPENTOK_PUBLISHER_WIDTH = 235;
345
+ var OPENTOK_PUBLISHER_HEIGHT = 145;
346
+
347
+ var OPENTOK_SUBSCRIBER_WIDTH = 235;
348
+ var OPENTOK_SUBSCRIBER_HEIGHT = 145;
349
+
350
+
351
+
352
+ function initVideoCallWith(slug){
353
+ if (TB.checkSystemRequirements() != TB.HAS_REQUIREMENTS) {
354
+ showNotificationOnVideoBox(slug,I18n.t('chat.videochat.requirements'));
355
+ contactsInfo[slug].videoChatStatus="disconnected";
356
+ } else {
357
+ //TB.setLogLevel(TB.DEBUG);
358
+ contactsInfo[slug].session = TB.initSession(contactsInfo[slug].session_id);
359
+ contactsInfo[slug].session.addEventListener('sessionConnected', sessionConnectedHandler);
360
+ contactsInfo[slug].session.addEventListener('sessionDisconnected', sessionDisconnectedHandler);
361
+ contactsInfo[slug].session.addEventListener('streamCreated', streamCreatedHandler);
362
+ contactsInfo[slug].session.addEventListener('streamDestroyed', streamDestroyedHandler);
363
+ contactsInfo[slug].session.connect(opentok_apiKey, contactsInfo[slug].user_token);
364
+ slugOfSession[contactsInfo[slug].session_id] = slug;
365
+ }
366
+ }
367
+
368
+
369
+ function sessionConnectedHandler(event) {
370
+ if (event.target.sessionId in slugOfSession){
371
+ var slug = slugOfSession[event.target.sessionId];
372
+ contactsInfo[slug].videoChatStatus="connected";
373
+ $(getChatBoxButtonForSlug(slug,"videoChange")).find("span").show();
374
+
375
+ //Create publishing div
376
+ var parentDiv = document.createElement('div');
377
+ var pubID = 'stream_publish_videochat_' + slug;
378
+ parentDiv.setAttribute('id', pubID);
379
+ parentDiv.setAttribute('class', 'stream_publish_videochat');
380
+
381
+ var stubDiv = document.createElement("div");
382
+ stubDiv.id = "opentok_publisher&" + slug;
383
+ parentDiv.appendChild(stubDiv);
384
+
385
+ //Interface update
386
+ setVideoBoxContent(slug,parentDiv);
387
+
388
+ //Publish
389
+ var publisherProps = {width: OPENTOK_PUBLISHER_WIDTH, height: OPENTOK_PUBLISHER_HEIGHT};
390
+ contactsInfo[slug].publisher = contactsInfo[slug].session.publish(stubDiv.id, publisherProps);
391
+ contactsInfo[slug].publisher.addEventListener('accessAllowed', accessAllowed);
392
+
393
+ //Subscribe
394
+ subscribeToStreams(event.streams,slug);
395
+
396
+ //Toggle!
397
+ togglePublisherDivOnVideoChat(slug);
398
+ } else {
399
+ //Close
400
+ }
401
+ }
402
+
403
+
404
+ function sessionDisconnectedHandler(event) {
405
+ // This signals that the user was disconnected from the Session. Any subscribers and publishers
406
+ // will automatically be removed. This default behaviour can be prevented using event.preventDefault()
407
+
408
+ var slug = slugOfSession[event.target.sessionId];
409
+ contactsInfo[slug].publisher = null;
410
+ contactsInfo[slug].videoChatStatus="disconnected";
411
+ }
412
+
413
+
414
+ function streamCreatedHandler(event) {
415
+ var slug = slugOfSession[event.target.sessionId];
416
+ subscribeToStreams(event.streams,slug);
417
+ }
418
+
419
+ function streamDestroyedHandler(event) {
420
+ // This signals that a stream was destroyed. Any Subscribers will automatically be removed.
421
+ // This default behaviour can be prevented using event.preventDefault()
422
+ var slug = slugOfSession[event.target.sessionId];
423
+ log("streamDestroyedHandler: se destruyo el stream de " + slug)
424
+ closeVideoSession(slug);
425
+ }
426
+
427
+
428
+ function subscribeToStreams(streams,slug) {
429
+ var session = contactsInfo[slug].session
430
+
431
+ for (var i = 0; i < streams.length; i++) {
432
+
433
+ // Make sure we don't subscribe to ourself
434
+ if (streams[i].connection.connectionId == session.connection.connectionId) {
435
+ return;
436
+ }
437
+
438
+ // Create subscriber div
439
+ var parentDiv = document.createElement('div');
440
+ parentDiv.setAttribute('class', 'stream_videochat');
441
+
442
+ var stubDiv = document.createElement("div");
443
+ stubDiv.id = 'stream' + streams[i].streamId;
444
+ parentDiv.appendChild(stubDiv);
445
+
446
+ addVideoBoxContent(slug,parentDiv);
447
+
448
+ // Subscribe to the stream
449
+ var subscriberProps = { width: OPENTOK_SUBSCRIBER_WIDTH,
450
+ height: OPENTOK_SUBSCRIBER_HEIGHT };
451
+ session.subscribe(streams[i], stubDiv.id, subscriberProps);
452
+ }
453
+ }
454
+
455
+
456
+ function accessAllowed(event){
457
+ var slug = event.target.replacedDivId.split("&")[1];
458
+ togglePublisherDivOnVideoChat(slug);
459
+ }