@stream-io/video-client 0.0.1-alpha.91 → 0.0.1-alpha.93
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/dist/index.browser.es.js +481 -414
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +481 -414
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +481 -414
- package/dist/index.es.js.map +1 -1
- package/dist/src/coordinator/connection/client.d.ts +4 -4
- package/dist/src/coordinator/connection/types.d.ts +6 -8
- package/dist/src/events/call-permissions.d.ts +3 -4
- package/dist/src/events/call.d.ts +6 -8
- package/dist/src/events/moderation.d.ts +3 -3
- package/dist/src/events/reactions.d.ts +3 -3
- package/dist/src/events/recording.d.ts +3 -3
- package/dist/src/gen/coordinator/index.d.ts +51 -51
- package/dist/src/permissions/PermissionsContext.d.ts +38 -0
- package/dist/src/permissions/index.d.ts +1 -0
- package/dist/src/rtc/Call.d.ts +78 -4
- package/dist/src/rtc/callEventHandlers.d.ts +1 -1
- package/dist/src/rtc/types.d.ts +0 -8
- package/dist/src/store/rxUtils.d.ts +7 -0
- package/generate-openapi.sh +3 -4
- package/openapitools.json +1 -1
- package/package.json +1 -1
- package/src/StreamVideoClient.ts +25 -40
- package/src/coordinator/connection/client.ts +11 -11
- package/src/coordinator/connection/types.ts +7 -49
- package/src/events/call-permissions.ts +10 -66
- package/src/events/call.ts +15 -67
- package/src/events/moderation.ts +5 -34
- package/src/events/reactions.ts +5 -16
- package/src/events/recording.ts +5 -27
- package/src/gen/coordinator/index.ts +51 -51
- package/src/permissions/PermissionsContext.ts +63 -0
- package/src/permissions/index.ts +1 -0
- package/src/rtc/Call.ts +178 -61
- package/src/rtc/callEventHandlers.ts +39 -16
- package/src/rtc/types.ts +1 -10
- package/src/store/rxUtils.ts +16 -0
package/dist/index.browser.es.js
CHANGED
|
@@ -12,93 +12,93 @@ import { fromByteArray } from 'base64-js';
|
|
|
12
12
|
* @export
|
|
13
13
|
*/
|
|
14
14
|
const DeviceFieldsRequestPushProviderEnum = {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
FIREBASE: 'firebase',
|
|
16
|
+
APN: 'apn',
|
|
17
|
+
HUAWEI: 'huawei',
|
|
18
|
+
XIAOMI: 'xiaomi',
|
|
19
19
|
};
|
|
20
20
|
/**
|
|
21
21
|
* All possibility of string to use
|
|
22
22
|
* @export
|
|
23
23
|
*/
|
|
24
24
|
const OwnCapability = {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
25
|
+
BLOCK_USERS: 'block-users',
|
|
26
|
+
CREATE_CALL: 'create-call',
|
|
27
|
+
CREATE_REACTION: 'create-reaction',
|
|
28
|
+
END_CALL: 'end-call',
|
|
29
|
+
JOIN_BACKSTAGE: 'join-backstage',
|
|
30
|
+
JOIN_CALL: 'join-call',
|
|
31
|
+
JOIN_ENDED_CALL: 'join-ended-call',
|
|
32
|
+
MUTE_USERS: 'mute-users',
|
|
33
|
+
READ_CALL: 'read-call',
|
|
34
|
+
REMOVE_CALL_MEMBER: 'remove-call-member',
|
|
35
|
+
SCREENSHARE: 'screenshare',
|
|
36
|
+
SEND_AUDIO: 'send-audio',
|
|
37
|
+
SEND_VIDEO: 'send-video',
|
|
38
|
+
START_BROADCAST_CALL: 'start-broadcast-call',
|
|
39
|
+
START_RECORD_CALL: 'start-record-call',
|
|
40
|
+
START_TRANSCRIPTION_CALL: 'start-transcription-call',
|
|
41
|
+
STOP_BROADCAST_CALL: 'stop-broadcast-call',
|
|
42
|
+
STOP_RECORD_CALL: 'stop-record-call',
|
|
43
|
+
STOP_TRANSCRIPTION_CALL: 'stop-transcription-call',
|
|
44
|
+
UPDATE_CALL: 'update-call',
|
|
45
|
+
UPDATE_CALL_MEMBER: 'update-call-member',
|
|
46
|
+
UPDATE_CALL_PERMISSIONS: 'update-call-permissions',
|
|
47
|
+
UPDATE_CALL_SETTINGS: 'update-call-settings',
|
|
48
48
|
};
|
|
49
49
|
/**
|
|
50
50
|
* @export
|
|
51
51
|
*/
|
|
52
52
|
const RecordSettingsModeEnum = {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
AVAILABLE: 'available',
|
|
54
|
+
DISABLED: 'disabled',
|
|
55
|
+
AUTO_ON: 'auto-on',
|
|
56
56
|
};
|
|
57
57
|
/**
|
|
58
58
|
* @export
|
|
59
59
|
*/
|
|
60
60
|
const RecordSettingsQualityEnum = {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
61
|
+
AUDIO_ONLY: 'audio-only',
|
|
62
|
+
_360P: '360p',
|
|
63
|
+
_480P: '480p',
|
|
64
|
+
_720P: '720p',
|
|
65
|
+
_1080P: '1080p',
|
|
66
|
+
_1440P: '1440p',
|
|
67
67
|
};
|
|
68
68
|
/**
|
|
69
69
|
* @export
|
|
70
70
|
*/
|
|
71
71
|
const RecordSettingsRequestModeEnum = {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
AVAILABLE: 'available',
|
|
73
|
+
DISABLED: 'disabled',
|
|
74
|
+
AUTO_ON: 'auto-on',
|
|
75
75
|
};
|
|
76
76
|
/**
|
|
77
77
|
* @export
|
|
78
78
|
*/
|
|
79
79
|
const RecordSettingsRequestQualityEnum = {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
80
|
+
AUDIO_ONLY: 'audio-only',
|
|
81
|
+
_360P: '360p',
|
|
82
|
+
_480P: '480p',
|
|
83
|
+
_720P: '720p',
|
|
84
|
+
_1080P: '1080p',
|
|
85
|
+
_1440P: '1440p',
|
|
86
86
|
};
|
|
87
87
|
/**
|
|
88
88
|
* @export
|
|
89
89
|
*/
|
|
90
90
|
const TranscriptionSettingsModeEnum = {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
AVAILABLE: 'available',
|
|
92
|
+
DISABLED: 'disabled',
|
|
93
|
+
AUTO_ON: 'auto-on',
|
|
94
94
|
};
|
|
95
95
|
/**
|
|
96
96
|
* @export
|
|
97
97
|
*/
|
|
98
98
|
const TranscriptionSettingsRequestModeEnum = {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
AVAILABLE: 'available',
|
|
100
|
+
DISABLED: 'disabled',
|
|
101
|
+
AUTO_ON: 'auto-on',
|
|
102
102
|
};
|
|
103
103
|
|
|
104
104
|
class ErrorFromResponse extends Error {
|
|
@@ -4653,6 +4653,127 @@ class Publisher {
|
|
|
4653
4653
|
}
|
|
4654
4654
|
}
|
|
4655
4655
|
|
|
4656
|
+
/**
|
|
4657
|
+
* Event handler that watched the delivery of CallAcceptedEvent
|
|
4658
|
+
* Updates the state store and notifies its subscribers that
|
|
4659
|
+
* the given user will be joining the call.
|
|
4660
|
+
*/
|
|
4661
|
+
const watchCallAccepted = (store) => {
|
|
4662
|
+
return function onCallAccepted(event) {
|
|
4663
|
+
if (event.type !== 'call.accepted')
|
|
4664
|
+
return;
|
|
4665
|
+
const { call_cid } = event;
|
|
4666
|
+
const acceptedIncomingCall = store.incomingCalls.find((incomingCall) => incomingCall.cid === call_cid);
|
|
4667
|
+
if (acceptedIncomingCall) {
|
|
4668
|
+
console.warn('Received CallAcceptedEvent for an incoming call');
|
|
4669
|
+
return;
|
|
4670
|
+
}
|
|
4671
|
+
const acceptedOutgoingCall = store.outgoingCalls.find((outgoingCall) => outgoingCall.cid === call_cid);
|
|
4672
|
+
const activeCall = store.activeCall;
|
|
4673
|
+
// FIXME OL: we should revisit this logic, it is hard to follow
|
|
4674
|
+
const acceptedActiveCall = (activeCall === null || activeCall === void 0 ? void 0 : activeCall.cid) !== undefined && activeCall.cid === call_cid
|
|
4675
|
+
? activeCall
|
|
4676
|
+
: undefined;
|
|
4677
|
+
if (!acceptedOutgoingCall && !acceptedActiveCall) {
|
|
4678
|
+
console.warn(`CallAcceptedEvent received for a non-existent outgoing call (CID: ${call_cid}`);
|
|
4679
|
+
return;
|
|
4680
|
+
}
|
|
4681
|
+
// once in active call, it is unnecessary to keep track of accepted call events
|
|
4682
|
+
if (call_cid === (acceptedActiveCall === null || acceptedActiveCall === void 0 ? void 0 : acceptedActiveCall.cid)) {
|
|
4683
|
+
return;
|
|
4684
|
+
}
|
|
4685
|
+
// do not set a new accepted call while in an active call? It would lead to joining a new active call.
|
|
4686
|
+
// todo: solve the situation of 2nd outgoing call being accepted in the UI SDK
|
|
4687
|
+
store.setAcceptedCall(event);
|
|
4688
|
+
};
|
|
4689
|
+
};
|
|
4690
|
+
/**
|
|
4691
|
+
* Event handler that watches delivery of CallRejected Websocket event.
|
|
4692
|
+
* Updates the state store and notifies its subscribers that
|
|
4693
|
+
* the given user will not be joining the call.
|
|
4694
|
+
*/
|
|
4695
|
+
const watchCallRejected = (store) => {
|
|
4696
|
+
return function onCallRejected(event) {
|
|
4697
|
+
if (event.type !== 'call.rejected')
|
|
4698
|
+
return;
|
|
4699
|
+
const { call_cid } = event;
|
|
4700
|
+
const rejectedIncomingCall = store.incomingCalls.find((incomingCall) => incomingCall.cid === call_cid);
|
|
4701
|
+
if (rejectedIncomingCall) {
|
|
4702
|
+
console.warn('Received CallRejectedEvent for an incoming call');
|
|
4703
|
+
return;
|
|
4704
|
+
}
|
|
4705
|
+
const rejectedOutgoingCall = store.outgoingCalls.find((outgoingCall) => outgoingCall.cid === call_cid);
|
|
4706
|
+
const activeCall = store.activeCall;
|
|
4707
|
+
const rejectedActiveCall = (activeCall === null || activeCall === void 0 ? void 0 : activeCall.cid) !== undefined && activeCall.cid === call_cid
|
|
4708
|
+
? activeCall
|
|
4709
|
+
: undefined;
|
|
4710
|
+
if (!rejectedOutgoingCall && !rejectedActiveCall) {
|
|
4711
|
+
console.warn(`CallRejectedEvent received for a non-existent outgoing call (CID: ${call_cid}`);
|
|
4712
|
+
return;
|
|
4713
|
+
}
|
|
4714
|
+
// FIXME: we should remove the call from pending once every callee has rejected, but for now we support only 1:1 ring calls
|
|
4715
|
+
store.setPendingCalls((pendingCalls) => pendingCalls.filter((pendingCall) => pendingCall.cid !== call_cid));
|
|
4716
|
+
};
|
|
4717
|
+
};
|
|
4718
|
+
/**
|
|
4719
|
+
* Event handler that watches the delivery of CallEndedEvent
|
|
4720
|
+
* Updates the state store and notifies its subscribers that
|
|
4721
|
+
* the call is now considered terminated.
|
|
4722
|
+
*/
|
|
4723
|
+
const watchCallCancelled = (store) => {
|
|
4724
|
+
return function onCallCancelled(event) {
|
|
4725
|
+
if (event.type !== 'call.ended')
|
|
4726
|
+
return;
|
|
4727
|
+
const { call_cid } = event;
|
|
4728
|
+
const cancelledIncomingCall = store.incomingCalls.find((incomingCall) => incomingCall.cid === call_cid);
|
|
4729
|
+
const activeCall = store.activeCall;
|
|
4730
|
+
const cancelledActiveCall = (activeCall === null || activeCall === void 0 ? void 0 : activeCall.cid) !== undefined && activeCall.cid === call_cid
|
|
4731
|
+
? activeCall
|
|
4732
|
+
: undefined;
|
|
4733
|
+
if (!cancelledIncomingCall && !cancelledActiveCall) {
|
|
4734
|
+
console.warn(`CallEndedEvent received for a non-existent incoming call (CID: ${call_cid}`);
|
|
4735
|
+
return;
|
|
4736
|
+
}
|
|
4737
|
+
store.setPendingCalls((pendingCalls) => pendingCalls.filter((pendingCall) => pendingCall.cid !== call_cid));
|
|
4738
|
+
};
|
|
4739
|
+
};
|
|
4740
|
+
/**
|
|
4741
|
+
* An event handler which listens to `call.updated` events
|
|
4742
|
+
* and updates the given call state accordingly.
|
|
4743
|
+
*/
|
|
4744
|
+
const watchCallUpdated = (state) => {
|
|
4745
|
+
return function onCallUpdated(event) {
|
|
4746
|
+
if (event.type !== 'call.updated')
|
|
4747
|
+
return;
|
|
4748
|
+
state.setMetadata(event.call);
|
|
4749
|
+
};
|
|
4750
|
+
};
|
|
4751
|
+
|
|
4752
|
+
/**
|
|
4753
|
+
* Event handler that watches for `call.permission_request` events
|
|
4754
|
+
* Updates the state store using the `callPermissionRequest$` stream
|
|
4755
|
+
*/
|
|
4756
|
+
const watchCallPermissionRequest = (state) => {
|
|
4757
|
+
return function onCallPermissionRequest(event) {
|
|
4758
|
+
if (event.type !== 'call.permission_request')
|
|
4759
|
+
return;
|
|
4760
|
+
state.setCallPermissionRequest(event);
|
|
4761
|
+
};
|
|
4762
|
+
};
|
|
4763
|
+
/**
|
|
4764
|
+
* Event handler that watches for `call.permissions_updated` events
|
|
4765
|
+
*/
|
|
4766
|
+
const watchCallPermissionsUpdated = (state) => {
|
|
4767
|
+
return function onCallPermissionsUpdated(event) {
|
|
4768
|
+
if (event.type !== 'call.permissions_updated')
|
|
4769
|
+
return;
|
|
4770
|
+
const { localParticipant } = state;
|
|
4771
|
+
if (event.user.id === (localParticipant === null || localParticipant === void 0 ? void 0 : localParticipant.userId)) {
|
|
4772
|
+
state.setMetadata((metadata) => (Object.assign(Object.assign({}, metadata), { own_capabilities: event.own_capabilities })));
|
|
4773
|
+
}
|
|
4774
|
+
};
|
|
4775
|
+
};
|
|
4776
|
+
|
|
4656
4777
|
/**
|
|
4657
4778
|
* An event responder which handles the `changePublishQuality` event.
|
|
4658
4779
|
*/
|
|
@@ -4750,6 +4871,57 @@ const watchTrackUnpublished = (dispatcher, state) => {
|
|
|
4750
4871
|
};
|
|
4751
4872
|
const unique = (v, i, arr) => arr.indexOf(v) === i;
|
|
4752
4873
|
|
|
4874
|
+
/**
|
|
4875
|
+
* Watches the delivery of CallReactionEvent.
|
|
4876
|
+
*
|
|
4877
|
+
* @param state the state store to update.
|
|
4878
|
+
*/
|
|
4879
|
+
const watchNewReactions = (state) => {
|
|
4880
|
+
return function onNewReactions(event) {
|
|
4881
|
+
if (event.type !== 'call.reaction_new')
|
|
4882
|
+
return;
|
|
4883
|
+
const { reaction } = event;
|
|
4884
|
+
const { user, custom, type, emoji_code } = reaction;
|
|
4885
|
+
state.setParticipants((participants) => {
|
|
4886
|
+
return participants.map((p) => {
|
|
4887
|
+
// skip if the reaction is not for this participant
|
|
4888
|
+
if (p.userId !== user.id)
|
|
4889
|
+
return p;
|
|
4890
|
+
// skip if the reaction is not for this session
|
|
4891
|
+
if (custom.sessionId && p.sessionId !== custom.sessionId)
|
|
4892
|
+
return p;
|
|
4893
|
+
// update the participant with the new reaction
|
|
4894
|
+
return Object.assign(Object.assign({}, p), { reaction: {
|
|
4895
|
+
type,
|
|
4896
|
+
emoji_code,
|
|
4897
|
+
custom,
|
|
4898
|
+
} });
|
|
4899
|
+
});
|
|
4900
|
+
});
|
|
4901
|
+
};
|
|
4902
|
+
};
|
|
4903
|
+
|
|
4904
|
+
/**
|
|
4905
|
+
* Watches for `call.recording_started` events.
|
|
4906
|
+
*/
|
|
4907
|
+
const watchCallRecordingStarted = (state) => {
|
|
4908
|
+
return function onCallRecordingStarted(event) {
|
|
4909
|
+
if (event.type !== 'call.recording_started')
|
|
4910
|
+
return;
|
|
4911
|
+
state.setCallRecordingInProgress(true);
|
|
4912
|
+
};
|
|
4913
|
+
};
|
|
4914
|
+
/**
|
|
4915
|
+
* Watches for `call.recording_stopped` events.
|
|
4916
|
+
*/
|
|
4917
|
+
const watchCallRecordingStopped = (state) => {
|
|
4918
|
+
return function onCallRecordingStopped(event) {
|
|
4919
|
+
if (event.type !== 'call.recording_stopped')
|
|
4920
|
+
return;
|
|
4921
|
+
state.setCallRecordingInProgress(false);
|
|
4922
|
+
};
|
|
4923
|
+
};
|
|
4924
|
+
|
|
4753
4925
|
/**
|
|
4754
4926
|
* Watches for `dominantSpeakerChanged` events.
|
|
4755
4927
|
*/
|
|
@@ -4792,15 +4964,52 @@ const watchAudioLevelChanged = (dispatcher, state) => {
|
|
|
4792
4964
|
});
|
|
4793
4965
|
};
|
|
4794
4966
|
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4967
|
+
/**
|
|
4968
|
+
* Event handler that watches for `call.blocked_user` events,
|
|
4969
|
+
* updates the call store `blocked_user_ids` property by adding
|
|
4970
|
+
* `event.user_id` to the list
|
|
4971
|
+
*/
|
|
4972
|
+
const watchBlockedUser = (state) => (event) => {
|
|
4973
|
+
if (event.type !== 'call.blocked_user')
|
|
4974
|
+
return;
|
|
4975
|
+
state.setMetadata((metadata) => (Object.assign(Object.assign({}, metadata), { blocked_user_ids: [...metadata.blocked_user_ids, event.user.id] })));
|
|
4976
|
+
};
|
|
4977
|
+
/**
|
|
4978
|
+
* Event handler that watches for `call.unblocked_user` events,
|
|
4979
|
+
* updates the call store `blocked_user_ids` property by
|
|
4980
|
+
* removing `event.user_id` from the list
|
|
4981
|
+
*/
|
|
4982
|
+
const watchUnblockedUser = (state) => (event) => {
|
|
4983
|
+
if (event.type !== 'call.unblocked_user')
|
|
4984
|
+
return;
|
|
4985
|
+
state.setMetadata((metadata) => {
|
|
4986
|
+
const blocked_user_ids = metadata.blocked_user_ids.filter((userId) => event.user.id !== userId);
|
|
4987
|
+
return Object.assign(Object.assign({}, metadata), { blocked_user_ids });
|
|
4988
|
+
});
|
|
4989
|
+
};
|
|
4990
|
+
|
|
4991
|
+
const registerEventHandlers = (call, state, dispatcher) => {
|
|
4992
|
+
const eventHandlers = [
|
|
4993
|
+
watchChangePublishQuality(dispatcher, call),
|
|
4994
|
+
watchConnectionQualityChanged(dispatcher, state),
|
|
4995
|
+
watchParticipantJoined(dispatcher, state),
|
|
4996
|
+
watchParticipantLeft(dispatcher, state),
|
|
4997
|
+
watchTrackPublished(dispatcher, state),
|
|
4998
|
+
watchTrackUnpublished(dispatcher, state),
|
|
4999
|
+
watchAudioLevelChanged(dispatcher, state),
|
|
5000
|
+
watchDominantSpeakerChanged(dispatcher, state),
|
|
5001
|
+
call.on('call.updated', watchCallUpdated(state)),
|
|
5002
|
+
call.on('call.blocked_user', watchBlockedUser(state)),
|
|
5003
|
+
call.on('call.unblocked_user', watchUnblockedUser(state)),
|
|
5004
|
+
call.on('call.reaction_new', watchNewReactions(state)),
|
|
5005
|
+
call.on('call.recording_started', watchCallRecordingStarted(state)),
|
|
5006
|
+
call.on('call.recording_stopped', watchCallRecordingStopped(state)),
|
|
5007
|
+
call.on('call.permission_request', watchCallPermissionRequest(state)),
|
|
5008
|
+
call.on('call.permissions_updated', watchCallPermissionsUpdated(state)),
|
|
5009
|
+
];
|
|
5010
|
+
return () => {
|
|
5011
|
+
eventHandlers.forEach((unsubscribe) => unsubscribe());
|
|
5012
|
+
};
|
|
4804
5013
|
};
|
|
4805
5014
|
|
|
4806
5015
|
const sfuEventKinds = {
|
|
@@ -4895,9 +5104,22 @@ const setCurrentValue = (subject, update) => {
|
|
|
4895
5104
|
subject.next(next);
|
|
4896
5105
|
return next;
|
|
4897
5106
|
};
|
|
5107
|
+
/**
|
|
5108
|
+
* Creates a subscription and returns a function to unsubscribe.
|
|
5109
|
+
*
|
|
5110
|
+
* @param observable the observable to subscribe to.
|
|
5111
|
+
* @param handler the handler to call when the observable emits a value.
|
|
5112
|
+
*/
|
|
5113
|
+
const createSubscription = (observable, handler) => {
|
|
5114
|
+
const subscription = observable.subscribe(handler);
|
|
5115
|
+
return () => {
|
|
5116
|
+
subscription.unsubscribe();
|
|
5117
|
+
};
|
|
5118
|
+
};
|
|
4898
5119
|
|
|
4899
5120
|
var rxUtils = /*#__PURE__*/Object.freeze({
|
|
4900
5121
|
__proto__: null,
|
|
5122
|
+
createSubscription: createSubscription,
|
|
4901
5123
|
getCurrentValue: getCurrentValue,
|
|
4902
5124
|
setCurrentValue: setCurrentValue
|
|
4903
5125
|
});
|
|
@@ -6052,6 +6274,65 @@ class ViewportTracker {
|
|
|
6052
6274
|
}
|
|
6053
6275
|
}
|
|
6054
6276
|
|
|
6277
|
+
/**
|
|
6278
|
+
* Stores the permissions for the current user and exposes
|
|
6279
|
+
* a few helper methods which make it easier to work with permissions.
|
|
6280
|
+
*
|
|
6281
|
+
* This is an internal class meant to be used in combination with
|
|
6282
|
+
* a {@link Call} instance.
|
|
6283
|
+
*
|
|
6284
|
+
* @internal
|
|
6285
|
+
*/
|
|
6286
|
+
class PermissionsContext {
|
|
6287
|
+
constructor() {
|
|
6288
|
+
this.permissions = [];
|
|
6289
|
+
/**
|
|
6290
|
+
* Sets the permissions for the current user.
|
|
6291
|
+
*
|
|
6292
|
+
* @param permissions the permissions to set.
|
|
6293
|
+
*/
|
|
6294
|
+
this.setPermissions = (permissions) => {
|
|
6295
|
+
this.permissions = permissions;
|
|
6296
|
+
};
|
|
6297
|
+
/**
|
|
6298
|
+
* Sets the settings for the bound call.
|
|
6299
|
+
* @param settings
|
|
6300
|
+
*/
|
|
6301
|
+
this.setCallSettings = (settings) => {
|
|
6302
|
+
this.settings = settings;
|
|
6303
|
+
};
|
|
6304
|
+
/**
|
|
6305
|
+
* Checks if the current user has a specific permission.
|
|
6306
|
+
*
|
|
6307
|
+
* @param permission the permission to check for.
|
|
6308
|
+
*/
|
|
6309
|
+
this.hasPermission = (permission) => {
|
|
6310
|
+
return this.permissions.includes(permission);
|
|
6311
|
+
};
|
|
6312
|
+
/**
|
|
6313
|
+
* Checks if the current user can request a specific permission
|
|
6314
|
+
* within the call.
|
|
6315
|
+
*
|
|
6316
|
+
* @param permission the permission to check for.
|
|
6317
|
+
*/
|
|
6318
|
+
this.canRequest = (permission) => {
|
|
6319
|
+
if (!this.settings)
|
|
6320
|
+
return false;
|
|
6321
|
+
const { audio, video, screensharing } = this.settings;
|
|
6322
|
+
switch (permission) {
|
|
6323
|
+
case OwnCapability.SEND_AUDIO:
|
|
6324
|
+
return audio.access_request_enabled;
|
|
6325
|
+
case OwnCapability.SEND_VIDEO:
|
|
6326
|
+
return video.access_request_enabled;
|
|
6327
|
+
case OwnCapability.SCREENSHARE:
|
|
6328
|
+
return screensharing.access_request_enabled;
|
|
6329
|
+
default:
|
|
6330
|
+
return false;
|
|
6331
|
+
}
|
|
6332
|
+
};
|
|
6333
|
+
}
|
|
6334
|
+
}
|
|
6335
|
+
|
|
6055
6336
|
/**
|
|
6056
6337
|
* Represents a call type.
|
|
6057
6338
|
*/
|
|
@@ -6162,6 +6443,10 @@ class Call {
|
|
|
6162
6443
|
* ViewportTracker instance
|
|
6163
6444
|
*/
|
|
6164
6445
|
this.viewportTracker = new ViewportTracker();
|
|
6446
|
+
/**
|
|
6447
|
+
* The permissions context of this call.
|
|
6448
|
+
*/
|
|
6449
|
+
this.permissionsContext = new PermissionsContext();
|
|
6165
6450
|
/**
|
|
6166
6451
|
* The event dispatcher instance dedicated to this Call instance.
|
|
6167
6452
|
* @private
|
|
@@ -6176,15 +6461,7 @@ class Call {
|
|
|
6176
6461
|
* @private
|
|
6177
6462
|
*/
|
|
6178
6463
|
this.leaveCallHooks = [];
|
|
6179
|
-
|
|
6180
|
-
* Remove subscription for WebSocket events that were created by the `on` method.
|
|
6181
|
-
* @param eventName
|
|
6182
|
-
* @param fn
|
|
6183
|
-
* @returns
|
|
6184
|
-
*/
|
|
6185
|
-
this.off = (eventName, fn) => {
|
|
6186
|
-
return this.dispatcher.off(eventName, fn);
|
|
6187
|
-
};
|
|
6464
|
+
this.streamClientEventHandlers = new Map();
|
|
6188
6465
|
/**
|
|
6189
6466
|
* Leave the call and stop the media streams that were published by the call.
|
|
6190
6467
|
*/
|
|
@@ -6245,6 +6522,7 @@ class Call {
|
|
|
6245
6522
|
const call = yield join(this.streamClient, this.type, this.id, data);
|
|
6246
6523
|
this.state.setMetadata(call.metadata);
|
|
6247
6524
|
this.state.setMembers(call.members);
|
|
6525
|
+
// TODO OL: do we need to handle JOIN_CALL permission here?
|
|
6248
6526
|
// FIXME OL: convert to a derived state
|
|
6249
6527
|
this.state.setCallRecordingInProgress(call.metadata.recording);
|
|
6250
6528
|
// FIXME OL: remove once cascading is implemented
|
|
@@ -6373,12 +6651,7 @@ class Call {
|
|
|
6373
6651
|
// fails to respond in time
|
|
6374
6652
|
const { callState } = yield this.waitForJoinResponse();
|
|
6375
6653
|
const currentParticipants = (callState === null || callState === void 0 ? void 0 : callState.participants) || [];
|
|
6376
|
-
|
|
6377
|
-
ownCapabilities: call.metadata.own_capabilities,
|
|
6378
|
-
};
|
|
6379
|
-
this.state.setParticipants(currentParticipants.map((participant) => (Object.assign(Object.assign(Object.assign({}, participant), { isLoggedInUser: participant.sessionId === sfuClient.sessionId, viewportVisibilityState: VisibilityState.UNKNOWN }), (participant.sessionId === sfuClient.sessionId
|
|
6380
|
-
? ownCapabilities
|
|
6381
|
-
: {})))));
|
|
6654
|
+
this.state.setParticipants(currentParticipants.map((participant) => (Object.assign(Object.assign({}, participant), { isLoggedInUser: participant.sessionId === sfuClient.sessionId, viewportVisibilityState: VisibilityState.UNKNOWN }))));
|
|
6382
6655
|
this.clientStore.setActiveCall(this);
|
|
6383
6656
|
this.reconnectAttempts = 0; // reset the reconnect attempts counter
|
|
6384
6657
|
this.state.setCallingState(CallingState.JOINED);
|
|
@@ -6397,8 +6670,13 @@ class Call {
|
|
|
6397
6670
|
}
|
|
6398
6671
|
}
|
|
6399
6672
|
});
|
|
6673
|
+
/**
|
|
6674
|
+
* Will update the call members.
|
|
6675
|
+
*
|
|
6676
|
+
* @param data the request data.
|
|
6677
|
+
*/
|
|
6400
6678
|
this.updateCallMembers = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
6401
|
-
return
|
|
6679
|
+
return this.streamClient.post(`${this.streamClientBasePath}/members`, data);
|
|
6402
6680
|
});
|
|
6403
6681
|
/**
|
|
6404
6682
|
* Starts publishing the given video stream to the call.
|
|
@@ -6751,38 +7029,72 @@ class Call {
|
|
|
6751
7029
|
.subscribe(() => resolve());
|
|
6752
7030
|
});
|
|
6753
7031
|
};
|
|
7032
|
+
/**
|
|
7033
|
+
* Sends a reaction to the other call participants.
|
|
7034
|
+
*
|
|
7035
|
+
* @param reaction the reaction to send.
|
|
7036
|
+
*/
|
|
6754
7037
|
this.sendReaction = (reaction) => __awaiter(this, void 0, void 0, function* () {
|
|
6755
7038
|
return this.streamClient.post(`${this.streamClientBasePath}/reaction`, reaction);
|
|
6756
7039
|
});
|
|
7040
|
+
/**
|
|
7041
|
+
* Blocks the user with the given `userId`.
|
|
7042
|
+
*
|
|
7043
|
+
* @param userId the id of the user to block.
|
|
7044
|
+
*/
|
|
6757
7045
|
this.blockUser = (userId) => __awaiter(this, void 0, void 0, function* () {
|
|
6758
7046
|
return this.streamClient.post(`${this.streamClientBasePath}/block`, {
|
|
6759
7047
|
user_id: userId,
|
|
6760
7048
|
});
|
|
6761
7049
|
});
|
|
7050
|
+
/**
|
|
7051
|
+
* Unblocks the user with the given `userId`.
|
|
7052
|
+
*
|
|
7053
|
+
* @param userId the id of the user to unblock.
|
|
7054
|
+
*/
|
|
6762
7055
|
this.unblockUser = (userId) => __awaiter(this, void 0, void 0, function* () {
|
|
6763
7056
|
return this.streamClient.post(`${this.streamClientBasePath}/unblock`, {
|
|
6764
7057
|
user_id: userId,
|
|
6765
7058
|
});
|
|
6766
7059
|
});
|
|
6767
|
-
|
|
7060
|
+
/**
|
|
7061
|
+
* Mutes the user with the given `userId`.
|
|
7062
|
+
*
|
|
7063
|
+
* @param userId the id of the user to mute.
|
|
7064
|
+
* @param type the type of the mute operation.
|
|
7065
|
+
*/
|
|
7066
|
+
this.muteUser = (userId, type) => {
|
|
7067
|
+
// FIXME OL: handle muting self.
|
|
6768
7068
|
return this.streamClient.post(`${this.streamClientBasePath}/mute_users`, {
|
|
6769
|
-
user_ids: [userId],
|
|
7069
|
+
user_ids: Array.isArray(userId) ? userId : [userId],
|
|
6770
7070
|
[type]: true,
|
|
6771
|
-
// session_ids: [sessionId],
|
|
6772
7071
|
});
|
|
6773
7072
|
};
|
|
7073
|
+
/**
|
|
7074
|
+
* Will mute all users in the call.
|
|
7075
|
+
*
|
|
7076
|
+
* @param type the type of the mute operation.
|
|
7077
|
+
*/
|
|
6774
7078
|
this.muteAllUsers = (type) => {
|
|
6775
7079
|
return this.streamClient.post(`${this.streamClientBasePath}/mute_users`, {
|
|
6776
7080
|
mute_all_users: true,
|
|
6777
7081
|
[type]: true,
|
|
6778
7082
|
});
|
|
6779
7083
|
};
|
|
7084
|
+
/**
|
|
7085
|
+
* Loads the information about the call.
|
|
7086
|
+
*/
|
|
6780
7087
|
this.get = () => __awaiter(this, void 0, void 0, function* () {
|
|
6781
7088
|
const response = yield this.streamClient.get(this.streamClientBasePath);
|
|
6782
7089
|
this.state.setMetadata(response.call);
|
|
6783
7090
|
this.state.setMembers(response.members);
|
|
6784
7091
|
return response;
|
|
6785
7092
|
});
|
|
7093
|
+
/**
|
|
7094
|
+
* Loads the information about the call and creates it if it doesn't exist.
|
|
7095
|
+
*
|
|
7096
|
+
* @param data the data to create the call with.
|
|
7097
|
+
*/
|
|
6786
7098
|
this.getOrCreate = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
6787
7099
|
const response = yield this.streamClient.post(this.streamClientBasePath, data);
|
|
6788
7100
|
if ((data === null || data === void 0 ? void 0 : data.ring) && !this.dropTimeout) {
|
|
@@ -6804,28 +7116,23 @@ class Call {
|
|
|
6804
7116
|
* Starts recording the call
|
|
6805
7117
|
*/
|
|
6806
7118
|
this.startRecording = () => __awaiter(this, void 0, void 0, function* () {
|
|
6807
|
-
|
|
6808
|
-
return yield this.streamClient.post(`${this.streamClientBasePath}/start_recording`, {});
|
|
6809
|
-
}
|
|
6810
|
-
catch (error) {
|
|
6811
|
-
console.log(`Failed to start recording`, error);
|
|
6812
|
-
}
|
|
7119
|
+
return this.streamClient.post(`${this.streamClientBasePath}/start_recording`, {});
|
|
6813
7120
|
});
|
|
6814
7121
|
/**
|
|
6815
7122
|
* Stops recording the call
|
|
6816
7123
|
*/
|
|
6817
7124
|
this.stopRecording = () => __awaiter(this, void 0, void 0, function* () {
|
|
6818
|
-
|
|
6819
|
-
return yield this.streamClient.post(`${this.streamClientBasePath}/stop_recording`, {});
|
|
6820
|
-
}
|
|
6821
|
-
catch (error) {
|
|
6822
|
-
console.log(`Failed to stop recording`, error);
|
|
6823
|
-
}
|
|
7125
|
+
return this.streamClient.post(`${this.streamClientBasePath}/stop_recording`, {});
|
|
6824
7126
|
});
|
|
6825
7127
|
/**
|
|
6826
7128
|
* Sends a `call.permission_request` event to all users connected to the call. The call settings object contains infomration about which permissions can be requested during a call (for example a user might be allowed to request permission to publish audio, but not video).
|
|
6827
7129
|
*/
|
|
6828
7130
|
this.requestPermissions = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
7131
|
+
const { permissions } = data;
|
|
7132
|
+
const canRequestPermissions = permissions.every((permission) => this.permissionsContext.canRequest(permission));
|
|
7133
|
+
if (!canRequestPermissions) {
|
|
7134
|
+
throw new Error(`You are not allowed to request permissions: ${permissions.join(', ')}`);
|
|
7135
|
+
}
|
|
6829
7136
|
return this.streamClient.post(`${this.streamClientBasePath}/request_permission`, data);
|
|
6830
7137
|
});
|
|
6831
7138
|
/**
|
|
@@ -6841,12 +7148,24 @@ class Call {
|
|
|
6841
7148
|
this.updateUserPermissions = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
6842
7149
|
return this.streamClient.post(`${this.streamClientBasePath}/user_permissions`, data);
|
|
6843
7150
|
});
|
|
7151
|
+
/**
|
|
7152
|
+
* Starts the livestreaming of the call.
|
|
7153
|
+
*/
|
|
6844
7154
|
this.goLive = () => __awaiter(this, void 0, void 0, function* () {
|
|
6845
7155
|
return this.streamClient.post(`${this.streamClientBasePath}/go_live`, {});
|
|
6846
7156
|
});
|
|
7157
|
+
/**
|
|
7158
|
+
* Stops the livestreaming of the call.
|
|
7159
|
+
*/
|
|
6847
7160
|
this.stopLive = () => __awaiter(this, void 0, void 0, function* () {
|
|
6848
7161
|
return this.streamClient.post(`${this.streamClientBasePath}/stop_live`, {});
|
|
6849
7162
|
});
|
|
7163
|
+
/**
|
|
7164
|
+
* Updates the call settings or custom data.
|
|
7165
|
+
*
|
|
7166
|
+
* @param custom the custom data to update.
|
|
7167
|
+
* @param settings the call settings to update.
|
|
7168
|
+
*/
|
|
6850
7169
|
this.update = (custom, settings) => __awaiter(this, void 0, void 0, function* () {
|
|
6851
7170
|
const payload = {
|
|
6852
7171
|
custom: custom,
|
|
@@ -6854,6 +7173,9 @@ class Call {
|
|
|
6854
7173
|
};
|
|
6855
7174
|
return this.streamClient.patch(`${this.streamClientBasePath}`, payload);
|
|
6856
7175
|
});
|
|
7176
|
+
/**
|
|
7177
|
+
* Ends the call. Once the call is ended, it cannot be re-joined.
|
|
7178
|
+
*/
|
|
6857
7179
|
this.endCall = () => __awaiter(this, void 0, void 0, function* () {
|
|
6858
7180
|
return this.streamClient.post(`${this.streamClientBasePath}/mark_ended`);
|
|
6859
7181
|
});
|
|
@@ -6976,9 +7298,19 @@ class Call {
|
|
|
6976
7298
|
this.state.setCallRecordingsList(response.recordings);
|
|
6977
7299
|
return response;
|
|
6978
7300
|
});
|
|
7301
|
+
/**
|
|
7302
|
+
* Returns a list of Edge Serves for current call.
|
|
7303
|
+
*
|
|
7304
|
+
* @param data the data.
|
|
7305
|
+
*/
|
|
6979
7306
|
this.getEdgeServer = (data) => {
|
|
6980
7307
|
return this.streamClient.post(`${this.streamClientBasePath}/get_edge_server`, data);
|
|
6981
7308
|
};
|
|
7309
|
+
/**
|
|
7310
|
+
* Sends an event to all call participants.
|
|
7311
|
+
*
|
|
7312
|
+
* @param event the event to send.
|
|
7313
|
+
*/
|
|
6982
7314
|
this.sendEvent = (event) => __awaiter(this, void 0, void 0, function* () {
|
|
6983
7315
|
return this.streamClient.post(`${this.streamClientBasePath}/event`, event);
|
|
6984
7316
|
});
|
|
@@ -6996,13 +7328,29 @@ class Call {
|
|
|
6996
7328
|
}
|
|
6997
7329
|
this.state.setMetadata(metadata);
|
|
6998
7330
|
this.state.setMembers(members || []);
|
|
6999
|
-
registerEventHandlers(this, this.state, this.dispatcher);
|
|
7000
|
-
this.
|
|
7001
|
-
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7331
|
+
this.leaveCallHooks.push(registerEventHandlers(this, this.state, this.dispatcher));
|
|
7332
|
+
this.registerEffects();
|
|
7333
|
+
this.leaveCallHooks.push(createSubscription(this.trackSubscriptionsSubject.pipe(debounceTime(UPDATE_SUBSCRIPTIONS_DEBOUNCE_DURATION)), (subscriptions) => { var _a; return (_a = this.sfuClient) === null || _a === void 0 ? void 0 : _a.updateSubscriptions(subscriptions); }));
|
|
7334
|
+
}
|
|
7335
|
+
registerEffects() {
|
|
7336
|
+
this.leaveCallHooks.push(
|
|
7337
|
+
// handles updating the permissions context when the metadata changes.
|
|
7338
|
+
createSubscription(this.state.metadata$, (metadata) => {
|
|
7339
|
+
if (!metadata)
|
|
7340
|
+
return;
|
|
7341
|
+
this.permissionsContext.setPermissions(metadata.own_capabilities);
|
|
7342
|
+
this.permissionsContext.setCallSettings(metadata.settings);
|
|
7343
|
+
}),
|
|
7344
|
+
// handles the case when the user is blocked by the call owner.
|
|
7345
|
+
createSubscription(this.state.metadata$, (metadata) => {
|
|
7346
|
+
if (!metadata)
|
|
7347
|
+
return;
|
|
7348
|
+
const connectedUser = this.clientStore.connectedUser;
|
|
7349
|
+
if (connectedUser &&
|
|
7350
|
+
metadata.blocked_user_ids.includes(connectedUser.id)) {
|
|
7351
|
+
this.leave();
|
|
7352
|
+
}
|
|
7353
|
+
}));
|
|
7006
7354
|
}
|
|
7007
7355
|
on(eventName, fn) {
|
|
7008
7356
|
if (isSfuEvent(eventName)) {
|
|
@@ -7014,320 +7362,25 @@ class Call {
|
|
|
7014
7362
|
fn(event);
|
|
7015
7363
|
}
|
|
7016
7364
|
};
|
|
7365
|
+
this.streamClientEventHandlers.set(fn, eventHandler);
|
|
7017
7366
|
return this.streamClient.on(eventName, eventHandler);
|
|
7018
7367
|
}
|
|
7019
7368
|
}
|
|
7020
|
-
|
|
7021
|
-
|
|
7022
|
-
|
|
7023
|
-
}
|
|
7024
|
-
|
|
7025
|
-
/**
|
|
7026
|
-
* Event handler that watches the delivery of CallCreated Websocket event
|
|
7027
|
-
* Updates the state store and notifies its subscribers that
|
|
7028
|
-
* a new pending call has been initiated.
|
|
7029
|
-
*/
|
|
7030
|
-
const watchCallCreated = (store, streamClient) => {
|
|
7031
|
-
return function onCallCreated(event) {
|
|
7032
|
-
if (event.type !== 'call.created') {
|
|
7033
|
-
return;
|
|
7034
|
-
}
|
|
7035
|
-
const { call, members, ringing } = event;
|
|
7036
|
-
if (!call) {
|
|
7037
|
-
console.warn("Can't find call in CallCreatedEvent");
|
|
7038
|
-
return;
|
|
7039
|
-
}
|
|
7040
|
-
const currentUser = store.connectedUser;
|
|
7041
|
-
if ((currentUser === null || currentUser === void 0 ? void 0 : currentUser.id) === call.created_by.id) {
|
|
7042
|
-
console.warn('Received CallCreatedEvent sent by the current user');
|
|
7043
|
-
return;
|
|
7044
|
-
}
|
|
7045
|
-
store.setPendingCalls((pendingCalls) => [
|
|
7046
|
-
...pendingCalls,
|
|
7047
|
-
new Call({
|
|
7048
|
-
streamClient,
|
|
7049
|
-
type: call.type,
|
|
7050
|
-
id: call.id,
|
|
7051
|
-
metadata: call,
|
|
7052
|
-
members,
|
|
7053
|
-
ringing,
|
|
7054
|
-
clientStore: store,
|
|
7055
|
-
}),
|
|
7056
|
-
]);
|
|
7057
|
-
};
|
|
7058
|
-
};
|
|
7059
|
-
/**
|
|
7060
|
-
* Event handler that watched the delivery of CallAcceptedEvent
|
|
7061
|
-
* Updates the state store and notifies its subscribers that
|
|
7062
|
-
* the given user will be joining the call.
|
|
7063
|
-
*/
|
|
7064
|
-
const watchCallAccepted = (store) => {
|
|
7065
|
-
return function onCallAccepted(event) {
|
|
7066
|
-
if (event.type !== 'call.accepted') {
|
|
7067
|
-
return;
|
|
7068
|
-
}
|
|
7069
|
-
const { call_cid } = event;
|
|
7070
|
-
if (!call_cid) {
|
|
7071
|
-
console.warn("Can't find call_cid in CallAcceptedEvent");
|
|
7072
|
-
return;
|
|
7073
|
-
}
|
|
7074
|
-
const acceptedIncomingCall = store.incomingCalls.find((incomingCall) => incomingCall.cid === call_cid);
|
|
7075
|
-
if (acceptedIncomingCall) {
|
|
7076
|
-
console.warn('Received CallAcceptedEvent for an incoming call');
|
|
7077
|
-
return;
|
|
7078
|
-
}
|
|
7079
|
-
const acceptedOutgoingCall = store.outgoingCalls.find((outgoingCall) => outgoingCall.cid === call_cid);
|
|
7080
|
-
const activeCall = store.activeCall;
|
|
7081
|
-
// FIXME OL: we should revisit this logic, it is hard to follow
|
|
7082
|
-
const acceptedActiveCall = (activeCall === null || activeCall === void 0 ? void 0 : activeCall.cid) !== undefined && activeCall.cid === call_cid
|
|
7083
|
-
? activeCall
|
|
7084
|
-
: undefined;
|
|
7085
|
-
if (!acceptedOutgoingCall && !acceptedActiveCall) {
|
|
7086
|
-
console.warn(`CallAcceptedEvent received for a non-existent outgoing call (CID: ${call_cid}`);
|
|
7087
|
-
return;
|
|
7088
|
-
}
|
|
7089
|
-
// once in active call, it is unnecessary to keep track of accepted call events
|
|
7090
|
-
if (call_cid === (acceptedActiveCall === null || acceptedActiveCall === void 0 ? void 0 : acceptedActiveCall.cid)) {
|
|
7091
|
-
return;
|
|
7092
|
-
}
|
|
7093
|
-
// do not set a new accepted call while in an active call? It would lead to joining a new active call.
|
|
7094
|
-
// todo: solve the situation of 2nd outgoing call being accepted in the UI SDK
|
|
7095
|
-
store.setAcceptedCall(event);
|
|
7096
|
-
};
|
|
7097
|
-
};
|
|
7098
|
-
/**
|
|
7099
|
-
* Event handler that watches delivery of CallRejected Websocket event.
|
|
7100
|
-
* Updates the state store and notifies its subscribers that
|
|
7101
|
-
* the given user will not be joining the call.
|
|
7102
|
-
*/
|
|
7103
|
-
const watchCallRejected = (store) => {
|
|
7104
|
-
return function onCallRejected(event) {
|
|
7105
|
-
if (event.type !== 'call.rejected') {
|
|
7106
|
-
return;
|
|
7107
|
-
}
|
|
7108
|
-
const { call_cid } = event;
|
|
7109
|
-
if (!call_cid) {
|
|
7110
|
-
console.warn("Can't find call_cid in CallRejectedEvent");
|
|
7111
|
-
return;
|
|
7112
|
-
}
|
|
7113
|
-
const rejectedIncomingCall = store.incomingCalls.find((incomingCall) => incomingCall.cid === call_cid);
|
|
7114
|
-
if (rejectedIncomingCall) {
|
|
7115
|
-
console.warn('Received CallRejectedEvent for an incoming call');
|
|
7116
|
-
return;
|
|
7117
|
-
}
|
|
7118
|
-
const rejectedOutgoingCall = store.outgoingCalls.find((outgoingCall) => outgoingCall.cid === call_cid);
|
|
7119
|
-
const activeCall = store.activeCall;
|
|
7120
|
-
const rejectedActiveCall = (activeCall === null || activeCall === void 0 ? void 0 : activeCall.cid) !== undefined && activeCall.cid === call_cid
|
|
7121
|
-
? activeCall
|
|
7122
|
-
: undefined;
|
|
7123
|
-
if (!rejectedOutgoingCall && !rejectedActiveCall) {
|
|
7124
|
-
console.warn(`CallRejectedEvent received for a non-existent outgoing call (CID: ${call_cid}`);
|
|
7125
|
-
return;
|
|
7126
|
-
}
|
|
7127
|
-
// FIXME: we should remove the call from pending once every callee has rejected, but for now we support only 1:1 ring calls
|
|
7128
|
-
store.setPendingCalls((pendingCalls) => pendingCalls.filter((pendingCall) => pendingCall.cid !== call_cid));
|
|
7129
|
-
};
|
|
7130
|
-
};
|
|
7131
|
-
/**
|
|
7132
|
-
* Event handler that watches the delivery of CallEndedEvent
|
|
7133
|
-
* Updates the state store and notifies its subscribers that
|
|
7134
|
-
* the call is now considered terminated.
|
|
7135
|
-
*/
|
|
7136
|
-
const watchCallCancelled = (store) => {
|
|
7137
|
-
return function onCallCancelled(event) {
|
|
7138
|
-
if (event.type !== 'call.ended') {
|
|
7139
|
-
return;
|
|
7140
|
-
}
|
|
7141
|
-
const { call_cid } = event;
|
|
7142
|
-
if (!call_cid) {
|
|
7143
|
-
console.log("Can't find call in CallEndedEvent");
|
|
7144
|
-
return;
|
|
7145
|
-
}
|
|
7146
|
-
const cancelledIncomingCall = store.incomingCalls.find((incomingCall) => incomingCall.cid === call_cid);
|
|
7147
|
-
const activeCall = store.activeCall;
|
|
7148
|
-
const cancelledActiveCall = (activeCall === null || activeCall === void 0 ? void 0 : activeCall.cid) !== undefined && activeCall.cid === call_cid
|
|
7149
|
-
? activeCall
|
|
7150
|
-
: undefined;
|
|
7151
|
-
if (!cancelledIncomingCall && !cancelledActiveCall) {
|
|
7152
|
-
console.warn(`CallEndedEvent received for a non-existent incoming call (CID: ${call_cid}`);
|
|
7153
|
-
return;
|
|
7154
|
-
}
|
|
7155
|
-
store.setPendingCalls((pendingCalls) => pendingCalls.filter((pendingCall) => pendingCall.cid !== call_cid));
|
|
7156
|
-
};
|
|
7157
|
-
};
|
|
7158
|
-
|
|
7159
|
-
/**
|
|
7160
|
-
* Event handler that watches for `call.permission_request` events
|
|
7161
|
-
* Updates the state store using the `callPermissionRequest$` stream
|
|
7162
|
-
*/
|
|
7163
|
-
const watchCallPermissionRequest = (store) => {
|
|
7164
|
-
return function onCallPermissionRequest(event) {
|
|
7165
|
-
if (event.type !== 'call.permission_request') {
|
|
7166
|
-
return;
|
|
7167
|
-
}
|
|
7168
|
-
const activeCall = store.activeCall;
|
|
7169
|
-
if (!activeCall) {
|
|
7170
|
-
console.warn(`Ignoring "call.permission_request" as there is no active call`, event);
|
|
7171
|
-
return;
|
|
7172
|
-
}
|
|
7173
|
-
if (activeCall.cid !== event.call_cid) {
|
|
7174
|
-
console.warn(`Ignoring "call.permission_request" as it doesn't belong to the active call`, event);
|
|
7175
|
-
return;
|
|
7176
|
-
}
|
|
7177
|
-
const state = activeCall.state;
|
|
7178
|
-
const localParticipant = state.localParticipant;
|
|
7179
|
-
if (!(localParticipant === null || localParticipant === void 0 ? void 0 : localParticipant.ownCapabilities.includes('update-call-permissions'))) {
|
|
7180
|
-
console.warn(`Ignoring "call.permission_request" as the user doesn't have permission to handle it`);
|
|
7181
|
-
return;
|
|
7182
|
-
}
|
|
7183
|
-
state.setCallPermissionRequest(event);
|
|
7184
|
-
};
|
|
7185
|
-
};
|
|
7186
|
-
/**
|
|
7187
|
-
* Event handler that watches for `call.permissions_updated` events
|
|
7188
|
-
* It will update the `localParticipant$` or `remoteParticipants$` based on whose permissions were changed.
|
|
7189
|
-
*/
|
|
7190
|
-
const watchCallPermissionsUpdated = (store) => {
|
|
7191
|
-
return function onCallPermissionsUpdated(event) {
|
|
7192
|
-
if (event.type !== 'call.permissions_updated') {
|
|
7193
|
-
return;
|
|
7194
|
-
}
|
|
7195
|
-
const activeCall = store.activeCall;
|
|
7196
|
-
if (!activeCall) {
|
|
7197
|
-
console.warn(`Ignoring "call.permissions_updated" as there is no active call`, event);
|
|
7198
|
-
return;
|
|
7199
|
-
}
|
|
7200
|
-
if (activeCall.cid !== event.call_cid) {
|
|
7201
|
-
console.warn(`Ignoring "call.permissions_updated" as it doesn't belong to the active call`, event);
|
|
7202
|
-
return;
|
|
7203
|
-
}
|
|
7204
|
-
const state = activeCall.state;
|
|
7205
|
-
const localParticipant = state.localParticipant;
|
|
7206
|
-
if (event.user.id === (localParticipant === null || localParticipant === void 0 ? void 0 : localParticipant.userId)) {
|
|
7207
|
-
state.updateParticipant(localParticipant.sessionId, {
|
|
7208
|
-
ownCapabilities: event.own_capabilities,
|
|
7209
|
-
});
|
|
7210
|
-
}
|
|
7211
|
-
// TODO: update remote participant once SFU includes that info in the participant data model
|
|
7212
|
-
};
|
|
7213
|
-
};
|
|
7214
|
-
|
|
7215
|
-
/**
|
|
7216
|
-
* Watches the delivery of CallReactionEvent.
|
|
7217
|
-
*
|
|
7218
|
-
* @param store the state store to update.
|
|
7219
|
-
*/
|
|
7220
|
-
const watchNewReactions = (store) => {
|
|
7221
|
-
return function onNewReactions(event) {
|
|
7222
|
-
if (event.type !== 'call.reaction_new') {
|
|
7223
|
-
return;
|
|
7224
|
-
}
|
|
7225
|
-
const { call_cid, reaction } = event;
|
|
7226
|
-
const activeCall = store.activeCall;
|
|
7227
|
-
if (!activeCall || activeCall.cid !== call_cid) {
|
|
7228
|
-
console.warn('Received CallReactionEvent for an inactive or unknown call');
|
|
7229
|
-
return;
|
|
7230
|
-
}
|
|
7231
|
-
const state = activeCall.state;
|
|
7232
|
-
const { user, custom, type, emoji_code } = reaction;
|
|
7233
|
-
state.setParticipants((participants) => {
|
|
7234
|
-
return participants.map((p) => {
|
|
7235
|
-
// skip if the reaction is not for this participant
|
|
7236
|
-
if (p.userId !== user.id)
|
|
7237
|
-
return p;
|
|
7238
|
-
// skip if the reaction is not for this session
|
|
7239
|
-
if (custom.sessionId && p.sessionId !== custom.sessionId)
|
|
7240
|
-
return p;
|
|
7241
|
-
// update the participant with the new reaction
|
|
7242
|
-
return Object.assign(Object.assign({}, p), { reaction: {
|
|
7243
|
-
type,
|
|
7244
|
-
emoji_code,
|
|
7245
|
-
custom,
|
|
7246
|
-
} });
|
|
7247
|
-
});
|
|
7248
|
-
});
|
|
7249
|
-
};
|
|
7250
|
-
};
|
|
7251
|
-
|
|
7252
|
-
/**
|
|
7253
|
-
* Watches for `call.recording_started` events.
|
|
7254
|
-
*/
|
|
7255
|
-
const watchCallRecordingStarted = (store) => {
|
|
7256
|
-
return function onCallRecordingStarted(event) {
|
|
7257
|
-
if (event.type !== 'call.recording_started') {
|
|
7258
|
-
return;
|
|
7259
|
-
}
|
|
7260
|
-
const { call_cid } = event;
|
|
7261
|
-
const activeCall = store.activeCall;
|
|
7262
|
-
if (!activeCall || activeCall.cid !== call_cid) {
|
|
7263
|
-
console.warn('Received CallRecordingStartedEvent for a non-active call');
|
|
7264
|
-
return;
|
|
7265
|
-
}
|
|
7266
|
-
const state = activeCall.state;
|
|
7267
|
-
state.setCallRecordingInProgress(true);
|
|
7268
|
-
};
|
|
7269
|
-
};
|
|
7270
|
-
/**
|
|
7271
|
-
* Watches for `call.recording_stopped` events.
|
|
7272
|
-
*/
|
|
7273
|
-
const watchCallRecordingStopped = (store) => {
|
|
7274
|
-
return function onCallRecordingStopped(event) {
|
|
7275
|
-
if (event.type !== 'call.recording_stopped') {
|
|
7276
|
-
return;
|
|
7369
|
+
off(eventName, fn) {
|
|
7370
|
+
if (isSfuEvent(eventName)) {
|
|
7371
|
+
return this.dispatcher.off(eventName, fn);
|
|
7277
7372
|
}
|
|
7278
|
-
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
7373
|
+
else {
|
|
7374
|
+
const registeredEventHandler = this.streamClientEventHandlers.get(fn);
|
|
7375
|
+
if (registeredEventHandler) {
|
|
7376
|
+
return this.streamClient.off(eventName, registeredEventHandler);
|
|
7377
|
+
}
|
|
7283
7378
|
}
|
|
7284
|
-
const state = activeCall.state;
|
|
7285
|
-
state.setCallRecordingInProgress(false);
|
|
7286
|
-
};
|
|
7287
|
-
};
|
|
7288
|
-
|
|
7289
|
-
/**
|
|
7290
|
-
* Event handler that watches for `call.blocked_user` events,
|
|
7291
|
-
* updates the call store `blocked_user_ids` property by adding
|
|
7292
|
-
* `event.user_id` to the list
|
|
7293
|
-
*/
|
|
7294
|
-
const watchBlockedUser = (store) => (event) => {
|
|
7295
|
-
var _a;
|
|
7296
|
-
if (event.type !== 'call.blocked_user') {
|
|
7297
|
-
return;
|
|
7298
|
-
}
|
|
7299
|
-
const activeCall = store.activeCall;
|
|
7300
|
-
if (!activeCall || activeCall.cid !== event.call_cid) {
|
|
7301
|
-
console.warn(`Received "call.blocked_user" for an inactive or unknown call`, event);
|
|
7302
|
-
return;
|
|
7303
|
-
}
|
|
7304
|
-
const state = activeCall.state;
|
|
7305
|
-
// FIXME: end call
|
|
7306
|
-
if (((_a = state.localParticipant) === null || _a === void 0 ? void 0 : _a.userId) === event.user.id) {
|
|
7307
|
-
activeCall.leave();
|
|
7308
|
-
}
|
|
7309
|
-
state.setMetadata((metadata) => (Object.assign(Object.assign({}, metadata), { blocked_user_ids: [...metadata.blocked_user_ids, event.user.id] })));
|
|
7310
|
-
};
|
|
7311
|
-
/**
|
|
7312
|
-
* Event handler that watches for `call.unblocked_user` events,
|
|
7313
|
-
* updates the call store `blocked_user_ids` property by
|
|
7314
|
-
* removing `event.user_id` from the list
|
|
7315
|
-
*/
|
|
7316
|
-
const watchUnblockedUser = (store) => (event) => {
|
|
7317
|
-
if (event.type !== 'call.unblocked_user') {
|
|
7318
|
-
return;
|
|
7319
7379
|
}
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
console.warn(`Received "call.unblocked_user" for an inactive or unknown call`, event);
|
|
7323
|
-
return;
|
|
7380
|
+
get data() {
|
|
7381
|
+
return this.state.metadata;
|
|
7324
7382
|
}
|
|
7325
|
-
|
|
7326
|
-
state.setMetadata((metadata) => {
|
|
7327
|
-
const blocked_user_ids = metadata.blocked_user_ids.filter((userId) => event.user.id !== userId);
|
|
7328
|
-
return Object.assign(Object.assign({}, metadata), { blocked_user_ids });
|
|
7329
|
-
});
|
|
7330
|
-
};
|
|
7383
|
+
}
|
|
7331
7384
|
|
|
7332
7385
|
var https = null;
|
|
7333
7386
|
|
|
@@ -8943,7 +8996,7 @@ class StreamClient {
|
|
|
8943
8996
|
}
|
|
8944
8997
|
getUserAgent() {
|
|
8945
8998
|
return (this.userAgent ||
|
|
8946
|
-
`stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.1-alpha.
|
|
8999
|
+
`stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.1-alpha.92"}`);
|
|
8947
9000
|
}
|
|
8948
9001
|
setUserAgent(userAgent) {
|
|
8949
9002
|
this.userAgent = userAgent;
|
|
@@ -9003,17 +9056,31 @@ class StreamVideoClient {
|
|
|
9003
9056
|
yield this.streamClient.connectUser(
|
|
9004
9057
|
// @ts-expect-error
|
|
9005
9058
|
user, tokenOrProvider);
|
|
9006
|
-
|
|
9059
|
+
// FIXME: OL: unregister the event listeners.
|
|
9060
|
+
this.on('call.created', (event) => {
|
|
9061
|
+
if (event.type !== 'call.created')
|
|
9062
|
+
return;
|
|
9063
|
+
const { call, members, ringing } = event;
|
|
9064
|
+
if (user.id === call.created_by.id) {
|
|
9065
|
+
console.warn('Received CallCreatedEvent sent by the current user');
|
|
9066
|
+
return;
|
|
9067
|
+
}
|
|
9068
|
+
this.writeableStateStore.setPendingCalls((pendingCalls) => [
|
|
9069
|
+
...pendingCalls,
|
|
9070
|
+
new Call({
|
|
9071
|
+
streamClient: this.streamClient,
|
|
9072
|
+
type: call.type,
|
|
9073
|
+
id: call.id,
|
|
9074
|
+
metadata: call,
|
|
9075
|
+
members,
|
|
9076
|
+
ringing,
|
|
9077
|
+
clientStore: this.writeableStateStore,
|
|
9078
|
+
}),
|
|
9079
|
+
]);
|
|
9080
|
+
});
|
|
9007
9081
|
this.on('call.accepted', watchCallAccepted(this.writeableStateStore));
|
|
9008
9082
|
this.on('call.rejected', watchCallRejected(this.writeableStateStore));
|
|
9009
9083
|
this.on('call.ended', watchCallCancelled(this.writeableStateStore));
|
|
9010
|
-
this.on('call.permission_request', watchCallPermissionRequest(this.writeableStateStore));
|
|
9011
|
-
this.on('call.permissions_updated', watchCallPermissionsUpdated(this.writeableStateStore));
|
|
9012
|
-
this.on('call.blocked_user', watchBlockedUser(this.writeableStateStore));
|
|
9013
|
-
this.on('call.unblocked_user', watchUnblockedUser(this.writeableStateStore));
|
|
9014
|
-
this.on('call.recording_started', watchCallRecordingStarted(this.writeableStateStore));
|
|
9015
|
-
this.on('call.recording_stopped', watchCallRecordingStopped(this.writeableStateStore));
|
|
9016
|
-
this.on('call.reaction_new', watchNewReactions(this.writeableStateStore));
|
|
9017
9084
|
this.writeableStateStore.setConnectedUser(user);
|
|
9018
9085
|
});
|
|
9019
9086
|
/**
|