@cometchat/calls-sdk-react-native 5.0.0-beta.1 → 5.0.0-beta.11

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
@@ -33,8 +33,10 @@ let zustand_middleware = require("zustand/middleware");
33
33
  let zustand_shallow = require("zustand/shallow");
34
34
  let react = require("react");
35
35
  react = __toESM(react);
36
- let lib_jitsi_meet = require("lib-jitsi-meet");
37
- lib_jitsi_meet = __toESM(lib_jitsi_meet);
36
+ let __cometchat_calls_lib_webrtc = require("@cometchat/calls-lib-webrtc");
37
+ __cometchat_calls_lib_webrtc = __toESM(__cometchat_calls_lib_webrtc);
38
+ let __react_native_async_storage_async_storage = require("@react-native-async-storage/async-storage");
39
+ __react_native_async_storage_async_storage = __toESM(__react_native_async_storage_async_storage);
38
40
  let react_native = require("react-native");
39
41
  let react_native_webrtc = require("react-native-webrtc");
40
42
  let react_jsx_runtime = require("react/jsx-runtime");
@@ -75,17 +77,24 @@ var EventBus = class {
75
77
  }
76
78
  }
77
79
  }
78
- subscribe(actionType, listener) {
80
+ subscribe(actionType, listener, options) {
81
+ if (options?.signal?.aborted) {
82
+ return () => {};
83
+ }
79
84
  if (!this.actionListenersMap.get(actionType)) {
80
85
  this.actionListenersMap.set(actionType, []);
81
86
  }
82
87
  this.actionListenersMap.get(actionType)?.push(listener);
83
- return () => {
88
+ const unsubscribe = () => {
84
89
  const listenersList = this.actionListenersMap.get(actionType);
85
90
  if (listenersList) {
86
91
  this.actionListenersMap.set(actionType, listenersList.filter((l) => l !== listener));
87
92
  }
88
93
  };
94
+ if (options?.signal) {
95
+ options.signal.addEventListener("abort", unsubscribe, { once: true });
96
+ }
97
+ return unsubscribe;
89
98
  }
90
99
  };
91
100
  const eventBus = new EventBus();
@@ -127,7 +136,10 @@ const VIDEO_PAUSE_AUTHORITY = {
127
136
  BACKGROUND: 1 << 1,
128
137
  SCREEN_SHARE: 1 << 2
129
138
  };
130
- const CONFERENCE_COMMANDS = { userInfo: "user-info" };
139
+ const CONFERENCE_COMMANDS = {
140
+ userInfo: "user-info",
141
+ initialConfig: "initial_config"
142
+ };
131
143
  const VIDEO_QUALITY_LEVELS = {
132
144
  ULTRA: 2160,
133
145
  HIGH: 720,
@@ -135,10 +147,12 @@ const VIDEO_QUALITY_LEVELS = {
135
147
  LOW: 180,
136
148
  NONE: 0
137
149
  };
138
- const PLATFORM = {
150
+ const SDK_PLATFORM = {
139
151
  WEB: "web",
140
152
  ANDROID: "android",
141
- IOS: "ios"
153
+ IOS: "ios",
154
+ REACT_NATIVE_ANDROID: "react-native-android",
155
+ REACT_NATIVE_IOS: "react-native-ios"
142
156
  };
143
157
  const EVENT_LISTENER_METHODS = {
144
158
  SessionStatusListener: {
@@ -253,7 +267,7 @@ function calculateTileLayout(containerWidth, containerHeight, numberOfTiles) {
253
267
  const tileArea = totalArea / numberOfTiles;
254
268
  const minArea = MIN_TILE_WIDTH * MIN_TILE_WIDTH * MIN_ASPECT_RATIO;
255
269
  if (tileArea < minArea) {
256
- const columnCount$1 = Math.floor(containerWidth / MIN_TILE_WIDTH);
270
+ const columnCount$1 = Math.max(2, Math.floor(containerWidth / MIN_TILE_WIDTH));
257
271
  const rowCount$1 = Math.ceil(numberOfTiles / columnCount$1);
258
272
  const totalHorizontalGap$1 = columnCount$1 * GRID_GAP;
259
273
  const tileWidth$1 = (containerWidth - totalHorizontalGap$1) / columnCount$1;
@@ -436,12 +450,37 @@ function isDeviceEqual(device1, device2) {
436
450
  function getDefaultDevice(devices) {
437
451
  return devices.find((device) => device.deviceId === "default") || devices[0];
438
452
  }
453
+ /**
454
+ * Returns a promise that resolves when the given Zustand store
455
+ * satisfies the provided predicate. Resolves immediately if the
456
+ * condition is already met. Includes a timeout to avoid hanging
457
+ * forever (defaults to 5 000 ms).
458
+ */
459
+ function waitForStoreState(store, predicate, timeoutMs = 5e3) {
460
+ return new Promise((resolve, reject) => {
461
+ if (predicate(store.getState())) {
462
+ resolve();
463
+ return;
464
+ }
465
+ const timer = setTimeout(() => {
466
+ unsubscribe();
467
+ reject(new Error("waitForStoreState timed out"));
468
+ }, timeoutMs);
469
+ const unsubscribe = store.subscribe((state) => {
470
+ if (predicate(state)) {
471
+ clearTimeout(timer);
472
+ unsubscribe();
473
+ resolve();
474
+ }
475
+ });
476
+ });
477
+ }
439
478
 
440
479
  //#endregion
441
480
  //#region calls-sdk-core/utils/try-catch.ts
442
- async function tryCatch(promise) {
481
+ async function tryCatch(promise, timeoutMs) {
443
482
  try {
444
- const data = await promise;
483
+ const data = timeoutMs != null ? await Promise.race([promise, new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), timeoutMs))]) : await promise;
445
484
  return {
446
485
  data,
447
486
  error: null
@@ -485,76 +524,163 @@ function debounce(func, delay) {
485
524
  //#endregion
486
525
  //#region calls-sdk-core/utils/session-methods-core.ts
487
526
  var SessionMethodsCore = class {
527
+ /**
528
+ * Mutes the local user's audio during the call.
529
+ */
488
530
  static muteAudio() {
489
531
  muteAudioTrack();
490
532
  }
533
+ /**
534
+ * Unmutes the local user's audio during the call.
535
+ */
491
536
  static unmuteAudio() {
492
537
  unMuteAudioTrack();
493
538
  }
539
+ /**
540
+ * Toggles the local user's audio mute state.
541
+ * If audio is muted, it will be unmuted, and vice versa.
542
+ */
543
+ static toggleAudio() {
544
+ toggleAudioTrack();
545
+ }
546
+ /**
547
+ * Pauses the local user's video stream.
548
+ */
494
549
  static pauseVideo() {
495
550
  pauseVideoTrack();
496
551
  }
552
+ /**
553
+ * Resumes the local user's video stream.
554
+ */
497
555
  static resumeVideo() {
498
556
  resumeVideoTrack();
499
557
  }
558
+ /**
559
+ * Toggles the local user's video stream.
560
+ * If video is paused, it will be resumed, and vice versa.
561
+ */
562
+ static toggleVideo() {
563
+ toggleVideoTrack();
564
+ }
565
+ /**
566
+ * Local user leaves the current session.
567
+ */
500
568
  static leaveSession() {
501
569
  leaveSession();
502
570
  }
503
- static startScreenSharing() {
504
- startScreenSharing();
505
- }
506
- static stopScreenSharing() {
507
- stopScreenSharing();
571
+ /**
572
+ * Ends the current session for all participants.
573
+ * This will terminate the conference and disconnect everyone.
574
+ */
575
+ static endSessionForAll() {
576
+ leaveSession({ shouldEndSession: true });
508
577
  }
578
+ /**
579
+ * Raises the user's virtual hand in the call.
580
+ */
509
581
  static raiseHand() {
510
582
  raisedHandLocal();
511
583
  }
584
+ /**
585
+ * Lowers the user's virtual hand in the call.
586
+ */
512
587
  static lowerHand() {
513
588
  lowerHandLocal();
514
589
  }
590
+ /**
591
+ * Toggles the user's virtual hand state.
592
+ * If the hand is raised, it will be lowered, and vice versa.
593
+ */
594
+ static toggleHand() {
595
+ toggleRaiseHand();
596
+ }
597
+ /**
598
+ * Switches between the front and rear camera.
599
+ */
515
600
  static switchCamera() {
516
601
  switchCamera();
517
602
  }
603
+ /**
604
+ * Sets the layout type for the call.
605
+ * @param layout - The type of layout to set (tile, sidebar or spotlight).
606
+ */
518
607
  static setLayout(layout$1) {
519
608
  setLayout(layout$1);
520
609
  }
521
- static startRecording() {}
522
- static stopRecording() {}
523
- static enablePictureInPictureLayout() {
524
- enablePictureInPictureLayout();
610
+ /**
611
+ * Starts recording the call.
612
+ */
613
+ static startRecording() {
614
+ startRecording();
525
615
  }
526
- static disablePictureInPictureLayout() {
527
- disablePictureInPictureLayout();
616
+ /**
617
+ * Stops the ongoing call recording.
618
+ */
619
+ static stopRecording() {
620
+ stopRecording();
621
+ }
622
+ /**
623
+ * Toggles the call recording state.
624
+ * If recording is active, it will be stopped, and vice versa.
625
+ */
626
+ static toggleRecording() {
627
+ toggleRecording();
528
628
  }
629
+ /**
630
+ * Pins a participant's video to focus on them.
631
+ * @param participantId - The ID of the participant to pin.
632
+ * @param type - The type of the participant.
633
+ */
529
634
  static pinParticipant(participantId, type) {
530
635
  pinParticipant(participantId, type);
531
636
  }
637
+ /**
638
+ * Unpins a participant's video.
639
+ */
532
640
  static unpinParticipant() {
533
641
  unpinParticipant();
534
642
  }
643
+ /**
644
+ * Mutes the audio of a specific participant.
645
+ * @param participantId - The ID of the participant to mute.
646
+ */
535
647
  static muteParticipant(participantId) {
536
648
  muteParticipant(participantId);
537
649
  }
650
+ /**
651
+ * Pauses the video stream of a specific participant.
652
+ * @param participantId - The ID of the participant whose video to pause.
653
+ */
538
654
  static pauseParticipantVideo(participantId) {
539
655
  pauseParticipantVideo(participantId);
540
656
  }
657
+ /**
658
+ * Sets the unread message count displayed on the chat button.
659
+ * @param count - The number of unread messages.
660
+ */
541
661
  static setChatButtonUnreadCount(count) {
542
662
  setChatButtonUnreadCount(count);
543
663
  }
544
664
  /**
545
- * @deprecated use startScreenSharing() instead
665
+ * Toggles the visibility of the participant list panel.
666
+ */
667
+ static toggleParticipantList() {
668
+ toggleParticipantList();
669
+ }
670
+ /**
671
+ * Shows the participant list panel.
546
672
  */
547
- static startScreenShare() {
548
- this.startScreenSharing();
673
+ static showParticipantList() {
674
+ showParticipantList();
549
675
  }
550
676
  /**
551
- * @deprecated use stopScreenSharing() instead
677
+ * Hides the participant list panel.
552
678
  */
553
- static stopScreenShare() {
554
- this.stopScreenSharing();
679
+ static hideParticipantList() {
680
+ hideParticipantList();
555
681
  }
556
682
  /**
557
- * @deprecated switchToVideoCall is deprecated and not supported
683
+ * @deprecated switchToVideoCall is deprecated and not supported.
558
684
  */
559
685
  static switchToVideoCall() {
560
686
  console.error("switchToVideoCall method deprecated and not supported.");
@@ -603,7 +729,7 @@ async function createLocalTrackF(type, deviceId = null, timeout = null, addition
603
729
  if (iAmRecorder) {
604
730
  return;
605
731
  }
606
- const { data: tracks, error } = await tryCatch(lib_jitsi_meet.default.createLocalTracks({
732
+ const { data: tracks, error } = await tryCatch(__cometchat_calls_lib_webrtc.default.createLocalTracks({
607
733
  devices: [type],
608
734
  cameraDeviceId: deviceId,
609
735
  micDeviceId: deviceId,
@@ -644,6 +770,27 @@ async function createLocalTrack(type, deviceId = null, cameraFacing = CAMERA_FAC
644
770
  }
645
771
  }
646
772
  }
773
+ function createLocalTracks() {
774
+ const enableCompanionMode = useConfigStore.getState().enableCompanionMode;
775
+ if (!enableCompanionMode) {
776
+ const audioInputDeviceId = useConfigStore.getState().audioInputDeviceId ?? useBaseStore.getState().audioInputDevice?.deviceId;
777
+ createLocalTrack("audio", audioInputDeviceId);
778
+ }
779
+ const sessionType = useConfigStore.getState().sessionType;
780
+ if (sessionType === SESSION_TYPE.VIDEO) {
781
+ const videoInputDeviceIdP1 = useConfigStore.getState().videoInputDeviceId;
782
+ const videoInputDeviceIdP2 = useBaseStore.getState().videoInputDevice?.deviceId;
783
+ const initialCameraFacingP1 = useConfigStore.getState().initialCameraFacing;
784
+ const initialCameraFacingP2 = useBaseStore.getState().cameraFacing;
785
+ if (videoInputDeviceIdP1) {
786
+ createLocalTrack("video", videoInputDeviceIdP1);
787
+ } else if (initialCameraFacingP1) {
788
+ createLocalTrack("video", null, initialCameraFacingP2);
789
+ } else {
790
+ createLocalTrack("video", videoInputDeviceIdP2, initialCameraFacingP2);
791
+ }
792
+ }
793
+ }
647
794
  function updateAudioInputDevice(deviceId) {
648
795
  const audioInputDevices = useBaseStore.getState().audioInputDevices.filter((device) => device.deviceId !== "");
649
796
  if (audioInputDevices.length > 0) {
@@ -692,11 +839,11 @@ function updateVideoInputDeviceState(device, skipSubscribe = false) {
692
839
  }
693
840
  }
694
841
  function updateAudioOutputDevice(deviceId) {
695
- if (!lib_jitsi_meet.default.mediaDevices.isDeviceChangeAvailable("output")) {
842
+ if (!__cometchat_calls_lib_webrtc.default.mediaDevices.isDeviceChangeAvailable("output")) {
696
843
  console.warn("Adjusting audio output is not supported");
697
844
  return;
698
845
  }
699
- lib_jitsi_meet.default.mediaDevices.setAudioOutputDevice(deviceId).then(() => {
846
+ __cometchat_calls_lib_webrtc.default.mediaDevices.setAudioOutputDevice(deviceId).then(() => {
700
847
  const audioOutputDevices = useBaseStore.getState().audioOutputDevices;
701
848
  const device = audioOutputDevices.find((d) => d.deviceId === deviceId);
702
849
  if (device) {
@@ -825,7 +972,7 @@ function sendParticipantListChangedEvent() {
825
972
 
826
973
  //#endregion
827
974
  //#region calls-sdk-core/store/config.ts
828
- const initialState$7 = {
975
+ const initialState$8 = {
829
976
  sessionType: "VIDEO",
830
977
  autoStartRecording: false,
831
978
  layout: LAYOUT.TILE,
@@ -843,7 +990,6 @@ const initialState$7 = {
843
990
  hideLeaveSessionButton: false,
844
991
  hideToggleAudioButton: false,
845
992
  hideParticipantListButton: false,
846
- hideSwitchLayoutButton: false,
847
993
  hideChatButton: true,
848
994
  hideToggleVideoButton: false,
849
995
  hideScreenSharingButton: false,
@@ -856,13 +1002,17 @@ const initialState$7 = {
856
1002
  startVideoPaused: false,
857
1003
  title: "",
858
1004
  enableNoiseReduction: false,
1005
+ unstable_renderAudioOnly: false,
859
1006
  idleTimeoutPeriodBeforePrompt: 6e4,
860
1007
  idleTimeoutPeriodAfterPrompt: 18e4,
861
1008
  enableSpotlightDrag: true,
862
1009
  enableSpotlightSwap: true,
863
- showFrameRate: false
1010
+ showFrameRate: false,
1011
+ enableCompanionMode: false,
1012
+ isPeerCall: false,
1013
+ enableNotifications: true
864
1014
  };
865
- const useConfigStore = (0, zustand.create)()((0, zustand_middleware.subscribeWithSelector)((0, zustand_middleware.combine)(initialState$7, (set) => ({ reset: () => set(initialState$7) }))));
1015
+ const useConfigStore = (0, zustand.create)()((0, zustand_middleware.subscribeWithSelector)((0, zustand_middleware.combine)(initialState$8, (set) => ({ reset: () => set(initialState$8) }))));
866
1016
  const setConfig = (config) => {
867
1017
  useConfigStore.setState(config);
868
1018
  };
@@ -880,18 +1030,24 @@ const initialLocalParticipant = {
880
1030
  type: "human",
881
1031
  uid: "unknown"
882
1032
  };
883
- const initialState$6 = {
1033
+ const initialState$7 = {
884
1034
  dominantSpeakers: [],
885
1035
  localParticipant: initialLocalParticipant,
886
1036
  participants: [],
887
1037
  virtualParticipants: []
888
1038
  };
889
- const useParticipantStore = (0, zustand.create)()((0, zustand_middleware.subscribeWithSelector)((0, zustand_middleware.combine)(initialState$6, (set, get$1) => ({
1039
+ const useParticipantStore = (0, zustand.create)()((0, zustand_middleware.subscribeWithSelector)((0, zustand_middleware.combine)(initialState$7, (set, get$1) => ({
890
1040
  addParticipant: (participant) => {
891
- set((state) => ({ participants: [...state.participants, participant] }));
1041
+ set((state) => ({ participants: state.participants.some((p) => p.pid === participant.pid) ? state.participants.map((p) => p.pid === participant.pid ? {
1042
+ ...p,
1043
+ ...participant
1044
+ } : p) : [...state.participants, participant] }));
892
1045
  },
893
1046
  addVirtualParticipant: (participant) => {
894
- set((state) => ({ virtualParticipants: [...state.virtualParticipants, participant] }));
1047
+ set((state) => ({ virtualParticipants: state.virtualParticipants.some((p) => p.pid === participant.pid && p.type === participant.type) ? state.virtualParticipants.map((p) => p.pid === participant.pid && p.type === participant.type ? {
1048
+ ...p,
1049
+ ...participant
1050
+ } : p) : [...state.virtualParticipants, participant] }));
895
1051
  },
896
1052
  clearParticipants: () => set({
897
1053
  participants: [],
@@ -961,7 +1117,7 @@ const useParticipantStore = (0, zustand.create)()((0, zustand_middleware.subscri
961
1117
  }
962
1118
  return get$1().participants.find((p) => p.pid === pid);
963
1119
  },
964
- reset: () => set(initialState$6)
1120
+ reset: () => set(initialState$7)
965
1121
  }))));
966
1122
  function useAllParticipants() {
967
1123
  const localParticipant = useParticipantStore((state) => state.localParticipant);
@@ -1093,9 +1249,35 @@ useParticipantStore.subscribe((state) => state.participants.filter((p) => p.uid)
1093
1249
  }
1094
1250
  });
1095
1251
 
1252
+ //#endregion
1253
+ //#region calls-sdk-core/store/utils/send-initial-config.ts
1254
+ function sendInitialConfig() {
1255
+ const conference = useConferenceStore.getState().conference;
1256
+ if (!conference?.room) {
1257
+ return;
1258
+ }
1259
+ const config = useConfigStore.getState();
1260
+ const localParticipant = useParticipantStore.getState().localParticipant;
1261
+ const attributes = {
1262
+ session_id: config.sessionId,
1263
+ is_audio_only: String(config.sessionType === "VOICE"),
1264
+ is_audio_muted: String(config.startAudioMuted),
1265
+ is_video_muted: String(config.startVideoPaused),
1266
+ start_recording_on_call_start: String(config.autoStartRecording),
1267
+ uid: localParticipant.uid,
1268
+ platform: useBaseStore.getState().sdkPlatform,
1269
+ platform_version: useBaseStore.getState().platformVersion,
1270
+ user_agent: useBaseStore.getState().userAgent,
1271
+ meeting_id: conference.room?.xmpp?.getJid?.() ?? config.sessionId,
1272
+ mode: config.layout,
1273
+ commit_id: "fef38834"
1274
+ };
1275
+ conference.room.addOrReplaceInPresence(CONFERENCE_COMMANDS.initialConfig, { attributes });
1276
+ }
1277
+
1096
1278
  //#endregion
1097
1279
  //#region calls-sdk-core/store/conference.ts
1098
- const initialState$5 = {
1280
+ const initialState$6 = {
1099
1281
  conference: null,
1100
1282
  conferenceJoined: false,
1101
1283
  conferenceJoinedAt: null,
@@ -1105,12 +1287,12 @@ const initialState$5 = {
1105
1287
  connectionQuality: new Map(),
1106
1288
  raiseHandMap: new Map(),
1107
1289
  recording: {
1108
- status: lib_jitsi_meet.default.constants.recording.status.OFF,
1109
- mode: lib_jitsi_meet.default.constants.recording.mode.FILE
1290
+ status: __cometchat_calls_lib_webrtc.default.constants.recording.status.OFF,
1291
+ mode: __cometchat_calls_lib_webrtc.default.constants.recording.mode.FILE
1110
1292
  },
1111
1293
  isRecording: false
1112
1294
  };
1113
- const useConferenceStore = (0, zustand.create)()((0, zustand_middleware.subscribeWithSelector)((0, zustand_middleware.combine)(initialState$5, (set) => ({
1295
+ const useConferenceStore = (0, zustand.create)()((0, zustand_middleware.subscribeWithSelector)((0, zustand_middleware.combine)(initialState$6, (set) => ({
1114
1296
  conferenceWillJoin: (conference) => {
1115
1297
  if (typeof window?.APP !== "undefined") {
1116
1298
  window.APP.conference._room = conference;
@@ -1121,13 +1303,17 @@ const useConferenceStore = (0, zustand.create)()((0, zustand_middleware.subscrib
1121
1303
  });
1122
1304
  },
1123
1305
  reset: () => {
1124
- set(initialState$5);
1306
+ set(initialState$6);
1125
1307
  },
1126
1308
  raiseHand: (participantId, timestamp) => {
1127
1309
  set((state) => ({ raiseHandMap: new Map(state.raiseHandMap).set(participantId, timestamp) }));
1128
1310
  sendParticipantEvent(EVENT_LISTENER_METHODS.ParticipantEventsListner.onParticipantHandRaised, participantId);
1129
1311
  },
1130
1312
  lowerHand: (participantId) => {
1313
+ const hasRaisedHand = useConferenceStore.getState().raiseHandMap.has(participantId);
1314
+ if (!hasRaisedHand) {
1315
+ return;
1316
+ }
1131
1317
  set((state) => {
1132
1318
  const raiseHandMap = new Map(state.raiseHandMap);
1133
1319
  raiseHandMap.delete(participantId);
@@ -1138,13 +1324,22 @@ const useConferenceStore = (0, zustand.create)()((0, zustand_middleware.subscrib
1138
1324
  leaveConference: async () => {
1139
1325
  const conference = useConferenceStore.getState().conference;
1140
1326
  if (conference) {
1141
- const { error } = await tryCatch(conference.leave());
1327
+ const { error } = await tryCatch(conference.leave(), 500);
1142
1328
  if (error) {
1143
1329
  console.warn("Error leaving conference:", error);
1144
1330
  eventBus.publish({ type: EVENT_LISTENER_METHODS.SessionStatusListener.onSessionLeft });
1145
1331
  }
1146
1332
  }
1147
1333
  },
1334
+ endConference: async () => {
1335
+ const conference = useConferenceStore.getState().conference;
1336
+ if (conference) {
1337
+ const { error } = await tryCatch(conference.end());
1338
+ if (error) {
1339
+ console.warn("Error ending conference:", error);
1340
+ }
1341
+ }
1342
+ },
1148
1343
  stopRecording: async () => {
1149
1344
  const conference = useConferenceStore.getState().conference;
1150
1345
  if (conference) {
@@ -1209,7 +1404,7 @@ useConferenceStore.subscribe((state) => state.recording, (recording) => {
1209
1404
  const recordingMode = recording.mode;
1210
1405
  const recordingError = recording.error;
1211
1406
  const initiator = recording.initiator;
1212
- const isRecording = !recordingError && initiator && recordingMode === lib_jitsi_meet.default.constants.recording.mode.FILE && (recordingStatus === lib_jitsi_meet.default.constants.recording.status.ON || recordingStatus === lib_jitsi_meet.default.constants.recording.status.PENDING);
1407
+ const isRecording = !recordingError && initiator && recordingMode === __cometchat_calls_lib_webrtc.default.constants.recording.mode.FILE && (recordingStatus === __cometchat_calls_lib_webrtc.default.constants.recording.status.ON || recordingStatus === __cometchat_calls_lib_webrtc.default.constants.recording.status.PENDING);
1213
1408
  if (isRecording) {
1214
1409
  useConferenceStore.setState({ isRecording: true });
1215
1410
  } else {
@@ -1251,7 +1446,7 @@ async function startRecording() {
1251
1446
  const conference = useConferenceStore.getState().conference;
1252
1447
  if (conference) {
1253
1448
  const { data, error } = await tryCatch(conference.startRecording({
1254
- mode: lib_jitsi_meet.default.constants.recording.mode.FILE,
1449
+ mode: __cometchat_calls_lib_webrtc.default.constants.recording.mode.FILE,
1255
1450
  appData: JSON.stringify({ startedAt: Date.now() })
1256
1451
  }));
1257
1452
  if (data) {
@@ -1276,15 +1471,16 @@ const getIsConferenceJoined = () => {
1276
1471
  return conferenceStatus === "joined" || conferenceStatus === "restored";
1277
1472
  };
1278
1473
  useConferenceStore.subscribe((state) => state.conference, (conference) => {
1474
+ sendInitialConfig();
1279
1475
  if (conference) {
1280
1476
  const localParticipant = useParticipantStore.getState().localParticipant;
1281
- conference?.sendCommand(CONFERENCE_COMMANDS.userInfo, { value: JSON.stringify(localParticipant) });
1477
+ conference.sendCommand(CONFERENCE_COMMANDS.userInfo, { value: JSON.stringify(localParticipant) });
1282
1478
  }
1283
1479
  });
1284
1480
 
1285
1481
  //#endregion
1286
1482
  //#region calls-sdk-core/store/tracks.ts
1287
- const initialState$4 = {
1483
+ const initialState$5 = {
1288
1484
  tracks: [],
1289
1485
  permissions: {
1290
1486
  audio: false,
@@ -1292,9 +1488,9 @@ const initialState$4 = {
1292
1488
  initialized: false
1293
1489
  }
1294
1490
  };
1295
- const useTracksStore = (0, zustand.create)()((0, zustand_middleware.subscribeWithSelector)((0, zustand_middleware.combine)(initialState$4, (set, get$1) => ({
1491
+ const useTracksStore = (0, zustand.create)()((0, zustand_middleware.subscribeWithSelector)((0, zustand_middleware.combine)(initialState$5, (set, get$1) => ({
1296
1492
  reset: () => set({
1297
- ...initialState$4,
1493
+ ...initialState$5,
1298
1494
  permissions: get$1().permissions
1299
1495
  }),
1300
1496
  addTrack: (originalTrack) => set((state) => {
@@ -1316,6 +1512,12 @@ const useTracksStore = (0, zustand.create)()((0, zustand_middleware.subscribeWit
1316
1512
  muted: originalTrack.isMuted() ? 1 : 0,
1317
1513
  originalTrack
1318
1514
  };
1515
+ const existingIdx = state.tracks.findIndex((t) => t.pid === participantId && t.mediaType === track.mediaType && t.local === isLocal);
1516
+ if (existingIdx !== -1) {
1517
+ const tracks = [...state.tracks];
1518
+ tracks[existingIdx] = track;
1519
+ return { tracks };
1520
+ }
1319
1521
  return { tracks: [...state.tracks, track] };
1320
1522
  }),
1321
1523
  removeTrack: (originalTrack) => set((state) => ({ tracks: state.tracks.filter((track) => track.originalTrack !== originalTrack) })),
@@ -1517,8 +1719,13 @@ useTracksStore.subscribe((state) => state.tracks.find((t) => t.mediaType === MED
1517
1719
  }
1518
1720
  if (track) {
1519
1721
  const deviceId = track.getDeviceId();
1520
- const device = useBaseStore.getState().audioInputDevices.find((d) => d.deviceId === deviceId);
1521
- updateAudioInputDeviceState(device, true);
1722
+ waitForStoreState(useBaseStore, (state) => state.audioInputDevices.length > 0).then(() => {
1723
+ const audioInputDevices = useBaseStore.getState().audioInputDevices;
1724
+ const device = audioInputDevices.find((d) => d.deviceId === deviceId);
1725
+ updateAudioInputDeviceState(device, true);
1726
+ }).catch(() => {
1727
+ updateAudioInputDeviceState(undefined, true);
1728
+ });
1522
1729
  }
1523
1730
  });
1524
1731
  useTracksStore.subscribe((state) => state.tracks.find((t) => t.mediaType === MEDIA_TYPE.VIDEO && t.local)?.originalTrack, (track, prevTrack) => {
@@ -1665,7 +1872,7 @@ function updateConfig(config) {
1665
1872
 
1666
1873
  //#endregion
1667
1874
  //#region calls-sdk-core/store/base.ts
1668
- const initialState$3 = {
1875
+ const initialState$4 = {
1669
1876
  audioModeMenuVisible: false,
1670
1877
  audioModes: [],
1671
1878
  audioInputDevices: [],
@@ -1700,20 +1907,23 @@ const initialState$3 = {
1700
1907
  desktopSharingFrameRate: 5,
1701
1908
  chatButtonUnreadCount: 0,
1702
1909
  enableNoiseReduction: true,
1703
- sdkPlatform: PLATFORM.WEB,
1704
- webOSName: "unknown",
1910
+ sdkPlatform: SDK_PLATFORM.WEB,
1705
1911
  isMobileBrowser: false,
1706
1912
  visibleParticipants: {
1707
1913
  startIndex: 0,
1708
1914
  endIndex: 0
1915
+ },
1916
+ sidebarVisibleParticipants: {
1917
+ startIndex: 0,
1918
+ endIndex: 0
1709
1919
  }
1710
1920
  };
1711
- const useBaseStore = (0, zustand.create)()((0, zustand_middleware.subscribeWithSelector)((0, zustand_middleware.persist)((0, zustand_middleware.combine)(initialState$3, (set, get$1) => ({
1921
+ const useBaseStore = (0, zustand.create)()((0, zustand_middleware.subscribeWithSelector)((0, zustand_middleware.persist)((0, zustand_middleware.combine)(initialState$4, (set, get$1) => ({
1712
1922
  addSubscriptions: (subscriptions) => {
1713
1923
  useBaseStore.setState((state) => ({ subscriptions: [...state.subscriptions, ...subscriptions] }));
1714
1924
  },
1715
1925
  reset: () => set((state) => ({
1716
- ...initialState$3,
1926
+ ...initialState$4,
1717
1927
  audioInputDevice: state.audioInputDevice,
1718
1928
  audioOutputDevice: state.audioOutputDevice,
1719
1929
  videoInputDevice: state.videoInputDevice,
@@ -1724,11 +1934,11 @@ const useBaseStore = (0, zustand.create)()((0, zustand_middleware.subscribeWithS
1724
1934
  toggleParticipantListVisible: () => set((state) => ({ participantListVisible: !state.participantListVisible })),
1725
1935
  incrementConnectionRetryCount: () => set((state) => ({ connectionRetryCount: state.connectionRetryCount + 1 })),
1726
1936
  isMobileSDK: () => {
1727
- const isMobileSDK = get$1().sdkPlatform === "android" || get$1().sdkPlatform === "ios";
1937
+ const isMobileSDK = get$1().sdkPlatform !== "web";
1728
1938
  return isMobileSDK;
1729
1939
  },
1730
1940
  isMobile: () => {
1731
- const isMobileSDK = get$1().sdkPlatform === "android" || get$1().sdkPlatform === "ios";
1941
+ const isMobileSDK = get$1().sdkPlatform !== "web";
1732
1942
  const isMobileBrowser = get$1().isMobileBrowser;
1733
1943
  return isMobileSDK || isMobileBrowser;
1734
1944
  },
@@ -1774,6 +1984,7 @@ const useBaseStore = (0, zustand.create)()((0, zustand_middleware.subscribeWithS
1774
1984
  const toggleParticipantListVisible = useBaseStore.getState().toggleParticipantListVisible;
1775
1985
  const hideParticipantList = () => useBaseStore.setState({ participantListVisible: false });
1776
1986
  const showParticipantList = () => useBaseStore.setState({ participantListVisible: true });
1987
+ const toggleParticipantList = () => useBaseStore.setState((state) => ({ participantListVisible: !state.participantListVisible }));
1777
1988
  const toggleMoreMenuVisible = useBaseStore.getState().toggleMoreMenuVisible;
1778
1989
  const toggleAudioModeMenuVisible = () => {
1779
1990
  useBaseStore.setState((state) => ({ audioModeMenuVisible: !state.audioModeMenuVisible }));
@@ -1822,6 +2033,9 @@ const toggleEnableNoiseReduction = () => {
1822
2033
  const setChatButtonUnreadCount = (count) => {
1823
2034
  useBaseStore.setState({ chatButtonUnreadCount: count });
1824
2035
  };
2036
+ const setAudioMode = (mode) => {
2037
+ useBaseStore.setState({ selectedAudioModeType: mode });
2038
+ };
1825
2039
  const getLayout = () => {
1826
2040
  return useBaseStore.getState().layout;
1827
2041
  };
@@ -1944,13 +2158,13 @@ initBaseStoreSubscriptions();
1944
2158
 
1945
2159
  //#endregion
1946
2160
  //#region calls-sdk-core/store/connection.ts
1947
- const initialState$2 = {
2161
+ const initialState$3 = {
1948
2162
  connection: undefined,
1949
2163
  connectionStatus: "initial",
1950
2164
  error: undefined,
1951
2165
  timeEstablished: undefined
1952
2166
  };
1953
- const useConnectionStore = (0, zustand.create)()((0, zustand_middleware.subscribeWithSelector)((0, zustand_middleware.combine)(initialState$2, (set) => ({
2167
+ const useConnectionStore = (0, zustand.create)()((0, zustand_middleware.subscribeWithSelector)((0, zustand_middleware.combine)(initialState$3, (set) => ({
1954
2168
  connectionEstablished: (connection) => set({
1955
2169
  connection,
1956
2170
  connectionStatus: "connected",
@@ -1983,17 +2197,88 @@ const useConnectionStore = (0, zustand.create)()((0, zustand_middleware.subscrib
1983
2197
  eventBus.stopEmitting();
1984
2198
  await tryCatch(connection.disconnect());
1985
2199
  eventBus.publish({ type: EVENT_LISTENER_METHODS.SessionStatusListener.onConnectionClosed }, true);
1986
- set(initialState$2);
2200
+ set(initialState$3);
1987
2201
  }
1988
2202
  },
1989
- reset: () => set(initialState$2)
2203
+ reset: () => set(initialState$3)
1990
2204
  }))));
2205
+ function waitForConnection() {
2206
+ const { connectionStatus } = useConnectionStore.getState();
2207
+ if (connectionStatus === "connected") return Promise.resolve();
2208
+ return new Promise((resolve, reject) => {
2209
+ const timeout = setTimeout(() => {
2210
+ unsub();
2211
+ reject(new Error("Connection timed out after 3 seconds"));
2212
+ }, 3e3);
2213
+ const unsub = useConnectionStore.subscribe((s) => s.connectionStatus, (status) => {
2214
+ if (status === "connected") {
2215
+ clearTimeout(timeout);
2216
+ unsub();
2217
+ resolve();
2218
+ } else if (status === "error") {
2219
+ clearTimeout(timeout);
2220
+ unsub();
2221
+ reject(useConnectionStore.getState().error);
2222
+ }
2223
+ });
2224
+ });
2225
+ }
2226
+
2227
+ //#endregion
2228
+ //#region calls-sdk-core/store/toast.ts
2229
+ const MAX_TOASTS = 3;
2230
+ const initialState$2 = { toasts: [] };
2231
+ let counter = 0;
2232
+ const useToastStore = (0, zustand.create)((set) => ({
2233
+ ...initialState$2,
2234
+ addToast: (toast) => {
2235
+ if (!getIsConferenceJoined()) {
2236
+ return "";
2237
+ }
2238
+ if (!useConfigStore.getState().enableNotifications) {
2239
+ return "";
2240
+ }
2241
+ const id = `toast-${++counter}-${Date.now()}`;
2242
+ const newToast = {
2243
+ ...toast,
2244
+ id,
2245
+ createdAt: Date.now()
2246
+ };
2247
+ set((state) => {
2248
+ const updated = [...state.toasts, newToast];
2249
+ if (updated.length > MAX_TOASTS) {
2250
+ return { toasts: updated.slice(-MAX_TOASTS) };
2251
+ }
2252
+ return { toasts: updated };
2253
+ });
2254
+ return id;
2255
+ },
2256
+ removeToast: (id) => {
2257
+ set((state) => ({ toasts: state.toasts.filter((t) => t.id !== id) }));
2258
+ },
2259
+ clearAll: () => {
2260
+ set(initialState$2);
2261
+ },
2262
+ reset: () => {
2263
+ set(initialState$2);
2264
+ }
2265
+ }));
2266
+ function showToast(params) {
2267
+ return useToastStore.getState().addToast({
2268
+ message: params.message,
2269
+ type: params.type ?? "info",
2270
+ duration: params.duration ?? 3e3,
2271
+ position: params.position ?? "bottom",
2272
+ action: params.action
2273
+ });
2274
+ }
1991
2275
 
1992
2276
  //#endregion
1993
2277
  //#region calls-sdk-core/store/utils/hooks.ts
1994
2278
  const useHideMuteAudioButton = () => {
1995
2279
  const hideMuteAudioButton = useConfigStore((state) => state.hideToggleAudioButton);
1996
- return hideMuteAudioButton;
2280
+ const enableCompanionMode = useConfigStore((state) => state.enableCompanionMode);
2281
+ return hideMuteAudioButton || enableCompanionMode;
1997
2282
  };
1998
2283
  const useHideToggleVideoButton = () => {
1999
2284
  const hideToggleVideoButton = useConfigStore((state) => state.hideToggleVideoButton);
@@ -2015,7 +2300,7 @@ const useHideScreenSharingButton = () => {
2015
2300
  const useHideSwitchCameraButton = () => {
2016
2301
  const videoTrack = getLocalTrack(MEDIA_TYPE.VIDEO);
2017
2302
  const hideSwitchCameraButton = useConfigStore((state) => state.hideSwitchCameraButton);
2018
- return hideSwitchCameraButton || !videoTrack;
2303
+ return hideSwitchCameraButton || !videoTrack?.originalTrack;
2019
2304
  };
2020
2305
  const useHideChatButton = () => {
2021
2306
  const hideChatButton = useConfigStore((state) => state.hideChatButton);
@@ -2060,8 +2345,21 @@ const getMainParticipant = () => {
2060
2345
  const useIsReconnecting = () => {
2061
2346
  const connectionStatus = useConnectionStore((state) => state.connectionStatus);
2062
2347
  const conferenceStatus = useConferenceStore((state) => state.conferenceStatus);
2063
- const reconnecting = connectionStatus === "connected" && conferenceStatus === "interrupted";
2064
- return reconnecting;
2348
+ const isP2P = useConferenceStore((state) => state.p2p);
2349
+ const [isOnline, setIsOnline] = (0, react.useState)(true);
2350
+ (0, react.useEffect)(() => {
2351
+ if (typeof window === "undefined") return;
2352
+ const controller = new AbortController();
2353
+ const { signal } = controller;
2354
+ window.addEventListener("online", () => setIsOnline(true), { signal });
2355
+ window.addEventListener("offline", () => setIsOnline(false), { signal });
2356
+ return () => controller.abort();
2357
+ }, []);
2358
+ const interrupted = connectionStatus === "connected" && conferenceStatus === "interrupted";
2359
+ if (isP2P && interrupted && isOnline) {
2360
+ return false;
2361
+ }
2362
+ return interrupted;
2065
2363
  };
2066
2364
  const useHideRecordingButton = () => {
2067
2365
  const hideRecordingButton = useConfigStore((state) => state.hideRecordingButton);
@@ -2139,6 +2437,11 @@ const useIsVideoInputSelectionSupported = () => {
2139
2437
  const isVideoInputSelectionSupported = hasVideoPermission && videoInputDevices.length > 0;
2140
2438
  return isVideoInputSelectionSupported;
2141
2439
  };
2440
+ const useShouldMirrorLocalVideo = () => {
2441
+ const mirrorLocalVideo = useBaseStore((state) => state.mirrorLocalVideo);
2442
+ const cameraFacing = useBaseStore((state) => state.cameraFacing);
2443
+ return cameraFacing === "user" && mirrorLocalVideo;
2444
+ };
2142
2445
 
2143
2446
  //#endregion
2144
2447
  //#region calls-sdk-core/store/utils/switch-camera.ts
@@ -2187,8 +2490,10 @@ function setReceiverConstraintsInternal() {
2187
2490
  }
2188
2491
  });
2189
2492
  } else if (layout$1 === "SIDEBAR") {
2190
- const participants = useParticipantStore.getState().participants;
2191
- participants.forEach((participant) => {
2493
+ const { startIndex, endIndex } = useBaseStore.getState().sidebarVisibleParticipants;
2494
+ const allParticipants = getAllParticipants();
2495
+ const visibleSidebarParticipants = allParticipants.slice(startIndex, endIndex);
2496
+ visibleSidebarParticipants.forEach((participant) => {
2192
2497
  const videoSources$1 = participant.sources?.get("video");
2193
2498
  if (videoSources$1) {
2194
2499
  Array.from(videoSources$1.keys()).forEach((source) => {
@@ -2214,6 +2519,9 @@ const setReceiverConstraints = debounce(setReceiverConstraintsInternal, 200);
2214
2519
  useBaseStore.subscribe((state) => state.visibleParticipants, () => {
2215
2520
  setReceiverConstraints();
2216
2521
  });
2522
+ useBaseStore.subscribe((state) => state.sidebarVisibleParticipants, () => {
2523
+ setReceiverConstraints();
2524
+ });
2217
2525
  useBaseStore.subscribe((state) => state.layout, () => {
2218
2526
  setReceiverConstraints();
2219
2527
  });
@@ -2306,13 +2614,17 @@ var ConferenceListener = class {
2306
2614
  } else {
2307
2615
  useTracksStore.getState().removeTrack(track);
2308
2616
  }
2309
- track.removeAllListeners(lib_jitsi_meet.default.events.track.TRACK_MUTE_CHANGED);
2310
- track.removeAllListeners(lib_jitsi_meet.default.events.track.TRACK_VIDEOTYPE_CHANGED);
2311
- track.removeAllListeners(lib_jitsi_meet.default.events.track.NO_DATA_FROM_SOURCE);
2617
+ track.removeAllListeners(__cometchat_calls_lib_webrtc.default.events.track.TRACK_MUTE_CHANGED);
2618
+ track.removeAllListeners(__cometchat_calls_lib_webrtc.default.events.track.TRACK_VIDEOTYPE_CHANGED);
2619
+ track.removeAllListeners(__cometchat_calls_lib_webrtc.default.events.track.NO_DATA_FROM_SOURCE);
2312
2620
  }
2313
2621
  onConferenceJoinInProgress() {}
2314
- onConferenceFailed(_conference, error, message) {
2315
- console.error("Conference failed:", error, message);
2622
+ onConferenceFailed(errorName, error, message) {
2623
+ if (errorName === __cometchat_calls_lib_webrtc.default.errors.conference.CONFERENCE_DESTROYED) {
2624
+ leaveSession({ forceLeave: true });
2625
+ return;
2626
+ }
2627
+ console.error("Conference failed:", errorName, error, message);
2316
2628
  useConferenceStore.setState({
2317
2629
  conferenceStatus: "error",
2318
2630
  conferenceJoined: false,
@@ -2347,6 +2659,7 @@ var ConferenceListener = class {
2347
2659
  }
2348
2660
  onConnectionEstablished() {
2349
2661
  useConferenceStore.setState({ conferenceStatus: "joined" });
2662
+ setTimeout(setReceiverConstraints, 500);
2350
2663
  }
2351
2664
  onConnectionInterrupted() {
2352
2665
  useConferenceStore.setState({ conferenceStatus: "interrupted" });
@@ -2358,17 +2671,19 @@ var ConferenceListener = class {
2358
2671
  useConferenceStore.setState({ p2p });
2359
2672
  }
2360
2673
  onTrackMuteChanged(track, participantThatMutedUs) {
2361
- if (participantThatMutedUs) {
2362
- useTracksStore.getState().updateTrack(track, { muted: track.isMuted() ? 1 : 0 });
2363
- const displayName = participantThatMutedUs.getDisplayName();
2364
- if (displayName) {
2365
- eventBus.publish({
2366
- type: INTERNAL_EVENTS.notification,
2367
- payload: {
2368
- type: "info",
2369
- message: `${displayName} has muted you.`
2370
- }
2371
- });
2674
+ if (track.isLocal()) {
2675
+ useTracksStore.getState().updateLocalTrack(track.getType(), { muted: track.isMuted() ? 1 : 0 });
2676
+ if (participantThatMutedUs) {
2677
+ const displayName = participantThatMutedUs.getDisplayName();
2678
+ if (displayName) {
2679
+ eventBus.publish({
2680
+ type: INTERNAL_EVENTS.notification,
2681
+ payload: {
2682
+ type: "info",
2683
+ message: `${displayName} has muted you.`
2684
+ }
2685
+ });
2686
+ }
2372
2687
  }
2373
2688
  }
2374
2689
  }
@@ -2423,6 +2738,24 @@ var ConferenceListener = class {
2423
2738
  useParticipantStore.getState().updateParticipant(participantId, { role: newRole });
2424
2739
  }
2425
2740
  }
2741
+ onTrackUnmuteRejected(track) {
2742
+ if (!track.isLocal()) {
2743
+ return;
2744
+ }
2745
+ const mediaType = track.getType();
2746
+ track.dispose().catch(() => {});
2747
+ useTracksStore.getState().updateLocalTrack(mediaType, {
2748
+ originalTrack: undefined,
2749
+ muted: 1
2750
+ });
2751
+ eventBus.publish({
2752
+ type: INTERNAL_EVENTS.notification,
2753
+ payload: {
2754
+ type: "info",
2755
+ message: `Your ${mediaType} unmute was rejected.`
2756
+ }
2757
+ });
2758
+ }
2426
2759
  onTalkWhileMuted() {}
2427
2760
  onConferenceError(error) {
2428
2761
  console.error("Conference error:", error);
@@ -2479,29 +2812,30 @@ const UserInfoCommandSchema = valibot.pick(HumanParticipantSchema, ["avatar", "u
2479
2812
  //#endregion
2480
2813
  //#region calls-sdk-core/handlers/conference.ts
2481
2814
  function addConferenceListeners(conference) {
2482
- conference.on(lib_jitsi_meet.default.events.conference.USER_JOINED, conferenceListener.onUserJoined);
2483
- conference.on(lib_jitsi_meet.default.events.conference.USER_LEFT, conferenceListener.onUserLeft);
2484
- conference.on(lib_jitsi_meet.default.events.conference.TRACK_ADDED, conferenceListener.onTrackAdded);
2485
- conference.on(lib_jitsi_meet.default.events.conference.TRACK_REMOVED, conferenceListener.onTrackRemoved);
2486
- conference.on(lib_jitsi_meet.default.events.conference.CONFERENCE_JOIN_IN_PROGRESS, conferenceListener.onConferenceJoinInProgress);
2487
- conference.on(lib_jitsi_meet.default.events.conference.CONFERENCE_FAILED, conferenceListener.onConferenceFailed);
2488
- conference.on(lib_jitsi_meet.default.events.conference.RECORDER_STATE_CHANGED, conferenceListener.onRecorderStateChanged);
2489
- conference.on(lib_jitsi_meet.default.events.conference.CONNECTION_ESTABLISHED, conferenceListener.onConnectionEstablished);
2490
- conference.on(lib_jitsi_meet.default.events.conference.CONNECTION_INTERRUPTED, conferenceListener.onConnectionInterrupted);
2491
- conference.on(lib_jitsi_meet.default.events.conference.CONNECTION_RESTORED, conferenceListener.onConnectionRestored);
2492
- conference.on(lib_jitsi_meet.default.events.conference.P2P_STATUS, conferenceListener.onP2PStatus);
2493
- conference.on(lib_jitsi_meet.default.events.conference.TRACK_MUTE_CHANGED, conferenceListener.onTrackMuteChanged);
2494
- conference.on(lib_jitsi_meet.default.events.conference.CONFERENCE_JOINED, conferenceListener.onConferenceJoined);
2495
- conference.on(lib_jitsi_meet.default.events.conference.CONFERENCE_LEFT, conferenceListener.onConferenceLeft);
2496
- conference.on(lib_jitsi_meet.default.events.conference.PARTICIPANT_SOURCE_UPDATED, conferenceListener.onParticipantSourceUpdated);
2497
- conference.on(lib_jitsi_meet.default.events.conference.CONFERENCE_CREATED_TIMESTAMP, conferenceListener.onConferenceCreatedTimestamp);
2498
- conference.on(lib_jitsi_meet.default.events.conference.DOMINANT_SPEAKER_CHANGED, conferenceListener.onDominantSpeakerChanged);
2499
- conference.on(lib_jitsi_meet.default.events.connectionQuality.LOCAL_STATS_UPDATED, conferenceListener.onLocalStatsUpdated);
2500
- conference.on(lib_jitsi_meet.default.events.connectionQuality.REMOTE_STATS_UPDATED, conferenceListener.onRemoteStatsUpdated);
2501
- conference.on(lib_jitsi_meet.default.events.conference.PARTICIPANT_PROPERTY_CHANGED, conferenceListener.onParticipantPropertyChanged);
2502
- conference.on(lib_jitsi_meet.default.events.conference.USER_ROLE_CHANGED, conferenceListener.onUserRoleChanged);
2503
- conference.on(lib_jitsi_meet.default.events.conference.TALK_WHILE_MUTED, conferenceListener.onTalkWhileMuted);
2504
- conference.on(lib_jitsi_meet.default.events.conference.TRACK_AUDIO_LEVEL_CHANGED, conferenceListener.onTrackAudioLevelChanged);
2815
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.USER_JOINED, conferenceListener.onUserJoined);
2816
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.USER_LEFT, conferenceListener.onUserLeft);
2817
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.TRACK_ADDED, conferenceListener.onTrackAdded);
2818
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.TRACK_REMOVED, conferenceListener.onTrackRemoved);
2819
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.CONFERENCE_JOIN_IN_PROGRESS, conferenceListener.onConferenceJoinInProgress);
2820
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.CONFERENCE_FAILED, conferenceListener.onConferenceFailed);
2821
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.RECORDER_STATE_CHANGED, conferenceListener.onRecorderStateChanged);
2822
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.CONNECTION_ESTABLISHED, conferenceListener.onConnectionEstablished);
2823
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.CONNECTION_INTERRUPTED, conferenceListener.onConnectionInterrupted);
2824
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.CONNECTION_RESTORED, conferenceListener.onConnectionRestored);
2825
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.P2P_STATUS, conferenceListener.onP2PStatus);
2826
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.TRACK_MUTE_CHANGED, conferenceListener.onTrackMuteChanged);
2827
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.CONFERENCE_JOINED, conferenceListener.onConferenceJoined);
2828
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.CONFERENCE_LEFT, conferenceListener.onConferenceLeft);
2829
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.PARTICIPANT_SOURCE_UPDATED, conferenceListener.onParticipantSourceUpdated);
2830
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.CONFERENCE_CREATED_TIMESTAMP, conferenceListener.onConferenceCreatedTimestamp);
2831
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.DOMINANT_SPEAKER_CHANGED, conferenceListener.onDominantSpeakerChanged);
2832
+ conference.on(__cometchat_calls_lib_webrtc.default.events.connectionQuality.LOCAL_STATS_UPDATED, conferenceListener.onLocalStatsUpdated);
2833
+ conference.on(__cometchat_calls_lib_webrtc.default.events.connectionQuality.REMOTE_STATS_UPDATED, conferenceListener.onRemoteStatsUpdated);
2834
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.PARTICIPANT_PROPERTY_CHANGED, conferenceListener.onParticipantPropertyChanged);
2835
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.USER_ROLE_CHANGED, conferenceListener.onUserRoleChanged);
2836
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.TALK_WHILE_MUTED, conferenceListener.onTalkWhileMuted);
2837
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.TRACK_UNMUTE_REJECTED, conferenceListener.onTrackUnmuteRejected);
2838
+ conference.on(__cometchat_calls_lib_webrtc.default.events.conference.TRACK_AUDIO_LEVEL_CHANGED, conferenceListener.onTrackAudioLevelChanged);
2505
2839
  conference.addCommandListener(CONFERENCE_COMMANDS.userInfo, (data, id) => {
2506
2840
  const vData = valibot.safeParse(UserInfoCommandSchema, safeParseJson(data.value));
2507
2841
  if (vData.success) {
@@ -2512,17 +2846,23 @@ function addConferenceListeners(conference) {
2512
2846
  }
2513
2847
  });
2514
2848
  }
2515
- async function createConference(connection, roomName) {
2849
+ async function _createConference() {
2850
+ const sessionId = useConfigStore.getState().sessionId;
2851
+ const connection = useConnectionStore.getState().connection;
2516
2852
  if (!connection) {
2517
2853
  throw new Error("No connection available");
2518
2854
  }
2855
+ const connectionStatus = useConnectionStore.getState().connectionStatus;
2856
+ if (connectionStatus !== "connected") {
2857
+ await waitForConnection();
2858
+ }
2519
2859
  const existingConference = useConferenceStore.getState().conference;
2520
2860
  if (existingConference) {
2521
2861
  console.log("Conference already exists, skipping creation");
2522
2862
  return;
2523
2863
  }
2524
2864
  const connectionConfig = useConnectionStore.getState().connectionConfig;
2525
- const conference = connection.initJitsiConference(roomName, connectionConfig);
2865
+ const conference = connection.initJitsiConference(sessionId, connectionConfig);
2526
2866
  const localAudioTrack = getLocalTrack(MEDIA_TYPE.AUDIO)?.originalTrack;
2527
2867
  const localVideoTrack = getLocalTrack(MEDIA_TYPE.VIDEO)?.originalTrack;
2528
2868
  if (localAudioTrack) {
@@ -2537,6 +2877,20 @@ async function createConference(connection, roomName) {
2537
2877
  conference.setDisplayName(useParticipantStore.getState().localParticipant.name);
2538
2878
  conference.join();
2539
2879
  }
2880
+ async function createConference() {
2881
+ const conference = useConferenceStore.getState().conference;
2882
+ if (!conference) {
2883
+ const result = await tryCatch(_createConference());
2884
+ if (result.error) {
2885
+ console.error("Error creating conference", result.error);
2886
+ useConferenceStore.setState({
2887
+ conferenceStatus: "error",
2888
+ conferenceJoined: false,
2889
+ conferenceError: result.error.message
2890
+ });
2891
+ }
2892
+ }
2893
+ }
2540
2894
  function muteParticipant(participantId) {
2541
2895
  const conference = useConferenceStore.getState().conference;
2542
2896
  conference?.muteParticipant(participantId, "audio");
@@ -2548,31 +2902,29 @@ function pauseParticipantVideo(participantId) {
2548
2902
 
2549
2903
  //#endregion
2550
2904
  //#region calls-sdk-core/handlers/connection.ts
2551
- function connect(roomName) {
2905
+ async function connect(autoJoinConference = true) {
2906
+ const existingConnection = useConnectionStore.getState().connection;
2907
+ if (existingConnection) {
2908
+ createConference();
2909
+ return;
2910
+ }
2552
2911
  const options = useConnectionStore.getState().connectionConfig;
2553
2912
  const jwt = useConnectionStore.getState().jwt;
2554
2913
  const iAmRecorder = useConfigStore.getState().iAmRecorder;
2555
2914
  if (options && iAmRecorder) {
2556
2915
  options.p2p = { enabled: false };
2557
2916
  }
2558
- const connection = new lib_jitsi_meet.default.JitsiConnection(null, jwt, options);
2917
+ const connection = new __cometchat_calls_lib_webrtc.default.JitsiConnection(null, jwt, options);
2559
2918
  useConnectionStore.getState().connectionWillConnect(connection);
2560
- connection.addEventListener(lib_jitsi_meet.default.events.connection.CONNECTION_ESTABLISHED, onConnectionEstablished);
2561
- connection.addEventListener(lib_jitsi_meet.default.events.connection.CONNECTION_FAILED, onConnectionFailed);
2562
- connection.addEventListener(lib_jitsi_meet.default.events.connection.CONNECTION_DISCONNECTED, onDisconnected);
2563
- connection.addEventListener(lib_jitsi_meet.default.events.connection.PROPERTIES_UPDATED, onPropertiesUpdated);
2919
+ connection.addEventListener(__cometchat_calls_lib_webrtc.default.events.connection.CONNECTION_ESTABLISHED, onConnectionEstablished);
2920
+ connection.addEventListener(__cometchat_calls_lib_webrtc.default.events.connection.CONNECTION_FAILED, onConnectionFailed);
2921
+ connection.addEventListener(__cometchat_calls_lib_webrtc.default.events.connection.CONNECTION_DISCONNECTED, onDisconnected);
2922
+ connection.addEventListener(__cometchat_calls_lib_webrtc.default.events.connection.PROPERTIES_UPDATED, onPropertiesUpdated);
2564
2923
  async function onConnectionEstablished() {
2565
2924
  useConnectionStore.getState().connectionEstablished(connection);
2566
2925
  eventBus.publish({ type: INTERNAL_EVENTS.onConnectionEstablished });
2567
- const result = await tryCatch(createConference(connection, roomName));
2568
- if (result.error) {
2569
- console.error("Error creating conference", result.error);
2570
- useConferenceStore.setState({
2571
- conferenceStatus: "error",
2572
- conferenceJoined: false,
2573
- conferenceError: result.error.message
2574
- });
2575
- }
2926
+ if (!autoJoinConference) return;
2927
+ createConference();
2576
2928
  }
2577
2929
  function onConnectionFailed(err, message, ...args) {
2578
2930
  unsubscribe();
@@ -2584,9 +2936,9 @@ function connect(roomName) {
2584
2936
  console.log("Properties updated", properties);
2585
2937
  }
2586
2938
  function unsubscribe() {
2587
- connection.removeEventListener(lib_jitsi_meet.default.events.connection.PROPERTIES_UPDATED, onPropertiesUpdated);
2588
- connection.removeEventListener(lib_jitsi_meet.default.events.connection.CONNECTION_FAILED, onConnectionFailed);
2589
- connection.removeEventListener(lib_jitsi_meet.default.events.connection.CONNECTION_DISCONNECTED, onDisconnected);
2939
+ connection.removeEventListener(__cometchat_calls_lib_webrtc.default.events.connection.PROPERTIES_UPDATED, onPropertiesUpdated);
2940
+ connection.removeEventListener(__cometchat_calls_lib_webrtc.default.events.connection.CONNECTION_FAILED, onConnectionFailed);
2941
+ connection.removeEventListener(__cometchat_calls_lib_webrtc.default.events.connection.CONNECTION_DISCONNECTED, onDisconnected);
2590
2942
  }
2591
2943
  const xmpp_username_override = localStorage.getItem("xmpp_username_override");
2592
2944
  const xmpp_password_override = localStorage.getItem("xmpp_password_override");
@@ -2643,7 +2995,7 @@ function updateInputOutputDevices(onlyUpdateIfLabelIsEmpty = false) {
2643
2995
  if (onlyUpdateIfLabelIsEmpty && isLabelEmpty()) {
2644
2996
  return;
2645
2997
  }
2646
- const { mediaDevices } = lib_jitsi_meet.default;
2998
+ const { mediaDevices } = __cometchat_calls_lib_webrtc.default;
2647
2999
  if (mediaDevices.isDeviceChangeAvailable()) {
2648
3000
  mediaDevices.enumerateDevices((devices) => {
2649
3001
  const audioInputDevices = devices.filter((device) => device.kind === "audioinput" && device.deviceId !== "");
@@ -2658,8 +3010,8 @@ function updateInputOutputDevices(onlyUpdateIfLabelIsEmpty = false) {
2658
3010
  }
2659
3011
  }
2660
3012
  function _initDeviceList() {
2661
- const { mediaDevices } = lib_jitsi_meet.default;
2662
- mediaDevices.addEventListener(lib_jitsi_meet.default.events.mediaDevices.DEVICE_LIST_CHANGED, (devices) => {
3013
+ const { mediaDevices } = __cometchat_calls_lib_webrtc.default;
3014
+ mediaDevices.addEventListener(__cometchat_calls_lib_webrtc.default.events.mediaDevices.DEVICE_LIST_CHANGED, (devices) => {
2663
3015
  const existingAudioInputDevices = useBaseStore.getState().audioInputDevices;
2664
3016
  const existingAudioOutputDevices = useBaseStore.getState().audioOutputDevices;
2665
3017
  const existingVideoInputDevices = useBaseStore.getState().videoInputDevices;
@@ -2678,7 +3030,7 @@ const initDeviceList = runOnce(_initDeviceList);
2678
3030
  //#region calls-sdk-core/handlers/screen-share.ts
2679
3031
  function startScreenSharing() {
2680
3032
  const desktopSharingFrameRate = useBaseStore.getState().desktopSharingFrameRate;
2681
- lib_jitsi_meet.default.createLocalTracks({
3033
+ __cometchat_calls_lib_webrtc.default.createLocalTracks({
2682
3034
  devices: ["desktop"],
2683
3035
  desktopSharingFrameRate
2684
3036
  }).then((tracks) => {
@@ -2739,6 +3091,7 @@ function resetAllStores() {
2739
3091
  useConfigStore.getState().reset();
2740
3092
  useConnectionStore.getState().reset();
2741
3093
  useParticipantStore.getState().reset();
3094
+ useToastStore.getState().reset();
2742
3095
  useTracksStore.getState().reset();
2743
3096
  }
2744
3097
 
@@ -2769,7 +3122,8 @@ var Mutex = class {
2769
3122
  //#endregion
2770
3123
  //#region calls-sdk-core/handlers/init.ts
2771
3124
  function initializeLib() {
2772
- lib_jitsi_meet.default.init();
3125
+ __cometchat_calls_lib_webrtc.default.init();
3126
+ __cometchat_calls_lib_webrtc.default.setLogLevel(__cometchat_calls_lib_webrtc.default.logLevels.ERROR);
2773
3127
  console.log("JitsiMeetJS initialized successfully.");
2774
3128
  }
2775
3129
 
@@ -2778,6 +3132,7 @@ function initializeLib() {
2778
3132
  let isSessionStarted = false;
2779
3133
  let reconnectTimeoutId = null;
2780
3134
  const RECONNECT_DEBOUNCE_DELAY = 3e3;
3135
+ initializeLib();
2781
3136
  function startSession() {
2782
3137
  const sessionId = useConfigStore.getState().sessionId;
2783
3138
  if (!sessionId) {
@@ -2790,29 +3145,13 @@ function startSession() {
2790
3145
  }
2791
3146
  isSessionStarted = true;
2792
3147
  console.log(`Session started in room: ${sessionId}`);
2793
- initializeLib();
2794
- const audioInputDeviceId = useConfigStore.getState().audioInputDeviceId ?? useBaseStore.getState().audioInputDevice?.deviceId;
2795
- createLocalTrack("audio", audioInputDeviceId);
2796
- const sessionType = useConfigStore.getState().sessionType;
2797
- if (sessionType === SESSION_TYPE.VIDEO) {
2798
- const videoInputDeviceIdP1 = useConfigStore.getState().videoInputDeviceId;
2799
- const videoInputDeviceIdP2 = useBaseStore.getState().videoInputDevice?.deviceId;
2800
- const initialCameraFacingP1 = useConfigStore.getState().initialCameraFacing;
2801
- const initialCameraFacingP2 = useBaseStore.getState().cameraFacing;
2802
- if (videoInputDeviceIdP1) {
2803
- createLocalTrack("video", videoInputDeviceIdP1);
2804
- } else if (initialCameraFacingP1) {
2805
- createLocalTrack("video", null, initialCameraFacingP2);
2806
- } else {
2807
- createLocalTrack("video", videoInputDeviceIdP2, initialCameraFacingP2);
2808
- }
2809
- }
3148
+ createLocalTracks();
2810
3149
  const audioOutputDeviceId = useConfigStore.getState().audioOutputDeviceId ?? useBaseStore.getState().audioOutputDevice?.deviceId;
2811
3150
  if (audioOutputDeviceId) {
2812
3151
  updateAudioOutputDevice(audioOutputDeviceId);
2813
3152
  }
2814
3153
  eventBus.startEmitting();
2815
- const test = tryCatchSync(() => connect(sessionId));
3154
+ const test = tryCatchSync(() => connect());
2816
3155
  if (test.error) {
2817
3156
  console.error("Error connecting to session:", test.error);
2818
3157
  useConnectionStore.getState().connectionFailed(test.error.message);
@@ -2829,8 +3168,14 @@ async function _leaveSession() {
2829
3168
  await useConnectionStore.getState().disconnect();
2830
3169
  }
2831
3170
  const sessionMutex = new Mutex();
2832
- function leaveSession() {
3171
+ function leaveSession(options = {}) {
2833
3172
  return sessionMutex.run(async () => {
3173
+ const isPeerCall = useConfigStore.getState().isPeerCall;
3174
+ const shouldEnd = options.shouldEndSession || isPeerCall && !options.forceLeave;
3175
+ if (shouldEnd) {
3176
+ useConferenceStore.getState().endConference();
3177
+ return;
3178
+ }
2834
3179
  useBaseStore.getState().clearIdealTimeoutTimer();
2835
3180
  cancelPendingReconnect();
2836
3181
  await _leaveSession();
@@ -2891,7 +3236,7 @@ function onTrack(track) {
2891
3236
  originalTrack: track,
2892
3237
  ...track.getVideoType() === "desktop" ? { muted: 0 } : typeof muted === "boolean" ? { muted } : {}
2893
3238
  });
2894
- track.on(lib_jitsi_meet.default.events.track.LOCAL_TRACK_STOPPED, (t) => {
3239
+ track.on(__cometchat_calls_lib_webrtc.default.events.track.LOCAL_TRACK_STOPPED, (t) => {
2895
3240
  if (t.getVideoType() === "desktop") {
2896
3241
  stopScreenSharing();
2897
3242
  }
@@ -2899,15 +3244,15 @@ function onTrack(track) {
2899
3244
  } else {
2900
3245
  useTracksStore.getState().addTrack(track);
2901
3246
  }
2902
- track.removeAllListeners(lib_jitsi_meet.default.events.track.TRACK_MUTE_CHANGED);
2903
- track.removeAllListeners(lib_jitsi_meet.default.events.track.TRACK_VIDEOTYPE_CHANGED);
2904
- track.on(lib_jitsi_meet.default.events.track.TRACK_MUTE_CHANGED, (t) => {
3247
+ track.removeAllListeners(__cometchat_calls_lib_webrtc.default.events.track.TRACK_MUTE_CHANGED);
3248
+ track.removeAllListeners(__cometchat_calls_lib_webrtc.default.events.track.TRACK_VIDEOTYPE_CHANGED);
3249
+ track.on(__cometchat_calls_lib_webrtc.default.events.track.TRACK_MUTE_CHANGED, (t) => {
2905
3250
  if (t.isLocal()) {
2906
3251
  return;
2907
3252
  }
2908
3253
  useTracksStore.getState().updateTrack(t, { muted: t.isMuted() ? 1 : 0 });
2909
3254
  });
2910
- track.on(lib_jitsi_meet.default.events.track.TRACK_VIDEOTYPE_CHANGED, (type) => {
3255
+ track.on(__cometchat_calls_lib_webrtc.default.events.track.TRACK_VIDEOTYPE_CHANGED, (type) => {
2911
3256
  useTracksStore.getState().updateTrack(track, {
2912
3257
  videoType: type,
2913
3258
  mediaType: type === "desktop" ? "screenshare" : "video"
@@ -3298,6 +3643,10 @@ eventBus.subscribe(INTERNAL_EVENTS.lifecycle.componentDidMount, () => {
3298
3643
  });
3299
3644
  });
3300
3645
  useBaseStore.subscribe((state) => state.appState, (appState) => {
3646
+ const sessionType = useConfigStore.getState().sessionType;
3647
+ if (sessionType !== SESSION_TYPE.VIDEO) {
3648
+ return;
3649
+ }
3301
3650
  if (appState === "active") {
3302
3651
  resumeVideoTrack(VIDEO_PAUSE_AUTHORITY.BACKGROUND);
3303
3652
  } else {
@@ -3738,6 +4087,13 @@ const commonStyles = react_native.StyleSheet.create({
3738
4087
  borderDefault: { borderColor: colors.border.default },
3739
4088
  borderDark: { borderColor: colors.border.dark },
3740
4089
  borderHighlight: { borderColor: colors.border.highlight },
4090
+ absoluteFill: {
4091
+ position: "absolute",
4092
+ top: 0,
4093
+ bottom: 0,
4094
+ left: 0,
4095
+ right: 0
4096
+ },
3741
4097
  flex1: { flex: 1 },
3742
4098
  flexRow: { flexDirection: "row" },
3743
4099
  flexColumn: { flexDirection: "column" },
@@ -3927,10 +4283,16 @@ const PopupMenu = ({ visible, onClose, options, anchorLayout }) => {
3927
4283
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Modal, {
3928
4284
  transparent: true,
3929
4285
  animationType: "none",
4286
+ supportedOrientations: [
4287
+ "portrait",
4288
+ "landscape-left",
4289
+ "landscape-right"
4290
+ ],
3930
4291
  onRequestClose: onClose,
3931
4292
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
3932
4293
  style: styles$27.backdrop,
3933
4294
  onPress: onClose,
4295
+ testID: "cometchat-popup-menu-backdrop",
3934
4296
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Animated.View, {
3935
4297
  style: [styles$27.menu, {
3936
4298
  [isBelowMiddle ? "bottom" : "top"]: isBelowMiddle ? callContainerDimension.height - (y - 4) : y + height + 4,
@@ -3951,6 +4313,7 @@ const PopupMenu = ({ visible, onClose, options, anchorLayout }) => {
3951
4313
  },
3952
4314
  activeOpacity: option.selected ? DISABLED_OPTION_OPACITY : .2,
3953
4315
  style: [styles$27.menuItem, option.selected ? styles$27.menuItemSelected : {}],
4316
+ testID: `cometchat-popup-menu-option-${index}`,
3954
4317
  children: [option.iconName && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon_native_default, {
3955
4318
  name: option.iconName,
3956
4319
  size: 24,
@@ -4112,6 +4475,7 @@ const MoreOptionButton = ({ ruid }) => {
4112
4475
  ref: buttonRef,
4113
4476
  style: styles$4.moreButton,
4114
4477
  onPress: showMenu,
4478
+ testID: "cometchat-participant-more-options-button",
4115
4479
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon_native_default, {
4116
4480
  name: "more",
4117
4481
  size: 20,
@@ -4251,7 +4615,11 @@ const VideoNative = ({ videoTrack, style, objectFit = "cover", mirror = false, m
4251
4615
  return null;
4252
4616
  }
4253
4617
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Animated.View, {
4254
- style: [styles$25.videoContainer, { opacity: fadeAnim }],
4618
+ style: [
4619
+ commonStyles.absoluteFill,
4620
+ styles$25.videoContainer,
4621
+ { opacity: fadeAnim }
4622
+ ],
4255
4623
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_webrtc.RTCView, {
4256
4624
  streamURL: streamURL.toURL(),
4257
4625
  style: [styles$25.video, style],
@@ -4264,8 +4632,7 @@ const VideoNative = ({ videoTrack, style, objectFit = "cover", mirror = false, m
4264
4632
  const styles$25 = react_native.StyleSheet.create({
4265
4633
  videoContainer: {
4266
4634
  height: "100%",
4267
- width: "100%",
4268
- ...react_native.StyleSheet.absoluteFillObject
4635
+ width: "100%"
4269
4636
  },
4270
4637
  video: {
4271
4638
  width: "100%",
@@ -4281,6 +4648,7 @@ const Tile = ({ participant, style, zOrder, showLabel = true, disablePress = fal
4281
4648
  const videoTrack = useTrackByParticipantId(pid, type === "screen-share" ? MEDIA_TYPE.SCREENSHARE : MEDIA_TYPE.VIDEO)?.originalTrack;
4282
4649
  const videoMuted = useTrackMuted(type === "screen-share" ? MEDIA_TYPE.SCREENSHARE : MEDIA_TYPE.VIDEO, pid);
4283
4650
  const enableParticipantContextMenu = useEnableParticipantContextMenu();
4651
+ const shouldMirror = useShouldMirrorLocalVideo();
4284
4652
  const [size, fontSize] = react.default.useMemo(() => {
4285
4653
  const flatStyle = react_native.StyleSheet.flatten(style);
4286
4654
  const width$1 = flatStyle?.width;
@@ -4298,6 +4666,7 @@ const Tile = ({ participant, style, zOrder, showLabel = true, disablePress = fal
4298
4666
  activeOpacity: 1,
4299
4667
  disabled: disablePress,
4300
4668
  style: [styles$24.callScreen, style],
4669
+ testID: `cometchat-tile-${pid}`,
4301
4670
  children: [
4302
4671
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
4303
4672
  style: styles$24.tileAvatar,
@@ -4313,7 +4682,7 @@ const Tile = ({ participant, style, zOrder, showLabel = true, disablePress = fal
4313
4682
  objectFit: type === "screen-share" ? "contain" : "cover",
4314
4683
  muted: videoMuted,
4315
4684
  zOrder,
4316
- mirror: isLocal
4685
+ mirror: isLocal && type !== "screen-share" && shouldMirror
4317
4686
  }),
4318
4687
  showLabel && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Label_native_default, { participant }),
4319
4688
  enableParticipantContextMenu && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
@@ -4372,6 +4741,7 @@ const GroupAvatarTile = ({ startIndex = 4, style }) => {
4372
4741
  const overflowCount = Math.max(0, participantCount - startIndex - 3);
4373
4742
  const visible = participants.slice(startIndex, startIndex + (overflowCount === 1 ? 4 : 3));
4374
4743
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.TouchableOpacity, {
4744
+ testID: "cometchat-group-avatar-tile",
4375
4745
  style: [styles$23.container, style],
4376
4746
  onPress: toggleParticipantListVisible,
4377
4747
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
@@ -4479,6 +4849,7 @@ function SidebarLayout() {
4479
4849
  const mainParticipant = useMainParticipant();
4480
4850
  const participants = allParticipants.length > 1 ? [mainParticipant].concat(allParticipants) : [mainParticipant];
4481
4851
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
4852
+ testID: "cometchat-sidebar-layout",
4482
4853
  style: styles$22.container,
4483
4854
  children: [
4484
4855
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tile_native_default, {
@@ -4615,23 +4986,26 @@ const Spotlight = () => {
4615
4986
  if (otherParticipant) {
4616
4987
  spotlightParticipants.push(otherParticipant);
4617
4988
  }
4618
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tile_native_default, {
4619
- participant: spotlightParticipants[0],
4620
- disablePress: true
4621
- }, spotlightParticipants[0].ruid), spotlightParticipants[1] && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pan, {
4622
- disableDrag: !enableSpotlightDrag,
4623
- layout: {
4624
- width: mainAreaDimension.width,
4625
- height: mainAreaDimension.height
4626
- },
4627
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tile_native_default, {
4628
- showLabel: false,
4629
- disablePress: !enableSpotlightSwap,
4630
- participant: spotlightParticipants[1],
4631
- style: styles$20.panTile,
4632
- zOrder: 1
4633
- }, spotlightParticipants[1].ruid)
4634
- })] });
4989
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
4990
+ testID: "cometchat-spotlight-layout",
4991
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tile_native_default, {
4992
+ participant: spotlightParticipants[0],
4993
+ disablePress: true
4994
+ }, spotlightParticipants[0].ruid), spotlightParticipants[1] && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pan, {
4995
+ disableDrag: !enableSpotlightDrag,
4996
+ layout: {
4997
+ width: mainAreaDimension.width,
4998
+ height: mainAreaDimension.height
4999
+ },
5000
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tile_native_default, {
5001
+ showLabel: false,
5002
+ disablePress: !enableSpotlightSwap,
5003
+ participant: spotlightParticipants[1],
5004
+ style: styles$20.panTile,
5005
+ zOrder: 1
5006
+ }, spotlightParticipants[1].ruid)
5007
+ })]
5008
+ });
4635
5009
  };
4636
5010
  const styles$20 = react_native.StyleSheet.create({ panTile: {
4637
5011
  borderColor: "#1A1A1A",
@@ -4664,6 +5038,7 @@ function TileLayout() {
4664
5038
  participantCount: isPIPLayoutEnabled ? 1 : participants.length
4665
5039
  });
4666
5040
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.FlatList, {
5041
+ testID: "cometchat-tile-layout",
4667
5042
  data: isPIPLayoutEnabled ? [mainParticipant] : participants,
4668
5043
  renderItem: ({ item }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tile_native_default, {
4669
5044
  participant: item,
@@ -4731,7 +5106,11 @@ function ProcessingOverlay({ message, visible = true, animated = false }) {
4731
5106
  return null;
4732
5107
  }
4733
5108
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.Animated.View, {
4734
- style: [styles$18.overlay, { opacity }],
5109
+ style: [
5110
+ commonStyles.absoluteFill,
5111
+ styles$18.overlay,
5112
+ { opacity }
5113
+ ],
4735
5114
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.ActivityIndicator, {
4736
5115
  size: "large",
4737
5116
  color: "#fff"
@@ -4743,7 +5122,6 @@ function ProcessingOverlay({ message, visible = true, animated = false }) {
4743
5122
  }
4744
5123
  const styles$18 = react_native.StyleSheet.create({
4745
5124
  overlay: {
4746
- ...react_native.StyleSheet.absoluteFillObject,
4747
5125
  justifyContent: "center",
4748
5126
  alignItems: "center",
4749
5127
  backgroundColor: "#1A1A1A",
@@ -4921,7 +5299,6 @@ function showConfirmationDialog(title, description, confirmText, cancelText, onC
4921
5299
  const { width } = react_native.Dimensions.get("window");
4922
5300
  const styles$15 = react_native.StyleSheet.create({
4923
5301
  backdrop: {
4924
- ...react_native.StyleSheet.absoluteFillObject,
4925
5302
  backgroundColor: "rgba(0, 0, 0, 0.8)",
4926
5303
  justifyContent: "center",
4927
5304
  alignItems: "center",
@@ -5013,10 +5390,16 @@ function ConfirmationDialog() {
5013
5390
  visible,
5014
5391
  transparent: true,
5015
5392
  animationType: "fade",
5393
+ supportedOrientations: [
5394
+ "portrait",
5395
+ "landscape-left",
5396
+ "landscape-right"
5397
+ ],
5016
5398
  onRequestClose: handleBackdropPress,
5017
5399
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
5018
- style: styles$15.backdrop,
5400
+ style: [commonStyles.absoluteFill, styles$15.backdrop],
5019
5401
  onPress: handleBackdropPress,
5402
+ testID: "cometchat-confirmation-dialog-backdrop",
5020
5403
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
5021
5404
  style: styles$15.dialog,
5022
5405
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
@@ -5059,7 +5442,7 @@ function ConfirmationDialog() {
5059
5442
  //#endregion
5060
5443
  //#region src/ui/bottom-sheet/BottomSheet.native.tsx
5061
5444
  const SCREEN_HEIGHT = react_native.Dimensions.get("window").height;
5062
- const BottomSheet = ({ children, isVisible, onClose, maxHeight = SCREEN_HEIGHT * .4 }) => {
5445
+ const BottomSheet = ({ children, isVisible, onClose, maxHeight = SCREEN_HEIGHT * .4, testID }) => {
5063
5446
  const visibleTranslateY = SCREEN_HEIGHT - maxHeight;
5064
5447
  const hiddenTranslateY = (0, react.useRef)(SCREEN_HEIGHT).current;
5065
5448
  const animatedValue = (0, react.useRef)(new react_native.Animated.Value(hiddenTranslateY)).current;
@@ -5085,8 +5468,10 @@ const BottomSheet = ({ children, isVisible, onClose, maxHeight = SCREEN_HEIGHT *
5085
5468
  const bottomSheetAnimation = { transform: [{ translateY: animatedValue }] };
5086
5469
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [isVisible && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.TouchableWithoutFeedback, {
5087
5470
  onPress: onClose,
5088
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, { style: styles$14.backdrop })
5471
+ testID: "cometchat-bottom-sheet-backdrop",
5472
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, { style: [commonStyles.absoluteFill, styles$14.backdrop] })
5089
5473
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.Animated.View, {
5474
+ testID,
5090
5475
  style: [
5091
5476
  styles$14.bottomSheet,
5092
5477
  bottomSheetAnimation,
@@ -5100,7 +5485,6 @@ const BottomSheet = ({ children, isVisible, onClose, maxHeight = SCREEN_HEIGHT *
5100
5485
  };
5101
5486
  const styles$14 = react_native.StyleSheet.create({
5102
5487
  backdrop: {
5103
- ...react_native.StyleSheet.absoluteFillObject,
5104
5488
  backgroundColor: "rgba(0,0,0,0.5)",
5105
5489
  zIndex: 1
5106
5490
  },
@@ -5144,8 +5528,9 @@ var BottomSheet_native_default = BottomSheet;
5144
5528
 
5145
5529
  //#endregion
5146
5530
  //#region src/ui/control-pane/MenuItem.native.tsx
5147
- const MenuItem = ({ iconName, label, onPress, selected = false }) => {
5531
+ const MenuItem = ({ iconName, label, onPress, selected = false, testID }) => {
5148
5532
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.TouchableOpacity, {
5533
+ testID,
5149
5534
  onPress: () => {
5150
5535
  hideAllBottomSheets();
5151
5536
  onPress();
@@ -5198,6 +5583,7 @@ const AudioModesMenu = ({ isVisible, onClose }) => {
5198
5583
  style: [commonStyles.bodyRegular, styles$12.noItemsText],
5199
5584
  children: "No audio modes available"
5200
5585
  }), audioModes.map((mode, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuItem_native_default, {
5586
+ testID: `cometchat-menu-item-audio-${mode.type.toLowerCase()}`,
5201
5587
  iconName: AUDIO_MODE_TYPE_ICON_MAP[mode.type],
5202
5588
  label: mode.type,
5203
5589
  selected: mode.selected,
@@ -5249,6 +5635,7 @@ const AudioModeButton = () => {
5249
5635
  style: controlPaneStyles.controlButton,
5250
5636
  onPress: toggleAudioModeMenuVisible,
5251
5637
  activeOpacity: .7,
5638
+ testID: "cometchat-audio-mode-button",
5252
5639
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon_native_default, {
5253
5640
  name: "speaker-fill",
5254
5641
  fill: "#FFF",
@@ -5274,6 +5661,7 @@ const AudioControl = () => {
5274
5661
  style: [controlPaneStyles.controlButton, muted && controlPaneStyles.toggledButton],
5275
5662
  onPress,
5276
5663
  activeOpacity: .7,
5664
+ testID: "cometchat-audio-toggle-button",
5277
5665
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon_native_default, {
5278
5666
  name: muted ? "mic-off-fill" : "mic-fill",
5279
5667
  fill: muted ? "#9F3032" : "#FFF",
@@ -5299,6 +5687,7 @@ const VideoControl = () => {
5299
5687
  style: [controlPaneStyles.controlButton, videoMuted && controlPaneStyles.toggledButton],
5300
5688
  onPress,
5301
5689
  activeOpacity: .7,
5690
+ testID: "cometchat-video-toggle-button",
5302
5691
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon_native_default, {
5303
5692
  name: videoMuted ? "video-off-fill" : "video-fill",
5304
5693
  fill: videoMuted ? "#9F3032" : "#FFF",
@@ -5323,6 +5712,7 @@ const LeaveSessionButton = () => {
5323
5712
  style: [controlPaneStyles.controlButton, controlPaneStyles.leaveSessionButton],
5324
5713
  onPress,
5325
5714
  activeOpacity: .7,
5715
+ testID: "cometchat-leave-session-button",
5326
5716
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon_native_default, {
5327
5717
  name: "call-end",
5328
5718
  fill: "#FFF",
@@ -5339,6 +5729,7 @@ const MoreMenuButton = () => {
5339
5729
  style: controlPaneStyles.controlButton,
5340
5730
  onPress: toggleMoreMenuVisible,
5341
5731
  activeOpacity: .7,
5732
+ testID: "cometchat-more-menu-button",
5342
5733
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon_native_default, {
5343
5734
  name: "more",
5344
5735
  fill: "#FFF",
@@ -5357,6 +5748,7 @@ const ControlPane = () => {
5357
5748
  }
5358
5749
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
5359
5750
  style: controlPaneStyles.controlPane,
5751
+ testID: "cometchat-control-panel",
5360
5752
  children: [
5361
5753
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Audio_native_default, {}),
5362
5754
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Video_native_default, {}),
@@ -5414,22 +5806,26 @@ const MoreMenu = ({ isVisible, onClose }) => {
5414
5806
  toggleParticipantListVisible();
5415
5807
  }, []);
5416
5808
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BottomSheet_native_default, {
5809
+ testID: "cometchat-more-menu-bottom-sheet",
5417
5810
  maxHeight: bottomSheetMaxHeight,
5418
5811
  isVisible,
5419
5812
  onClose,
5420
5813
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.ScrollView, { children: [
5421
5814
  numberOfVisibleItems === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
5815
+ testID: "cometchat-more-menu-empty-state",
5422
5816
  style: [commonStyles.bodyRegular, styles$11.noItemsText],
5423
5817
  children: "No options available"
5424
5818
  }),
5425
5819
  !hideScreenSharingButton && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScreenShareButton_default, {}),
5426
5820
  !hideRaiseHandButton && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuItem_native_default, {
5821
+ testID: "cometchat-menu-item-raise-hand",
5427
5822
  iconName: "raise-hand-fill",
5428
5823
  label: raiseHandTimestamp ? "Lower Hand" : "Raise Hand",
5429
5824
  onPress: onRaiseHandPress,
5430
5825
  selected: Boolean(raiseHandTimestamp)
5431
5826
  }),
5432
5827
  !hideRecordingButton && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuItem_native_default, {
5828
+ testID: isRecording ? "cometchat-menu-item-stop-recording" : "cometchat-menu-item-start-recording",
5433
5829
  iconName: isRecording ? "record-stop-fill" : "record-fill",
5434
5830
  label: isRecording ? "Stop Recording" : "Start Recording",
5435
5831
  onPress: () => {
@@ -5440,6 +5836,7 @@ const MoreMenu = ({ isVisible, onClose }) => {
5440
5836
  }
5441
5837
  }),
5442
5838
  !hideParticipantListButton && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuItem_native_default, {
5839
+ testID: "cometchat-menu-item-participants",
5443
5840
  iconName: "participants",
5444
5841
  label: "Participants",
5445
5842
  onPress: onParticipantListPress
@@ -5481,14 +5878,15 @@ const FullScreenDialog = ({ children, visible = false }) => {
5481
5878
  return null;
5482
5879
  }
5483
5880
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Animated.View, {
5484
- style: [styles$10.container, { opacity: fadeAnim }],
5881
+ style: [
5882
+ commonStyles.absoluteFill,
5883
+ styles$10.container,
5884
+ { opacity: fadeAnim }
5885
+ ],
5485
5886
  children
5486
5887
  });
5487
5888
  };
5488
- const styles$10 = react_native.StyleSheet.create({ container: {
5489
- ...react_native.StyleSheet.absoluteFillObject,
5490
- zIndex: 1e3
5491
- } });
5889
+ const styles$10 = react_native.StyleSheet.create({ container: { zIndex: 1e3 } });
5492
5890
  var FullScreenDialog_native_default = FullScreenDialog;
5493
5891
 
5494
5892
  //#endregion
@@ -5566,6 +5964,7 @@ const ChangeLayout = () => {
5566
5964
  eventBus.publish({ type: EVENT_LISTENER_METHODS.ButtonClickListener.onChangeLayoutButtonClicked });
5567
5965
  showMenu();
5568
5966
  },
5967
+ testID: "cometchat-change-layout-button",
5569
5968
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon_native_default, {
5570
5969
  name: "tile-fill",
5571
5970
  fill: "#FFFFFF"
@@ -5618,6 +6017,7 @@ const ChatButton = () => {
5618
6017
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.TouchableOpacity, {
5619
6018
  style: [styles$9.iconButton],
5620
6019
  onPress,
6020
+ testID: "cometchat-chat-button",
5621
6021
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon_native_default, {
5622
6022
  name: "chat",
5623
6023
  fill: "#FFFFFF"
@@ -5674,6 +6074,7 @@ const SwitchCamera = () => {
5674
6074
  return null;
5675
6075
  }
5676
6076
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.TouchableOpacity, {
6077
+ testID: "cometchat-switch-camera-button",
5677
6078
  disabled,
5678
6079
  style: [styles$8.iconButton, disabled && styles$8.iconButtonDisabled],
5679
6080
  onPress,
@@ -5706,6 +6107,7 @@ const SessionTimer = () => {
5706
6107
  return null;
5707
6108
  }
5708
6109
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
6110
+ testID: "cometchat-session-timer",
5709
6111
  style: [commonStyles.caption1Regular, styles$7.meetingTime],
5710
6112
  children: miliSecondsToMMSS(conferenceElapsedTime)
5711
6113
  });
@@ -5718,6 +6120,7 @@ const Header = () => {
5718
6120
  }
5719
6121
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
5720
6122
  style: styles$7.headerContainer,
6123
+ testID: "cometchat-header-panel",
5721
6124
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
5722
6125
  style: styles$7.meetingInfo,
5723
6126
  children: [title && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
@@ -5817,69 +6220,80 @@ const IdealTimeoutModal = ({ style = {} }) => {
5817
6220
  transparent: true,
5818
6221
  visible: idleTimeoutModalVisible,
5819
6222
  animationType: "none",
6223
+ supportedOrientations: [
6224
+ "portrait",
6225
+ "landscape-left",
6226
+ "landscape-right"
6227
+ ],
5820
6228
  statusBarTranslucent: true,
5821
6229
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.TouchableWithoutFeedback, {
5822
6230
  onPress: handleOverlayPress,
6231
+ testID: "cometchat-idle-timeout-overlay",
5823
6232
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Animated.View, {
5824
6233
  style: [styles$6.overlay, { opacity: fadeAnim }],
5825
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.TouchableWithoutFeedback, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Animated.View, {
5826
- style: [
5827
- styles$6.modal,
5828
- style,
5829
- {
5830
- opacity: fadeAnim,
5831
- transform: [{ scale: scaleAnim }]
5832
- }
5833
- ],
5834
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
5835
- style: styles$6.content,
5836
- children: [
5837
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
5838
- style: styles$6.timerIcon,
5839
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
5840
- style: [commonStyles.heading3Bold, styles$6.timerText],
5841
- children: formattedTime
5842
- })
5843
- }),
5844
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
5845
- style: styles$6.textContent,
5846
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
5847
- style: [commonStyles.heading2Medium, styles$6.title],
5848
- children: "Are you still there?"
5849
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.Text, {
5850
- style: [commonStyles.bodyRegular, styles$6.subtitle],
5851
- children: [
5852
- "You are the only one here, so this call will end in less than ",
5853
- ceilMinutes,
5854
- " minute",
5855
- ceilMinutes > 1 ? "s" : "",
5856
- ". Do you want to stay in this call?"
5857
- ]
5858
- })]
5859
- }),
5860
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
5861
- style: styles$6.actions,
5862
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.TouchableOpacity, {
5863
- style: [styles$6.button, styles$6.buttonSecondary],
5864
- onPress: onStayInCall,
5865
- activeOpacity: .8,
6234
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.TouchableWithoutFeedback, {
6235
+ testID: "cometchat-idle-timeout-modal",
6236
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Animated.View, {
6237
+ style: [
6238
+ styles$6.modal,
6239
+ style,
6240
+ {
6241
+ opacity: fadeAnim,
6242
+ transform: [{ scale: scaleAnim }]
6243
+ }
6244
+ ],
6245
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
6246
+ style: styles$6.content,
6247
+ children: [
6248
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
6249
+ style: styles$6.timerIcon,
5866
6250
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
5867
- style: [commonStyles.bodyMedium, styles$6.buttonSecondaryText],
5868
- children: "Stay on the call"
6251
+ style: [commonStyles.heading3Bold, styles$6.timerText],
6252
+ children: formattedTime
5869
6253
  })
5870
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.TouchableOpacity, {
5871
- style: [styles$6.button, styles$6.buttonPrimary],
5872
- onPress: leaveSession,
5873
- activeOpacity: .8,
5874
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
5875
- style: [commonStyles.bodyMedium, styles$6.buttonPrimaryText],
5876
- children: "Leave now"
5877
- })
5878
- })]
5879
- })
5880
- ]
6254
+ }),
6255
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
6256
+ style: styles$6.textContent,
6257
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
6258
+ style: [commonStyles.heading2Medium, styles$6.title],
6259
+ children: "Are you still there?"
6260
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.Text, {
6261
+ style: [commonStyles.bodyRegular, styles$6.subtitle],
6262
+ children: [
6263
+ "You are the only one here, so this call will end in less than ",
6264
+ ceilMinutes,
6265
+ " minute",
6266
+ ceilMinutes > 1 ? "s" : "",
6267
+ ". Do you want to stay in this call?"
6268
+ ]
6269
+ })]
6270
+ }),
6271
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
6272
+ style: styles$6.actions,
6273
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.TouchableOpacity, {
6274
+ style: [styles$6.button, styles$6.buttonSecondary],
6275
+ onPress: onStayInCall,
6276
+ activeOpacity: .8,
6277
+ testID: "cometchat-idle-timeout-stay-button",
6278
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
6279
+ style: [commonStyles.bodyMedium, styles$6.buttonSecondaryText],
6280
+ children: "Stay on the call"
6281
+ })
6282
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.TouchableOpacity, {
6283
+ style: [styles$6.button, styles$6.buttonPrimary],
6284
+ onPress: () => leaveSession(),
6285
+ activeOpacity: .8,
6286
+ testID: "cometchat-idle-timeout-leave-button",
6287
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
6288
+ style: [commonStyles.bodyMedium, styles$6.buttonPrimaryText],
6289
+ children: "Leave now"
6290
+ })
6291
+ })]
6292
+ })
6293
+ ]
6294
+ })
5881
6295
  })
5882
- }) })
6296
+ })
5883
6297
  })
5884
6298
  })
5885
6299
  });
@@ -5898,6 +6312,7 @@ const styles$6 = react_native.StyleSheet.create({
5898
6312
  borderWidth: 1,
5899
6313
  borderColor: "#383838",
5900
6314
  width: "100%",
6315
+ maxWidth: 372,
5901
6316
  paddingTop: 32,
5902
6317
  paddingHorizontal: 20,
5903
6318
  paddingBottom: 20,
@@ -5976,6 +6391,7 @@ const ShareInviteButton = () => {
5976
6391
  style: styles$5.shareButtonContainer,
5977
6392
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.TouchableOpacity, {
5978
6393
  style: styles$5.shareButton,
6394
+ testID: "cometchat-share-invite-button",
5979
6395
  onPress: () => {
5980
6396
  eventBus.publish({ type: "onShareInviteButtonClicked" });
5981
6397
  },
@@ -6112,6 +6528,7 @@ const ParticipantList = () => {
6112
6528
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.TouchableOpacity, {
6113
6529
  onPress: toggleParticipantListVisible,
6114
6530
  accessibilityLabel: "Close participants list",
6531
+ testID: "cometchat-participant-list-close-button",
6115
6532
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon_native_default, {
6116
6533
  name: "close",
6117
6534
  size: 24,
@@ -6133,7 +6550,8 @@ const ParticipantList = () => {
6133
6550
  style: styles$3.searchInput,
6134
6551
  value: searchTerm,
6135
6552
  onChangeText: setSearchTerm,
6136
- placeholderTextColor: "#858585"
6553
+ placeholderTextColor: "#858585",
6554
+ testID: "cometchat-participant-search-input"
6137
6555
  })]
6138
6556
  })
6139
6557
  }),
@@ -6274,45 +6692,6 @@ const styles$2 = react_native.StyleSheet.create({
6274
6692
  }
6275
6693
  });
6276
6694
 
6277
- //#endregion
6278
- //#region src/ui/toast/toast-state.ts
6279
- const MAX_TOASTS = 3;
6280
- let counter = 0;
6281
- const useToastStore = (0, zustand.create)((set) => ({
6282
- toasts: [],
6283
- addToast: (toast) => {
6284
- const id = `toast-${++counter}-${Date.now()}`;
6285
- const newToast = {
6286
- ...toast,
6287
- id,
6288
- createdAt: Date.now()
6289
- };
6290
- set((state) => {
6291
- const updated = [...state.toasts, newToast];
6292
- if (updated.length > MAX_TOASTS) {
6293
- return { toasts: updated.slice(-MAX_TOASTS) };
6294
- }
6295
- return { toasts: updated };
6296
- });
6297
- return id;
6298
- },
6299
- removeToast: (id) => {
6300
- set((state) => ({ toasts: state.toasts.filter((t) => t.id !== id) }));
6301
- },
6302
- clearAll: () => {
6303
- set({ toasts: [] });
6304
- }
6305
- }));
6306
- function showToast(params) {
6307
- return useToastStore.getState().addToast({
6308
- message: params.message,
6309
- type: params.type ?? "info",
6310
- duration: params.duration ?? 3e3,
6311
- position: params.position ?? "bottom",
6312
- action: params.action
6313
- });
6314
- }
6315
-
6316
6695
  //#endregion
6317
6696
  //#region src/ui/toast/Toast.native.tsx
6318
6697
  const SLIDE_IN_DURATION = 300;
@@ -6387,6 +6766,7 @@ function ToastItemView({ toast, onDismiss }) {
6387
6766
  }), toast.action && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
6388
6767
  style: styles$2.actionButton,
6389
6768
  onPress: handleActionPress,
6769
+ testID: "cometchat-toast-action-button",
6390
6770
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
6391
6771
  style: styles$2.actionText,
6392
6772
  children: toast.action.label
@@ -6439,15 +6819,20 @@ function CallUI(props) {
6439
6819
  const isConferenceJoined = useIsConferenceJoined();
6440
6820
  (0, react.useLayoutEffect)(() => {
6441
6821
  eventBus.publish({ type: INTERNAL_EVENTS.lifecycle.componentDidMount });
6442
- updateConfig(props.callSettings);
6822
+ updateConfig(props.sessionSettings);
6443
6823
  return () => {
6444
6824
  eventBus.publish({ type: INTERNAL_EVENTS.lifecycle.componentWillUnmount }, true);
6445
6825
  };
6446
- }, [props.callSettings]);
6826
+ }, [props.sessionSettings]);
6447
6827
  (0, react.useEffect)(() => {
6448
- useBaseStore.setState({ sdkPlatform: react_native.Platform.OS });
6828
+ if (props.sessionSettings.sdkPlatform) {
6829
+ useBaseStore.setState({ sdkPlatform: props.sessionSettings.sdkPlatform });
6830
+ } else {
6831
+ useBaseStore.setState({ sdkPlatform: react_native.Platform.OS === "ios" ? "react-native-ios" : "react-native-android" });
6832
+ }
6833
+ useBaseStore.setState({ platformVersion: react_native.Platform.Version });
6449
6834
  startSession();
6450
- }, []);
6835
+ }, [props.sessionSettings.sdkPlatform]);
6451
6836
  (0, react.useEffect)(() => {
6452
6837
  const sub = AudioModeEventEmitter.addListener(AudioModeModule_default.DEVICE_CHANGE_EVENT, (e) => {
6453
6838
  console.log("AudioMode.DEVICE_CHANGE_EVENT", e);
@@ -6460,13 +6845,13 @@ function CallUI(props) {
6460
6845
  (0, react.useEffect)(() => {
6461
6846
  if (react_native.Platform.OS === "android") {
6462
6847
  AudioModeModule_default.setMode(type === SESSION_TYPE.VOICE ? AudioModeModule_default.AUDIO_CALL : AudioModeModule_default.VIDEO_CALL);
6463
- if (props.callSettings.audioMode) {
6464
- AudioModeModule_default.setAudioDevice(props.callSettings.audioMode);
6848
+ if (props.sessionSettings.audioMode) {
6849
+ AudioModeModule_default.setAudioDevice(props.sessionSettings.audioMode);
6465
6850
  }
6466
6851
  } else if (react_native.Platform.OS === "ios") {
6467
6852
  AudioModeModule_default.updateDeviceList();
6468
6853
  }
6469
- }, [props.callSettings.audioMode, type]);
6854
+ }, [props.sessionSettings.audioMode, type]);
6470
6855
  if (isPIPLayoutEnabled) {
6471
6856
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PiPTile_default, {});
6472
6857
  }
@@ -6513,13 +6898,6 @@ const styles$1 = react_native.StyleSheet.create({
6513
6898
  alignItems: "center",
6514
6899
  gap: GRID_GAP,
6515
6900
  paddingHorizontal: 20
6516
- },
6517
- loadingContainer: {
6518
- ...react_native.StyleSheet.absoluteFillObject,
6519
- justifyContent: "center",
6520
- alignItems: "center",
6521
- backgroundColor: "#000",
6522
- zIndex: 1e3
6523
6901
  }
6524
6902
  });
6525
6903
  var index_native_default = CallUI;
@@ -6595,10 +6973,10 @@ const convertLegacyCallSettingsToV5Props = (callSettings) => {
6595
6973
  if (cs.defaultAudioMode === "BLUETOOTH" || cs.defaultAudioMode === "EARPIECE" || cs.defaultAudioMode === "HEADPHONES" || cs.defaultAudioMode === "SPEAKER") {
6596
6974
  v5Props.audioMode = cs.defaultAudioMode;
6597
6975
  }
6598
- if (cs.mode === "SPOTLIGHT") {
6599
- v5Props.layout = "SPOTLIGHT";
6600
- } else {
6601
- v5Props.layout = "SIDEBAR";
6976
+ if (typeof cs.layout === "string") {
6977
+ v5Props.layout = cs.layout;
6978
+ } else if (cs.mode === "SPOTLIGHT" || cs.mode === "SIDEBAR") {
6979
+ v5Props.layout = cs.mode;
6602
6980
  }
6603
6981
  if (cs.idleTimeoutPeriod) {
6604
6982
  v5Props.idleTimeoutPeriodAfterPrompt = 6e4;
@@ -6758,10 +7136,11 @@ async function callVerifyTokenAPI({ appId, region, calltoken, baseURL }) {
6758
7136
  }
6759
7137
 
6760
7138
  //#endregion
6761
- //#region src/AppRN.tsx
6762
- function App(props) {
7139
+ //#region src/AppReactNativeSDK.tsx
7140
+ function AppReactNativeSDK(props) {
6763
7141
  const [internalSettings, setInternalSettings] = react.default.useState(null);
6764
7142
  const [infoMessage, setInfoMessage] = react.default.useState(null);
7143
+ const sessionSettings = props.sessionSettings ?? props.callSettings ?? {};
6765
7144
  (0, react.useEffect)(() => {
6766
7145
  return eventBus.subscribe("onConnectionClosed", () => {
6767
7146
  setTimeout(() => {
@@ -6771,7 +7150,7 @@ function App(props) {
6771
7150
  }, []);
6772
7151
  (0, react.useEffect)(() => {
6773
7152
  const listeners = [];
6774
- const cs = props.callSettings ?? {};
7153
+ const cs = sessionSettings ?? {};
6775
7154
  if (cs.listener?.onUserJoined) {
6776
7155
  listeners.push(CometChatCalls.addEventListener("onParticipantJoined", cs.listener.onUserJoined));
6777
7156
  }
@@ -6809,7 +7188,7 @@ function App(props) {
6809
7188
  listener();
6810
7189
  });
6811
7190
  };
6812
- }, [props.callSettings]);
7191
+ }, [sessionSettings]);
6813
7192
  (0, react.useEffect)(() => {
6814
7193
  callVerifyTokenAPI({
6815
7194
  appId: CometChatCalls.appSettings?.appId || "",
@@ -6838,14 +7217,12 @@ function App(props) {
6838
7217
  visible: true
6839
7218
  });
6840
7219
  }
6841
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(index_native_default, { callSettings: {
6842
- ...props.callSettings,
6843
- ...convertLegacyCallSettingsToV5Props(props?.callSettings ?? {}),
7220
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(index_native_default, { sessionSettings: {
7221
+ ...sessionSettings,
7222
+ ...convertLegacyCallSettingsToV5Props(sessionSettings ?? {}),
6844
7223
  internalSettings
6845
7224
  } });
6846
7225
  }
6847
- var AppRN_default = App;
6848
- const AppComponent = App;
6849
7226
 
6850
7227
  //#endregion
6851
7228
  //#region src/v4/Constants.ts
@@ -10578,7 +10955,13 @@ var CometChatCalls = class extends SessionMethodsCore {
10578
10955
  static OngoingCallListener = OngoingCallListener;
10579
10956
  static CallSettingsBuilder = CallSettingsBuilder;
10580
10957
  static CallAppSettingsBuilder = CallAppSettingsBuilder;
10581
- static Component = AppComponent;
10958
+ static Component = AppReactNativeSDK;
10959
+ /**
10960
+ * Initializes the CometChat Calls SDK with the provided app settings.
10961
+ * Must be called before any other SDK methods.
10962
+ * @param appSettings - The application settings for configuring the SDK.
10963
+ * @returns An object indicating success or failure with error details.
10964
+ */
10582
10965
  static async init(appSettings) {
10583
10966
  const parsedAppSettings = valibot.safeParse(CallAppSettingsSchema, appSettings);
10584
10967
  if (!parsedAppSettings.success) {
@@ -10594,7 +10977,7 @@ var CometChatCalls = class extends SessionMethodsCore {
10594
10977
  }
10595
10978
  this.appSettings = parsedAppSettings.output;
10596
10979
  this.isInitialized = true;
10597
- const savedUser = this.getSavedUser();
10980
+ const savedUser = await this.getSavedUser();
10598
10981
  if (savedUser) {
10599
10982
  let parsedUser;
10600
10983
  if (typeof savedUser === "string") {
@@ -10613,6 +10996,14 @@ var CometChatCalls = class extends SessionMethodsCore {
10613
10996
  error: null
10614
10997
  };
10615
10998
  }
10999
+ /**
11000
+ * Logs in a user with their UID and an optional auth key.
11001
+ * If no auth key is provided, the one from app settings is used.
11002
+ * @param uid - The unique identifier of the user.
11003
+ * @param authKey - The authentication key. Falls back to the key provided in app settings.
11004
+ * @returns A Promise that resolves to the logged-in User object.
11005
+ * @throws {CometChatException} If login fails or validation errors occur.
11006
+ */
10616
11007
  static async login(uid, authKey) {
10617
11008
  try {
10618
11009
  if (this.loginInProgress) {
@@ -10655,12 +11046,11 @@ var CometChatCalls = class extends SessionMethodsCore {
10655
11046
  if (this.loggedInUser && this.loggedInUser.uid !== uid) {
10656
11047
  await this.logoutInternal();
10657
11048
  }
10658
- console.log("Logging in user with UID:", uid);
10659
11049
  const authToken = await this.loginWithUID(uid, resolvedAuthKey);
10660
11050
  const user = await this.authenticateWithToken(authToken);
10661
11051
  this.loginInProgress = false;
10662
11052
  this.loggedInUser = user;
10663
- this.saveUser(user);
11053
+ await this.saveUser(user);
10664
11054
  this.notifyLoginSuccess(user);
10665
11055
  return user;
10666
11056
  } catch (error) {
@@ -10670,6 +11060,12 @@ var CometChatCalls = class extends SessionMethodsCore {
10670
11060
  throw cometChatError;
10671
11061
  }
10672
11062
  }
11063
+ /**
11064
+ * Logs in a user directly with an auth token.
11065
+ * @param authToken - The authentication token for the user.
11066
+ * @returns A Promise that resolves to the logged-in User object.
11067
+ * @throws {CometChatException} If login fails or the token is invalid.
11068
+ */
10673
11069
  static async loginWithAuthToken(authToken) {
10674
11070
  try {
10675
11071
  if (this.loginInProgress) {
@@ -10702,7 +11098,7 @@ var CometChatCalls = class extends SessionMethodsCore {
10702
11098
  const user = await this.authenticateWithToken(authToken);
10703
11099
  this.loginInProgress = false;
10704
11100
  this.loggedInUser = user;
10705
- this.saveUser(user);
11101
+ await this.saveUser(user);
10706
11102
  this.notifyLoginSuccess(user);
10707
11103
  return user;
10708
11104
  } catch (error) {
@@ -10712,6 +11108,11 @@ var CometChatCalls = class extends SessionMethodsCore {
10712
11108
  throw cometChatError;
10713
11109
  }
10714
11110
  }
11111
+ /**
11112
+ * Logs out the currently logged-in user and clears local session data.
11113
+ * @returns A Promise that resolves to a success message string.
11114
+ * @throws {CometChatException} If no user is logged in or logout fails.
11115
+ */
10715
11116
  static async logout() {
10716
11117
  try {
10717
11118
  if (!this.loggedInUser) {
@@ -10729,24 +11130,53 @@ var CometChatCalls = class extends SessionMethodsCore {
10729
11130
  throw cometChatError;
10730
11131
  }
10731
11132
  }
11133
+ /**
11134
+ * Retrieves the currently logged-in user.
11135
+ * @returns The logged-in User object, or null if no user is logged in.
11136
+ */
10732
11137
  static getLoggedInUser() {
10733
11138
  if (this.loggedInUser && typeof this.loggedInUser === "string") {
10734
11139
  this.loggedInUser = JSON.parse(this.loggedInUser);
10735
11140
  }
10736
11141
  return this.loggedInUser;
10737
11142
  }
11143
+ /**
11144
+ * Retrieves the auth token of the currently logged-in user.
11145
+ * @returns The auth token string, or null if no user is logged in.
11146
+ */
10738
11147
  static getUserAuthToken() {
10739
11148
  return this.loggedInUser?.authToken || null;
10740
11149
  }
11150
+ /**
11151
+ * Checks whether a user is currently logged in.
11152
+ * @returns True if a user is logged in with a valid auth token, false otherwise.
11153
+ */
10741
11154
  static isUserLoggedIn() {
10742
11155
  return this.loggedInUser !== null && this.loggedInUser.authToken !== undefined;
10743
11156
  }
11157
+ /**
11158
+ * Registers a login listener to receive login/logout lifecycle callbacks.
11159
+ * @param listenerId - A unique identifier for the listener.
11160
+ * @param listener - The listener object with callback methods.
11161
+ */
10744
11162
  static addLoginListener(listenerId, listener) {
10745
11163
  this.loginListeners.set(listenerId, listener);
10746
11164
  }
11165
+ /**
11166
+ * Removes a previously registered login listener.
11167
+ * @param listenerId - The unique identifier of the listener to remove.
11168
+ */
10747
11169
  static removeLoginListener(listenerId) {
10748
11170
  this.loginListeners.delete(listenerId);
10749
11171
  }
11172
+ /**
11173
+ * Generates a call token for the given session.
11174
+ * Uses the provided auth token or falls back to the logged-in user's token.
11175
+ * @param sessionId - The session ID to generate a token for.
11176
+ * @param authToken - Optional auth token. If omitted, the logged-in user's token is used.
11177
+ * @returns A Promise that resolves to an object containing the generated token.
11178
+ * @throws {CometChatException} If the session ID is missing, no auth token is available, or the SDK is not initialized.
11179
+ */
10750
11180
  static async generateToken(sessionId, authToken) {
10751
11181
  try {
10752
11182
  if (!sessionId || sessionId.trim() === "") {
@@ -10801,7 +11231,7 @@ var CometChatCalls = class extends SessionMethodsCore {
10801
11231
  appId
10802
11232
  },
10803
11233
  body: {
10804
- platform: "web",
11234
+ platform: "react-native",
10805
11235
  deviceId: this.generateDeviceId()
10806
11236
  }
10807
11237
  });
@@ -10822,7 +11252,7 @@ var CometChatCalls = class extends SessionMethodsCore {
10822
11252
  appId
10823
11253
  },
10824
11254
  body: {
10825
- platform: "web",
11255
+ platform: "react-native",
10826
11256
  deviceId: this.generateDeviceId()
10827
11257
  }
10828
11258
  });
@@ -10862,7 +11292,7 @@ var CometChatCalls = class extends SessionMethodsCore {
10862
11292
  }
10863
11293
  }
10864
11294
  this.loggedInUser = null;
10865
- this.clearSavedUser();
11295
+ await this.clearSavedUser();
10866
11296
  }
10867
11297
  static async callGenerateTokenAPI(sessionId, authToken) {
10868
11298
  const appId = this.appSettings?.appId || "";
@@ -10890,9 +11320,11 @@ var CometChatCalls = class extends SessionMethodsCore {
10890
11320
  baseURL: this.getBaseURL()
10891
11321
  });
10892
11322
  }
10893
- static saveUser(user) {
11323
+ static getStorageKey() {
11324
+ return `${this.appSettings?.appId}:common_store/user`;
11325
+ }
11326
+ static async saveUser(user) {
10894
11327
  try {
10895
- const key = `${this.appSettings?.appId}:common_store/user`;
10896
11328
  const userWithDefaults = {
10897
11329
  hasBlockedMe: false,
10898
11330
  blockedByMe: false,
@@ -10901,31 +11333,28 @@ var CometChatCalls = class extends SessionMethodsCore {
10901
11333
  role: user.role || "default",
10902
11334
  wsChannel: user.wsChannel || { identity: `[${this.appSettings?.appId}]${user.uid}` }
10903
11335
  };
10904
- localStorage.setItem(key, JSON.stringify(userWithDefaults));
11336
+ await __react_native_async_storage_async_storage.default.setItem(this.getStorageKey(), JSON.stringify(userWithDefaults));
10905
11337
  } catch (error) {
10906
- console.warn("Failed to save user to localStorage:", error);
11338
+ console.warn("Failed to save user to AsyncStorage:", error);
10907
11339
  }
10908
11340
  }
10909
- static getSavedUser() {
11341
+ static async getSavedUser() {
10910
11342
  try {
10911
- const key = `${this.appSettings?.appId}:common_store/user`;
10912
- const savedUser = localStorage.getItem(key);
10913
- return savedUser ? savedUser : null;
11343
+ return await __react_native_async_storage_async_storage.default.getItem(this.getStorageKey());
10914
11344
  } catch (error) {
10915
- console.warn("Failed to get saved user from localStorage:", error);
11345
+ console.warn("Failed to get saved user from AsyncStorage:", error);
10916
11346
  return null;
10917
11347
  }
10918
11348
  }
10919
- static clearSavedUser() {
11349
+ static async clearSavedUser() {
10920
11350
  try {
10921
- const key = `${this.appSettings?.appId}:common_store/user`;
10922
- localStorage.removeItem(key);
11351
+ await __react_native_async_storage_async_storage.default.removeItem(this.getStorageKey());
10923
11352
  } catch (error) {
10924
- console.warn("Failed to clear saved user from localStorage:", error);
11353
+ console.warn("Failed to clear saved user from AsyncStorage:", error);
10925
11354
  }
10926
11355
  }
10927
11356
  static generateDeviceId() {
10928
- return "web_" + Math.random().toString(36).substr(2, 9);
11357
+ return "rn_" + Math.random().toString(36).substring(2, 11);
10929
11358
  }
10930
11359
  static createError(error) {
10931
11360
  if (error.errorCode && error.errorDescription) {
@@ -10980,11 +11409,36 @@ var CometChatCalls = class extends SessionMethodsCore {
10980
11409
  }
10981
11410
  });
10982
11411
  }
10983
- static addEventListener(eventType, listener) {
10984
- return eventBus.subscribe(eventType, listener);
11412
+ /**
11413
+ * Adds an event listener for SDK events.
11414
+ * @param eventType - The type of event to listen for.
11415
+ * @param listener - The callback function to invoke when the event fires.
11416
+ * @param options - Optional configuration including an AbortSignal for automatic cleanup.
11417
+ * @returns An unsubscribe function to remove the listener.
11418
+ */
11419
+ static addEventListener(eventType, listener, options) {
11420
+ return eventBus.subscribe(eventType, listener, options);
11421
+ }
11422
+ /**
11423
+ * Sets the audio output mode (mobile only).
11424
+ * @param mode - The audio mode to set (e.g., 'SPEAKER', 'EARPIECE', 'BLUETOOTH', 'HEADPHONES').
11425
+ */
11426
+ static setAudioMode(mode) {
11427
+ setAudioMode(mode);
11428
+ }
11429
+ /**
11430
+ * Enables Picture-in-Picture (PIP) layout during the call.
11431
+ */
11432
+ static enablePictureInPictureLayout() {
11433
+ enablePictureInPictureLayout();
11434
+ }
11435
+ /**
11436
+ * Disables Picture-in-Picture (PIP) layout.
11437
+ */
11438
+ static disablePictureInPictureLayout() {
11439
+ disablePictureInPictureLayout();
10985
11440
  }
10986
11441
  };
10987
11442
 
10988
11443
  //#endregion
10989
- exports.CometChatCalls = CometChatCalls;
10990
- //# sourceMappingURL=index.js.map
11444
+ exports.CometChatCalls = CometChatCalls;