@stream-io/video-client 0.0.2-alpha.6 → 0.0.2-alpha.8

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.
package/dist/index.cjs.js CHANGED
@@ -7048,6 +7048,15 @@ class StreamVideoWriteableStateStore {
7048
7048
  this.unregisterCall = (call) => {
7049
7049
  return this.setCalls((calls) => calls.filter((c) => c !== call));
7050
7050
  };
7051
+ /**
7052
+ * Finds a {@link Call} object in the list of {@link Call} objects created/tracked by this client.
7053
+ *
7054
+ * @param type the type of call to find.
7055
+ * @param id the id of the call to find.
7056
+ */
7057
+ this.findCall = (type, id) => {
7058
+ return this.calls.find((c) => c.type === type && c.id === id);
7059
+ };
7051
7060
  this.connectedUserSubject.subscribe((user) => __awaiter(this, void 0, void 0, function* () {
7052
7061
  // leave all calls when the user disconnects.
7053
7062
  if (!user) {
@@ -7167,16 +7176,39 @@ const watchCallAccepted = (call) => {
7167
7176
  * Once the event is received, the call is left.
7168
7177
  */
7169
7178
  const watchCallRejected = (call) => {
7170
- let totalRejections = 0;
7171
7179
  return function onCallRejected(event) {
7172
7180
  return __awaiter(this, void 0, void 0, function* () {
7173
7181
  if (event.type !== 'call.rejected')
7174
7182
  return;
7175
- totalRejections++;
7176
- const { state } = call;
7177
- if (totalRejections >= state.members.length &&
7178
- state.callingState === exports.CallingState.RINGING) {
7179
- yield call.leave();
7183
+ // We want to discard the event if it's from the current user
7184
+ if (event.user.id === call.currentUserId)
7185
+ return;
7186
+ const { call: eventCall } = event;
7187
+ const { session: callSession } = eventCall;
7188
+ if (!callSession) {
7189
+ console.log('No call session provided. Ignoring call.rejected event.');
7190
+ return;
7191
+ }
7192
+ const rejectedBy = callSession.rejected_by;
7193
+ const { members, callingState } = call.state;
7194
+ if (callingState !== exports.CallingState.RINGING) {
7195
+ console.log('Call is not in ringing mode (it is either accepted or rejected already). Ignoring call.rejected event.');
7196
+ return;
7197
+ }
7198
+ if (call.isCreatedByMe) {
7199
+ const everyoneElseRejected = members
7200
+ .filter((m) => m.user_id !== call.currentUserId)
7201
+ .every((m) => rejectedBy[m.user_id]);
7202
+ if (everyoneElseRejected) {
7203
+ console.log('everyone rejected, leaving the call');
7204
+ yield call.leave();
7205
+ }
7206
+ }
7207
+ else {
7208
+ if (rejectedBy[eventCall.created_by.id]) {
7209
+ console.log('call creator rejected, leaving call');
7210
+ yield call.leave();
7211
+ }
7180
7212
  }
7181
7213
  });
7182
7214
  };
@@ -7647,6 +7679,13 @@ const watchUnblockedUser = (state) => (event) => {
7647
7679
  });
7648
7680
  };
7649
7681
 
7682
+ /**
7683
+ * Registers the default event handlers for a call during its lifecycle.
7684
+ *
7685
+ * @param call the call to register event handlers for.
7686
+ * @param state the call state.
7687
+ * @param dispatcher the dispatcher.
7688
+ */
7650
7689
  const registerEventHandlers = (call, state, dispatcher) => {
7651
7690
  const coordinatorEvents = {
7652
7691
  'call.blocked_user': watchBlockedUser(state),
@@ -7669,8 +7708,6 @@ const registerEventHandlers = (call, state, dispatcher) => {
7669
7708
  'call.session_participant_left': watchCallSessionParticipantLeft(state),
7670
7709
  'call.unblocked_user': watchUnblockedUser(state),
7671
7710
  'call.updated': watchCallUpdated(state),
7672
- 'call.notification': (event) => console.log(`Received ${event.type} event`, event),
7673
- 'call.ring': (event) => console.log(`Received ${event.type} event`, event),
7674
7711
  };
7675
7712
  const eventHandlers = [
7676
7713
  watchChangePublishQuality(dispatcher, call),
@@ -7696,6 +7733,11 @@ const registerEventHandlers = (call, state, dispatcher) => {
7696
7733
  eventHandlers.forEach((unsubscribe) => unsubscribe());
7697
7734
  };
7698
7735
  };
7736
+ /**
7737
+ * Registers event handlers for a call that is of ringing type.
7738
+ *
7739
+ * @param call the call to register event handlers for.
7740
+ */
7699
7741
  const registerRingingCallEventHandlers = (call) => {
7700
7742
  const coordinatorRingEvents = {
7701
7743
  'call.accepted': watchCallAccepted(call),
@@ -8302,13 +8344,11 @@ class Call {
8302
8344
  if (this.isCreatedByMe && !hasOtherParticipants) {
8303
8345
  // Signals other users that I have cancelled my call to them
8304
8346
  // before they accepted it.
8305
- // Causes the `call.ended` event to be emitted to all the call members.
8306
- yield this.endCall();
8347
+ yield this.reject();
8307
8348
  }
8308
8349
  else if (reject && callingState === exports.CallingState.RINGING) {
8309
8350
  // Signals other users that I have rejected the incoming call.
8310
- // Causes the `call.rejected` event to be emitted to all the call members.
8311
- yield this.sendEvent({ type: 'call.rejected' });
8351
+ yield this.reject();
8312
8352
  }
8313
8353
  }
8314
8354
  (_a = this.statsReporter) === null || _a === void 0 ? void 0 : _a.stop();
@@ -8340,9 +8380,16 @@ class Call {
8340
8380
  });
8341
8381
  /**
8342
8382
  * Loads the information about the call.
8383
+ *
8384
+ * @param params.ring if set to true, a `call.ring` event will be sent to the call members.
8385
+ * @param params.notify if set to true, a `call.notification` event will be sent to the call members.
8386
+ * @param params.members_limit the members limit.
8343
8387
  */
8344
8388
  this.get = (params) => __awaiter(this, void 0, void 0, function* () {
8345
8389
  const response = yield this.streamClient.get(this.streamClientBasePath, params);
8390
+ if ((params === null || params === void 0 ? void 0 : params.ring) && !this.ringing) {
8391
+ this.ringingSubject.next(true);
8392
+ }
8346
8393
  this.state.setMetadata(response.call);
8347
8394
  this.state.setMembers(response.members);
8348
8395
  if (this.streamClient._hasConnectionID()) {
@@ -8358,6 +8405,9 @@ class Call {
8358
8405
  */
8359
8406
  this.getOrCreate = (data) => __awaiter(this, void 0, void 0, function* () {
8360
8407
  const response = yield this.streamClient.post(this.streamClientBasePath, data);
8408
+ if ((data === null || data === void 0 ? void 0 : data.ring) && !this.ringing) {
8409
+ this.ringingSubject.next(true);
8410
+ }
8361
8411
  this.state.setMetadata(response.call);
8362
8412
  this.state.setMembers(response.members);
8363
8413
  if (this.streamClient._hasConnectionID()) {
@@ -8366,12 +8416,40 @@ class Call {
8366
8416
  }
8367
8417
  return response;
8368
8418
  });
8419
+ /**
8420
+ * A shortcut for {@link Call.get} with `ring` parameter set to `true`.
8421
+ * Will send a `call.ring` event to the call members.
8422
+ */
8369
8423
  this.ring = () => __awaiter(this, void 0, void 0, function* () {
8370
8424
  return yield this.get({ ring: true });
8371
8425
  });
8426
+ /**
8427
+ * A shortcut for {@link Call.get} with `notify` parameter set to `true`.
8428
+ * Will send a `call.notification` event to the call members.
8429
+ */
8372
8430
  this.notify = () => __awaiter(this, void 0, void 0, function* () {
8373
8431
  return yield this.get({ notify: true });
8374
8432
  });
8433
+ /**
8434
+ * Marks the incoming call as accepted.
8435
+ *
8436
+ * This method should be used only for "ringing" call flows.
8437
+ * {@link Call.join} invokes this method automatically for you when joining a call.
8438
+ * Unless you are implementing a custom "ringing" flow, you should not use this method.
8439
+ */
8440
+ this.accept = () => __awaiter(this, void 0, void 0, function* () {
8441
+ return this.streamClient.post(`${this.streamClientBasePath}/accept`);
8442
+ });
8443
+ /**
8444
+ * Marks the incoming call as rejected.
8445
+ *
8446
+ * This method should be used only for "ringing" call flows.
8447
+ * {@link Call.leave} invokes this method automatically for you when you leave or reject this call.
8448
+ * Unless you are implementing a custom "ringing" flow, you should not use this method.
8449
+ */
8450
+ this.reject = () => __awaiter(this, void 0, void 0, function* () {
8451
+ return this.streamClient.post(`${this.streamClientBasePath}/reject`);
8452
+ });
8375
8453
  /**
8376
8454
  * Will start to watch for call related WebSocket events and initiate a call session with the server.
8377
8455
  *
@@ -8384,6 +8462,13 @@ class Call {
8384
8462
  }
8385
8463
  const previousCallingState = this.state.callingState;
8386
8464
  this.state.setCallingState(exports.CallingState.JOINING);
8465
+ if ((data === null || data === void 0 ? void 0 : data.ring) && !this.ringing) {
8466
+ this.ringingSubject.next(true);
8467
+ }
8468
+ if (this.ringing && !this.isCreatedByMe) {
8469
+ // signals other users that I have accepted the incoming call.
8470
+ yield this.accept();
8471
+ }
8387
8472
  let sfuServer;
8388
8473
  let sfuToken;
8389
8474
  let connectionConfig;
@@ -8580,14 +8665,6 @@ class Call {
8580
8665
  }
8581
8666
  }
8582
8667
  });
8583
- /**
8584
- * Will update the call members.
8585
- *
8586
- * @param data the request data.
8587
- */
8588
- this.updateCallMembers = (data) => __awaiter(this, void 0, void 0, function* () {
8589
- return this.streamClient.post(`${this.streamClientBasePath}/members`, data);
8590
- });
8591
8668
  /**
8592
8669
  * Starts publishing the given video stream to the call.
8593
8670
  * The stream will be stopped if the user changes an input device, or if the user leaves the call.
@@ -9067,7 +9144,17 @@ class Call {
9067
9144
  this.queryMembers = (request) => {
9068
9145
  return this.streamClient.post('/call/members', Object.assign(Object.assign({}, request), { id: this.id, type: this.type }));
9069
9146
  };
9147
+ /**
9148
+ * Will update the call members.
9149
+ *
9150
+ * @param data the request data.
9151
+ */
9152
+ this.updateCallMembers = (data) => __awaiter(this, void 0, void 0, function* () {
9153
+ return this.streamClient.post(`${this.streamClientBasePath}/members`, data);
9154
+ });
9070
9155
  this.scheduleAutoDrop = () => {
9156
+ if (this.dropTimeout)
9157
+ clearTimeout(this.dropTimeout);
9071
9158
  const subscription = this.state.metadata$
9072
9159
  .pipe(rxjs.pairwise(), rxjs.tap(([prevMeta, currentMeta]) => {
9073
9160
  if (!(currentMeta && this.clientStore.connectedUser))
@@ -9079,8 +9166,8 @@ class Call {
9079
9166
  currentMeta.settings.ring.auto_cancel_timeout_ms,
9080
9167
  ]
9081
9168
  : [
9082
- prevMeta === null || prevMeta === void 0 ? void 0 : prevMeta.settings.ring.auto_reject_timeout_ms,
9083
- currentMeta.settings.ring.auto_reject_timeout_ms,
9169
+ prevMeta === null || prevMeta === void 0 ? void 0 : prevMeta.settings.ring.incoming_call_timeout_ms,
9170
+ currentMeta.settings.ring.incoming_call_timeout_ms,
9084
9171
  ];
9085
9172
  if (typeof timeoutMs === 'undefined' || timeoutMs === prevTimeoutMs)
9086
9173
  return;
@@ -9128,12 +9215,6 @@ class Call {
9128
9215
  this.sendEvent = (event) => __awaiter(this, void 0, void 0, function* () {
9129
9216
  return this.streamClient.post(`${this.streamClientBasePath}/event`, event);
9130
9217
  });
9131
- this.accept = () => __awaiter(this, void 0, void 0, function* () {
9132
- return this.streamClient.post(`${this.streamClientBasePath}/accept`);
9133
- });
9134
- this.reject = () => __awaiter(this, void 0, void 0, function* () {
9135
- return this.streamClient.post(`${this.streamClientBasePath}/reject`);
9136
- });
9137
9218
  this.type = type;
9138
9219
  this.id = id;
9139
9220
  this.cid = `${type}:${id}`;
@@ -10881,7 +10962,7 @@ class StreamClient {
10881
10962
  }
10882
10963
  getUserAgent() {
10883
10964
  return (this.userAgent ||
10884
- `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.2-alpha.5"}`);
10965
+ `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.2-alpha.7"}`);
10885
10966
  }
10886
10967
  setUserAgent(userAgent) {
10887
10968
  this.userAgent = userAgent;
@@ -10927,6 +11008,7 @@ class StreamVideoClient {
10927
11008
  * @param opts the options for the client.
10928
11009
  */
10929
11010
  constructor(apiKey, opts) {
11011
+ this.eventHandlersToUnregister = [];
10930
11012
  /**
10931
11013
  * Connects the given user to the client.
10932
11014
  * Only one user can connect at a time, if you want to change users, call `disconnectUser` before connecting a new user.
@@ -10939,8 +11021,8 @@ class StreamVideoClient {
10939
11021
  const connectUserResponse = yield this.streamClient.connectUser(
10940
11022
  // @ts-expect-error
10941
11023
  user, tokenOrProvider);
10942
- // FIXME OL: unregister the event listeners.
10943
- this.on('connection.changed', (e) => {
11024
+ this.writeableStateStore.setConnectedUser(user);
11025
+ this.eventHandlersToUnregister.push(this.on('connection.changed', (e) => {
10944
11026
  const event = e;
10945
11027
  if (event.online) {
10946
11028
  const callsToReWatch = this.writeableStateStore.calls
@@ -10958,9 +11040,8 @@ class StreamVideoClient {
10958
11040
  });
10959
11041
  }
10960
11042
  }
10961
- });
10962
- // FIXME: OL: unregister the event listeners.
10963
- this.on('call.created', (event) => {
11043
+ }));
11044
+ this.eventHandlersToUnregister.push(this.on('call.created', (event) => {
10964
11045
  if (event.type !== 'call.created')
10965
11046
  return;
10966
11047
  const { call, members } = event;
@@ -10974,11 +11055,36 @@ class StreamVideoClient {
10974
11055
  id: call.id,
10975
11056
  metadata: call,
10976
11057
  members,
10977
- ringing: false,
10978
11058
  clientStore: this.writeableStateStore,
10979
11059
  }));
10980
- });
10981
- this.writeableStateStore.setConnectedUser(user);
11060
+ }));
11061
+ this.eventHandlersToUnregister.push(this.on('call.ring', (event) => __awaiter(this, void 0, void 0, function* () {
11062
+ if (event.type !== 'call.ring')
11063
+ return;
11064
+ const { call, members } = event;
11065
+ if (user.id === call.created_by.id) {
11066
+ console.warn('Received `call.ring` sent by the current user');
11067
+ return;
11068
+ }
11069
+ // The call might already be tracked by the client,
11070
+ // if `call.created` was received before `call.ring`.
11071
+ // In that case, we just reuse the already tracked call.
11072
+ let theCall = this.writeableStateStore.findCall(call.type, call.id);
11073
+ if (!theCall) {
11074
+ // otherwise, we create a new call
11075
+ theCall = new Call({
11076
+ streamClient: this.streamClient,
11077
+ type: call.type,
11078
+ id: call.id,
11079
+ members,
11080
+ clientStore: this.writeableStateStore,
11081
+ ringing: true,
11082
+ });
11083
+ }
11084
+ // we fetch the latest metadata for the call from the server
11085
+ yield theCall.get({ ring: true });
11086
+ this.writeableStateStore.registerCall(theCall);
11087
+ })));
10982
11088
  return connectUserResponse;
10983
11089
  });
10984
11090
  /**
@@ -11001,6 +11107,8 @@ class StreamVideoClient {
11001
11107
  */
11002
11108
  this.disconnectUser = (timeout) => __awaiter(this, void 0, void 0, function* () {
11003
11109
  yield this.streamClient.disconnectUser(timeout);
11110
+ this.eventHandlersToUnregister.forEach((unregister) => unregister());
11111
+ this.eventHandlersToUnregister = [];
11004
11112
  this.writeableStateStore.setConnectedUser(undefined);
11005
11113
  });
11006
11114
  /**