@reactoo/watchtogether-sdk-js 2.5.16 → 2.5.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -29,7 +29,7 @@ class Room {
29
29
  }
30
30
 
31
31
  createSession(constructId = null, type = 'reactooroom', options = {}) {
32
- return new RoomSession(constructId, type, this.debug, options);
32
+ return new RoomSession(constructId, type, {debug: this.debug, ...options});
33
33
  }
34
34
 
35
35
  static testSafariVp8() {
@@ -88,19 +88,36 @@ class RoomSession {
88
88
  //TODO: solve
89
89
  // #eventList = ['error', 'kicked', 'addLocalParticipant', ,'addRemoteInstructor','addRemoteParticipant','addRemoteTalkback', 'addRemoteObserver', 'removeRemoteInstructor', 'removeLocalParticipant', 'removeRemoteParticipant', 'removeRemoteTalkback', 'removeRemoteObserver', 'localMuted', 'localHasVideo', 'localHasAudio', 'data', 'iceState', 'connectionState', 'joined', 'joining', 'dataChannel', 'disconnect', 'observerIds', 'talkbackIds', 'instructorId', 'published', 'publishing', 'remoteTrackMuted', 'streamingStatus', 'streaming', 'streamStarting'];
90
90
  //
91
- // #sessionTypes = {
92
- // 'reactooroom': 'janus.plugin.reactooroom',
93
- // 'streaming': 'janus.plugin.streaming'
94
- // };
95
91
 
96
- static sessionTypes() {
97
- return {
98
- 'reactooroom': 'janus.plugin.reactooroom',
99
- 'streaming': 'janus.plugin.streaming'
100
- }
92
+ static sessionTypes = {
93
+ 'reactooroom': 'janus.plugin.reactooroom',
94
+ 'streaming': 'janus.plugin.streaming'
95
+ }
96
+
97
+ static subscriptionRules = {
98
+ participant: {
99
+ watchTogether: ['participant', 'talkback'],
100
+ videoWall: ['instructor', 'observer', 'talkback']
101
+ },
102
+ monitor: {
103
+ watchTogether: ['participant'],
104
+ videoWall: ['instructor', 'participant'],
105
+ },
106
+ talkback: {
107
+ watchTogether: ['participant'],
108
+ videoWall: ['instructor', 'participant'],
109
+ },
110
+ observer: {
111
+ watchTogether: ['participant'],
112
+ videoWall: ['participant'],
113
+ },
114
+ instructor: {
115
+ watchTogether: [],
116
+ videoWall: [],
117
+ },
101
118
  };
102
119
 
103
- constructor(constructId = null, type = 'reactooroom', debug, options = {}) {
120
+ constructor(constructId = null, type = 'reactooroom', options = {}) {
104
121
 
105
122
  Object.assign(this, emitter());
106
123
 
@@ -113,18 +130,11 @@ class RoomSession {
113
130
  this.userId = null;
114
131
  this.sessiontype = type;
115
132
  this.initialBitrate = 0;
133
+ //TODO: remove this
116
134
  this.isMonitor = false; // currently used just for classroom context so monitor user only subscribes to participants and not trainer (for other monitor this flag is not necessary)
117
135
  this.recordingFilename = null;
118
- this.pluginName = RoomSession.sessionTypes()[type];
119
- this.options = {
120
- ...{
121
- debug: debug,
122
- classroomObserverSubscribeToInstructor: false,
123
- classroomInstructorSubscribeToParticipants: false,
124
- safariBugHotfixEnabled: adapter.browserDetails.browser === 'safari' && adapter.browserDetails.version < 605
125
- },
126
- options
127
- };
136
+ this.pluginName = RoomSession.sessionTypes[type];
137
+ this.options = options;
128
138
  this.id = null;
129
139
  this.privateId = null;
130
140
  this.constructId = constructId || RoomSession.randomString(16);
@@ -155,10 +165,17 @@ class RoomSession {
155
165
  this.isVideoEnabled = false;
156
166
  this.isAudioEnabed = false;
157
167
  this.isUnifiedPlan = RoomSession.checkUnifiedPlan();
168
+
169
+ this.subscriptionRules = {
170
+ ...RoomSession.subscriptionRules,
171
+ ...(this.options.subscriptionRules || {})
172
+ }
173
+
158
174
  this._log = RoomSession.noop;
159
175
  if (this.options.debug) {
160
176
  this._enableDebug();
161
177
  }
178
+
162
179
  }
163
180
 
164
181
  // Check if this browser supports Unified Plan and transceivers
@@ -189,6 +206,88 @@ class RoomSession {
189
206
  }
190
207
  return unifiedPlan;
191
208
  }
209
+
210
+ _participantShouldSubscribe(userId) {
211
+ let allowedObservers = this._observerIds || [];
212
+ let allowedTalkback = this._talkbackIds || [];
213
+ let allowedInstructor = this._instuctorId || null;
214
+ let localUserRole = 'participant';
215
+ if(this.isMonitor) {
216
+ localUserRole = 'monitor';
217
+ } else if(allowedObservers.indexOf(this.userId) > -1) {
218
+ localUserRole = 'observer';
219
+ } else if(allowedTalkback.indexOf(this.userId) > -1) {
220
+ localUserRole = 'talkback';
221
+ } else if(this.userId === allowedInstructor) {
222
+ localUserRole = 'instructor';
223
+ }
224
+ let remoteUserRole = 'participant';
225
+ if(allowedObservers.indexOf(userId) > -1) {
226
+ remoteUserRole = 'observer';
227
+ } else if(allowedTalkback.indexOf(userId) > -1) {
228
+ remoteUserRole = 'talkback';
229
+ } else if(userId === allowedInstructor) {
230
+ remoteUserRole = 'instructor';
231
+ }
232
+ let mode = allowedInstructor !== null ? 'videoWall' : 'watchTogether';
233
+ return this.subscriptionRules[localUserRole][mode].indexOf(remoteUserRole) > -1;
234
+ }
235
+
236
+ _getAddParticipantEventName(handleId) {
237
+
238
+ let handle = this._getHandle(handleId);
239
+ if (!handle) {
240
+ this.emit('error', {
241
+ type: 'warning',
242
+ id: 15,
243
+ message: 'id non-existent',
244
+ data: [handleId, 'getParticipantEventName']
245
+ });
246
+ }
247
+
248
+ let allowedTalkback = this._talkbackIds || [];
249
+ let allowedObservers = this._observerIds || [];
250
+ let allowedInstructor = this._instuctorId || null;
251
+ let eventName = 'addRemoteParticipant';
252
+ if(handle.userId === allowedInstructor) {
253
+ eventName = 'addRemoteInstructor';
254
+ }
255
+ if (allowedTalkback.indexOf(handle.userId) > -1) {
256
+ eventName = 'addRemoteTalkback';
257
+ }
258
+ if (allowedObservers.indexOf(handle.userId) > -1) {
259
+ eventName = 'addRemoteObserver';
260
+ }
261
+ return eventName
262
+ }
263
+
264
+ _getRemoveParticipantEventName(handleId) {
265
+
266
+ let handle = this._getHandle(handleId);
267
+ if (!handle) {
268
+ this.emit('error', {
269
+ type: 'warning',
270
+ id: 15,
271
+ message: 'id non-existent',
272
+ data: [handleId, 'getParticipantEventName']
273
+ });
274
+ }
275
+
276
+ let allowedTalkback = this._talkbackIds || [];
277
+ let allowedObservers = this._observerIds || [];
278
+ let allowedInstructor = this._instuctorId || null;
279
+ let eventName = 'removeRemoteParticipant';
280
+ if(handle.userId === allowedInstructor) {
281
+ eventName = 'removeRemoteInstructor';
282
+ }
283
+ if (allowedTalkback.indexOf(handle.userId) > -1) {
284
+ eventName = 'removeRemoteTalkback';
285
+ }
286
+ if (allowedObservers.indexOf(handle.userId) > -1) {
287
+ eventName = 'removeRemoteObserver';
288
+ }
289
+ return eventName
290
+ }
192
291
 
193
292
  sendMessage(handleId, message = {body: 'Example Body'}, dontWait = false, dontResolveOnAck = false) {
194
293
  return this._send({
@@ -280,7 +379,7 @@ class RoomSession {
280
379
  this.stopStream();
281
380
  }
282
381
 
283
- this.emit('error', {type: 'error', id: 4, message: 'lost connection to WebSockets', data: null});
382
+ this.emit('error', {type: 'error', id: 4, message: 'Lost connection to WebSockets', data: null});
284
383
  }
285
384
  }
286
385
 
@@ -316,7 +415,7 @@ class RoomSession {
316
415
  _stopKeepAlive() {
317
416
  clearTimeout(this._keepAliveId);
318
417
  }
319
-
418
+
320
419
  _handleWsEvents(event) {
321
420
 
322
421
  let json = JSON.parse(event.data);
@@ -382,10 +481,6 @@ class RoomSession {
382
481
  let unpublished = msg["unpublished"];
383
482
  let error = msg["error"];
384
483
 
385
- let allowedObservers = this._observerIds || [];
386
- let allowedTalkback = this._talkbackIds || [];
387
- let allowedInstructor = this._instuctorId || null;
388
-
389
484
  if (event === "joined") {
390
485
  this.id = msg["id"];
391
486
  this.privateId = msg["private_id"];
@@ -401,68 +496,7 @@ class RoomSession {
401
496
  streams[i]["display"] = userId;
402
497
  }
403
498
  this._log('Remote userId: ', userId);
404
-
405
- let isClassroom = allowedInstructor !== null;
406
- let subscribeCondition;
407
- let subCondition = false
408
-
409
- if(!isClassroom) {
410
- subscribeCondition = allowedObservers.indexOf(userId) === -1 && allowedTalkback.indexOf(this.userId) === -1;
411
- } else {
412
-
413
- // instructor -> everyone but observer
414
- if(this.options.classroomInstructorSubscribeToParticipants) {
415
- subCondition = this.userId === allowedInstructor && allowedObservers.indexOf(userId) === -1;
416
- }
417
-
418
- if(this.options.classroomObserverSubscribeToInstructor) {
419
-
420
- /*
421
-
422
- monitor/talkback -> all but talkback
423
- observer -> all but talkback
424
- instructor -> no one
425
- participant -> only instructor, observer and talkback
426
-
427
- 1st line -> Im not monitor/talkback and im not observer and im not instructor and user to subscribe is instructor or observer or talkback
428
- 2nd line -> Im monitor/talkback and im not instructor and user connecting is not talkback
429
- 3rd line -> Im observer and im not instructor and user connecting is not talkback
430
-
431
- */
432
-
433
- subscribeCondition = subCondition ||
434
- ((!this.isMonitor && allowedObservers.indexOf(this.userId) === -1 && this.userId !== allowedInstructor) && (userId === allowedInstructor || allowedObservers.indexOf(userId) > -1 || allowedTalkback.indexOf(userId) > -1)) ||
435
- (this.isMonitor && this.userId !== allowedInstructor && allowedTalkback.indexOf(userId) === -1) ||
436
- (allowedObservers.indexOf(this.userId) > -1 && this.userId !== allowedInstructor && allowedTalkback.indexOf(userId) === -1)
437
-
438
-
439
-
440
- } else {
441
-
442
- /*
443
-
444
- monitor/talkback -> all but talkback
445
- observer -> all but instructor and talkback
446
- instructor -> no one
447
- participant -> only instructor, observer and talkback
448
-
449
- 1st line -> Im not monitor/talkback and im not observer and im not instructor and user to subscribe is instructor or observer or talkback
450
- 2nd line -> Im monitor/talkback and im not instructor and user connecting is not talkback
451
- 3rd line -> Im observer and im not instructor and user connecting is not instructor and its not talkback
452
-
453
- */
454
-
455
- subscribeCondition = subCondition ||
456
- ((!this.isMonitor && allowedObservers.indexOf(this.userId) === -1 && this.userId !== allowedInstructor) && (userId === allowedInstructor || allowedObservers.indexOf(userId) > -1 || allowedTalkback.indexOf(userId) > -1)) ||
457
- (this.isMonitor && this.userId !== allowedInstructor && allowedTalkback.indexOf(userId) === -1) ||
458
- (allowedObservers.indexOf(this.userId) > -1 && this.userId !== allowedInstructor && userId !== allowedInstructor && allowedTalkback.indexOf(userId) === -1)
459
-
460
- }
461
-
462
-
463
- }
464
-
465
- if (subscribeCondition) {
499
+ if (this._participantShouldSubscribe(userId)) {
466
500
  this._log('Creating user: ', userId);
467
501
  this._createParticipant(userId, id)
468
502
  .then(handle => {
@@ -497,66 +531,7 @@ class RoomSession {
497
531
  streams[i]["display"] = userId;
498
532
  }
499
533
  this._log('Remote userId: ', userId);
500
-
501
- let isClassroom = allowedInstructor !== null;
502
- let subscribeCondition;
503
- let subCondition = false
504
-
505
- if(!isClassroom) {
506
- subscribeCondition = allowedObservers.indexOf(userId) === -1 && allowedTalkback.indexOf(this.userId) === -1;
507
- } else {
508
-
509
- // instructor -> everyone but observer
510
- if(this.options.classroomInstructorSubscribeToParticipants) {
511
- subCondition = this.userId === allowedInstructor && allowedObservers.indexOf(userId) === -1;
512
- }
513
-
514
- if(this.options.classroomObserverSubscribeToInstructor) {
515
-
516
- /*
517
-
518
- monitor/talkback -> all but talkback
519
- observer -> all but talkback
520
- instructor -> no one
521
- participant -> only instructor, observer and talkback
522
-
523
- 1st line -> Im not monitor/talkback and im not observer and im not instructor and user to subscribe is instructor or observer or talkback
524
- 2nd line -> Im monitor/talkback and im not instructor and user connecting is not talkback
525
- 3rd line -> Im observer and im not instructor and user connecting is not talkback
526
-
527
- */
528
-
529
- subscribeCondition = subCondition ||
530
- ((!this.isMonitor && allowedObservers.indexOf(this.userId) === -1 && this.userId !== allowedInstructor) && (userId === allowedInstructor || allowedObservers.indexOf(userId) > -1 || allowedTalkback.indexOf(userId) > -1)) ||
531
- (this.isMonitor && this.userId !== allowedInstructor && allowedTalkback.indexOf(userId) === -1) ||
532
- (allowedObservers.indexOf(this.userId) > -1 && this.userId !== allowedInstructor && allowedTalkback.indexOf(userId) === -1)
533
-
534
-
535
-
536
- } else {
537
-
538
- /*
539
-
540
- monitor/talkback -> all but talkback
541
- observer -> all but instructor and talkback
542
- instructor -> no one
543
- participant -> only instructor, observer and talkback
544
-
545
- 1st line -> Im not monitor/talkback and im not observer and im not instructor and user to subscribe is instructor or observer or talkback
546
- 2nd line -> Im monitor/talkback and im not instructor and user connecting is not talkback
547
- 3rd line -> Im observer and im not instructor and user connecting is not instructor and its not talkback
548
-
549
- */
550
-
551
- subscribeCondition = subCondition ||
552
- ((!this.isMonitor && allowedObservers.indexOf(this.userId) === -1 && this.userId !== allowedInstructor) && (userId === allowedInstructor || allowedObservers.indexOf(userId) > -1 || allowedTalkback.indexOf(userId) > -1)) ||
553
- (this.isMonitor && this.userId !== allowedInstructor && allowedTalkback.indexOf(userId) === -1) ||
554
- (allowedObservers.indexOf(this.userId) > -1 && this.userId !== allowedInstructor && userId !== allowedInstructor && allowedTalkback.indexOf(userId) === -1)
555
-
556
- }
557
- }
558
-
559
- if (subscribeCondition) {
534
+ if (this._participantShouldSubscribe(userId)) {
560
535
  this._log('Creating user: ', userId);
561
536
  this._createParticipant(userId, id)
562
537
  .then(handle => {
@@ -660,16 +635,7 @@ class RoomSession {
660
635
 
661
636
  if (event === "attached") {
662
637
  this._log('Remote have successfully joined Room', msg);
663
- let allowedTalkback = this._talkbackIds || [];
664
- let allowedObservers = this._observerIds || [];
665
- let eventName = 'addRemoteParticipant';
666
- if (allowedTalkback.indexOf(handle.userId) > -1) {
667
- eventName = 'addRemoteTalkback';
668
- }
669
- if (allowedObservers.indexOf(handle.userId) > -1) {
670
- eventName = 'addRemoteObserver';
671
- }
672
- this.emit(eventName, {
638
+ this.emit(this._getAddParticipantEventName(handle.handleId), {
673
639
  tid: generateUUID(),
674
640
  id: handle.handleId,
675
641
  userId: handle.userId,
@@ -807,20 +773,7 @@ class RoomSession {
807
773
  this.emit('published', {status: false, hasStream: false});
808
774
  this.emit('removeLocalParticipant', {id: handleId, userId: handle.userId});
809
775
  } else {
810
- let allowedTalkback = this._talkbackIds || [];
811
- let allowedObservers = this._observerIds || [];
812
- let allowedInstructor = this._instuctorId || null;
813
- let eventName = 'removeRemoteParticipant';
814
- if(handle.userId === allowedInstructor) {
815
- eventName = 'removeRemoteInstructor';
816
- }
817
- if (allowedTalkback.indexOf(handle.userId) > -1) {
818
- eventName = 'removeRemoteTalkback';
819
- }
820
- if (allowedObservers.indexOf(handle.userId) > -1) {
821
- eventName = 'removeRemoteObserver';
822
- }
823
- this.emit(eventName, {id: handleId, userId: handle.userId});
776
+ this.emit(this._getRemoveParticipantEventName(handleId), {id: handleId, userId: handle.userId});
824
777
  }
825
778
 
826
779
  if (removeHandle) {
@@ -1134,7 +1087,7 @@ class RoomSession {
1134
1087
  _enableDebug() {
1135
1088
  this._log = console.log.bind(console);
1136
1089
  }
1137
-
1090
+
1138
1091
  _getHandle(handleId, rfid = null) {
1139
1092
  return this._participants.find(p => p.handleId === handleId || (rfid && p.rfid === rfid));
1140
1093
  }
@@ -1198,12 +1151,40 @@ class RoomSession {
1198
1151
  this._iceRestart(handleId);
1199
1152
  }
1200
1153
  this.emit('connectionState', [handleId, handleId === this.handleId, config.pc.connectionState]);
1154
+ if(handleId !== this.handleId && config.pc.connectionState === 'connected') {
1155
+ this.emit(this._getAddParticipantEventName(handle.handleId), {
1156
+ tid: generateUUID(),
1157
+ id: handle.handleId,
1158
+ userId: handle.userId,
1159
+ stream: config.stream,
1160
+ optional: true,
1161
+ constructId: this.constructId,
1162
+ metaData: this.options.metaData,
1163
+ adding: true,
1164
+ hasAudioTrack: !!(config.stream && config.stream.getAudioTracks().length),
1165
+ hasVideoTrack: !!(config.stream && config.stream.getVideoTracks().length)
1166
+ })
1167
+ }
1201
1168
  };
1202
1169
  config.pc.oniceconnectionstatechange = () => {
1203
1170
  if (config.pc.iceConnectionState === 'failed') {
1204
1171
  this._iceRestart(handleId);
1205
1172
  }
1206
1173
  this.emit('iceState', [handleId, handleId === this.handleId, config.pc.iceConnectionState]);
1174
+ if(handleId !== this.handleId && (config.pc.iceConnectionState === 'completed' || config.pc.iceConnectionState === 'connected')) {
1175
+ this.emit(this._getAddParticipantEventName(handle.handleId), {
1176
+ tid: generateUUID(),
1177
+ id: handle.handleId,
1178
+ userId: handle.userId,
1179
+ stream: config.stream,
1180
+ optional: true,
1181
+ constructId: this.constructId,
1182
+ metaData: this.options.metaData,
1183
+ adding: true,
1184
+ hasAudioTrack: !!(config.stream && config.stream.getAudioTracks().length),
1185
+ hasVideoTrack: !!(config.stream && config.stream.getVideoTracks().length)
1186
+ })
1187
+ }
1207
1188
  };
1208
1189
  config.pc.onicecandidate = (event) => {
1209
1190
  if (event.candidate == null || (adapter.browserDetails.browser === 'edge' && event.candidate.candidate.indexOf('endOfCandidates') > 0)) {
@@ -1241,26 +1222,8 @@ class RoomSession {
1241
1222
  }
1242
1223
 
1243
1224
  if (event.track) {
1244
-
1245
1225
  config.stream.addTrack(event.track);
1246
-
1247
- let allowedTalkback = this._talkbackIds || [];
1248
- let allowedObservers = this._observerIds || [];
1249
- let allowedInstructor = this._instuctorId || null;
1250
- let eventName = 'addRemoteParticipant';
1251
- if(handle.userId === allowedInstructor) {
1252
- eventName = 'addRemoteInstructor';
1253
- }
1254
- if (allowedTalkback.indexOf(handle.userId) > -1) {
1255
- eventName = 'addRemoteTalkback';
1256
- }
1257
- if (allowedObservers.indexOf(handle.userId) > -1) {
1258
- eventName = 'addRemoteObserver';
1259
- }
1260
-
1261
- this._log(eventName, 'ontrack');
1262
-
1263
- this.emit(eventName, {
1226
+ this.emit(this._getAddParticipantEventName(handle.handleId), {
1264
1227
  tid: generateUUID(),
1265
1228
  id: handle.handleId,
1266
1229
  userId: handle.userId,
@@ -1277,25 +1240,9 @@ class RoomSession {
1277
1240
  return;
1278
1241
 
1279
1242
  event.track.onended = (ev) => {
1280
-
1281
- let allowedTalkback = this._talkbackIds || [];
1282
- let allowedObservers = this._observerIds || [];
1283
- let allowedInstructor = this._instuctorId || null;
1284
- let eventName = 'addRemoteParticipant';
1285
- if(handle.userId === allowedInstructor) {
1286
- eventName = 'addRemoteInstructor';
1287
- }
1288
- if (allowedTalkback.indexOf(handle.userId) > -1) {
1289
- eventName = 'addRemoteTalkback';
1290
- }
1291
- if (allowedObservers.indexOf(handle.userId) > -1) {
1292
- eventName = 'addRemoteObserver';
1293
- }
1294
-
1295
- this._log(eventName, 'onended');
1296
1243
  if (config.stream) {
1297
1244
  config.stream && config.stream.removeTrack(ev.target);
1298
- this.emit(eventName, {
1245
+ this.emit(this._getAddParticipantEventName(handle.handleId), {
1299
1246
  tid: generateUUID(),
1300
1247
  id: handle.handleId,
1301
1248
  userId: handle.userId,
@@ -1371,7 +1318,7 @@ class RoomSession {
1371
1318
 
1372
1319
  let handle = this._getHandle(handleId);
1373
1320
  if (!handle) {
1374
- return Promise.reject({type: 'warning', id: 16, message: 'id non-existent', data: [handleId, 'rtc peer']});
1321
+ return Promise.reject({type: 'warning', id: 15, message: 'id non-existent', data: [handleId, 'rtc peer']});
1375
1322
  }
1376
1323
 
1377
1324
  var config = handle.webrtcStuff;
@@ -1461,7 +1408,7 @@ class RoomSession {
1461
1408
  if (!handle) {
1462
1409
  return Promise.reject({
1463
1410
  type: 'warning',
1464
- id: 17,
1411
+ id: 15,
1465
1412
  message: 'id non-existent',
1466
1413
  data: [handleId, 'createAO', type]
1467
1414
  });
@@ -1638,7 +1585,7 @@ class RoomSession {
1638
1585
  if (!handle) {
1639
1586
  return Promise.reject({
1640
1587
  type: 'warning',
1641
- id: 18,
1588
+ id: 15,
1642
1589
  message: 'id non-existent',
1643
1590
  data: [handleId, 'publish remote participant']
1644
1591
  })
@@ -1936,10 +1883,7 @@ class RoomSession {
1936
1883
  }
1937
1884
  let config = handle.webrtcStuff;
1938
1885
 
1939
- if(this.options.safariBugHotfixEnabled) {
1940
- this.isVideoMuted = !this.isVideoMuted;
1941
- }
1942
- else if (this.isUnifiedPlan) {
1886
+ if (this.isUnifiedPlan) {
1943
1887
  let transceiver = config.pc.getTransceivers()
1944
1888
  .find(t => t.sender && t.sender.track && t.receiver.track.kind === "video" && t.stopped === false);
1945
1889
  if (transceiver) {