@stream-io/video-client 0.0.2-alpha.7 → 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/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
4
4
 
5
+ ## [0.0.2-alpha.8](https://github.com/GetStream/stream-video-js/compare/client0.0.2-alpha.7...client0.0.2-alpha.8) (2023-05-30)
6
+
7
+
8
+ ### Features
9
+
10
+ * integrate the new call ring flow ([#562](https://github.com/GetStream/stream-video-js/issues/562)) ([c407961](https://github.com/GetStream/stream-video-js/commit/c4079614cb962e098215c0061690d59c35882cd8))
11
+
12
+
13
+
5
14
  ## [0.0.2-alpha.7](https://github.com/GetStream/stream-video-js/compare/client0.0.2-alpha.6...client0.0.2-alpha.7) (2023-05-30)
6
15
 
7
16
 
@@ -7044,6 +7044,15 @@ class StreamVideoWriteableStateStore {
7044
7044
  this.unregisterCall = (call) => {
7045
7045
  return this.setCalls((calls) => calls.filter((c) => c !== call));
7046
7046
  };
7047
+ /**
7048
+ * Finds a {@link Call} object in the list of {@link Call} objects created/tracked by this client.
7049
+ *
7050
+ * @param type the type of call to find.
7051
+ * @param id the id of the call to find.
7052
+ */
7053
+ this.findCall = (type, id) => {
7054
+ return this.calls.find((c) => c.type === type && c.id === id);
7055
+ };
7047
7056
  this.connectedUserSubject.subscribe((user) => __awaiter(this, void 0, void 0, function* () {
7048
7057
  // leave all calls when the user disconnects.
7049
7058
  if (!user) {
@@ -7163,16 +7172,39 @@ const watchCallAccepted = (call) => {
7163
7172
  * Once the event is received, the call is left.
7164
7173
  */
7165
7174
  const watchCallRejected = (call) => {
7166
- let totalRejections = 0;
7167
7175
  return function onCallRejected(event) {
7168
7176
  return __awaiter(this, void 0, void 0, function* () {
7169
7177
  if (event.type !== 'call.rejected')
7170
7178
  return;
7171
- totalRejections++;
7172
- const { state } = call;
7173
- if (totalRejections >= state.members.length &&
7174
- state.callingState === CallingState.RINGING) {
7175
- yield call.leave();
7179
+ // We want to discard the event if it's from the current user
7180
+ if (event.user.id === call.currentUserId)
7181
+ return;
7182
+ const { call: eventCall } = event;
7183
+ const { session: callSession } = eventCall;
7184
+ if (!callSession) {
7185
+ console.log('No call session provided. Ignoring call.rejected event.');
7186
+ return;
7187
+ }
7188
+ const rejectedBy = callSession.rejected_by;
7189
+ const { members, callingState } = call.state;
7190
+ if (callingState !== CallingState.RINGING) {
7191
+ console.log('Call is not in ringing mode (it is either accepted or rejected already). Ignoring call.rejected event.');
7192
+ return;
7193
+ }
7194
+ if (call.isCreatedByMe) {
7195
+ const everyoneElseRejected = members
7196
+ .filter((m) => m.user_id !== call.currentUserId)
7197
+ .every((m) => rejectedBy[m.user_id]);
7198
+ if (everyoneElseRejected) {
7199
+ console.log('everyone rejected, leaving the call');
7200
+ yield call.leave();
7201
+ }
7202
+ }
7203
+ else {
7204
+ if (rejectedBy[eventCall.created_by.id]) {
7205
+ console.log('call creator rejected, leaving call');
7206
+ yield call.leave();
7207
+ }
7176
7208
  }
7177
7209
  });
7178
7210
  };
@@ -7643,6 +7675,13 @@ const watchUnblockedUser = (state) => (event) => {
7643
7675
  });
7644
7676
  };
7645
7677
 
7678
+ /**
7679
+ * Registers the default event handlers for a call during its lifecycle.
7680
+ *
7681
+ * @param call the call to register event handlers for.
7682
+ * @param state the call state.
7683
+ * @param dispatcher the dispatcher.
7684
+ */
7646
7685
  const registerEventHandlers = (call, state, dispatcher) => {
7647
7686
  const coordinatorEvents = {
7648
7687
  'call.blocked_user': watchBlockedUser(state),
@@ -7665,8 +7704,6 @@ const registerEventHandlers = (call, state, dispatcher) => {
7665
7704
  'call.session_participant_left': watchCallSessionParticipantLeft(state),
7666
7705
  'call.unblocked_user': watchUnblockedUser(state),
7667
7706
  '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
7707
  };
7671
7708
  const eventHandlers = [
7672
7709
  watchChangePublishQuality(dispatcher, call),
@@ -7692,6 +7729,11 @@ const registerEventHandlers = (call, state, dispatcher) => {
7692
7729
  eventHandlers.forEach((unsubscribe) => unsubscribe());
7693
7730
  };
7694
7731
  };
7732
+ /**
7733
+ * Registers event handlers for a call that is of ringing type.
7734
+ *
7735
+ * @param call the call to register event handlers for.
7736
+ */
7695
7737
  const registerRingingCallEventHandlers = (call) => {
7696
7738
  const coordinatorRingEvents = {
7697
7739
  'call.accepted': watchCallAccepted(call),
@@ -8298,13 +8340,11 @@ class Call {
8298
8340
  if (this.isCreatedByMe && !hasOtherParticipants) {
8299
8341
  // Signals other users that I have cancelled my call to them
8300
8342
  // before they accepted it.
8301
- // Causes the `call.ended` event to be emitted to all the call members.
8302
- yield this.endCall();
8343
+ yield this.reject();
8303
8344
  }
8304
8345
  else if (reject && callingState === CallingState.RINGING) {
8305
8346
  // 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' });
8347
+ yield this.reject();
8308
8348
  }
8309
8349
  }
8310
8350
  (_a = this.statsReporter) === null || _a === void 0 ? void 0 : _a.stop();
@@ -8336,9 +8376,16 @@ class Call {
8336
8376
  });
8337
8377
  /**
8338
8378
  * Loads the information about the call.
8379
+ *
8380
+ * @param params.ring if set to true, a `call.ring` event will be sent to the call members.
8381
+ * @param params.notify if set to true, a `call.notification` event will be sent to the call members.
8382
+ * @param params.members_limit the members limit.
8339
8383
  */
8340
8384
  this.get = (params) => __awaiter(this, void 0, void 0, function* () {
8341
8385
  const response = yield this.streamClient.get(this.streamClientBasePath, params);
8386
+ if ((params === null || params === void 0 ? void 0 : params.ring) && !this.ringing) {
8387
+ this.ringingSubject.next(true);
8388
+ }
8342
8389
  this.state.setMetadata(response.call);
8343
8390
  this.state.setMembers(response.members);
8344
8391
  if (this.streamClient._hasConnectionID()) {
@@ -8354,6 +8401,9 @@ class Call {
8354
8401
  */
8355
8402
  this.getOrCreate = (data) => __awaiter(this, void 0, void 0, function* () {
8356
8403
  const response = yield this.streamClient.post(this.streamClientBasePath, data);
8404
+ if ((data === null || data === void 0 ? void 0 : data.ring) && !this.ringing) {
8405
+ this.ringingSubject.next(true);
8406
+ }
8357
8407
  this.state.setMetadata(response.call);
8358
8408
  this.state.setMembers(response.members);
8359
8409
  if (this.streamClient._hasConnectionID()) {
@@ -8362,12 +8412,40 @@ class Call {
8362
8412
  }
8363
8413
  return response;
8364
8414
  });
8415
+ /**
8416
+ * A shortcut for {@link Call.get} with `ring` parameter set to `true`.
8417
+ * Will send a `call.ring` event to the call members.
8418
+ */
8365
8419
  this.ring = () => __awaiter(this, void 0, void 0, function* () {
8366
8420
  return yield this.get({ ring: true });
8367
8421
  });
8422
+ /**
8423
+ * A shortcut for {@link Call.get} with `notify` parameter set to `true`.
8424
+ * Will send a `call.notification` event to the call members.
8425
+ */
8368
8426
  this.notify = () => __awaiter(this, void 0, void 0, function* () {
8369
8427
  return yield this.get({ notify: true });
8370
8428
  });
8429
+ /**
8430
+ * Marks the incoming call as accepted.
8431
+ *
8432
+ * This method should be used only for "ringing" call flows.
8433
+ * {@link Call.join} invokes this method automatically for you when joining a call.
8434
+ * Unless you are implementing a custom "ringing" flow, you should not use this method.
8435
+ */
8436
+ this.accept = () => __awaiter(this, void 0, void 0, function* () {
8437
+ return this.streamClient.post(`${this.streamClientBasePath}/accept`);
8438
+ });
8439
+ /**
8440
+ * Marks the incoming call as rejected.
8441
+ *
8442
+ * This method should be used only for "ringing" call flows.
8443
+ * {@link Call.leave} invokes this method automatically for you when you leave or reject this call.
8444
+ * Unless you are implementing a custom "ringing" flow, you should not use this method.
8445
+ */
8446
+ this.reject = () => __awaiter(this, void 0, void 0, function* () {
8447
+ return this.streamClient.post(`${this.streamClientBasePath}/reject`);
8448
+ });
8371
8449
  /**
8372
8450
  * Will start to watch for call related WebSocket events and initiate a call session with the server.
8373
8451
  *
@@ -8380,6 +8458,13 @@ class Call {
8380
8458
  }
8381
8459
  const previousCallingState = this.state.callingState;
8382
8460
  this.state.setCallingState(CallingState.JOINING);
8461
+ if ((data === null || data === void 0 ? void 0 : data.ring) && !this.ringing) {
8462
+ this.ringingSubject.next(true);
8463
+ }
8464
+ if (this.ringing && !this.isCreatedByMe) {
8465
+ // signals other users that I have accepted the incoming call.
8466
+ yield this.accept();
8467
+ }
8383
8468
  let sfuServer;
8384
8469
  let sfuToken;
8385
8470
  let connectionConfig;
@@ -8576,14 +8661,6 @@ class Call {
8576
8661
  }
8577
8662
  }
8578
8663
  });
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
- return this.streamClient.post(`${this.streamClientBasePath}/members`, data);
8586
- });
8587
8664
  /**
8588
8665
  * Starts publishing the given video stream to the call.
8589
8666
  * The stream will be stopped if the user changes an input device, or if the user leaves the call.
@@ -9063,7 +9140,17 @@ class Call {
9063
9140
  this.queryMembers = (request) => {
9064
9141
  return this.streamClient.post('/call/members', Object.assign(Object.assign({}, request), { id: this.id, type: this.type }));
9065
9142
  };
9143
+ /**
9144
+ * Will update the call members.
9145
+ *
9146
+ * @param data the request data.
9147
+ */
9148
+ this.updateCallMembers = (data) => __awaiter(this, void 0, void 0, function* () {
9149
+ return this.streamClient.post(`${this.streamClientBasePath}/members`, data);
9150
+ });
9066
9151
  this.scheduleAutoDrop = () => {
9152
+ if (this.dropTimeout)
9153
+ clearTimeout(this.dropTimeout);
9067
9154
  const subscription = this.state.metadata$
9068
9155
  .pipe(pairwise(), tap(([prevMeta, currentMeta]) => {
9069
9156
  if (!(currentMeta && this.clientStore.connectedUser))
@@ -9075,8 +9162,8 @@ class Call {
9075
9162
  currentMeta.settings.ring.auto_cancel_timeout_ms,
9076
9163
  ]
9077
9164
  : [
9078
- prevMeta === null || prevMeta === void 0 ? void 0 : prevMeta.settings.ring.auto_reject_timeout_ms,
9079
- currentMeta.settings.ring.auto_reject_timeout_ms,
9165
+ prevMeta === null || prevMeta === void 0 ? void 0 : prevMeta.settings.ring.incoming_call_timeout_ms,
9166
+ currentMeta.settings.ring.incoming_call_timeout_ms,
9080
9167
  ];
9081
9168
  if (typeof timeoutMs === 'undefined' || timeoutMs === prevTimeoutMs)
9082
9169
  return;
@@ -9124,12 +9211,6 @@ class Call {
9124
9211
  this.sendEvent = (event) => __awaiter(this, void 0, void 0, function* () {
9125
9212
  return this.streamClient.post(`${this.streamClientBasePath}/event`, event);
9126
9213
  });
9127
- this.accept = () => __awaiter(this, void 0, void 0, function* () {
9128
- return this.streamClient.post(`${this.streamClientBasePath}/accept`);
9129
- });
9130
- this.reject = () => __awaiter(this, void 0, void 0, function* () {
9131
- return this.streamClient.post(`${this.streamClientBasePath}/reject`);
9132
- });
9133
9214
  this.type = type;
9134
9215
  this.id = id;
9135
9216
  this.cid = `${type}:${id}`;
@@ -10876,7 +10957,7 @@ class StreamClient {
10876
10957
  }
10877
10958
  getUserAgent() {
10878
10959
  return (this.userAgent ||
10879
- `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.2-alpha.6"}`);
10960
+ `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.2-alpha.7"}`);
10880
10961
  }
10881
10962
  setUserAgent(userAgent) {
10882
10963
  this.userAgent = userAgent;
@@ -10922,6 +11003,7 @@ class StreamVideoClient {
10922
11003
  * @param opts the options for the client.
10923
11004
  */
10924
11005
  constructor(apiKey, opts) {
11006
+ this.eventHandlersToUnregister = [];
10925
11007
  /**
10926
11008
  * Connects the given user to the client.
10927
11009
  * Only one user can connect at a time, if you want to change users, call `disconnectUser` before connecting a new user.
@@ -10934,8 +11016,8 @@ class StreamVideoClient {
10934
11016
  const connectUserResponse = yield this.streamClient.connectUser(
10935
11017
  // @ts-expect-error
10936
11018
  user, tokenOrProvider);
10937
- // FIXME OL: unregister the event listeners.
10938
- this.on('connection.changed', (e) => {
11019
+ this.writeableStateStore.setConnectedUser(user);
11020
+ this.eventHandlersToUnregister.push(this.on('connection.changed', (e) => {
10939
11021
  const event = e;
10940
11022
  if (event.online) {
10941
11023
  const callsToReWatch = this.writeableStateStore.calls
@@ -10953,9 +11035,8 @@ class StreamVideoClient {
10953
11035
  });
10954
11036
  }
10955
11037
  }
10956
- });
10957
- // FIXME: OL: unregister the event listeners.
10958
- this.on('call.created', (event) => {
11038
+ }));
11039
+ this.eventHandlersToUnregister.push(this.on('call.created', (event) => {
10959
11040
  if (event.type !== 'call.created')
10960
11041
  return;
10961
11042
  const { call, members } = event;
@@ -10969,11 +11050,36 @@ class StreamVideoClient {
10969
11050
  id: call.id,
10970
11051
  metadata: call,
10971
11052
  members,
10972
- ringing: false,
10973
11053
  clientStore: this.writeableStateStore,
10974
11054
  }));
10975
- });
10976
- this.writeableStateStore.setConnectedUser(user);
11055
+ }));
11056
+ this.eventHandlersToUnregister.push(this.on('call.ring', (event) => __awaiter(this, void 0, void 0, function* () {
11057
+ if (event.type !== 'call.ring')
11058
+ return;
11059
+ const { call, members } = event;
11060
+ if (user.id === call.created_by.id) {
11061
+ console.warn('Received `call.ring` sent by the current user');
11062
+ return;
11063
+ }
11064
+ // The call might already be tracked by the client,
11065
+ // if `call.created` was received before `call.ring`.
11066
+ // In that case, we just reuse the already tracked call.
11067
+ let theCall = this.writeableStateStore.findCall(call.type, call.id);
11068
+ if (!theCall) {
11069
+ // otherwise, we create a new call
11070
+ theCall = new Call({
11071
+ streamClient: this.streamClient,
11072
+ type: call.type,
11073
+ id: call.id,
11074
+ members,
11075
+ clientStore: this.writeableStateStore,
11076
+ ringing: true,
11077
+ });
11078
+ }
11079
+ // we fetch the latest metadata for the call from the server
11080
+ yield theCall.get({ ring: true });
11081
+ this.writeableStateStore.registerCall(theCall);
11082
+ })));
10977
11083
  return connectUserResponse;
10978
11084
  });
10979
11085
  /**
@@ -10996,6 +11102,8 @@ class StreamVideoClient {
10996
11102
  */
10997
11103
  this.disconnectUser = (timeout) => __awaiter(this, void 0, void 0, function* () {
10998
11104
  yield this.streamClient.disconnectUser(timeout);
11105
+ this.eventHandlersToUnregister.forEach((unregister) => unregister());
11106
+ this.eventHandlersToUnregister = [];
10999
11107
  this.writeableStateStore.setConnectedUser(undefined);
11000
11108
  });
11001
11109
  /**