@reactoo/watchtogether-sdk-js 2.5.32 → 2.5.38

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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  import adapter from 'webrtc-adapter';
4
4
  import emitter from './wt-emitter';
5
- import {generateUUID} from "./wt-utils";
5
+ import {decodeJanusDisplay, generateUUID} from "./wt-utils";
6
6
 
7
7
  class Room {
8
8
 
@@ -96,24 +96,39 @@ class RoomSession {
96
96
 
97
97
  static subscriptionRules = {
98
98
  participant: {
99
- watchTogether: ['participant', 'talkback'],
100
- videoWall: ['instructor', 'observer', 'talkback']
99
+ "watchparty": ['participant', 'talkback'],
100
+ "commentary": ['participant', 'talkback'],
101
+ "videowall": ['instructor', 'observer', 'talkback'],
102
+ "videowall-queue": ['instructor', 'observer', 'talkback'],
103
+ "videowall-queue-video": ['instructor', 'observer', 'talkback']
101
104
  },
102
105
  monitor: {
103
- watchTogether: ['participant'],
104
- videoWall: ['instructor', 'participant'],
106
+ "watchparty": ['participant'],
107
+ "commentary": ['participant'],
108
+ "videowall": ['instructor', 'participant'],
109
+ "videowall-queue": ['instructor', 'participant'],
110
+ "videowall-queue-video": ['instructor', 'participant'],
105
111
  },
106
112
  talkback: {
107
- watchTogether: ['participant'],
108
- videoWall: ['instructor', 'participant'],
113
+ "watchparty": ['participant'],
114
+ "commentary": ['participant'],
115
+ "videowall": ['instructor', 'participant'],
116
+ "videowall-queue": ['instructor', 'participant'],
117
+ "videowall-queue-video": ['instructor', 'participant'],
109
118
  },
110
119
  observer: {
111
- watchTogether: ['participant'],
112
- videoWall: ['participant'],
120
+ "watchparty": ['participant'],
121
+ "commentary": ['participant'],
122
+ "videowall": ['participant'],
123
+ "videowall-queue": ['participant'],
124
+ "videowall-queue-video": ['participant'],
113
125
  },
114
126
  instructor: {
115
- watchTogether: [],
116
- videoWall: [],
127
+ "watchparty": [],
128
+ "commentary": [],
129
+ "videowall": [],
130
+ "videowall-queue": [],
131
+ "videowall-queue-video": [],
117
132
  },
118
133
  };
119
134
 
@@ -130,8 +145,6 @@ class RoomSession {
130
145
  this.userId = null;
131
146
  this.sessiontype = type;
132
147
  this.initialBitrate = 0;
133
- //TODO: remove this
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)
135
148
  this.recordingFilename = null;
136
149
  this.pluginName = RoomSession.sessionTypes[type];
137
150
  this.options = options;
@@ -143,10 +156,12 @@ class RoomSession {
143
156
  this.ws = null;
144
157
  this.isRestarting = false;
145
158
 
146
- //TODO: do it better
147
- // double click prevention
148
- this.connectingPromise = null;
149
- this.disconnectingPromise = null;
159
+ this.isConnecting = false;
160
+ this.isDisconnecting = false;
161
+ this.isConnected = false;
162
+ this.isPublished = false;
163
+ this.isReclaiming = false;
164
+ this.isStreaming = false;
150
165
 
151
166
  this._ipv6Support = false;
152
167
  this._retries = 0;
@@ -156,12 +171,10 @@ class RoomSession {
156
171
  this._observerIds = [];
157
172
  this._talkbackIds = [];
158
173
  this._instuctorId = null;
159
- this._hasJoined = false;
160
- this._isStreaming = false;
161
- this._isPublished = false;
174
+ this._roomType = 'watchparty';
162
175
  this._isDataChannelOpen = false;
163
- this._dataChannelTimeoutId = null;
164
- this._messageTimeoutId = null;
176
+ this._abortController = null;
177
+
165
178
  this.isAudioMuted = false;
166
179
  this.isVideoMuted = false;
167
180
  this.isVideoEnabled = false;
@@ -210,29 +223,29 @@ class RoomSession {
210
223
  }
211
224
 
212
225
  _participantShouldSubscribe(userId) {
226
+ const myUserId = decodeJanusDisplay(this.userId)?.userId;
227
+ const remoteUserId = decodeJanusDisplay(userId)?.userId;
228
+
213
229
  let allowedObservers = this._observerIds || [];
214
230
  let allowedTalkback = this._talkbackIds || [];
215
231
  let allowedInstructor = this._instuctorId || null;
216
232
  let localUserRole = 'participant';
217
- if(this.isMonitor) {
218
- localUserRole = 'monitor';
219
- } else if(allowedObservers.indexOf(this.userId) > -1) {
233
+ if(allowedObservers.indexOf(myUserId) > -1) {
220
234
  localUserRole = 'observer';
221
- } else if(allowedTalkback.indexOf(this.userId) > -1) {
235
+ } else if(allowedTalkback.indexOf(myUserId) > -1) {
222
236
  localUserRole = 'talkback';
223
- } else if(this.userId === allowedInstructor) {
237
+ } else if(myUserId === allowedInstructor) {
224
238
  localUserRole = 'instructor';
225
239
  }
226
240
  let remoteUserRole = 'participant';
227
- if(allowedObservers.indexOf(userId) > -1) {
241
+ if(allowedObservers.indexOf(remoteUserId) > -1) {
228
242
  remoteUserRole = 'observer';
229
- } else if(allowedTalkback.indexOf(userId) > -1) {
243
+ } else if(allowedTalkback.indexOf(remoteUserId) > -1) {
230
244
  remoteUserRole = 'talkback';
231
- } else if(userId === allowedInstructor) {
245
+ } else if(remoteUserId === allowedInstructor) {
232
246
  remoteUserRole = 'instructor';
233
247
  }
234
- let mode = allowedInstructor !== null ? 'videoWall' : 'watchTogether';
235
- return this.subscriptionRules[localUserRole][mode].indexOf(remoteUserRole) > -1;
248
+ return this.subscriptionRules[localUserRole][(this._roomType || 'watchparty')].indexOf(remoteUserRole) > -1;
236
249
  }
237
250
 
238
251
  _getAddParticipantEventName(handleId) {
@@ -247,17 +260,19 @@ class RoomSession {
247
260
  });
248
261
  }
249
262
 
263
+ const decodedUserId = decodeJanusDisplay(handle.userId)?.userId;
264
+
250
265
  let allowedTalkback = this._talkbackIds || [];
251
266
  let allowedObservers = this._observerIds || [];
252
267
  let allowedInstructor = this._instuctorId || null;
253
268
  let eventName = 'addRemoteParticipant';
254
- if(handle.userId === allowedInstructor) {
269
+ if(decodedUserId === allowedInstructor) {
255
270
  eventName = 'addRemoteInstructor';
256
271
  }
257
- if (allowedTalkback.indexOf(handle.userId) > -1) {
272
+ if (allowedTalkback.indexOf(decodedUserId) > -1) {
258
273
  eventName = 'addRemoteTalkback';
259
274
  }
260
- if (allowedObservers.indexOf(handle.userId) > -1) {
275
+ if (allowedObservers.indexOf(decodedUserId) > -1) {
261
276
  eventName = 'addRemoteObserver';
262
277
  }
263
278
  return eventName
@@ -275,17 +290,19 @@ class RoomSession {
275
290
  });
276
291
  }
277
292
 
293
+ const decodedUserId = decodeJanusDisplay(handle.userId)?.userId;
294
+
278
295
  let allowedTalkback = this._talkbackIds || [];
279
296
  let allowedObservers = this._observerIds || [];
280
297
  let allowedInstructor = this._instuctorId || null;
281
298
  let eventName = 'removeRemoteParticipant';
282
- if(handle.userId === allowedInstructor) {
299
+ if(decodedUserId === allowedInstructor) {
283
300
  eventName = 'removeRemoteInstructor';
284
301
  }
285
- if (allowedTalkback.indexOf(handle.userId) > -1) {
302
+ if (allowedTalkback.indexOf(decodedUserId) > -1) {
286
303
  eventName = 'removeRemoteTalkback';
287
304
  }
288
- if (allowedObservers.indexOf(handle.userId) > -1) {
305
+ if (allowedObservers.indexOf(decodedUserId) > -1) {
289
306
  eventName = 'removeRemoteObserver';
290
307
  }
291
308
  return eventName
@@ -321,12 +338,25 @@ class RoomSession {
321
338
  transaction,
322
339
  token: this.token, ...((this.sessionId && {'session_id': this.sessionId}) || {})
323
340
  };
341
+
342
+ this._log(requestData);
343
+
324
344
  return new Promise((resolve, reject) => {
345
+ let messageTimeoutId = null;
346
+
347
+ let abortResponse = () => {
348
+ this._abortController.signal.removeEventListener('abort', abortResponse);
349
+ clearTimeout(messageTimeoutId);
350
+ this.ws.removeEventListener('message', parseResponse);
351
+ reject({type: 'warning', id: 17, message: 'connection cancelled'})
352
+ };
353
+
325
354
  let parseResponse = (event) => {
326
355
  let json = JSON.parse(event.data);
327
356
  let r_transaction = json['transaction'];
328
357
  if (r_transaction === transaction && (!dontResolveOnAck || json['janus'] !== 'ack')) {
329
- clearTimeout(this._messageTimeoutId);
358
+ clearTimeout(messageTimeoutId);
359
+ this._abortController.signal.removeEventListener('abort', abortResponse);
330
360
  this.ws.removeEventListener('message', parseResponse);
331
361
  if (json['janus'] === 'error') {
332
362
  if (json?.error?.code == 403) {
@@ -347,11 +377,16 @@ class RoomSession {
347
377
 
348
378
  } else {
349
379
  if (this.ws && this.ws.readyState === 1) {
380
+
350
381
  this.ws.addEventListener('message', parseResponse);
351
- this._messageTimeoutId = setTimeout(() => {
382
+
383
+ messageTimeoutId = setTimeout(() => {
352
384
  this.ws.removeEventListener('message', parseResponse);
385
+ this._abortController.signal.removeEventListener('abort', abortResponse);
353
386
  reject({type: 'error', id: 3, message: 'send timeout', data: requestData});
354
387
  }, 10000);
388
+
389
+ this._abortController.signal.addEventListener('abort', abortResponse);
355
390
  this.ws.send(JSON.stringify(requestData));
356
391
  } else {
357
392
  reject({type: 'warning', id: 29, message: 'No connection to WebSockets', data: requestData});
@@ -361,7 +396,8 @@ class RoomSession {
361
396
  }
362
397
 
363
398
  _connectionClosed() {
364
- if (this.disconnectingPromise || this.connectingPromise) {
399
+
400
+ if (!this.isConnected || this.isConnecting || this.isDisconnecting) {
365
401
  return;
366
402
  }
367
403
 
@@ -484,7 +520,7 @@ class RoomSession {
484
520
  if (event === "joined") {
485
521
  this.id = msg["id"];
486
522
  this.privateId = msg["private_id"];
487
- this._hasJoined = true;
523
+ this.isConnected = true;
488
524
  this.emit('joined', true);
489
525
  this._log('We have successfully joined Room');
490
526
  for (let f in list) {
@@ -593,7 +629,7 @@ class RoomSession {
593
629
  }
594
630
  if (result["status"] === 'started') {
595
631
  this.emit('streaming', true);
596
- this._isStreaming = true;
632
+ this.isStreaming = true;
597
633
  }
598
634
  }
599
635
 
@@ -640,7 +676,7 @@ class RoomSession {
640
676
  this.emit(this._getAddParticipantEventName(handle.handleId), {
641
677
  tid: generateUUID(),
642
678
  id: handle.handleId,
643
- userId: handle.userId,
679
+ userId: decodeJanusDisplay(handle.userId)?.userId,
644
680
  stream: null,
645
681
  track: null,
646
682
  adding: false,
@@ -775,11 +811,11 @@ class RoomSession {
775
811
 
776
812
  if (handleId === this.handleId) {
777
813
  this._isDataChannelOpen = false;
778
- this._isPublished = false;
814
+ this.isPublished = false;
779
815
  this.emit('published', {status: false, hasStream: false});
780
- this.emit('removeLocalParticipant', {id: handleId, userId: handle.userId});
816
+ this.emit('removeLocalParticipant', {id: handleId, userId: decodeJanusDisplay(handle.userId)?.userId});
781
817
  } else {
782
- this.emit(this._getRemoveParticipantEventName(handleId), {id: handleId, userId: handle.userId});
818
+ this.emit(this._getRemoveParticipantEventName(handleId), {id: handleId, userId: decodeJanusDisplay(handle.userId)?.userId});
783
819
  }
784
820
 
785
821
  if (removeHandle) {
@@ -836,10 +872,10 @@ class RoomSession {
836
872
  }
837
873
 
838
874
  _leaveRoom(dontWait = false) {
839
- return this._hasJoined
875
+ return this.isConnected
840
876
  ? this.sendMessage(this.handleId, {body: {"request": "leave"}}, dontWait)
841
877
  .finally(() => {
842
- this._hasJoined = false;
878
+ this.isConnected = false;
843
879
  this.emit('joined', false);
844
880
  })
845
881
  : Promise.resolve();
@@ -849,8 +885,8 @@ class RoomSession {
849
885
 
850
886
  _reconnect() {
851
887
 
852
- if (this.connectingPromise) {
853
- return this.connectingPromise;
888
+ if (this.isReclaiming) {
889
+ return Promise.resolve();
854
890
  }
855
891
 
856
892
  if (this.ws) {
@@ -860,25 +896,39 @@ class RoomSession {
860
896
  }
861
897
  }
862
898
  this._stopKeepAlive();
863
- this.connectingPromise = new Promise((resolve, reject) => {
864
- this.emit('joining', true);
899
+ this.isReclaiming = true;
900
+ this.emit('joining', true);
901
+ return new Promise((resolve, reject) => {
902
+
903
+ let abortReconnect = () => {
904
+ this._abortController.signal.removeEventListener('abort', abortReconnect);
905
+ this.ws.removeEventListener('close', this.__connectionClosedBoundFn);
906
+ this.ws.removeEventListener('message', this.__handleWsEventsBoundFn);
907
+ this.ws.onopen = null;
908
+ this.ws.onerror = null;
909
+ this.isReclaiming = false;
910
+ this.emit('joining', false);
911
+ reject({type: 'warning', id: 17, message: 'Connection cancelled', data: e});
912
+ };
913
+
865
914
  this.ws = new WebSocket(this.server, 'janus-protocol');
866
915
  this.__connectionClosedBoundFn = this._connectionClosed.bind(this);
867
916
  this.__handleWsEventsBoundFn = this._handleWsEvents.bind(this);
868
917
  this.ws.addEventListener('close', this.__connectionClosedBoundFn);
869
918
  this.ws.addEventListener('message', this.__handleWsEventsBoundFn);
870
919
  this.ws.onopen = () => {
920
+ this._abortController.signal.removeEventListener('abort', abortReconnect);
871
921
  this._send({"janus": "claim"})
872
922
  .then(json => {
873
923
  this.sessionId = json["session_id"] ? json["session_id"] : json.data["id"];
874
924
  this._startKeepAlive();
875
- this.connectingPromise = null;
925
+ this.isReclaiming = false;
876
926
  this.emit('joining', false);
877
927
  this._retries = 0;
878
928
  resolve(json);
879
929
  })
880
930
  .catch(error => {
881
- this.connectingPromise = null;
931
+ this.isReclaiming = false;
882
932
  this.emit('joining', false);
883
933
  reject({type: 'error', id: 11, message: 'reconnection error', data: error})
884
934
  });
@@ -886,26 +936,27 @@ class RoomSession {
886
936
 
887
937
  // this is called before 'close' event callback so it doesn't break reconnect loop
888
938
  this.ws.onerror = (e) => {
889
- this.connectingPromise = null;
939
+ this._abortController.signal.removeEventListener('abort', abortReconnect);
940
+ this.isReclaiming = false;
890
941
  this.emit('joining', false);
891
942
  reject({type: 'warning', id: 12, message: 'ws reconnection error', data: e});
892
943
  }
944
+
945
+ this._abortController.signal.addEventListener('abort', abortReconnect);
893
946
  });
894
- return this.connectingPromise;
895
947
  }
896
948
 
897
- connect(roomId, pin, server, iceServers, token, display, userId, webrtcVersion = 0, initialBitrate = 0, isMonitor, recordingFilename) {
949
+ connect(roomId, pin, server, iceServers, token, display, userId, webrtcVersion = 0, initialBitrate = 0, recordingFilename) {
898
950
 
899
- if (this.connectingPromise) {
900
- return this.connectingPromise;
951
+ if (this.isConnecting) {
952
+ return Promise.reject({type: 'warning', id: 16, message: 'connection already in progress'});
901
953
  }
902
954
 
903
- this.emit('joined', false);
904
955
  if (this.ws) {
905
956
  this._wipeListeners();
906
957
  }
907
958
  this._stopKeepAlive();
908
- this.disconnectingPromise = null;
959
+ this._abortController = new AbortController();
909
960
  this.sessionId = null;
910
961
  this.server = server;
911
962
  this.iceServers = iceServers;
@@ -916,17 +967,30 @@ class RoomSession {
916
967
  this.userId = userId;
917
968
  this.webrtcVersion = webrtcVersion;
918
969
  this.initialBitrate = initialBitrate;
919
- this.isMonitor = isMonitor;
920
970
  this.recordingFilename = recordingFilename;
921
- this.disconnectingPromise = null;
922
- this.connectingPromise = new Promise((resolve, reject) => {
923
- this.emit('joining', true);
971
+ this.isConnecting = true;
972
+ this.emit('joining', true);
973
+ return new Promise((resolve, reject) => {
974
+
924
975
  this.ws = new WebSocket(this.server, 'janus-protocol');
925
976
  this.__connectionClosedBoundFn = this._connectionClosed.bind(this);
926
977
  this.__handleWsEventsBoundFn = this._handleWsEvents.bind(this);
978
+
979
+ let abortConnect = () => {
980
+ this._abortController.signal.removeEventListener('abort', abortConnect);
981
+ this.ws.removeEventListener('close', this.__connectionClosedBoundFn);
982
+ this.ws.removeEventListener('message', this.__handleWsEventsBoundFn);
983
+ this.ws.onopen = null;
984
+ this.ws.onerror = null;
985
+ this.isConnecting = false;
986
+ this.emit('joining', false);
987
+ reject({type: 'warning', id: 17, message: 'Connection cancelled'});
988
+ };
989
+
927
990
  this.ws.addEventListener('close', this.__connectionClosedBoundFn);
928
991
  this.ws.addEventListener('message', this.__handleWsEventsBoundFn);
929
992
  this.ws.onopen = () => {
993
+ this._abortController.signal.removeEventListener('abort', abortConnect);
930
994
  this._retries = 0;
931
995
  this._send({"janus": "create"})
932
996
  .then(json => {
@@ -941,36 +1005,41 @@ class RoomSession {
941
1005
  })
942
1006
  .then(() => this._joinRoom(roomId, pin, userId, display))
943
1007
  .then(() => {
944
- this.connectingPromise = null;
1008
+ this.isConnecting = false;
945
1009
  this.emit('joining', false);
946
1010
  resolve(this);
947
1011
  })
948
1012
  .catch(error => {
949
- this.connectingPromise = null;
1013
+ this.isConnecting = false;
950
1014
  this.emit('joining', false);
951
- reject({type: 'error', id: 13, message: 'connection error', data: error})
1015
+ reject({type: error?.type === 'warning' ? 'warning' : 'error', id: 13, message: 'connection error', data: error})
952
1016
  });
953
1017
  };
1018
+
954
1019
  this.ws.onerror = (e) => {
955
- this.connectingPromise = null;
1020
+ this._abortController.signal.removeEventListener('abort', abortConnect);
1021
+ this.isConnecting = false;
956
1022
  this.emit('joining', false);
957
1023
  reject({type: 'error', id: 14, message: 'ws connection error', data: e});
958
1024
  }
1025
+
1026
+ this._abortController.signal.addEventListener('abort', abortConnect);
1027
+
959
1028
  });
960
- return this.connectingPromise;
961
1029
  }
962
1030
 
963
1031
  disconnect() {
964
- if (this.disconnectingPromise) {
965
- return this.disconnectingPromise;
1032
+
1033
+ if (this.isDisconnecting) {
1034
+ return Promise.resolve();
966
1035
  }
967
1036
 
968
- let _hasJoined = this._hasJoined;
969
-
970
- clearTimeout(this._messageTimeoutId);
971
- clearTimeout(this._dataChannelTimeoutId);
1037
+ this._abortController?.abort?.();
972
1038
  this._stopKeepAlive();
973
- this.disconnectingPromise = Promise.all(this._participants.map(p => this._removeParticipant(p.handleId)))
1039
+
1040
+ let isConnected = this.isConnected;
1041
+ this.isDisconnecting = true;
1042
+ return Promise.all(this._participants.map(p => this._removeParticipant(p.handleId)))
974
1043
  .finally(() => {
975
1044
  this._wipeListeners();
976
1045
  if (this.ws && this.ws.readyState === 1) {
@@ -978,46 +1047,59 @@ class RoomSession {
978
1047
  this.ws.close();
979
1048
  }
980
1049
  this.sessionId = null;
981
- //TODO: Just in case something crashed along the way
982
- this._isPublished = false;
983
- this._hasJoined = false;
1050
+ this.isPublished = false;
1051
+ this.isConnected = false;
1052
+ this.isDisconnecting = false;
984
1053
  this.emit('publishing', false);
985
1054
  this.emit('published', {status: false, hasStream: false});
986
1055
  this.emit('joining', false);
987
1056
  this.emit('joined', false);
988
- this.emit('disconnect', _hasJoined);
1057
+ this.emit('disconnect', isConnected);
989
1058
  return Promise.resolve('Disconnected');
990
1059
  })
991
- return this.disconnectingPromise;
992
1060
  }
993
1061
 
994
1062
  startStream(streamId, server, iceServers, token, userId) {
995
1063
 
996
- if (this.connectingPromise) {
997
- return this.connectingPromise
1064
+ if (this.isConnecting) {
1065
+ return Promise.reject({type: 'warning', id: 16, message: 'connection error', data: 'Connection is in progress'});
998
1066
  }
999
1067
 
1000
- this.emit('streaming', false);
1001
1068
  if (this.ws) {
1002
1069
  this._wipeListeners();
1003
1070
  }
1071
+
1004
1072
  this._stopKeepAlive();
1005
- this.disconnectingPromise = null;
1006
- this.sessionId = null;
1073
+ this._abortController = new AbortController();
1007
1074
  this.server = server;
1008
1075
  this.iceServers = iceServers;
1009
1076
  this.token = token;
1010
1077
  this.streamId = streamId;
1011
1078
  this.userId = userId;
1079
+ this.sessionId = null;
1080
+ this.isConnecting = true;
1081
+ this.emit('streamStarting', true);
1082
+ return new Promise((resolve, reject) => {
1012
1083
 
1013
- this.connectingPromise = new Promise((resolve, reject) => {
1014
- this.emit('streamStarting', true);
1015
1084
  this.ws = new WebSocket(this.server, 'janus-protocol');
1016
1085
  this.__connectionClosedBoundFn = this._connectionClosed.bind(this);
1017
1086
  this.__handleWsEventsBoundFn = this._handleWsEvents.bind(this);
1087
+
1088
+ let abortConnect = () => {
1089
+ this._abortController.signal.removeEventListener('abort', abortConnect);
1090
+ this.ws.removeEventListener('close', this.__connectionClosedBoundFn);
1091
+ this.ws.removeEventListener('message', this.__handleWsEventsBoundFn);
1092
+ this.ws.onopen = null;
1093
+ this.ws.onerror = null;
1094
+ this.isConnecting = false;
1095
+ this.emit('streamStarting', false);
1096
+ reject({type: 'warning', id: 17, message: 'Connection cancelled'});
1097
+ };
1098
+
1018
1099
  this.ws.addEventListener('close', this.__connectionClosedBoundFn);
1019
1100
  this.ws.addEventListener('message', this.__handleWsEventsBoundFn);
1020
1101
  this.ws.onopen = () => {
1102
+ this._abortController.signal.removeEventListener('abort', abortConnect);
1021
1103
  this._retries = 0;
1022
1104
  this._send({"janus": "create"})
1023
1105
  .then(json => {
@@ -1032,38 +1114,39 @@ class RoomSession {
1032
1114
  })
1033
1115
  .then(() => this._watchStream(streamId))
1034
1116
  .then(() => {
1035
- this.connectingPromise = null;
1117
+ this.isConnecting = false;
1036
1118
  this.emit('streamStarting', false);
1037
1119
  resolve(this);
1038
1120
  })
1039
1121
  .catch(error => {
1040
- this.connectingPromise = null;
1122
+ this.isConnecting = false;
1041
1123
  this.emit('streamStarting', false);
1042
1124
  reject({type: 'error', id: 13, message: 'connection error', data: error})
1043
1125
  });
1044
1126
  };
1045
1127
  this.ws.onerror = (e) => {
1046
- this.connectingPromise = null;
1128
+ this._abortController.signal.removeEventListener('abort', abortConnect);
1129
+ this.isConnecting = false;
1047
1130
  this.emit('streamStarting', false);
1048
1131
  reject({type: 'error', id: 14, message: 'ws connection error', data: e});
1049
1132
  }
1133
+
1134
+ this._abortController.signal.addEventListener('abort', abortConnect);
1050
1135
  });
1051
- return this.connectingPromise;
1052
1136
  }
1053
1137
 
1054
1138
  stopStream() {
1055
- if (this.disconnectingPromise) {
1056
- return this.disconnectingPromise;
1057
- }
1058
1139
 
1059
- let _isStreaming = this._isStreaming;
1140
+ if (this.isDisconnecting) {
1141
+ return Promise.resolve();
1142
+ }
1060
1143
 
1144
+ this._abortController?.abort?.();
1061
1145
  this._stopKeepAlive();
1062
- this.disconnectingPromise = this.sendMessage(this.handleId, {
1063
- body: {
1064
- "request": "stop"
1065
- }
1066
- }, false, true)
1146
+
1147
+ let isStreaming = this.isStreaming;
1148
+ this.isDisconnecting = true;
1149
+ return this.sendMessage(this.handleId, {body: {"request": "stop"}}, false, true)
1067
1150
  .then(() => this._removeParticipant(this.handleId))
1068
1151
  .finally(() => {
1069
1152
  this._wipeListeners();
@@ -1072,15 +1155,13 @@ class RoomSession {
1072
1155
  this.ws.close();
1073
1156
  }
1074
1157
  this.sessionId = null;
1075
- this._isStreaming = false;
1158
+ this.isDisconnecting = false;
1159
+ this.isStreaming = false;
1076
1160
  this.emit('streamStarting', false);
1077
1161
  this.emit('streaming', false);
1078
- this.emit('disconnect', _isStreaming);
1079
- this.disconnectingPromise = null;
1162
+ this.emit('disconnect', isStreaming);
1080
1163
  return Promise.resolve('Disconnected');
1081
1164
  });
1082
-
1083
- return this.disconnectingPromise;
1084
1165
  }
1085
1166
 
1086
1167
  destroy() {
@@ -1171,7 +1252,7 @@ class RoomSession {
1171
1252
  this.emit(this._getAddParticipantEventName(handle.handleId), {
1172
1253
  tid: generateUUID(),
1173
1254
  id: handle.handleId,
1174
- userId: handle.userId,
1255
+ userId: decodeJanusDisplay(handle.userId)?.userId,
1175
1256
  stream: config.stream,
1176
1257
  track: null,
1177
1258
  optional: true,
@@ -1192,7 +1273,7 @@ class RoomSession {
1192
1273
  this.emit(this._getAddParticipantEventName(handle.handleId), {
1193
1274
  tid: generateUUID(),
1194
1275
  id: handle.handleId,
1195
- userId: handle.userId,
1276
+ userId: decodeJanusDisplay(handle.userId)?.userId,
1196
1277
  stream: config.stream,
1197
1278
  track: null,
1198
1279
  optional: true,
@@ -1245,7 +1326,7 @@ class RoomSession {
1245
1326
  tid: generateUUID(),
1246
1327
  mid,
1247
1328
  id: handle.handleId,
1248
- userId: handle.userId,
1329
+ userId: decodeJanusDisplay(handle.userId)?.userId,
1249
1330
  stream: config.stream,
1250
1331
  track: event.track,
1251
1332
  constructId: this.constructId,
@@ -1273,7 +1354,7 @@ class RoomSession {
1273
1354
  tid: generateUUID(),
1274
1355
  id: handle.handleId,
1275
1356
  mid,
1276
- userId: handle.userId,
1357
+ userId: decodeJanusDisplay(handle.userId)?.userId,
1277
1358
  stream: config.stream,
1278
1359
  track: ev.target,
1279
1360
  constructId: this.constructId,
@@ -1299,7 +1380,7 @@ class RoomSession {
1299
1380
  this.emit('remoteTrackMuted', {
1300
1381
  id: handle.handleId,
1301
1382
  mid,
1302
- userId: handle.userId,
1383
+ userId: decodeJanusDisplay(handle.userId)?.userId,
1303
1384
  stream: config.stream,
1304
1385
  kind: ev.target.kind,
1305
1386
  track: ev.target,
@@ -1320,7 +1401,7 @@ class RoomSession {
1320
1401
  this.emit('remoteTrackMuted', {
1321
1402
  id: handle.handleId,
1322
1403
  mid,
1323
- userId: handle.userId,
1404
+ userId: decodeJanusDisplay(handle.userId)?.userId,
1324
1405
  stream: config.stream,
1325
1406
  kind: ev.target.kind,
1326
1407
  track: ev.target,
@@ -1710,6 +1791,14 @@ class RoomSession {
1710
1791
 
1711
1792
  publishLocal(stream, {keepAudio = false, keepVideo = false} = {}) {
1712
1793
 
1794
+ if(this.isDisconnecting || !this.isConnected) {
1795
+ return Promise.reject({
1796
+ type: 'warning',
1797
+ id: 18,
1798
+ message: 'Either not connected or disconnecting',
1799
+ })
1800
+ }
1801
+
1713
1802
  this.emit('publishing', true);
1714
1803
 
1715
1804
  let handle = this._getHandle(this.handleId);
@@ -1874,23 +1963,40 @@ class RoomSession {
1874
1963
  return Promise.resolve(r)
1875
1964
  } else {
1876
1965
  return new Promise((resolve, reject) => {
1877
- let __ = (val) => {
1966
+
1967
+ let dataChannelTimeoutId = null;
1968
+
1969
+ let _resolve = (val) => {
1878
1970
  if (val) {
1879
- clearTimeout(this._dataChannelTimeoutId);
1880
- this.off('dataChannel', __, this);
1971
+ clearTimeout(dataChannelTimeoutId);
1972
+ this._abortController.signal.removeEventListener('abort', _rejectAbort);
1973
+ this.off('dataChannel', _resolve, this);
1881
1974
  resolve(this);
1882
1975
  }
1883
1976
  };
1884
- this._dataChannelTimeoutId = setTimeout(() => {
1885
- this.off('dataChannel', __, this);
1977
+
1978
+ let _rejectTimeout = () => {
1979
+ this.off('dataChannel', _resolve, this);
1980
+ this._abortController.signal.removeEventListener('abort', _rejectAbort);
1886
1981
  reject({type: 'error', id: 27, message: 'Data channel did not open', data: null});
1887
- }, 5000);
1888
- this.on('dataChannel', __, this);
1982
+ }
1983
+
1984
+ let _rejectAbort = () => {
1985
+ this._abortController.signal.removeEventListener('abort', _rejectAbort);
1986
+ clearTimeout(dataChannelTimeoutId);
1987
+ this.off('dataChannel', _resolve, this);
1988
+ reject({type: 'warning', id: 17, message: 'Connection cancelled'})
1989
+ }
1990
+
1991
+ dataChannelTimeoutId = setTimeout(_rejectTimeout, 5000);
1992
+ this._abortController.signal.addEventListener('abort', _rejectAbort);
1993
+
1994
+ this.on('dataChannel', _resolve, this);
1889
1995
  });
1890
1996
  }
1891
1997
  })
1892
1998
  .then(r => {
1893
- this._isPublished = true;
1999
+ this.isPublished = true;
1894
2000
  if(config.stream) {
1895
2001
  let tracks = config.stream.getTracks();
1896
2002
  tracks.forEach(track => {
@@ -1899,7 +2005,7 @@ class RoomSession {
1899
2005
  this.emit('addLocalParticipant', {
1900
2006
  tid: generateUUID(),
1901
2007
  id: handle.handleId,
1902
- userId: handle.userId,
2008
+ userId: decodeJanusDisplay(handle.userId)?.userId,
1903
2009
  track,
1904
2010
  stream: config.stream,
1905
2011
  adding: true,
@@ -1912,7 +2018,7 @@ class RoomSession {
1912
2018
  this.emit('addLocalParticipant', {
1913
2019
  tid:generateUUID(),
1914
2020
  id: handle.handleId,
1915
- userId: handle.userId,
2021
+ userId: decodeJanusDisplay(handle.userId)?.userId,
1916
2022
  track: ev.target,
1917
2023
  stream: config.stream,
1918
2024
  adding: false,
@@ -1929,7 +2035,7 @@ class RoomSession {
1929
2035
  this.emit('addLocalParticipant', {
1930
2036
  tid: generateUUID(),
1931
2037
  id: handle.handleId,
1932
- userId: handle.userId,
2038
+ userId: decodeJanusDisplay(handle.userId)?.userId,
1933
2039
  stream: null,
1934
2040
  adding: false,
1935
2041
  constructId: this.constructId,
@@ -1954,10 +2060,10 @@ class RoomSession {
1954
2060
  }
1955
2061
 
1956
2062
  unpublishLocal(dontWait = false) {
1957
- return this._isPublished
2063
+ return this.isPublished
1958
2064
  ? this.sendMessage(this.handleId, {body: {"request": "unpublish"}}, dontWait)
1959
2065
  .finally(r => {
1960
- this._isPublished = false;
2066
+ this.isPublished = false;
1961
2067
  this.emit('published', {status: false, hasStream: false});
1962
2068
  return r
1963
2069
  })
@@ -2028,6 +2134,11 @@ class RoomSession {
2028
2134
  return this._talkbackIds;
2029
2135
  }
2030
2136
 
2137
+ setRoomType(type = 'watchparty') {
2138
+ this._roomType = type;
2139
+ return this._roomType;
2140
+ }
2141
+
2031
2142
  }
2032
2143
 
2033
2144
  export default Room;