@reactoo/watchtogether-sdk-js 2.5.38 → 2.5.39

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.
@@ -32,6 +32,7 @@
32
32
  <input type="number" id="connection-timeout" placeholder="5000" min="0">
33
33
 
34
34
  <br><br>
35
+
35
36
  <button type="submit" id="join-room">Create users and join room</button>
36
37
 
37
38
  <button type="button" id="leave-room" onclick="leaveParticipants()">Leave room</button>
@@ -48,10 +48,15 @@
48
48
  display: flex;
49
49
  flex-direction: column;
50
50
  border: 1px solid black;
51
- width: 190px;
51
+ width: 150px;
52
52
  gap: 0;
53
53
  }
54
54
 
55
55
  .participant-container canvas {
56
56
  aspect-ratio: calc(16/9);
57
57
  }
58
+
59
+ .space {
60
+ height: 10px;
61
+ background-color: darkgrey;
62
+ }
@@ -5,7 +5,7 @@
5
5
  <meta charset="utf-8">
6
6
  <title>The Bulk Join 2</title>
7
7
  <script src="../../dist/watchtogether-sdk.js"></script>
8
- <link rel="stylesheet" href="bulk_join_room_2.css">
8
+ <link rel="stylesheet" href="./bulk_join_room_2.css">
9
9
  </head>
10
10
 
11
11
  <body>
@@ -246,17 +246,36 @@
246
246
  const canvasContext = canvasElement.getContext('2d');
247
247
  containerElement.appendChild(canvasElement);
248
248
 
249
+ let spaceElement = document.createElement('div');
250
+ spaceElement.className = 'space';
251
+ containerElement.appendChild(spaceElement);
252
+
249
253
  let participantNameElement;
250
254
  participantNameElement = document.createElement('input');
251
255
  participantNameElement.setAttribute('type', 'text');
252
256
  participantNameElement.setAttribute('placeholder', 'Name');
253
257
  containerElement.appendChild(participantNameElement);
254
258
 
259
+ const getNameButtonElement = document.createElement('button');
260
+ getNameButtonElement.innerText = 'Get name';
261
+ getNameButtonElement.addEventListener('click', () => {
262
+ sdkInstance.user.getUserSelf()
263
+ .then(response => {
264
+ participants[gifId].displayname = response.data.displayname;
265
+ participantNameElement.value = response.data.displayname;
266
+ });
267
+ });
268
+ containerElement.appendChild(getNameButtonElement);
269
+
255
270
  const setNameButtonElement = document.createElement('button');
256
271
  setNameButtonElement.innerText = 'Save name';
257
272
  setNameButtonElement.addEventListener('click', () => sdkInstance.user.updateUserSelf({lastRoomId: settings.roomId, displayname: participantNameElement.value}));
258
273
  containerElement.appendChild(setNameButtonElement);
259
274
 
275
+ spaceElement = document.createElement('div');
276
+ spaceElement.className = 'space';
277
+ containerElement.appendChild(spaceElement);
278
+
260
279
  const destroyButtonElement = document.createElement('button');
261
280
  destroyButtonElement.innerText = 'Destroy';
262
281
  destroyButtonElement.addEventListener('click', () => destroyParticipant(participants[gifId]));
@@ -272,6 +291,10 @@
272
291
  leaveButtonElement.addEventListener('click', () => disconnectParticipantFromRoom(participants[gifId]));
273
292
  containerElement.appendChild(leaveButtonElement);
274
293
 
294
+ spaceElement = document.createElement('div');
295
+ spaceElement.className = 'space';
296
+ containerElement.appendChild(spaceElement);
297
+
275
298
  const toggleCameraButtonElement = document.createElement('button');
276
299
  toggleCameraButtonElement.innerText = 'Toggle camera';
277
300
  toggleCameraButtonElement.addEventListener('click', () => participants[gifId].session.toggleVideo());
@@ -282,6 +305,14 @@
282
305
  toggleAudioButtonElement.addEventListener('click', () => participants[gifId].session.toggleAudio());
283
306
  containerElement.appendChild(toggleAudioButtonElement);
284
307
 
308
+ const toggleRaiseHandButtonElement = document.createElement('button');
309
+ toggleRaiseHandButtonElement.innerText = 'Toggle raise hand';
310
+ toggleRaiseHandButtonElement.addEventListener('click', () => {
311
+ sdkInstance.room.setUser({roomId: settings.roomId, userId: participants[gifId].sdkInstance.userId, flag: participants[gifId].handRaised ? 'handLower' : 'handRaise'});
312
+ participants[gifId].handRaised = !participants[gifId].handRaised;
313
+ });
314
+ containerElement.appendChild(toggleRaiseHandButtonElement);
315
+
285
316
  return fetch(gifUrl)
286
317
  .then(response => {
287
318
  const imageDecoder = new ImageDecoder({data: response.body, type: 'image/gif'});
@@ -299,6 +330,7 @@
299
330
  sdkInstance,
300
331
  loginPromise: sdkInstance.auth.deviceLogin(gifId),
301
332
  session: null, // Will be set after room join
333
+ handRaised: false,
302
334
  };
303
335
 
304
336
  if (settings.fetchNames) {
@@ -151,7 +151,7 @@
151
151
  })
152
152
 
153
153
  })
154
- .then(r => Instance.room.createSession({constructId, roomId:r.roomId, pinHash: r.pinHash, options: {
154
+ .then(r => Instance.room.createSession({constructId, roomId:r.roomId, pinHash: r.pinHash, role:'participant', options: {
155
155
  //subscriptionRules: {participant: {videoWall: [], watchTogether: []}}
156
156
  }})) // pin hash is not needed if you're owner of the room
157
157
  .then(session => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reactoo/watchtogether-sdk-js",
3
- "version": "2.5.38",
3
+ "version": "2.5.39",
4
4
  "description": "Javascript SDK for Reactoo",
5
5
  "main": "src/index.js",
6
6
  "unpkg": "dist/watchtogether-sdk.min.js",
@@ -17,7 +17,7 @@ import syncDisabled from "../modules/sync-modules/sync-disabled";
17
17
  import syncDaznDash from "../modules/sync-modules/sync-dazn-dash";
18
18
  import syncUniversal from "../modules/sync-modules/sync-universal";
19
19
 
20
- let roomSession = function ({roomId, pinHash, isTalkback, isInstructor}, room, wt) {
20
+ let roomSession = function ({roomId, pinHash, role}, room, wt) {
21
21
 
22
22
  let primaryRoomId = roomId;
23
23
  let publicCustomEvents = ['changePlayerSource', 'chatMessage', 'userUpdate', 'reconnecting', 'connecting', 'remoteMuted', 'scaling'];
@@ -88,26 +88,19 @@ let roomSession = function ({roomId, pinHash, isTalkback, isInstructor}, room, w
88
88
  emitter.emit('connecting', true);
89
89
  clearTimeout(alpTimeoutId);
90
90
  abortController = new AbortController();
91
- return Promise.all([
92
- wt.room.__joinRoom({
93
- roomId: reactooRoomId || primaryRoomId,
94
- pinHash,
95
- isTalkback,
96
- isInstructor}, abortController?.signal),
97
- wt.user.getUserSelf()])
98
- .then(([roomData, userData]) => {
91
+ return wt.room.__joinRoom({
92
+ roomId: reactooRoomId || primaryRoomId,
93
+ pinHash,
94
+ role
95
+ }, abortController?.signal)
96
+ .then(roomData => {
99
97
  // Happens when we reroute user to a different room
100
98
  if(roomData?.data?.reactooRoomId !== roomId) {
101
99
  roomId = roomData.data.reactooRoomId;
102
100
  emitter.emit('changeRoomId', roomId);
103
101
  }
104
- return Promise.all([roomData, userData])
105
- })
106
- .then(([roomData, userData]) => Promise.all([roomData, userData, this.setRoomVars()]))
107
- .then(([roomData, userData, _]) => Promise.all([
108
- roomData,
109
- userData,
110
- room.connect(
102
+ room.setRoomType(roomData.data.roomType);
103
+ return room.connect(
111
104
  roomData.data.roomId,
112
105
  roomData.data.pin,
113
106
  roomData.data.href,
@@ -118,11 +111,10 @@ let roomSession = function ({roomId, pinHash, isTalkback, isInstructor}, room, w
118
111
  roomData.data.webrtcVersion,
119
112
  (roomData.data.bitrate ? parseInt(roomData.data.bitrate) : 0),
120
113
  roomData.data.recordingFilename)
121
- ]))
114
+ })
122
115
  .finally(() => {
123
116
  emitter.emit('connecting', false);
124
117
  })
125
-
126
118
  },
127
119
 
128
120
  disconnect: function (dontWaitForResponses) {
@@ -186,10 +178,6 @@ let roomSession = function ({roomId, pinHash, isTalkback, isInstructor}, room, w
186
178
  this.restart();
187
179
  } else if (msg.action === 'user_update_displayname' || msg.action === 'user_update_avatar' || msg.action === 'user_update_customattributes' || msg.action === 'user_update_privateattributes') {
188
180
  emitter.emit('userUpdate', msg.text);
189
- } else if (msg.action === 'observer_connecting' || msg.action === 'talkback_connecting' || msg.action === 'instructor_connecting') {
190
- this.setRoomVars().catch(e => {
191
- room._log('Setting observers failed, this will cause issues', e);
192
- });
193
181
  } else if (msg.action === 'bitrate_changed') {
194
182
  this.setBitrateCap(msg.text);
195
183
  } else if (msg.user_action === 'chat_message') {
@@ -303,17 +291,6 @@ let roomSession = function ({roomId, pinHash, isTalkback, isInstructor}, room, w
303
291
  }
304
292
  },
305
293
 
306
- setRoomVars: () => {
307
- return wt.room.getRoomById(roomId, pinHash, undefined, false, abortController?.signal)
308
- .then(r => {
309
- // setting observers userId's so we can ignore them when creating participant
310
- room.setRoomType(r.data.type);
311
- room.setObserverIds(r.data.allowedObservers);
312
- room.setTalkbackIds(r.data.allowedTalkbacks);
313
- room.setInstructorId(r.data.classroom?.instructorUserId || r.data.videowall?.hostUserId);
314
- });
315
- },
316
-
317
294
  publishLocal: function (stream = null, {keepAudio = false, keepVideo = false} = {}) {
318
295
  return room.publishLocal(stream, {keepAudio, keepVideo})
319
296
  },
@@ -331,11 +308,9 @@ let roomSession = function ({roomId, pinHash, isTalkback, isInstructor}, room, w
331
308
  },
332
309
 
333
310
  setBitrateCap: (bitrate) => {
334
-
335
- if(isInstructor) {
311
+ if(role === 'host') {
336
312
  return;
337
313
  }
338
-
339
314
  return room.sendMessage(room.handleId, {
340
315
  "body": {
341
316
  "request": "configure",
@@ -344,19 +319,6 @@ let roomSession = function ({roomId, pinHash, isTalkback, isInstructor}, room, w
344
319
  }).catch(() => null)
345
320
  },
346
321
 
347
- switchChannel: (channelId) => {
348
- return room.sendMessage(room.handleId, {
349
- body: {
350
- request: "sync_source_set",
351
- room: room.roomId,
352
- timestamp: new Date().getTime(),
353
- wt_channel_id: channelId,
354
- fragment: "0",
355
- fragment_pos: 0
356
- }
357
- });
358
- },
359
-
360
322
  sendSystemMessage: (action, value = {}, to, set_master) => {
361
323
  return room.sendMessage(room.handleId, {
362
324
  body: {
@@ -205,14 +205,13 @@ let room = function () {
205
205
  }))
206
206
  },
207
207
 
208
- __joinRoom: ({roomId, pinHash, instanceType = this.__instanceType, isTalkback = undefined, isInstructor = undefined, customBearer = undefined} = {}, signal) => {
208
+ __joinRoom: ({roomId, pinHash, instanceType = this.__instanceType, role = 'participant', customBearer = undefined} = {}, signal) => {
209
209
  return this.__privates.auth.__client
210
210
  .then(client => client.apis.wt.join({
211
211
  roomId,
212
212
  pinHash,
213
213
  instanceType,
214
- isTalkback,
215
- isInstructor,
214
+ role,
216
215
  platform: this.browser === 'firefox' ? 'web-firefox' : 'web'
217
216
  }, {
218
217
  ...(signal ? {
@@ -245,10 +244,11 @@ let room = function () {
245
244
  .then(newSession => {
246
245
  let existingSessionIndex = roomSessions.findIndex(session => session.constructId === newSession.constructId);
247
246
  if(existingSessionIndex > -1) {
248
- return this.room.destroySession(newSession.constructId).then(() => {
249
- roomSessions.push(newSession);
250
- return newSession;
251
- });
247
+ return this.room.destroySession(newSession.constructId)
248
+ .then(() => {
249
+ roomSessions.push(newSession);
250
+ return newSession;
251
+ });
252
252
  } else {
253
253
  roomSessions.push(newSession);
254
254
  return newSession;
@@ -256,22 +256,21 @@ let room = function () {
256
256
  })
257
257
  },
258
258
 
259
- createSession: ({constructId, roomId, pinHash, isTalkback, isMonitor, isInstructor, options}) => {
259
+ createSession: ({constructId, roomId, pinHash, role, options}) => {
260
260
  return this.__privates.room.whenInitialized
261
261
  .then(lib => roomSession.call(this, {
262
262
  roomId,
263
263
  pinHash,
264
- isTalkback,
265
- isMonitor,
266
- isInstructor
264
+ role,
267
265
  }, lib.createSession(constructId, 'reactooroom', options), this))
268
266
  .then(newSession => {
269
267
  let existingSessionIndex = roomSessions.findIndex(session => session.constructId === newSession.constructId);
270
268
  if(existingSessionIndex > -1) {
271
- return this.room.destroySession(newSession.constructId).then(() => {
272
- roomSessions.push(newSession);
273
- return newSession;
274
- });
269
+ return this.room.destroySession(newSession.constructId)
270
+ .then(() => {
271
+ roomSessions.push(newSession);
272
+ return newSession;
273
+ });
275
274
  } else {
276
275
  roomSessions.push(newSession);
277
276
  return newSession;
@@ -98,23 +98,23 @@ class RoomSession {
98
98
  participant: {
99
99
  "watchparty": ['participant', 'talkback'],
100
100
  "commentary": ['participant', 'talkback'],
101
- "videowall": ['instructor', 'observer', 'talkback'],
102
- "videowall-queue": ['instructor', 'observer', 'talkback'],
103
- "videowall-queue-video": ['instructor', 'observer', 'talkback']
101
+ "videowall": ['host', 'observer', 'talkback'],
102
+ "videowall-queue": ['host', 'observer', 'talkback'],
103
+ "videowall-queue-video": ['host', 'observer', 'talkback']
104
104
  },
105
105
  monitor: {
106
106
  "watchparty": ['participant'],
107
107
  "commentary": ['participant'],
108
- "videowall": ['instructor', 'participant'],
109
- "videowall-queue": ['instructor', 'participant'],
110
- "videowall-queue-video": ['instructor', 'participant'],
108
+ "videowall": ['host', 'participant'],
109
+ "videowall-queue": ['host', 'participant'],
110
+ "videowall-queue-video": ['host', 'participant'],
111
111
  },
112
112
  talkback: {
113
113
  "watchparty": ['participant'],
114
114
  "commentary": ['participant'],
115
- "videowall": ['instructor', 'participant'],
116
- "videowall-queue": ['instructor', 'participant'],
117
- "videowall-queue-video": ['instructor', 'participant'],
115
+ "videowall": ['host', 'participant'],
116
+ "videowall-queue": ['host', 'participant'],
117
+ "videowall-queue-video": ['host', 'participant'],
118
118
  },
119
119
  observer: {
120
120
  "watchparty": ['participant'],
@@ -123,13 +123,15 @@ class RoomSession {
123
123
  "videowall-queue": ['participant'],
124
124
  "videowall-queue-video": ['participant'],
125
125
  },
126
- instructor: {
126
+ host: {
127
127
  "watchparty": [],
128
128
  "commentary": [],
129
129
  "videowall": [],
130
130
  "videowall-queue": [],
131
131
  "videowall-queue-video": [],
132
132
  },
133
+ companionTV: {},
134
+ companionPhone: {},
133
135
  };
134
136
 
135
137
  constructor(constructId = null, type = 'reactooroom', options = {}) {
@@ -168,9 +170,6 @@ class RoomSession {
168
170
  this._maxRetries = 3;
169
171
  this._keepAliveId = null;
170
172
  this._participants = [];
171
- this._observerIds = [];
172
- this._talkbackIds = [];
173
- this._instuctorId = null;
174
173
  this._roomType = 'watchparty';
175
174
  this._isDataChannelOpen = false;
176
175
  this._abortController = null;
@@ -223,28 +222,10 @@ class RoomSession {
223
222
  }
224
223
 
225
224
  _participantShouldSubscribe(userId) {
226
- const myUserId = decodeJanusDisplay(this.userId)?.userId;
227
- const remoteUserId = decodeJanusDisplay(userId)?.userId;
228
-
229
- let allowedObservers = this._observerIds || [];
230
- let allowedTalkback = this._talkbackIds || [];
231
- let allowedInstructor = this._instuctorId || null;
232
- let localUserRole = 'participant';
233
- if(allowedObservers.indexOf(myUserId) > -1) {
234
- localUserRole = 'observer';
235
- } else if(allowedTalkback.indexOf(myUserId) > -1) {
236
- localUserRole = 'talkback';
237
- } else if(myUserId === allowedInstructor) {
238
- localUserRole = 'instructor';
239
- }
240
- let remoteUserRole = 'participant';
241
- if(allowedObservers.indexOf(remoteUserId) > -1) {
242
- remoteUserRole = 'observer';
243
- } else if(allowedTalkback.indexOf(remoteUserId) > -1) {
244
- remoteUserRole = 'talkback';
245
- } else if(remoteUserId === allowedInstructor) {
246
- remoteUserRole = 'instructor';
247
- }
225
+ const myUser = decodeJanusDisplay(this.display);
226
+ const remoteUser = decodeJanusDisplay(userId);
227
+ let localUserRole = myUser?.role || 'participant';
228
+ let remoteUserRole = remoteUser?.role || 'participant';
248
229
  return this.subscriptionRules[localUserRole][(this._roomType || 'watchparty')].indexOf(remoteUserRole) > -1;
249
230
  }
250
231
 
@@ -260,22 +241,25 @@ class RoomSession {
260
241
  });
261
242
  }
262
243
 
263
- const decodedUserId = decodeJanusDisplay(handle.userId)?.userId;
264
-
265
- let allowedTalkback = this._talkbackIds || [];
266
- let allowedObservers = this._observerIds || [];
267
- let allowedInstructor = this._instuctorId || null;
268
- let eventName = 'addRemoteParticipant';
269
- if(decodedUserId === allowedInstructor) {
270
- eventName = 'addRemoteInstructor';
271
- }
272
- if (allowedTalkback.indexOf(decodedUserId) > -1) {
273
- eventName = 'addRemoteTalkback';
244
+ const participantRole = decodeJanusDisplay(handle.userId)?.role;
245
+ switch (participantRole) {
246
+ case 'participant':
247
+ return 'addRemoteParticipant';
248
+ case 'talkback':
249
+ return 'addRemoteTalkback';
250
+ case 'monitor':
251
+ return 'addRemoteTalkback';
252
+ case 'observer':
253
+ return 'addRemoteObserver';
254
+ case 'host':
255
+ return 'addRemoteInstructor';
256
+ case 'companionTV':
257
+ return 'addRemoteCompanionTV';
258
+ case 'companionPhone':
259
+ return 'addRemoteCompanionPhone';
260
+ default:
261
+ return 'addRemoteParticipant';
274
262
  }
275
- if (allowedObservers.indexOf(decodedUserId) > -1) {
276
- eventName = 'addRemoteObserver';
277
- }
278
- return eventName
279
263
  }
280
264
 
281
265
  _getRemoveParticipantEventName(handleId) {
@@ -290,22 +274,25 @@ class RoomSession {
290
274
  });
291
275
  }
292
276
 
293
- const decodedUserId = decodeJanusDisplay(handle.userId)?.userId;
294
-
295
- let allowedTalkback = this._talkbackIds || [];
296
- let allowedObservers = this._observerIds || [];
297
- let allowedInstructor = this._instuctorId || null;
298
- let eventName = 'removeRemoteParticipant';
299
- if(decodedUserId === allowedInstructor) {
300
- eventName = 'removeRemoteInstructor';
301
- }
302
- if (allowedTalkback.indexOf(decodedUserId) > -1) {
303
- eventName = 'removeRemoteTalkback';
277
+ const participantRole = decodeJanusDisplay(handle.userId)?.role;
278
+ switch (participantRole) {
279
+ case 'participant':
280
+ return 'removeRemoteParticipant';
281
+ case 'talkback':
282
+ return 'addRemoteTalkback';
283
+ case 'monitor':
284
+ return 'removeRemoteTalkback';
285
+ case 'observer':
286
+ return 'removeRemoteObserver';
287
+ case 'host':
288
+ return 'removeRemoteInstructor';
289
+ case 'companionTV':
290
+ return 'removeRemoteCompanionTV';
291
+ case 'companionPhone':
292
+ return 'removeRemoteCompanionPhone';
293
+ default:
294
+ return 'removeRemoteParticipant';
304
295
  }
305
- if (allowedObservers.indexOf(decodedUserId) > -1) {
306
- eventName = 'removeRemoteObserver';
307
- }
308
- return eventName
309
296
  }
310
297
 
311
298
  sendMessage(handleId, message = {body: 'Example Body'}, dontWait = false, dontResolveOnAck = false) {
@@ -2116,24 +2103,6 @@ class RoomSession {
2116
2103
  this.emit('localMuted', {type: 'video', value: this.isVideoMuted, mid});
2117
2104
  }
2118
2105
 
2119
- setInstructorId(instructorId = null) {
2120
- this._instuctorId = instructorId;
2121
- this.emit('instructorId', this._instuctorId);
2122
- return this._instuctorId;
2123
- }
2124
-
2125
- setObserverIds(observerIds = []) {
2126
- this._observerIds = observerIds;
2127
- this.emit('observerIds', this._observerIds);
2128
- return this._observerIds;
2129
- }
2130
-
2131
- setTalkbackIds(talkbackIds = []) {
2132
- this._talkbackIds = talkbackIds;
2133
- this.emit('talkbackIds', this._talkbackIds);
2134
- return this._talkbackIds;
2135
- }
2136
-
2137
2106
  setRoomType(type = 'watchparty') {
2138
2107
  this._roomType = type;
2139
2108
  return this._roomType;