@stream-io/video-client 0.2.2 → 0.3.0
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 +18 -0
- package/dist/index.browser.es.js +325 -421
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +325 -421
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +325 -421
- package/dist/index.es.js.map +1 -1
- package/dist/src/Call.d.ts +8 -10
- package/dist/src/StreamVideoClient.d.ts +3 -1
- package/dist/src/events/call-permissions.d.ts +0 -5
- package/dist/src/events/call.d.ts +0 -6
- package/dist/src/events/index.d.ts +0 -6
- package/dist/src/gen/coordinator/index.d.ts +25 -0
- package/dist/src/rtc/Dispatcher.d.ts +2 -2
- package/dist/src/rtc/Publisher.d.ts +0 -1
- package/dist/src/store/CallState.d.ts +164 -89
- package/dist/src/types.d.ts +1 -7
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/Call.ts +37 -44
- package/src/StreamVideoClient.ts +14 -17
- package/src/events/__tests__/call-permissions.test.ts +1 -61
- package/src/events/__tests__/call.test.ts +5 -50
- package/src/events/call-permissions.ts +0 -14
- package/src/events/call.ts +5 -16
- package/src/events/callEventHandlers.ts +2 -57
- package/src/events/index.ts +0 -6
- package/src/gen/coordinator/index.ts +25 -0
- package/src/rtc/Dispatcher.ts +2 -2
- package/src/rtc/Publisher.ts +4 -6
- package/src/store/CallState.ts +475 -119
- package/src/store/__tests__/CallState.test.ts +447 -1
- package/src/types.ts +0 -8
- package/dist/src/events/__tests__/backstage.test.d.ts +0 -1
- package/dist/src/events/__tests__/members.test.d.ts +0 -1
- package/dist/src/events/__tests__/recording.test.d.ts +0 -1
- package/dist/src/events/__tests__/sessions.test.d.ts +0 -1
- package/dist/src/events/backstage.d.ts +0 -6
- package/dist/src/events/members.d.ts +0 -18
- package/dist/src/events/moderation.d.ts +0 -14
- package/dist/src/events/reactions.d.ts +0 -8
- package/dist/src/events/recording.d.ts +0 -18
- package/dist/src/events/sessions.d.ts +0 -26
- package/src/events/__tests__/backstage.test.ts +0 -15
- package/src/events/__tests__/members.test.ts +0 -135
- package/src/events/__tests__/recording.test.ts +0 -65
- package/src/events/__tests__/sessions.test.ts +0 -135
- package/src/events/backstage.ts +0 -15
- package/src/events/members.ts +0 -62
- package/src/events/moderation.ts +0 -35
- package/src/events/reactions.ts +0 -30
- package/src/events/recording.ts +0 -64
- package/src/events/sessions.ts +0 -102
package/src/Call.ts
CHANGED
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
GetCallResponse,
|
|
29
29
|
GetOrCreateCallRequest,
|
|
30
30
|
GetOrCreateCallResponse,
|
|
31
|
+
GoLiveRequest,
|
|
31
32
|
GoLiveResponse,
|
|
32
33
|
ListRecordingsResponse,
|
|
33
34
|
MuteUsersRequest,
|
|
@@ -104,6 +105,7 @@ import {
|
|
|
104
105
|
CallEventHandler,
|
|
105
106
|
CallEventTypes,
|
|
106
107
|
EventHandler,
|
|
108
|
+
EventTypes,
|
|
107
109
|
Logger,
|
|
108
110
|
StreamCallEvent,
|
|
109
111
|
} from './coordinator/connection/types';
|
|
@@ -199,7 +201,6 @@ export class Call {
|
|
|
199
201
|
type,
|
|
200
202
|
id,
|
|
201
203
|
streamClient,
|
|
202
|
-
metadata,
|
|
203
204
|
members,
|
|
204
205
|
ownCapabilities,
|
|
205
206
|
sortParticipantsBy,
|
|
@@ -224,13 +225,17 @@ export class Call {
|
|
|
224
225
|
this.state.setSortParticipantsBy(participantSorter);
|
|
225
226
|
}
|
|
226
227
|
|
|
227
|
-
this.state.setMetadata(metadata);
|
|
228
228
|
this.state.setMembers(members || []);
|
|
229
229
|
this.state.setOwnCapabilities(ownCapabilities || []);
|
|
230
230
|
this.state.setCallingState(
|
|
231
231
|
ringing ? CallingState.RINGING : CallingState.IDLE,
|
|
232
232
|
);
|
|
233
233
|
|
|
234
|
+
this.on('all', (event) => {
|
|
235
|
+
// update state with the latest event data
|
|
236
|
+
this.state.updateFromEvent(event);
|
|
237
|
+
});
|
|
238
|
+
|
|
234
239
|
this.leaveCallHooks.push(
|
|
235
240
|
registerEventHandlers(this, this.state, this.dispatcher),
|
|
236
241
|
);
|
|
@@ -249,10 +254,10 @@ export class Call {
|
|
|
249
254
|
|
|
250
255
|
private registerEffects() {
|
|
251
256
|
this.leaveCallHooks.push(
|
|
252
|
-
// handles updating the permissions context when the
|
|
253
|
-
createSubscription(this.state.
|
|
254
|
-
if (!
|
|
255
|
-
this.permissionsContext.setCallSettings(
|
|
257
|
+
// handles updating the permissions context when the settings change.
|
|
258
|
+
createSubscription(this.state.settings$, (settings) => {
|
|
259
|
+
if (!settings) return;
|
|
260
|
+
this.permissionsContext.setCallSettings(settings);
|
|
256
261
|
}),
|
|
257
262
|
|
|
258
263
|
// handle the case when the user permissions are modified.
|
|
@@ -283,13 +288,10 @@ export class Call {
|
|
|
283
288
|
}),
|
|
284
289
|
|
|
285
290
|
// handles the case when the user is blocked by the call owner.
|
|
286
|
-
createSubscription(this.state.
|
|
287
|
-
if (!
|
|
291
|
+
createSubscription(this.state.blockedUserIds$, async (blockedUserIds) => {
|
|
292
|
+
if (!blockedUserIds) return;
|
|
288
293
|
const currentUserId = this.currentUserId;
|
|
289
|
-
if (
|
|
290
|
-
currentUserId &&
|
|
291
|
-
metadata.blocked_user_ids.includes(currentUserId)
|
|
292
|
-
) {
|
|
294
|
+
if (currentUserId && blockedUserIds.includes(currentUserId)) {
|
|
293
295
|
this.logger('info', 'Leaving call because of being blocked');
|
|
294
296
|
await this.leave();
|
|
295
297
|
}
|
|
@@ -328,9 +330,9 @@ export class Call {
|
|
|
328
330
|
* @returns a function which can be called to unsubscribe from the given event(s)
|
|
329
331
|
*/
|
|
330
332
|
on(eventName: SfuEventKinds, fn: SfuEventListener): () => void;
|
|
331
|
-
on(eventName:
|
|
333
|
+
on(eventName: EventTypes, fn: CallEventHandler): () => void;
|
|
332
334
|
on(
|
|
333
|
-
eventName: SfuEventKinds |
|
|
335
|
+
eventName: SfuEventKinds | EventTypes,
|
|
334
336
|
fn: SfuEventListener | CallEventHandler,
|
|
335
337
|
) {
|
|
336
338
|
if (isSfuEvent(eventName)) {
|
|
@@ -419,13 +421,6 @@ export class Call {
|
|
|
419
421
|
this.state.setCallingState(CallingState.LEFT);
|
|
420
422
|
};
|
|
421
423
|
|
|
422
|
-
/**
|
|
423
|
-
* A getter for the call metadata.
|
|
424
|
-
*/
|
|
425
|
-
get data() {
|
|
426
|
-
return this.state.metadata;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
424
|
/**
|
|
430
425
|
* A flag indicating whether the call is "ringing" type of call.
|
|
431
426
|
*/
|
|
@@ -444,7 +439,7 @@ export class Call {
|
|
|
444
439
|
* A flag indicating whether the call was created by the current user.
|
|
445
440
|
*/
|
|
446
441
|
get isCreatedByMe() {
|
|
447
|
-
return this.state.
|
|
442
|
+
return this.state.createdBy?.id === this.currentUserId;
|
|
448
443
|
}
|
|
449
444
|
|
|
450
445
|
/**
|
|
@@ -468,7 +463,7 @@ export class Call {
|
|
|
468
463
|
this.ringingSubject.next(true);
|
|
469
464
|
}
|
|
470
465
|
|
|
471
|
-
this.state.
|
|
466
|
+
this.state.updateFromCallResponse(response.call);
|
|
472
467
|
this.state.setMembers(response.members);
|
|
473
468
|
this.state.setOwnCapabilities(response.own_capabilities);
|
|
474
469
|
|
|
@@ -495,7 +490,7 @@ export class Call {
|
|
|
495
490
|
this.ringingSubject.next(true);
|
|
496
491
|
}
|
|
497
492
|
|
|
498
|
-
this.state.
|
|
493
|
+
this.state.updateFromCallResponse(response.call);
|
|
499
494
|
this.state.setMembers(response.members);
|
|
500
495
|
this.state.setOwnCapabilities(response.own_capabilities);
|
|
501
496
|
|
|
@@ -597,7 +592,7 @@ export class Call {
|
|
|
597
592
|
let connectionConfig: RTCConfiguration | undefined;
|
|
598
593
|
try {
|
|
599
594
|
const call = await join(this.streamClient, this.type, this.id, data);
|
|
600
|
-
this.state.
|
|
595
|
+
this.state.updateFromCallResponse(call.metadata);
|
|
601
596
|
this.state.setMembers(call.members);
|
|
602
597
|
this.state.setOwnCapabilities(call.ownCapabilities);
|
|
603
598
|
connectionConfig = call.connectionConfig;
|
|
@@ -814,7 +809,7 @@ export class Call {
|
|
|
814
809
|
});
|
|
815
810
|
}
|
|
816
811
|
|
|
817
|
-
const audioSettings = this.
|
|
812
|
+
const audioSettings = this.state.settings?.audio;
|
|
818
813
|
const isDtxEnabled = !!audioSettings?.opus_dtx_enabled;
|
|
819
814
|
const isRedEnabled = !!audioSettings?.redundant_coding_enabled;
|
|
820
815
|
|
|
@@ -1461,11 +1456,14 @@ export class Call {
|
|
|
1461
1456
|
|
|
1462
1457
|
/**
|
|
1463
1458
|
* Starts the livestreaming of the call.
|
|
1459
|
+
*
|
|
1460
|
+
* @param data the request data.
|
|
1461
|
+
* @param params the request params.
|
|
1464
1462
|
*/
|
|
1465
|
-
goLive = async (params?: { notify?: boolean }) => {
|
|
1466
|
-
return this.streamClient.post<GoLiveResponse>(
|
|
1463
|
+
goLive = async (data: GoLiveRequest = {}, params?: { notify?: boolean }) => {
|
|
1464
|
+
return this.streamClient.post<GoLiveResponse, GoLiveRequest>(
|
|
1467
1465
|
`${this.streamClientBasePath}/go_live`,
|
|
1468
|
-
|
|
1466
|
+
data,
|
|
1469
1467
|
params,
|
|
1470
1468
|
);
|
|
1471
1469
|
};
|
|
@@ -1512,7 +1510,7 @@ export class Call {
|
|
|
1512
1510
|
>(`${this.streamClientBasePath}`, updates);
|
|
1513
1511
|
|
|
1514
1512
|
const { call, members, own_capabilities } = response;
|
|
1515
|
-
this.state.
|
|
1513
|
+
this.state.updateFromCallResponse(call);
|
|
1516
1514
|
this.state.setMembers(members);
|
|
1517
1515
|
this.state.setOwnCapabilities(own_capabilities);
|
|
1518
1516
|
|
|
@@ -1613,23 +1611,23 @@ export class Call {
|
|
|
1613
1611
|
|
|
1614
1612
|
private scheduleAutoDrop = () => {
|
|
1615
1613
|
if (this.dropTimeout) clearTimeout(this.dropTimeout);
|
|
1616
|
-
const subscription = this.state.
|
|
1614
|
+
const subscription = this.state.settings$
|
|
1617
1615
|
.pipe(
|
|
1618
1616
|
pairwise(),
|
|
1619
|
-
tap(([
|
|
1620
|
-
if (!
|
|
1617
|
+
tap(([prevSettings, currentSettings]) => {
|
|
1618
|
+
if (!currentSettings || !this.clientStore.connectedUser) return;
|
|
1621
1619
|
|
|
1622
1620
|
const isOutgoingCall =
|
|
1623
|
-
this.currentUserId ===
|
|
1621
|
+
this.currentUserId === this.state.createdBy?.id;
|
|
1624
1622
|
|
|
1625
1623
|
const [prevTimeoutMs, timeoutMs] = isOutgoingCall
|
|
1626
1624
|
? [
|
|
1627
|
-
|
|
1628
|
-
|
|
1625
|
+
prevSettings?.ring.auto_cancel_timeout_ms,
|
|
1626
|
+
currentSettings.ring.auto_cancel_timeout_ms,
|
|
1629
1627
|
]
|
|
1630
1628
|
: [
|
|
1631
|
-
|
|
1632
|
-
|
|
1629
|
+
prevSettings?.ring.incoming_call_timeout_ms,
|
|
1630
|
+
currentSettings.ring.incoming_call_timeout_ms,
|
|
1633
1631
|
];
|
|
1634
1632
|
if (
|
|
1635
1633
|
typeof timeoutMs === 'undefined' ||
|
|
@@ -1654,7 +1652,6 @@ export class Call {
|
|
|
1654
1652
|
|
|
1655
1653
|
/**
|
|
1656
1654
|
* Retrieves the list of recordings for the current call or call session.
|
|
1657
|
-
* Updates the call state with the returned array of CallRecording objects.
|
|
1658
1655
|
*
|
|
1659
1656
|
* If `callSessionId` is provided, it will return the recordings for that call session.
|
|
1660
1657
|
* Otherwise, all recordings for the current call will be returned.
|
|
@@ -1668,13 +1665,9 @@ export class Call {
|
|
|
1668
1665
|
if (callSessionId) {
|
|
1669
1666
|
endpoint = `${endpoint}/${callSessionId}`;
|
|
1670
1667
|
}
|
|
1671
|
-
|
|
1668
|
+
return this.streamClient.get<ListRecordingsResponse>(
|
|
1672
1669
|
`${endpoint}/recordings`,
|
|
1673
1670
|
);
|
|
1674
|
-
|
|
1675
|
-
this.state.setCallRecordingsList(response.recordings);
|
|
1676
|
-
|
|
1677
|
-
return response;
|
|
1678
1671
|
};
|
|
1679
1672
|
|
|
1680
1673
|
/**
|
package/src/StreamVideoClient.ts
CHANGED
|
@@ -217,16 +217,15 @@ export class StreamVideoClient {
|
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
this.logger('info', `New call created and registered: ${call.cid}`);
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
);
|
|
220
|
+
const newCall = new Call({
|
|
221
|
+
streamClient: this.streamClient,
|
|
222
|
+
type: call.type,
|
|
223
|
+
id: call.id,
|
|
224
|
+
members,
|
|
225
|
+
clientStore: this.writeableStateStore,
|
|
226
|
+
});
|
|
227
|
+
newCall.state.updateFromCallResponse(call);
|
|
228
|
+
this.writeableStateStore.registerCall(newCall);
|
|
230
229
|
}),
|
|
231
230
|
);
|
|
232
231
|
|
|
@@ -246,7 +245,6 @@ export class StreamVideoClient {
|
|
|
246
245
|
// if `call.created` was received before `call.ring`.
|
|
247
246
|
// In that case, we cleanup the already tracked call.
|
|
248
247
|
const prevCall = this.writeableStateStore.findCall(call.type, call.id);
|
|
249
|
-
const prevMetadata = prevCall?.state.metadata;
|
|
250
248
|
await prevCall?.leave();
|
|
251
249
|
// we create a new call
|
|
252
250
|
const theCall = new Call({
|
|
@@ -256,8 +254,8 @@ export class StreamVideoClient {
|
|
|
256
254
|
members,
|
|
257
255
|
clientStore: this.writeableStateStore,
|
|
258
256
|
ringing: true,
|
|
259
|
-
metadata: prevMetadata,
|
|
260
257
|
});
|
|
258
|
+
theCall.state.updateFromCallResponse(call);
|
|
261
259
|
// we fetch the latest metadata for the call from the server
|
|
262
260
|
await theCall.get();
|
|
263
261
|
this.writeableStateStore.registerCall(theCall);
|
|
@@ -357,12 +355,12 @@ export class StreamVideoClient {
|
|
|
357
355
|
streamClient: this.streamClient,
|
|
358
356
|
id: c.call.id,
|
|
359
357
|
type: c.call.type,
|
|
360
|
-
metadata: c.call,
|
|
361
358
|
members: c.members,
|
|
362
359
|
ownCapabilities: c.own_capabilities,
|
|
363
360
|
watching: data.watch,
|
|
364
361
|
clientStore: this.writeableStateStore,
|
|
365
362
|
});
|
|
363
|
+
call.state.updateFromCallResponse(c.call);
|
|
366
364
|
if (data.watch) {
|
|
367
365
|
this.writeableStateStore.registerCall(call);
|
|
368
366
|
}
|
|
@@ -374,10 +372,9 @@ export class StreamVideoClient {
|
|
|
374
372
|
};
|
|
375
373
|
};
|
|
376
374
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
375
|
+
/**
|
|
376
|
+
* Returns a list of available data centers available for hosting calls.
|
|
377
|
+
*/
|
|
381
378
|
edges = async () => {
|
|
382
379
|
return this.streamClient.get<GetEdgesResponse>(`/edges`);
|
|
383
380
|
};
|
|
@@ -1,69 +1,9 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
import { CallState } from '../../store';
|
|
3
|
-
import {
|
|
4
|
-
watchCallGrantsUpdated,
|
|
5
|
-
watchCallPermissionsUpdated,
|
|
6
|
-
} from '../call-permissions';
|
|
3
|
+
import { watchCallGrantsUpdated } from '../call-permissions';
|
|
7
4
|
import { OwnCapability } from '../../gen/coordinator';
|
|
8
|
-
import { ConnectionQuality } from '../../gen/video/sfu/models/models';
|
|
9
5
|
|
|
10
6
|
describe('Call Permission Events', () => {
|
|
11
|
-
it('handles call.permissions_updated', () => {
|
|
12
|
-
const state = new CallState();
|
|
13
|
-
state.setParticipants([
|
|
14
|
-
{
|
|
15
|
-
userId: 'test',
|
|
16
|
-
name: 'test',
|
|
17
|
-
sessionId: 'test',
|
|
18
|
-
isDominantSpeaker: false,
|
|
19
|
-
isSpeaking: false,
|
|
20
|
-
audioLevel: 0,
|
|
21
|
-
image: '',
|
|
22
|
-
publishedTracks: [],
|
|
23
|
-
connectionQuality: ConnectionQuality.EXCELLENT,
|
|
24
|
-
roles: [],
|
|
25
|
-
trackLookupPrefix: '',
|
|
26
|
-
isLocalParticipant: true,
|
|
27
|
-
},
|
|
28
|
-
]);
|
|
29
|
-
const handler = watchCallPermissionsUpdated(state);
|
|
30
|
-
handler({
|
|
31
|
-
type: 'call.permissions_updated',
|
|
32
|
-
created_at: '',
|
|
33
|
-
call_cid: 'development:12345',
|
|
34
|
-
own_capabilities: [OwnCapability.SEND_AUDIO, OwnCapability.SEND_VIDEO],
|
|
35
|
-
user: {
|
|
36
|
-
id: 'test',
|
|
37
|
-
created_at: '',
|
|
38
|
-
role: '',
|
|
39
|
-
updated_at: '',
|
|
40
|
-
custom: {},
|
|
41
|
-
teams: [],
|
|
42
|
-
},
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
expect(state.ownCapabilities).toEqual([
|
|
46
|
-
OwnCapability.SEND_AUDIO,
|
|
47
|
-
OwnCapability.SEND_VIDEO,
|
|
48
|
-
]);
|
|
49
|
-
|
|
50
|
-
handler({
|
|
51
|
-
type: 'call.permissions_updated',
|
|
52
|
-
created_at: '',
|
|
53
|
-
call_cid: 'development:12345',
|
|
54
|
-
own_capabilities: [OwnCapability.SEND_VIDEO],
|
|
55
|
-
user: {
|
|
56
|
-
id: 'test',
|
|
57
|
-
created_at: '',
|
|
58
|
-
role: '',
|
|
59
|
-
updated_at: '',
|
|
60
|
-
custom: {},
|
|
61
|
-
teams: [],
|
|
62
|
-
},
|
|
63
|
-
});
|
|
64
|
-
expect(state.ownCapabilities).toEqual([OwnCapability.SEND_VIDEO]);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
7
|
it('handles sfu.callGrantsUpdated', () => {
|
|
68
8
|
const state = new CallState();
|
|
69
9
|
const handler = watchCallGrantsUpdated(state);
|
|
@@ -1,60 +1,15 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
CallState,
|
|
5
|
-
StreamVideoWriteableStateStore,
|
|
6
|
-
} from '../../store';
|
|
7
|
-
import {
|
|
8
|
-
watchCallAccepted,
|
|
9
|
-
watchCallEnded,
|
|
10
|
-
watchCallRejected,
|
|
11
|
-
watchCallUpdated,
|
|
12
|
-
} from '../call';
|
|
2
|
+
import { CallingState, StreamVideoWriteableStateStore } from '../../store';
|
|
3
|
+
import { watchCallAccepted, watchCallEnded, watchCallRejected } from '../call';
|
|
13
4
|
import {
|
|
14
5
|
CallAcceptedEvent,
|
|
15
6
|
CallEndedEvent,
|
|
16
7
|
CallResponse,
|
|
17
|
-
CallUpdatedEvent,
|
|
18
8
|
} from '../../gen/coordinator';
|
|
19
9
|
import { Call } from '../../Call';
|
|
20
10
|
import { StreamClient } from '../../coordinator/connection/client';
|
|
21
11
|
|
|
22
12
|
describe('Call ringing events', () => {
|
|
23
|
-
describe('call.updated', () => {
|
|
24
|
-
it(`will update the call's metadata`, () => {
|
|
25
|
-
const state = new CallState();
|
|
26
|
-
const handler = watchCallUpdated(state);
|
|
27
|
-
const event: CallUpdatedEvent = {
|
|
28
|
-
type: 'call.updated',
|
|
29
|
-
call_cid: 'development:12345',
|
|
30
|
-
// @ts-expect-error
|
|
31
|
-
call: {
|
|
32
|
-
cid: 'development:12345',
|
|
33
|
-
},
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
// @ts-ignore
|
|
37
|
-
handler(event);
|
|
38
|
-
expect(state.metadata).toEqual(event.call);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it(`will ignore unknown events`, () => {
|
|
42
|
-
const state = new CallState();
|
|
43
|
-
const handler = watchCallUpdated(state);
|
|
44
|
-
const event = {
|
|
45
|
-
type: 'call.updated.unknown',
|
|
46
|
-
call_cid: 'development:12345',
|
|
47
|
-
call: {
|
|
48
|
-
cid: 'development:12345',
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
// @ts-ignore
|
|
53
|
-
handler(event);
|
|
54
|
-
expect(state.metadata).toBeUndefined();
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
|
|
58
13
|
describe(`call.accepted`, () => {
|
|
59
14
|
it(`will ignore events from the current user`, async () => {
|
|
60
15
|
const call = fakeCall();
|
|
@@ -96,7 +51,7 @@ describe('Call ringing events', () => {
|
|
|
96
51
|
describe(`call.rejected`, () => {
|
|
97
52
|
it(`caller will leave the call if all callees have rejected`, async () => {
|
|
98
53
|
const call = fakeCall({ currentUserId: 'm1' });
|
|
99
|
-
call.state.
|
|
54
|
+
call.state.updateFromCallResponse({
|
|
100
55
|
...fakeMetadata(),
|
|
101
56
|
// @ts-ignore
|
|
102
57
|
created_by: { id: 'm1' },
|
|
@@ -141,7 +96,7 @@ describe('Call ringing events', () => {
|
|
|
141
96
|
|
|
142
97
|
it(`caller will not leave the call if only one callee rejects`, async () => {
|
|
143
98
|
const call = fakeCall();
|
|
144
|
-
call.state.
|
|
99
|
+
call.state.updateFromCallResponse({
|
|
145
100
|
...fakeMetadata(),
|
|
146
101
|
// @ts-ignore
|
|
147
102
|
created_by: { id: 'm0' },
|
|
@@ -182,7 +137,7 @@ describe('Call ringing events', () => {
|
|
|
182
137
|
|
|
183
138
|
it('callee will leave the call if caller rejects', async () => {
|
|
184
139
|
const call = fakeCall({ currentUserId: 'm1' });
|
|
185
|
-
call.state.
|
|
140
|
+
call.state.updateFromCallResponse({
|
|
186
141
|
...fakeMetadata(),
|
|
187
142
|
// @ts-ignore
|
|
188
143
|
created_by: { id: 'm0' },
|
|
@@ -1,21 +1,7 @@
|
|
|
1
|
-
import { StreamVideoEvent } from '../coordinator/connection/types';
|
|
2
1
|
import { CallState } from '../store';
|
|
3
2
|
import { SfuEvent } from '../gen/video/sfu/event/events';
|
|
4
3
|
import { OwnCapability } from '../gen/coordinator';
|
|
5
4
|
|
|
6
|
-
/**
|
|
7
|
-
* Event handler that watches for `call.permissions_updated` events
|
|
8
|
-
*/
|
|
9
|
-
export const watchCallPermissionsUpdated = (state: CallState) => {
|
|
10
|
-
return function onCallPermissionsUpdated(event: StreamVideoEvent) {
|
|
11
|
-
if (event.type !== 'call.permissions_updated') return;
|
|
12
|
-
const { localParticipant } = state;
|
|
13
|
-
if (event.user.id === localParticipant?.userId) {
|
|
14
|
-
state.setOwnCapabilities(event.own_capabilities);
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
};
|
|
18
|
-
|
|
19
5
|
/**
|
|
20
6
|
* Event handler that watches for `callGrantsUpdated` events.
|
|
21
7
|
*
|
package/src/events/call.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CallingState
|
|
1
|
+
import { CallingState } from '../store';
|
|
2
2
|
import { StreamVideoEvent } from '../coordinator/connection/types';
|
|
3
3
|
import { Call } from '../Call';
|
|
4
4
|
|
|
@@ -76,24 +76,13 @@ export const watchCallRejected = (call: Call) => {
|
|
|
76
76
|
export const watchCallEnded = (call: Call) => {
|
|
77
77
|
return async function onCallCancelled(event: StreamVideoEvent) {
|
|
78
78
|
if (event.type !== 'call.ended') return;
|
|
79
|
+
const { callingState } = call.state;
|
|
79
80
|
if (
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
callingState === CallingState.RINGING ||
|
|
82
|
+
callingState === CallingState.JOINED ||
|
|
83
|
+
callingState === CallingState.JOINING
|
|
83
84
|
) {
|
|
84
|
-
call.state.setMetadata(event.call);
|
|
85
85
|
await call.leave();
|
|
86
86
|
}
|
|
87
87
|
};
|
|
88
88
|
};
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* An event handler which listens to `call.updated` events
|
|
92
|
-
* and updates the given call state accordingly.
|
|
93
|
-
*/
|
|
94
|
-
export const watchCallUpdated = (state: CallState) => {
|
|
95
|
-
return function onCallUpdated(event: StreamVideoEvent) {
|
|
96
|
-
if (event.type !== 'call.updated') return;
|
|
97
|
-
state.setMetadata(event.call);
|
|
98
|
-
};
|
|
99
|
-
};
|
|
@@ -3,31 +3,14 @@ import { Dispatcher } from '../rtc';
|
|
|
3
3
|
import { CallState } from '../store';
|
|
4
4
|
import {
|
|
5
5
|
watchAudioLevelChanged,
|
|
6
|
-
watchBlockedUser,
|
|
7
6
|
watchCallAccepted,
|
|
8
|
-
watchCallBroadcastingStarted,
|
|
9
|
-
watchCallBroadcastingStopped,
|
|
10
7
|
watchCallEnded,
|
|
11
8
|
watchCallGrantsUpdated,
|
|
12
|
-
watchCallLiveStarted,
|
|
13
|
-
watchCallMemberAdded,
|
|
14
|
-
watchCallMemberRemoved,
|
|
15
|
-
watchCallMemberUpdated,
|
|
16
|
-
watchCallMemberUpdatedPermission,
|
|
17
|
-
watchCallPermissionsUpdated,
|
|
18
|
-
watchCallRecordingStarted,
|
|
19
|
-
watchCallRecordingStopped,
|
|
20
9
|
watchCallRejected,
|
|
21
|
-
watchCallSessionEnded,
|
|
22
|
-
watchCallSessionParticipantJoined,
|
|
23
|
-
watchCallSessionParticipantLeft,
|
|
24
|
-
watchCallSessionStarted,
|
|
25
|
-
watchCallUpdated,
|
|
26
10
|
watchChangePublishQuality,
|
|
27
11
|
watchConnectionQualityChanged,
|
|
28
12
|
watchDominantSpeakerChanged,
|
|
29
13
|
watchLiveEnded,
|
|
30
|
-
watchNewReactions,
|
|
31
14
|
watchParticipantCountChanged,
|
|
32
15
|
watchParticipantJoined,
|
|
33
16
|
watchParticipantLeft,
|
|
@@ -35,7 +18,6 @@ import {
|
|
|
35
18
|
watchSfuErrorReports,
|
|
36
19
|
watchTrackPublished,
|
|
37
20
|
watchTrackUnpublished,
|
|
38
|
-
watchUnblockedUser,
|
|
39
21
|
} from '../events';
|
|
40
22
|
import {
|
|
41
23
|
CallEventTypes,
|
|
@@ -47,16 +29,6 @@ type RingCallEvents = Extract<
|
|
|
47
29
|
'call.accepted' | 'call.rejected'
|
|
48
30
|
>;
|
|
49
31
|
|
|
50
|
-
type AllCallEvents = Exclude<
|
|
51
|
-
CallEventTypes,
|
|
52
|
-
| 'call.created' // handled by StreamVideoClient
|
|
53
|
-
| 'call.ring' // handled by StreamVideoClient
|
|
54
|
-
| 'call.notification' // not used currently
|
|
55
|
-
| 'call.permission_request' // should be handled by the SDK component
|
|
56
|
-
| 'custom' // integrators should handle custom events
|
|
57
|
-
| RingCallEvents // handled by registerRingingCallEventHandlers
|
|
58
|
-
>;
|
|
59
|
-
|
|
60
32
|
/**
|
|
61
33
|
* Registers the default event handlers for a call during its lifecycle.
|
|
62
34
|
*
|
|
@@ -69,31 +41,9 @@ export const registerEventHandlers = (
|
|
|
69
41
|
state: CallState,
|
|
70
42
|
dispatcher: Dispatcher,
|
|
71
43
|
) => {
|
|
72
|
-
const coordinatorEvents: {
|
|
73
|
-
[key in AllCallEvents]: (e: StreamCallEvent) => any;
|
|
74
|
-
} = {
|
|
75
|
-
'call.blocked_user': watchBlockedUser(state),
|
|
76
|
-
'call.broadcasting_started': watchCallBroadcastingStarted(state),
|
|
77
|
-
'call.broadcasting_stopped': watchCallBroadcastingStopped(state),
|
|
78
|
-
'call.ended': watchCallEnded(call),
|
|
79
|
-
'call.live_started': watchCallLiveStarted(state),
|
|
80
|
-
'call.member_added': watchCallMemberAdded(state),
|
|
81
|
-
'call.member_removed': watchCallMemberRemoved(state),
|
|
82
|
-
'call.member_updated': watchCallMemberUpdated(state),
|
|
83
|
-
'call.member_updated_permission': watchCallMemberUpdatedPermission(state),
|
|
84
|
-
'call.permissions_updated': watchCallPermissionsUpdated(state),
|
|
85
|
-
'call.reaction_new': watchNewReactions(state),
|
|
86
|
-
'call.recording_started': watchCallRecordingStarted(state),
|
|
87
|
-
'call.recording_stopped': watchCallRecordingStopped(state),
|
|
88
|
-
'call.session_started': watchCallSessionStarted(state),
|
|
89
|
-
'call.session_ended': watchCallSessionEnded(state),
|
|
90
|
-
'call.session_participant_joined': watchCallSessionParticipantJoined(state),
|
|
91
|
-
'call.session_participant_left': watchCallSessionParticipantLeft(state),
|
|
92
|
-
'call.unblocked_user': watchUnblockedUser(state),
|
|
93
|
-
'call.updated': watchCallUpdated(state),
|
|
94
|
-
'call.user_muted': () => console.log('call.user_muted received'),
|
|
95
|
-
};
|
|
96
44
|
const eventHandlers = [
|
|
45
|
+
call.on('call.ended', watchCallEnded(call)),
|
|
46
|
+
|
|
97
47
|
watchLiveEnded(dispatcher, call),
|
|
98
48
|
watchSfuErrorReports(dispatcher),
|
|
99
49
|
watchChangePublishQuality(dispatcher, call),
|
|
@@ -113,11 +63,6 @@ export const registerEventHandlers = (
|
|
|
113
63
|
call.on('pinsUpdated', watchPinsUpdated(state)),
|
|
114
64
|
];
|
|
115
65
|
|
|
116
|
-
Object.keys(coordinatorEvents).forEach((event) => {
|
|
117
|
-
const eventName = event as AllCallEvents;
|
|
118
|
-
eventHandlers.push(call.on(eventName, coordinatorEvents[eventName]));
|
|
119
|
-
});
|
|
120
|
-
|
|
121
66
|
if (call.ringing) {
|
|
122
67
|
// these events are only relevant when the call is ringing
|
|
123
68
|
eventHandlers.push(registerRingingCallEventHandlers(call));
|
package/src/events/index.ts
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
export * from './backstage';
|
|
2
1
|
export * from './call';
|
|
3
2
|
export * from './call-permissions';
|
|
4
3
|
export * from './internal';
|
|
5
|
-
export * from './members';
|
|
6
4
|
export * from './participant';
|
|
7
|
-
export * from './reactions';
|
|
8
|
-
export * from './recording';
|
|
9
5
|
export * from './speaker';
|
|
10
|
-
export * from './sessions';
|
|
11
|
-
export * from './moderation';
|
|
@@ -2412,6 +2412,31 @@ export interface GetOrCreateCallResponse {
|
|
|
2412
2412
|
*/
|
|
2413
2413
|
own_capabilities: Array<OwnCapability>;
|
|
2414
2414
|
}
|
|
2415
|
+
/**
|
|
2416
|
+
*
|
|
2417
|
+
* @export
|
|
2418
|
+
* @interface GoLiveRequest
|
|
2419
|
+
*/
|
|
2420
|
+
export interface GoLiveRequest {
|
|
2421
|
+
/**
|
|
2422
|
+
*
|
|
2423
|
+
* @type {boolean}
|
|
2424
|
+
* @memberof GoLiveRequest
|
|
2425
|
+
*/
|
|
2426
|
+
start_hls?: boolean;
|
|
2427
|
+
/**
|
|
2428
|
+
*
|
|
2429
|
+
* @type {boolean}
|
|
2430
|
+
* @memberof GoLiveRequest
|
|
2431
|
+
*/
|
|
2432
|
+
start_recording?: boolean;
|
|
2433
|
+
/**
|
|
2434
|
+
*
|
|
2435
|
+
* @type {boolean}
|
|
2436
|
+
* @memberof GoLiveRequest
|
|
2437
|
+
*/
|
|
2438
|
+
start_transcription?: boolean;
|
|
2439
|
+
}
|
|
2415
2440
|
/**
|
|
2416
2441
|
*
|
|
2417
2442
|
* @export
|
package/src/rtc/Dispatcher.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { EventTypes, Logger } from '../coordinator/connection/types';
|
|
2
2
|
import type { SfuEvent } from '../gen/video/sfu/event/events';
|
|
3
3
|
import { getLogger } from '../logger';
|
|
4
4
|
|
|
@@ -26,7 +26,7 @@ const sfuEventKinds: { [key in SfuEventKinds]: undefined } = {
|
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
export const isSfuEvent = (
|
|
29
|
-
eventName: SfuEventKinds |
|
|
29
|
+
eventName: SfuEventKinds | EventTypes,
|
|
30
30
|
): eventName is SfuEventKinds => {
|
|
31
31
|
return Object.prototype.hasOwnProperty.call(sfuEventKinds, eventName);
|
|
32
32
|
};
|