@stream-io/video-client 0.0.2-alpha.2 → 0.0.2-alpha.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.
@@ -5733,14 +5733,13 @@ class Publisher {
5733
5733
  };
5734
5734
  this.updateVideoPublishQuality = (enabledRids) => __awaiter(this, void 0, void 0, function* () {
5735
5735
  var _a;
5736
- console.log('Updating publish quality, qualities requested by SFU:', enabledRids);
5736
+ console.log('Update publish quality, requested rids by SFU:', enabledRids);
5737
5737
  const videoSender = (_a = this.transceiverRegistry[TrackType.VIDEO]) === null || _a === void 0 ? void 0 : _a.sender;
5738
5738
  if (!videoSender)
5739
5739
  return;
5740
5740
  const params = videoSender.getParameters();
5741
5741
  let changed = false;
5742
5742
  params.encodings.forEach((enc) => {
5743
- console.log(enc.rid, enc.active);
5744
5743
  // flip 'active' flag only when necessary
5745
5744
  const shouldEnable = enabledRids.includes(enc.rid);
5746
5745
  if (shouldEnable !== enc.active) {
@@ -5753,6 +5752,10 @@ class Publisher {
5753
5752
  console.warn('No suitable video encoding quality found');
5754
5753
  }
5755
5754
  yield videoSender.setParameters(params);
5755
+ console.log(`Update publish quality, enabled rids: ${params.encodings
5756
+ .filter((e) => e.active)
5757
+ .map((e) => e.rid)
5758
+ .join(', ')}`);
5756
5759
  }
5757
5760
  });
5758
5761
  this.getCodecPreferences = (trackType, preferredCodec) => {
@@ -6615,6 +6618,12 @@ class CallState {
6615
6618
  * @internal
6616
6619
  */
6617
6620
  this.membersSubject = new BehaviorSubject([]);
6621
+ /**
6622
+ * The list of capabilities of the current user.
6623
+ *
6624
+ * @private
6625
+ */
6626
+ this.ownCapabilitiesSubject = new BehaviorSubject([]);
6618
6627
  /**
6619
6628
  * The calling state.
6620
6629
  *
@@ -6797,6 +6806,15 @@ class CallState {
6797
6806
  this.setMembers = (members) => {
6798
6807
  this.setCurrentValue(this.membersSubject, members);
6799
6808
  };
6809
+ /**
6810
+ * Sets the own capabilities.
6811
+ *
6812
+ * @internal
6813
+ * @param capabilities the capabilities to set.
6814
+ */
6815
+ this.setOwnCapabilities = (capabilities) => {
6816
+ return this.setCurrentValue(this.ownCapabilitiesSubject, capabilities);
6817
+ };
6800
6818
  /**
6801
6819
  * Will try to find the participant with the given sessionId in the current call.
6802
6820
  *
@@ -6886,6 +6904,7 @@ class CallState {
6886
6904
  this.callRecordingList$ = this.callRecordingListSubject.asObservable();
6887
6905
  this.metadata$ = this.metadataSubject.asObservable();
6888
6906
  this.members$ = this.membersSubject.asObservable();
6907
+ this.ownCapabilities$ = this.ownCapabilitiesSubject.asObservable();
6889
6908
  this.callingState$ = this.callingStateSubject.asObservable();
6890
6909
  }
6891
6910
  /**
@@ -6981,6 +7000,12 @@ class CallState {
6981
7000
  get members() {
6982
7001
  return this.getCurrentValue(this.members$);
6983
7002
  }
7003
+ /**
7004
+ * The capabilities of the current user for the current call.
7005
+ */
7006
+ get ownCapabilities() {
7007
+ return this.getCurrentValue(this.ownCapabilities$);
7008
+ }
6984
7009
  }
6985
7010
 
6986
7011
  class StreamVideoWriteableStateStore {
@@ -7044,6 +7069,15 @@ class StreamVideoWriteableStateStore {
7044
7069
  this.unregisterCall = (call) => {
7045
7070
  return this.setCalls((calls) => calls.filter((c) => c !== call));
7046
7071
  };
7072
+ /**
7073
+ * Finds a {@link Call} object in the list of {@link Call} objects created/tracked by this client.
7074
+ *
7075
+ * @param type the type of call to find.
7076
+ * @param id the id of the call to find.
7077
+ */
7078
+ this.findCall = (type, id) => {
7079
+ return this.calls.find((c) => c.type === type && c.id === id);
7080
+ };
7047
7081
  this.connectedUserSubject.subscribe((user) => __awaiter(this, void 0, void 0, function* () {
7048
7082
  // leave all calls when the user disconnects.
7049
7083
  if (!user) {
@@ -7163,16 +7197,39 @@ const watchCallAccepted = (call) => {
7163
7197
  * Once the event is received, the call is left.
7164
7198
  */
7165
7199
  const watchCallRejected = (call) => {
7166
- let totalRejections = 0;
7167
7200
  return function onCallRejected(event) {
7168
7201
  return __awaiter(this, void 0, void 0, function* () {
7169
7202
  if (event.type !== 'call.rejected')
7170
7203
  return;
7171
- totalRejections++;
7172
- const { state } = call;
7173
- if (totalRejections >= state.members.length &&
7174
- state.callingState === CallingState.RINGING) {
7175
- yield call.leave();
7204
+ // We want to discard the event if it's from the current user
7205
+ if (event.user.id === call.currentUserId)
7206
+ return;
7207
+ const { call: eventCall } = event;
7208
+ const { session: callSession } = eventCall;
7209
+ if (!callSession) {
7210
+ console.log('No call session provided. Ignoring call.rejected event.');
7211
+ return;
7212
+ }
7213
+ const rejectedBy = callSession.rejected_by;
7214
+ const { members, callingState } = call.state;
7215
+ if (callingState !== CallingState.RINGING) {
7216
+ console.log('Call is not in ringing mode (it is either accepted or rejected already). Ignoring call.rejected event.');
7217
+ return;
7218
+ }
7219
+ if (call.isCreatedByMe) {
7220
+ const everyoneElseRejected = members
7221
+ .filter((m) => m.user_id !== call.currentUserId)
7222
+ .every((m) => rejectedBy[m.user_id]);
7223
+ if (everyoneElseRejected) {
7224
+ console.log('everyone rejected, leaving the call');
7225
+ yield call.leave();
7226
+ }
7227
+ }
7228
+ else {
7229
+ if (rejectedBy[eventCall.created_by.id]) {
7230
+ console.log('call creator rejected, leaving call');
7231
+ yield call.leave();
7232
+ }
7176
7233
  }
7177
7234
  });
7178
7235
  };
@@ -7225,7 +7282,7 @@ const watchCallPermissionsUpdated = (state) => {
7225
7282
  return;
7226
7283
  const { localParticipant } = state;
7227
7284
  if (event.user.id === (localParticipant === null || localParticipant === void 0 ? void 0 : localParticipant.userId)) {
7228
- state.setMetadata((metadata) => (Object.assign(Object.assign({}, metadata), { own_capabilities: event.own_capabilities })));
7285
+ state.setOwnCapabilities(event.own_capabilities);
7229
7286
  }
7230
7287
  };
7231
7288
  };
@@ -7236,7 +7293,6 @@ const watchCallPermissionsUpdated = (state) => {
7236
7293
  */
7237
7294
  const watchCallGrantsUpdated = (state) => {
7238
7295
  return function onCallGrantsUpdated(event) {
7239
- var _a;
7240
7296
  if (event.eventPayload.oneofKind !== 'callGrantsUpdated')
7241
7297
  return;
7242
7298
  const { currentGrants } = event.eventPayload.callGrantsUpdated;
@@ -7247,15 +7303,13 @@ const watchCallGrantsUpdated = (state) => {
7247
7303
  [OwnCapability.SEND_VIDEO]: canPublishVideo,
7248
7304
  [OwnCapability.SCREENSHARE]: canScreenshare,
7249
7305
  };
7250
- const nextCapabilities = (((_a = state.metadata) === null || _a === void 0 ? void 0 : _a.own_capabilities) || []).filter((capability) => update[capability] !== false);
7306
+ const nextCapabilities = state.ownCapabilities.filter((capability) => update[capability] !== false);
7251
7307
  Object.entries(update).forEach(([capability, value]) => {
7252
7308
  if (value && !nextCapabilities.includes(capability)) {
7253
7309
  nextCapabilities.push(capability);
7254
7310
  }
7255
7311
  });
7256
- state.setMetadata((metadata) => {
7257
- return Object.assign(Object.assign({}, metadata), { own_capabilities: nextCapabilities });
7258
- });
7312
+ state.setOwnCapabilities(nextCapabilities);
7259
7313
  }
7260
7314
  };
7261
7315
  };
@@ -7548,10 +7602,7 @@ const watchCallSessionStarted = (state) => {
7548
7602
  return function onCallSessionStarted(event) {
7549
7603
  if (event.type !== 'call.session_started')
7550
7604
  return;
7551
- const { call } = event;
7552
- state.setMetadata((metadata) => (Object.assign(Object.assign({}, call), {
7553
- // FIXME OL: temporary, until the backend sends the own_capabilities
7554
- own_capabilities: (metadata === null || metadata === void 0 ? void 0 : metadata.own_capabilities) || [] })));
7605
+ state.setMetadata(event.call);
7555
7606
  };
7556
7607
  };
7557
7608
  /**
@@ -7563,10 +7614,7 @@ const watchCallSessionEnded = (state) => {
7563
7614
  return function onCallSessionEnded(event) {
7564
7615
  if (event.type !== 'call.session_ended')
7565
7616
  return;
7566
- const { call } = event;
7567
- state.setMetadata((metadata) => (Object.assign(Object.assign({}, call), {
7568
- // FIXME OL: temporary, until the backend sends the own_capabilities
7569
- own_capabilities: (metadata === null || metadata === void 0 ? void 0 : metadata.own_capabilities) || [] })));
7617
+ state.setMetadata(event.call);
7570
7618
  };
7571
7619
  };
7572
7620
  /**
@@ -7643,6 +7691,13 @@ const watchUnblockedUser = (state) => (event) => {
7643
7691
  });
7644
7692
  };
7645
7693
 
7694
+ /**
7695
+ * Registers the default event handlers for a call during its lifecycle.
7696
+ *
7697
+ * @param call the call to register event handlers for.
7698
+ * @param state the call state.
7699
+ * @param dispatcher the dispatcher.
7700
+ */
7646
7701
  const registerEventHandlers = (call, state, dispatcher) => {
7647
7702
  const coordinatorEvents = {
7648
7703
  'call.blocked_user': watchBlockedUser(state),
@@ -7665,8 +7720,6 @@ const registerEventHandlers = (call, state, dispatcher) => {
7665
7720
  'call.session_participant_left': watchCallSessionParticipantLeft(state),
7666
7721
  'call.unblocked_user': watchUnblockedUser(state),
7667
7722
  'call.updated': watchCallUpdated(state),
7668
- 'call.notification': (event) => console.log(`Received ${event.type} event`, event),
7669
- 'call.ring': (event) => console.log(`Received ${event.type} event`, event),
7670
7723
  };
7671
7724
  const eventHandlers = [
7672
7725
  watchChangePublishQuality(dispatcher, call),
@@ -7692,6 +7745,11 @@ const registerEventHandlers = (call, state, dispatcher) => {
7692
7745
  eventHandlers.forEach((unsubscribe) => unsubscribe());
7693
7746
  };
7694
7747
  };
7748
+ /**
7749
+ * Registers event handlers for a call that is of ringing type.
7750
+ *
7751
+ * @param call the call to register event handlers for.
7752
+ */
7695
7753
  const registerRingingCallEventHandlers = (call) => {
7696
7754
  const coordinatorRingEvents = {
7697
7755
  'call.accepted': watchCallAccepted(call),
@@ -7718,13 +7776,14 @@ const registerRingingCallEventHandlers = (call) => {
7718
7776
  const join = (httpClient, type, id, data) => __awaiter(void 0, void 0, void 0, function* () {
7719
7777
  yield httpClient.connectionIdPromise;
7720
7778
  const joinCallResponse = yield doJoin(httpClient, type, id, data);
7721
- const { call, credentials, members } = joinCallResponse;
7779
+ const { call, credentials, members, own_capabilities } = joinCallResponse;
7722
7780
  return {
7723
7781
  connectionConfig: toRtcConfiguration(credentials.ice_servers),
7724
7782
  sfuServer: credentials.server,
7725
7783
  token: credentials.token,
7726
7784
  metadata: call,
7727
7785
  members,
7786
+ ownCapabilities: own_capabilities,
7728
7787
  };
7729
7788
  });
7730
7789
  const doJoin = (httpClient, type, id, data) => __awaiter(void 0, void 0, void 0, function* () {
@@ -7741,9 +7800,12 @@ const doJoin = (httpClient, type, id, data) => __awaiter(void 0, void 0, void 0,
7741
7800
  });
7742
7801
  const getLocationHint = () => __awaiter(void 0, void 0, void 0, function* () {
7743
7802
  const hintURL = `https://hint.stream-io-video.com/`;
7803
+ const abortController = new AbortController();
7804
+ const timeoutId = setTimeout(() => abortController.abort(), 1000);
7744
7805
  try {
7745
7806
  const response = yield fetch(hintURL, {
7746
7807
  method: 'HEAD',
7808
+ signal: abortController.signal,
7747
7809
  });
7748
7810
  const awsPop = response.headers.get('x-amz-cf-pop') || 'ERR';
7749
7811
  return awsPop.substring(0, 3); // AMS1-P2 -> AMS
@@ -7752,6 +7814,9 @@ const getLocationHint = () => __awaiter(void 0, void 0, void 0, function* () {
7752
7814
  console.error(`Failed to get location hint from ${hintURL}`, e);
7753
7815
  return 'ERR';
7754
7816
  }
7817
+ finally {
7818
+ clearTimeout(timeoutId);
7819
+ }
7755
7820
  });
7756
7821
  const toRtcConfiguration = (config) => {
7757
7822
  if (!config || config.length === 0)
@@ -8254,7 +8319,7 @@ class Call {
8254
8319
  * Use the [`StreamVideoClient.call`](./StreamVideoClient.md/#call)
8255
8320
  * method to construct a `Call` instance.
8256
8321
  */
8257
- constructor({ type, id, streamClient, metadata, members, sortParticipantsBy, clientStore, ringing = false, watching = false, }) {
8322
+ constructor({ type, id, streamClient, metadata, members, ownCapabilities, sortParticipantsBy, clientStore, ringing = false, watching = false, }) {
8258
8323
  /**
8259
8324
  * ViewportTracker instance
8260
8325
  */
@@ -8298,13 +8363,11 @@ class Call {
8298
8363
  if (this.isCreatedByMe && !hasOtherParticipants) {
8299
8364
  // Signals other users that I have cancelled my call to them
8300
8365
  // before they accepted it.
8301
- // Causes the `call.ended` event to be emitted to all the call members.
8302
- yield this.endCall();
8366
+ yield this.reject();
8303
8367
  }
8304
8368
  else if (reject && callingState === CallingState.RINGING) {
8305
8369
  // Signals other users that I have rejected the incoming call.
8306
- // Causes the `call.rejected` event to be emitted to all the call members.
8307
- yield this.sendEvent({ type: 'call.rejected' });
8370
+ yield this.reject();
8308
8371
  }
8309
8372
  }
8310
8373
  (_a = this.statsReporter) === null || _a === void 0 ? void 0 : _a.stop();
@@ -8336,11 +8399,19 @@ class Call {
8336
8399
  });
8337
8400
  /**
8338
8401
  * Loads the information about the call.
8402
+ *
8403
+ * @param params.ring if set to true, a `call.ring` event will be sent to the call members.
8404
+ * @param params.notify if set to true, a `call.notification` event will be sent to the call members.
8405
+ * @param params.members_limit the members limit.
8339
8406
  */
8340
8407
  this.get = (params) => __awaiter(this, void 0, void 0, function* () {
8341
8408
  const response = yield this.streamClient.get(this.streamClientBasePath, params);
8409
+ if ((params === null || params === void 0 ? void 0 : params.ring) && !this.ringing) {
8410
+ this.ringingSubject.next(true);
8411
+ }
8342
8412
  this.state.setMetadata(response.call);
8343
8413
  this.state.setMembers(response.members);
8414
+ this.state.setOwnCapabilities(response.own_capabilities);
8344
8415
  if (this.streamClient._hasConnectionID()) {
8345
8416
  this.watching = true;
8346
8417
  this.clientStore.registerCall(this);
@@ -8354,20 +8425,52 @@ class Call {
8354
8425
  */
8355
8426
  this.getOrCreate = (data) => __awaiter(this, void 0, void 0, function* () {
8356
8427
  const response = yield this.streamClient.post(this.streamClientBasePath, data);
8428
+ if ((data === null || data === void 0 ? void 0 : data.ring) && !this.ringing) {
8429
+ this.ringingSubject.next(true);
8430
+ }
8357
8431
  this.state.setMetadata(response.call);
8358
8432
  this.state.setMembers(response.members);
8433
+ this.state.setOwnCapabilities(response.own_capabilities);
8359
8434
  if (this.streamClient._hasConnectionID()) {
8360
8435
  this.watching = true;
8361
8436
  this.clientStore.registerCall(this);
8362
8437
  }
8363
8438
  return response;
8364
8439
  });
8440
+ /**
8441
+ * A shortcut for {@link Call.get} with `ring` parameter set to `true`.
8442
+ * Will send a `call.ring` event to the call members.
8443
+ */
8365
8444
  this.ring = () => __awaiter(this, void 0, void 0, function* () {
8366
8445
  return yield this.get({ ring: true });
8367
8446
  });
8447
+ /**
8448
+ * A shortcut for {@link Call.get} with `notify` parameter set to `true`.
8449
+ * Will send a `call.notification` event to the call members.
8450
+ */
8368
8451
  this.notify = () => __awaiter(this, void 0, void 0, function* () {
8369
8452
  return yield this.get({ notify: true });
8370
8453
  });
8454
+ /**
8455
+ * Marks the incoming call as accepted.
8456
+ *
8457
+ * This method should be used only for "ringing" call flows.
8458
+ * {@link Call.join} invokes this method automatically for you when joining a call.
8459
+ * Unless you are implementing a custom "ringing" flow, you should not use this method.
8460
+ */
8461
+ this.accept = () => __awaiter(this, void 0, void 0, function* () {
8462
+ return this.streamClient.post(`${this.streamClientBasePath}/accept`);
8463
+ });
8464
+ /**
8465
+ * Marks the incoming call as rejected.
8466
+ *
8467
+ * This method should be used only for "ringing" call flows.
8468
+ * {@link Call.leave} invokes this method automatically for you when you leave or reject this call.
8469
+ * Unless you are implementing a custom "ringing" flow, you should not use this method.
8470
+ */
8471
+ this.reject = () => __awaiter(this, void 0, void 0, function* () {
8472
+ return this.streamClient.post(`${this.streamClientBasePath}/reject`);
8473
+ });
8371
8474
  /**
8372
8475
  * Will start to watch for call related WebSocket events and initiate a call session with the server.
8373
8476
  *
@@ -8380,6 +8483,13 @@ class Call {
8380
8483
  }
8381
8484
  const previousCallingState = this.state.callingState;
8382
8485
  this.state.setCallingState(CallingState.JOINING);
8486
+ if ((data === null || data === void 0 ? void 0 : data.ring) && !this.ringing) {
8487
+ this.ringingSubject.next(true);
8488
+ }
8489
+ if (this.ringing && !this.isCreatedByMe) {
8490
+ // signals other users that I have accepted the incoming call.
8491
+ yield this.accept();
8492
+ }
8383
8493
  let sfuServer;
8384
8494
  let sfuToken;
8385
8495
  let connectionConfig;
@@ -8387,6 +8497,7 @@ class Call {
8387
8497
  const call = yield join(this.streamClient, this.type, this.id, data);
8388
8498
  this.state.setMetadata(call.metadata);
8389
8499
  this.state.setMembers(call.members);
8500
+ this.state.setOwnCapabilities(call.ownCapabilities);
8390
8501
  connectionConfig = call.connectionConfig;
8391
8502
  sfuServer = call.sfuServer;
8392
8503
  sfuToken = call.token;
@@ -8576,15 +8687,6 @@ class Call {
8576
8687
  }
8577
8688
  }
8578
8689
  });
8579
- /**
8580
- * Will update the call members.
8581
- *
8582
- * @param data the request data.
8583
- */
8584
- this.updateCallMembers = (data) => __awaiter(this, void 0, void 0, function* () {
8585
- // FIXME: OL: implement kick-users
8586
- return this.streamClient.post(`${this.streamClientBasePath}/members`, data);
8587
- });
8588
8690
  /**
8589
8691
  * Starts publishing the given video stream to the call.
8590
8692
  * The stream will be stopped if the user changes an input device, or if the user leaves the call.
@@ -9037,7 +9139,12 @@ class Call {
9037
9139
  * @param updates the updates to apply to the call.
9038
9140
  */
9039
9141
  this.update = (updates) => __awaiter(this, void 0, void 0, function* () {
9040
- return this.streamClient.patch(`${this.streamClientBasePath}`, updates);
9142
+ const response = yield this.streamClient.patch(`${this.streamClientBasePath}`, updates);
9143
+ const { call, members, own_capabilities } = response;
9144
+ this.state.setMetadata(call);
9145
+ this.state.setMembers(members);
9146
+ this.state.setOwnCapabilities(own_capabilities);
9147
+ return response;
9041
9148
  });
9042
9149
  /**
9043
9150
  * Ends the call. Once the call is ended, it cannot be re-joined.
@@ -9064,7 +9171,17 @@ class Call {
9064
9171
  this.queryMembers = (request) => {
9065
9172
  return this.streamClient.post('/call/members', Object.assign(Object.assign({}, request), { id: this.id, type: this.type }));
9066
9173
  };
9174
+ /**
9175
+ * Will update the call members.
9176
+ *
9177
+ * @param data the request data.
9178
+ */
9179
+ this.updateCallMembers = (data) => __awaiter(this, void 0, void 0, function* () {
9180
+ return this.streamClient.post(`${this.streamClientBasePath}/members`, data);
9181
+ });
9067
9182
  this.scheduleAutoDrop = () => {
9183
+ if (this.dropTimeout)
9184
+ clearTimeout(this.dropTimeout);
9068
9185
  const subscription = this.state.metadata$
9069
9186
  .pipe(pairwise(), tap(([prevMeta, currentMeta]) => {
9070
9187
  if (!(currentMeta && this.clientStore.connectedUser))
@@ -9076,8 +9193,8 @@ class Call {
9076
9193
  currentMeta.settings.ring.auto_cancel_timeout_ms,
9077
9194
  ]
9078
9195
  : [
9079
- prevMeta === null || prevMeta === void 0 ? void 0 : prevMeta.settings.ring.auto_reject_timeout_ms,
9080
- currentMeta.settings.ring.auto_reject_timeout_ms,
9196
+ prevMeta === null || prevMeta === void 0 ? void 0 : prevMeta.settings.ring.incoming_call_timeout_ms,
9197
+ currentMeta.settings.ring.incoming_call_timeout_ms,
9081
9198
  ];
9082
9199
  if (typeof timeoutMs === 'undefined' || timeoutMs === prevTimeoutMs)
9083
9200
  return;
@@ -9091,25 +9208,23 @@ class Call {
9091
9208
  });
9092
9209
  };
9093
9210
  /**
9094
- * Performs HTTP request to retrieve the list of recordings for the current call
9095
- * Updates the call state with provided array of CallRecording objects
9211
+ * Retrieves the list of recordings for the current call or call session.
9212
+ * Updates the call state with the returned array of CallRecording objects.
9213
+ *
9214
+ * If `callSessionId` is provided, it will return the recordings for that call session.
9215
+ * Otherwise, all recordings for the current call will be returned.
9216
+ *
9217
+ * @param callSessionId the call session id to retrieve recordings for.
9096
9218
  */
9097
- this.queryRecordings = () => __awaiter(this, void 0, void 0, function* () {
9098
- // FIXME: this is a temporary setting to take call ID as session ID
9099
- const sessionId = this.id;
9100
- const response = yield this.streamClient.get(`${this.streamClientBasePath}/${sessionId}/recordings`);
9219
+ this.queryRecordings = (callSessionId) => __awaiter(this, void 0, void 0, function* () {
9220
+ let endpoint = this.streamClientBasePath;
9221
+ if (callSessionId) {
9222
+ endpoint = `${endpoint}/${callSessionId}`;
9223
+ }
9224
+ const response = yield this.streamClient.get(`${endpoint}/recordings`);
9101
9225
  this.state.setCallRecordingsList(response.recordings);
9102
9226
  return response;
9103
9227
  });
9104
- /**
9105
- * Returns a list of Edge Serves for current call.
9106
- *
9107
- * @deprecated merged with `call.join`.
9108
- * @param data the data.
9109
- */
9110
- this.getEdgeServer = (data) => {
9111
- return this.streamClient.post(`${this.streamClientBasePath}/get_edge_server`, data);
9112
- };
9113
9228
  /**
9114
9229
  * Sends an event to all call participants.
9115
9230
  *
@@ -9118,12 +9233,6 @@ class Call {
9118
9233
  this.sendEvent = (event) => __awaiter(this, void 0, void 0, function* () {
9119
9234
  return this.streamClient.post(`${this.streamClientBasePath}/event`, event);
9120
9235
  });
9121
- this.accept = () => __awaiter(this, void 0, void 0, function* () {
9122
- return this.streamClient.post(`${this.streamClientBasePath}/accept`);
9123
- });
9124
- this.reject = () => __awaiter(this, void 0, void 0, function* () {
9125
- return this.streamClient.post(`${this.streamClientBasePath}/reject`);
9126
- });
9127
9236
  this.type = type;
9128
9237
  this.id = id;
9129
9238
  this.cid = `${type}:${id}`;
@@ -9139,6 +9248,7 @@ class Call {
9139
9248
  }
9140
9249
  this.state.setMetadata(metadata);
9141
9250
  this.state.setMembers(members || []);
9251
+ this.state.setOwnCapabilities(ownCapabilities || []);
9142
9252
  this.state.setCallingState(ringing ? CallingState.RINGING : CallingState.IDLE);
9143
9253
  this.leaveCallHooks.push(registerEventHandlers(this, this.state, this.dispatcher));
9144
9254
  this.registerEffects();
@@ -9150,23 +9260,13 @@ class Call {
9150
9260
  createSubscription(this.state.metadata$, (metadata) => {
9151
9261
  if (!metadata)
9152
9262
  return;
9153
- this.permissionsContext.setPermissions(metadata.own_capabilities);
9154
9263
  this.permissionsContext.setCallSettings(metadata.settings);
9155
9264
  }),
9156
- // handles the case when the user is blocked by the call owner.
9157
- createSubscription(this.state.metadata$, (metadata) => __awaiter(this, void 0, void 0, function* () {
9158
- if (!metadata)
9159
- return;
9160
- const currentUserId = this.currentUserId;
9161
- if (currentUserId &&
9162
- metadata.blocked_user_ids.includes(currentUserId)) {
9163
- yield this.leave();
9164
- }
9165
- })),
9166
- // handle the case when the user permissions are revoked.
9167
- createSubscription(this.state.metadata$, (metadata) => {
9168
- if (!metadata)
9169
- return;
9265
+ // handle the case when the user permissions are modified.
9266
+ createSubscription(this.state.ownCapabilities$, (ownCapabilities) => {
9267
+ // update the permission context.
9268
+ this.permissionsContext.setPermissions(ownCapabilities);
9269
+ // check if the user still has publishing permissions and stop publishing if not.
9170
9270
  const permissionToTrackType = {
9171
9271
  [OwnCapability.SEND_AUDIO]: TrackType.AUDIO,
9172
9272
  [OwnCapability.SEND_VIDEO]: TrackType.VIDEO,
@@ -9181,6 +9281,16 @@ class Call {
9181
9281
  }
9182
9282
  });
9183
9283
  }),
9284
+ // handles the case when the user is blocked by the call owner.
9285
+ createSubscription(this.state.metadata$, (metadata) => __awaiter(this, void 0, void 0, function* () {
9286
+ if (!metadata)
9287
+ return;
9288
+ const currentUserId = this.currentUserId;
9289
+ if (currentUserId &&
9290
+ metadata.blocked_user_ids.includes(currentUserId)) {
9291
+ yield this.leave();
9292
+ }
9293
+ })),
9184
9294
  // watch for auto drop cancellation
9185
9295
  createSubscription(this.state.callingState$, (callingState) => {
9186
9296
  if (!this.ringing)
@@ -10870,7 +10980,7 @@ class StreamClient {
10870
10980
  }
10871
10981
  getUserAgent() {
10872
10982
  return (this.userAgent ||
10873
- `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.2-alpha.1"}`);
10983
+ `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.2-alpha.19"}`);
10874
10984
  }
10875
10985
  setUserAgent(userAgent) {
10876
10986
  this.userAgent = userAgent;
@@ -10916,6 +11026,7 @@ class StreamVideoClient {
10916
11026
  * @param opts the options for the client.
10917
11027
  */
10918
11028
  constructor(apiKey, opts) {
11029
+ this.eventHandlersToUnregister = [];
10919
11030
  /**
10920
11031
  * Connects the given user to the client.
10921
11032
  * Only one user can connect at a time, if you want to change users, call `disconnectUser` before connecting a new user.
@@ -10928,8 +11039,8 @@ class StreamVideoClient {
10928
11039
  const connectUserResponse = yield this.streamClient.connectUser(
10929
11040
  // @ts-expect-error
10930
11041
  user, tokenOrProvider);
10931
- // FIXME OL: unregister the event listeners.
10932
- this.on('connection.changed', (e) => {
11042
+ this.writeableStateStore.setConnectedUser(user);
11043
+ this.eventHandlersToUnregister.push(this.on('connection.changed', (e) => {
10933
11044
  const event = e;
10934
11045
  if (event.online) {
10935
11046
  const callsToReWatch = this.writeableStateStore.calls
@@ -10947,9 +11058,8 @@ class StreamVideoClient {
10947
11058
  });
10948
11059
  }
10949
11060
  }
10950
- });
10951
- // FIXME: OL: unregister the event listeners.
10952
- this.on('call.created', (event) => {
11061
+ }));
11062
+ this.eventHandlersToUnregister.push(this.on('call.created', (event) => {
10953
11063
  if (event.type !== 'call.created')
10954
11064
  return;
10955
11065
  const { call, members } = event;
@@ -10963,11 +11073,36 @@ class StreamVideoClient {
10963
11073
  id: call.id,
10964
11074
  metadata: call,
10965
11075
  members,
10966
- ringing: false,
10967
11076
  clientStore: this.writeableStateStore,
10968
11077
  }));
10969
- });
10970
- this.writeableStateStore.setConnectedUser(user);
11078
+ }));
11079
+ this.eventHandlersToUnregister.push(this.on('call.ring', (event) => __awaiter(this, void 0, void 0, function* () {
11080
+ if (event.type !== 'call.ring')
11081
+ return;
11082
+ const { call, members } = event;
11083
+ if (user.id === call.created_by.id) {
11084
+ console.warn('Received `call.ring` sent by the current user');
11085
+ return;
11086
+ }
11087
+ // The call might already be tracked by the client,
11088
+ // if `call.created` was received before `call.ring`.
11089
+ // In that case, we just reuse the already tracked call.
11090
+ let theCall = this.writeableStateStore.findCall(call.type, call.id);
11091
+ if (!theCall) {
11092
+ // otherwise, we create a new call
11093
+ theCall = new Call({
11094
+ streamClient: this.streamClient,
11095
+ type: call.type,
11096
+ id: call.id,
11097
+ members,
11098
+ clientStore: this.writeableStateStore,
11099
+ ringing: true,
11100
+ });
11101
+ }
11102
+ // we fetch the latest metadata for the call from the server
11103
+ yield theCall.get({ ring: true });
11104
+ this.writeableStateStore.registerCall(theCall);
11105
+ })));
10971
11106
  return connectUserResponse;
10972
11107
  });
10973
11108
  /**
@@ -10990,6 +11125,8 @@ class StreamVideoClient {
10990
11125
  */
10991
11126
  this.disconnectUser = (timeout) => __awaiter(this, void 0, void 0, function* () {
10992
11127
  yield this.streamClient.disconnectUser(timeout);
11128
+ this.eventHandlersToUnregister.forEach((unregister) => unregister());
11129
+ this.eventHandlersToUnregister = [];
10993
11130
  this.writeableStateStore.setConnectedUser(undefined);
10994
11131
  });
10995
11132
  /**
@@ -11051,6 +11188,7 @@ class StreamVideoClient {
11051
11188
  type: c.call.type,
11052
11189
  metadata: c.call,
11053
11190
  members: c.members,
11191
+ ownCapabilities: c.own_capabilities,
11054
11192
  watching: data.watch,
11055
11193
  clientStore: this.writeableStateStore,
11056
11194
  });
@@ -11400,7 +11538,7 @@ const createSoundDetector = (audioStream, onSoundDetectedStateChanged, options =
11400
11538
  const percentage = averagedDataValue > audioLevelThreshold
11401
11539
  ? 100
11402
11540
  : Math.round((averagedDataValue / audioLevelThreshold) * 100);
11403
- onSoundDetectedStateChanged(isSoundDetected, percentage);
11541
+ onSoundDetectedStateChanged({ isSoundDetected, audioLevel: percentage });
11404
11542
  }, detectionFrequencyInMs);
11405
11543
  return function stop() {
11406
11544
  return __awaiter(this, void 0, void 0, function* () {