@defcomm/meetingsdk 0.2.4 → 0.2.5

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.js CHANGED
@@ -385,9 +385,6 @@ var SFUClient = class {
385
385
  this.localStream = null;
386
386
  this.screenStream = null;
387
387
  this.videoSender = null;
388
- this.audioMuted = false;
389
- this.videoMuted = false;
390
- this.activeRecording = null;
391
388
  this.audioSender = null;
392
389
  this.screenSender = null;
393
390
  this.audioTransceiver = null;
@@ -408,7 +405,7 @@ var SFUClient = class {
408
405
  this.joiningWithResume = false;
409
406
  this.reconnectTimer = null;
410
407
  this.reconnectAttempt = 0;
411
- this.maxReconnectAttempts = 6;
408
+ this.maxReconnectAttempts = 8;
412
409
  this.reconnectBaseMs = 750;
413
410
  this.joinWaiter = null;
414
411
  this.transportRecoveryInProgress = false;
@@ -431,8 +428,7 @@ var SFUClient = class {
431
428
  this.trackToSource = /* @__PURE__ */ new Map();
432
429
  this.localTrackIds = /* @__PURE__ */ new Map();
433
430
  this.subscriberStatsTimer = null;
434
- this.roomSyncTimer = null;
435
- this.roomSyncInFlight = false;
431
+ this.lastRecordingId = null;
436
432
  this.heartbeatTimer = null;
437
433
  this.apiBase = options.apiBase || "https://api.example.com/api";
438
434
  this.wsBase = options.wsBase || "wss://api.example.com/ws";
@@ -445,6 +441,8 @@ var SFUClient = class {
445
441
  });
446
442
  this.onParticipantPresence = options.onParticipantPresence || (() => {
447
443
  });
444
+ this.onParticipantMediaState = options.onParticipantMediaState || (() => {
445
+ });
448
446
  this.onTrackPublished = options.onTrackPublished || (() => {
449
447
  });
450
448
  this.onTrackUnpublished = options.onTrackUnpublished || (() => {
@@ -471,14 +469,10 @@ var SFUClient = class {
471
469
  });
472
470
  this.onTrackStateChanged = options.onTrackStateChanged || (() => {
473
471
  });
474
- this.onParticipantMediaState = options.onParticipantMediaState || (() => {
475
- });
476
472
  this.onRecordingStarted = options.onRecordingStarted || (() => {
477
473
  });
478
474
  this.onRecordingStopped = options.onRecordingStopped || (() => {
479
475
  });
480
- this.onRoomState = options.onRoomState || (() => {
481
- });
482
476
  this.onError = options.onError || console.error;
483
477
  this.autoSubscribe = options.autoSubscribe !== false;
484
478
  }
@@ -500,29 +494,6 @@ var SFUClient = class {
500
494
  this.heartbeatTimer = null;
501
495
  }
502
496
  }
503
- startRoomStateSync() {
504
- this.stopRoomStateSync();
505
- this.roomSyncTimer = setInterval(() => {
506
- if (this.state !== "connected") return;
507
- void this.syncRoomState();
508
- }, 5e3);
509
- }
510
- stopRoomStateSync() {
511
- if (this.roomSyncTimer) {
512
- clearInterval(this.roomSyncTimer);
513
- this.roomSyncTimer = null;
514
- }
515
- this.roomSyncInFlight = false;
516
- }
517
- async syncRoomState() {
518
- if (this.roomSyncInFlight || !this.isSocketOpen()) return;
519
- this.roomSyncInFlight = true;
520
- try {
521
- this.send({ type: "sync_room_state" });
522
- } finally {
523
- this.roomSyncInFlight = false;
524
- }
525
- }
526
497
  createId() {
527
498
  return typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : `id_${Math.random().toString(36).slice(2)}_${Date.now()}`;
528
499
  }
@@ -620,13 +591,11 @@ var SFUClient = class {
620
591
  this.resumeToken = null;
621
592
  }
622
593
  this.room = nextRoom;
623
- this.audioMuted = Boolean(options.audioMuted);
624
- this.videoMuted = Boolean(options.videoMuted);
625
594
  this.joinOptions = {
626
595
  displayName: options.displayName,
627
596
  avatarUrl: options.avatarUrl,
628
- audioMuted: this.audioMuted,
629
- videoMuted: this.videoMuted
597
+ audioMuted: options.audioMuted,
598
+ videoMuted: options.videoMuted
630
599
  };
631
600
  if (options.participantId) this.participantId = options.participantId;
632
601
  if (!this.resumeToken) {
@@ -696,8 +665,8 @@ var SFUClient = class {
696
665
  resume_token: this.resumeToken,
697
666
  display_name: options.displayName,
698
667
  avatar_url: options.avatarUrl,
699
- audio_muted: this.audioMuted,
700
- video_muted: this.videoMuted
668
+ audio_muted: options.audioMuted ?? this.joinOptions.audioMuted ?? false,
669
+ video_muted: options.videoMuted ?? this.joinOptions.videoMuted ?? false
701
670
  };
702
671
  if (this.pendingJoinRequestId) {
703
672
  this.send({
@@ -738,20 +707,8 @@ var SFUClient = class {
738
707
  scheduleReconnect() {
739
708
  if (this.reconnectTimer || this.intentionalClose) return;
740
709
  if (this.reconnectAttempt >= this.maxReconnectAttempts) {
741
- const error = new Error("SFU reconnect attempts exhausted");
742
- console.error("[SFU] Reconnect attempts exhausted; leaving meeting", error);
743
- this.intentionalClose = true;
744
- this.stopHeartbeat();
745
- this.stopRoomStateSync();
746
- this.cleanupAll();
747
710
  this.setState("disconnected");
748
- this.onError({
749
- code: "RECONNECT_TIMEOUT",
750
- message: error.message,
751
- recoverable: false
752
- });
753
- this.onDisconnected();
754
- this.failJoin(error);
711
+ this.failJoin(new Error("SFU reconnect attempts exhausted"));
755
712
  return;
756
713
  }
757
714
  this.reconnectAttempt += 1;
@@ -824,8 +781,8 @@ var SFUClient = class {
824
781
  resume_token: this.resumeToken,
825
782
  display_name: this.joinOptions.displayName,
826
783
  avatar_url: this.joinOptions.avatarUrl,
827
- audio_muted: this.audioMuted,
828
- video_muted: this.videoMuted
784
+ audio_muted: this.joinOptions.audioMuted ?? false,
785
+ video_muted: this.joinOptions.videoMuted ?? false
829
786
  }
830
787
  });
831
788
  }
@@ -900,8 +857,22 @@ var SFUClient = class {
900
857
  if (!track?.track_id) break;
901
858
  this.rememberTrack(track);
902
859
  if (track.participant_id === this.currentParticipantId) {
903
- if (track.source === "audio") this.localTrackIds.set("audio", track.track_id);
904
- if (track.source === "camera") this.localTrackIds.set("camera", track.track_id);
860
+ if (track.source === "audio") {
861
+ this.localTrackIds.set("audio", track.track_id);
862
+ const muted = !(this.localStream?.getAudioTracks()[0]?.enabled ?? true);
863
+ this.send({
864
+ type: "track_state",
865
+ payload: { track_id: track.track_id, muted }
866
+ });
867
+ }
868
+ if (track.source === "camera") {
869
+ this.localTrackIds.set("camera", track.track_id);
870
+ const muted = !(this.localStream?.getVideoTracks()[0]?.enabled ?? true);
871
+ this.send({
872
+ type: "track_state",
873
+ payload: { track_id: track.track_id, muted }
874
+ });
875
+ }
905
876
  if (track.source === "screen")
906
877
  this.localTrackIds.set("screen", track.track_id);
907
878
  break;
@@ -930,27 +901,6 @@ var SFUClient = class {
930
901
  this.onTrackUnpublished(track);
931
902
  break;
932
903
  }
933
- case "participant_media_state": {
934
- const participantId = payload.participant_id;
935
- if (!participantId) break;
936
- const participant = this.participants.get(participantId);
937
- if (participant) {
938
- participant.audio_muted = Boolean(payload.audio_muted);
939
- participant.video_muted = Boolean(payload.video_muted);
940
- this.participants.set(participantId, participant);
941
- }
942
- for (const track of this.trackMetadata.values()) {
943
- if (track.participant_id !== participantId) continue;
944
- if (track.source === "audio") track.muted = Boolean(payload.audio_muted);
945
- if (track.source === "camera") track.muted = Boolean(payload.video_muted);
946
- }
947
- this.onParticipantMediaState(
948
- participantId,
949
- Boolean(payload.audio_muted),
950
- Boolean(payload.video_muted)
951
- );
952
- break;
953
- }
954
904
  case "track_state_changed": {
955
905
  const trackId = payload.track_id || payload.track?.track_id;
956
906
  if (!trackId) break;
@@ -972,20 +922,16 @@ var SFUClient = class {
972
922
  case "subscription_updated": {
973
923
  break;
974
924
  }
975
- case "room_state": {
976
- await this.applyRoomState(payload);
977
- break;
978
- }
979
925
  case "recording_started": {
980
- this.activeRecording = {
926
+ this.lastRecordingId = payload.recording_id || this.lastRecordingId;
927
+ this.onRecordingStarted({
981
928
  recording_id: payload.recording_id,
982
929
  started_at: payload.started_at
983
- };
984
- this.onRecordingStarted(this.activeRecording);
930
+ });
985
931
  break;
986
932
  }
987
933
  case "recording_stopped": {
988
- this.activeRecording = null;
934
+ this.lastRecordingId = null;
989
935
  this.onRecordingStopped({
990
936
  recording_id: payload.recording_id,
991
937
  stopped_at: payload.stopped_at
@@ -1021,6 +967,29 @@ var SFUClient = class {
1021
967
  this.onScreenShareStopped(participantId, trackId);
1022
968
  break;
1023
969
  }
970
+ case "room_state": {
971
+ await this.reconcileRoomState(payload);
972
+ break;
973
+ }
974
+ case "participant_media_state": {
975
+ const participantId = payload.participant_id;
976
+ if (participantId) {
977
+ const current = this.participants.get(participantId);
978
+ if (current) {
979
+ this.participants.set(participantId, {
980
+ ...current,
981
+ audio_muted: Boolean(payload.audio_muted),
982
+ video_muted: Boolean(payload.video_muted)
983
+ });
984
+ }
985
+ }
986
+ this.onParticipantMediaState?.(
987
+ participantId,
988
+ Boolean(payload.audio_muted),
989
+ Boolean(payload.video_muted)
990
+ );
991
+ break;
992
+ }
1024
993
  case "error": {
1025
994
  const message2 = payload.message || "SFU signaling error";
1026
995
  if (this.state === "reconnecting" && message2.includes("participant session is stale")) {
@@ -1043,66 +1012,89 @@ var SFUClient = class {
1043
1012
  console.debug("[SFU] Ignoring unknown server message", message);
1044
1013
  }
1045
1014
  }
1046
- async applyRoomState(payload) {
1047
- const authoritative = /* @__PURE__ */ new Map();
1048
- for (const participant of payload?.participants || []) {
1049
- if (participant?.participant_id) authoritative.set(participant.participant_id, participant);
1015
+ async reconcileRoomState(payload) {
1016
+ const nextParticipants = /* @__PURE__ */ new Map();
1017
+ for (const participant of payload.participants || []) {
1018
+ if (participant?.participant_id) {
1019
+ nextParticipants.set(participant.participant_id, participant);
1020
+ }
1050
1021
  }
1051
- for (const id of [...this.participants.keys()]) {
1052
- if (!authoritative.has(id) && id !== this.currentParticipantId) {
1053
- this.participants.delete(id);
1054
- this.removeRemoteParticipant(id);
1055
- this.onParticipantLeft(id);
1022
+ for (const participantId of this.participants.keys()) {
1023
+ if (participantId !== this.currentParticipantId && !nextParticipants.has(participantId)) {
1024
+ this.participants.delete(participantId);
1025
+ this.onParticipantLeft(participantId);
1056
1026
  }
1057
1027
  }
1058
- for (const [id, participant] of authoritative) {
1059
- if (id === this.currentParticipantId) continue;
1060
- const previous = this.participants.get(id);
1061
- this.participants.set(id, {
1062
- ...previous,
1063
- ...participant,
1064
- audio_muted: Boolean(participant.audio_muted),
1065
- video_muted: Boolean(participant.video_muted)
1066
- });
1067
- if (!previous) this.onParticipantJoined(participant);
1068
- if (participant.presence) this.onParticipantPresence(id, String(participant.presence));
1028
+ for (const participant of nextParticipants.values()) {
1029
+ if (participant.participant_id === this.currentParticipantId) continue;
1030
+ const previous = this.participants.get(participant.participant_id);
1031
+ const wasScreenSharing = Boolean(previous?.screen_sharing);
1032
+ const isScreenSharing = Boolean(participant.screen_sharing);
1033
+ this.participants.set(participant.participant_id, participant);
1034
+ if (!previous) {
1035
+ this.onParticipantJoined(participant);
1036
+ }
1037
+ if (participant.presence) {
1038
+ this.onParticipantPresence(
1039
+ participant.participant_id,
1040
+ String(participant.presence).toLowerCase()
1041
+ );
1042
+ }
1043
+ this.onParticipantMediaState(
1044
+ participant.participant_id,
1045
+ Boolean(participant.audio_muted),
1046
+ Boolean(participant.video_muted)
1047
+ );
1048
+ if (!wasScreenSharing && isScreenSharing) {
1049
+ this.onScreenShareStarted(participant.participant_id, void 0);
1050
+ } else if (wasScreenSharing && !isScreenSharing) {
1051
+ this.onScreenShareStopped(
1052
+ participant.participant_id,
1053
+ participant.screen_track_id || void 0
1054
+ );
1055
+ }
1069
1056
  }
1070
1057
  const nextTracks = /* @__PURE__ */ new Map();
1071
- for (const track of payload?.tracks || []) {
1072
- if (!track?.track_id) continue;
1073
- nextTracks.set(track.track_id, track);
1074
- this.rememberTrack(track);
1075
- }
1076
- for (const id of [...this.trackMetadata.keys()]) {
1077
- if (!nextTracks.has(id)) {
1078
- this.trackMetadata.delete(id);
1079
- this.subscribedTracks.delete(id);
1080
- this.trackToParticipant.delete(id);
1081
- this.trackToSource.delete(id);
1082
- }
1083
- }
1084
- if (payload?.recording) {
1085
- const current = {
1086
- recording_id: payload.recording.recording_id,
1087
- started_at: payload.recording.started_at
1088
- };
1089
- if (!this.activeRecording || this.activeRecording.recording_id !== current.recording_id) {
1090
- this.activeRecording = current;
1091
- this.onRecordingStarted(current);
1058
+ for (const track of payload.tracks || []) {
1059
+ if (track?.track_id) {
1060
+ nextTracks.set(track.track_id, track);
1061
+ this.rememberTrack(track);
1062
+ }
1063
+ }
1064
+ for (const [trackId, oldTrack] of [...this.trackMetadata.entries()]) {
1065
+ if (!nextTracks.has(trackId)) {
1066
+ this.trackMetadata.delete(trackId);
1067
+ this.trackToParticipant.delete(trackId);
1068
+ this.trackToSource.delete(trackId);
1069
+ this.subscribedTracks.delete(trackId);
1070
+ if (oldTrack.participant_id !== this.currentParticipantId) {
1071
+ this.onTrackUnpublished(oldTrack);
1072
+ }
1092
1073
  }
1093
- } else if (this.activeRecording) {
1094
- const previous = this.activeRecording;
1095
- this.activeRecording = null;
1096
- this.onRecordingStopped({
1097
- recording_id: previous.recording_id,
1098
- stopped_at: (/* @__PURE__ */ new Date()).toISOString()
1099
- });
1100
1074
  }
1101
1075
  if (this.autoSubscribe) {
1102
- const missing = [...nextTracks.values()].filter((t) => t.participant_id !== this.currentParticipantId && !this.subscribedTracks.has(t.track_id)).map((t) => t.track_id);
1076
+ const missing = [...nextTracks.values()].filter(
1077
+ (track) => track.participant_id !== this.currentParticipantId && !this.subscribedTracks.has(track.track_id)
1078
+ ).map((track) => track.track_id);
1103
1079
  if (missing.length) await this.subscribeMultiple(missing);
1104
1080
  }
1105
- this.onRoomState(payload);
1081
+ const nextRecordingId = payload.recording?.recording_id || null;
1082
+ if (payload.recording) {
1083
+ if (this.lastRecordingId !== nextRecordingId) {
1084
+ this.lastRecordingId = nextRecordingId;
1085
+ this.onRecordingStarted({
1086
+ recording_id: payload.recording.recording_id,
1087
+ started_at: payload.recording.started_at
1088
+ });
1089
+ }
1090
+ } else if (this.lastRecordingId) {
1091
+ const recordingId = this.lastRecordingId;
1092
+ this.lastRecordingId = null;
1093
+ this.onRecordingStopped({
1094
+ recording_id: recordingId,
1095
+ stopped_at: (/* @__PURE__ */ new Date()).toISOString()
1096
+ });
1097
+ }
1106
1098
  }
1107
1099
  rememberTrack(track) {
1108
1100
  this.trackMetadata.set(track.track_id, track);
@@ -1133,23 +1125,8 @@ var SFUClient = class {
1133
1125
  for (const track of payload.tracks || []) {
1134
1126
  if (track?.track_id) this.rememberTrack(track);
1135
1127
  }
1136
- if (payload.recording) {
1137
- this.activeRecording = {
1138
- recording_id: payload.recording.recording_id,
1139
- started_at: payload.recording.started_at
1140
- };
1141
- this.onRecordingStarted(this.activeRecording);
1142
- } else if (this.activeRecording) {
1143
- const previous = this.activeRecording;
1144
- this.activeRecording = null;
1145
- this.onRecordingStopped({
1146
- recording_id: previous.recording_id,
1147
- stopped_at: (/* @__PURE__ */ new Date()).toISOString()
1148
- });
1149
- }
1150
1128
  await this.initializePeerConnections();
1151
1129
  this.setState("connected");
1152
- this.startRoomStateSync();
1153
1130
  this.onConnected(payload, resumed);
1154
1131
  for (const participant of this.participants.values()) {
1155
1132
  if (participant.participant_id !== this.currentParticipantId) {
@@ -1605,31 +1582,25 @@ var SFUClient = class {
1605
1582
  this.localStream?.getAudioTracks().forEach((track) => {
1606
1583
  track.enabled = !muted;
1607
1584
  });
1608
- const trackId = this.localTrackIds.get("audio");
1609
- if (trackId) {
1610
- this.send({
1611
- type: "track_state",
1612
- payload: {
1613
- track_id: trackId,
1614
- muted
1615
- }
1616
- });
1617
- }
1585
+ this.send({
1586
+ type: "set_media_state",
1587
+ payload: {
1588
+ audio_muted: muted,
1589
+ video_muted: !(this.localStream?.getVideoTracks()[0]?.enabled ?? true)
1590
+ }
1591
+ });
1618
1592
  }
1619
1593
  muteVideo(muted) {
1620
1594
  this.localStream?.getVideoTracks().forEach((track) => {
1621
1595
  track.enabled = !muted;
1622
1596
  });
1623
- const trackId = this.localTrackIds.get("camera");
1624
- if (trackId) {
1625
- this.send({
1626
- type: "track_state",
1627
- payload: {
1628
- track_id: trackId,
1629
- muted
1630
- }
1631
- });
1632
- }
1597
+ this.send({
1598
+ type: "set_media_state",
1599
+ payload: {
1600
+ audio_muted: !(this.localStream?.getAudioTracks()[0]?.enabled ?? true),
1601
+ video_muted: muted
1602
+ }
1603
+ });
1633
1604
  }
1634
1605
  async startRecording() {
1635
1606
  if (!this.send({ type: "start_recording" })) {
@@ -1704,7 +1675,6 @@ var SFUClient = class {
1704
1675
  }
1705
1676
  async leave() {
1706
1677
  this.stopHeartbeat();
1707
- this.stopRoomStateSync();
1708
1678
  this.intentionalClose = true;
1709
1679
  this.setState("leaving");
1710
1680
  if (this.reconnectTimer) {
@@ -2072,13 +2042,9 @@ var VideoSDKCore = class {
2072
2042
  );
2073
2043
  return;
2074
2044
  }
2075
- if (state === "disconnected" || state === "idle") {
2076
- this.sfuClient = null;
2077
- } else {
2078
- throw new Error(
2079
- `SFU client already exists in state "${state}". Disconnect explicitly before creating another connection.`
2080
- );
2081
- }
2045
+ throw new Error(
2046
+ `SFU client already exists in state "${state}". Disconnect explicitly before creating another connection.`
2047
+ );
2082
2048
  }
2083
2049
  const client = new SFUClient({
2084
2050
  apiBase: this.apiBase,
@@ -2093,50 +2059,12 @@ var VideoSDKCore = class {
2093
2059
  console.log(`[SFU] ${resumed ? "Resumed" : "Joined"} room`, payload);
2094
2060
  this.state.updateLocalParticipant({
2095
2061
  id: this.myId,
2096
- name: this.participantName
2097
- });
2098
- },
2099
- onRoomState: (roomState) => {
2100
- for (const participant of roomState?.participants || []) {
2101
- const pid = participant?.participant_id;
2102
- if (!pid || pid === this.myId) continue;
2103
- const current = this.state.getParticipant(pid);
2104
- if (!current) continue;
2105
- this.state.updateParticipantMedia(pid, {
2106
- stream: current.media?.stream ?? null,
2107
- micEnabled: !Boolean(participant.audio_muted),
2108
- camEnabled: !Boolean(participant.video_muted),
2109
- isScreenSharing: Boolean(participant.screen_sharing)
2110
- });
2111
- }
2112
- const presenters = /* @__PURE__ */ new Set();
2113
- for (const participant of roomState?.participants || []) {
2114
- const pid = participant?.participant_id;
2115
- if (!pid || pid === this.myId) continue;
2116
- const current = this.state.getParticipant(pid);
2117
- if (!current) continue;
2118
- if (participant.screen_sharing) {
2119
- presenters.add(pid);
2120
- this.state.updateParticipantMedia(pid, {
2121
- isScreenSharing: true,
2122
- screenStream: current.media?.screenStream ?? null
2123
- });
2124
- } else if (current.media?.isScreenSharing) {
2125
- const screen = this.remoteScreenStreams.get(pid);
2126
- screen?.getTracks().forEach((track) => track.stop());
2127
- this.remoteScreenStreams.delete(pid);
2128
- this.state.updateParticipantMedia(pid, {
2129
- isScreenSharing: false,
2130
- screenStream: null,
2131
- screenTrack: void 0
2132
- });
2062
+ name: this.participantName,
2063
+ media: {
2064
+ micEnabled: this.localStream?.getAudioTracks()[0]?.enabled ?? true,
2065
+ camEnabled: this.localStream?.getVideoTracks()[0]?.enabled ?? true
2133
2066
  }
2134
- }
2135
- const presenter = [...presenters][0] ?? null;
2136
- if (this.state.presenterId !== presenter) {
2137
- this.state.setPresenterId(presenter);
2138
- }
2139
- this.events.onRoomUpdate?.(roomState);
2067
+ });
2140
2068
  },
2141
2069
  onDisconnected: () => {
2142
2070
  console.log("[SFU] Signaling WebSocket disconnected; reconnecting");
@@ -2204,22 +2132,44 @@ var VideoSDKCore = class {
2204
2132
  return;
2205
2133
  }
2206
2134
  const pname = participant.user_metadata?.name || participant.display_name || "Participant";
2207
- this.state.addParticipant({
2135
+ const participantMedia = participant.media || {};
2136
+ const participantState = {
2208
2137
  id: pid,
2209
2138
  name: pname,
2210
- connectionState: "connected",
2139
+ connectionState: participant.presence === "reconnecting" ? "reconnecting" : "connected",
2211
2140
  media: {
2212
2141
  micEnabled: !Boolean(participant.audio_muted),
2213
2142
  camEnabled: !Boolean(participant.video_muted),
2214
- isScreenSharing: false,
2143
+ isScreenSharing: Boolean(participant.screen_sharing),
2144
+ screenStream: participantMedia.screenStream ?? null,
2215
2145
  stream: null
2216
2146
  }
2217
- });
2147
+ };
2148
+ if (!this.state.addParticipant(participantState)) {
2149
+ this.state.updateParticipantMedia(pid, participantState.media);
2150
+ }
2218
2151
  this.events.onUserJoined?.({
2219
2152
  id: pid,
2220
2153
  name: pname
2221
2154
  });
2222
2155
  },
2156
+ onParticipantMediaState: (participantId, audioMuted, videoMuted) => {
2157
+ if (participantId === this.myId) {
2158
+ this.state.updateLocalParticipant({
2159
+ media: {
2160
+ micEnabled: !audioMuted,
2161
+ camEnabled: !videoMuted
2162
+ }
2163
+ });
2164
+ return;
2165
+ }
2166
+ this.state.updateParticipantMedia(participantId, {
2167
+ micEnabled: !audioMuted,
2168
+ camEnabled: !videoMuted
2169
+ });
2170
+ this.events.onMuteStateChanged?.(participantId, "audio", audioMuted);
2171
+ this.events.onMuteStateChanged?.(participantId, "video", videoMuted);
2172
+ },
2223
2173
  onParticipantPresence: (participantId, presence) => {
2224
2174
  if (participantId === this.myId) {
2225
2175
  return;
@@ -2283,18 +2233,6 @@ var VideoSDKCore = class {
2283
2233
  camEnabled: track.kind === "video" ? false : current.media?.camEnabled ?? true
2284
2234
  });
2285
2235
  },
2286
- onParticipantMediaState: (participantId, audioMuted, videoMuted) => {
2287
- if (participantId === this.myId) return;
2288
- const current = this.state.getParticipant(participantId);
2289
- if (!current) return;
2290
- this.state.updateParticipantMedia(participantId, {
2291
- stream: current.media?.stream ?? null,
2292
- micEnabled: !audioMuted,
2293
- camEnabled: !videoMuted
2294
- });
2295
- this.events.onMuteStateChanged?.(participantId, "audio", audioMuted);
2296
- this.events.onMuteStateChanged?.(participantId, "video", videoMuted);
2297
- },
2298
2236
  onTrackStateChanged: (track) => {
2299
2237
  const pid = track.participant_id;
2300
2238
  if (!pid || pid === this.myId) {
@@ -2396,8 +2334,8 @@ var VideoSDKCore = class {
2396
2334
  await client.getToken(roomId, {
2397
2335
  displayName: name,
2398
2336
  participantId: this.myId,
2399
- audioMuted: this.state.localParticipant?.media?.micEnabled,
2400
- videoMuted: this.state.localParticipant?.media?.camEnabled
2337
+ audioMuted: !this.localStream?.getAudioTracks()[0]?.enabled,
2338
+ videoMuted: !this.localStream?.getVideoTracks()[0]?.enabled
2401
2339
  });
2402
2340
  }
2403
2341
  // SFU STATE
@@ -2561,6 +2499,7 @@ var VideoSDKCore = class {
2561
2499
  screenTrack: this.screenStream.getVideoTracks()[0]
2562
2500
  }
2563
2501
  });
2502
+ this.state.setPresenterId(this.myId);
2564
2503
  return this.screenStream;
2565
2504
  } catch (err) {
2566
2505
  this.emitError(
@@ -2582,6 +2521,9 @@ var VideoSDKCore = class {
2582
2521
  this.screenStream.getTracks().forEach((track) => track.stop());
2583
2522
  this.screenStream = null;
2584
2523
  this.isScreenSharing = false;
2524
+ if (this.state.presenterId === this.myId) {
2525
+ this.state.setPresenterId(null);
2526
+ }
2585
2527
  this.state.updateLocalParticipant({
2586
2528
  media: {
2587
2529
  isScreenSharing: false,
@@ -2711,7 +2653,6 @@ var MeetingProvider = ({
2711
2653
  /* @__PURE__ */ new Set()
2712
2654
  );
2713
2655
  const meetingLeftListeners = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
2714
- const roomUpdateListeners = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
2715
2656
  const trackStateListeners = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
2716
2657
  const recordingStartedListeners = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
2717
2658
  const recordingStoppedListeners = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
@@ -2736,9 +2677,6 @@ var MeetingProvider = ({
2736
2677
  onMeetingLeft: () => {
2737
2678
  meetingLeftListeners.current.forEach((fn) => fn());
2738
2679
  },
2739
- onRoomUpdate: (data) => {
2740
- roomUpdateListeners.current.forEach((fn) => fn(data));
2741
- },
2742
2680
  onTrackStateChanged: (track) => {
2743
2681
  trackStateListeners.current.forEach((fn) => fn(track));
2744
2682
  },
@@ -2837,10 +2775,6 @@ var MeetingProvider = ({
2837
2775
  meetingLeftListeners.current.delete(cb);
2838
2776
  };
2839
2777
  },
2840
- onRoomUpdate: (cb) => {
2841
- roomUpdateListeners.current.add(cb);
2842
- return () => roomUpdateListeners.current.delete(cb);
2843
- },
2844
2778
  onTrackStateChanged: (cb) => {
2845
2779
  trackStateListeners.current.add(cb);
2846
2780
  return () => trackStateListeners.current.delete(cb);