social_stream-presence 0.13.1 → 0.13.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. data/app/assets/javascripts/jquery.flexselect.sstreampresence.js +2 -2
  2. data/app/assets/javascripts/jquery.ui.chatbox.sstreampresence.js +5 -5
  3. data/app/assets/javascripts/presence.js.erb +6 -4
  4. data/app/assets/javascripts/presence_XmppClient.js.erb +1136 -996
  5. data/app/assets/javascripts/presence_audio.js.erb +74 -60
  6. data/app/assets/javascripts/presence_game.js.erb +35 -22
  7. data/app/assets/javascripts/presence_game_comunication.js.erb +22 -5
  8. data/app/assets/javascripts/presence_game_factory.js.erb +1 -1
  9. data/app/assets/javascripts/presence_game_interface.js.erb +33 -13
  10. data/app/assets/javascripts/presence_notifications.js +206 -183
  11. data/app/assets/javascripts/presence_parser.js +265 -247
  12. data/app/assets/javascripts/presence_persistence.js +199 -188
  13. data/app/assets/javascripts/presence_store.js +22 -11
  14. data/app/assets/javascripts/presence_uiManager.js.erb +553 -530
  15. data/app/assets/javascripts/presence_utilities.js +244 -219
  16. data/app/assets/javascripts/presence_videochat.js.erb +436 -409
  17. data/app/assets/javascripts/presence_windowManager.js +586 -532
  18. data/app/views/chat/_index.html.erb +7 -13
  19. data/config/locales/en.yml +2 -1
  20. data/config/locales/es.yml +2 -1
  21. data/ejabberd/ejabberd_files.zip +0 -0
  22. data/ejabberd/ejabberd_scripts/authentication_script +9 -2
  23. data/ejabberd/mod_sspresence/mod_sspresence.beam +0 -0
  24. data/lib/generators/social_stream/presence/templates/initializer.rb +4 -0
  25. data/lib/social_stream/presence/version.rb +1 -1
  26. data/lib/social_stream/presence/xmpp_server_order.rb +1 -0
  27. data/lib/social_stream-presence.rb +3 -0
  28. metadata +68 -63
@@ -2,73 +2,87 @@
2
2
  //Audio functions
3
3
  ////////////////////
4
4
 
5
- //Global audio variables
6
- var audio_path = '<%=image_path("chat")%>';
7
- var onMessageAudio;
8
-
9
- var html5_audiotypes=[
10
- ["mp3","audio/mpeg"],
11
- //["mp4","audio/mp4"],
12
- //["ogg","audio/ogg"],
13
- ["wav","audio/wav"]
14
- ]
15
-
16
- function initAudio(){
17
- //Init all audio files
18
- initSound("onMessageAudio");
19
- }
20
-
21
- function initSound(sound){
5
+ PRESENCE.AUDIO = (function(P,$,undefined){
6
+
7
+ //Audio variables
8
+ var audio_path = '<%=image_path("chat")%>';
9
+ var onMessageAudio;
10
+
11
+ var html5_audiotypes=[
12
+ ["mp3","audio/mpeg"],
13
+ //["mp4","audio/mp4"],
14
+ //["ogg","audio/ogg"],
15
+ ["wav","audio/wav"]
16
+ ]
17
+
18
+
19
+ var init = function(){
20
+ //Init all audio files
21
+ initSound("onMessageAudio");
22
+ }
23
+
24
+
25
+ var initSound = function(sound){
22
26
 
23
- //Check support for HTML5 audio
24
- var html5audio=document.createElement('audio')
27
+ //Check support for HTML5 audio
28
+ var html5audio=document.createElement('audio')
25
29
 
26
- if (html5audio.canPlayType){
27
- path = audio_path + "/" + sound;
28
- window[sound] = new Audio();
30
+ if (html5audio.canPlayType){
31
+ path = audio_path + "/" + sound;
32
+ window[sound] = new Audio();
29
33
 
30
- for(i=0; i<html5_audiotypes.length; i++){
31
- if (window[sound].canPlayType(html5_audiotypes[i][1])) {
32
- var source= document.createElement('source');
33
- source.type= html5_audiotypes[i][1];
34
- source.src= path + '.' + html5_audiotypes[i][0];
35
- window[sound].addEventListener('ended', endSoundListener);
36
- window[sound].appendChild(source);
37
- }
38
- }
39
- } else {
34
+ for(i=0; i<html5_audiotypes.length; i++){
35
+ if (window[sound].canPlayType(html5_audiotypes[i][1])) {
36
+ var source= document.createElement('source');
37
+ source.type= html5_audiotypes[i][1];
38
+ source.src= path + '.' + html5_audiotypes[i][0];
39
+ window[sound].addEventListener('ended', endSoundListener);
40
+ window[sound].appendChild(source);
41
+ }
42
+ }
43
+ } else {
40
44
  //Browser doesn't support HTML5 audio
45
+ }
41
46
  }
42
- }
43
47
 
44
- function endSoundListener(){ }
45
48
 
46
- function playSound(sound){
47
- if (window[sound]!=null){
48
- window[sound].play();
49
- } else {
50
- //Fallback option: When browser doesn't support HTML5 audio
51
- $('body').append('<embed src="' + audio_path + '/' + sound + '.mp3" autostart="true" hidden="true" loop="false">');
52
- }
53
- }
49
+ function endSoundListener(){ }
54
50
 
55
- function initAndPlaySound(sound){
56
- initSound(sound);
57
- playSound(sound);
58
- }
59
51
 
52
+ function playSound(sound){
53
+ if (window[sound]!=null){
54
+ window[sound].play();
55
+ } else {
56
+ //Fallback option: When browser doesn't support HTML5 audio
57
+ $('body').append('<embed src="' + audio_path + '/' + sound + '.mp3" autostart="true" hidden="true" loop="false">');
58
+ }
59
+ }
60
60
 
61
- function mustPlaySoundForChatWindow(chatBox){
62
- //Deny conditions
63
- if(userStatus == "dnd"){
64
- return false;
65
- }
66
-
67
- //Accept conditions
68
- if (!chatFocus){
69
- return true;
70
- }
71
-
72
- //Default action
73
- return false
74
- }
61
+ function initAndPlaySound(sound){
62
+ initSound(sound);
63
+ playSound(sound);
64
+ }
65
+
66
+
67
+ function mustPlaySoundForChatWindow(chatBox){
68
+ //Deny conditions
69
+ if(PRESENCE.XMPPClient.getUserStatus() == "dnd"){
70
+ return false;
71
+ }
72
+
73
+ //Accept conditions
74
+ if (!PRESENCE.UTILITIES.getChatFocus()){
75
+ return true;
76
+ }
77
+
78
+ //Default action
79
+ return false
80
+ }
81
+
82
+ return {
83
+ init : init,
84
+ mustPlaySoundForChatWindow : mustPlaySoundForChatWindow,
85
+ playSound : playSound
86
+ };
87
+
88
+ }) (PRESENCE, jQuery);
@@ -40,8 +40,12 @@ PRESENCE.GAME = (function(P,$,undefined){
40
40
  // CORE METHODS //
41
41
  /////////////////////////////////
42
42
 
43
- var init = function(myConnection){
44
- P.GAME.COMUNICATION.init(myConnection);
43
+ var init = function(){
44
+ var enable = '<%=SocialStream::Presence.games%>';
45
+ if(enable=="true"){
46
+ P.GAME.INTERFACE.enableGameFeature(true);
47
+ P.GAME.COMUNICATION.init(PRESENCE.XMPPClient.getConnection());
48
+ }
45
49
  };
46
50
 
47
51
 
@@ -56,7 +60,7 @@ PRESENCE.GAME = (function(P,$,undefined){
56
60
  var gameStatus = null;
57
61
  }
58
62
 
59
- if(! isUserConnected()){
63
+ if(! PRESENCE.XMPPClient.isUserConnected()){
60
64
  P.GAME.INTERFACE.updateInterfaceOnInformationMessage(slug, I18n.t("chat.game.offline"));
61
65
  if(gameStatus!=null){
62
66
  contactsInfo[slug].gameStatus = "disconnected";
@@ -64,8 +68,8 @@ PRESENCE.GAME = (function(P,$,undefined){
64
68
  return;
65
69
  }
66
70
 
67
- if(! isSlugChatConnected(slug)){
68
- P.GAME.INTERFACE.updateInterfaceOnInformationMessage(slug, I18n.t("chat.game.guestOffline", {name: getNameFromSlug(slug)}));
71
+ if(! PRESENCE.UIMANAGER.isSlugChatConnected(slug)){
72
+ P.GAME.INTERFACE.updateInterfaceOnInformationMessage(slug, I18n.t("chat.game.guestOffline", {name: PRESENCE.XMPPClient.getNameFromSlug(slug)}));
69
73
  if(gameStatus!=null){
70
74
  contactsInfo[slug].gameStatus = "disconnected";
71
75
  }
@@ -142,13 +146,13 @@ PRESENCE.GAME = (function(P,$,undefined){
142
146
  contactsInfo[slug].gameStatus = "playing";
143
147
  P.GAME.INTERFACE.updateInterfaceBeforeStartGame(slug,contactsInfo[slug].game)
144
148
  } else if (response=="no"){
145
- P.GAME.INTERFACE.updateInterfaceOnInformationMessage(slug,I18n.t("chat.game.rejected", {name: getNameFromSlug(slug)}));
149
+ P.GAME.INTERFACE.updateInterfaceOnInformationMessage(slug,I18n.t("chat.game.rejected", {name: PRESENCE.XMPPClient.getNameFromSlug(slug)}));
146
150
  contactsInfo[slug].gameStatus="disconnected";
147
151
  } else if (response=="busy"){
148
- P.GAME.INTERFACE.updateInterfaceOnInformationMessage(slug,I18n.t("chat.game.rejectedBusy", {name: getNameFromSlug(slug)}));
152
+ P.GAME.INTERFACE.updateInterfaceOnInformationMessage(slug,I18n.t("chat.game.rejectedBusy", {name: PRESENCE.XMPPClient.getNameFromSlug(slug)}));
149
153
  contactsInfo[slug].gameStatus="disconnected";
150
154
  } else {
151
- P.GAME.INTERFACE.updateInterfaceOnInformationMessage(slug,I18n.t("chat.game.unknown", {name: getNameFromSlug(slug)}));
155
+ P.GAME.INTERFACE.updateInterfaceOnInformationMessage(slug,I18n.t("chat.game.unknown", {name: PRESENCE.XMPPClient.getNameFromSlug(slug)}));
152
156
  contactsInfo[slug].gameStatus="disconnected";
153
157
  }
154
158
  }
@@ -157,10 +161,10 @@ PRESENCE.GAME = (function(P,$,undefined){
157
161
  if(slug in contactsInfo){
158
162
  if (status == "finish") {
159
163
  if (contactsInfo[slug].gameStatus == "pending") {
160
- P.GAME.INTERFACE.updateInterfaceOnInformationMessage(slug, I18n.t("chat.game.cancel", {name: getNameFromSlug(slug)}));
164
+ P.GAME.INTERFACE.updateInterfaceOnInformationMessage(slug, I18n.t("chat.game.cancel", {name: PRESENCE.XMPPClient.getNameFromSlug(slug)}));
161
165
  contactsInfo[slug].gameStatus = "disconnected";
162
166
  } else if (contactsInfo[slug].gameStatus == "playing") {
163
- P.GAME.INTERFACE.updateInterfaceOnInformationMessage(slug, I18n.t("chat.game.finish", {name: getNameFromSlug(slug)}));
167
+ P.GAME.INTERFACE.updateInterfaceOnInformationMessage(slug, I18n.t("chat.game.finish", {name: PRESENCE.XMPPClient.getNameFromSlug(slug)}));
164
168
  contactsInfo[slug].gameStatus = "disconnected";
165
169
  }
166
170
  }
@@ -168,6 +172,14 @@ PRESENCE.GAME = (function(P,$,undefined){
168
172
  finishGame(slug);
169
173
  }
170
174
  }
175
+
176
+ var updateLogicAfterReceivedGameRequestError = function(slug){
177
+ if(contactsInfo[slug].gameStatus!="waiting"){
178
+ return true;
179
+ }
180
+ P.GAME.INTERFACE.updateInterfaceOnInformationMessage(slug,I18n.t("chat.game.clientIssue", {name: PRESENCE.XMPPClient.getNameFromSlug(slug)}));
181
+ contactsInfo[slug].gameStatus="disconnected";
182
+ }
171
183
 
172
184
  var getPlayerNameWithId = function(slug){
173
185
  if(! slug in contactsInfo){
@@ -251,13 +263,13 @@ PRESENCE.GAME = (function(P,$,undefined){
251
263
  return;
252
264
  }
253
265
  } else {
254
- log("Warning: Missed " + game.name + " validateParams method")
266
+ PRESENCE.UTILITIES.log("Warning: Missed " + game.name + " validateParams method")
255
267
  }
256
268
 
257
269
  if(typeof PRESENCE.GAME[game.id].minimumRequirements == "function"){
258
270
  //Check requirements
259
271
  } else {
260
- log("Warning: Missed " + game.name + " minRequirements method")
272
+ PRESENCE.UTILITIES.log("Warning: Missed " + game.name + " minRequirements method")
261
273
  }
262
274
 
263
275
  //Add handler and remove previous if exits
@@ -301,16 +313,17 @@ PRESENCE.GAME = (function(P,$,undefined){
301
313
 
302
314
  return {
303
315
  init: init,
304
- game: game,
305
- player: player,
306
- startGame: startGame,
307
- finishGame: finishGame,
308
- createValidationResult: createValidationResult,
309
- requestUserToPlay: requestUserToPlay,
310
- responseUserToPlay: responseUserToPlay,
311
- updateLogicAfterReceivedGameRequest: updateLogicAfterReceivedGameRequest,
312
- updateLogicAfterReceivedGameRequestCancelation: updateLogicAfterReceivedGameRequestCancelation,
313
- updateLogicAfterReceivedGameRequestResponse: updateLogicAfterReceivedGameRequestResponse,
316
+ game : game,
317
+ player : player,
318
+ startGame : startGame,
319
+ finishGame : finishGame,
320
+ createValidationResult : createValidationResult,
321
+ requestUserToPlay : requestUserToPlay,
322
+ responseUserToPlay : responseUserToPlay,
323
+ updateLogicAfterReceivedGameRequest : updateLogicAfterReceivedGameRequest,
324
+ updateLogicAfterReceivedGameRequestCancelation : updateLogicAfterReceivedGameRequestCancelation,
325
+ updateLogicAfterReceivedGameRequestResponse : updateLogicAfterReceivedGameRequestResponse,
326
+ updateLogicAfterReceivedGameRequestError : updateLogicAfterReceivedGameRequestError,
314
327
  sendAction: sendAction,
315
328
  userDisconnected: userDisconnected
316
329
  };
@@ -10,10 +10,14 @@ PRESENCE.GAME.COMUNICATION = (function(P,$,undefined){
10
10
  //////////////////////////////////////////////
11
11
 
12
12
  var connection = null;
13
+ var iqStanzaID = new Array();
13
14
  iqStanzaID['gameRequest'] = "gameRequestID";
14
15
  iqStanzaID['gameRequestFinish'] = "gameRequestFinishID";
15
16
  iqStanzaID['gameAction'] = "gameActionID";
16
17
 
18
+ var getIQStanzaID = function(){
19
+ return iqStanzaID;
20
+ }
17
21
 
18
22
  /////////////////////////////////
19
23
  // COMUNICATION METHODS //
@@ -22,10 +26,13 @@ PRESENCE.GAME.COMUNICATION = (function(P,$,undefined){
22
26
  var init = function(myConnection){
23
27
  connection = myConnection;
24
28
  //addHandler:(callback, namespace to match, stanza name, stanza type, stanza id , stanza from, options)
25
- connection.addHandler(handleRequestGameIQStanza,null, "iq", "get",iqStanzaID['gameRequest'], null);
26
- connection.addHandler(handleIQResultFromGameRequest,null, "iq", "result",iqStanzaID['gameRequest'], null);
27
- connection.addHandler(handleIQResultFromGameRequestFinish,null, "iq", "result", iqStanzaID['gameRequestFinish'], null);
28
- connection.addHandler(handleActionIQStanza,null, "iq", "result", getIdForIqAction("gameId"), null);
29
+ if(connection){
30
+ connection.addHandler(handleRequestGameIQStanza,null, "iq", "get",iqStanzaID['gameRequest'], null);
31
+ connection.addHandler(handleIQResultFromGameRequest,null, "iq", "result",iqStanzaID['gameRequest'], null);
32
+ connection.addHandler(handleIQErrorFromGameRequest,null, "iq", "error",iqStanzaID['gameRequest'], null);
33
+ connection.addHandler(handleIQResultFromGameRequestFinish,null, "iq", "result", iqStanzaID['gameRequestFinish'], null);
34
+ connection.addHandler(handleActionIQStanza,null, "iq", "result", getIdForIqAction("gameId"), null);
35
+ }
29
36
  };
30
37
 
31
38
 
@@ -121,6 +128,7 @@ PRESENCE.GAME.COMUNICATION = (function(P,$,undefined){
121
128
 
122
129
  //RECEIVE GAME REQUEST RESPONSE
123
130
  var handleIQResultFromGameRequest = function(iq){
131
+
124
132
  var from = iq.getAttribute("from");
125
133
  var slug = from.split("@")[0];
126
134
  var queryTag = iq.getElementsByTagName('query');
@@ -134,9 +142,17 @@ PRESENCE.GAME.COMUNICATION = (function(P,$,undefined){
134
142
  return true;
135
143
  }
136
144
  }
145
+
137
146
  return true;
138
147
  }
139
148
 
149
+ //RECEIVE GAME REQUEST ERROR RESPONSE
150
+ var handleIQErrorFromGameRequest = function(iq){
151
+ var from = iq.getAttribute("from");
152
+ var slug = from.split("@")[0];
153
+ P.GAME.updateLogicAfterReceivedGameRequestError(slug)
154
+ return true;
155
+ }
140
156
 
141
157
 
142
158
  /////////////////////
@@ -374,7 +390,8 @@ PRESENCE.GAME.COMUNICATION = (function(P,$,undefined){
374
390
  sendIQStanzaWithAction: sendIQStanzaWithAction,
375
391
  handleActionIQStanza: handleActionIQStanza,
376
392
  addHandler : addHandler,
377
- removeHandler: removeHandler
393
+ removeHandler: removeHandler,
394
+ getIQStanzaID : getIQStanzaID
378
395
  };
379
396
 
380
397
  }) (PRESENCE, jQuery);
@@ -25,7 +25,7 @@ PRESENCE.GAME.FACTORY = (function(P,$,undefined){
25
25
 
26
26
  var generateGame = function(guest_slug,gameId,options){
27
27
  var player1 = new PRESENCE.GAME.player(user_slug,user_name)
28
- var player2 = new PRESENCE.GAME.player(guest_slug,getNameFromSlug(guest_slug))
28
+ var player2 = new PRESENCE.GAME.player(guest_slug,PRESENCE.XMPPClient.getNameFromSlug(guest_slug))
29
29
  var players = [player1,player2]
30
30
  var mygame = new PRESENCE.GAME.game(gameId,getGameName(gameId),players,options)
31
31
  return mygame;
@@ -12,8 +12,8 @@ PRESENCE.GAME.INTERFACE = (function(P,$,undefined){
12
12
  //gameStatus="pending";
13
13
 
14
14
  //Show or create chatbox
15
- createBuddyChatBox(slug);
16
- var chatBox = getChatBoxForSlug(slug);
15
+ PRESENCE.WINDOW.createBuddyChatBox(slug);
16
+ var chatBox = PRESENCE.WINDOW.getChatBoxForSlug(slug);
17
17
 
18
18
  //Show invitation message
19
19
  showGameInvitation(slug,game);
@@ -22,7 +22,7 @@ PRESENCE.GAME.INTERFACE = (function(P,$,undefined){
22
22
  hideVideoChatButton(slug);
23
23
 
24
24
  //Show gamebox
25
- toggleVideoBoxForSlug(slug,true);
25
+ PRESENCE.WINDOW.toggleVideoBoxForSlug(slug,true);
26
26
  }
27
27
 
28
28
  var updateInterfaceBeforeStartGame = function(slug,game){
@@ -31,18 +31,18 @@ PRESENCE.GAME.INTERFACE = (function(P,$,undefined){
31
31
  parentDiv.setAttribute('id', divID);
32
32
  $(parentDiv).css('width', "100%");
33
33
  $(parentDiv).css('height', "100%");
34
- setVideoBoxContent(slug,parentDiv);
34
+ PRESENCE.WINDOW.setVideoBoxContent(slug,parentDiv);
35
35
 
36
36
  PRESENCE.GAME.startGame(slug,divID)
37
37
  }
38
38
 
39
39
  var updateInterfaceAfterFinishGame = function(slug,game){
40
- toggleVideoBoxForSlug(slug,false);
40
+ PRESENCE.WINDOW.toggleVideoBoxForSlug(slug,false);
41
41
  showVideoChatButton(slug);
42
42
  }
43
43
 
44
44
  var updateInterfaceOnInformationMessage = function(slug,msg){
45
- setVideoBoxContent(slug,"<p class=\"game-info\"> " + msg +" </p>");
45
+ PRESENCE.WINDOW.setVideoBoxContent(slug,"<p class=\"game-info\"> " + msg +" </p>");
46
46
  }
47
47
 
48
48
 
@@ -53,7 +53,7 @@ PRESENCE.GAME.INTERFACE = (function(P,$,undefined){
53
53
 
54
54
  var pickGamesButton = function (uiElement){
55
55
  var slug = $(uiElement.element).attr("id");
56
- var videoBoxVisibility = toggleVideoBoxForSlug(slug);
56
+ var videoBoxVisibility = PRESENCE.WINDOW.toggleVideoBoxForSlug(slug);
57
57
 
58
58
  if (videoBoxVisibility) {
59
59
  hideVideoChatButton(slug);
@@ -89,7 +89,7 @@ PRESENCE.GAME.INTERFACE = (function(P,$,undefined){
89
89
  }
90
90
  }
91
91
  var template = generateGameSelectionTemplate(slug,gameItem)
92
- setVideoBoxContent(slug,template);
92
+ PRESENCE.WINDOW.setVideoBoxContent(slug,template);
93
93
  setShowGamesButtonsFunction();
94
94
  }
95
95
 
@@ -184,10 +184,10 @@ PRESENCE.GAME.INTERFACE = (function(P,$,undefined){
184
184
  }
185
185
 
186
186
  var showGameInvitation = function(slug,game){
187
- var title = "<p class=\"game-info\">" + I18n.t("chat.game.call", {name: getNameFromSlug(slug), game: game.name}) + " </p>";
187
+ var title = "<p class=\"game-info\">" + I18n.t("chat.game.call", {name: PRESENCE.XMPPClient.getNameFromSlug(slug), game: game.name}) + " </p>";
188
188
  var msg = title + "<p class=\"game-request\"> <a class=\"gameButton\" slug=\""+slug+"\" value=\"yes\">" + I18n.t("chat.game.accept") + "</a> -"
189
189
  + " <a class=\"gameButton\" slug=\""+slug+"\" value=\"no\">" + I18n.t("chat.game.deny") + "</a> </p>";
190
- setVideoBoxContent(slug,msg);
190
+ PRESENCE.WINDOW.setVideoBoxContent(slug,msg);
191
191
  setGameRequestButtonsFunction();
192
192
  }
193
193
 
@@ -201,24 +201,44 @@ PRESENCE.GAME.INTERFACE = (function(P,$,undefined){
201
201
  }
202
202
 
203
203
  var hideVideoChatButton = function(slug){
204
- $(getChatBoxButtonForSlug(slug,"video")).hide();
204
+ $(PRESENCE.WINDOW.getChatBoxButtonForSlug(slug,"video")).hide();
205
205
  }
206
206
 
207
207
  var showVideoChatButton = function(slug){
208
- $(getChatBoxButtonForSlug(slug,"video")).show();
208
+ $(PRESENCE.WINDOW.getChatBoxButtonForSlug(slug,"video")).show();
209
209
  }
210
210
 
211
211
  var play = function(){
212
212
  $(".chat-gamesthick").css("display","block");
213
213
  }
214
214
 
215
+ var enableGameFeature = function(enable){
216
+ //Changing chat-gamesthick CSS class by JQuery
217
+ var ss = document.styleSheets;
218
+ for (var i=0; i<ss.length; i++) {
219
+ var rules = ss[i].cssRules || ss[i].rules;
220
+ if (rules != undefined){
221
+ for (var j=0; j<rules.length; j++) {
222
+ if (rules[j].selectorText === ".chat-gamesthick") {
223
+ if(enable){
224
+ rules[j].style.display = 'block'
225
+ } else {
226
+ rules[j].style.display = 'none'
227
+ }
228
+ }
229
+ }
230
+ }
231
+ }
232
+ }
233
+
215
234
  return {
216
235
  pickGamesButton: pickGamesButton,
217
236
  updateInterfaceAfterGameRequestReceived: updateInterfaceAfterGameRequestReceived,
218
237
  updateInterfaceBeforeStartGame: updateInterfaceBeforeStartGame,
219
238
  updateInterfaceAfterFinishGame: updateInterfaceAfterFinishGame,
220
239
  updateInterfaceOnInformationMessage: updateInterfaceOnInformationMessage,
221
- play: play
240
+ play: play,
241
+ enableGameFeature : enableGameFeature
222
242
  };
223
243
 
224
244
  }) (PRESENCE, jQuery);