@reactoo/watchtogether-sdk-js 2.6.61 → 2.6.63

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.
@@ -149,12 +149,12 @@
149
149
  Instance.room.getSessionByConstructId(constructId).toggleAudio()
150
150
  }
151
151
 
152
- function setListenIntercomGroups(groups) {
153
- Instance.room.getSessionByConstructId(constructId).setListenIntercomGroups(groups)
152
+ function setListenIntercomChannels(groups) {
153
+ Instance.room.getSessionByConstructId(constructId).setListenIntercomChannels(groups)
154
154
  }
155
155
 
156
- function setTalkIntercomGroups(groups) {
157
- Instance.room.getSessionByConstructId(constructId).setTalkIntercomGroups(groups)
156
+ function setTalkIntercomChannels(groups) {
157
+ Instance.room.getSessionByConstructId(constructId).setTalkIntercomChannels(groups)
158
158
  }
159
159
 
160
160
  let Instance = WatchTogetherSDK({debug:true, apiUrl: 'https://api.reactoo.com/stefan/swagger.json'})({instanceType:'reactooDemo'});
@@ -212,6 +212,9 @@
212
212
  }})) // pin hash is not needed if you're owner of the room
213
213
  .then(session => {
214
214
 
215
+ session.setTalkIntercomChannels([]);
216
+ session.setListenIntercomChannels([]);
217
+
215
218
  session.$on('connecting', (status) => {
216
219
  console.log('connecting', status);
217
220
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reactoo/watchtogether-sdk-js",
3
- "version": "2.6.61",
3
+ "version": "2.6.63",
4
4
  "description": "Javascript SDK for Reactoo",
5
5
  "main": "src/index.js",
6
6
  "unpkg": "dist/watchtogether-sdk.min.js",
@@ -336,16 +336,16 @@ let roomSession = function ({roomId, pinHash, role}, room, wt) {
336
336
  return room.toggleVideo(value, source);
337
337
  },
338
338
 
339
- setTalkIntercomGroups: (groups) => {
340
- return room.setTalkIntercomGroups(groups);
339
+ setTalkIntercomChannels: (groups) => {
340
+ return room.setTalkIntercomChannels(groups);
341
341
  },
342
342
 
343
343
  getTalkIntercomGroups: () => {
344
344
  return room._talkIntercomGroups;
345
345
  },
346
346
 
347
- setListenIntercomGroups: (groups) => {
348
- return room.setListenIntercomGroups(groups);
347
+ setListenIntercomChannels: (groups) => {
348
+ return room.setListenIntercomChannels(groups);
349
349
  },
350
350
 
351
351
  getListenIntercomGroups: () => {
@@ -202,8 +202,8 @@ class RoomSession {
202
202
  this._maxRetries = 5;
203
203
  this._keepAliveId = null;
204
204
  this._participants = [];
205
- this._talkIntercomGroups = ['participants'];
206
- this._listenIntercomGroups = ['participants'];
205
+ this._talkIntercomChannels = ['participants'];
206
+ this._listenIntercomChannels = ['participants'];
207
207
  this._roomType = 'watchparty';
208
208
  this._isDataChannelOpen = false;
209
209
  this._abortController = null;
@@ -232,7 +232,7 @@ class RoomSession {
232
232
  return true;
233
233
  }
234
234
  const intercomGroups = JSON.parse(stream.description || "[]")?.intercomGroups || [];
235
- return intercomGroups.some(g => this._listenIntercomGroups.indexOf(g) > -1);
235
+ return intercomGroups.some(g => this._listenIntercomChannels.indexOf(g) > -1);
236
236
  };
237
237
 
238
238
  _getAddParticipantEventName(handleId) {
@@ -565,13 +565,15 @@ class RoomSession {
565
565
  this._createParticipant(userId, id)
566
566
  .then(handle => {
567
567
  this._updateParticipantsTrackData(handle.handleId, streams);
568
+ const subscribe = streams.filter(s => !s.disabled && this._intercomSubscribe(s)).map(stream => ({feed: stream.id, mid: stream.mid}));
569
+ handle.webrtcStuff.subscribeMap = structuredClone(subscribe);
568
570
  return this.sendMessage(handle.handleId, {
569
571
  body: {
570
572
  "request": "join",
571
573
  "room": this.roomId,
572
574
  "ptype": "subscriber",
573
575
  "private_id": this.privateId,
574
- streams: streams.filter(s => !s.disabled && this._intercomSubscribe(s)).map(stream => ({feed: stream.id, mid: stream.mid})),
576
+ streams: subscribe,
575
577
  //"feed": id,
576
578
  ...(this.webrtcVersion > 1000 ? {id: this.userId} : {}),
577
579
  pin: this.pin
@@ -608,12 +610,14 @@ class RoomSession {
608
610
  this._updateParticipantsTrackData(handle.handleId, streams)
609
611
 
610
612
  let subscribe = streams
611
- .filter(stream => !stream.disabled && this._intercomSubscribe(stream) && !this._isAlreadySubscribed(handle.handleId, stream))
613
+ .filter(stream => !stream.disabled && this._intercomSubscribe(stream) && !this._isAlreadySubscribed(handle.handleId, stream.id, stream.mid))
612
614
  .map(s => ({feed: s.id, mid: s.mid}));
613
615
 
614
616
  let unsubscribe = streams.filter(stream => stream.disabled || !this._intercomSubscribe(stream))
615
617
  .map(s => ({feed: s.id, mid: s.mid}));
616
618
 
619
+ this._updateSubscribeMap(handle.handleId, subscribe, unsubscribe);
620
+
617
621
  this._log('Already subscribed to user: ', userId, 'Update streams', subscribe, unsubscribe);
618
622
 
619
623
  if(subscribe.length || unsubscribe.length) {
@@ -631,13 +635,15 @@ class RoomSession {
631
635
  this._createParticipant(userId, id)
632
636
  .then(handle => {
633
637
  this._updateParticipantsTrackData(handle.handleId, streams);
638
+ const subscribe = streams.filter(s => !s.disabled && this._intercomSubscribe(s)).map(stream => ({feed: stream.id, mid: stream.mid}));
639
+ handle.webrtcStuff.subscribeMap = structuredClone(subscribe);
634
640
  return this.sendMessage(handle.handleId, {
635
641
  body: {
636
642
  "request": "join",
637
643
  "room": this.roomId,
638
644
  "ptype": "subscriber",
639
645
  "private_id": this.privateId,
640
- streams: streams.filter(s => !s.disabled && this._intercomSubscribe(s)).map(stream => ({feed: stream.id, mid: stream.mid})),
646
+ streams: subscribe,
641
647
  ...(this.webrtcVersion > 1000 ? {id: this.userId} : {}),
642
648
  pin: this.pin
643
649
  }
@@ -746,12 +752,17 @@ class RoomSession {
746
752
 
747
753
  if (event === "updated") {
748
754
  this._log('Remote has updated tracks', msg);
749
- this._updateCurrentSubscriptions(handle.handleId, msg["streams"] || []);
755
+ if(msg["streams"]) {
756
+ this._updateTransceiverMap(handle.handleId, msg["streams"]);
757
+ }
758
+
750
759
  }
751
760
 
752
761
  if (event === "attached") {
753
762
  this._log('Remote have successfully joined Room', msg);
754
- this._updateCurrentSubscriptions(handle.handleId, msg["streams"] || []);
763
+ if(msg["streams"]) {
764
+ this._updateTransceiverMap(handle.handleId, msg["streams"] || []);
765
+ }
755
766
  this.emit(this._getAddParticipantEventName(handle.handleId), {
756
767
  tid: generateUUID(),
757
768
  id: handle.handleId,
@@ -855,18 +866,20 @@ class RoomSession {
855
866
  try {
856
867
  if (handle.webrtcStuff.stream) {
857
868
  if(!this.isRestarting) {
858
- handle.webrtcStuff.stream.getTracks().forEach(track => track.stop());
869
+ handle.webrtcStuff.stream?.getTracks().forEach(track => track.stop());
859
870
  }
860
871
  else {
861
- handle.webrtcStuff.stream.getTracks().forEach(track => track.onended = null);
872
+ handle.webrtcStuff.stream?.getTracks().forEach(track => track.onended = null);
862
873
  }
863
874
  }
864
875
  } catch (e) {
865
876
  // Do nothing
866
877
  }
867
878
 
868
- handle.webrtcStuff.stream.onremovetrack = null;
869
- handle.webrtcStuff.stream = null;
879
+ if(handle.webrtcStuff.stream) {
880
+ handle.webrtcStuff.stream.onremovetrack = null;
881
+ handle.webrtcStuff.stream = null;
882
+ }
870
883
 
871
884
  if (handle.webrtcStuff.dataChannel) {
872
885
  Object.keys(handle.webrtcStuff.dataChannel).forEach(label => {
@@ -892,7 +905,8 @@ class RoomSession {
892
905
  stream: null,
893
906
  streamMap: {},
894
907
  tracksMap: [],
895
- currentSubscriptions: [],
908
+ transceiverMap: [],
909
+ subscribeMap: [],
896
910
  mySdp: null,
897
911
  mediaConstraints: null,
898
912
  pc: null,
@@ -944,7 +958,8 @@ class RoomSession {
944
958
  stream: null,
945
959
  streamMap: {},
946
960
  tracksMap: [],
947
- currentSubscriptions: [],
961
+ transceiverMap: [],
962
+ subscribeMap: [],
948
963
  mySdp: null,
949
964
  mediaConstraints: null,
950
965
  pc: null,
@@ -961,7 +976,33 @@ class RoomSession {
961
976
  })
962
977
  }
963
978
 
964
- _isAlreadySubscribed(handleId, stream) {
979
+
980
+ _updateSubscribeMap(handleId, subscribe, unsubscribe) {
981
+ let handle = this._getHandle(handleId);
982
+ if (!handle) {
983
+ this.emit('error', {
984
+ type: 'warning',
985
+ id: 15,
986
+ message: 'id non-existent',
987
+ data: [handleId, 'updateSubscribeMap']
988
+ });
989
+ return;
990
+ }
991
+ let currentSubscribeMap = handle.webrtcStuff.subscribeMap;
992
+ subscribe.forEach(s => {
993
+ if(!currentSubscribeMap.find(c => c.feed === s.feed && c.mid === s.mid)) {
994
+ currentSubscribeMap.push(s);
995
+ }
996
+ });
997
+ unsubscribe.forEach(s => {
998
+ let index = currentSubscribeMap.findIndex(c => c.feed === s.feed && c.mid === s.mid);
999
+ if(index > -1) {
1000
+ currentSubscribeMap.splice(index, 1);
1001
+ }
1002
+ });
1003
+ }
1004
+
1005
+ _isAlreadySubscribed(handleId, feed, mid) {
965
1006
  let handle = this._getHandle(handleId);
966
1007
  if (!handle) {
967
1008
  this.emit('error', {
@@ -972,23 +1013,23 @@ class RoomSession {
972
1013
  });
973
1014
  return;
974
1015
  }
975
- return handle.webrtcStuff.currentSubscriptions.filter(t => t.active).findIndex(t => t.mid === stream.mid) > -1
1016
+ return handle.webrtcStuff.subscribeMap.findIndex(t => t.mid === mid && t.feed === feed) > -1
976
1017
  }
977
1018
 
978
- _updateCurrentSubscriptions(handleId, streams) {
979
- this._log('Updating current subscription data', handleId, streams);
1019
+ _updateTransceiverMap(handleId, streams) {
1020
+ this._log('Updating current transceiver map', handleId, streams);
980
1021
  let handle = this._getHandle(handleId);
981
1022
  if (!handle) {
982
1023
  this.emit('error', {
983
1024
  type: 'warning',
984
1025
  id: 15,
985
1026
  message: 'id non-existent',
986
- data: [handleId, 'updateCurrentSubscriptions']
1027
+ data: [handleId, 'updateTransceiverMap']
987
1028
  });
988
1029
  return;
989
1030
  }
990
1031
  let config = handle.webrtcStuff;
991
- config.currentSubscriptions = structuredClone(streams);
1032
+ config.transceiverMap = structuredClone(streams);
992
1033
  }
993
1034
 
994
1035
  _updateParticipantsTrackData(handleId, streams) {
@@ -1030,18 +1071,18 @@ class RoomSession {
1030
1071
  }
1031
1072
  let config = handle.webrtcStuff;
1032
1073
  config.streamMap = {};
1033
- config.tracksMap.forEach(tItem => {
1074
+ config.transceiverMap.forEach(tItem => {
1034
1075
  if(tItem.type === 'data') {
1035
1076
  return;
1036
1077
  }
1037
1078
  if(tItem.active === false) {
1038
1079
  return;
1039
1080
  }
1040
- const source = JSON.parse(tItem.description)?.source;
1081
+ const source = JSON.parse(tItem.feed_description)?.source;
1041
1082
  if(!config.streamMap[source]) {
1042
1083
  config.streamMap[source] = [];
1043
1084
  }
1044
- let trackId = config.pc.getTransceivers().find(t => t.mid === tItem.mid).receiver.track.id;
1085
+ let trackId = config.pc.getTransceivers().find(t => t.mid === tItem.mid)?.receiver?.track?.id;
1045
1086
  if(trackId) {
1046
1087
  config.streamMap[source].push(trackId);
1047
1088
  }
@@ -1537,13 +1578,13 @@ class RoomSession {
1537
1578
  if(!this._getHandle(handle.handleId)) {
1538
1579
  return;
1539
1580
  }
1581
+ this._updateRemoteParticipantStreamMap(handle.handleId);
1540
1582
 
1541
1583
  let transceiver = config.pc?.getTransceivers()?.find(
1542
1584
  t => t.receiver.track === ev.track);
1543
1585
 
1544
1586
  let mid = transceiver?.mid || ev.track.id;
1545
1587
  let source = Object.keys(config.streamMap).find(key => config.streamMap[key].includes(ev.track.id));
1546
- this._updateRemoteParticipantStreamMap(handle.handleId);
1547
1588
  this.emit(this._getAddParticipantEventName(handle.handleId), {
1548
1589
  tid: generateUUID(),
1549
1590
  id: handle.handleId,
@@ -1565,9 +1606,9 @@ class RoomSession {
1565
1606
 
1566
1607
  if (event.track) {
1567
1608
  config.stream?.addTrack(event.track);
1609
+ this._updateRemoteParticipantStreamMap(handle.handleId);
1568
1610
  let mid = event.transceiver ? event.transceiver.mid : event.track.id;
1569
1611
  let source = Object.keys(config.streamMap).find(key => config.streamMap[key].includes(event.track.id));
1570
- this._updateRemoteParticipantStreamMap(handle.handleId);
1571
1612
  this.emit(this._getAddParticipantEventName(handle.handleId), {
1572
1613
  tid: generateUUID(),
1573
1614
  mid,
@@ -1595,11 +1636,11 @@ class RoomSession {
1595
1636
  if(!this._getHandle(handle.handleId)) {
1596
1637
  return;
1597
1638
  }
1639
+ this._updateRemoteParticipantStreamMap(handle.handleId);
1598
1640
  let transceiver = config.pc?.getTransceivers()?.find(
1599
1641
  t => t.receiver.track === ev.target);
1600
1642
  let mid = transceiver?.mid || ev.target.id;
1601
1643
  let source = Object.keys(config.streamMap).find(key => config.streamMap[key].includes(ev.target.id));
1602
- this._updateRemoteParticipantStreamMap(handle.handleId);
1603
1644
  this.emit(this._getAddParticipantEventName(handle.handleId), {
1604
1645
  tid: generateUUID(),
1605
1646
  id: handle.handleId,
@@ -1802,7 +1843,6 @@ class RoomSession {
1802
1843
  }
1803
1844
 
1804
1845
  _setupTransceivers(handleId, [audioSend, audioRecv, videoSend, videoRecv, audioTransceiver = null, videoTransceiver = null]) {
1805
-
1806
1846
  //TODO: this should be refactored to use handle's trackMap so we dont have to pass any parameters
1807
1847
 
1808
1848
  let handle = this._getHandle(handleId);
@@ -1811,7 +1851,7 @@ class RoomSession {
1811
1851
  }
1812
1852
  let config = handle.webrtcStuff;
1813
1853
 
1814
- const setTransceiver = (transceiver, send, recv) => {
1854
+ const setTransceiver = (transceiver, send, recv, kind = 'audio') => {
1815
1855
  if (!send && !recv) {
1816
1856
  // disabled: have we removed it?
1817
1857
  if (transceiver) {
@@ -1847,7 +1887,7 @@ class RoomSession {
1847
1887
  }
1848
1888
  } else {
1849
1889
  // In theory, this is the only case where we might not have a transceiver yet
1850
- config.pc.addTransceiver("audio", {direction: "recvonly"});
1890
+ config.pc.addTransceiver(kind, {direction: "recvonly"});
1851
1891
  }
1852
1892
  }
1853
1893
  }
@@ -1856,10 +1896,10 @@ class RoomSession {
1856
1896
  // if we're passing any transceivers, we work only on them, doesn't matter if one of them is null
1857
1897
  if(audioTransceiver || videoTransceiver) {
1858
1898
  if(audioTransceiver) {
1859
- setTransceiver(audioTransceiver, audioSend, audioRecv);
1899
+ setTransceiver(audioTransceiver, audioSend, audioRecv, 'audio');
1860
1900
  }
1861
1901
  if(videoTransceiver) {
1862
- setTransceiver(videoTransceiver, videoSend, videoRecv);
1902
+ setTransceiver(videoTransceiver, videoSend, videoRecv, 'video');
1863
1903
  }
1864
1904
  }
1865
1905
  // else we work on all transceivers
@@ -1872,13 +1912,13 @@ class RoomSession {
1872
1912
  (t.sender && t.sender.track && t.sender.track.kind === "audio") ||
1873
1913
  (t.receiver && t.receiver.track && t.receiver.track.kind === "audio")
1874
1914
  ) {
1875
- setTransceiver(t, audioSend, audioRecv);
1915
+ setTransceiver(t, audioSend, audioRecv, 'audio');
1876
1916
  }
1877
1917
  if (
1878
1918
  (t.sender && t.sender.track && t.sender.track.kind === "video") ||
1879
1919
  (t.receiver && t.receiver.track && t.receiver.track.kind === "video")
1880
1920
  ) {
1881
- setTransceiver(t, videoSend, videoRecv);
1921
+ setTransceiver(t, videoSend, videoRecv, 'video');
1882
1922
  }
1883
1923
  }
1884
1924
  }
@@ -2238,6 +2278,7 @@ class RoomSession {
2238
2278
 
2239
2279
  let hasAudio = !!(stream && stream.getAudioTracks().length > 0);
2240
2280
  let hasVideo = !!(stream && stream.getVideoTracks().length > 0);
2281
+
2241
2282
  this._setupTransceivers(this.handleId, [hasAudio, false, hasVideo, false, audioTransceiver, videoTransceiver]);
2242
2283
 
2243
2284
  const emitEvents = () => {
@@ -2341,7 +2382,7 @@ class RoomSession {
2341
2382
  config.streamMap[source].forEach(trackId => {
2342
2383
  let t = transceivers.find(transceiver => transceiver.sender.track && transceiver.sender.track.id === trackId)
2343
2384
  if(t) {
2344
- descriptions.push({mid: t.mid, description: JSON.stringify({source, intercomGroups: this._talkIntercomGroups})});
2385
+ descriptions.push({mid: t.mid, description: JSON.stringify({source, intercomGroups: this._talkIntercomChannels})});
2345
2386
  }
2346
2387
  })
2347
2388
  });
@@ -2496,14 +2537,14 @@ class RoomSession {
2496
2537
  }
2497
2538
 
2498
2539
 
2499
- setTalkIntercomGroups(groups = ['participants']) {
2540
+ setTalkIntercomChannels(groups = ['participants']) {
2500
2541
 
2501
2542
  if(typeof groups !== 'object' || !("length" in groups)) {
2502
- this._log('setTalkIntercomGroups: groups must be an array');
2543
+ this._log('setTalkIntercomChannels: groups must be an array');
2503
2544
  groups = [groups];
2504
2545
  }
2505
2546
 
2506
- this._talkIntercomGroups = structuredClone(groups);
2547
+ this._talkIntercomChannels = structuredClone(groups);
2507
2548
  let handle = this._getHandle(this.handleId);
2508
2549
  if (!handle) {
2509
2550
  return Promise.resolve();
@@ -2527,14 +2568,14 @@ class RoomSession {
2527
2568
  })
2528
2569
  }
2529
2570
 
2530
- setListenIntercomGroups(groups = ['participants']) {
2571
+ setListenIntercomChannels(groups = ['participants']) {
2531
2572
 
2532
2573
  if(typeof groups !== 'object' || !("length" in groups)) {
2533
- this._log('setListenIntercomGroups: groups must be an array');
2574
+ this._log('setListenIntercomChannels: groups must be an array');
2534
2575
  groups = [groups];
2535
2576
  }
2536
2577
 
2537
- this._listenIntercomGroups = structuredClone(groups);
2578
+ this._listenIntercomChannels = structuredClone(groups);
2538
2579
  let handle = this._getHandle(this.handleId);
2539
2580
  if (!handle) {
2540
2581
  return Promise.resolve();
@@ -2558,20 +2599,22 @@ class RoomSession {
2558
2599
 
2559
2600
  tracksMap.forEach(track => {
2560
2601
  if(track.type === 'data') {
2561
- //subscribe.push({feed: track.id, mid: track.mid})
2562
2602
  return;
2563
2603
  }
2564
2604
  const description = JSON.parse(track.description);
2565
2605
  const intercomGroups = description?.intercomGroups || [];
2566
-
2567
- if(this._listenIntercomGroups.some(g => intercomGroups.includes(g))) {
2568
- subscribe.push({feed: track.id, mid: track.mid})
2606
+ if(this._listenIntercomChannels.some(g => intercomGroups.includes(g))) {
2607
+ if(!this._isAlreadySubscribed(participant.handleId, track.id, track.mid)) {
2608
+ subscribe.push({feed: track.id, mid: track.mid})
2609
+ }
2569
2610
  }
2570
2611
  else {
2571
2612
  unsubscribe.push({feed: track.id, mid: track.mid})
2572
2613
  }
2573
2614
  });
2574
2615
 
2616
+ this._updateSubscribeMap(participant.handleId, subscribe, unsubscribe);
2617
+
2575
2618
  if(subscribe.length || unsubscribe.length) {
2576
2619
  promises.push(this.sendMessage(handle.handleId, {
2577
2620
  body: {