@stream-io/video-client 0.1.11 → 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 +11 -0
- package/dist/index.browser.es.js +253 -28
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +253 -28
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +253 -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 +60 -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/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
|
@@ -317,6 +317,25 @@ export interface BroadcastSettings {
|
|
|
317
317
|
*/
|
|
318
318
|
hls: HLSSettings;
|
|
319
319
|
}
|
|
320
|
+
/**
|
|
321
|
+
*
|
|
322
|
+
* @export
|
|
323
|
+
* @interface BroadcastSettingsRequest
|
|
324
|
+
*/
|
|
325
|
+
export interface BroadcastSettingsRequest {
|
|
326
|
+
/**
|
|
327
|
+
*
|
|
328
|
+
* @type {boolean}
|
|
329
|
+
* @memberof BroadcastSettingsRequest
|
|
330
|
+
*/
|
|
331
|
+
enabled?: boolean;
|
|
332
|
+
/**
|
|
333
|
+
*
|
|
334
|
+
* @type {HLSSettingsRequest}
|
|
335
|
+
* @memberof BroadcastSettingsRequest
|
|
336
|
+
*/
|
|
337
|
+
hls?: HLSSettingsRequest;
|
|
338
|
+
}
|
|
320
339
|
/**
|
|
321
340
|
* This event is sent when a user accepts a notification to join a call.
|
|
322
341
|
* @export
|
|
@@ -1340,6 +1359,12 @@ export interface CallSettingsRequest {
|
|
|
1340
1359
|
* @memberof CallSettingsRequest
|
|
1341
1360
|
*/
|
|
1342
1361
|
backstage?: BackstageSettingsRequest;
|
|
1362
|
+
/**
|
|
1363
|
+
*
|
|
1364
|
+
* @type {BroadcastSettingsRequest}
|
|
1365
|
+
* @memberof CallSettingsRequest
|
|
1366
|
+
*/
|
|
1367
|
+
broadcasting?: BroadcastSettingsRequest;
|
|
1343
1368
|
/**
|
|
1344
1369
|
*
|
|
1345
1370
|
* @type {GeofenceSettingsRequest}
|
|
@@ -2413,6 +2438,31 @@ export interface HLSSettings {
|
|
|
2413
2438
|
*/
|
|
2414
2439
|
quality_tracks: Array<string>;
|
|
2415
2440
|
}
|
|
2441
|
+
/**
|
|
2442
|
+
*
|
|
2443
|
+
* @export
|
|
2444
|
+
* @interface HLSSettingsRequest
|
|
2445
|
+
*/
|
|
2446
|
+
export interface HLSSettingsRequest {
|
|
2447
|
+
/**
|
|
2448
|
+
*
|
|
2449
|
+
* @type {boolean}
|
|
2450
|
+
* @memberof HLSSettingsRequest
|
|
2451
|
+
*/
|
|
2452
|
+
auto_on?: boolean;
|
|
2453
|
+
/**
|
|
2454
|
+
*
|
|
2455
|
+
* @type {boolean}
|
|
2456
|
+
* @memberof HLSSettingsRequest
|
|
2457
|
+
*/
|
|
2458
|
+
enabled?: boolean;
|
|
2459
|
+
/**
|
|
2460
|
+
*
|
|
2461
|
+
* @type {Array<string>}
|
|
2462
|
+
* @memberof HLSSettingsRequest
|
|
2463
|
+
*/
|
|
2464
|
+
quality_tracks?: Array<string>;
|
|
2465
|
+
}
|
|
2416
2466
|
/**
|
|
2417
2467
|
*
|
|
2418
2468
|
* @export
|
|
@@ -2836,6 +2886,7 @@ export const OwnCapability = {
|
|
|
2836
2886
|
JOIN_CALL: 'join-call',
|
|
2837
2887
|
JOIN_ENDED_CALL: 'join-ended-call',
|
|
2838
2888
|
MUTE_USERS: 'mute-users',
|
|
2889
|
+
PIN_FOR_EVERYONE: 'pin-for-everyone',
|
|
2839
2890
|
READ_CALL: 'read-call',
|
|
2840
2891
|
REMOVE_CALL_MEMBER: 'remove-call-member',
|
|
2841
2892
|
SCREENSHARE: 'screenshare',
|
|
@@ -2959,6 +3010,38 @@ export interface PermissionRequestEvent {
|
|
|
2959
3010
|
*/
|
|
2960
3011
|
user: UserResponse;
|
|
2961
3012
|
}
|
|
3013
|
+
/**
|
|
3014
|
+
*
|
|
3015
|
+
* @export
|
|
3016
|
+
* @interface PinRequest
|
|
3017
|
+
*/
|
|
3018
|
+
export interface PinRequest {
|
|
3019
|
+
/**
|
|
3020
|
+
*
|
|
3021
|
+
* @type {string}
|
|
3022
|
+
* @memberof PinRequest
|
|
3023
|
+
*/
|
|
3024
|
+
session_id: string;
|
|
3025
|
+
/**
|
|
3026
|
+
*
|
|
3027
|
+
* @type {string}
|
|
3028
|
+
* @memberof PinRequest
|
|
3029
|
+
*/
|
|
3030
|
+
user_id: string;
|
|
3031
|
+
}
|
|
3032
|
+
/**
|
|
3033
|
+
*
|
|
3034
|
+
* @export
|
|
3035
|
+
* @interface PinResponse
|
|
3036
|
+
*/
|
|
3037
|
+
export interface PinResponse {
|
|
3038
|
+
/**
|
|
3039
|
+
* Duration of the request in human-readable format
|
|
3040
|
+
* @type {string}
|
|
3041
|
+
* @memberof PinResponse
|
|
3042
|
+
*/
|
|
3043
|
+
duration: string;
|
|
3044
|
+
}
|
|
2962
3045
|
/**
|
|
2963
3046
|
*
|
|
2964
3047
|
* @export
|
|
@@ -3774,6 +3857,38 @@ export interface UnblockedUserEvent {
|
|
|
3774
3857
|
*/
|
|
3775
3858
|
user: UserResponse;
|
|
3776
3859
|
}
|
|
3860
|
+
/**
|
|
3861
|
+
*
|
|
3862
|
+
* @export
|
|
3863
|
+
* @interface UnpinRequest
|
|
3864
|
+
*/
|
|
3865
|
+
export interface UnpinRequest {
|
|
3866
|
+
/**
|
|
3867
|
+
*
|
|
3868
|
+
* @type {string}
|
|
3869
|
+
* @memberof UnpinRequest
|
|
3870
|
+
*/
|
|
3871
|
+
session_id: string;
|
|
3872
|
+
/**
|
|
3873
|
+
*
|
|
3874
|
+
* @type {string}
|
|
3875
|
+
* @memberof UnpinRequest
|
|
3876
|
+
*/
|
|
3877
|
+
user_id: string;
|
|
3878
|
+
}
|
|
3879
|
+
/**
|
|
3880
|
+
*
|
|
3881
|
+
* @export
|
|
3882
|
+
* @interface UnpinResponse
|
|
3883
|
+
*/
|
|
3884
|
+
export interface UnpinResponse {
|
|
3885
|
+
/**
|
|
3886
|
+
* Duration of the request in human-readable format
|
|
3887
|
+
* @type {string}
|
|
3888
|
+
* @memberof UnpinResponse
|
|
3889
|
+
*/
|
|
3890
|
+
duration: string;
|
|
3891
|
+
}
|
|
3777
3892
|
/**
|
|
3778
3893
|
*
|
|
3779
3894
|
* @export
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
Participant,
|
|
29
29
|
ParticipantCount,
|
|
30
30
|
PeerType,
|
|
31
|
+
Pin,
|
|
31
32
|
TrackInfo,
|
|
32
33
|
TrackType,
|
|
33
34
|
TrackUnpublishReason,
|
|
@@ -218,10 +219,31 @@ export interface SfuEvent {
|
|
|
218
219
|
*/
|
|
219
220
|
iceRestart: ICERestart;
|
|
220
221
|
}
|
|
222
|
+
| {
|
|
223
|
+
oneofKind: 'pinsUpdated';
|
|
224
|
+
/**
|
|
225
|
+
* PinsChanged is sent the list of pins in the call changes. This event contains the entire list of pins.
|
|
226
|
+
*
|
|
227
|
+
* @generated from protobuf field: stream.video.sfu.event.PinsChanged pins_updated = 22;
|
|
228
|
+
*/
|
|
229
|
+
pinsUpdated: PinsChanged;
|
|
230
|
+
}
|
|
221
231
|
| {
|
|
222
232
|
oneofKind: undefined;
|
|
223
233
|
};
|
|
224
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
* @generated from protobuf message stream.video.sfu.event.PinsChanged
|
|
237
|
+
*/
|
|
238
|
+
export interface PinsChanged {
|
|
239
|
+
/**
|
|
240
|
+
* the list of pins in the call.
|
|
241
|
+
* Pins are ordered in descending order (most important first).
|
|
242
|
+
*
|
|
243
|
+
* @generated from protobuf field: repeated stream.video.sfu.models.Pin pins = 1;
|
|
244
|
+
*/
|
|
245
|
+
pins: Pin[];
|
|
246
|
+
}
|
|
225
247
|
/**
|
|
226
248
|
* @generated from protobuf message stream.video.sfu.event.Error
|
|
227
249
|
*/
|
|
@@ -844,6 +866,13 @@ class SfuEvent$Type extends MessageType<SfuEvent> {
|
|
|
844
866
|
oneof: 'eventPayload',
|
|
845
867
|
T: () => ICERestart,
|
|
846
868
|
},
|
|
869
|
+
{
|
|
870
|
+
no: 22,
|
|
871
|
+
name: 'pins_updated',
|
|
872
|
+
kind: 'message',
|
|
873
|
+
oneof: 'eventPayload',
|
|
874
|
+
T: () => PinsChanged,
|
|
875
|
+
},
|
|
847
876
|
]);
|
|
848
877
|
}
|
|
849
878
|
create(value?: PartialMessage<SfuEvent>): SfuEvent {
|
|
@@ -1055,6 +1084,17 @@ class SfuEvent$Type extends MessageType<SfuEvent> {
|
|
|
1055
1084
|
),
|
|
1056
1085
|
};
|
|
1057
1086
|
break;
|
|
1087
|
+
case /* stream.video.sfu.event.PinsChanged pins_updated */ 22:
|
|
1088
|
+
message.eventPayload = {
|
|
1089
|
+
oneofKind: 'pinsUpdated',
|
|
1090
|
+
pinsUpdated: PinsChanged.internalBinaryRead(
|
|
1091
|
+
reader,
|
|
1092
|
+
reader.uint32(),
|
|
1093
|
+
options,
|
|
1094
|
+
(message.eventPayload as any).pinsUpdated,
|
|
1095
|
+
),
|
|
1096
|
+
};
|
|
1097
|
+
break;
|
|
1058
1098
|
default:
|
|
1059
1099
|
let u = options.readUnknownField;
|
|
1060
1100
|
if (u === 'throw')
|
|
@@ -1198,6 +1238,13 @@ class SfuEvent$Type extends MessageType<SfuEvent> {
|
|
|
1198
1238
|
writer.tag(21, WireType.LengthDelimited).fork(),
|
|
1199
1239
|
options,
|
|
1200
1240
|
).join();
|
|
1241
|
+
/* stream.video.sfu.event.PinsChanged pins_updated = 22; */
|
|
1242
|
+
if (message.eventPayload.oneofKind === 'pinsUpdated')
|
|
1243
|
+
PinsChanged.internalBinaryWrite(
|
|
1244
|
+
message.eventPayload.pinsUpdated,
|
|
1245
|
+
writer.tag(22, WireType.LengthDelimited).fork(),
|
|
1246
|
+
options,
|
|
1247
|
+
).join();
|
|
1201
1248
|
let u = options.writeUnknownFields;
|
|
1202
1249
|
if (u !== false)
|
|
1203
1250
|
(u == true ? UnknownFieldHandler.onWrite : u)(
|
|
@@ -1213,6 +1260,90 @@ class SfuEvent$Type extends MessageType<SfuEvent> {
|
|
|
1213
1260
|
*/
|
|
1214
1261
|
export const SfuEvent = new SfuEvent$Type();
|
|
1215
1262
|
// @generated message type with reflection information, may provide speed optimized methods
|
|
1263
|
+
class PinsChanged$Type extends MessageType<PinsChanged> {
|
|
1264
|
+
constructor() {
|
|
1265
|
+
super('stream.video.sfu.event.PinsChanged', [
|
|
1266
|
+
{
|
|
1267
|
+
no: 1,
|
|
1268
|
+
name: 'pins',
|
|
1269
|
+
kind: 'message',
|
|
1270
|
+
repeat: 1 /*RepeatType.PACKED*/,
|
|
1271
|
+
T: () => Pin,
|
|
1272
|
+
},
|
|
1273
|
+
]);
|
|
1274
|
+
}
|
|
1275
|
+
create(value?: PartialMessage<PinsChanged>): PinsChanged {
|
|
1276
|
+
const message = { pins: [] };
|
|
1277
|
+
globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
|
|
1278
|
+
enumerable: false,
|
|
1279
|
+
value: this,
|
|
1280
|
+
});
|
|
1281
|
+
if (value !== undefined)
|
|
1282
|
+
reflectionMergePartial<PinsChanged>(this, message, value);
|
|
1283
|
+
return message;
|
|
1284
|
+
}
|
|
1285
|
+
internalBinaryRead(
|
|
1286
|
+
reader: IBinaryReader,
|
|
1287
|
+
length: number,
|
|
1288
|
+
options: BinaryReadOptions,
|
|
1289
|
+
target?: PinsChanged,
|
|
1290
|
+
): PinsChanged {
|
|
1291
|
+
let message = target ?? this.create(),
|
|
1292
|
+
end = reader.pos + length;
|
|
1293
|
+
while (reader.pos < end) {
|
|
1294
|
+
let [fieldNo, wireType] = reader.tag();
|
|
1295
|
+
switch (fieldNo) {
|
|
1296
|
+
case /* repeated stream.video.sfu.models.Pin pins */ 1:
|
|
1297
|
+
message.pins.push(
|
|
1298
|
+
Pin.internalBinaryRead(reader, reader.uint32(), options),
|
|
1299
|
+
);
|
|
1300
|
+
break;
|
|
1301
|
+
default:
|
|
1302
|
+
let u = options.readUnknownField;
|
|
1303
|
+
if (u === 'throw')
|
|
1304
|
+
throw new globalThis.Error(
|
|
1305
|
+
`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`,
|
|
1306
|
+
);
|
|
1307
|
+
let d = reader.skip(wireType);
|
|
1308
|
+
if (u !== false)
|
|
1309
|
+
(u === true ? UnknownFieldHandler.onRead : u)(
|
|
1310
|
+
this.typeName,
|
|
1311
|
+
message,
|
|
1312
|
+
fieldNo,
|
|
1313
|
+
wireType,
|
|
1314
|
+
d,
|
|
1315
|
+
);
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
return message;
|
|
1319
|
+
}
|
|
1320
|
+
internalBinaryWrite(
|
|
1321
|
+
message: PinsChanged,
|
|
1322
|
+
writer: IBinaryWriter,
|
|
1323
|
+
options: BinaryWriteOptions,
|
|
1324
|
+
): IBinaryWriter {
|
|
1325
|
+
/* repeated stream.video.sfu.models.Pin pins = 1; */
|
|
1326
|
+
for (let i = 0; i < message.pins.length; i++)
|
|
1327
|
+
Pin.internalBinaryWrite(
|
|
1328
|
+
message.pins[i],
|
|
1329
|
+
writer.tag(1, WireType.LengthDelimited).fork(),
|
|
1330
|
+
options,
|
|
1331
|
+
).join();
|
|
1332
|
+
let u = options.writeUnknownFields;
|
|
1333
|
+
if (u !== false)
|
|
1334
|
+
(u == true ? UnknownFieldHandler.onWrite : u)(
|
|
1335
|
+
this.typeName,
|
|
1336
|
+
message,
|
|
1337
|
+
writer,
|
|
1338
|
+
);
|
|
1339
|
+
return writer;
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
/**
|
|
1343
|
+
* @generated MessageType for protobuf message stream.video.sfu.event.PinsChanged
|
|
1344
|
+
*/
|
|
1345
|
+
export const PinsChanged = new PinsChanged$Type();
|
|
1346
|
+
// @generated message type with reflection information, may provide speed optimized methods
|
|
1216
1347
|
class Error$Type extends MessageType<Error> {
|
|
1217
1348
|
constructor() {
|
|
1218
1349
|
super('stream.video.sfu.event.Error', [
|
|
@@ -48,6 +48,13 @@ export interface CallState {
|
|
|
48
48
|
* @generated from protobuf field: stream.video.sfu.models.ParticipantCount participant_count = 3;
|
|
49
49
|
*/
|
|
50
50
|
participantCount?: ParticipantCount;
|
|
51
|
+
/**
|
|
52
|
+
* the list of pins in the call.
|
|
53
|
+
* Pins are ordered in descending order (most important first).
|
|
54
|
+
*
|
|
55
|
+
* @generated from protobuf field: repeated stream.video.sfu.models.Pin pins = 4;
|
|
56
|
+
*/
|
|
57
|
+
pins: Pin[];
|
|
51
58
|
}
|
|
52
59
|
/**
|
|
53
60
|
* @generated from protobuf message stream.video.sfu.models.ParticipantCount
|
|
@@ -67,6 +74,23 @@ export interface ParticipantCount {
|
|
|
67
74
|
*/
|
|
68
75
|
anonymous: number;
|
|
69
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* @generated from protobuf message stream.video.sfu.models.Pin
|
|
79
|
+
*/
|
|
80
|
+
export interface Pin {
|
|
81
|
+
/**
|
|
82
|
+
* the user to pin
|
|
83
|
+
*
|
|
84
|
+
* @generated from protobuf field: string user_id = 1;
|
|
85
|
+
*/
|
|
86
|
+
userId: string;
|
|
87
|
+
/**
|
|
88
|
+
* the user sesion_id to pin, if not provided, applies to all sessions
|
|
89
|
+
*
|
|
90
|
+
* @generated from protobuf field: string session_id = 2;
|
|
91
|
+
*/
|
|
92
|
+
sessionId: string;
|
|
93
|
+
}
|
|
70
94
|
/**
|
|
71
95
|
* those who are online in the call
|
|
72
96
|
*
|
|
@@ -695,10 +719,17 @@ class CallState$Type extends MessageType<CallState> {
|
|
|
695
719
|
kind: 'message',
|
|
696
720
|
T: () => ParticipantCount,
|
|
697
721
|
},
|
|
722
|
+
{
|
|
723
|
+
no: 4,
|
|
724
|
+
name: 'pins',
|
|
725
|
+
kind: 'message',
|
|
726
|
+
repeat: 1 /*RepeatType.PACKED*/,
|
|
727
|
+
T: () => Pin,
|
|
728
|
+
},
|
|
698
729
|
]);
|
|
699
730
|
}
|
|
700
731
|
create(value?: PartialMessage<CallState>): CallState {
|
|
701
|
-
const message = { participants: [] };
|
|
732
|
+
const message = { participants: [], pins: [] };
|
|
702
733
|
globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
|
|
703
734
|
enumerable: false,
|
|
704
735
|
value: this,
|
|
@@ -739,6 +770,11 @@ class CallState$Type extends MessageType<CallState> {
|
|
|
739
770
|
message.participantCount,
|
|
740
771
|
);
|
|
741
772
|
break;
|
|
773
|
+
case /* repeated stream.video.sfu.models.Pin pins */ 4:
|
|
774
|
+
message.pins.push(
|
|
775
|
+
Pin.internalBinaryRead(reader, reader.uint32(), options),
|
|
776
|
+
);
|
|
777
|
+
break;
|
|
742
778
|
default:
|
|
743
779
|
let u = options.readUnknownField;
|
|
744
780
|
if (u === 'throw')
|
|
@@ -784,6 +820,13 @@ class CallState$Type extends MessageType<CallState> {
|
|
|
784
820
|
writer.tag(3, WireType.LengthDelimited).fork(),
|
|
785
821
|
options,
|
|
786
822
|
).join();
|
|
823
|
+
/* repeated stream.video.sfu.models.Pin pins = 4; */
|
|
824
|
+
for (let i = 0; i < message.pins.length; i++)
|
|
825
|
+
Pin.internalBinaryWrite(
|
|
826
|
+
message.pins[i],
|
|
827
|
+
writer.tag(4, WireType.LengthDelimited).fork(),
|
|
828
|
+
options,
|
|
829
|
+
).join();
|
|
787
830
|
let u = options.writeUnknownFields;
|
|
788
831
|
if (u !== false)
|
|
789
832
|
(u == true ? UnknownFieldHandler.onWrite : u)(
|
|
@@ -878,6 +921,84 @@ class ParticipantCount$Type extends MessageType<ParticipantCount> {
|
|
|
878
921
|
*/
|
|
879
922
|
export const ParticipantCount = new ParticipantCount$Type();
|
|
880
923
|
// @generated message type with reflection information, may provide speed optimized methods
|
|
924
|
+
class Pin$Type extends MessageType<Pin> {
|
|
925
|
+
constructor() {
|
|
926
|
+
super('stream.video.sfu.models.Pin', [
|
|
927
|
+
{ no: 1, name: 'user_id', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
|
|
928
|
+
{ no: 2, name: 'session_id', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
|
|
929
|
+
]);
|
|
930
|
+
}
|
|
931
|
+
create(value?: PartialMessage<Pin>): Pin {
|
|
932
|
+
const message = { userId: '', sessionId: '' };
|
|
933
|
+
globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
|
|
934
|
+
enumerable: false,
|
|
935
|
+
value: this,
|
|
936
|
+
});
|
|
937
|
+
if (value !== undefined) reflectionMergePartial<Pin>(this, message, value);
|
|
938
|
+
return message;
|
|
939
|
+
}
|
|
940
|
+
internalBinaryRead(
|
|
941
|
+
reader: IBinaryReader,
|
|
942
|
+
length: number,
|
|
943
|
+
options: BinaryReadOptions,
|
|
944
|
+
target?: Pin,
|
|
945
|
+
): Pin {
|
|
946
|
+
let message = target ?? this.create(),
|
|
947
|
+
end = reader.pos + length;
|
|
948
|
+
while (reader.pos < end) {
|
|
949
|
+
let [fieldNo, wireType] = reader.tag();
|
|
950
|
+
switch (fieldNo) {
|
|
951
|
+
case /* string user_id */ 1:
|
|
952
|
+
message.userId = reader.string();
|
|
953
|
+
break;
|
|
954
|
+
case /* string session_id */ 2:
|
|
955
|
+
message.sessionId = reader.string();
|
|
956
|
+
break;
|
|
957
|
+
default:
|
|
958
|
+
let u = options.readUnknownField;
|
|
959
|
+
if (u === 'throw')
|
|
960
|
+
throw new globalThis.Error(
|
|
961
|
+
`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`,
|
|
962
|
+
);
|
|
963
|
+
let d = reader.skip(wireType);
|
|
964
|
+
if (u !== false)
|
|
965
|
+
(u === true ? UnknownFieldHandler.onRead : u)(
|
|
966
|
+
this.typeName,
|
|
967
|
+
message,
|
|
968
|
+
fieldNo,
|
|
969
|
+
wireType,
|
|
970
|
+
d,
|
|
971
|
+
);
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
return message;
|
|
975
|
+
}
|
|
976
|
+
internalBinaryWrite(
|
|
977
|
+
message: Pin,
|
|
978
|
+
writer: IBinaryWriter,
|
|
979
|
+
options: BinaryWriteOptions,
|
|
980
|
+
): IBinaryWriter {
|
|
981
|
+
/* string user_id = 1; */
|
|
982
|
+
if (message.userId !== '')
|
|
983
|
+
writer.tag(1, WireType.LengthDelimited).string(message.userId);
|
|
984
|
+
/* string session_id = 2; */
|
|
985
|
+
if (message.sessionId !== '')
|
|
986
|
+
writer.tag(2, WireType.LengthDelimited).string(message.sessionId);
|
|
987
|
+
let u = options.writeUnknownFields;
|
|
988
|
+
if (u !== false)
|
|
989
|
+
(u == true ? UnknownFieldHandler.onWrite : u)(
|
|
990
|
+
this.typeName,
|
|
991
|
+
message,
|
|
992
|
+
writer,
|
|
993
|
+
);
|
|
994
|
+
return writer;
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
/**
|
|
998
|
+
* @generated MessageType for protobuf message stream.video.sfu.models.Pin
|
|
999
|
+
*/
|
|
1000
|
+
export const Pin = new Pin$Type();
|
|
1001
|
+
// @generated message type with reflection information, may provide speed optimized methods
|
|
881
1002
|
class Participant$Type extends MessageType<Participant> {
|
|
882
1003
|
constructor() {
|
|
883
1004
|
super('stream.video.sfu.models.Participant', [
|
package/src/rtc/Dispatcher.ts
CHANGED
package/src/rtc/flows/join.ts
CHANGED
|
@@ -112,15 +112,9 @@ export const reconcileParticipantLocalState = (
|
|
|
112
112
|
) => {
|
|
113
113
|
if (!source) return target;
|
|
114
114
|
|
|
115
|
-
|
|
116
|
-
target
|
|
117
|
-
target.screenShareStream = source.screenShareStream;
|
|
115
|
+
// copy everything from source to target
|
|
116
|
+
Object.assign(target, source);
|
|
118
117
|
|
|
119
|
-
target.videoDimension = source.videoDimension;
|
|
120
|
-
target.screenShareDimension = source.screenShareDimension;
|
|
121
|
-
target.pinnedAt = source.pinnedAt;
|
|
122
|
-
target.reaction = source.reaction;
|
|
123
|
-
target.viewportVisibilityState = source.viewportVisibilityState;
|
|
124
118
|
if (
|
|
125
119
|
isStreamVideoLocalParticipant(source) &&
|
|
126
120
|
isStreamVideoLocalParticipant(target)
|
|
@@ -92,7 +92,10 @@ export const participants = (): StreamVideoParticipant[] => [
|
|
|
92
92
|
isDominantSpeaker: false,
|
|
93
93
|
audioLevel: 0,
|
|
94
94
|
image: '',
|
|
95
|
-
|
|
95
|
+
pin: {
|
|
96
|
+
isLocalPin: true,
|
|
97
|
+
pinnedAt: Date.now(),
|
|
98
|
+
},
|
|
96
99
|
roles: [],
|
|
97
100
|
viewportVisibilityState: VisibilityState.VISIBLE,
|
|
98
101
|
},
|
|
@@ -69,13 +69,15 @@ export const publishingAudio: Comparator<StreamVideoParticipant> = (a, b) => {
|
|
|
69
69
|
* @param b the second participant.
|
|
70
70
|
*/
|
|
71
71
|
export const pinned: Comparator<StreamVideoParticipant> = (a, b) => {
|
|
72
|
-
if (a.
|
|
73
|
-
if (a.
|
|
74
|
-
if (a.
|
|
72
|
+
if (a.pin && b.pin) {
|
|
73
|
+
if (!a.pin.isLocalPin && b.pin.isLocalPin) return -1;
|
|
74
|
+
if (a.pin.isLocalPin && !b.pin.isLocalPin) return 1;
|
|
75
|
+
if (a.pin.pinnedAt > b.pin.pinnedAt) return -1;
|
|
76
|
+
if (a.pin.pinnedAt < b.pin.pinnedAt) return 1;
|
|
75
77
|
}
|
|
76
78
|
|
|
77
|
-
if (a.
|
|
78
|
-
if (!a.
|
|
79
|
+
if (a.pin && !b.pin) return -1;
|
|
80
|
+
if (!a.pin && b.pin) return 1;
|
|
79
81
|
|
|
80
82
|
return 0;
|
|
81
83
|
};
|
package/src/store/CallState.ts
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
MemberResponse,
|
|
17
17
|
OwnCapability,
|
|
18
18
|
} from '../gen/coordinator';
|
|
19
|
-
import { TrackType } from '../gen/video/sfu/models/models';
|
|
19
|
+
import { Pin, TrackType } from '../gen/video/sfu/models/models';
|
|
20
20
|
import { Comparator } from '../sorting';
|
|
21
21
|
import * as SortingPreset from '../sorting/presets';
|
|
22
22
|
import { getLogger } from '../logger';
|
|
@@ -287,7 +287,7 @@ export class CallState {
|
|
|
287
287
|
);
|
|
288
288
|
|
|
289
289
|
this.pinnedParticipants$ = this.participants$.pipe(
|
|
290
|
-
map((participants) => participants.filter((p) => p.
|
|
290
|
+
map((participants) => participants.filter((p) => !!p.pin)),
|
|
291
291
|
);
|
|
292
292
|
|
|
293
293
|
this.dominantSpeaker$ = this.participants$.pipe(
|
|
@@ -678,4 +678,45 @@ export class CallState {
|
|
|
678
678
|
}),
|
|
679
679
|
);
|
|
680
680
|
};
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* Updates the participant pinned state with server side pinning data.
|
|
684
|
+
*
|
|
685
|
+
* @param pins the latest pins from the server.
|
|
686
|
+
*/
|
|
687
|
+
setServerSidePins = (pins: Pin[]) => {
|
|
688
|
+
const pinsLookup = pins.reduce<{ [sessionId: string]: number | undefined }>(
|
|
689
|
+
(lookup, pin) => {
|
|
690
|
+
lookup[pin.sessionId] = Date.now();
|
|
691
|
+
return lookup;
|
|
692
|
+
},
|
|
693
|
+
{},
|
|
694
|
+
);
|
|
695
|
+
|
|
696
|
+
return this.setParticipants((participants) =>
|
|
697
|
+
participants.map((participant) => {
|
|
698
|
+
const serverSidePinnedAt = pinsLookup[participant.sessionId];
|
|
699
|
+
// the participant is newly pinned
|
|
700
|
+
if (serverSidePinnedAt) {
|
|
701
|
+
return {
|
|
702
|
+
...participant,
|
|
703
|
+
pin: {
|
|
704
|
+
isLocalPin: false,
|
|
705
|
+
pinnedAt: serverSidePinnedAt,
|
|
706
|
+
},
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
// the participant is no longer pinned server side
|
|
710
|
+
// we need to reset the pin
|
|
711
|
+
if (participant.pin && !participant.pin.isLocalPin) {
|
|
712
|
+
return {
|
|
713
|
+
...participant,
|
|
714
|
+
pin: undefined,
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
// no changes to be applied
|
|
718
|
+
return participant;
|
|
719
|
+
}),
|
|
720
|
+
);
|
|
721
|
+
};
|
|
681
722
|
}
|