@defcomm/meetingsdk 0.2.6 → 0.2.8
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.d.mts +38 -1
- package/dist/index.d.ts +38 -1
- package/dist/index.js +278 -49
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +278 -49
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -357,6 +357,7 @@ var SFUClient = class {
|
|
|
357
357
|
this.iceServers = [];
|
|
358
358
|
this.requestId = 0;
|
|
359
359
|
this.publisherRevision = 0;
|
|
360
|
+
this.screenShareGeneration = 0;
|
|
360
361
|
this.currentParticipantId = null;
|
|
361
362
|
this.token = null;
|
|
362
363
|
this.room = null;
|
|
@@ -367,6 +368,8 @@ var SFUClient = class {
|
|
|
367
368
|
this.intentionalClose = false;
|
|
368
369
|
this.leaveAcknowledged = false;
|
|
369
370
|
this.joiningWithResume = false;
|
|
371
|
+
this.desiredAudioMuted = false;
|
|
372
|
+
this.desiredVideoMuted = false;
|
|
370
373
|
this.reconnectTimer = null;
|
|
371
374
|
this.reconnectAttempt = 0;
|
|
372
375
|
this.maxReconnectAttempts = 8;
|
|
@@ -435,6 +438,14 @@ var SFUClient = class {
|
|
|
435
438
|
this.onRecordingStopped = options.onRecordingStopped || (() => {
|
|
436
439
|
});
|
|
437
440
|
this.onError = options.onError || console.error;
|
|
441
|
+
this.onChatMessage = options.onChatMessage || (() => {
|
|
442
|
+
});
|
|
443
|
+
this.onReaction = options.onReaction || (() => {
|
|
444
|
+
});
|
|
445
|
+
this.onRoomUpdate = options.onRoomUpdate || (() => {
|
|
446
|
+
});
|
|
447
|
+
this.onParticipantMediaState = options.onParticipantMediaState || (() => {
|
|
448
|
+
});
|
|
438
449
|
this.autoSubscribe = options.autoSubscribe !== false;
|
|
439
450
|
}
|
|
440
451
|
startHeartbeat() {
|
|
@@ -557,6 +568,10 @@ var SFUClient = class {
|
|
|
557
568
|
avatarUrl: options.avatarUrl
|
|
558
569
|
};
|
|
559
570
|
if (options.participantId) this.participantId = options.participantId;
|
|
571
|
+
if (typeof options.audioMuted === "boolean")
|
|
572
|
+
this.desiredAudioMuted = options.audioMuted;
|
|
573
|
+
if (typeof options.videoMuted === "boolean")
|
|
574
|
+
this.desiredVideoMuted = options.videoMuted;
|
|
560
575
|
if (!this.resumeToken) {
|
|
561
576
|
this.resumeToken = this.loadResumeToken(this.room);
|
|
562
577
|
}
|
|
@@ -623,7 +638,9 @@ var SFUClient = class {
|
|
|
623
638
|
room_code: this.room,
|
|
624
639
|
resume_token: this.resumeToken,
|
|
625
640
|
display_name: options.displayName,
|
|
626
|
-
avatar_url: options.avatarUrl
|
|
641
|
+
avatar_url: options.avatarUrl,
|
|
642
|
+
audio_muted: this.desiredAudioMuted,
|
|
643
|
+
video_muted: this.desiredVideoMuted
|
|
627
644
|
};
|
|
628
645
|
if (this.pendingJoinRequestId) {
|
|
629
646
|
this.send({
|
|
@@ -798,6 +815,16 @@ var SFUClient = class {
|
|
|
798
815
|
this.onParticipantLeft(participantId);
|
|
799
816
|
break;
|
|
800
817
|
}
|
|
818
|
+
case "participant_media_state": {
|
|
819
|
+
const participantId = payload.participant_id;
|
|
820
|
+
if (!participantId) break;
|
|
821
|
+
this.onParticipantMediaState(
|
|
822
|
+
participantId,
|
|
823
|
+
Boolean(payload.audio_muted),
|
|
824
|
+
Boolean(payload.video_muted)
|
|
825
|
+
);
|
|
826
|
+
break;
|
|
827
|
+
}
|
|
801
828
|
case "participant_presence":
|
|
802
829
|
case "participant_presence_changed": {
|
|
803
830
|
const participantId = payload.participant_id;
|
|
@@ -920,6 +947,50 @@ var SFUClient = class {
|
|
|
920
947
|
this.onScreenShareStopped(participantId, trackId);
|
|
921
948
|
break;
|
|
922
949
|
}
|
|
950
|
+
case "room_state": {
|
|
951
|
+
const participants = payload.participants || [];
|
|
952
|
+
this.onRoomStateReconciled(payload);
|
|
953
|
+
this.onRoomUpdate(payload);
|
|
954
|
+
for (const participant of participants) {
|
|
955
|
+
const pid = participant?.participant_id;
|
|
956
|
+
if (!pid) continue;
|
|
957
|
+
if (pid !== this.currentParticipantId) {
|
|
958
|
+
this.participants.set(pid, participant);
|
|
959
|
+
this.onParticipantPresence(
|
|
960
|
+
pid,
|
|
961
|
+
String(participant.presence || "connected")
|
|
962
|
+
);
|
|
963
|
+
this.onParticipantMediaState(
|
|
964
|
+
pid,
|
|
965
|
+
Boolean(participant.audio_muted),
|
|
966
|
+
Boolean(participant.video_muted)
|
|
967
|
+
);
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
for (const [pid] of this.participants) {
|
|
971
|
+
if (!participants.some((p) => p?.participant_id === pid)) {
|
|
972
|
+
this.participants.delete(pid);
|
|
973
|
+
this.removeRemoteParticipant(pid);
|
|
974
|
+
this.onParticipantLeft(pid);
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
for (const track of payload.tracks || []) this.rememberTrack(track);
|
|
978
|
+
if (Array.isArray(payload.chat_history)) {
|
|
979
|
+
for (const message2 of payload.chat_history)
|
|
980
|
+
this.onChatMessage(message2);
|
|
981
|
+
}
|
|
982
|
+
break;
|
|
983
|
+
}
|
|
984
|
+
case "chat_message": {
|
|
985
|
+
const msg = payload.message || payload;
|
|
986
|
+
if (msg?.id) this.onChatMessage(msg);
|
|
987
|
+
break;
|
|
988
|
+
}
|
|
989
|
+
case "reaction": {
|
|
990
|
+
const reaction = payload.reaction || payload;
|
|
991
|
+
if (reaction?.id && reaction?.emoji) this.onReaction(reaction);
|
|
992
|
+
break;
|
|
993
|
+
}
|
|
923
994
|
case "error": {
|
|
924
995
|
const message2 = payload.message || "SFU signaling error";
|
|
925
996
|
if (this.state === "reconnecting" && message2.includes("participant session is stale")) {
|
|
@@ -942,6 +1013,16 @@ var SFUClient = class {
|
|
|
942
1013
|
console.debug("[SFU] Ignoring unknown server message", message);
|
|
943
1014
|
}
|
|
944
1015
|
}
|
|
1016
|
+
onRoomStateReconciled(payload) {
|
|
1017
|
+
const participants = payload.participants || [];
|
|
1018
|
+
const local = participants.find(
|
|
1019
|
+
(p) => p?.participant_id === this.currentParticipantId
|
|
1020
|
+
);
|
|
1021
|
+
if (local) {
|
|
1022
|
+
this.desiredAudioMuted = Boolean(local.audio_muted);
|
|
1023
|
+
this.desiredVideoMuted = Boolean(local.video_muted);
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
945
1026
|
rememberTrack(track) {
|
|
946
1027
|
this.trackMetadata.set(track.track_id, track);
|
|
947
1028
|
this.trackToParticipant.set(track.track_id, track.participant_id);
|
|
@@ -977,8 +1058,21 @@ var SFUClient = class {
|
|
|
977
1058
|
for (const participant of this.participants.values()) {
|
|
978
1059
|
if (participant.participant_id !== this.currentParticipantId) {
|
|
979
1060
|
this.onParticipantJoined(participant);
|
|
1061
|
+
this.onParticipantPresence(
|
|
1062
|
+
participant.participant_id,
|
|
1063
|
+
String(participant.presence || "connected")
|
|
1064
|
+
);
|
|
1065
|
+
this.onParticipantMediaState(
|
|
1066
|
+
participant.participant_id,
|
|
1067
|
+
Boolean(participant.audio_muted),
|
|
1068
|
+
Boolean(participant.video_muted)
|
|
1069
|
+
);
|
|
980
1070
|
}
|
|
981
1071
|
}
|
|
1072
|
+
if (Array.isArray(payload.chat_history)) {
|
|
1073
|
+
for (const message of payload.chat_history) this.onChatMessage(message);
|
|
1074
|
+
}
|
|
1075
|
+
this.onRoomUpdate(payload);
|
|
982
1076
|
if (this.localStream) {
|
|
983
1077
|
await this.publishExistingTracks();
|
|
984
1078
|
}
|
|
@@ -1337,9 +1431,27 @@ var SFUClient = class {
|
|
|
1337
1431
|
if (!this.screenTransceiver || !this.screenSender) {
|
|
1338
1432
|
throw new Error("Screen transceiver is not initialized");
|
|
1339
1433
|
}
|
|
1340
|
-
|
|
1434
|
+
const existingTrack = this.screenSender.track;
|
|
1435
|
+
if (this.screenStream && existingTrack && existingTrack.readyState === "live") {
|
|
1341
1436
|
return this.screenStream;
|
|
1342
1437
|
}
|
|
1438
|
+
const generation = ++this.screenShareGeneration;
|
|
1439
|
+
try {
|
|
1440
|
+
await this.screenSender.replaceTrack(null);
|
|
1441
|
+
} catch (err) {
|
|
1442
|
+
console.warn("[SFU] Failed to clear previous screen track", err);
|
|
1443
|
+
}
|
|
1444
|
+
if (this.screenStream) {
|
|
1445
|
+
for (const track of this.screenStream.getTracks()) {
|
|
1446
|
+
try {
|
|
1447
|
+
track.onended = null;
|
|
1448
|
+
track.stop();
|
|
1449
|
+
} catch {
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
this.screenStream = null;
|
|
1454
|
+
this.screenTransceiver.direction = "inactive";
|
|
1343
1455
|
const screenStream = await navigator.mediaDevices.getDisplayMedia({
|
|
1344
1456
|
video: true,
|
|
1345
1457
|
audio: false
|
|
@@ -1351,83 +1463,99 @@ var SFUClient = class {
|
|
|
1351
1463
|
}
|
|
1352
1464
|
this.screenStream = screenStream;
|
|
1353
1465
|
try {
|
|
1354
|
-
if (!this.send({ type: "start_screen_share" })) {
|
|
1355
|
-
throw new Error("Failed to signal start_screen_share");
|
|
1356
|
-
}
|
|
1357
1466
|
await this.screenSender.replaceTrack(screenTrack);
|
|
1358
1467
|
this.screenTransceiver.direction = "sendonly";
|
|
1468
|
+
this.send({
|
|
1469
|
+
type: "start_screen_share"
|
|
1470
|
+
});
|
|
1471
|
+
await new Promise((resolve) => {
|
|
1472
|
+
queueMicrotask(resolve);
|
|
1473
|
+
});
|
|
1359
1474
|
const offer = await this.publisher.createOffer();
|
|
1360
1475
|
await this.publisher.setLocalDescription(offer);
|
|
1476
|
+
const localDescription = this.publisher.localDescription;
|
|
1477
|
+
if (!localDescription?.sdp) {
|
|
1478
|
+
throw new Error("Publisher did not produce a valid screen-share SDP");
|
|
1479
|
+
}
|
|
1480
|
+
const revision = ++this.publisherRevision;
|
|
1361
1481
|
this.send({
|
|
1362
1482
|
type: "publish_offer",
|
|
1363
1483
|
payload: {
|
|
1364
|
-
revision
|
|
1365
|
-
sdp:
|
|
1484
|
+
revision,
|
|
1485
|
+
sdp: localDescription.sdp
|
|
1366
1486
|
}
|
|
1367
1487
|
});
|
|
1368
1488
|
screenTrack.onended = () => {
|
|
1489
|
+
if (generation !== this.screenShareGeneration) {
|
|
1490
|
+
return;
|
|
1491
|
+
}
|
|
1369
1492
|
void this.stopScreenShare();
|
|
1370
1493
|
};
|
|
1371
|
-
|
|
1372
|
-
screenTrackId: screenTrack.id,
|
|
1373
|
-
cameraTrackId: this.videoSender?.track?.id,
|
|
1374
|
-
screenMid: this.screenTransceiver.mid,
|
|
1375
|
-
cameraMid: this.cameraTransceiver?.mid
|
|
1376
|
-
});
|
|
1377
|
-
return this.screenStream;
|
|
1494
|
+
return screenStream;
|
|
1378
1495
|
} catch (error) {
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1496
|
+
if (generation === this.screenShareGeneration) {
|
|
1497
|
+
try {
|
|
1498
|
+
await this.screenSender.replaceTrack(null);
|
|
1499
|
+
} catch {
|
|
1500
|
+
}
|
|
1501
|
+
this.screenTransceiver.direction = "inactive";
|
|
1502
|
+
screenTrack.onended = null;
|
|
1503
|
+
screenStream.getTracks().forEach((track) => {
|
|
1504
|
+
try {
|
|
1505
|
+
track.stop();
|
|
1506
|
+
} catch {
|
|
1507
|
+
}
|
|
1508
|
+
});
|
|
1509
|
+
this.screenStream = null;
|
|
1510
|
+
try {
|
|
1511
|
+
this.send({
|
|
1512
|
+
type: "stop_screen_share"
|
|
1513
|
+
});
|
|
1514
|
+
} catch {
|
|
1515
|
+
}
|
|
1389
1516
|
}
|
|
1390
1517
|
throw error;
|
|
1391
1518
|
}
|
|
1392
1519
|
}
|
|
1393
1520
|
async stopScreenShare() {
|
|
1394
|
-
|
|
1395
|
-
const
|
|
1396
|
-
if (
|
|
1521
|
+
const stream = this.screenStream;
|
|
1522
|
+
const senderTrack = this.screenSender?.track || null;
|
|
1523
|
+
if (!stream && !senderTrack) return;
|
|
1524
|
+
++this.screenShareGeneration;
|
|
1525
|
+
if (senderTrack) senderTrack.onended = null;
|
|
1397
1526
|
try {
|
|
1398
1527
|
await this.screenSender?.replaceTrack(null);
|
|
1399
1528
|
} catch (error) {
|
|
1400
1529
|
this.onError(error);
|
|
1401
1530
|
}
|
|
1402
|
-
if (this.screenTransceiver)
|
|
1403
|
-
this.screenTransceiver.direction = "inactive";
|
|
1404
|
-
}
|
|
1405
|
-
this.send({ type: "stop_screen_share" });
|
|
1531
|
+
if (this.screenTransceiver) this.screenTransceiver.direction = "inactive";
|
|
1406
1532
|
try {
|
|
1407
1533
|
const offer = await this.publisher?.createOffer();
|
|
1408
1534
|
if (offer && this.publisher) {
|
|
1409
1535
|
await this.publisher.setLocalDescription(offer);
|
|
1410
1536
|
this.send({
|
|
1411
1537
|
type: "publish_offer",
|
|
1412
|
-
payload: {
|
|
1413
|
-
revision: ++this.publisherRevision,
|
|
1414
|
-
sdp: offer.sdp
|
|
1415
|
-
}
|
|
1538
|
+
payload: { revision: ++this.publisherRevision, sdp: offer.sdp }
|
|
1416
1539
|
});
|
|
1417
1540
|
}
|
|
1418
1541
|
} catch (error) {
|
|
1419
1542
|
this.onError(error);
|
|
1420
1543
|
}
|
|
1421
|
-
this.
|
|
1544
|
+
this.send({ type: "stop_screen_share" });
|
|
1545
|
+
stream?.getTracks().forEach((track) => track.stop());
|
|
1422
1546
|
this.screenStream = null;
|
|
1423
|
-
if (this.currentParticipantId)
|
|
1547
|
+
if (this.currentParticipantId)
|
|
1424
1548
|
this.onScreenShareStopped(this.currentParticipantId);
|
|
1425
|
-
}
|
|
1426
1549
|
}
|
|
1427
1550
|
muteAudio(muted) {
|
|
1551
|
+
this.desiredAudioMuted = muted;
|
|
1428
1552
|
this.localStream?.getAudioTracks().forEach((track) => {
|
|
1429
1553
|
track.enabled = !muted;
|
|
1430
1554
|
});
|
|
1555
|
+
this.send({
|
|
1556
|
+
type: "set_media_state",
|
|
1557
|
+
payload: { audio_muted: muted, video_muted: this.desiredVideoMuted }
|
|
1558
|
+
});
|
|
1431
1559
|
const trackId = this.localTrackIds.get("audio");
|
|
1432
1560
|
if (trackId) {
|
|
1433
1561
|
this.send({
|
|
@@ -1440,9 +1568,14 @@ var SFUClient = class {
|
|
|
1440
1568
|
}
|
|
1441
1569
|
}
|
|
1442
1570
|
muteVideo(muted) {
|
|
1571
|
+
this.desiredVideoMuted = muted;
|
|
1443
1572
|
this.localStream?.getVideoTracks().forEach((track) => {
|
|
1444
1573
|
track.enabled = !muted;
|
|
1445
1574
|
});
|
|
1575
|
+
this.send({
|
|
1576
|
+
type: "set_media_state",
|
|
1577
|
+
payload: { audio_muted: this.desiredAudioMuted, video_muted: muted }
|
|
1578
|
+
});
|
|
1446
1579
|
const trackId = this.localTrackIds.get("camera");
|
|
1447
1580
|
if (trackId) {
|
|
1448
1581
|
this.send({
|
|
@@ -1454,6 +1587,16 @@ var SFUClient = class {
|
|
|
1454
1587
|
});
|
|
1455
1588
|
}
|
|
1456
1589
|
}
|
|
1590
|
+
sendChatMessage(input) {
|
|
1591
|
+
return this.send({
|
|
1592
|
+
type: "send_chat",
|
|
1593
|
+
payload: {
|
|
1594
|
+
message: input.message,
|
|
1595
|
+
reply_to: input.reply_to ?? null,
|
|
1596
|
+
target: input.target ?? null
|
|
1597
|
+
}
|
|
1598
|
+
});
|
|
1599
|
+
}
|
|
1457
1600
|
async startRecording() {
|
|
1458
1601
|
if (!this.send({ type: "start_recording" })) {
|
|
1459
1602
|
throw new Error("SFU signaling is not connected");
|
|
@@ -1505,6 +1648,12 @@ var SFUClient = class {
|
|
|
1505
1648
|
);
|
|
1506
1649
|
return true;
|
|
1507
1650
|
}
|
|
1651
|
+
sendReaction(reaction) {
|
|
1652
|
+
this.send({
|
|
1653
|
+
type: "send_reaction",
|
|
1654
|
+
reaction
|
|
1655
|
+
});
|
|
1656
|
+
}
|
|
1508
1657
|
removeRemoteParticipant(participantId) {
|
|
1509
1658
|
const stream = this.remoteStreams.get(participantId);
|
|
1510
1659
|
if (stream) {
|
|
@@ -1921,6 +2070,44 @@ var VideoSDKCore = class {
|
|
|
1921
2070
|
console.warn(`[SFU] Reconnecting, attempt ${attempt}`);
|
|
1922
2071
|
},
|
|
1923
2072
|
// ADMISSION CONTROL
|
|
2073
|
+
onRoomUpdate: (payload) => {
|
|
2074
|
+
const participants = payload?.participants || [];
|
|
2075
|
+
const local = participants.find(
|
|
2076
|
+
(p) => p?.participant_id === this.myId
|
|
2077
|
+
);
|
|
2078
|
+
if (local) {
|
|
2079
|
+
const media = this.state.localParticipant?.media;
|
|
2080
|
+
this.state.updateLocalParticipant({
|
|
2081
|
+
id: this.myId,
|
|
2082
|
+
name: this.participantName,
|
|
2083
|
+
media: {
|
|
2084
|
+
micEnabled: !Boolean(local.audio_muted),
|
|
2085
|
+
camEnabled: !Boolean(local.video_muted),
|
|
2086
|
+
isScreenSharing: Boolean(local.screen_sharing),
|
|
2087
|
+
screenStream: this.screenStream,
|
|
2088
|
+
screenTrack: this.screenStream?.getVideoTracks()[0]
|
|
2089
|
+
}
|
|
2090
|
+
});
|
|
2091
|
+
if (this.localStream) {
|
|
2092
|
+
this.localStream.getAudioTracks().forEach((track) => {
|
|
2093
|
+
track.enabled = !Boolean(local.audio_muted);
|
|
2094
|
+
});
|
|
2095
|
+
this.localStream.getVideoTracks().forEach((track) => {
|
|
2096
|
+
track.enabled = !Boolean(local.video_muted);
|
|
2097
|
+
});
|
|
2098
|
+
}
|
|
2099
|
+
if (local.screen_sharing) this.state.setPresenterId(this.myId);
|
|
2100
|
+
else if (this.state.presenterId === this.myId)
|
|
2101
|
+
this.state.setPresenterId(null);
|
|
2102
|
+
}
|
|
2103
|
+
const presenter = participants.find((p) => p?.screen_sharing);
|
|
2104
|
+
if (presenter) this.state.setPresenterId(presenter.participant_id);
|
|
2105
|
+
else if (!local?.screen_sharing) this.state.setPresenterId(null);
|
|
2106
|
+
for (const message of payload?.chat_history || []) {
|
|
2107
|
+
this.state.addChatMessage(message);
|
|
2108
|
+
}
|
|
2109
|
+
this.events.onRoomUpdate?.(payload);
|
|
2110
|
+
},
|
|
1924
2111
|
onJoinPending: (info) => {
|
|
1925
2112
|
console.log("[SFU] Join request pending", info);
|
|
1926
2113
|
},
|
|
@@ -1955,6 +2142,19 @@ var VideoSDKCore = class {
|
|
|
1955
2142
|
false
|
|
1956
2143
|
);
|
|
1957
2144
|
},
|
|
2145
|
+
onChatMessage: (message) => {
|
|
2146
|
+
const msg = {
|
|
2147
|
+
id: message.id,
|
|
2148
|
+
text: message.text,
|
|
2149
|
+
sender_id: message.sender_id,
|
|
2150
|
+
sender_name: message.sender_name,
|
|
2151
|
+
timestamp: Number(message.timestamp),
|
|
2152
|
+
reply_to: message.reply_to ?? null,
|
|
2153
|
+
target: message.target ?? null
|
|
2154
|
+
};
|
|
2155
|
+
this.state.addChatMessage(msg);
|
|
2156
|
+
this.events.onChatMessage?.(msg);
|
|
2157
|
+
},
|
|
1958
2158
|
onJoinRequested: (request) => {
|
|
1959
2159
|
const requestId = request?.request_id || request?.requestId;
|
|
1960
2160
|
const participantId = request?.user_id || request?.participantId;
|
|
@@ -2023,6 +2223,17 @@ var VideoSDKCore = class {
|
|
|
2023
2223
|
this.events.onUserLeft?.(pid);
|
|
2024
2224
|
},
|
|
2025
2225
|
// TRACKS
|
|
2226
|
+
onParticipantMediaState: (participantId, audioMuted, videoMuted) => {
|
|
2227
|
+
if (participantId === this.myId) return;
|
|
2228
|
+
const participant = this.state.getParticipant(participantId);
|
|
2229
|
+
if (!participant) return;
|
|
2230
|
+
this.state.updateParticipantMedia(participantId, {
|
|
2231
|
+
micEnabled: !audioMuted,
|
|
2232
|
+
camEnabled: !videoMuted
|
|
2233
|
+
});
|
|
2234
|
+
this.events.onMuteStateChanged?.(participantId, "audio", audioMuted);
|
|
2235
|
+
this.events.onMuteStateChanged?.(participantId, "video", videoMuted);
|
|
2236
|
+
},
|
|
2026
2237
|
onTrackPublished: (track) => {
|
|
2027
2238
|
console.log("[SFU] Track published", track);
|
|
2028
2239
|
},
|
|
@@ -2092,6 +2303,9 @@ var VideoSDKCore = class {
|
|
|
2092
2303
|
// SCREEN SHARE
|
|
2093
2304
|
onScreenShareStarted: (participantId, _track) => {
|
|
2094
2305
|
console.log("[SFU] Screen share started", participantId);
|
|
2306
|
+
if (participantId === this.myId && !this.screenStream) {
|
|
2307
|
+
this.screenStream = this.sfuClient?.getScreenStream() ?? null;
|
|
2308
|
+
}
|
|
2095
2309
|
this.state.setPresenterId(participantId);
|
|
2096
2310
|
if (participantId === this.myId) {
|
|
2097
2311
|
this.state.updateLocalParticipant({
|
|
@@ -2315,7 +2529,7 @@ var VideoSDKCore = class {
|
|
|
2315
2529
|
media: {
|
|
2316
2530
|
isScreenSharing: true,
|
|
2317
2531
|
screenStream: this.screenStream,
|
|
2318
|
-
screenTrack: this.screenStream
|
|
2532
|
+
screenTrack: this.screenStream?.getVideoTracks()[0]
|
|
2319
2533
|
}
|
|
2320
2534
|
});
|
|
2321
2535
|
return this.screenStream;
|
|
@@ -2372,18 +2586,20 @@ var VideoSDKCore = class {
|
|
|
2372
2586
|
console.warn("SFU Client not connected");
|
|
2373
2587
|
return;
|
|
2374
2588
|
}
|
|
2375
|
-
const
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
sender_name: senderName,
|
|
2380
|
-
text: payload.message.trim(),
|
|
2381
|
-
timestamp: Date.now(),
|
|
2589
|
+
const message = payload.message.trim();
|
|
2590
|
+
if (!message) return;
|
|
2591
|
+
this.sfuClient.sendChatMessage({
|
|
2592
|
+
message,
|
|
2382
2593
|
reply_to: payload.reply_to ?? null,
|
|
2383
2594
|
target: payload.target ?? null
|
|
2384
|
-
};
|
|
2385
|
-
|
|
2386
|
-
|
|
2595
|
+
});
|
|
2596
|
+
}
|
|
2597
|
+
sendReaction(reaction) {
|
|
2598
|
+
if (!this.sfuClient) {
|
|
2599
|
+
console.warn("SFU Client not connected");
|
|
2600
|
+
return;
|
|
2601
|
+
}
|
|
2602
|
+
this.sfuClient.sendReaction(reaction);
|
|
2387
2603
|
}
|
|
2388
2604
|
// CLEANUP
|
|
2389
2605
|
cleanupRemoteParticipant(participantId) {
|
|
@@ -2471,6 +2687,7 @@ var MeetingProvider = ({
|
|
|
2471
2687
|
const trackStateListeners = useRef(/* @__PURE__ */ new Set());
|
|
2472
2688
|
const recordingStartedListeners = useRef(/* @__PURE__ */ new Set());
|
|
2473
2689
|
const recordingStoppedListeners = useRef(/* @__PURE__ */ new Set());
|
|
2690
|
+
const reactionListeners = useRef(/* @__PURE__ */ new Set());
|
|
2474
2691
|
const activeSpeakerListeners = useRef(
|
|
2475
2692
|
/* @__PURE__ */ new Set()
|
|
2476
2693
|
);
|
|
@@ -2500,6 +2717,9 @@ var MeetingProvider = ({
|
|
|
2500
2717
|
},
|
|
2501
2718
|
onRecordingStopped: (recording) => {
|
|
2502
2719
|
recordingStoppedListeners.current.forEach((fn) => fn(recording));
|
|
2720
|
+
},
|
|
2721
|
+
onReaction: (reaction) => {
|
|
2722
|
+
reactionListeners.current.forEach((fn) => fn(reaction));
|
|
2503
2723
|
}
|
|
2504
2724
|
}
|
|
2505
2725
|
);
|
|
@@ -2546,6 +2766,7 @@ var MeetingProvider = ({
|
|
|
2546
2766
|
startScreenShare: sdk.startScreenShare.bind(sdk),
|
|
2547
2767
|
stopScreenShare: sdk.stopScreenShare.bind(sdk),
|
|
2548
2768
|
sendMessage: sdk.sendChatMessage.bind(sdk),
|
|
2769
|
+
sendReaction: sdk.sendReaction.bind(sdk),
|
|
2549
2770
|
room: sdk.getMeeting(),
|
|
2550
2771
|
localParticipant,
|
|
2551
2772
|
participants,
|
|
@@ -2602,6 +2823,10 @@ var MeetingProvider = ({
|
|
|
2602
2823
|
recordingStoppedListeners.current.add(cb);
|
|
2603
2824
|
return () => recordingStoppedListeners.current.delete(cb);
|
|
2604
2825
|
},
|
|
2826
|
+
onReaction: (cb) => {
|
|
2827
|
+
reactionListeners.current.add(cb);
|
|
2828
|
+
return () => reactionListeners.current.delete(cb);
|
|
2829
|
+
},
|
|
2605
2830
|
onActiveSpeakersChanged: (cb) => {
|
|
2606
2831
|
activeSpeakerListeners.current.add(cb);
|
|
2607
2832
|
return () => {
|
|
@@ -2698,6 +2923,10 @@ var useMeeting = (handlers) => {
|
|
|
2698
2923
|
if (!handlers?.onRecordingStopped) return;
|
|
2699
2924
|
return ctx.onRecordingStopped(handlers.onRecordingStopped);
|
|
2700
2925
|
}, [handlers?.onRecordingStopped]);
|
|
2926
|
+
useEffect3(() => {
|
|
2927
|
+
if (!handlers?.onReaction) return;
|
|
2928
|
+
return ctx.onReaction(handlers.onReaction);
|
|
2929
|
+
}, [handlers?.onReaction]);
|
|
2701
2930
|
const { sdk: _, ...publicApi } = ctx;
|
|
2702
2931
|
return publicApi;
|
|
2703
2932
|
};
|