@afosecure/meetingsdk 1.3.2 → 1.3.4

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 CHANGED
@@ -38,6 +38,8 @@ type ChatMessage = {
38
38
  type Participant = {
39
39
  id: string;
40
40
  name?: string;
41
+ isHost?: boolean;
42
+ isLocal?: boolean;
41
43
  media?: ParticipantMedia;
42
44
  };
43
45
  type ParticipantMedia = {
@@ -50,6 +52,7 @@ type ParticipantMedia = {
50
52
  camEnabled: boolean;
51
53
  isScreenSharing: boolean;
52
54
  remoteScreenStreamId?: string;
55
+ cameraStreamId?: string;
53
56
  };
54
57
  type Listener = () => void;
55
58
  type ChatInput = {
@@ -130,7 +133,7 @@ declare class VideoSDKCore {
130
133
  private localStream;
131
134
  private screenStream;
132
135
  private isScreenSharing;
133
- private peerTransceivers;
136
+ private screenSenders;
134
137
  private pingInterval;
135
138
  private pendingIceCandidates;
136
139
  private pendingOffers;
@@ -160,27 +163,14 @@ declare class VideoSDKCore {
160
163
  private handleJoinApproved;
161
164
  private handle;
162
165
  private createPeer;
163
- /**
164
- * Capture the screen transceiver's MID after SDP negotiation completes.
165
- * The MID is assigned during negotiation and is stable for the life of the connection.
166
- */
167
- private captureScreenMid;
168
166
  private createOffer;
169
167
  private shouldInitiate;
170
168
  private handleOffer;
171
169
  private closePeer;
172
- /**
173
- * Start screen sharing using replaceTrack on the pre-established screen transceiver.
174
- * No need to add/remove tracks, no renegotiation needed (transceiver already in SDP).
175
- * Just swap the track and update direction if needed.
176
- */
177
170
  startScreenShare(): Promise<MediaStream>;
178
- /**
179
- * Stop screen sharing: clear the screen transceiver track and flip direction back to recvonly.
180
- */
181
- stopScreenShare(): Promise<void>;
171
+ stopScreenShare(): void;
182
172
  sendChatMessage(payload: ChatInput): void;
183
- disconnect(): Promise<void>;
173
+ disconnect(): void;
184
174
  private flushIce;
185
175
  private send;
186
176
  approveJoinRequest(requestId: string): void;
package/dist/index.d.ts CHANGED
@@ -38,6 +38,8 @@ type ChatMessage = {
38
38
  type Participant = {
39
39
  id: string;
40
40
  name?: string;
41
+ isHost?: boolean;
42
+ isLocal?: boolean;
41
43
  media?: ParticipantMedia;
42
44
  };
43
45
  type ParticipantMedia = {
@@ -50,6 +52,7 @@ type ParticipantMedia = {
50
52
  camEnabled: boolean;
51
53
  isScreenSharing: boolean;
52
54
  remoteScreenStreamId?: string;
55
+ cameraStreamId?: string;
53
56
  };
54
57
  type Listener = () => void;
55
58
  type ChatInput = {
@@ -130,7 +133,7 @@ declare class VideoSDKCore {
130
133
  private localStream;
131
134
  private screenStream;
132
135
  private isScreenSharing;
133
- private peerTransceivers;
136
+ private screenSenders;
134
137
  private pingInterval;
135
138
  private pendingIceCandidates;
136
139
  private pendingOffers;
@@ -160,27 +163,14 @@ declare class VideoSDKCore {
160
163
  private handleJoinApproved;
161
164
  private handle;
162
165
  private createPeer;
163
- /**
164
- * Capture the screen transceiver's MID after SDP negotiation completes.
165
- * The MID is assigned during negotiation and is stable for the life of the connection.
166
- */
167
- private captureScreenMid;
168
166
  private createOffer;
169
167
  private shouldInitiate;
170
168
  private handleOffer;
171
169
  private closePeer;
172
- /**
173
- * Start screen sharing using replaceTrack on the pre-established screen transceiver.
174
- * No need to add/remove tracks, no renegotiation needed (transceiver already in SDP).
175
- * Just swap the track and update direction if needed.
176
- */
177
170
  startScreenShare(): Promise<MediaStream>;
178
- /**
179
- * Stop screen sharing: clear the screen transceiver track and flip direction back to recvonly.
180
- */
181
- stopScreenShare(): Promise<void>;
171
+ stopScreenShare(): void;
182
172
  sendChatMessage(payload: ChatInput): void;
183
- disconnect(): Promise<void>;
173
+ disconnect(): void;
184
174
  private flushIce;
185
175
  private send;
186
176
  approveJoinRequest(requestId: string): void;
package/dist/index.js CHANGED
@@ -101,9 +101,7 @@ var MeetingState = class {
101
101
  camEnabled: true,
102
102
  isScreenSharing: false,
103
103
  ...p.media,
104
- // preserve existing media items if they happen to exist
105
104
  ...patch
106
- // apply the incoming stream updates
107
105
  }
108
106
  };
109
107
  const next = new Map(this.participants);
@@ -210,8 +208,7 @@ var VideoSDKCore = class {
210
208
  this.localStream = null;
211
209
  this.screenStream = null;
212
210
  this.isScreenSharing = false;
213
- // Transceiver-based tracking: maps peerId -> { cameraTransceiver, screenTransceiver, screenMid }
214
- this.peerTransceivers = {};
211
+ this.screenSenders = {};
215
212
  this.pingInterval = null;
216
213
  this.pendingIceCandidates = {};
217
214
  this.pendingOffers = {};
@@ -240,7 +237,7 @@ var VideoSDKCore = class {
240
237
  this.joinRejecter = void 0;
241
238
  console.error("[MeetingSDK Error]", err);
242
239
  }
243
- // STREAM
240
+ // ---------------- STREAM ----------------
244
241
  async initLocal(video, name) {
245
242
  this.participantName = name;
246
243
  try {
@@ -277,7 +274,7 @@ var VideoSDKCore = class {
277
274
  throw err;
278
275
  }
279
276
  }
280
- // CONNECT
277
+ // ---------------- CONNECT ----------------
281
278
  async connect(roomId, name) {
282
279
  this.room.id = roomId;
283
280
  this.reset();
@@ -291,7 +288,8 @@ var VideoSDKCore = class {
291
288
  type: "JOIN",
292
289
  room_id: roomId,
293
290
  user_id: this.myId,
294
- sender_name: name
291
+ sender_name: name,
292
+ camera_stream_id: this.localStream?.id.replace(/[{}]/g, "")
295
293
  });
296
294
  };
297
295
  this.ws.onerror = (err) => {
@@ -423,11 +421,10 @@ var VideoSDKCore = class {
423
421
  this.pingInterval = null;
424
422
  }
425
423
  }
426
- // RESET
424
+ // ---------------- RESET ----------------
427
425
  reset() {
428
426
  Object.values(this.peers).forEach((pc) => pc.close());
429
427
  this.peers = {};
430
- this.peerTransceivers = {};
431
428
  this.initiators.clear();
432
429
  this.pendingIceCandidates = {};
433
430
  this.state.resetRemoteState();
@@ -482,7 +479,6 @@ var VideoSDKCore = class {
482
479
  type: "answer",
483
480
  sdp: msg.payload
484
481
  });
485
- this.captureScreenMid(msg.sender);
486
482
  await this.flushIce(msg.sender, pc);
487
483
  } catch (err) {
488
484
  console.error("[Signaling] Failed to apply answer:", err);
@@ -519,6 +515,7 @@ var VideoSDKCore = class {
519
515
  if (msg.presenterId) {
520
516
  this.state.setPresenterId(msg.presenterId);
521
517
  this.events.onScreenShareStarted?.(msg.presenterId, null);
518
+ this.state.setPresenterId(msg.presenterId);
522
519
  }
523
520
  for (const p of msg.participants || []) {
524
521
  if (!p?.id || p.id === this.myId) continue;
@@ -531,7 +528,8 @@ var VideoSDKCore = class {
531
528
  this.state.setPresenterId(p.id);
532
529
  this.state.updateParticipantMedia(p.id, {
533
530
  isScreenSharing: true,
534
- remoteScreenStreamId: p.remoteScreenStreamId
531
+ remoteScreenStreamId: p.remoteScreenStreamId,
532
+ cameraStreamId: p.cameraStreamId || null
535
533
  });
536
534
  console.log(
537
535
  `[EXISTING_USERS] Pre-seeded screen state for ${p.id}, waiting for ontrack`
@@ -601,10 +599,12 @@ var VideoSDKCore = class {
601
599
  });
602
600
  break;
603
601
  }
602
+ // ============ NEW: HANDLE JOIN_APPROVED WITH RECONNECT ============
604
603
  case "JOIN_APPROVED": {
605
604
  await this.handleJoinApproved(msg);
606
605
  break;
607
606
  }
607
+ // ============ END: JOIN_APPROVED ============
608
608
  case "JOIN_REJECTED": {
609
609
  const decision = "rejected";
610
610
  console.log("JOIN_REJECTED - user not allowed to join");
@@ -652,12 +652,14 @@ var VideoSDKCore = class {
652
652
  const peerId2 = msg.peerId;
653
653
  this.state.updateParticipantMedia(peerId2, {
654
654
  isScreenSharing: true,
655
- remoteScreenStreamId: msg.stream_id
655
+ remoteScreenStreamId: msg.stream_id,
656
+ cameraStreamId: msg.camera_stream_id || null
656
657
  });
657
658
  if (!this.state.presenterId) {
658
659
  this.state.setPresenterId(peerId2);
659
660
  }
660
- this.events.onScreenShareStarted?.(peerId2, null);
661
+ const screenStream = this.state.getParticipant(peerId2)?.media?.screenStream;
662
+ this.events.onScreenShareStarted?.(peerId2, screenStream || null);
661
663
  break;
662
664
  }
663
665
  case "SCREEN_SHARE_STOP": {
@@ -684,7 +686,8 @@ var VideoSDKCore = class {
684
686
  }
685
687
  }
686
688
  }
687
- async createPeer(id) {
689
+ // ---------------- PEER ----------------
690
+ createPeer(id) {
688
691
  if (!this.localStream) throw new Error("No local stream");
689
692
  if (!this.iceServers || this.iceServers.length === 0) {
690
693
  throw new Error(
@@ -692,9 +695,7 @@ var VideoSDKCore = class {
692
695
  );
693
696
  }
694
697
  console.log(
695
- "Creating peer connection for",
696
- id,
697
- "with tracks:",
698
+ "Adding tracks",
698
699
  this.localStream.getTracks().map((t) => ({
699
700
  kind: t.kind,
700
701
  enabled: t.enabled,
@@ -704,58 +705,40 @@ var VideoSDKCore = class {
704
705
  const pc = new RTCPeerConnection({
705
706
  iceServers: this.iceServers
706
707
  });
707
- const audioTransceiver = pc.addTransceiver("audio", {
708
- direction: "sendrecv"
709
- });
710
- const audioTrack = this.localStream.getAudioTracks()[0];
711
- if (audioTrack) {
712
- await audioTransceiver.sender.replaceTrack(audioTrack);
713
- }
714
- const cameraTransceiver = pc.addTransceiver("video", {
715
- direction: "sendrecv"
716
- });
717
- const videoTrack = this.localStream.getVideoTracks()[0];
718
- if (videoTrack) {
719
- await cameraTransceiver.sender.replaceTrack(videoTrack);
720
- }
721
- const screenTransceiver = pc.addTransceiver("video", {
722
- direction: this.isScreenSharing ? "sendrecv" : "recvonly"
723
- });
724
- if (this.isScreenSharing && this.screenStream) {
725
- const screenTrack = this.screenStream.getVideoTracks()[0];
726
- if (screenTrack) {
727
- await screenTransceiver.sender.replaceTrack(screenTrack);
728
- }
729
- }
730
- this.peerTransceivers[id] = {
731
- cameraTransceiver,
732
- screenTransceiver,
733
- screenMid: null
734
- // will be populated after negotiation
735
- };
736
708
  pc.ontrack = (event) => {
737
- const transceiver = event.transceiver;
738
- const isScreenTrack = transceiver === this.peerTransceivers[id]?.screenTransceiver;
709
+ console.log("ontrack");
710
+ console.log("kind:", event.track.kind);
711
+ console.log("mid:", event.transceiver.mid);
712
+ console.log("streams:", event.streams);
713
+ const incomingStream = event.streams?.[0] || new MediaStream([event.track]);
714
+ const streamId = incomingStream?.id;
715
+ const participant = this.state.getParticipant(id);
716
+ const isScreenStream = streamId && (streamId === participant?.media?.remoteScreenStreamId || participant?.media?.isScreenSharing && streamId !== participant?.media?.stream?.id && event.track.kind === "video");
739
717
  console.log(
740
- `[ontrack] ${id}: kind=${event.track.kind}, mid=${transceiver.mid}, isScreen=${isScreenTrack}`
718
+ `[ontrack] peerId: ${id}, streamId: ${streamId}, isScreen: ${isScreenStream}`
719
+ );
720
+ console.log(` - cameraStreamId: ${participant?.media?.cameraStreamId}`);
721
+ console.log(
722
+ ` - screenStreamId: ${participant?.media?.remoteScreenStreamId}`
741
723
  );
742
- const incomingStream = event.streams?.[0] || new MediaStream([event.track]);
743
724
  if (event.track.muted) {
744
725
  event.track.onunmute = () => {
745
- console.log(`[ontrack] ${event.track.kind} track unmuted for ${id}`);
726
+ console.log(`${event.track.kind} track unmuted for ${id}`);
746
727
  };
747
728
  }
748
- if (isScreenTrack) {
749
- const videoTrack2 = event.track.kind === "video" ? event.track : incomingStream.getVideoTracks()[0];
729
+ if (isScreenStream) {
730
+ const videoTrack = event.track.kind === "video" ? event.track : incomingStream.getVideoTracks()[0] || participant?.media?.screenTrack;
750
731
  this.state.updateParticipantMedia(id, {
751
732
  screenStream: incomingStream,
752
- screenTrack: videoTrack2,
733
+ screenTrack: videoTrack,
734
+ remoteScreenStreamId: incomingStream.id,
753
735
  isScreenSharing: true
754
736
  });
755
737
  if (!this.state.presenterId) {
756
738
  this.state.setPresenterId(id);
757
739
  }
758
740
  this.events.onScreenShareStarted?.(id, incomingStream);
741
+ console.log(`Screen share stream detected and stored for ${id}`);
759
742
  } else {
760
743
  this.state.updateParticipantMedia(id, {
761
744
  stream: incomingStream,
@@ -775,41 +758,29 @@ var VideoSDKCore = class {
775
758
  });
776
759
  };
777
760
  pc.oniceconnectionstatechange = () => {
778
- console.log(`[ICE Connection] ${id}: ${pc.iceConnectionState}`);
761
+ console.log(`ICE Connection State: ${pc.iceConnectionState}`);
779
762
  };
780
763
  pc.onconnectionstatechange = () => {
781
- console.log(`[Connection] ${id}: ${pc.connectionState}`);
782
764
  if (pc.connectionState === "failed") {
783
765
  try {
784
766
  pc.restartIce();
785
- } catch (e) {
786
- console.warn("Failed to restart ICE:", e);
767
+ } catch {
787
768
  }
788
769
  }
789
770
  };
790
- return pc;
791
- }
792
- /**
793
- * Capture the screen transceiver's MID after SDP negotiation completes.
794
- * The MID is assigned during negotiation and is stable for the life of the connection.
795
- */
796
- captureScreenMid(peerId) {
797
- const pc = this.peers[peerId];
798
- if (!pc) return;
799
- const transceivers = pc.getTransceivers();
800
- const screenTransceiver = this.peerTransceivers[peerId]?.screenTransceiver;
801
- if (!screenTransceiver) return;
802
- const negotiatedTransceiver = transceivers.find(
803
- (t) => t === screenTransceiver
804
- );
805
- if (negotiatedTransceiver?.mid) {
806
- this.peerTransceivers[peerId].screenMid = negotiatedTransceiver.mid;
807
- console.log(
808
- `[Negotiation] Captured screenMid for ${peerId}: ${negotiatedTransceiver.mid}`
809
- );
771
+ this.localStream.getTracks().forEach((track) => {
772
+ pc.addTrack(track, this.localStream);
773
+ });
774
+ if (this.isScreenSharing && this.screenStream) {
775
+ this.screenSenders[id] = [];
776
+ this.screenStream.getTracks().forEach((track) => {
777
+ const sender = pc.addTrack(track, this.screenStream);
778
+ this.screenSenders[id].push(sender);
779
+ });
810
780
  }
781
+ return pc;
811
782
  }
812
- // OFFER
783
+ // ---------------- OFFER ----------------
813
784
  async createOffer(id, isRenegotiation = false) {
814
785
  if (!isRenegotiation && !this.shouldInitiate(id)) {
815
786
  console.debug(
@@ -827,13 +798,12 @@ var VideoSDKCore = class {
827
798
  this.initiators.add(id);
828
799
  }
829
800
  if (!this.peers[id]) {
830
- this.peers[id] = await this.createPeer(id);
801
+ this.peers[id] = this.createPeer(id);
831
802
  }
832
803
  const pc = this.peers[id];
833
804
  try {
834
805
  const offer = await pc.createOffer();
835
806
  await pc.setLocalDescription(offer);
836
- this.captureScreenMid(id);
837
807
  this.send({
838
808
  type: "OFFER",
839
809
  payload: offer.sdp,
@@ -843,18 +813,12 @@ var VideoSDKCore = class {
843
813
  console.debug(`[Offer] Sent to ${id}`);
844
814
  } catch (err) {
845
815
  console.error(`[Offer] Failed for ${id}:`, err);
846
- this.emitError(
847
- "OFFER_CREATION_FAILED",
848
- `Failed to create offer for ${id}`,
849
- err,
850
- true
851
- );
852
816
  }
853
817
  }
854
818
  shouldInitiate(peerId) {
855
819
  return this.myId < peerId;
856
820
  }
857
- // ANSWER
821
+ // ---------------- ANSWER ----------------
858
822
  async handleOffer(sdp, id) {
859
823
  if (!this.iceServers || this.iceServers.length === 0) {
860
824
  console.warn("[Offer] Waiting for iceServers, queuing offer from", id);
@@ -862,7 +826,7 @@ var VideoSDKCore = class {
862
826
  return;
863
827
  }
864
828
  if (!this.peers[id]) {
865
- this.peers[id] = await this.createPeer(id);
829
+ this.peers[id] = this.createPeer(id);
866
830
  }
867
831
  const pc = this.peers[id];
868
832
  try {
@@ -878,9 +842,8 @@ var VideoSDKCore = class {
878
842
  );
879
843
  pc.close();
880
844
  delete this.peers[id];
881
- delete this.peerTransceivers[id];
882
845
  this.initiators.delete(id);
883
- this.peers[id] = await this.createPeer(id);
846
+ this.peers[id] = this.createPeer(id);
884
847
  }
885
848
  }
886
849
  if (this.peers[id].signalingState !== "stable" && this.peers[id].signalingState !== "have-local-offer") {
@@ -893,7 +856,6 @@ var VideoSDKCore = class {
893
856
  type: "offer",
894
857
  sdp
895
858
  });
896
- this.captureScreenMid(id);
897
859
  const pending = this.pendingIceCandidates[id] || [];
898
860
  for (const candidate of pending) {
899
861
  try {
@@ -923,26 +885,18 @@ var VideoSDKCore = class {
923
885
  );
924
886
  }
925
887
  }
926
- // CLEANUP
888
+ // ---------------- CLEANUP ----------------
927
889
  closePeer(id) {
928
890
  const pc = this.peers[id];
929
891
  if (!pc) return;
930
892
  pc.ontrack = null;
931
893
  pc.onicecandidate = null;
932
894
  pc.onconnectionstatechange = null;
933
- pc.oniceconnectionstatechange = null;
934
895
  pc.close();
935
896
  delete this.peers[id];
936
- delete this.peerTransceivers[id];
937
897
  this.initiators.delete(id);
938
898
  this.state.removeParticipant(id);
939
899
  }
940
- // SCREEN SHARE (TRANSCEIVER-BASED)
941
- /**
942
- * Start screen sharing using replaceTrack on the pre-established screen transceiver.
943
- * No need to add/remove tracks, no renegotiation needed (transceiver already in SDP).
944
- * Just swap the track and update direction if needed.
945
- */
946
900
  async startScreenShare() {
947
901
  try {
948
902
  if (this.state.presenterId && this.state.presenterId !== this.myId) {
@@ -953,55 +907,35 @@ var VideoSDKCore = class {
953
907
  }
954
908
  this.screenStream = await navigator.mediaDevices.getDisplayMedia({
955
909
  video: true
910
+ // audio: true,
956
911
  });
957
- const screenTrack = this.screenStream.getVideoTracks()[0];
958
- if (!screenTrack) {
959
- throw new Error("No video track in screen stream");
960
- }
961
912
  this.isScreenSharing = true;
962
913
  this.state.updateLocalParticipant({
963
914
  media: {
964
915
  isScreenSharing: true,
965
916
  screenStream: this.screenStream,
966
- screenTrack
917
+ screenTrack: this.screenStream.getVideoTracks()[0]
967
918
  }
968
919
  });
969
920
  this.state.setPresenterId(this.myId);
970
- screenTrack.onended = () => {
971
- console.log("[Screen Share] User stopped via browser button");
921
+ this.screenStream.getVideoTracks()[0].onended = () => {
972
922
  this.stopScreenShare();
973
923
  };
974
- for (const [peerId, pc] of Object.entries(this.peers)) {
975
- const txInfo = this.peerTransceivers[peerId];
976
- if (!txInfo) {
977
- console.warn(
978
- `[Screen Share] No transceiver info for ${peerId}, skipping`
979
- );
980
- continue;
981
- }
982
- try {
983
- await txInfo.screenTransceiver.sender.replaceTrack(screenTrack);
984
- if (txInfo.screenTransceiver.currentDirection === "recvonly") {
985
- txInfo.screenTransceiver.direction = "sendrecv";
986
- console.log(
987
- `[Screen Share] Flipped ${peerId} screen transceiver to sendrecv`
988
- );
989
- await this.createOffer(peerId, true);
990
- }
991
- } catch (err) {
992
- console.error(
993
- `[Screen Share] Failed to update transceiver for ${peerId}:`,
994
- err
995
- );
996
- }
997
- }
924
+ Object.entries(this.peers).forEach(([peerId, pc]) => {
925
+ this.screenSenders[peerId] = [];
926
+ this.screenStream.getTracks().forEach((track) => {
927
+ const sender = pc.addTrack(track, this.screenStream);
928
+ this.screenSenders[peerId].push(sender);
929
+ });
930
+ this.createOffer(peerId, true);
931
+ });
998
932
  this.send({
999
933
  type: "SCREEN_SHARE_START",
1000
934
  sender: this.myId,
1001
935
  room_id: this.room.id,
936
+ camera_id: this.localStream?.id.replace(/[{}]/g, ""),
1002
937
  stream_id: this.screenStream.id.replace(/[{}]/g, "")
1003
938
  });
1004
- console.log("[Screen Share] Started successfully");
1005
939
  return this.screenStream;
1006
940
  } catch (err) {
1007
941
  this.emitError(
@@ -1015,32 +949,21 @@ var VideoSDKCore = class {
1015
949
  throw err;
1016
950
  }
1017
951
  }
1018
- /**
1019
- * Stop screen sharing: clear the screen transceiver track and flip direction back to recvonly.
1020
- */
1021
- async stopScreenShare() {
952
+ stopScreenShare() {
1022
953
  if (!this.screenStream) return;
1023
- console.log("[Screen Share] Stopping...");
1024
954
  this.screenStream.getTracks().forEach((t) => t.stop());
1025
- for (const [peerId, pc] of Object.entries(this.peers)) {
1026
- const txInfo = this.peerTransceivers[peerId];
1027
- if (!txInfo) continue;
1028
- try {
1029
- await txInfo.screenTransceiver.sender.replaceTrack(null);
1030
- if (txInfo.screenTransceiver.currentDirection === "sendrecv") {
1031
- txInfo.screenTransceiver.direction = "recvonly";
1032
- console.log(
1033
- `[Screen Share] Flipped ${peerId} screen transceiver to recvonly`
1034
- );
1035
- await this.createOffer(peerId, true);
955
+ Object.entries(this.peers).forEach(([peerId, pc]) => {
956
+ const senders = this.screenSenders[peerId] || [];
957
+ senders.forEach((sender) => {
958
+ try {
959
+ pc.removeTrack(sender);
960
+ } catch (err) {
961
+ console.warn(err);
1036
962
  }
1037
- } catch (err) {
1038
- console.error(
1039
- `[Screen Share] Failed to clear transceiver for ${peerId}:`,
1040
- err
1041
- );
1042
- }
1043
- }
963
+ });
964
+ delete this.screenSenders[peerId];
965
+ this.createOffer(peerId, true);
966
+ });
1044
967
  this.screenStream = null;
1045
968
  this.isScreenSharing = false;
1046
969
  this.state.updateLocalParticipant({
@@ -1058,9 +981,7 @@ var VideoSDKCore = class {
1058
981
  sender: this.myId,
1059
982
  room_id: this.room.id
1060
983
  });
1061
- console.log("[Screen Share] Stopped");
1062
984
  }
1063
- // CHAT
1064
985
  sendChatMessage(payload) {
1065
986
  if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
1066
987
  console.warn("WS not connected");
@@ -1093,13 +1014,11 @@ var VideoSDKCore = class {
1093
1014
  client_ts: Date.now()
1094
1015
  });
1095
1016
  }
1096
- // DISCONNECT
1097
- async disconnect() {
1017
+ disconnect() {
1098
1018
  this.intentionalDisconnect = true;
1099
- await this.stopScreenShare();
1019
+ this.stopScreenShare();
1100
1020
  Object.values(this.peers).forEach((pc) => pc.close());
1101
1021
  this.peers = {};
1102
- this.peerTransceivers = {};
1103
1022
  this.initiators.clear();
1104
1023
  this.stopHeartbeat();
1105
1024
  if (this.ws?.readyState === WebSocket.OPEN) {