@stream-io/video-client 0.1.10 → 0.2.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 +260 -28
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +260 -28
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +260 -28
- package/dist/index.es.js.map +1 -1
- package/dist/src/Call.d.ts +27 -6
- package/dist/src/events/internal.d.ts +6 -0
- package/dist/src/gen/coordinator/index.d.ts +115 -0
- package/dist/src/gen/video/sfu/event/events.d.ts +31 -1
- package/dist/src/gen/video/sfu/models/models.d.ts +34 -0
- package/dist/src/store/CallState.d.ts +7 -0
- package/dist/src/types.d.ts +16 -2
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/Call.ts +69 -10
- package/src/events/callEventHandlers.ts +2 -0
- package/src/events/internal.ts +13 -0
- package/src/gen/coordinator/index.ts +115 -0
- package/src/gen/video/sfu/event/events.ts +131 -0
- package/src/gen/video/sfu/models/models.ts +122 -1
- package/src/rtc/Dispatcher.ts +1 -0
- package/src/rtc/__tests__/videoLayers.test.ts +22 -0
- package/src/rtc/flows/join.ts +2 -8
- package/src/sorting/__tests__/participant-data.ts +4 -1
- package/src/sorting/participants.ts +7 -5
- package/src/store/CallState.ts +43 -2
- package/src/store/__tests__/CallState.test.ts +133 -78
- package/src/types.ts +18 -2
package/dist/index.es.js
CHANGED
|
@@ -50,6 +50,7 @@ const OwnCapability = {
|
|
|
50
50
|
JOIN_CALL: 'join-call',
|
|
51
51
|
JOIN_ENDED_CALL: 'join-ended-call',
|
|
52
52
|
MUTE_USERS: 'mute-users',
|
|
53
|
+
PIN_FOR_EVERYONE: 'pin-for-everyone',
|
|
53
54
|
READ_CALL: 'read-call',
|
|
54
55
|
REMOVE_CALL_MEMBER: 'remove-call-member',
|
|
55
56
|
SCREENSHARE: 'screenshare',
|
|
@@ -974,10 +975,17 @@ class CallState$Type extends MessageType {
|
|
|
974
975
|
kind: 'message',
|
|
975
976
|
T: () => ParticipantCount,
|
|
976
977
|
},
|
|
978
|
+
{
|
|
979
|
+
no: 4,
|
|
980
|
+
name: 'pins',
|
|
981
|
+
kind: 'message',
|
|
982
|
+
repeat: 1 /*RepeatType.PACKED*/,
|
|
983
|
+
T: () => Pin,
|
|
984
|
+
},
|
|
977
985
|
]);
|
|
978
986
|
}
|
|
979
987
|
create(value) {
|
|
980
|
-
const message = { participants: [] };
|
|
988
|
+
const message = { participants: [], pins: [] };
|
|
981
989
|
globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
|
|
982
990
|
enumerable: false,
|
|
983
991
|
value: this,
|
|
@@ -1000,6 +1008,9 @@ class CallState$Type extends MessageType {
|
|
|
1000
1008
|
case /* stream.video.sfu.models.ParticipantCount participant_count */ 3:
|
|
1001
1009
|
message.participantCount = ParticipantCount.internalBinaryRead(reader, reader.uint32(), options, message.participantCount);
|
|
1002
1010
|
break;
|
|
1011
|
+
case /* repeated stream.video.sfu.models.Pin pins */ 4:
|
|
1012
|
+
message.pins.push(Pin.internalBinaryRead(reader, reader.uint32(), options));
|
|
1013
|
+
break;
|
|
1003
1014
|
default:
|
|
1004
1015
|
let u = options.readUnknownField;
|
|
1005
1016
|
if (u === 'throw')
|
|
@@ -1021,6 +1032,9 @@ class CallState$Type extends MessageType {
|
|
|
1021
1032
|
/* stream.video.sfu.models.ParticipantCount participant_count = 3; */
|
|
1022
1033
|
if (message.participantCount)
|
|
1023
1034
|
ParticipantCount.internalBinaryWrite(message.participantCount, writer.tag(3, WireType.LengthDelimited).fork(), options).join();
|
|
1035
|
+
/* repeated stream.video.sfu.models.Pin pins = 4; */
|
|
1036
|
+
for (let i = 0; i < message.pins.length; i++)
|
|
1037
|
+
Pin.internalBinaryWrite(message.pins[i], writer.tag(4, WireType.LengthDelimited).fork(), options).join();
|
|
1024
1038
|
let u = options.writeUnknownFields;
|
|
1025
1039
|
if (u !== false)
|
|
1026
1040
|
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
@@ -1089,6 +1103,63 @@ class ParticipantCount$Type extends MessageType {
|
|
|
1089
1103
|
*/
|
|
1090
1104
|
const ParticipantCount = new ParticipantCount$Type();
|
|
1091
1105
|
// @generated message type with reflection information, may provide speed optimized methods
|
|
1106
|
+
class Pin$Type extends MessageType {
|
|
1107
|
+
constructor() {
|
|
1108
|
+
super('stream.video.sfu.models.Pin', [
|
|
1109
|
+
{ no: 1, name: 'user_id', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
|
|
1110
|
+
{ no: 2, name: 'session_id', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
|
|
1111
|
+
]);
|
|
1112
|
+
}
|
|
1113
|
+
create(value) {
|
|
1114
|
+
const message = { userId: '', sessionId: '' };
|
|
1115
|
+
globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
|
|
1116
|
+
enumerable: false,
|
|
1117
|
+
value: this,
|
|
1118
|
+
});
|
|
1119
|
+
if (value !== undefined)
|
|
1120
|
+
reflectionMergePartial(this, message, value);
|
|
1121
|
+
return message;
|
|
1122
|
+
}
|
|
1123
|
+
internalBinaryRead(reader, length, options, target) {
|
|
1124
|
+
let message = target !== null && target !== void 0 ? target : this.create(), end = reader.pos + length;
|
|
1125
|
+
while (reader.pos < end) {
|
|
1126
|
+
let [fieldNo, wireType] = reader.tag();
|
|
1127
|
+
switch (fieldNo) {
|
|
1128
|
+
case /* string user_id */ 1:
|
|
1129
|
+
message.userId = reader.string();
|
|
1130
|
+
break;
|
|
1131
|
+
case /* string session_id */ 2:
|
|
1132
|
+
message.sessionId = reader.string();
|
|
1133
|
+
break;
|
|
1134
|
+
default:
|
|
1135
|
+
let u = options.readUnknownField;
|
|
1136
|
+
if (u === 'throw')
|
|
1137
|
+
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
|
1138
|
+
let d = reader.skip(wireType);
|
|
1139
|
+
if (u !== false)
|
|
1140
|
+
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
return message;
|
|
1144
|
+
}
|
|
1145
|
+
internalBinaryWrite(message, writer, options) {
|
|
1146
|
+
/* string user_id = 1; */
|
|
1147
|
+
if (message.userId !== '')
|
|
1148
|
+
writer.tag(1, WireType.LengthDelimited).string(message.userId);
|
|
1149
|
+
/* string session_id = 2; */
|
|
1150
|
+
if (message.sessionId !== '')
|
|
1151
|
+
writer.tag(2, WireType.LengthDelimited).string(message.sessionId);
|
|
1152
|
+
let u = options.writeUnknownFields;
|
|
1153
|
+
if (u !== false)
|
|
1154
|
+
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
1155
|
+
return writer;
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
/**
|
|
1159
|
+
* @generated MessageType for protobuf message stream.video.sfu.models.Pin
|
|
1160
|
+
*/
|
|
1161
|
+
const Pin = new Pin$Type();
|
|
1162
|
+
// @generated message type with reflection information, may provide speed optimized methods
|
|
1092
1163
|
class Participant$Type extends MessageType {
|
|
1093
1164
|
constructor() {
|
|
1094
1165
|
super('stream.video.sfu.models.Participant', [
|
|
@@ -2403,6 +2474,7 @@ var models = /*#__PURE__*/Object.freeze({
|
|
|
2403
2474
|
Participant: Participant,
|
|
2404
2475
|
ParticipantCount: ParticipantCount,
|
|
2405
2476
|
get PeerType () { return PeerType; },
|
|
2477
|
+
Pin: Pin,
|
|
2406
2478
|
Sdk: Sdk,
|
|
2407
2479
|
get SdkType () { return SdkType; },
|
|
2408
2480
|
StreamQuality: StreamQuality,
|
|
@@ -3494,6 +3566,13 @@ class SfuEvent$Type extends MessageType {
|
|
|
3494
3566
|
oneof: 'eventPayload',
|
|
3495
3567
|
T: () => ICERestart,
|
|
3496
3568
|
},
|
|
3569
|
+
{
|
|
3570
|
+
no: 22,
|
|
3571
|
+
name: 'pins_updated',
|
|
3572
|
+
kind: 'message',
|
|
3573
|
+
oneof: 'eventPayload',
|
|
3574
|
+
T: () => PinsChanged,
|
|
3575
|
+
},
|
|
3497
3576
|
]);
|
|
3498
3577
|
}
|
|
3499
3578
|
create(value) {
|
|
@@ -3613,6 +3692,12 @@ class SfuEvent$Type extends MessageType {
|
|
|
3613
3692
|
iceRestart: ICERestart.internalBinaryRead(reader, reader.uint32(), options, message.eventPayload.iceRestart),
|
|
3614
3693
|
};
|
|
3615
3694
|
break;
|
|
3695
|
+
case /* stream.video.sfu.event.PinsChanged pins_updated */ 22:
|
|
3696
|
+
message.eventPayload = {
|
|
3697
|
+
oneofKind: 'pinsUpdated',
|
|
3698
|
+
pinsUpdated: PinsChanged.internalBinaryRead(reader, reader.uint32(), options, message.eventPayload.pinsUpdated),
|
|
3699
|
+
};
|
|
3700
|
+
break;
|
|
3616
3701
|
default:
|
|
3617
3702
|
let u = options.readUnknownField;
|
|
3618
3703
|
if (u === 'throw')
|
|
@@ -3676,6 +3761,9 @@ class SfuEvent$Type extends MessageType {
|
|
|
3676
3761
|
/* stream.video.sfu.event.ICERestart ice_restart = 21; */
|
|
3677
3762
|
if (message.eventPayload.oneofKind === 'iceRestart')
|
|
3678
3763
|
ICERestart.internalBinaryWrite(message.eventPayload.iceRestart, writer.tag(21, WireType.LengthDelimited).fork(), options).join();
|
|
3764
|
+
/* stream.video.sfu.event.PinsChanged pins_updated = 22; */
|
|
3765
|
+
if (message.eventPayload.oneofKind === 'pinsUpdated')
|
|
3766
|
+
PinsChanged.internalBinaryWrite(message.eventPayload.pinsUpdated, writer.tag(22, WireType.LengthDelimited).fork(), options).join();
|
|
3679
3767
|
let u = options.writeUnknownFields;
|
|
3680
3768
|
if (u !== false)
|
|
3681
3769
|
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
@@ -3687,6 +3775,62 @@ class SfuEvent$Type extends MessageType {
|
|
|
3687
3775
|
*/
|
|
3688
3776
|
const SfuEvent = new SfuEvent$Type();
|
|
3689
3777
|
// @generated message type with reflection information, may provide speed optimized methods
|
|
3778
|
+
class PinsChanged$Type extends MessageType {
|
|
3779
|
+
constructor() {
|
|
3780
|
+
super('stream.video.sfu.event.PinsChanged', [
|
|
3781
|
+
{
|
|
3782
|
+
no: 1,
|
|
3783
|
+
name: 'pins',
|
|
3784
|
+
kind: 'message',
|
|
3785
|
+
repeat: 1 /*RepeatType.PACKED*/,
|
|
3786
|
+
T: () => Pin,
|
|
3787
|
+
},
|
|
3788
|
+
]);
|
|
3789
|
+
}
|
|
3790
|
+
create(value) {
|
|
3791
|
+
const message = { pins: [] };
|
|
3792
|
+
globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
|
|
3793
|
+
enumerable: false,
|
|
3794
|
+
value: this,
|
|
3795
|
+
});
|
|
3796
|
+
if (value !== undefined)
|
|
3797
|
+
reflectionMergePartial(this, message, value);
|
|
3798
|
+
return message;
|
|
3799
|
+
}
|
|
3800
|
+
internalBinaryRead(reader, length, options, target) {
|
|
3801
|
+
let message = target !== null && target !== void 0 ? target : this.create(), end = reader.pos + length;
|
|
3802
|
+
while (reader.pos < end) {
|
|
3803
|
+
let [fieldNo, wireType] = reader.tag();
|
|
3804
|
+
switch (fieldNo) {
|
|
3805
|
+
case /* repeated stream.video.sfu.models.Pin pins */ 1:
|
|
3806
|
+
message.pins.push(Pin.internalBinaryRead(reader, reader.uint32(), options));
|
|
3807
|
+
break;
|
|
3808
|
+
default:
|
|
3809
|
+
let u = options.readUnknownField;
|
|
3810
|
+
if (u === 'throw')
|
|
3811
|
+
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
|
3812
|
+
let d = reader.skip(wireType);
|
|
3813
|
+
if (u !== false)
|
|
3814
|
+
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
|
3815
|
+
}
|
|
3816
|
+
}
|
|
3817
|
+
return message;
|
|
3818
|
+
}
|
|
3819
|
+
internalBinaryWrite(message, writer, options) {
|
|
3820
|
+
/* repeated stream.video.sfu.models.Pin pins = 1; */
|
|
3821
|
+
for (let i = 0; i < message.pins.length; i++)
|
|
3822
|
+
Pin.internalBinaryWrite(message.pins[i], writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
|
3823
|
+
let u = options.writeUnknownFields;
|
|
3824
|
+
if (u !== false)
|
|
3825
|
+
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
3826
|
+
return writer;
|
|
3827
|
+
}
|
|
3828
|
+
}
|
|
3829
|
+
/**
|
|
3830
|
+
* @generated MessageType for protobuf message stream.video.sfu.event.PinsChanged
|
|
3831
|
+
*/
|
|
3832
|
+
const PinsChanged = new PinsChanged$Type();
|
|
3833
|
+
// @generated message type with reflection information, may provide speed optimized methods
|
|
3690
3834
|
class Error$Type extends MessageType {
|
|
3691
3835
|
constructor() {
|
|
3692
3836
|
super('stream.video.sfu.event.Error', [
|
|
@@ -5549,6 +5693,7 @@ var events = /*#__PURE__*/Object.freeze({
|
|
|
5549
5693
|
Migration: Migration,
|
|
5550
5694
|
ParticipantJoined: ParticipantJoined,
|
|
5551
5695
|
ParticipantLeft: ParticipantLeft,
|
|
5696
|
+
PinsChanged: PinsChanged,
|
|
5552
5697
|
PublisherAnswer: PublisherAnswer,
|
|
5553
5698
|
SfuEvent: SfuEvent,
|
|
5554
5699
|
SfuRequest: SfuRequest,
|
|
@@ -6041,6 +6186,7 @@ const sfuEventKinds = {
|
|
|
6041
6186
|
callGrantsUpdated: undefined,
|
|
6042
6187
|
goAway: undefined,
|
|
6043
6188
|
iceRestart: undefined,
|
|
6189
|
+
pinsUpdated: undefined,
|
|
6044
6190
|
};
|
|
6045
6191
|
const isSfuEvent = (eventName) => {
|
|
6046
6192
|
return Object.prototype.hasOwnProperty.call(sfuEventKinds, eventName);
|
|
@@ -7693,15 +7839,19 @@ const publishingAudio = (a, b) => {
|
|
|
7693
7839
|
* @param b the second participant.
|
|
7694
7840
|
*/
|
|
7695
7841
|
const pinned = (a, b) => {
|
|
7696
|
-
if (a.
|
|
7697
|
-
if (a.
|
|
7842
|
+
if (a.pin && b.pin) {
|
|
7843
|
+
if (!a.pin.isLocalPin && b.pin.isLocalPin)
|
|
7844
|
+
return -1;
|
|
7845
|
+
if (a.pin.isLocalPin && !b.pin.isLocalPin)
|
|
7846
|
+
return 1;
|
|
7847
|
+
if (a.pin.pinnedAt > b.pin.pinnedAt)
|
|
7698
7848
|
return -1;
|
|
7699
|
-
if (a.pinnedAt < b.pinnedAt)
|
|
7849
|
+
if (a.pin.pinnedAt < b.pin.pinnedAt)
|
|
7700
7850
|
return 1;
|
|
7701
7851
|
}
|
|
7702
|
-
if (a.
|
|
7852
|
+
if (a.pin && !b.pin)
|
|
7703
7853
|
return -1;
|
|
7704
|
-
if (!a.
|
|
7854
|
+
if (!a.pin && b.pin)
|
|
7705
7855
|
return 1;
|
|
7706
7856
|
return 0;
|
|
7707
7857
|
};
|
|
@@ -8100,11 +8250,39 @@ class CallState {
|
|
|
8100
8250
|
return p;
|
|
8101
8251
|
}));
|
|
8102
8252
|
};
|
|
8253
|
+
/**
|
|
8254
|
+
* Updates the participant pinned state with server side pinning data.
|
|
8255
|
+
*
|
|
8256
|
+
* @param pins the latest pins from the server.
|
|
8257
|
+
*/
|
|
8258
|
+
this.setServerSidePins = (pins) => {
|
|
8259
|
+
const pinsLookup = pins.reduce((lookup, pin) => {
|
|
8260
|
+
lookup[pin.sessionId] = Date.now();
|
|
8261
|
+
return lookup;
|
|
8262
|
+
}, {});
|
|
8263
|
+
return this.setParticipants((participants) => participants.map((participant) => {
|
|
8264
|
+
const serverSidePinnedAt = pinsLookup[participant.sessionId];
|
|
8265
|
+
// the participant is newly pinned
|
|
8266
|
+
if (serverSidePinnedAt) {
|
|
8267
|
+
return Object.assign(Object.assign({}, participant), { pin: {
|
|
8268
|
+
isLocalPin: false,
|
|
8269
|
+
pinnedAt: serverSidePinnedAt,
|
|
8270
|
+
} });
|
|
8271
|
+
}
|
|
8272
|
+
// the participant is no longer pinned server side
|
|
8273
|
+
// we need to reset the pin
|
|
8274
|
+
if (participant.pin && !participant.pin.isLocalPin) {
|
|
8275
|
+
return Object.assign(Object.assign({}, participant), { pin: undefined });
|
|
8276
|
+
}
|
|
8277
|
+
// no changes to be applied
|
|
8278
|
+
return participant;
|
|
8279
|
+
}));
|
|
8280
|
+
};
|
|
8103
8281
|
this.logger = getLogger(['call-state']);
|
|
8104
8282
|
this.participants$ = this.participantsSubject.pipe(map$1((ps) => ps.sort(this.sortParticipantsBy)));
|
|
8105
8283
|
this.localParticipant$ = this.participants$.pipe(map$1((participants) => participants.find(isStreamVideoLocalParticipant)));
|
|
8106
8284
|
this.remoteParticipants$ = this.participants$.pipe(map$1((participants) => participants.filter((p) => !p.isLocalParticipant)));
|
|
8107
|
-
this.pinnedParticipants$ = this.participants$.pipe(map$1((participants) => participants.filter((p) => p.
|
|
8285
|
+
this.pinnedParticipants$ = this.participants$.pipe(map$1((participants) => participants.filter((p) => !!p.pin)));
|
|
8108
8286
|
this.dominantSpeaker$ = this.participants$.pipe(map$1((participants) => participants.find((p) => p.isDominantSpeaker)));
|
|
8109
8287
|
this.hasOngoingScreenShare$ = this.participants$.pipe(map$1((participants) => {
|
|
8110
8288
|
return participants.some((p) => p.publishedTracks.includes(TrackType.SCREEN_SHARE));
|
|
@@ -8417,6 +8595,18 @@ const watchSfuErrorReports = (dispatcher) => {
|
|
|
8417
8595
|
});
|
|
8418
8596
|
});
|
|
8419
8597
|
};
|
|
8598
|
+
/**
|
|
8599
|
+
* Watches for `pinsUpdated` events and updates the pinned state of participants
|
|
8600
|
+
* in the call.
|
|
8601
|
+
*/
|
|
8602
|
+
const watchPinsUpdated = (state) => {
|
|
8603
|
+
return function onPinsUpdated(e) {
|
|
8604
|
+
if (e.eventPayload.oneofKind !== 'pinsUpdated')
|
|
8605
|
+
return;
|
|
8606
|
+
const { pins } = e.eventPayload.pinsUpdated;
|
|
8607
|
+
state.setServerSidePins(pins);
|
|
8608
|
+
};
|
|
8609
|
+
};
|
|
8420
8610
|
|
|
8421
8611
|
/**
|
|
8422
8612
|
* Watches for `call.member_added` events.
|
|
@@ -8795,6 +8985,7 @@ const registerEventHandlers = (call, state, dispatcher) => {
|
|
|
8795
8985
|
watchAudioLevelChanged(dispatcher, state),
|
|
8796
8986
|
watchDominantSpeakerChanged(dispatcher, state),
|
|
8797
8987
|
call.on('callGrantsUpdated', watchCallGrantsUpdated(state)),
|
|
8988
|
+
call.on('pinsUpdated', watchPinsUpdated(state)),
|
|
8798
8989
|
];
|
|
8799
8990
|
Object.keys(coordinatorEvents).forEach((event) => {
|
|
8800
8991
|
const eventName = event;
|
|
@@ -8900,14 +9091,8 @@ const getCascadingModeParams = () => {
|
|
|
8900
9091
|
const reconcileParticipantLocalState = (target, source) => {
|
|
8901
9092
|
if (!source)
|
|
8902
9093
|
return target;
|
|
8903
|
-
|
|
8904
|
-
target
|
|
8905
|
-
target.screenShareStream = source.screenShareStream;
|
|
8906
|
-
target.videoDimension = source.videoDimension;
|
|
8907
|
-
target.screenShareDimension = source.screenShareDimension;
|
|
8908
|
-
target.pinnedAt = source.pinnedAt;
|
|
8909
|
-
target.reaction = source.reaction;
|
|
8910
|
-
target.viewportVisibilityState = source.viewportVisibilityState;
|
|
9094
|
+
// copy everything from source to target
|
|
9095
|
+
Object.assign(target, source);
|
|
8911
9096
|
if (isStreamVideoLocalParticipant(source) &&
|
|
8912
9097
|
isStreamVideoLocalParticipant(target)) {
|
|
8913
9098
|
target.audioDeviceId = source.audioDeviceId;
|
|
@@ -9590,7 +9775,7 @@ class Call {
|
|
|
9590
9775
|
* @returns a promise which resolves once the call join-flow has finished.
|
|
9591
9776
|
*/
|
|
9592
9777
|
this.join = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
9593
|
-
var _e, _f;
|
|
9778
|
+
var _e, _f, _g;
|
|
9594
9779
|
const callingState = this.state.callingState;
|
|
9595
9780
|
if ([CallingState.JOINED, CallingState.JOINING].includes(callingState)) {
|
|
9596
9781
|
this.logger('warn', 'Join method called twice, you should only call this once');
|
|
@@ -9838,6 +10023,7 @@ class Call {
|
|
|
9838
10023
|
const startedAt = (callState === null || callState === void 0 ? void 0 : callState.startedAt)
|
|
9839
10024
|
? Timestamp.toDate(callState.startedAt)
|
|
9840
10025
|
: new Date();
|
|
10026
|
+
const pins = (_g = callState === null || callState === void 0 ? void 0 : callState.pins) !== null && _g !== void 0 ? _g : [];
|
|
9841
10027
|
this.state.setParticipants(() => {
|
|
9842
10028
|
const participantLookup = this.state.getParticipantLookupBySessionId();
|
|
9843
10029
|
return currentParticipants.map((p) => {
|
|
@@ -9845,7 +10031,7 @@ class Call {
|
|
|
9845
10031
|
isLocalParticipant: p.sessionId === sfuClient.sessionId,
|
|
9846
10032
|
viewportVisibilityState: VisibilityState.UNKNOWN,
|
|
9847
10033
|
});
|
|
9848
|
-
// We need to preserve
|
|
10034
|
+
// We need to preserve the local state of the participant
|
|
9849
10035
|
// (e.g. videoDimension, visibilityState, pinnedAt, etc.)
|
|
9850
10036
|
// as it doesn't exist on the server.
|
|
9851
10037
|
const existingParticipant = participantLookup[p.sessionId];
|
|
@@ -9855,8 +10041,16 @@ class Call {
|
|
|
9855
10041
|
this.state.setParticipantCount((participantCount === null || participantCount === void 0 ? void 0 : participantCount.total) || 0);
|
|
9856
10042
|
this.state.setAnonymousParticipantCount((participantCount === null || participantCount === void 0 ? void 0 : participantCount.anonymous) || 0);
|
|
9857
10043
|
this.state.setStartedAt(startedAt);
|
|
10044
|
+
this.state.setServerSidePins(pins);
|
|
9858
10045
|
this.reconnectAttempts = 0; // reset the reconnect attempts counter
|
|
9859
10046
|
this.state.setCallingState(CallingState.JOINED);
|
|
10047
|
+
// 3. once we have the "joinResponse", and possibly reconciled the local state
|
|
10048
|
+
// we schedule a fast subscription update for all remote participants
|
|
10049
|
+
// that were visible before we reconnected or migrated to a new SFU.
|
|
10050
|
+
const { remoteParticipants } = this.state;
|
|
10051
|
+
if (remoteParticipants.length > 0) {
|
|
10052
|
+
this.updateSubscriptions(remoteParticipants, DebounceType.FAST);
|
|
10053
|
+
}
|
|
9860
10054
|
this.logger('info', `Joined call ${this.cid}`);
|
|
9861
10055
|
}
|
|
9862
10056
|
catch (err) {
|
|
@@ -9972,9 +10166,9 @@ class Call {
|
|
|
9972
10166
|
* @param trackType the track type to stop publishing.
|
|
9973
10167
|
*/
|
|
9974
10168
|
this.stopPublish = (trackType) => __awaiter(this, void 0, void 0, function* () {
|
|
9975
|
-
var
|
|
10169
|
+
var _h;
|
|
9976
10170
|
this.logger('info', `stopPublish ${TrackType[trackType]}`);
|
|
9977
|
-
yield ((
|
|
10171
|
+
yield ((_h = this.publisher) === null || _h === void 0 ? void 0 : _h.unpublishStream(trackType));
|
|
9978
10172
|
});
|
|
9979
10173
|
/**
|
|
9980
10174
|
* Update track subscription configuration for one or more participants.
|
|
@@ -10062,6 +10256,8 @@ class Call {
|
|
|
10062
10256
|
* @param deviceId the selected device, `undefined` means the user wants to use the system's default audio output
|
|
10063
10257
|
*/
|
|
10064
10258
|
this.setAudioOutputDevice = (deviceId) => {
|
|
10259
|
+
if (!this.sfuClient)
|
|
10260
|
+
return;
|
|
10065
10261
|
this.state.updateParticipant(this.sfuClient.sessionId, {
|
|
10066
10262
|
audioOutputDeviceId: deviceId,
|
|
10067
10263
|
});
|
|
@@ -10075,6 +10271,8 @@ class Call {
|
|
|
10075
10271
|
* @param deviceId the selected device, pass `undefined` to clear the device selection
|
|
10076
10272
|
*/
|
|
10077
10273
|
this.setAudioDevice = (deviceId) => {
|
|
10274
|
+
if (!this.sfuClient)
|
|
10275
|
+
return;
|
|
10078
10276
|
this.state.updateParticipant(this.sfuClient.sessionId, {
|
|
10079
10277
|
audioDeviceId: deviceId,
|
|
10080
10278
|
});
|
|
@@ -10087,6 +10285,8 @@ class Call {
|
|
|
10087
10285
|
* @param deviceId the selected device, pass `undefined` to clear the device selection
|
|
10088
10286
|
*/
|
|
10089
10287
|
this.setVideoDevice = (deviceId) => {
|
|
10288
|
+
if (!this.sfuClient)
|
|
10289
|
+
return;
|
|
10090
10290
|
this.state.updateParticipant(this.sfuClient.sessionId, {
|
|
10091
10291
|
videoDeviceId: deviceId,
|
|
10092
10292
|
});
|
|
@@ -10115,8 +10315,8 @@ class Call {
|
|
|
10115
10315
|
* @returns
|
|
10116
10316
|
*/
|
|
10117
10317
|
this.updatePublishQuality = (enabledRids) => __awaiter(this, void 0, void 0, function* () {
|
|
10118
|
-
var
|
|
10119
|
-
return (
|
|
10318
|
+
var _j;
|
|
10319
|
+
return (_j = this.publisher) === null || _j === void 0 ? void 0 : _j.updateVideoPublishQuality(enabledRids);
|
|
10120
10320
|
});
|
|
10121
10321
|
this.assertCallJoined = () => {
|
|
10122
10322
|
return new Promise((resolve) => {
|
|
@@ -10320,16 +10520,48 @@ class Call {
|
|
|
10320
10520
|
return this.streamClient.post(`${this.streamClientBasePath}/mark_ended`);
|
|
10321
10521
|
});
|
|
10322
10522
|
/**
|
|
10323
|
-
*
|
|
10324
|
-
*
|
|
10325
|
-
* @param
|
|
10326
|
-
|
|
10523
|
+
* Pins the given session to the top of the participants list.
|
|
10524
|
+
*
|
|
10525
|
+
* @param sessionId the sessionId to pin.
|
|
10526
|
+
*/
|
|
10527
|
+
this.pin = (sessionId) => {
|
|
10528
|
+
this.state.updateParticipant(sessionId, {
|
|
10529
|
+
pin: {
|
|
10530
|
+
isLocalPin: true,
|
|
10531
|
+
pinnedAt: Date.now(),
|
|
10532
|
+
},
|
|
10533
|
+
});
|
|
10534
|
+
};
|
|
10535
|
+
/**
|
|
10536
|
+
* Unpins the given session from the top of the participants list.
|
|
10537
|
+
*
|
|
10538
|
+
* @param sessionId the sessionId to unpin.
|
|
10327
10539
|
*/
|
|
10328
|
-
this.
|
|
10540
|
+
this.unpin = (sessionId) => {
|
|
10329
10541
|
this.state.updateParticipant(sessionId, {
|
|
10330
|
-
|
|
10542
|
+
pin: undefined,
|
|
10331
10543
|
});
|
|
10332
10544
|
};
|
|
10545
|
+
/**
|
|
10546
|
+
* Pins the given session to the top of the participants list for everyone
|
|
10547
|
+
* in the call.
|
|
10548
|
+
* You can execute this method only if you have the `pin-for-everyone` capability.
|
|
10549
|
+
*
|
|
10550
|
+
* @param request the request object.
|
|
10551
|
+
*/
|
|
10552
|
+
this.pinForEveryone = (request) => __awaiter(this, void 0, void 0, function* () {
|
|
10553
|
+
return this.streamClient.post(`${this.streamClientBasePath}/pin`, request);
|
|
10554
|
+
});
|
|
10555
|
+
/**
|
|
10556
|
+
* Unpins the given session from the top of the participants list for everyone
|
|
10557
|
+
* in the call.
|
|
10558
|
+
* You can execute this method only if you have the `pin-for-everyone` capability.
|
|
10559
|
+
*
|
|
10560
|
+
* @param request the request object.
|
|
10561
|
+
*/
|
|
10562
|
+
this.unpinForEveryone = (request) => __awaiter(this, void 0, void 0, function* () {
|
|
10563
|
+
return this.streamClient.post(`${this.streamClientBasePath}/unpin`, request);
|
|
10564
|
+
});
|
|
10333
10565
|
/**
|
|
10334
10566
|
* Query call members with filter query. The result won't be stored in call state.
|
|
10335
10567
|
* @param request
|
|
@@ -11648,7 +11880,7 @@ class WSConnectionFallback {
|
|
|
11648
11880
|
}
|
|
11649
11881
|
}
|
|
11650
11882
|
|
|
11651
|
-
const version = '0.
|
|
11883
|
+
const version = '0.2.0';
|
|
11652
11884
|
|
|
11653
11885
|
const logger = getLogger(['location']);
|
|
11654
11886
|
const HINT_URL = `https://hint.stream-io-video.com/`;
|