Skip to content

Commit 69db0c4

Browse files
committed
Merge branch 'main' into base-profiles
2 parents 52f77f6 + 9da68db commit 69db0c4

File tree

84 files changed

+2148
-983
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+2148
-983
lines changed

packages/client/CHANGELOG.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,41 @@
22

33
This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
44

5+
## [1.11.2](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.11.1...@stream-io/video-client-1.11.2) (2024-11-14)
6+
7+
8+
### Bug Fixes
9+
10+
* fully reset token manager on user disconnect ([#1578](https://github.com/GetStream/stream-video-js/issues/1578)) ([6751abc](https://github.com/GetStream/stream-video-js/commit/6751abc0507085bd7c9f3f803f4c5929e0598bea)), closes [#1573](https://github.com/GetStream/stream-video-js/issues/1573)
11+
12+
## [1.11.1](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.11.0...@stream-io/video-client-1.11.1) (2024-11-14)
13+
14+
15+
### Bug Fixes
16+
17+
* reject was not called on timeout, decline and cancel scenarios ([#1576](https://github.com/GetStream/stream-video-js/issues/1576)) ([8be76a4](https://github.com/GetStream/stream-video-js/commit/8be76a447729aeba7f5c68f8a9bb85b4738cb76d))
18+
19+
## [1.11.0](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.10.5...@stream-io/video-client-1.11.0) (2024-11-13)
20+
21+
22+
### Features
23+
24+
* Connection timing ([#1574](https://github.com/GetStream/stream-video-js/issues/1574)) ([ce1dc9a](https://github.com/GetStream/stream-video-js/commit/ce1dc9a01fc5b0e60e3dac6653c27e99fd4b3ecb))
25+
26+
## [1.10.5](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.10.4...@stream-io/video-client-1.10.5) (2024-11-07)
27+
28+
29+
### Bug Fixes
30+
31+
* ignore maxSimulcastLayers override for SVC codecs ([#1564](https://github.com/GetStream/stream-video-js/issues/1564)) ([48f8abe](https://github.com/GetStream/stream-video-js/commit/48f8abe5fd5b48c367a04696febd582573def828))
32+
33+
## [1.10.4](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.10.3...@stream-io/video-client-1.10.4) (2024-11-07)
34+
35+
36+
### Bug Fixes
37+
38+
* max simulcast layers preference ([#1560](https://github.com/GetStream/stream-video-js/issues/1560)) ([2b0bf28](https://github.com/GetStream/stream-video-js/commit/2b0bf2824dce41c2709e361e0521cf85e1b2fd16))
39+
540
## [1.10.3](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.10.2...@stream-io/video-client-1.10.3) (2024-11-05)
641

742

packages/client/docusaurus/docs/javascript/02-guides/03-call-and-participant-state.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ const subscription = call.state.participants$.subscribe((participants) => {
151151
subscription.unsubscribe();
152152
```
153153

154+
In a call with many participants, the value of the `participants$` call state observable is truncated to 250 participants. The participants who are publishing video, audio, or screen sharing have priority over the other participants in the list. This means, for example, that in a livestream with one host and many viewers, the host is guaranteed to be in the list.
155+
154156
## Client state
155157

156158
The client state can be accessed by `client.state`.

packages/client/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@stream-io/video-client",
3-
"version": "1.10.3",
3+
"version": "1.11.2",
44
"packageManager": "[email protected]",
55
"main": "dist/index.cjs.js",
66
"module": "dist/index.es.js",

packages/client/src/Call.ts

Lines changed: 57 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -516,20 +516,15 @@ export class Call {
516516
await waitUntilCallJoined();
517517
}
518518

519-
if (reject && this.ringing) {
520-
// I'm the one who started the call, so I should cancel it.
521-
const hasOtherParticipants = this.state.remoteParticipants.length > 0;
522-
if (
523-
this.isCreatedByMe &&
524-
!hasOtherParticipants &&
525-
callingState === CallingState.RINGING
526-
) {
527-
// Signals other users that I have cancelled my call to them
528-
// before they accepted it.
529-
await this.reject();
530-
} else if (callingState === CallingState.RINGING) {
531-
// Signals other users that I have rejected the incoming call.
532-
await this.reject();
519+
if (callingState === CallingState.RINGING) {
520+
if (reject) {
521+
await this.reject(reason);
522+
} else {
523+
const hasOtherParticipants = this.state.remoteParticipants.length > 0;
524+
if (this.isCreatedByMe && !hasOtherParticipants) {
525+
// I'm the one who started the call, so I should cancel it when there are no other participants.
526+
await this.reject('cancel');
527+
}
533528
}
534529
}
535530

@@ -725,6 +720,7 @@ export class Call {
725720
* @returns a promise which resolves once the call join-flow has finished.
726721
*/
727722
join = async (data?: JoinCallData): Promise<void> => {
723+
const connectStartTime = Date.now();
728724
await this.setup();
729725
const callingState = this.state.callingState;
730726
if ([CallingState.JOINED, CallingState.JOINING].includes(callingState)) {
@@ -793,11 +789,11 @@ export class Call {
793789
: undefined;
794790
const { callState, fastReconnectDeadlineSeconds } = await sfuClient.join({
795791
subscriberSdp: receivingCapabilitiesSdp,
792+
publisherSdp: '',
796793
clientDetails,
797794
fastReconnect: performingFastReconnect,
798795
reconnectDetails,
799796
});
800-
801797
this.fastReconnectDeadlineSeconds = fastReconnectDeadlineSeconds;
802798
if (callState) {
803799
this.state.updateFromSfuCallState(
@@ -831,6 +827,16 @@ export class Call {
831827
});
832828
}
833829

830+
// make sure we only track connection timing if we are not calling this method as part of a reconnection flow
831+
if (!performingRejoin && !performingFastReconnect && !performingMigration) {
832+
this.sfuStatsReporter?.sendTelemetryData({
833+
data: {
834+
oneofKind: 'connectionTimeSeconds',
835+
connectionTimeSeconds: (Date.now() - connectStartTime) / 1000,
836+
},
837+
});
838+
}
839+
834840
if (performingRejoin) {
835841
const strategy = WebsocketReconnectStrategy[this.reconnectStrategy];
836842
await previousSfuClient?.leaveAndClose(
@@ -1130,28 +1136,49 @@ export class Call {
11301136
* @internal
11311137
*/
11321138
private reconnectFast = async () => {
1139+
let reconnectStartTime = Date.now();
11331140
this.reconnectStrategy = WebsocketReconnectStrategy.FAST;
11341141
this.state.setCallingState(CallingState.RECONNECTING);
1135-
return this.join(this.joinCallData);
1142+
await this.join(this.joinCallData);
1143+
this.sfuStatsReporter?.sendTelemetryData({
1144+
data: {
1145+
oneofKind: 'reconnection',
1146+
reconnection: {
1147+
timeSeconds: (Date.now() - reconnectStartTime) / 1000,
1148+
strategy: WebsocketReconnectStrategy.FAST,
1149+
},
1150+
},
1151+
});
11361152
};
11371153

11381154
/**
11391155
* Initiates the reconnection flow with the "rejoin" strategy.
11401156
* @internal
11411157
*/
11421158
private reconnectRejoin = async () => {
1159+
let reconnectStartTime = Date.now();
11431160
this.reconnectStrategy = WebsocketReconnectStrategy.REJOIN;
11441161
this.state.setCallingState(CallingState.RECONNECTING);
11451162
await this.join(this.joinCallData);
11461163
await this.restorePublishedTracks();
11471164
this.restoreSubscribedTracks();
1165+
this.sfuStatsReporter?.sendTelemetryData({
1166+
data: {
1167+
oneofKind: 'reconnection',
1168+
reconnection: {
1169+
timeSeconds: (Date.now() - reconnectStartTime) / 1000,
1170+
strategy: WebsocketReconnectStrategy.REJOIN,
1171+
},
1172+
},
1173+
});
11481174
};
11491175

11501176
/**
11511177
* Initiates the reconnection flow with the "migrate" strategy.
11521178
* @internal
11531179
*/
11541180
private reconnectMigrate = async () => {
1181+
let reconnectStartTime = Date.now();
11551182
const currentSfuClient = this.sfuClient;
11561183
if (!currentSfuClient) {
11571184
throw new Error('Cannot migrate without an active SFU client');
@@ -1196,6 +1223,15 @@ export class Call {
11961223
// and close the previous SFU client, without specifying close code
11971224
currentSfuClient.close();
11981225
}
1226+
this.sfuStatsReporter?.sendTelemetryData({
1227+
data: {
1228+
oneofKind: 'reconnection',
1229+
reconnection: {
1230+
timeSeconds: (Date.now() - reconnectStartTime) / 1000,
1231+
strategy: WebsocketReconnectStrategy.MIGRATE,
1232+
},
1233+
},
1234+
});
11991235
};
12001236

12011237
/**
@@ -1919,13 +1955,16 @@ export class Call {
19191955
// ignore if the call is not ringing
19201956
if (this.state.callingState !== CallingState.RINGING) return;
19211957

1922-
const timeoutInMs = settings.ring.auto_cancel_timeout_ms;
1958+
const timeoutInMs = this.isCreatedByMe
1959+
? settings.ring.auto_cancel_timeout_ms
1960+
: settings.ring.incoming_call_timeout_ms;
1961+
19231962
// 0 means no auto-drop
19241963
if (timeoutInMs <= 0) return;
19251964

19261965
clearTimeout(this.dropTimeout);
19271966
this.dropTimeout = setTimeout(() => {
1928-
this.leave({ reason: 'ring: timeout' }).catch((err) => {
1967+
this.leave({ reject: true, reason: 'timeout' }).catch((err) => {
19291968
this.logger('error', 'Failed to drop call', err);
19301969
});
19311970
}, timeoutInMs);

packages/client/src/__tests__/StreamVideoClient.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,15 @@ describe('StreamVideoClient', () => {
100100
expect(response.calls).toBeDefined();
101101
});
102102

103+
it('should clear token on disconnect', async () => {
104+
const user = { id: 'jane' };
105+
const tp = vi.fn(tokenProvider(user.id));
106+
await client.connectUser(user, tp);
107+
await client.disconnectUser();
108+
await client.connectUser({ type: 'anonymous' });
109+
expect(tp).toBeCalledTimes(1);
110+
});
111+
103112
afterEach(() => {
104113
client.disconnectUser();
105114
});

packages/client/src/coordinator/connection/token_manager.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ export class TokenManager {
6363
*/
6464
reset = () => {
6565
this.token = undefined;
66+
this.tokenProvider = undefined;
67+
this.type = 'static';
6668
this.user = undefined;
6769
this.loadTokenPromise = null;
6870
};

packages/client/src/gen/google/protobuf/struct.ts

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,13 @@
3333
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3434
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3535
//
36-
import type {
37-
JsonObject,
38-
JsonReadOptions,
39-
JsonValue,
40-
JsonWriteOptions,
41-
} from '@protobuf-ts/runtime';
42-
import {
43-
isJsonObject,
44-
MessageType,
45-
typeofJsonValue,
46-
} from '@protobuf-ts/runtime';
47-
36+
import { isJsonObject } from '@protobuf-ts/runtime';
37+
import { typeofJsonValue } from '@protobuf-ts/runtime';
38+
import type { JsonValue } from '@protobuf-ts/runtime';
39+
import type { JsonReadOptions } from '@protobuf-ts/runtime';
40+
import type { JsonWriteOptions } from '@protobuf-ts/runtime';
41+
import type { JsonObject } from '@protobuf-ts/runtime';
42+
import { MessageType } from '@protobuf-ts/runtime';
4843
/**
4944
* `Struct` represents a structured data value, consisting of fields
5045
* which map to dynamically typed values. In some languages, `Struct`

packages/client/src/gen/google/protobuf/timestamp.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,12 @@
3333
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3434
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3535
//
36-
import type {
37-
JsonReadOptions,
38-
JsonValue,
39-
JsonWriteOptions,
40-
} from '@protobuf-ts/runtime';
41-
import { MessageType, PbLong, typeofJsonValue } from '@protobuf-ts/runtime';
42-
36+
import { typeofJsonValue } from '@protobuf-ts/runtime';
37+
import type { JsonValue } from '@protobuf-ts/runtime';
38+
import type { JsonReadOptions } from '@protobuf-ts/runtime';
39+
import type { JsonWriteOptions } from '@protobuf-ts/runtime';
40+
import { PbLong } from '@protobuf-ts/runtime';
41+
import { MessageType } from '@protobuf-ts/runtime';
4342
/**
4443
* A Timestamp represents a point in time independent of any time zone or local
4544
* calendar, encoded as a count of seconds and fractions of seconds at

0 commit comments

Comments
 (0)