@stream-io/video-client 0.0.7 → 0.0.9

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.
@@ -30,6 +30,12 @@ export declare class Call {
30
30
  * The state of this call.
31
31
  */
32
32
  readonly state: CallState;
33
+ private rejoinPromise;
34
+ /**
35
+ * A promise that exposes the reconnection logic
36
+ * The use-case is for the react-native platform where online/offline events are not available in the window
37
+ */
38
+ get rejoin(): (() => Promise<void>) | undefined;
33
39
  /**
34
40
  * Flag indicating whether this call is "watched" and receives
35
41
  * updates from the backend.
@@ -41,6 +41,12 @@ export declare class Publisher {
41
41
  * @param trackType the track type to unpublish.
42
42
  */
43
43
  unpublishStream: (trackType: TrackType) => Promise<void>;
44
+ /**
45
+ * Returns true if the given track type is currently being published to the SFU.
46
+ *
47
+ * @param trackType the track type to check.
48
+ */
49
+ isPublishing: (trackType: TrackType) => boolean;
44
50
  private notifyTrackMuteStateChanged;
45
51
  /**
46
52
  * Stops publishing all tracks and stop all tracks.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stream-io/video-client",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "packageManager": "yarn@3.2.4",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.es.js",
package/src/Call.ts CHANGED
@@ -135,6 +135,16 @@ export class Call {
135
135
  */
136
136
  readonly state = new CallState();
137
137
 
138
+ private rejoinPromise: (() => Promise<void>) | undefined;
139
+
140
+ /**
141
+ * A promise that exposes the reconnection logic
142
+ * The use-case is for the react-native platform where online/offline events are not available in the window
143
+ */
144
+ get rejoin(): (() => Promise<void>) | undefined {
145
+ return this.rejoinPromise;
146
+ }
147
+
138
148
  /**
139
149
  * Flag indicating whether this call is "watched" and receives
140
150
  * updates from the backend.
@@ -254,22 +264,26 @@ export class Call {
254
264
  // update the permission context.
255
265
  this.permissionsContext.setPermissions(ownCapabilities);
256
266
 
267
+ if (!this.publisher) return;
268
+
257
269
  // check if the user still has publishing permissions and stop publishing if not.
258
270
  const permissionToTrackType = {
259
271
  [OwnCapability.SEND_AUDIO]: TrackType.AUDIO,
260
272
  [OwnCapability.SEND_VIDEO]: TrackType.VIDEO,
261
273
  [OwnCapability.SCREENSHARE]: TrackType.SCREEN_SHARE,
262
274
  };
263
- Object.entries(permissionToTrackType).forEach(([permission, type]) => {
275
+ for (const [permission, trackType] of Object.entries(
276
+ permissionToTrackType,
277
+ )) {
264
278
  const hasPermission = this.permissionsContext.hasPermission(
265
279
  permission as OwnCapability,
266
280
  );
267
- if (!hasPermission) {
268
- this.stopPublish(type).catch((err) => {
269
- console.error('Error stopping publish', type, err);
281
+ if (!hasPermission && this.publisher.isPublishing(trackType)) {
282
+ this.stopPublish(trackType).catch((err) => {
283
+ console.error('Error stopping publish', trackType, err);
270
284
  });
271
285
  }
272
- });
286
+ }
273
287
  }),
274
288
 
275
289
  // handles the case when the user is blocked by the call owner.
@@ -370,6 +384,7 @@ export class Call {
370
384
  if (callingState === CallingState.LEFT) {
371
385
  throw new Error('Cannot leave call that has already been left.');
372
386
  }
387
+ this.rejoinPromise = undefined;
373
388
 
374
389
  if (this.ringing) {
375
390
  // I'm the one who started the call, so I should cancel it.
@@ -642,7 +657,7 @@ export class Call {
642
657
  await sleep(retryInterval(this.reconnectAttempts));
643
658
  await this.join(data);
644
659
  console.log(`Rejoin: ${this.reconnectAttempts} successful!`);
645
- if (localParticipant) {
660
+ if (localParticipant && !isReactNative()) {
646
661
  const {
647
662
  audioStream,
648
663
  videoStream,
@@ -657,6 +672,8 @@ export class Call {
657
672
  console.log(`Rejoin: state restored ${this.reconnectAttempts}`);
658
673
  };
659
674
 
675
+ this.rejoinPromise = rejoin;
676
+
660
677
  // reconnect if the connection was closed unexpectedly. example:
661
678
  // - SFU crash or restart
662
679
  // - network change
@@ -667,6 +684,8 @@ export class Call {
667
684
  // do nothing if the connection was closed because of a policy violation
668
685
  // e.g., the user has been blocked by an admin or moderator
669
686
  if (e.code === KnownCodes.WS_POLICY_VIOLATION) return;
687
+ // do nothing for react-native as its handled by SDK
688
+ if (isReactNative()) return;
670
689
  if (this.reconnectAttempts < this.maxReconnectAttempts) {
671
690
  rejoin().catch(() => {
672
691
  console.log(
@@ -214,6 +214,20 @@ export class Publisher {
214
214
  }
215
215
  };
216
216
 
217
+ /**
218
+ * Returns true if the given track type is currently being published to the SFU.
219
+ *
220
+ * @param trackType the track type to check.
221
+ */
222
+ isPublishing = (trackType: TrackType): boolean => {
223
+ const transceiverForTrackType = this.transceiverRegistry[trackType];
224
+ if (transceiverForTrackType && transceiverForTrackType.sender) {
225
+ const sender = transceiverForTrackType.sender;
226
+ return !!sender.track && sender.track.readyState === 'live';
227
+ }
228
+ return false;
229
+ };
230
+
217
231
  private notifyTrackMuteStateChanged = async (
218
232
  mediaStream: MediaStream | undefined,
219
233
  track: MediaStreamTrack,
package/src/rtc/signal.ts CHANGED
@@ -9,15 +9,15 @@ export const createWebSocketSignalChannel = (opts: {
9
9
  ws.binaryType = 'arraybuffer'; // do we need this?
10
10
 
11
11
  ws.addEventListener('error', (e) => {
12
- console.error('Error', e);
12
+ console.log('Signaling WS channel error', e);
13
13
  });
14
14
 
15
15
  ws.addEventListener('close', (e) => {
16
- console.warn('Signalling channel is closed', e);
16
+ console.log('Signaling WS channel is closed', e);
17
17
  });
18
18
 
19
19
  ws.addEventListener('open', (e) => {
20
- console.log('Signalling channel is open', e);
20
+ console.log('Signaling WS channel is open', e);
21
21
  });
22
22
 
23
23
  if (onMessage) {