Skip to content

Commit

Permalink
Merge branch 'main' into base-profiles
Browse files Browse the repository at this point in the history
  • Loading branch information
oliverlaz committed Nov 18, 2024
2 parents 52f77f6 + 9da68db commit 69db0c4
Show file tree
Hide file tree
Showing 84 changed files with 2,148 additions and 983 deletions.
35 changes: 35 additions & 0 deletions packages/client/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,41 @@

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

## [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)


### Bug Fixes

* 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)

## [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)


### Bug Fixes

* 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))

## [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)


### Features

* Connection timing ([#1574](https://github.com/GetStream/stream-video-js/issues/1574)) ([ce1dc9a](https://github.com/GetStream/stream-video-js/commit/ce1dc9a01fc5b0e60e3dac6653c27e99fd4b3ecb))

## [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)


### Bug Fixes

* 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))

## [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)


### Bug Fixes

* max simulcast layers preference ([#1560](https://github.com/GetStream/stream-video-js/issues/1560)) ([2b0bf28](https://github.com/GetStream/stream-video-js/commit/2b0bf2824dce41c2709e361e0521cf85e1b2fd16))

## [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)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ const subscription = call.state.participants$.subscribe((participants) => {
subscription.unsubscribe();
```

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.

## Client state

The client state can be accessed by `client.state`.
Expand Down
2 changes: 1 addition & 1 deletion packages/client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@stream-io/video-client",
"version": "1.10.3",
"version": "1.11.2",
"packageManager": "[email protected]",
"main": "dist/index.cjs.js",
"module": "dist/index.es.js",
Expand Down
75 changes: 57 additions & 18 deletions packages/client/src/Call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -516,20 +516,15 @@ export class Call {
await waitUntilCallJoined();
}

if (reject && this.ringing) {
// I'm the one who started the call, so I should cancel it.
const hasOtherParticipants = this.state.remoteParticipants.length > 0;
if (
this.isCreatedByMe &&
!hasOtherParticipants &&
callingState === CallingState.RINGING
) {
// Signals other users that I have cancelled my call to them
// before they accepted it.
await this.reject();
} else if (callingState === CallingState.RINGING) {
// Signals other users that I have rejected the incoming call.
await this.reject();
if (callingState === CallingState.RINGING) {
if (reject) {
await this.reject(reason);
} else {
const hasOtherParticipants = this.state.remoteParticipants.length > 0;
if (this.isCreatedByMe && !hasOtherParticipants) {
// I'm the one who started the call, so I should cancel it when there are no other participants.
await this.reject('cancel');
}
}
}

Expand Down Expand Up @@ -725,6 +720,7 @@ export class Call {
* @returns a promise which resolves once the call join-flow has finished.
*/
join = async (data?: JoinCallData): Promise<void> => {
const connectStartTime = Date.now();
await this.setup();
const callingState = this.state.callingState;
if ([CallingState.JOINED, CallingState.JOINING].includes(callingState)) {
Expand Down Expand Up @@ -793,11 +789,11 @@ export class Call {
: undefined;
const { callState, fastReconnectDeadlineSeconds } = await sfuClient.join({
subscriberSdp: receivingCapabilitiesSdp,
publisherSdp: '',
clientDetails,
fastReconnect: performingFastReconnect,
reconnectDetails,
});

this.fastReconnectDeadlineSeconds = fastReconnectDeadlineSeconds;
if (callState) {
this.state.updateFromSfuCallState(
Expand Down Expand Up @@ -831,6 +827,16 @@ export class Call {
});
}

// make sure we only track connection timing if we are not calling this method as part of a reconnection flow
if (!performingRejoin && !performingFastReconnect && !performingMigration) {
this.sfuStatsReporter?.sendTelemetryData({
data: {
oneofKind: 'connectionTimeSeconds',
connectionTimeSeconds: (Date.now() - connectStartTime) / 1000,
},
});
}

if (performingRejoin) {
const strategy = WebsocketReconnectStrategy[this.reconnectStrategy];
await previousSfuClient?.leaveAndClose(
Expand Down Expand Up @@ -1130,28 +1136,49 @@ export class Call {
* @internal
*/
private reconnectFast = async () => {
let reconnectStartTime = Date.now();
this.reconnectStrategy = WebsocketReconnectStrategy.FAST;
this.state.setCallingState(CallingState.RECONNECTING);
return this.join(this.joinCallData);
await this.join(this.joinCallData);
this.sfuStatsReporter?.sendTelemetryData({
data: {
oneofKind: 'reconnection',
reconnection: {
timeSeconds: (Date.now() - reconnectStartTime) / 1000,
strategy: WebsocketReconnectStrategy.FAST,
},
},
});
};

/**
* Initiates the reconnection flow with the "rejoin" strategy.
* @internal
*/
private reconnectRejoin = async () => {
let reconnectStartTime = Date.now();
this.reconnectStrategy = WebsocketReconnectStrategy.REJOIN;
this.state.setCallingState(CallingState.RECONNECTING);
await this.join(this.joinCallData);
await this.restorePublishedTracks();
this.restoreSubscribedTracks();
this.sfuStatsReporter?.sendTelemetryData({
data: {
oneofKind: 'reconnection',
reconnection: {
timeSeconds: (Date.now() - reconnectStartTime) / 1000,
strategy: WebsocketReconnectStrategy.REJOIN,
},
},
});
};

/**
* Initiates the reconnection flow with the "migrate" strategy.
* @internal
*/
private reconnectMigrate = async () => {
let reconnectStartTime = Date.now();
const currentSfuClient = this.sfuClient;
if (!currentSfuClient) {
throw new Error('Cannot migrate without an active SFU client');
Expand Down Expand Up @@ -1196,6 +1223,15 @@ export class Call {
// and close the previous SFU client, without specifying close code
currentSfuClient.close();
}
this.sfuStatsReporter?.sendTelemetryData({
data: {
oneofKind: 'reconnection',
reconnection: {
timeSeconds: (Date.now() - reconnectStartTime) / 1000,
strategy: WebsocketReconnectStrategy.MIGRATE,
},
},
});
};

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

const timeoutInMs = settings.ring.auto_cancel_timeout_ms;
const timeoutInMs = this.isCreatedByMe
? settings.ring.auto_cancel_timeout_ms
: settings.ring.incoming_call_timeout_ms;

// 0 means no auto-drop
if (timeoutInMs <= 0) return;

clearTimeout(this.dropTimeout);
this.dropTimeout = setTimeout(() => {
this.leave({ reason: 'ring: timeout' }).catch((err) => {
this.leave({ reject: true, reason: 'timeout' }).catch((err) => {
this.logger('error', 'Failed to drop call', err);
});
}, timeoutInMs);
Expand Down
9 changes: 9 additions & 0 deletions packages/client/src/__tests__/StreamVideoClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,15 @@ describe('StreamVideoClient', () => {
expect(response.calls).toBeDefined();
});

it('should clear token on disconnect', async () => {
const user = { id: 'jane' };
const tp = vi.fn(tokenProvider(user.id));
await client.connectUser(user, tp);
await client.disconnectUser();
await client.connectUser({ type: 'anonymous' });
expect(tp).toBeCalledTimes(1);
});

afterEach(() => {
client.disconnectUser();
});
Expand Down
2 changes: 2 additions & 0 deletions packages/client/src/coordinator/connection/token_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ export class TokenManager {
*/
reset = () => {
this.token = undefined;
this.tokenProvider = undefined;
this.type = 'static';
this.user = undefined;
this.loadTokenPromise = null;
};
Expand Down
19 changes: 7 additions & 12 deletions packages/client/src/gen/google/protobuf/struct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,13 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
import type {
JsonObject,
JsonReadOptions,
JsonValue,
JsonWriteOptions,
} from '@protobuf-ts/runtime';
import {
isJsonObject,
MessageType,
typeofJsonValue,
} from '@protobuf-ts/runtime';

import { isJsonObject } from '@protobuf-ts/runtime';
import { typeofJsonValue } from '@protobuf-ts/runtime';
import type { JsonValue } from '@protobuf-ts/runtime';
import type { JsonReadOptions } from '@protobuf-ts/runtime';
import type { JsonWriteOptions } from '@protobuf-ts/runtime';
import type { JsonObject } from '@protobuf-ts/runtime';
import { MessageType } from '@protobuf-ts/runtime';
/**
* `Struct` represents a structured data value, consisting of fields
* which map to dynamically typed values. In some languages, `Struct`
Expand Down
13 changes: 6 additions & 7 deletions packages/client/src/gen/google/protobuf/timestamp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,12 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
import type {
JsonReadOptions,
JsonValue,
JsonWriteOptions,
} from '@protobuf-ts/runtime';
import { MessageType, PbLong, typeofJsonValue } from '@protobuf-ts/runtime';

import { typeofJsonValue } from '@protobuf-ts/runtime';
import type { JsonValue } from '@protobuf-ts/runtime';
import type { JsonReadOptions } from '@protobuf-ts/runtime';
import type { JsonWriteOptions } from '@protobuf-ts/runtime';
import { PbLong } from '@protobuf-ts/runtime';
import { MessageType } from '@protobuf-ts/runtime';
/**
* A Timestamp represents a point in time independent of any time zone or local
* calendar, encoded as a count of seconds and fractions of seconds at
Expand Down
Loading

0 comments on commit 69db0c4

Please sign in to comment.