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

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.mjs CHANGED
@@ -5,6 +5,7 @@ import { combine, persist, subscribeWithSelector } from "zustand/middleware";
5
5
  import { shallow } from "zustand/shallow";
6
6
  import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
7
7
  import JitsiMeetJS from "lib-jitsi-meet";
8
+ import AsyncStorage from "@react-native-async-storage/async-storage";
8
9
  import { ActivityIndicator, Animated, AppState, DeviceEventEmitter, Dimensions, FlatList, Image, Modal, NativeEventEmitter, NativeModules, PanResponder, Platform, Pressable, ScrollView, StyleSheet, Text, TextInput, TouchableOpacity, TouchableWithoutFeedback, View } from "react-native";
9
10
  import { RTCView, permissions } from "react-native-webrtc";
10
11
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -44,17 +45,24 @@ var EventBus = class {
44
45
  }
45
46
  }
46
47
  }
47
- subscribe(actionType, listener) {
48
+ subscribe(actionType, listener, options) {
49
+ if (options?.signal?.aborted) {
50
+ return () => {};
51
+ }
48
52
  if (!this.actionListenersMap.get(actionType)) {
49
53
  this.actionListenersMap.set(actionType, []);
50
54
  }
51
55
  this.actionListenersMap.get(actionType)?.push(listener);
52
- return () => {
56
+ const unsubscribe = () => {
53
57
  const listenersList = this.actionListenersMap.get(actionType);
54
58
  if (listenersList) {
55
59
  this.actionListenersMap.set(actionType, listenersList.filter((l) => l !== listener));
56
60
  }
57
61
  };
62
+ if (options?.signal) {
63
+ options.signal.addEventListener("abort", unsubscribe, { once: true });
64
+ }
65
+ return unsubscribe;
58
66
  }
59
67
  };
60
68
  const eventBus = new EventBus();
@@ -104,10 +112,12 @@ const VIDEO_QUALITY_LEVELS = {
104
112
  LOW: 180,
105
113
  NONE: 0
106
114
  };
107
- const PLATFORM = {
115
+ const SDK_PLATFORM = {
108
116
  WEB: "web",
109
117
  ANDROID: "android",
110
- IOS: "ios"
118
+ IOS: "ios",
119
+ REACT_NATIVE_ANDROID: "react-native-android",
120
+ REACT_NATIVE_IOS: "react-native-ios"
111
121
  };
112
122
  const EVENT_LISTENER_METHODS = {
113
123
  SessionStatusListener: {
@@ -222,7 +232,7 @@ function calculateTileLayout(containerWidth, containerHeight, numberOfTiles) {
222
232
  const tileArea = totalArea / numberOfTiles;
223
233
  const minArea = MIN_TILE_WIDTH * MIN_TILE_WIDTH * MIN_ASPECT_RATIO;
224
234
  if (tileArea < minArea) {
225
- const columnCount$1 = Math.floor(containerWidth / MIN_TILE_WIDTH);
235
+ const columnCount$1 = Math.max(2, Math.floor(containerWidth / MIN_TILE_WIDTH));
226
236
  const rowCount$1 = Math.ceil(numberOfTiles / columnCount$1);
227
237
  const totalHorizontalGap$1 = columnCount$1 * GRID_GAP;
228
238
  const tileWidth$1 = (containerWidth - totalHorizontalGap$1) / columnCount$1;
@@ -405,12 +415,37 @@ function isDeviceEqual(device1, device2) {
405
415
  function getDefaultDevice(devices) {
406
416
  return devices.find((device) => device.deviceId === "default") || devices[0];
407
417
  }
418
+ /**
419
+ * Returns a promise that resolves when the given Zustand store
420
+ * satisfies the provided predicate. Resolves immediately if the
421
+ * condition is already met. Includes a timeout to avoid hanging
422
+ * forever (defaults to 5 000 ms).
423
+ */
424
+ function waitForStoreState(store, predicate, timeoutMs = 5e3) {
425
+ return new Promise((resolve, reject) => {
426
+ if (predicate(store.getState())) {
427
+ resolve();
428
+ return;
429
+ }
430
+ const timer = setTimeout(() => {
431
+ unsubscribe();
432
+ reject(new Error("waitForStoreState timed out"));
433
+ }, timeoutMs);
434
+ const unsubscribe = store.subscribe((state) => {
435
+ if (predicate(state)) {
436
+ clearTimeout(timer);
437
+ unsubscribe();
438
+ resolve();
439
+ }
440
+ });
441
+ });
442
+ }
408
443
 
409
444
  //#endregion
410
445
  //#region calls-sdk-core/utils/try-catch.ts
411
- async function tryCatch(promise) {
446
+ async function tryCatch(promise, timeoutMs) {
412
447
  try {
413
- const data = await promise;
448
+ const data = timeoutMs != null ? await Promise.race([promise, new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), timeoutMs))]) : await promise;
414
449
  return {
415
450
  data,
416
451
  error: null
@@ -454,76 +489,163 @@ function debounce(func, delay) {
454
489
  //#endregion
455
490
  //#region calls-sdk-core/utils/session-methods-core.ts
456
491
  var SessionMethodsCore = class {
492
+ /**
493
+ * Mutes the local user's audio during the call.
494
+ */
457
495
  static muteAudio() {
458
496
  muteAudioTrack();
459
497
  }
498
+ /**
499
+ * Unmutes the local user's audio during the call.
500
+ */
460
501
  static unmuteAudio() {
461
502
  unMuteAudioTrack();
462
503
  }
504
+ /**
505
+ * Toggles the local user's audio mute state.
506
+ * If audio is muted, it will be unmuted, and vice versa.
507
+ */
508
+ static toggleAudio() {
509
+ toggleAudioTrack();
510
+ }
511
+ /**
512
+ * Pauses the local user's video stream.
513
+ */
463
514
  static pauseVideo() {
464
515
  pauseVideoTrack();
465
516
  }
517
+ /**
518
+ * Resumes the local user's video stream.
519
+ */
466
520
  static resumeVideo() {
467
521
  resumeVideoTrack();
468
522
  }
523
+ /**
524
+ * Toggles the local user's video stream.
525
+ * If video is paused, it will be resumed, and vice versa.
526
+ */
527
+ static toggleVideo() {
528
+ toggleVideoTrack();
529
+ }
530
+ /**
531
+ * Local user leaves the current session.
532
+ */
469
533
  static leaveSession() {
470
534
  leaveSession();
471
535
  }
472
- static startScreenSharing() {
473
- startScreenSharing();
474
- }
475
- static stopScreenSharing() {
476
- stopScreenSharing();
536
+ /**
537
+ * Ends the current session for all participants.
538
+ * This will terminate the conference and disconnect everyone.
539
+ */
540
+ static endSessionForAll() {
541
+ leaveSession({ shouldEndSession: true });
477
542
  }
543
+ /**
544
+ * Raises the user's virtual hand in the call.
545
+ */
478
546
  static raiseHand() {
479
547
  raisedHandLocal();
480
548
  }
549
+ /**
550
+ * Lowers the user's virtual hand in the call.
551
+ */
481
552
  static lowerHand() {
482
553
  lowerHandLocal();
483
554
  }
555
+ /**
556
+ * Toggles the user's virtual hand state.
557
+ * If the hand is raised, it will be lowered, and vice versa.
558
+ */
559
+ static toggleHand() {
560
+ toggleRaiseHand();
561
+ }
562
+ /**
563
+ * Switches between the front and rear camera.
564
+ */
484
565
  static switchCamera() {
485
566
  switchCamera();
486
567
  }
568
+ /**
569
+ * Sets the layout type for the call.
570
+ * @param layout - The type of layout to set (tile, sidebar or spotlight).
571
+ */
487
572
  static setLayout(layout$1) {
488
573
  setLayout(layout$1);
489
574
  }
490
- static startRecording() {}
491
- static stopRecording() {}
492
- static enablePictureInPictureLayout() {
493
- enablePictureInPictureLayout();
575
+ /**
576
+ * Starts recording the call.
577
+ */
578
+ static startRecording() {
579
+ startRecording();
494
580
  }
495
- static disablePictureInPictureLayout() {
496
- disablePictureInPictureLayout();
581
+ /**
582
+ * Stops the ongoing call recording.
583
+ */
584
+ static stopRecording() {
585
+ stopRecording();
586
+ }
587
+ /**
588
+ * Toggles the call recording state.
589
+ * If recording is active, it will be stopped, and vice versa.
590
+ */
591
+ static toggleRecording() {
592
+ toggleRecording();
497
593
  }
594
+ /**
595
+ * Pins a participant's video to focus on them.
596
+ * @param participantId - The ID of the participant to pin.
597
+ * @param type - The type of the participant.
598
+ */
498
599
  static pinParticipant(participantId, type) {
499
600
  pinParticipant(participantId, type);
500
601
  }
602
+ /**
603
+ * Unpins a participant's video.
604
+ */
501
605
  static unpinParticipant() {
502
606
  unpinParticipant();
503
607
  }
608
+ /**
609
+ * Mutes the audio of a specific participant.
610
+ * @param participantId - The ID of the participant to mute.
611
+ */
504
612
  static muteParticipant(participantId) {
505
613
  muteParticipant(participantId);
506
614
  }
615
+ /**
616
+ * Pauses the video stream of a specific participant.
617
+ * @param participantId - The ID of the participant whose video to pause.
618
+ */
507
619
  static pauseParticipantVideo(participantId) {
508
620
  pauseParticipantVideo(participantId);
509
621
  }
622
+ /**
623
+ * Sets the unread message count displayed on the chat button.
624
+ * @param count - The number of unread messages.
625
+ */
510
626
  static setChatButtonUnreadCount(count) {
511
627
  setChatButtonUnreadCount(count);
512
628
  }
513
629
  /**
514
- * @deprecated use startScreenSharing() instead
630
+ * Toggles the visibility of the participant list panel.
515
631
  */
516
- static startScreenShare() {
517
- this.startScreenSharing();
632
+ static toggleParticipantList() {
633
+ toggleParticipantList();
518
634
  }
519
635
  /**
520
- * @deprecated use stopScreenSharing() instead
636
+ * Shows the participant list panel.
521
637
  */
522
- static stopScreenShare() {
523
- this.stopScreenSharing();
638
+ static showParticipantList() {
639
+ showParticipantList();
524
640
  }
525
641
  /**
526
- * @deprecated switchToVideoCall is deprecated and not supported
642
+ * Hides the participant list panel.
643
+ */
644
+ static hideParticipantList() {
645
+ hideParticipantList();
646
+ }
647
+ /**
648
+ * @deprecated switchToVideoCall is deprecated and not supported.
527
649
  */
528
650
  static switchToVideoCall() {
529
651
  console.error("switchToVideoCall method deprecated and not supported.");
@@ -613,6 +735,27 @@ async function createLocalTrack(type, deviceId = null, cameraFacing = CAMERA_FAC
613
735
  }
614
736
  }
615
737
  }
738
+ function createLocalTracks() {
739
+ const enableCompanionMode = useConfigStore.getState().enableCompanionMode;
740
+ if (!enableCompanionMode) {
741
+ const audioInputDeviceId = useConfigStore.getState().audioInputDeviceId ?? useBaseStore.getState().audioInputDevice?.deviceId;
742
+ createLocalTrack("audio", audioInputDeviceId);
743
+ }
744
+ const sessionType = useConfigStore.getState().sessionType;
745
+ if (sessionType === SESSION_TYPE.VIDEO) {
746
+ const videoInputDeviceIdP1 = useConfigStore.getState().videoInputDeviceId;
747
+ const videoInputDeviceIdP2 = useBaseStore.getState().videoInputDevice?.deviceId;
748
+ const initialCameraFacingP1 = useConfigStore.getState().initialCameraFacing;
749
+ const initialCameraFacingP2 = useBaseStore.getState().cameraFacing;
750
+ if (videoInputDeviceIdP1) {
751
+ createLocalTrack("video", videoInputDeviceIdP1);
752
+ } else if (initialCameraFacingP1) {
753
+ createLocalTrack("video", null, initialCameraFacingP2);
754
+ } else {
755
+ createLocalTrack("video", videoInputDeviceIdP2, initialCameraFacingP2);
756
+ }
757
+ }
758
+ }
616
759
  function updateAudioInputDevice(deviceId) {
617
760
  const audioInputDevices = useBaseStore.getState().audioInputDevices.filter((device) => device.deviceId !== "");
618
761
  if (audioInputDevices.length > 0) {
@@ -794,7 +937,7 @@ function sendParticipantListChangedEvent() {
794
937
 
795
938
  //#endregion
796
939
  //#region calls-sdk-core/store/config.ts
797
- const initialState$7 = {
940
+ const initialState$8 = {
798
941
  sessionType: "VIDEO",
799
942
  autoStartRecording: false,
800
943
  layout: LAYOUT.TILE,
@@ -812,7 +955,6 @@ const initialState$7 = {
812
955
  hideLeaveSessionButton: false,
813
956
  hideToggleAudioButton: false,
814
957
  hideParticipantListButton: false,
815
- hideSwitchLayoutButton: false,
816
958
  hideChatButton: true,
817
959
  hideToggleVideoButton: false,
818
960
  hideScreenSharingButton: false,
@@ -825,13 +967,17 @@ const initialState$7 = {
825
967
  startVideoPaused: false,
826
968
  title: "",
827
969
  enableNoiseReduction: false,
970
+ unstable_renderAudioOnly: false,
828
971
  idleTimeoutPeriodBeforePrompt: 6e4,
829
972
  idleTimeoutPeriodAfterPrompt: 18e4,
830
973
  enableSpotlightDrag: true,
831
974
  enableSpotlightSwap: true,
832
- showFrameRate: false
975
+ showFrameRate: false,
976
+ enableCompanionMode: false,
977
+ isPeerCall: false,
978
+ enableNotifications: true
833
979
  };
834
- const useConfigStore = create()(subscribeWithSelector(combine(initialState$7, (set) => ({ reset: () => set(initialState$7) }))));
980
+ const useConfigStore = create()(subscribeWithSelector(combine(initialState$8, (set) => ({ reset: () => set(initialState$8) }))));
835
981
  const setConfig = (config) => {
836
982
  useConfigStore.setState(config);
837
983
  };
@@ -849,18 +995,24 @@ const initialLocalParticipant = {
849
995
  type: "human",
850
996
  uid: "unknown"
851
997
  };
852
- const initialState$6 = {
998
+ const initialState$7 = {
853
999
  dominantSpeakers: [],
854
1000
  localParticipant: initialLocalParticipant,
855
1001
  participants: [],
856
1002
  virtualParticipants: []
857
1003
  };
858
- const useParticipantStore = create()(subscribeWithSelector(combine(initialState$6, (set, get$1) => ({
1004
+ const useParticipantStore = create()(subscribeWithSelector(combine(initialState$7, (set, get$1) => ({
859
1005
  addParticipant: (participant) => {
860
- set((state) => ({ participants: [...state.participants, participant] }));
1006
+ set((state) => ({ participants: state.participants.some((p) => p.pid === participant.pid) ? state.participants.map((p) => p.pid === participant.pid ? {
1007
+ ...p,
1008
+ ...participant
1009
+ } : p) : [...state.participants, participant] }));
861
1010
  },
862
1011
  addVirtualParticipant: (participant) => {
863
- set((state) => ({ virtualParticipants: [...state.virtualParticipants, participant] }));
1012
+ 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 ? {
1013
+ ...p,
1014
+ ...participant
1015
+ } : p) : [...state.virtualParticipants, participant] }));
864
1016
  },
865
1017
  clearParticipants: () => set({
866
1018
  participants: [],
@@ -930,7 +1082,7 @@ const useParticipantStore = create()(subscribeWithSelector(combine(initialState$
930
1082
  }
931
1083
  return get$1().participants.find((p) => p.pid === pid);
932
1084
  },
933
- reset: () => set(initialState$6)
1085
+ reset: () => set(initialState$7)
934
1086
  }))));
935
1087
  function useAllParticipants() {
936
1088
  const localParticipant = useParticipantStore((state) => state.localParticipant);
@@ -1064,7 +1216,7 @@ useParticipantStore.subscribe((state) => state.participants.filter((p) => p.uid)
1064
1216
 
1065
1217
  //#endregion
1066
1218
  //#region calls-sdk-core/store/conference.ts
1067
- const initialState$5 = {
1219
+ const initialState$6 = {
1068
1220
  conference: null,
1069
1221
  conferenceJoined: false,
1070
1222
  conferenceJoinedAt: null,
@@ -1079,7 +1231,7 @@ const initialState$5 = {
1079
1231
  },
1080
1232
  isRecording: false
1081
1233
  };
1082
- const useConferenceStore = create()(subscribeWithSelector(combine(initialState$5, (set) => ({
1234
+ const useConferenceStore = create()(subscribeWithSelector(combine(initialState$6, (set) => ({
1083
1235
  conferenceWillJoin: (conference) => {
1084
1236
  if (typeof window?.APP !== "undefined") {
1085
1237
  window.APP.conference._room = conference;
@@ -1090,13 +1242,15 @@ const useConferenceStore = create()(subscribeWithSelector(combine(initialState$5
1090
1242
  });
1091
1243
  },
1092
1244
  reset: () => {
1093
- set(initialState$5);
1245
+ set(initialState$6);
1094
1246
  },
1095
1247
  raiseHand: (participantId, timestamp) => {
1096
1248
  set((state) => ({ raiseHandMap: new Map(state.raiseHandMap).set(participantId, timestamp) }));
1097
1249
  sendParticipantEvent(EVENT_LISTENER_METHODS.ParticipantEventsListner.onParticipantHandRaised, participantId);
1098
1250
  },
1099
1251
  lowerHand: (participantId) => {
1252
+ const hasRaisedHand = useConferenceStore.getState().raiseHandMap.has(participantId);
1253
+ if (!hasRaisedHand) return;
1100
1254
  set((state) => {
1101
1255
  const raiseHandMap = new Map(state.raiseHandMap);
1102
1256
  raiseHandMap.delete(participantId);
@@ -1107,13 +1261,22 @@ const useConferenceStore = create()(subscribeWithSelector(combine(initialState$5
1107
1261
  leaveConference: async () => {
1108
1262
  const conference = useConferenceStore.getState().conference;
1109
1263
  if (conference) {
1110
- const { error } = await tryCatch(conference.leave());
1264
+ const { error } = await tryCatch(conference.leave(), 500);
1111
1265
  if (error) {
1112
1266
  console.warn("Error leaving conference:", error);
1113
1267
  eventBus.publish({ type: EVENT_LISTENER_METHODS.SessionStatusListener.onSessionLeft });
1114
1268
  }
1115
1269
  }
1116
1270
  },
1271
+ endConference: async () => {
1272
+ const conference = useConferenceStore.getState().conference;
1273
+ if (conference) {
1274
+ const { error } = await tryCatch(conference.end());
1275
+ if (error) {
1276
+ console.warn("Error ending conference:", error);
1277
+ }
1278
+ }
1279
+ },
1117
1280
  stopRecording: async () => {
1118
1281
  const conference = useConferenceStore.getState().conference;
1119
1282
  if (conference) {
@@ -1253,7 +1416,7 @@ useConferenceStore.subscribe((state) => state.conference, (conference) => {
1253
1416
 
1254
1417
  //#endregion
1255
1418
  //#region calls-sdk-core/store/tracks.ts
1256
- const initialState$4 = {
1419
+ const initialState$5 = {
1257
1420
  tracks: [],
1258
1421
  permissions: {
1259
1422
  audio: false,
@@ -1261,9 +1424,9 @@ const initialState$4 = {
1261
1424
  initialized: false
1262
1425
  }
1263
1426
  };
1264
- const useTracksStore = create()(subscribeWithSelector(combine(initialState$4, (set, get$1) => ({
1427
+ const useTracksStore = create()(subscribeWithSelector(combine(initialState$5, (set, get$1) => ({
1265
1428
  reset: () => set({
1266
- ...initialState$4,
1429
+ ...initialState$5,
1267
1430
  permissions: get$1().permissions
1268
1431
  }),
1269
1432
  addTrack: (originalTrack) => set((state) => {
@@ -1285,6 +1448,12 @@ const useTracksStore = create()(subscribeWithSelector(combine(initialState$4, (s
1285
1448
  muted: originalTrack.isMuted() ? 1 : 0,
1286
1449
  originalTrack
1287
1450
  };
1451
+ const existingIdx = state.tracks.findIndex((t) => t.pid === participantId && t.mediaType === track.mediaType && t.local === isLocal);
1452
+ if (existingIdx !== -1) {
1453
+ const tracks = [...state.tracks];
1454
+ tracks[existingIdx] = track;
1455
+ return { tracks };
1456
+ }
1288
1457
  return { tracks: [...state.tracks, track] };
1289
1458
  }),
1290
1459
  removeTrack: (originalTrack) => set((state) => ({ tracks: state.tracks.filter((track) => track.originalTrack !== originalTrack) })),
@@ -1486,8 +1655,13 @@ useTracksStore.subscribe((state) => state.tracks.find((t) => t.mediaType === MED
1486
1655
  }
1487
1656
  if (track) {
1488
1657
  const deviceId = track.getDeviceId();
1489
- const device = useBaseStore.getState().audioInputDevices.find((d) => d.deviceId === deviceId);
1490
- updateAudioInputDeviceState(device, true);
1658
+ waitForStoreState(useBaseStore, (state) => state.audioInputDevices.length > 0).then(() => {
1659
+ const audioInputDevices = useBaseStore.getState().audioInputDevices;
1660
+ const device = audioInputDevices.find((d) => d.deviceId === deviceId);
1661
+ updateAudioInputDeviceState(device, true);
1662
+ }).catch(() => {
1663
+ updateAudioInputDeviceState(undefined, true);
1664
+ });
1491
1665
  }
1492
1666
  });
1493
1667
  useTracksStore.subscribe((state) => state.tracks.find((t) => t.mediaType === MEDIA_TYPE.VIDEO && t.local)?.originalTrack, (track, prevTrack) => {
@@ -1634,7 +1808,7 @@ function updateConfig(config) {
1634
1808
 
1635
1809
  //#endregion
1636
1810
  //#region calls-sdk-core/store/base.ts
1637
- const initialState$3 = {
1811
+ const initialState$4 = {
1638
1812
  audioModeMenuVisible: false,
1639
1813
  audioModes: [],
1640
1814
  audioInputDevices: [],
@@ -1669,20 +1843,24 @@ const initialState$3 = {
1669
1843
  desktopSharingFrameRate: 5,
1670
1844
  chatButtonUnreadCount: 0,
1671
1845
  enableNoiseReduction: true,
1672
- sdkPlatform: PLATFORM.WEB,
1846
+ sdkPlatform: SDK_PLATFORM.WEB,
1673
1847
  webOSName: "unknown",
1674
1848
  isMobileBrowser: false,
1675
1849
  visibleParticipants: {
1676
1850
  startIndex: 0,
1677
1851
  endIndex: 0
1852
+ },
1853
+ sidebarVisibleParticipants: {
1854
+ startIndex: 0,
1855
+ endIndex: 0
1678
1856
  }
1679
1857
  };
1680
- const useBaseStore = create()(subscribeWithSelector(persist(combine(initialState$3, (set, get$1) => ({
1858
+ const useBaseStore = create()(subscribeWithSelector(persist(combine(initialState$4, (set, get$1) => ({
1681
1859
  addSubscriptions: (subscriptions) => {
1682
1860
  useBaseStore.setState((state) => ({ subscriptions: [...state.subscriptions, ...subscriptions] }));
1683
1861
  },
1684
1862
  reset: () => set((state) => ({
1685
- ...initialState$3,
1863
+ ...initialState$4,
1686
1864
  audioInputDevice: state.audioInputDevice,
1687
1865
  audioOutputDevice: state.audioOutputDevice,
1688
1866
  videoInputDevice: state.videoInputDevice,
@@ -1693,11 +1871,11 @@ const useBaseStore = create()(subscribeWithSelector(persist(combine(initialState
1693
1871
  toggleParticipantListVisible: () => set((state) => ({ participantListVisible: !state.participantListVisible })),
1694
1872
  incrementConnectionRetryCount: () => set((state) => ({ connectionRetryCount: state.connectionRetryCount + 1 })),
1695
1873
  isMobileSDK: () => {
1696
- const isMobileSDK = get$1().sdkPlatform === "android" || get$1().sdkPlatform === "ios";
1874
+ const isMobileSDK = get$1().sdkPlatform !== "web";
1697
1875
  return isMobileSDK;
1698
1876
  },
1699
1877
  isMobile: () => {
1700
- const isMobileSDK = get$1().sdkPlatform === "android" || get$1().sdkPlatform === "ios";
1878
+ const isMobileSDK = get$1().sdkPlatform !== "web";
1701
1879
  const isMobileBrowser = get$1().isMobileBrowser;
1702
1880
  return isMobileSDK || isMobileBrowser;
1703
1881
  },
@@ -1743,6 +1921,7 @@ const useBaseStore = create()(subscribeWithSelector(persist(combine(initialState
1743
1921
  const toggleParticipantListVisible = useBaseStore.getState().toggleParticipantListVisible;
1744
1922
  const hideParticipantList = () => useBaseStore.setState({ participantListVisible: false });
1745
1923
  const showParticipantList = () => useBaseStore.setState({ participantListVisible: true });
1924
+ const toggleParticipantList = () => useBaseStore.setState((state) => ({ participantListVisible: !state.participantListVisible }));
1746
1925
  const toggleMoreMenuVisible = useBaseStore.getState().toggleMoreMenuVisible;
1747
1926
  const toggleAudioModeMenuVisible = () => {
1748
1927
  useBaseStore.setState((state) => ({ audioModeMenuVisible: !state.audioModeMenuVisible }));
@@ -1791,6 +1970,9 @@ const toggleEnableNoiseReduction = () => {
1791
1970
  const setChatButtonUnreadCount = (count) => {
1792
1971
  useBaseStore.setState({ chatButtonUnreadCount: count });
1793
1972
  };
1973
+ const setAudioMode = (mode) => {
1974
+ useBaseStore.setState({ selectedAudioModeType: mode });
1975
+ };
1794
1976
  const getLayout = () => {
1795
1977
  return useBaseStore.getState().layout;
1796
1978
  };
@@ -1913,13 +2095,13 @@ initBaseStoreSubscriptions();
1913
2095
 
1914
2096
  //#endregion
1915
2097
  //#region calls-sdk-core/store/connection.ts
1916
- const initialState$2 = {
2098
+ const initialState$3 = {
1917
2099
  connection: undefined,
1918
2100
  connectionStatus: "initial",
1919
2101
  error: undefined,
1920
2102
  timeEstablished: undefined
1921
2103
  };
1922
- const useConnectionStore = create()(subscribeWithSelector(combine(initialState$2, (set) => ({
2104
+ const useConnectionStore = create()(subscribeWithSelector(combine(initialState$3, (set) => ({
1923
2105
  connectionEstablished: (connection) => set({
1924
2106
  connection,
1925
2107
  connectionStatus: "connected",
@@ -1952,17 +2134,88 @@ const useConnectionStore = create()(subscribeWithSelector(combine(initialState$2
1952
2134
  eventBus.stopEmitting();
1953
2135
  await tryCatch(connection.disconnect());
1954
2136
  eventBus.publish({ type: EVENT_LISTENER_METHODS.SessionStatusListener.onConnectionClosed }, true);
1955
- set(initialState$2);
2137
+ set(initialState$3);
1956
2138
  }
1957
2139
  },
1958
- reset: () => set(initialState$2)
2140
+ reset: () => set(initialState$3)
1959
2141
  }))));
2142
+ function waitForConnection() {
2143
+ const { connectionStatus } = useConnectionStore.getState();
2144
+ if (connectionStatus === "connected") return Promise.resolve();
2145
+ return new Promise((resolve, reject) => {
2146
+ const timeout = setTimeout(() => {
2147
+ unsub();
2148
+ reject(new Error("Connection timed out after 3 seconds"));
2149
+ }, 3e3);
2150
+ const unsub = useConnectionStore.subscribe((s) => s.connectionStatus, (status) => {
2151
+ if (status === "connected") {
2152
+ clearTimeout(timeout);
2153
+ unsub();
2154
+ resolve();
2155
+ } else if (status === "error") {
2156
+ clearTimeout(timeout);
2157
+ unsub();
2158
+ reject(useConnectionStore.getState().error);
2159
+ }
2160
+ });
2161
+ });
2162
+ }
2163
+
2164
+ //#endregion
2165
+ //#region calls-sdk-core/store/toast.ts
2166
+ const MAX_TOASTS = 3;
2167
+ const initialState$2 = { toasts: [] };
2168
+ let counter = 0;
2169
+ const useToastStore = create((set) => ({
2170
+ ...initialState$2,
2171
+ addToast: (toast) => {
2172
+ if (!getIsConferenceJoined()) {
2173
+ return "";
2174
+ }
2175
+ if (!useConfigStore.getState().enableNotifications) {
2176
+ return "";
2177
+ }
2178
+ const id = `toast-${++counter}-${Date.now()}`;
2179
+ const newToast = {
2180
+ ...toast,
2181
+ id,
2182
+ createdAt: Date.now()
2183
+ };
2184
+ set((state) => {
2185
+ const updated = [...state.toasts, newToast];
2186
+ if (updated.length > MAX_TOASTS) {
2187
+ return { toasts: updated.slice(-MAX_TOASTS) };
2188
+ }
2189
+ return { toasts: updated };
2190
+ });
2191
+ return id;
2192
+ },
2193
+ removeToast: (id) => {
2194
+ set((state) => ({ toasts: state.toasts.filter((t) => t.id !== id) }));
2195
+ },
2196
+ clearAll: () => {
2197
+ set(initialState$2);
2198
+ },
2199
+ reset: () => {
2200
+ set(initialState$2);
2201
+ }
2202
+ }));
2203
+ function showToast(params) {
2204
+ return useToastStore.getState().addToast({
2205
+ message: params.message,
2206
+ type: params.type ?? "info",
2207
+ duration: params.duration ?? 3e3,
2208
+ position: params.position ?? "bottom",
2209
+ action: params.action
2210
+ });
2211
+ }
1960
2212
 
1961
2213
  //#endregion
1962
2214
  //#region calls-sdk-core/store/utils/hooks.ts
1963
2215
  const useHideMuteAudioButton = () => {
1964
2216
  const hideMuteAudioButton = useConfigStore((state) => state.hideToggleAudioButton);
1965
- return hideMuteAudioButton;
2217
+ const enableCompanionMode = useConfigStore((state) => state.enableCompanionMode);
2218
+ return hideMuteAudioButton || enableCompanionMode;
1966
2219
  };
1967
2220
  const useHideToggleVideoButton = () => {
1968
2221
  const hideToggleVideoButton = useConfigStore((state) => state.hideToggleVideoButton);
@@ -1984,7 +2237,7 @@ const useHideScreenSharingButton = () => {
1984
2237
  const useHideSwitchCameraButton = () => {
1985
2238
  const videoTrack = getLocalTrack(MEDIA_TYPE.VIDEO);
1986
2239
  const hideSwitchCameraButton = useConfigStore((state) => state.hideSwitchCameraButton);
1987
- return hideSwitchCameraButton || !videoTrack;
2240
+ return hideSwitchCameraButton || !videoTrack?.originalTrack;
1988
2241
  };
1989
2242
  const useHideChatButton = () => {
1990
2243
  const hideChatButton = useConfigStore((state) => state.hideChatButton);
@@ -2029,8 +2282,21 @@ const getMainParticipant = () => {
2029
2282
  const useIsReconnecting = () => {
2030
2283
  const connectionStatus = useConnectionStore((state) => state.connectionStatus);
2031
2284
  const conferenceStatus = useConferenceStore((state) => state.conferenceStatus);
2032
- const reconnecting = connectionStatus === "connected" && conferenceStatus === "interrupted";
2033
- return reconnecting;
2285
+ const isP2P = useConferenceStore((state) => state.p2p);
2286
+ const [isOnline, setIsOnline] = useState(true);
2287
+ useEffect(() => {
2288
+ if (typeof window === "undefined") return;
2289
+ const controller = new AbortController();
2290
+ const { signal } = controller;
2291
+ window.addEventListener("online", () => setIsOnline(true), { signal });
2292
+ window.addEventListener("offline", () => setIsOnline(false), { signal });
2293
+ return () => controller.abort();
2294
+ }, []);
2295
+ const interrupted = connectionStatus === "connected" && conferenceStatus === "interrupted";
2296
+ if (isP2P && interrupted && isOnline) {
2297
+ return false;
2298
+ }
2299
+ return interrupted;
2034
2300
  };
2035
2301
  const useHideRecordingButton = () => {
2036
2302
  const hideRecordingButton = useConfigStore((state) => state.hideRecordingButton);
@@ -2108,6 +2374,11 @@ const useIsVideoInputSelectionSupported = () => {
2108
2374
  const isVideoInputSelectionSupported = hasVideoPermission && videoInputDevices.length > 0;
2109
2375
  return isVideoInputSelectionSupported;
2110
2376
  };
2377
+ const useShouldMirrorLocalVideo = () => {
2378
+ const mirrorLocalVideo = useBaseStore((state) => state.mirrorLocalVideo);
2379
+ const cameraFacing = useBaseStore((state) => state.cameraFacing);
2380
+ return cameraFacing === "user" && mirrorLocalVideo;
2381
+ };
2111
2382
 
2112
2383
  //#endregion
2113
2384
  //#region calls-sdk-core/store/utils/switch-camera.ts
@@ -2156,8 +2427,10 @@ function setReceiverConstraintsInternal() {
2156
2427
  }
2157
2428
  });
2158
2429
  } else if (layout$1 === "SIDEBAR") {
2159
- const participants = useParticipantStore.getState().participants;
2160
- participants.forEach((participant) => {
2430
+ const { startIndex, endIndex } = useBaseStore.getState().sidebarVisibleParticipants;
2431
+ const allParticipants = getAllParticipants();
2432
+ const visibleSidebarParticipants = allParticipants.slice(startIndex, endIndex);
2433
+ visibleSidebarParticipants.forEach((participant) => {
2161
2434
  const videoSources$1 = participant.sources?.get("video");
2162
2435
  if (videoSources$1) {
2163
2436
  Array.from(videoSources$1.keys()).forEach((source) => {
@@ -2183,6 +2456,9 @@ const setReceiverConstraints = debounce(setReceiverConstraintsInternal, 200);
2183
2456
  useBaseStore.subscribe((state) => state.visibleParticipants, () => {
2184
2457
  setReceiverConstraints();
2185
2458
  });
2459
+ useBaseStore.subscribe((state) => state.sidebarVisibleParticipants, () => {
2460
+ setReceiverConstraints();
2461
+ });
2186
2462
  useBaseStore.subscribe((state) => state.layout, () => {
2187
2463
  setReceiverConstraints();
2188
2464
  });
@@ -2280,8 +2556,12 @@ var ConferenceListener = class {
2280
2556
  track.removeAllListeners(JitsiMeetJS.events.track.NO_DATA_FROM_SOURCE);
2281
2557
  }
2282
2558
  onConferenceJoinInProgress() {}
2283
- onConferenceFailed(_conference, error, message) {
2284
- console.error("Conference failed:", error, message);
2559
+ onConferenceFailed(errorName, error, message) {
2560
+ if (errorName === JitsiMeetJS.errors.conference.CONFERENCE_DESTROYED) {
2561
+ leaveSession({ forceLeave: true });
2562
+ return;
2563
+ }
2564
+ console.error("Conference failed:", errorName, error, message);
2285
2565
  useConferenceStore.setState({
2286
2566
  conferenceStatus: "error",
2287
2567
  conferenceJoined: false,
@@ -2316,6 +2596,7 @@ var ConferenceListener = class {
2316
2596
  }
2317
2597
  onConnectionEstablished() {
2318
2598
  useConferenceStore.setState({ conferenceStatus: "joined" });
2599
+ setTimeout(setReceiverConstraints, 500);
2319
2600
  }
2320
2601
  onConnectionInterrupted() {
2321
2602
  useConferenceStore.setState({ conferenceStatus: "interrupted" });
@@ -2327,17 +2608,19 @@ var ConferenceListener = class {
2327
2608
  useConferenceStore.setState({ p2p });
2328
2609
  }
2329
2610
  onTrackMuteChanged(track, participantThatMutedUs) {
2330
- if (participantThatMutedUs) {
2331
- useTracksStore.getState().updateTrack(track, { muted: track.isMuted() ? 1 : 0 });
2332
- const displayName = participantThatMutedUs.getDisplayName();
2333
- if (displayName) {
2334
- eventBus.publish({
2335
- type: INTERNAL_EVENTS.notification,
2336
- payload: {
2337
- type: "info",
2338
- message: `${displayName} has muted you.`
2339
- }
2340
- });
2611
+ if (track.isLocal()) {
2612
+ useTracksStore.getState().updateLocalTrack(track.getType(), { muted: track.isMuted() ? 1 : 0 });
2613
+ if (participantThatMutedUs) {
2614
+ const displayName = participantThatMutedUs.getDisplayName();
2615
+ if (displayName) {
2616
+ eventBus.publish({
2617
+ type: INTERNAL_EVENTS.notification,
2618
+ payload: {
2619
+ type: "info",
2620
+ message: `${displayName} has muted you.`
2621
+ }
2622
+ });
2623
+ }
2341
2624
  }
2342
2625
  }
2343
2626
  }
@@ -2392,6 +2675,24 @@ var ConferenceListener = class {
2392
2675
  useParticipantStore.getState().updateParticipant(participantId, { role: newRole });
2393
2676
  }
2394
2677
  }
2678
+ onTrackUnmuteRejected(track) {
2679
+ if (!track.isLocal()) {
2680
+ return;
2681
+ }
2682
+ const mediaType = track.getType();
2683
+ track.dispose().catch(() => {});
2684
+ useTracksStore.getState().updateLocalTrack(mediaType, {
2685
+ originalTrack: undefined,
2686
+ muted: 1
2687
+ });
2688
+ eventBus.publish({
2689
+ type: INTERNAL_EVENTS.notification,
2690
+ payload: {
2691
+ type: "info",
2692
+ message: `Your ${mediaType} unmute was rejected.`
2693
+ }
2694
+ });
2695
+ }
2395
2696
  onTalkWhileMuted() {}
2396
2697
  onConferenceError(error) {
2397
2698
  console.error("Conference error:", error);
@@ -2470,6 +2771,7 @@ function addConferenceListeners(conference) {
2470
2771
  conference.on(JitsiMeetJS.events.conference.PARTICIPANT_PROPERTY_CHANGED, conferenceListener.onParticipantPropertyChanged);
2471
2772
  conference.on(JitsiMeetJS.events.conference.USER_ROLE_CHANGED, conferenceListener.onUserRoleChanged);
2472
2773
  conference.on(JitsiMeetJS.events.conference.TALK_WHILE_MUTED, conferenceListener.onTalkWhileMuted);
2774
+ conference.on(JitsiMeetJS.events.conference.TRACK_UNMUTE_REJECTED, conferenceListener.onTrackUnmuteRejected);
2473
2775
  conference.on(JitsiMeetJS.events.conference.TRACK_AUDIO_LEVEL_CHANGED, conferenceListener.onTrackAudioLevelChanged);
2474
2776
  conference.addCommandListener(CONFERENCE_COMMANDS.userInfo, (data, id) => {
2475
2777
  const vData = v.safeParse(UserInfoCommandSchema, safeParseJson(data.value));
@@ -2481,17 +2783,23 @@ function addConferenceListeners(conference) {
2481
2783
  }
2482
2784
  });
2483
2785
  }
2484
- async function createConference(connection, roomName) {
2786
+ async function _createConference() {
2787
+ const sessionId = useConfigStore.getState().sessionId;
2788
+ const connection = useConnectionStore.getState().connection;
2485
2789
  if (!connection) {
2486
2790
  throw new Error("No connection available");
2487
2791
  }
2792
+ const connectionStatus = useConnectionStore.getState().connectionStatus;
2793
+ if (connectionStatus !== "connected") {
2794
+ await waitForConnection();
2795
+ }
2488
2796
  const existingConference = useConferenceStore.getState().conference;
2489
2797
  if (existingConference) {
2490
2798
  console.log("Conference already exists, skipping creation");
2491
2799
  return;
2492
2800
  }
2493
2801
  const connectionConfig = useConnectionStore.getState().connectionConfig;
2494
- const conference = connection.initJitsiConference(roomName, connectionConfig);
2802
+ const conference = connection.initJitsiConference(sessionId, connectionConfig);
2495
2803
  const localAudioTrack = getLocalTrack(MEDIA_TYPE.AUDIO)?.originalTrack;
2496
2804
  const localVideoTrack = getLocalTrack(MEDIA_TYPE.VIDEO)?.originalTrack;
2497
2805
  if (localAudioTrack) {
@@ -2506,6 +2814,20 @@ async function createConference(connection, roomName) {
2506
2814
  conference.setDisplayName(useParticipantStore.getState().localParticipant.name);
2507
2815
  conference.join();
2508
2816
  }
2817
+ async function createConference() {
2818
+ const conference = useConferenceStore.getState().conference;
2819
+ if (!conference) {
2820
+ const result = await tryCatch(_createConference());
2821
+ if (result.error) {
2822
+ console.error("Error creating conference", result.error);
2823
+ useConferenceStore.setState({
2824
+ conferenceStatus: "error",
2825
+ conferenceJoined: false,
2826
+ conferenceError: result.error.message
2827
+ });
2828
+ }
2829
+ }
2830
+ }
2509
2831
  function muteParticipant(participantId) {
2510
2832
  const conference = useConferenceStore.getState().conference;
2511
2833
  conference?.muteParticipant(participantId, "audio");
@@ -2517,7 +2839,12 @@ function pauseParticipantVideo(participantId) {
2517
2839
 
2518
2840
  //#endregion
2519
2841
  //#region calls-sdk-core/handlers/connection.ts
2520
- function connect(roomName) {
2842
+ async function connect(autoJoinConference = true) {
2843
+ const existingConnection = useConnectionStore.getState().connection;
2844
+ if (existingConnection) {
2845
+ createConference();
2846
+ return;
2847
+ }
2521
2848
  const options = useConnectionStore.getState().connectionConfig;
2522
2849
  const jwt = useConnectionStore.getState().jwt;
2523
2850
  const iAmRecorder = useConfigStore.getState().iAmRecorder;
@@ -2533,15 +2860,8 @@ function connect(roomName) {
2533
2860
  async function onConnectionEstablished() {
2534
2861
  useConnectionStore.getState().connectionEstablished(connection);
2535
2862
  eventBus.publish({ type: INTERNAL_EVENTS.onConnectionEstablished });
2536
- const result = await tryCatch(createConference(connection, roomName));
2537
- if (result.error) {
2538
- console.error("Error creating conference", result.error);
2539
- useConferenceStore.setState({
2540
- conferenceStatus: "error",
2541
- conferenceJoined: false,
2542
- conferenceError: result.error.message
2543
- });
2544
- }
2863
+ if (!autoJoinConference) return;
2864
+ createConference();
2545
2865
  }
2546
2866
  function onConnectionFailed(err, message, ...args) {
2547
2867
  unsubscribe();
@@ -2708,6 +3028,7 @@ function resetAllStores() {
2708
3028
  useConfigStore.getState().reset();
2709
3029
  useConnectionStore.getState().reset();
2710
3030
  useParticipantStore.getState().reset();
3031
+ useToastStore.getState().reset();
2711
3032
  useTracksStore.getState().reset();
2712
3033
  }
2713
3034
 
@@ -2739,6 +3060,7 @@ var Mutex = class {
2739
3060
  //#region calls-sdk-core/handlers/init.ts
2740
3061
  function initializeLib() {
2741
3062
  JitsiMeetJS.init();
3063
+ JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.ERROR);
2742
3064
  console.log("JitsiMeetJS initialized successfully.");
2743
3065
  }
2744
3066
 
@@ -2747,6 +3069,7 @@ function initializeLib() {
2747
3069
  let isSessionStarted = false;
2748
3070
  let reconnectTimeoutId = null;
2749
3071
  const RECONNECT_DEBOUNCE_DELAY = 3e3;
3072
+ initializeLib();
2750
3073
  function startSession() {
2751
3074
  const sessionId = useConfigStore.getState().sessionId;
2752
3075
  if (!sessionId) {
@@ -2759,29 +3082,13 @@ function startSession() {
2759
3082
  }
2760
3083
  isSessionStarted = true;
2761
3084
  console.log(`Session started in room: ${sessionId}`);
2762
- initializeLib();
2763
- const audioInputDeviceId = useConfigStore.getState().audioInputDeviceId ?? useBaseStore.getState().audioInputDevice?.deviceId;
2764
- createLocalTrack("audio", audioInputDeviceId);
2765
- const sessionType = useConfigStore.getState().sessionType;
2766
- if (sessionType === SESSION_TYPE.VIDEO) {
2767
- const videoInputDeviceIdP1 = useConfigStore.getState().videoInputDeviceId;
2768
- const videoInputDeviceIdP2 = useBaseStore.getState().videoInputDevice?.deviceId;
2769
- const initialCameraFacingP1 = useConfigStore.getState().initialCameraFacing;
2770
- const initialCameraFacingP2 = useBaseStore.getState().cameraFacing;
2771
- if (videoInputDeviceIdP1) {
2772
- createLocalTrack("video", videoInputDeviceIdP1);
2773
- } else if (initialCameraFacingP1) {
2774
- createLocalTrack("video", null, initialCameraFacingP2);
2775
- } else {
2776
- createLocalTrack("video", videoInputDeviceIdP2, initialCameraFacingP2);
2777
- }
2778
- }
3085
+ createLocalTracks();
2779
3086
  const audioOutputDeviceId = useConfigStore.getState().audioOutputDeviceId ?? useBaseStore.getState().audioOutputDevice?.deviceId;
2780
3087
  if (audioOutputDeviceId) {
2781
3088
  updateAudioOutputDevice(audioOutputDeviceId);
2782
3089
  }
2783
3090
  eventBus.startEmitting();
2784
- const test = tryCatchSync(() => connect(sessionId));
3091
+ const test = tryCatchSync(() => connect());
2785
3092
  if (test.error) {
2786
3093
  console.error("Error connecting to session:", test.error);
2787
3094
  useConnectionStore.getState().connectionFailed(test.error.message);
@@ -2798,8 +3105,14 @@ async function _leaveSession() {
2798
3105
  await useConnectionStore.getState().disconnect();
2799
3106
  }
2800
3107
  const sessionMutex = new Mutex();
2801
- function leaveSession() {
3108
+ function leaveSession(options = {}) {
2802
3109
  return sessionMutex.run(async () => {
3110
+ const isPeerCall = useConfigStore.getState().isPeerCall;
3111
+ const shouldEnd = options.shouldEndSession || isPeerCall && !options.forceLeave;
3112
+ if (shouldEnd) {
3113
+ useConferenceStore.getState().endConference();
3114
+ return;
3115
+ }
2803
3116
  useBaseStore.getState().clearIdealTimeoutTimer();
2804
3117
  cancelPendingReconnect();
2805
3118
  await _leaveSession();
@@ -3267,6 +3580,10 @@ eventBus.subscribe(INTERNAL_EVENTS.lifecycle.componentDidMount, () => {
3267
3580
  });
3268
3581
  });
3269
3582
  useBaseStore.subscribe((state) => state.appState, (appState) => {
3583
+ const sessionType = useConfigStore.getState().sessionType;
3584
+ if (sessionType !== SESSION_TYPE.VIDEO) {
3585
+ return;
3586
+ }
3270
3587
  if (appState === "active") {
3271
3588
  resumeVideoTrack(VIDEO_PAUSE_AUTHORITY.BACKGROUND);
3272
3589
  } else {
@@ -3707,6 +4024,13 @@ const commonStyles = StyleSheet.create({
3707
4024
  borderDefault: { borderColor: colors.border.default },
3708
4025
  borderDark: { borderColor: colors.border.dark },
3709
4026
  borderHighlight: { borderColor: colors.border.highlight },
4027
+ absoluteFill: {
4028
+ position: "absolute",
4029
+ top: 0,
4030
+ bottom: 0,
4031
+ left: 0,
4032
+ right: 0
4033
+ },
3710
4034
  flex1: { flex: 1 },
3711
4035
  flexRow: { flexDirection: "row" },
3712
4036
  flexColumn: { flexDirection: "column" },
@@ -3896,10 +4220,16 @@ const PopupMenu = ({ visible, onClose, options, anchorLayout }) => {
3896
4220
  return /* @__PURE__ */ jsx(Modal, {
3897
4221
  transparent: true,
3898
4222
  animationType: "none",
4223
+ supportedOrientations: [
4224
+ "portrait",
4225
+ "landscape-left",
4226
+ "landscape-right"
4227
+ ],
3899
4228
  onRequestClose: onClose,
3900
4229
  children: /* @__PURE__ */ jsx(Pressable, {
3901
4230
  style: styles$27.backdrop,
3902
4231
  onPress: onClose,
4232
+ testID: "cometchat-popup-menu-backdrop",
3903
4233
  children: /* @__PURE__ */ jsx(Animated.View, {
3904
4234
  style: [styles$27.menu, {
3905
4235
  [isBelowMiddle ? "bottom" : "top"]: isBelowMiddle ? callContainerDimension.height - (y - 4) : y + height + 4,
@@ -3920,6 +4250,7 @@ const PopupMenu = ({ visible, onClose, options, anchorLayout }) => {
3920
4250
  },
3921
4251
  activeOpacity: option.selected ? DISABLED_OPTION_OPACITY : .2,
3922
4252
  style: [styles$27.menuItem, option.selected ? styles$27.menuItemSelected : {}],
4253
+ testID: `cometchat-popup-menu-option-${index}`,
3923
4254
  children: [option.iconName && /* @__PURE__ */ jsx(Icon_native_default, {
3924
4255
  name: option.iconName,
3925
4256
  size: 24,
@@ -4081,6 +4412,7 @@ const MoreOptionButton = ({ ruid }) => {
4081
4412
  ref: buttonRef,
4082
4413
  style: styles$4.moreButton,
4083
4414
  onPress: showMenu,
4415
+ testID: "cometchat-participant-more-options-button",
4084
4416
  children: /* @__PURE__ */ jsx(Icon_native_default, {
4085
4417
  name: "more",
4086
4418
  size: 20,
@@ -4220,7 +4552,11 @@ const VideoNative = ({ videoTrack, style, objectFit = "cover", mirror = false, m
4220
4552
  return null;
4221
4553
  }
4222
4554
  return /* @__PURE__ */ jsx(Animated.View, {
4223
- style: [styles$25.videoContainer, { opacity: fadeAnim }],
4555
+ style: [
4556
+ commonStyles.absoluteFill,
4557
+ styles$25.videoContainer,
4558
+ { opacity: fadeAnim }
4559
+ ],
4224
4560
  children: /* @__PURE__ */ jsx(RTCView, {
4225
4561
  streamURL: streamURL.toURL(),
4226
4562
  style: [styles$25.video, style],
@@ -4233,8 +4569,7 @@ const VideoNative = ({ videoTrack, style, objectFit = "cover", mirror = false, m
4233
4569
  const styles$25 = StyleSheet.create({
4234
4570
  videoContainer: {
4235
4571
  height: "100%",
4236
- width: "100%",
4237
- ...StyleSheet.absoluteFillObject
4572
+ width: "100%"
4238
4573
  },
4239
4574
  video: {
4240
4575
  width: "100%",
@@ -4250,6 +4585,7 @@ const Tile = ({ participant, style, zOrder, showLabel = true, disablePress = fal
4250
4585
  const videoTrack = useTrackByParticipantId(pid, type === "screen-share" ? MEDIA_TYPE.SCREENSHARE : MEDIA_TYPE.VIDEO)?.originalTrack;
4251
4586
  const videoMuted = useTrackMuted(type === "screen-share" ? MEDIA_TYPE.SCREENSHARE : MEDIA_TYPE.VIDEO, pid);
4252
4587
  const enableParticipantContextMenu = useEnableParticipantContextMenu();
4588
+ const shouldMirror = useShouldMirrorLocalVideo();
4253
4589
  const [size, fontSize] = React.useMemo(() => {
4254
4590
  const flatStyle = StyleSheet.flatten(style);
4255
4591
  const width$1 = flatStyle?.width;
@@ -4267,6 +4603,7 @@ const Tile = ({ participant, style, zOrder, showLabel = true, disablePress = fal
4267
4603
  activeOpacity: 1,
4268
4604
  disabled: disablePress,
4269
4605
  style: [styles$24.callScreen, style],
4606
+ testID: `cometchat-tile-${pid}`,
4270
4607
  children: [
4271
4608
  /* @__PURE__ */ jsx(View, {
4272
4609
  style: styles$24.tileAvatar,
@@ -4282,7 +4619,7 @@ const Tile = ({ participant, style, zOrder, showLabel = true, disablePress = fal
4282
4619
  objectFit: type === "screen-share" ? "contain" : "cover",
4283
4620
  muted: videoMuted,
4284
4621
  zOrder,
4285
- mirror: isLocal
4622
+ mirror: isLocal && type !== "screen-share" && shouldMirror
4286
4623
  }),
4287
4624
  showLabel && /* @__PURE__ */ jsx(Label_native_default, { participant }),
4288
4625
  enableParticipantContextMenu && /* @__PURE__ */ jsx(View, {
@@ -4341,6 +4678,7 @@ const GroupAvatarTile = ({ startIndex = 4, style }) => {
4341
4678
  const overflowCount = Math.max(0, participantCount - startIndex - 3);
4342
4679
  const visible = participants.slice(startIndex, startIndex + (overflowCount === 1 ? 4 : 3));
4343
4680
  return /* @__PURE__ */ jsxs(TouchableOpacity, {
4681
+ testID: "cometchat-group-avatar-tile",
4344
4682
  style: [styles$23.container, style],
4345
4683
  onPress: toggleParticipantListVisible,
4346
4684
  children: [/* @__PURE__ */ jsx(View, {
@@ -4448,6 +4786,7 @@ function SidebarLayout() {
4448
4786
  const mainParticipant = useMainParticipant();
4449
4787
  const participants = allParticipants.length > 1 ? [mainParticipant].concat(allParticipants) : [mainParticipant];
4450
4788
  return /* @__PURE__ */ jsxs(View, {
4789
+ testID: "cometchat-sidebar-layout",
4451
4790
  style: styles$22.container,
4452
4791
  children: [
4453
4792
  /* @__PURE__ */ jsx(Tile_native_default, {
@@ -4584,23 +4923,26 @@ const Spotlight = () => {
4584
4923
  if (otherParticipant) {
4585
4924
  spotlightParticipants.push(otherParticipant);
4586
4925
  }
4587
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Tile_native_default, {
4588
- participant: spotlightParticipants[0],
4589
- disablePress: true
4590
- }, spotlightParticipants[0].ruid), spotlightParticipants[1] && /* @__PURE__ */ jsx(Pan, {
4591
- disableDrag: !enableSpotlightDrag,
4592
- layout: {
4593
- width: mainAreaDimension.width,
4594
- height: mainAreaDimension.height
4595
- },
4596
- children: /* @__PURE__ */ jsx(Tile_native_default, {
4597
- showLabel: false,
4598
- disablePress: !enableSpotlightSwap,
4599
- participant: spotlightParticipants[1],
4600
- style: styles$20.panTile,
4601
- zOrder: 1
4602
- }, spotlightParticipants[1].ruid)
4603
- })] });
4926
+ return /* @__PURE__ */ jsxs(View, {
4927
+ testID: "cometchat-spotlight-layout",
4928
+ children: [/* @__PURE__ */ jsx(Tile_native_default, {
4929
+ participant: spotlightParticipants[0],
4930
+ disablePress: true
4931
+ }, spotlightParticipants[0].ruid), spotlightParticipants[1] && /* @__PURE__ */ jsx(Pan, {
4932
+ disableDrag: !enableSpotlightDrag,
4933
+ layout: {
4934
+ width: mainAreaDimension.width,
4935
+ height: mainAreaDimension.height
4936
+ },
4937
+ children: /* @__PURE__ */ jsx(Tile_native_default, {
4938
+ showLabel: false,
4939
+ disablePress: !enableSpotlightSwap,
4940
+ participant: spotlightParticipants[1],
4941
+ style: styles$20.panTile,
4942
+ zOrder: 1
4943
+ }, spotlightParticipants[1].ruid)
4944
+ })]
4945
+ });
4604
4946
  };
4605
4947
  const styles$20 = StyleSheet.create({ panTile: {
4606
4948
  borderColor: "#1A1A1A",
@@ -4633,6 +4975,7 @@ function TileLayout() {
4633
4975
  participantCount: isPIPLayoutEnabled ? 1 : participants.length
4634
4976
  });
4635
4977
  return /* @__PURE__ */ jsx(FlatList, {
4978
+ testID: "cometchat-tile-layout",
4636
4979
  data: isPIPLayoutEnabled ? [mainParticipant] : participants,
4637
4980
  renderItem: ({ item }) => /* @__PURE__ */ jsx(Tile_native_default, {
4638
4981
  participant: item,
@@ -4700,7 +5043,11 @@ function ProcessingOverlay({ message, visible = true, animated = false }) {
4700
5043
  return null;
4701
5044
  }
4702
5045
  return /* @__PURE__ */ jsxs(Animated.View, {
4703
- style: [styles$18.overlay, { opacity }],
5046
+ style: [
5047
+ commonStyles.absoluteFill,
5048
+ styles$18.overlay,
5049
+ { opacity }
5050
+ ],
4704
5051
  children: [/* @__PURE__ */ jsx(ActivityIndicator, {
4705
5052
  size: "large",
4706
5053
  color: "#fff"
@@ -4712,7 +5059,6 @@ function ProcessingOverlay({ message, visible = true, animated = false }) {
4712
5059
  }
4713
5060
  const styles$18 = StyleSheet.create({
4714
5061
  overlay: {
4715
- ...StyleSheet.absoluteFillObject,
4716
5062
  justifyContent: "center",
4717
5063
  alignItems: "center",
4718
5064
  backgroundColor: "#1A1A1A",
@@ -4890,7 +5236,6 @@ function showConfirmationDialog(title, description, confirmText, cancelText, onC
4890
5236
  const { width } = Dimensions.get("window");
4891
5237
  const styles$15 = StyleSheet.create({
4892
5238
  backdrop: {
4893
- ...StyleSheet.absoluteFillObject,
4894
5239
  backgroundColor: "rgba(0, 0, 0, 0.8)",
4895
5240
  justifyContent: "center",
4896
5241
  alignItems: "center",
@@ -4982,10 +5327,16 @@ function ConfirmationDialog() {
4982
5327
  visible,
4983
5328
  transparent: true,
4984
5329
  animationType: "fade",
5330
+ supportedOrientations: [
5331
+ "portrait",
5332
+ "landscape-left",
5333
+ "landscape-right"
5334
+ ],
4985
5335
  onRequestClose: handleBackdropPress,
4986
5336
  children: /* @__PURE__ */ jsx(Pressable, {
4987
- style: styles$15.backdrop,
5337
+ style: [commonStyles.absoluteFill, styles$15.backdrop],
4988
5338
  onPress: handleBackdropPress,
5339
+ testID: "cometchat-confirmation-dialog-backdrop",
4989
5340
  children: /* @__PURE__ */ jsx(View, {
4990
5341
  style: styles$15.dialog,
4991
5342
  children: /* @__PURE__ */ jsxs(View, {
@@ -5028,7 +5379,7 @@ function ConfirmationDialog() {
5028
5379
  //#endregion
5029
5380
  //#region src/ui/bottom-sheet/BottomSheet.native.tsx
5030
5381
  const SCREEN_HEIGHT = Dimensions.get("window").height;
5031
- const BottomSheet = ({ children, isVisible, onClose, maxHeight = SCREEN_HEIGHT * .4 }) => {
5382
+ const BottomSheet = ({ children, isVisible, onClose, maxHeight = SCREEN_HEIGHT * .4, testID }) => {
5032
5383
  const visibleTranslateY = SCREEN_HEIGHT - maxHeight;
5033
5384
  const hiddenTranslateY = useRef(SCREEN_HEIGHT).current;
5034
5385
  const animatedValue = useRef(new Animated.Value(hiddenTranslateY)).current;
@@ -5054,8 +5405,10 @@ const BottomSheet = ({ children, isVisible, onClose, maxHeight = SCREEN_HEIGHT *
5054
5405
  const bottomSheetAnimation = { transform: [{ translateY: animatedValue }] };
5055
5406
  return /* @__PURE__ */ jsxs(Fragment, { children: [isVisible && /* @__PURE__ */ jsx(TouchableWithoutFeedback, {
5056
5407
  onPress: onClose,
5057
- children: /* @__PURE__ */ jsx(View, { style: styles$14.backdrop })
5408
+ testID: "cometchat-bottom-sheet-backdrop",
5409
+ children: /* @__PURE__ */ jsx(View, { style: [commonStyles.absoluteFill, styles$14.backdrop] })
5058
5410
  }), /* @__PURE__ */ jsxs(Animated.View, {
5411
+ testID,
5059
5412
  style: [
5060
5413
  styles$14.bottomSheet,
5061
5414
  bottomSheetAnimation,
@@ -5069,7 +5422,6 @@ const BottomSheet = ({ children, isVisible, onClose, maxHeight = SCREEN_HEIGHT *
5069
5422
  };
5070
5423
  const styles$14 = StyleSheet.create({
5071
5424
  backdrop: {
5072
- ...StyleSheet.absoluteFillObject,
5073
5425
  backgroundColor: "rgba(0,0,0,0.5)",
5074
5426
  zIndex: 1
5075
5427
  },
@@ -5113,8 +5465,9 @@ var BottomSheet_native_default = BottomSheet;
5113
5465
 
5114
5466
  //#endregion
5115
5467
  //#region src/ui/control-pane/MenuItem.native.tsx
5116
- const MenuItem = ({ iconName, label, onPress, selected = false }) => {
5468
+ const MenuItem = ({ iconName, label, onPress, selected = false, testID }) => {
5117
5469
  return /* @__PURE__ */ jsxs(TouchableOpacity, {
5470
+ testID,
5118
5471
  onPress: () => {
5119
5472
  hideAllBottomSheets();
5120
5473
  onPress();
@@ -5167,6 +5520,7 @@ const AudioModesMenu = ({ isVisible, onClose }) => {
5167
5520
  style: [commonStyles.bodyRegular, styles$12.noItemsText],
5168
5521
  children: "No audio modes available"
5169
5522
  }), audioModes.map((mode, index) => /* @__PURE__ */ jsx(MenuItem_native_default, {
5523
+ testID: `cometchat-menu-item-audio-${mode.type.toLowerCase()}`,
5170
5524
  iconName: AUDIO_MODE_TYPE_ICON_MAP[mode.type],
5171
5525
  label: mode.type,
5172
5526
  selected: mode.selected,
@@ -5218,6 +5572,7 @@ const AudioModeButton = () => {
5218
5572
  style: controlPaneStyles.controlButton,
5219
5573
  onPress: toggleAudioModeMenuVisible,
5220
5574
  activeOpacity: .7,
5575
+ testID: "cometchat-audio-mode-button",
5221
5576
  children: /* @__PURE__ */ jsx(Icon_native_default, {
5222
5577
  name: "speaker-fill",
5223
5578
  fill: "#FFF",
@@ -5243,6 +5598,7 @@ const AudioControl = () => {
5243
5598
  style: [controlPaneStyles.controlButton, muted && controlPaneStyles.toggledButton],
5244
5599
  onPress,
5245
5600
  activeOpacity: .7,
5601
+ testID: "cometchat-audio-toggle-button",
5246
5602
  children: /* @__PURE__ */ jsx(Icon_native_default, {
5247
5603
  name: muted ? "mic-off-fill" : "mic-fill",
5248
5604
  fill: muted ? "#9F3032" : "#FFF",
@@ -5268,6 +5624,7 @@ const VideoControl = () => {
5268
5624
  style: [controlPaneStyles.controlButton, videoMuted && controlPaneStyles.toggledButton],
5269
5625
  onPress,
5270
5626
  activeOpacity: .7,
5627
+ testID: "cometchat-video-toggle-button",
5271
5628
  children: /* @__PURE__ */ jsx(Icon_native_default, {
5272
5629
  name: videoMuted ? "video-off-fill" : "video-fill",
5273
5630
  fill: videoMuted ? "#9F3032" : "#FFF",
@@ -5292,6 +5649,7 @@ const LeaveSessionButton = () => {
5292
5649
  style: [controlPaneStyles.controlButton, controlPaneStyles.leaveSessionButton],
5293
5650
  onPress,
5294
5651
  activeOpacity: .7,
5652
+ testID: "cometchat-leave-session-button",
5295
5653
  children: /* @__PURE__ */ jsx(Icon_native_default, {
5296
5654
  name: "call-end",
5297
5655
  fill: "#FFF",
@@ -5308,6 +5666,7 @@ const MoreMenuButton = () => {
5308
5666
  style: controlPaneStyles.controlButton,
5309
5667
  onPress: toggleMoreMenuVisible,
5310
5668
  activeOpacity: .7,
5669
+ testID: "cometchat-more-menu-button",
5311
5670
  children: /* @__PURE__ */ jsx(Icon_native_default, {
5312
5671
  name: "more",
5313
5672
  fill: "#FFF",
@@ -5383,22 +5742,26 @@ const MoreMenu = ({ isVisible, onClose }) => {
5383
5742
  toggleParticipantListVisible();
5384
5743
  }, []);
5385
5744
  return /* @__PURE__ */ jsx(BottomSheet_native_default, {
5745
+ testID: "cometchat-more-menu-bottom-sheet",
5386
5746
  maxHeight: bottomSheetMaxHeight,
5387
5747
  isVisible,
5388
5748
  onClose,
5389
5749
  children: /* @__PURE__ */ jsxs(ScrollView, { children: [
5390
5750
  numberOfVisibleItems === 0 && /* @__PURE__ */ jsx(Text, {
5751
+ testID: "cometchat-more-menu-empty-state",
5391
5752
  style: [commonStyles.bodyRegular, styles$11.noItemsText],
5392
5753
  children: "No options available"
5393
5754
  }),
5394
5755
  !hideScreenSharingButton && /* @__PURE__ */ jsx(ScreenShareButton_default, {}),
5395
5756
  !hideRaiseHandButton && /* @__PURE__ */ jsx(MenuItem_native_default, {
5757
+ testID: "cometchat-menu-item-raise-hand",
5396
5758
  iconName: "raise-hand-fill",
5397
5759
  label: raiseHandTimestamp ? "Lower Hand" : "Raise Hand",
5398
5760
  onPress: onRaiseHandPress,
5399
5761
  selected: Boolean(raiseHandTimestamp)
5400
5762
  }),
5401
5763
  !hideRecordingButton && /* @__PURE__ */ jsx(MenuItem_native_default, {
5764
+ testID: isRecording ? "cometchat-menu-item-stop-recording" : "cometchat-menu-item-start-recording",
5402
5765
  iconName: isRecording ? "record-stop-fill" : "record-fill",
5403
5766
  label: isRecording ? "Stop Recording" : "Start Recording",
5404
5767
  onPress: () => {
@@ -5409,6 +5772,7 @@ const MoreMenu = ({ isVisible, onClose }) => {
5409
5772
  }
5410
5773
  }),
5411
5774
  !hideParticipantListButton && /* @__PURE__ */ jsx(MenuItem_native_default, {
5775
+ testID: "cometchat-menu-item-participants",
5412
5776
  iconName: "participants",
5413
5777
  label: "Participants",
5414
5778
  onPress: onParticipantListPress
@@ -5450,14 +5814,15 @@ const FullScreenDialog = ({ children, visible = false }) => {
5450
5814
  return null;
5451
5815
  }
5452
5816
  return /* @__PURE__ */ jsx(Animated.View, {
5453
- style: [styles$10.container, { opacity: fadeAnim }],
5817
+ style: [
5818
+ commonStyles.absoluteFill,
5819
+ styles$10.container,
5820
+ { opacity: fadeAnim }
5821
+ ],
5454
5822
  children
5455
5823
  });
5456
5824
  };
5457
- const styles$10 = StyleSheet.create({ container: {
5458
- ...StyleSheet.absoluteFillObject,
5459
- zIndex: 1e3
5460
- } });
5825
+ const styles$10 = StyleSheet.create({ container: { zIndex: 1e3 } });
5461
5826
  var FullScreenDialog_native_default = FullScreenDialog;
5462
5827
 
5463
5828
  //#endregion
@@ -5535,6 +5900,7 @@ const ChangeLayout = () => {
5535
5900
  eventBus.publish({ type: EVENT_LISTENER_METHODS.ButtonClickListener.onChangeLayoutButtonClicked });
5536
5901
  showMenu();
5537
5902
  },
5903
+ testID: "cometchat-change-layout-button",
5538
5904
  children: /* @__PURE__ */ jsx(Icon_native_default, {
5539
5905
  name: "tile-fill",
5540
5906
  fill: "#FFFFFF"
@@ -5587,6 +5953,7 @@ const ChatButton = () => {
5587
5953
  return /* @__PURE__ */ jsxs(TouchableOpacity, {
5588
5954
  style: [styles$9.iconButton],
5589
5955
  onPress,
5956
+ testID: "cometchat-chat-button",
5590
5957
  children: [/* @__PURE__ */ jsx(Icon_native_default, {
5591
5958
  name: "chat",
5592
5959
  fill: "#FFFFFF"
@@ -5643,6 +6010,7 @@ const SwitchCamera = () => {
5643
6010
  return null;
5644
6011
  }
5645
6012
  return /* @__PURE__ */ jsx(TouchableOpacity, {
6013
+ testID: "cometchat-switch-camera-button",
5646
6014
  disabled,
5647
6015
  style: [styles$8.iconButton, disabled && styles$8.iconButtonDisabled],
5648
6016
  onPress,
@@ -5675,6 +6043,7 @@ const SessionTimer = () => {
5675
6043
  return null;
5676
6044
  }
5677
6045
  return /* @__PURE__ */ jsx(Text, {
6046
+ testID: "cometchat-session-timer",
5678
6047
  style: [commonStyles.caption1Regular, styles$7.meetingTime],
5679
6048
  children: miliSecondsToMMSS(conferenceElapsedTime)
5680
6049
  });
@@ -5786,69 +6155,80 @@ const IdealTimeoutModal = ({ style = {} }) => {
5786
6155
  transparent: true,
5787
6156
  visible: idleTimeoutModalVisible,
5788
6157
  animationType: "none",
6158
+ supportedOrientations: [
6159
+ "portrait",
6160
+ "landscape-left",
6161
+ "landscape-right"
6162
+ ],
5789
6163
  statusBarTranslucent: true,
5790
6164
  children: /* @__PURE__ */ jsx(TouchableWithoutFeedback, {
5791
6165
  onPress: handleOverlayPress,
6166
+ testID: "cometchat-idle-timeout-overlay",
5792
6167
  children: /* @__PURE__ */ jsx(Animated.View, {
5793
6168
  style: [styles$6.overlay, { opacity: fadeAnim }],
5794
- children: /* @__PURE__ */ jsx(TouchableWithoutFeedback, { children: /* @__PURE__ */ jsx(Animated.View, {
5795
- style: [
5796
- styles$6.modal,
5797
- style,
5798
- {
5799
- opacity: fadeAnim,
5800
- transform: [{ scale: scaleAnim }]
5801
- }
5802
- ],
5803
- children: /* @__PURE__ */ jsxs(View, {
5804
- style: styles$6.content,
5805
- children: [
5806
- /* @__PURE__ */ jsx(View, {
5807
- style: styles$6.timerIcon,
5808
- children: /* @__PURE__ */ jsx(Text, {
5809
- style: [commonStyles.heading3Bold, styles$6.timerText],
5810
- children: formattedTime
5811
- })
5812
- }),
5813
- /* @__PURE__ */ jsxs(View, {
5814
- style: styles$6.textContent,
5815
- children: [/* @__PURE__ */ jsx(Text, {
5816
- style: [commonStyles.heading2Medium, styles$6.title],
5817
- children: "Are you still there?"
5818
- }), /* @__PURE__ */ jsxs(Text, {
5819
- style: [commonStyles.bodyRegular, styles$6.subtitle],
5820
- children: [
5821
- "You are the only one here, so this call will end in less than ",
5822
- ceilMinutes,
5823
- " minute",
5824
- ceilMinutes > 1 ? "s" : "",
5825
- ". Do you want to stay in this call?"
5826
- ]
5827
- })]
5828
- }),
5829
- /* @__PURE__ */ jsxs(View, {
5830
- style: styles$6.actions,
5831
- children: [/* @__PURE__ */ jsx(TouchableOpacity, {
5832
- style: [styles$6.button, styles$6.buttonSecondary],
5833
- onPress: onStayInCall,
5834
- activeOpacity: .8,
5835
- children: /* @__PURE__ */ jsx(Text, {
5836
- style: [commonStyles.bodyMedium, styles$6.buttonSecondaryText],
5837
- children: "Stay on the call"
5838
- })
5839
- }), /* @__PURE__ */ jsx(TouchableOpacity, {
5840
- style: [styles$6.button, styles$6.buttonPrimary],
5841
- onPress: leaveSession,
5842
- activeOpacity: .8,
6169
+ children: /* @__PURE__ */ jsx(TouchableWithoutFeedback, {
6170
+ testID: "cometchat-idle-timeout-modal",
6171
+ children: /* @__PURE__ */ jsx(Animated.View, {
6172
+ style: [
6173
+ styles$6.modal,
6174
+ style,
6175
+ {
6176
+ opacity: fadeAnim,
6177
+ transform: [{ scale: scaleAnim }]
6178
+ }
6179
+ ],
6180
+ children: /* @__PURE__ */ jsxs(View, {
6181
+ style: styles$6.content,
6182
+ children: [
6183
+ /* @__PURE__ */ jsx(View, {
6184
+ style: styles$6.timerIcon,
5843
6185
  children: /* @__PURE__ */ jsx(Text, {
5844
- style: [commonStyles.bodyMedium, styles$6.buttonPrimaryText],
5845
- children: "Leave now"
6186
+ style: [commonStyles.heading3Bold, styles$6.timerText],
6187
+ children: formattedTime
5846
6188
  })
5847
- })]
5848
- })
5849
- ]
6189
+ }),
6190
+ /* @__PURE__ */ jsxs(View, {
6191
+ style: styles$6.textContent,
6192
+ children: [/* @__PURE__ */ jsx(Text, {
6193
+ style: [commonStyles.heading2Medium, styles$6.title],
6194
+ children: "Are you still there?"
6195
+ }), /* @__PURE__ */ jsxs(Text, {
6196
+ style: [commonStyles.bodyRegular, styles$6.subtitle],
6197
+ children: [
6198
+ "You are the only one here, so this call will end in less than ",
6199
+ ceilMinutes,
6200
+ " minute",
6201
+ ceilMinutes > 1 ? "s" : "",
6202
+ ". Do you want to stay in this call?"
6203
+ ]
6204
+ })]
6205
+ }),
6206
+ /* @__PURE__ */ jsxs(View, {
6207
+ style: styles$6.actions,
6208
+ children: [/* @__PURE__ */ jsx(TouchableOpacity, {
6209
+ style: [styles$6.button, styles$6.buttonSecondary],
6210
+ onPress: onStayInCall,
6211
+ activeOpacity: .8,
6212
+ testID: "cometchat-idle-timeout-stay-button",
6213
+ children: /* @__PURE__ */ jsx(Text, {
6214
+ style: [commonStyles.bodyMedium, styles$6.buttonSecondaryText],
6215
+ children: "Stay on the call"
6216
+ })
6217
+ }), /* @__PURE__ */ jsx(TouchableOpacity, {
6218
+ style: [styles$6.button, styles$6.buttonPrimary],
6219
+ onPress: () => leaveSession(),
6220
+ activeOpacity: .8,
6221
+ testID: "cometchat-idle-timeout-leave-button",
6222
+ children: /* @__PURE__ */ jsx(Text, {
6223
+ style: [commonStyles.bodyMedium, styles$6.buttonPrimaryText],
6224
+ children: "Leave now"
6225
+ })
6226
+ })]
6227
+ })
6228
+ ]
6229
+ })
5850
6230
  })
5851
- }) })
6231
+ })
5852
6232
  })
5853
6233
  })
5854
6234
  });
@@ -5867,6 +6247,7 @@ const styles$6 = StyleSheet.create({
5867
6247
  borderWidth: 1,
5868
6248
  borderColor: "#383838",
5869
6249
  width: "100%",
6250
+ maxWidth: 372,
5870
6251
  paddingTop: 32,
5871
6252
  paddingHorizontal: 20,
5872
6253
  paddingBottom: 20,
@@ -5945,6 +6326,7 @@ const ShareInviteButton = () => {
5945
6326
  style: styles$5.shareButtonContainer,
5946
6327
  children: /* @__PURE__ */ jsxs(TouchableOpacity, {
5947
6328
  style: styles$5.shareButton,
6329
+ testID: "cometchat-share-invite-button",
5948
6330
  onPress: () => {
5949
6331
  eventBus.publish({ type: "onShareInviteButtonClicked" });
5950
6332
  },
@@ -6081,6 +6463,7 @@ const ParticipantList = () => {
6081
6463
  }), /* @__PURE__ */ jsx(TouchableOpacity, {
6082
6464
  onPress: toggleParticipantListVisible,
6083
6465
  accessibilityLabel: "Close participants list",
6466
+ testID: "cometchat-participant-list-close-button",
6084
6467
  children: /* @__PURE__ */ jsx(Icon_native_default, {
6085
6468
  name: "close",
6086
6469
  size: 24,
@@ -6102,7 +6485,8 @@ const ParticipantList = () => {
6102
6485
  style: styles$3.searchInput,
6103
6486
  value: searchTerm,
6104
6487
  onChangeText: setSearchTerm,
6105
- placeholderTextColor: "#858585"
6488
+ placeholderTextColor: "#858585",
6489
+ testID: "cometchat-participant-search-input"
6106
6490
  })]
6107
6491
  })
6108
6492
  }),
@@ -6243,45 +6627,6 @@ const styles$2 = StyleSheet.create({
6243
6627
  }
6244
6628
  });
6245
6629
 
6246
- //#endregion
6247
- //#region src/ui/toast/toast-state.ts
6248
- const MAX_TOASTS = 3;
6249
- let counter = 0;
6250
- const useToastStore = create((set) => ({
6251
- toasts: [],
6252
- addToast: (toast) => {
6253
- const id = `toast-${++counter}-${Date.now()}`;
6254
- const newToast = {
6255
- ...toast,
6256
- id,
6257
- createdAt: Date.now()
6258
- };
6259
- set((state) => {
6260
- const updated = [...state.toasts, newToast];
6261
- if (updated.length > MAX_TOASTS) {
6262
- return { toasts: updated.slice(-MAX_TOASTS) };
6263
- }
6264
- return { toasts: updated };
6265
- });
6266
- return id;
6267
- },
6268
- removeToast: (id) => {
6269
- set((state) => ({ toasts: state.toasts.filter((t) => t.id !== id) }));
6270
- },
6271
- clearAll: () => {
6272
- set({ toasts: [] });
6273
- }
6274
- }));
6275
- function showToast(params) {
6276
- return useToastStore.getState().addToast({
6277
- message: params.message,
6278
- type: params.type ?? "info",
6279
- duration: params.duration ?? 3e3,
6280
- position: params.position ?? "bottom",
6281
- action: params.action
6282
- });
6283
- }
6284
-
6285
6630
  //#endregion
6286
6631
  //#region src/ui/toast/Toast.native.tsx
6287
6632
  const SLIDE_IN_DURATION = 300;
@@ -6356,6 +6701,7 @@ function ToastItemView({ toast, onDismiss }) {
6356
6701
  }), toast.action && /* @__PURE__ */ jsx(Pressable, {
6357
6702
  style: styles$2.actionButton,
6358
6703
  onPress: handleActionPress,
6704
+ testID: "cometchat-toast-action-button",
6359
6705
  children: /* @__PURE__ */ jsx(Text, {
6360
6706
  style: styles$2.actionText,
6361
6707
  children: toast.action.label
@@ -6408,13 +6754,17 @@ function CallUI(props) {
6408
6754
  const isConferenceJoined = useIsConferenceJoined();
6409
6755
  useLayoutEffect(() => {
6410
6756
  eventBus.publish({ type: INTERNAL_EVENTS.lifecycle.componentDidMount });
6411
- updateConfig(props.callSettings);
6757
+ updateConfig(props.sessionSettings);
6412
6758
  return () => {
6413
6759
  eventBus.publish({ type: INTERNAL_EVENTS.lifecycle.componentWillUnmount }, true);
6414
6760
  };
6415
- }, [props.callSettings]);
6761
+ }, [props.sessionSettings]);
6416
6762
  useEffect(() => {
6417
- useBaseStore.setState({ sdkPlatform: Platform.OS });
6763
+ if (props.sessionSettings.sdkPlatform) {
6764
+ useBaseStore.setState({ sdkPlatform: props.sessionSettings.sdkPlatform });
6765
+ } else {
6766
+ useBaseStore.setState({ sdkPlatform: Platform.OS === "ios" ? "react-native-ios" : "react-native-android" });
6767
+ }
6418
6768
  startSession();
6419
6769
  }, []);
6420
6770
  useEffect(() => {
@@ -6429,13 +6779,13 @@ function CallUI(props) {
6429
6779
  useEffect(() => {
6430
6780
  if (Platform.OS === "android") {
6431
6781
  AudioModeModule_default.setMode(type === SESSION_TYPE.VOICE ? AudioModeModule_default.AUDIO_CALL : AudioModeModule_default.VIDEO_CALL);
6432
- if (props.callSettings.audioMode) {
6433
- AudioModeModule_default.setAudioDevice(props.callSettings.audioMode);
6782
+ if (props.sessionSettings.audioMode) {
6783
+ AudioModeModule_default.setAudioDevice(props.sessionSettings.audioMode);
6434
6784
  }
6435
6785
  } else if (Platform.OS === "ios") {
6436
6786
  AudioModeModule_default.updateDeviceList();
6437
6787
  }
6438
- }, [props.callSettings.audioMode, type]);
6788
+ }, [props.sessionSettings.audioMode, type]);
6439
6789
  if (isPIPLayoutEnabled) {
6440
6790
  return /* @__PURE__ */ jsx(PiPTile_default, {});
6441
6791
  }
@@ -6482,13 +6832,6 @@ const styles$1 = StyleSheet.create({
6482
6832
  alignItems: "center",
6483
6833
  gap: GRID_GAP,
6484
6834
  paddingHorizontal: 20
6485
- },
6486
- loadingContainer: {
6487
- ...StyleSheet.absoluteFillObject,
6488
- justifyContent: "center",
6489
- alignItems: "center",
6490
- backgroundColor: "#000",
6491
- zIndex: 1e3
6492
6835
  }
6493
6836
  });
6494
6837
  var index_native_default = CallUI;
@@ -6564,10 +6907,10 @@ const convertLegacyCallSettingsToV5Props = (callSettings) => {
6564
6907
  if (cs.defaultAudioMode === "BLUETOOTH" || cs.defaultAudioMode === "EARPIECE" || cs.defaultAudioMode === "HEADPHONES" || cs.defaultAudioMode === "SPEAKER") {
6565
6908
  v5Props.audioMode = cs.defaultAudioMode;
6566
6909
  }
6567
- if (cs.mode === "SPOTLIGHT") {
6568
- v5Props.layout = "SPOTLIGHT";
6569
- } else {
6570
- v5Props.layout = "SIDEBAR";
6910
+ if (typeof cs.layout === "string") {
6911
+ v5Props.layout = cs.layout;
6912
+ } else if (cs.mode === "SPOTLIGHT" || cs.mode === "SIDEBAR") {
6913
+ v5Props.layout = cs.mode;
6571
6914
  }
6572
6915
  if (cs.idleTimeoutPeriod) {
6573
6916
  v5Props.idleTimeoutPeriodAfterPrompt = 6e4;
@@ -6727,10 +7070,11 @@ async function callVerifyTokenAPI({ appId, region, calltoken, baseURL }) {
6727
7070
  }
6728
7071
 
6729
7072
  //#endregion
6730
- //#region src/AppRN.tsx
6731
- function App(props) {
7073
+ //#region src/AppReactNativeSDK.tsx
7074
+ function AppReactNativeSDK(props) {
6732
7075
  const [internalSettings, setInternalSettings] = React.useState(null);
6733
7076
  const [infoMessage, setInfoMessage] = React.useState(null);
7077
+ const sessionSettings = props.sessionSettings ?? props.callSettings ?? {};
6734
7078
  useEffect(() => {
6735
7079
  return eventBus.subscribe("onConnectionClosed", () => {
6736
7080
  setTimeout(() => {
@@ -6740,7 +7084,7 @@ function App(props) {
6740
7084
  }, []);
6741
7085
  useEffect(() => {
6742
7086
  const listeners = [];
6743
- const cs = props.callSettings ?? {};
7087
+ const cs = sessionSettings ?? {};
6744
7088
  if (cs.listener?.onUserJoined) {
6745
7089
  listeners.push(CometChatCalls.addEventListener("onParticipantJoined", cs.listener.onUserJoined));
6746
7090
  }
@@ -6778,7 +7122,7 @@ function App(props) {
6778
7122
  listener();
6779
7123
  });
6780
7124
  };
6781
- }, [props.callSettings]);
7125
+ }, [sessionSettings]);
6782
7126
  useEffect(() => {
6783
7127
  callVerifyTokenAPI({
6784
7128
  appId: CometChatCalls.appSettings?.appId || "",
@@ -6807,14 +7151,12 @@ function App(props) {
6807
7151
  visible: true
6808
7152
  });
6809
7153
  }
6810
- return /* @__PURE__ */ jsx(index_native_default, { callSettings: {
6811
- ...props.callSettings,
6812
- ...convertLegacyCallSettingsToV5Props(props?.callSettings ?? {}),
7154
+ return /* @__PURE__ */ jsx(index_native_default, { sessionSettings: {
7155
+ ...sessionSettings,
7156
+ ...convertLegacyCallSettingsToV5Props(sessionSettings ?? {}),
6813
7157
  internalSettings
6814
7158
  } });
6815
7159
  }
6816
- var AppRN_default = App;
6817
- const AppComponent = App;
6818
7160
 
6819
7161
  //#endregion
6820
7162
  //#region src/v4/Constants.ts
@@ -10547,7 +10889,13 @@ var CometChatCalls = class extends SessionMethodsCore {
10547
10889
  static OngoingCallListener = OngoingCallListener;
10548
10890
  static CallSettingsBuilder = CallSettingsBuilder;
10549
10891
  static CallAppSettingsBuilder = CallAppSettingsBuilder;
10550
- static Component = AppComponent;
10892
+ static Component = AppReactNativeSDK;
10893
+ /**
10894
+ * Initializes the CometChat Calls SDK with the provided app settings.
10895
+ * Must be called before any other SDK methods.
10896
+ * @param appSettings - The application settings for configuring the SDK.
10897
+ * @returns An object indicating success or failure with error details.
10898
+ */
10551
10899
  static async init(appSettings) {
10552
10900
  const parsedAppSettings = v.safeParse(CallAppSettingsSchema, appSettings);
10553
10901
  if (!parsedAppSettings.success) {
@@ -10563,7 +10911,7 @@ var CometChatCalls = class extends SessionMethodsCore {
10563
10911
  }
10564
10912
  this.appSettings = parsedAppSettings.output;
10565
10913
  this.isInitialized = true;
10566
- const savedUser = this.getSavedUser();
10914
+ const savedUser = await this.getSavedUser();
10567
10915
  if (savedUser) {
10568
10916
  let parsedUser;
10569
10917
  if (typeof savedUser === "string") {
@@ -10582,6 +10930,14 @@ var CometChatCalls = class extends SessionMethodsCore {
10582
10930
  error: null
10583
10931
  };
10584
10932
  }
10933
+ /**
10934
+ * Logs in a user with their UID and an optional auth key.
10935
+ * If no auth key is provided, the one from app settings is used.
10936
+ * @param uid - The unique identifier of the user.
10937
+ * @param authKey - The authentication key. Falls back to the key provided in app settings.
10938
+ * @returns A Promise that resolves to the logged-in User object.
10939
+ * @throws {CometChatException} If login fails or validation errors occur.
10940
+ */
10585
10941
  static async login(uid, authKey) {
10586
10942
  try {
10587
10943
  if (this.loginInProgress) {
@@ -10624,12 +10980,11 @@ var CometChatCalls = class extends SessionMethodsCore {
10624
10980
  if (this.loggedInUser && this.loggedInUser.uid !== uid) {
10625
10981
  await this.logoutInternal();
10626
10982
  }
10627
- console.log("Logging in user with UID:", uid);
10628
10983
  const authToken = await this.loginWithUID(uid, resolvedAuthKey);
10629
10984
  const user = await this.authenticateWithToken(authToken);
10630
10985
  this.loginInProgress = false;
10631
10986
  this.loggedInUser = user;
10632
- this.saveUser(user);
10987
+ await this.saveUser(user);
10633
10988
  this.notifyLoginSuccess(user);
10634
10989
  return user;
10635
10990
  } catch (error) {
@@ -10639,6 +10994,12 @@ var CometChatCalls = class extends SessionMethodsCore {
10639
10994
  throw cometChatError;
10640
10995
  }
10641
10996
  }
10997
+ /**
10998
+ * Logs in a user directly with an auth token.
10999
+ * @param authToken - The authentication token for the user.
11000
+ * @returns A Promise that resolves to the logged-in User object.
11001
+ * @throws {CometChatException} If login fails or the token is invalid.
11002
+ */
10642
11003
  static async loginWithAuthToken(authToken) {
10643
11004
  try {
10644
11005
  if (this.loginInProgress) {
@@ -10671,7 +11032,7 @@ var CometChatCalls = class extends SessionMethodsCore {
10671
11032
  const user = await this.authenticateWithToken(authToken);
10672
11033
  this.loginInProgress = false;
10673
11034
  this.loggedInUser = user;
10674
- this.saveUser(user);
11035
+ await this.saveUser(user);
10675
11036
  this.notifyLoginSuccess(user);
10676
11037
  return user;
10677
11038
  } catch (error) {
@@ -10681,6 +11042,11 @@ var CometChatCalls = class extends SessionMethodsCore {
10681
11042
  throw cometChatError;
10682
11043
  }
10683
11044
  }
11045
+ /**
11046
+ * Logs out the currently logged-in user and clears local session data.
11047
+ * @returns A Promise that resolves to a success message string.
11048
+ * @throws {CometChatException} If no user is logged in or logout fails.
11049
+ */
10684
11050
  static async logout() {
10685
11051
  try {
10686
11052
  if (!this.loggedInUser) {
@@ -10698,24 +11064,53 @@ var CometChatCalls = class extends SessionMethodsCore {
10698
11064
  throw cometChatError;
10699
11065
  }
10700
11066
  }
11067
+ /**
11068
+ * Retrieves the currently logged-in user.
11069
+ * @returns The logged-in User object, or null if no user is logged in.
11070
+ */
10701
11071
  static getLoggedInUser() {
10702
11072
  if (this.loggedInUser && typeof this.loggedInUser === "string") {
10703
11073
  this.loggedInUser = JSON.parse(this.loggedInUser);
10704
11074
  }
10705
11075
  return this.loggedInUser;
10706
11076
  }
11077
+ /**
11078
+ * Retrieves the auth token of the currently logged-in user.
11079
+ * @returns The auth token string, or null if no user is logged in.
11080
+ */
10707
11081
  static getUserAuthToken() {
10708
11082
  return this.loggedInUser?.authToken || null;
10709
11083
  }
11084
+ /**
11085
+ * Checks whether a user is currently logged in.
11086
+ * @returns True if a user is logged in with a valid auth token, false otherwise.
11087
+ */
10710
11088
  static isUserLoggedIn() {
10711
11089
  return this.loggedInUser !== null && this.loggedInUser.authToken !== undefined;
10712
11090
  }
11091
+ /**
11092
+ * Registers a login listener to receive login/logout lifecycle callbacks.
11093
+ * @param listenerId - A unique identifier for the listener.
11094
+ * @param listener - The listener object with callback methods.
11095
+ */
10713
11096
  static addLoginListener(listenerId, listener) {
10714
11097
  this.loginListeners.set(listenerId, listener);
10715
11098
  }
11099
+ /**
11100
+ * Removes a previously registered login listener.
11101
+ * @param listenerId - The unique identifier of the listener to remove.
11102
+ */
10716
11103
  static removeLoginListener(listenerId) {
10717
11104
  this.loginListeners.delete(listenerId);
10718
11105
  }
11106
+ /**
11107
+ * Generates a call token for the given session.
11108
+ * Uses the provided auth token or falls back to the logged-in user's token.
11109
+ * @param sessionId - The session ID to generate a token for.
11110
+ * @param authToken - Optional auth token. If omitted, the logged-in user's token is used.
11111
+ * @returns A Promise that resolves to an object containing the generated token.
11112
+ * @throws {CometChatException} If the session ID is missing, no auth token is available, or the SDK is not initialized.
11113
+ */
10719
11114
  static async generateToken(sessionId, authToken) {
10720
11115
  try {
10721
11116
  if (!sessionId || sessionId.trim() === "") {
@@ -10770,7 +11165,7 @@ var CometChatCalls = class extends SessionMethodsCore {
10770
11165
  appId
10771
11166
  },
10772
11167
  body: {
10773
- platform: "web",
11168
+ platform: "react-native",
10774
11169
  deviceId: this.generateDeviceId()
10775
11170
  }
10776
11171
  });
@@ -10791,7 +11186,7 @@ var CometChatCalls = class extends SessionMethodsCore {
10791
11186
  appId
10792
11187
  },
10793
11188
  body: {
10794
- platform: "web",
11189
+ platform: "react-native",
10795
11190
  deviceId: this.generateDeviceId()
10796
11191
  }
10797
11192
  });
@@ -10831,7 +11226,7 @@ var CometChatCalls = class extends SessionMethodsCore {
10831
11226
  }
10832
11227
  }
10833
11228
  this.loggedInUser = null;
10834
- this.clearSavedUser();
11229
+ await this.clearSavedUser();
10835
11230
  }
10836
11231
  static async callGenerateTokenAPI(sessionId, authToken) {
10837
11232
  const appId = this.appSettings?.appId || "";
@@ -10859,9 +11254,11 @@ var CometChatCalls = class extends SessionMethodsCore {
10859
11254
  baseURL: this.getBaseURL()
10860
11255
  });
10861
11256
  }
10862
- static saveUser(user) {
11257
+ static getStorageKey() {
11258
+ return `${this.appSettings?.appId}:common_store/user`;
11259
+ }
11260
+ static async saveUser(user) {
10863
11261
  try {
10864
- const key = `${this.appSettings?.appId}:common_store/user`;
10865
11262
  const userWithDefaults = {
10866
11263
  hasBlockedMe: false,
10867
11264
  blockedByMe: false,
@@ -10870,31 +11267,28 @@ var CometChatCalls = class extends SessionMethodsCore {
10870
11267
  role: user.role || "default",
10871
11268
  wsChannel: user.wsChannel || { identity: `[${this.appSettings?.appId}]${user.uid}` }
10872
11269
  };
10873
- localStorage.setItem(key, JSON.stringify(userWithDefaults));
11270
+ await AsyncStorage.setItem(this.getStorageKey(), JSON.stringify(userWithDefaults));
10874
11271
  } catch (error) {
10875
- console.warn("Failed to save user to localStorage:", error);
11272
+ console.warn("Failed to save user to AsyncStorage:", error);
10876
11273
  }
10877
11274
  }
10878
- static getSavedUser() {
11275
+ static async getSavedUser() {
10879
11276
  try {
10880
- const key = `${this.appSettings?.appId}:common_store/user`;
10881
- const savedUser = localStorage.getItem(key);
10882
- return savedUser ? savedUser : null;
11277
+ return await AsyncStorage.getItem(this.getStorageKey());
10883
11278
  } catch (error) {
10884
- console.warn("Failed to get saved user from localStorage:", error);
11279
+ console.warn("Failed to get saved user from AsyncStorage:", error);
10885
11280
  return null;
10886
11281
  }
10887
11282
  }
10888
- static clearSavedUser() {
11283
+ static async clearSavedUser() {
10889
11284
  try {
10890
- const key = `${this.appSettings?.appId}:common_store/user`;
10891
- localStorage.removeItem(key);
11285
+ await AsyncStorage.removeItem(this.getStorageKey());
10892
11286
  } catch (error) {
10893
- console.warn("Failed to clear saved user from localStorage:", error);
11287
+ console.warn("Failed to clear saved user from AsyncStorage:", error);
10894
11288
  }
10895
11289
  }
10896
11290
  static generateDeviceId() {
10897
- return "web_" + Math.random().toString(36).substr(2, 9);
11291
+ return "rn_" + Math.random().toString(36).substring(2, 11);
10898
11292
  }
10899
11293
  static createError(error) {
10900
11294
  if (error.errorCode && error.errorDescription) {
@@ -10949,11 +11343,36 @@ var CometChatCalls = class extends SessionMethodsCore {
10949
11343
  }
10950
11344
  });
10951
11345
  }
10952
- static addEventListener(eventType, listener) {
10953
- return eventBus.subscribe(eventType, listener);
11346
+ /**
11347
+ * Adds an event listener for SDK events.
11348
+ * @param eventType - The type of event to listen for.
11349
+ * @param listener - The callback function to invoke when the event fires.
11350
+ * @param options - Optional configuration including an AbortSignal for automatic cleanup.
11351
+ * @returns An unsubscribe function to remove the listener.
11352
+ */
11353
+ static addEventListener(eventType, listener, options) {
11354
+ return eventBus.subscribe(eventType, listener, options);
11355
+ }
11356
+ /**
11357
+ * Sets the audio output mode (mobile only).
11358
+ * @param mode - The audio mode to set (e.g., 'SPEAKER', 'EARPIECE', 'BLUETOOTH', 'HEADPHONES').
11359
+ */
11360
+ static setAudioMode(mode) {
11361
+ setAudioMode(mode);
11362
+ }
11363
+ /**
11364
+ * Enables Picture-in-Picture (PIP) layout during the call.
11365
+ */
11366
+ static enablePictureInPictureLayout() {
11367
+ enablePictureInPictureLayout();
11368
+ }
11369
+ /**
11370
+ * Disables Picture-in-Picture (PIP) layout.
11371
+ */
11372
+ static disablePictureInPictureLayout() {
11373
+ disablePictureInPictureLayout();
10954
11374
  }
10955
11375
  };
10956
11376
 
10957
11377
  //#endregion
10958
- export { CometChatCalls };
10959
- //# sourceMappingURL=index.mjs.map
11378
+ export { CometChatCalls };