@realtimexsco/live-chat 1.4.19 → 1.5.1

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
@@ -9,7 +9,7 @@ import { Dialog as Dialog$1, Slot, Avatar as Avatar$1, Tooltip as Tooltip$1, Swi
9
9
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
10
10
  import * as React9 from 'react';
11
11
  import React9__default, { createContext, useState, useEffect, useMemo, useContext, useCallback, useRef, useLayoutEffect, Fragment as Fragment$1, useSyncExternalStore } from 'react';
12
- import { Loader2, X, Video, Phone, PhoneOff, Sun, Moon, Settings, Search, UserPlus, ChevronDown, ArrowLeft, Users, WifiOff, Wifi, Sparkles, MessageSquareText, ChevronRight, Pin, Star, MoreVertical, Info, UserKey, ShieldUser, Paperclip, Clock, MessageSquareX, Trash2, LogOut, Ban, CheckCheck, Check, Camera, Save, Pencil, Mail, CornerUpLeft, CheckSquare, Smile, ChevronLeftIcon, ChevronRightIcon, ChevronDownIcon, MessageCircleMore, History, Shield, Send, AlertCircle, ShieldCheck, UserMinus, MessageCircle, ExternalLink, Download, ChevronLeft, ZoomOut, ZoomIn, RotateCcw, Music, Mic, MicOff, VideoOff, XIcon, ArrowRight, MoreHorizontal, PinOff, StarOff, ImageIcon, Film, Play, Pause, FileText, FileSpreadsheet, FileIcon, MessageSquare, Eye, Captions } from 'lucide-react';
12
+ import { Loader2, X, Video, Phone, PhoneOff, Sun, Moon, Settings, Search, UserPlus, ChevronDown, ArrowLeft, Users, WifiOff, Wifi, Sparkles, MessageSquareText, ChevronRight, Pin, Star, MoreVertical, Info, UserKey, ShieldUser, Paperclip, Clock, MessageSquareX, Trash2, LogOut, Ban, CheckCheck, Check, Camera, Save, Pencil, Mail, CornerUpLeft, CheckSquare, Smile, ChevronLeftIcon, ChevronRightIcon, ChevronDownIcon, MessageCircleMore, History, Shield, Send, AlertCircle, ShieldCheck, UserMinus, MessageCircle, ExternalLink, Download, ChevronLeft, ZoomOut, ZoomIn, RotateCcw, Music, MicOff, Mic, VideoOff, XIcon, ArrowRight, MoreHorizontal, PinOff, StarOff, ImageIcon, Film, Play, Pause, FileText, FileSpreadsheet, FileIcon, MessageSquare, Eye, Captions } from 'lucide-react';
13
13
  import { flushSync } from 'react-dom';
14
14
  import EmojiPicker, { Theme } from 'emoji-picker-react';
15
15
  import { getDefaultClassNames, DayPicker } from 'react-day-picker';
@@ -657,12 +657,55 @@ var init_call_api = __esm({
657
657
  };
658
658
  }
659
659
  });
660
- var idleState, useCallStore;
660
+
661
+ // src/call/call.types.ts
662
+ var CALL_MODES, CALL_STATUS, CALL_RING_TIMEOUT_MS, CLIENT_RING_FALLBACK_MS, CALL_LOG_EVENT;
663
+ var init_call_types = __esm({
664
+ "src/call/call.types.ts"() {
665
+ CALL_MODES = {
666
+ AUDIO: "audio",
667
+ VIDEO: "video"
668
+ };
669
+ CALL_STATUS = {
670
+ RINGING: "ringing",
671
+ ONGOING: "ongoing",
672
+ ENDED: "ended",
673
+ MISSED: "missed",
674
+ REJECTED: "rejected",
675
+ CANCELLED: "cancelled"
676
+ };
677
+ CALL_RING_TIMEOUT_MS = 4e4;
678
+ CLIENT_RING_FALLBACK_MS = CALL_RING_TIMEOUT_MS + 5e3;
679
+ CALL_LOG_EVENT = "realtimex:call-log";
680
+ }
681
+ });
682
+ var emitCallLog, ringTimer, clearRingTimer, scheduleRingTimer, idleState, useCallStore;
661
683
  var init_call_store = __esm({
662
684
  "src/call/call.store.ts"() {
663
685
  init_useStore();
664
686
  init_socket_service2();
665
687
  init_call_api();
688
+ init_call_types();
689
+ emitCallLog = (entry) => {
690
+ try {
691
+ window.dispatchEvent(new CustomEvent(CALL_LOG_EVENT, { detail: entry }));
692
+ } catch {
693
+ }
694
+ };
695
+ ringTimer = null;
696
+ clearRingTimer = () => {
697
+ if (ringTimer) clearTimeout(ringTimer);
698
+ ringTimer = null;
699
+ };
700
+ scheduleRingTimer = (callId, get, set) => {
701
+ clearRingTimer();
702
+ ringTimer = setTimeout(() => {
703
+ const state = get();
704
+ if (state.callId === callId && (state.uiStatus === "ringing-out" || state.uiStatus === "incoming")) {
705
+ set({ ...idleState });
706
+ }
707
+ }, CLIENT_RING_FALLBACK_MS);
708
+ };
666
709
  idleState = {
667
710
  uiStatus: "idle",
668
711
  callId: null,
@@ -672,13 +715,15 @@ var init_call_store = __esm({
672
715
  token: null,
673
716
  caller: null,
674
717
  participants: [],
675
- error: null
718
+ error: null,
719
+ callee: null,
720
+ callStartedAt: null
676
721
  };
677
722
  useCallStore = create((set, get) => ({
678
723
  ...idleState,
679
- startCall: async (conversationId, mode) => {
724
+ startCall: async (conversationId, mode, callee) => {
680
725
  if (get().uiStatus !== "idle") return;
681
- set({ ...idleState, uiStatus: "creating", conversationId, mode });
726
+ set({ ...idleState, uiStatus: "creating", conversationId, mode, callee: callee ?? null });
682
727
  try {
683
728
  const room = await apiCreateCallRoom(conversationId, mode);
684
729
  set({
@@ -690,8 +735,10 @@ var init_call_store = __esm({
690
735
  token: room.token,
691
736
  participants: room.participants
692
737
  });
738
+ scheduleRingTimer(room.callId, get, set);
693
739
  socket_service_default.emitCallInvite({ callId: room.callId });
694
740
  } catch (err) {
741
+ clearRingTimer();
695
742
  set({
696
743
  ...idleState,
697
744
  error: err instanceof Error ? err.message : "Could not start the call"
@@ -703,16 +750,18 @@ var init_call_store = __esm({
703
750
  if (callId && uiStatus === "ringing-out") {
704
751
  socket_service_default.emitCallCancel({ callId });
705
752
  }
753
+ clearRingTimer();
706
754
  set({ ...idleState });
707
755
  },
708
756
  acceptCall: async () => {
709
757
  const { callId, meetingId } = get();
710
758
  if (!callId || !meetingId) return;
759
+ clearRingTimer();
711
760
  set({ uiStatus: "joining" });
712
761
  try {
713
762
  const join = await apiFetchJoinToken(meetingId);
714
763
  socket_service_default.emitCallAccept({ callId });
715
- set({ uiStatus: "in-call", token: join.token });
764
+ set({ uiStatus: "in-call", token: join.token, callStartedAt: Date.now() });
716
765
  } catch (err) {
717
766
  set({
718
767
  ...idleState,
@@ -725,6 +774,7 @@ var init_call_store = __esm({
725
774
  if (callId) {
726
775
  socket_service_default.emitCallReject({ callId, reason });
727
776
  }
777
+ clearRingTimer();
728
778
  set({ ...idleState });
729
779
  },
730
780
  endCall: () => {
@@ -732,11 +782,21 @@ var init_call_store = __esm({
732
782
  if (callId) {
733
783
  socket_service_default.emitCallEnd({ callId });
734
784
  }
785
+ clearRingTimer();
786
+ set({ ...idleState });
787
+ },
788
+ reset: () => {
789
+ clearRingTimer();
735
790
  set({ ...idleState });
736
791
  },
737
- reset: () => set({ ...idleState }),
738
792
  _receiveIncoming: (payload) => {
739
- if (get().uiStatus !== "idle") return;
793
+ const currentStatus = get().uiStatus;
794
+ if (currentStatus !== "idle") {
795
+ console.warn(
796
+ `[realtimex-call] call_incoming for ${payload.callId} dropped \u2014 local call store is not idle (currently "${currentStatus}", stuck on callId ${get().callId}). If nothing was actually ringing on screen, this is a stuck state from an earlier call \u2014 refreshing the page clears it.`
797
+ );
798
+ return;
799
+ }
740
800
  set({
741
801
  uiStatus: "incoming",
742
802
  callId: payload.callId,
@@ -746,6 +806,7 @@ var init_call_store = __esm({
746
806
  caller: payload.caller,
747
807
  participants: payload.participants
748
808
  });
809
+ scheduleRingTimer(payload.callId, get, set);
749
810
  },
750
811
  _receiveAccepted: (payload) => {
751
812
  const state = get();
@@ -753,11 +814,17 @@ var init_call_store = __esm({
753
814
  if (state.uiStatus === "incoming") {
754
815
  const myUserId = useStore.getState().loggedUserDetails?._id;
755
816
  if (payload.userId === myUserId) {
817
+ clearRingTimer();
756
818
  set({ ...idleState });
757
819
  }
758
820
  return;
759
821
  }
760
- set({ uiStatus: "in-call", participants: payload.participants });
822
+ clearRingTimer();
823
+ set({
824
+ uiStatus: "in-call",
825
+ participants: payload.participants,
826
+ callStartedAt: Date.now()
827
+ });
761
828
  },
762
829
  // A single decline doesn't end a multi-callee call — the server only
763
830
  // moves the call to `rejected` (followed by `call_ended`) once every
@@ -771,17 +838,52 @@ var init_call_store = __esm({
771
838
  },
772
839
  _receiveCancelled: (payload) => {
773
840
  if (get().callId !== payload.callId) return;
841
+ clearRingTimer();
842
+ const myUserId = useStore.getState().loggedUserDetails?._id;
843
+ if (payload.endedBy !== myUserId) {
844
+ emitCallLog({
845
+ conversationId: payload.conversationId,
846
+ mode: payload.mode,
847
+ outcome: "missed",
848
+ durationSeconds: 0
849
+ });
850
+ }
774
851
  set({ ...idleState });
775
852
  },
776
853
  _receiveEnded: (payload) => {
777
854
  if (get().callId !== payload.callId) return;
855
+ clearRingTimer();
856
+ emitCallLog({
857
+ conversationId: payload.conversationId,
858
+ mode: payload.mode,
859
+ outcome: payload.durationSeconds > 0 ? "completed" : "declined",
860
+ durationSeconds: payload.durationSeconds
861
+ });
778
862
  set({ ...idleState });
779
863
  },
780
864
  _receiveBusy: (payload) => {
781
865
  if (get().callId !== payload.callId) return;
866
+ clearRingTimer();
867
+ emitCallLog({
868
+ conversationId: payload.conversationId,
869
+ mode: payload.mode,
870
+ outcome: "busy",
871
+ durationSeconds: 0
872
+ });
782
873
  set({ ...idleState, error: "That user is already on another call." });
783
874
  },
784
- _receiveMissed: () => {
875
+ // Guarded by callId like every other _receive* handler — a late/stale
876
+ // call_missed for a call that has already ended (accepted, rejected,
877
+ // or replaced by a new one) must not clobber whatever is happening now.
878
+ _receiveMissed: (payload) => {
879
+ if (get().callId !== payload.callId) return;
880
+ clearRingTimer();
881
+ emitCallLog({
882
+ conversationId: payload.conversationId,
883
+ mode: payload.mode,
884
+ outcome: "missed",
885
+ durationSeconds: 0
886
+ });
785
887
  set({ ...idleState });
786
888
  }
787
889
  }));
@@ -795,26 +897,34 @@ var init_call_listeners = __esm({
795
897
  init_socket_events_constants();
796
898
  init_call_store();
797
899
  registerCallSocketListeners = (socket) => {
900
+ console.debug("[realtimex-call] registerCallSocketListeners: attached to socket", socket.id);
798
901
  socket.on(SOCKET_EVENTS.CALL_INCOMING, (payload) => {
902
+ console.log("[realtimex-call] call_incoming received:", payload);
799
903
  useCallStore.getState()._receiveIncoming(payload);
800
904
  });
801
905
  socket.on(SOCKET_EVENTS.CALL_ACCEPTED, (payload) => {
906
+ console.log("[realtimex-call] call_accepted received:", payload);
802
907
  useCallStore.getState()._receiveAccepted(payload);
803
908
  });
804
909
  socket.on(SOCKET_EVENTS.CALL_REJECTED, (payload) => {
910
+ console.log("[realtimex-call] call_rejected received:", payload);
805
911
  useCallStore.getState()._receiveRejected(payload);
806
912
  });
807
913
  socket.on(SOCKET_EVENTS.CALL_CANCELLED, (payload) => {
914
+ console.log("[realtimex-call] call_cancelled received:", payload);
808
915
  useCallStore.getState()._receiveCancelled(payload);
809
916
  });
810
917
  socket.on(SOCKET_EVENTS.CALL_ENDED, (payload) => {
918
+ console.log("[realtimex-call] call_ended received:", payload);
811
919
  useCallStore.getState()._receiveEnded(payload);
812
920
  });
813
921
  socket.on(SOCKET_EVENTS.CALL_BUSY, (payload) => {
922
+ console.log("[realtimex-call] call_busy received:", payload);
814
923
  useCallStore.getState()._receiveBusy(payload);
815
924
  });
816
- socket.on(SOCKET_EVENTS.CALL_MISSED, () => {
817
- useCallStore.getState()._receiveMissed();
925
+ socket.on(SOCKET_EVENTS.CALL_MISSED, (payload) => {
926
+ console.log("[realtimex-call] call_missed received:", payload);
927
+ useCallStore.getState()._receiveMissed(payload);
818
928
  });
819
929
  };
820
930
  }
@@ -4238,22 +4348,6 @@ var init_button = __esm({
4238
4348
  );
4239
4349
  }
4240
4350
  });
4241
-
4242
- // src/call/videosdk.loader.ts
4243
- var loadVideoSDK;
4244
- var init_videosdk_loader = __esm({
4245
- "src/call/videosdk.loader.ts"() {
4246
- loadVideoSDK = async () => {
4247
- try {
4248
- return await import('@videosdk.live/react-sdk');
4249
- } catch {
4250
- throw new Error(
4251
- 'Audio/video calling needs the "@videosdk.live/react-sdk" package \u2014 run: npm install @videosdk.live/react-sdk'
4252
- );
4253
- }
4254
- };
4255
- }
4256
- });
4257
4351
  function Avatar({
4258
4352
  className,
4259
4353
  size = "default",
@@ -4306,6 +4400,25 @@ var init_avatar = __esm({
4306
4400
  init_utils2();
4307
4401
  }
4308
4402
  });
4403
+
4404
+ // src/call/videosdk.loader.ts
4405
+ var loadVideoSDK;
4406
+ var init_videosdk_loader = __esm({
4407
+ "src/call/videosdk.loader.ts"() {
4408
+ loadVideoSDK = async () => {
4409
+ try {
4410
+ return await import('@videosdk.live/react-sdk');
4411
+ } catch (err) {
4412
+ console.error("[realtimex-call] failed to load @videosdk.live/react-sdk:", err);
4413
+ const message = err instanceof Error ? err.message : String(err);
4414
+ const looksMissing = /Failed to resolve module|Cannot find module|find package/i.test(message);
4415
+ throw new Error(
4416
+ looksMissing ? 'Audio/video calling needs the "@videosdk.live/react-sdk" package \u2014 run: npm install @videosdk.live/react-sdk' : `Audio/video calling failed to load: ${message}`
4417
+ );
4418
+ }
4419
+ };
4420
+ }
4421
+ });
4309
4422
  var ParticipantView, ParticipantView_default;
4310
4423
  var init_ParticipantView = __esm({
4311
4424
  "src/call/ParticipantView.tsx"() {
@@ -4319,7 +4432,7 @@ var init_ParticipantView = __esm({
4319
4432
  fallbackImage,
4320
4433
  className
4321
4434
  }) => {
4322
- const { webcamStream, micStream, webcamOn, micOn, displayName } = sdk.useParticipant(participantId);
4435
+ const { webcamStream, micStream, webcamOn, micOn, displayName, isActiveSpeaker } = sdk.useParticipant(participantId);
4323
4436
  const videoRef = useRef(null);
4324
4437
  const audioRef = useRef(null);
4325
4438
  useEffect(() => {
@@ -4348,7 +4461,8 @@ var init_ParticipantView = __esm({
4348
4461
  "div",
4349
4462
  {
4350
4463
  className: cn(
4351
- "relative flex aspect-video min-h-[120px] items-center justify-center overflow-hidden rounded-xl bg-neutral-900",
4464
+ "relative flex aspect-video min-h-[140px] items-center justify-center overflow-hidden rounded-2xl bg-gradient-to-br from-neutral-800 to-neutral-900 ring-1 ring-white/5 transition-shadow",
4465
+ isActiveSpeaker && micOn && "ring-2 ring-emerald-400/80",
4352
4466
  className
4353
4467
  ),
4354
4468
  children: [
@@ -4365,17 +4479,14 @@ var init_ParticipantView = __esm({
4365
4479
  }
4366
4480
  ),
4367
4481
  !isLocal && /* @__PURE__ */ jsx("audio", { ref: audioRef, autoPlay: true, playsInline: true }),
4368
- !webcamOn && /* @__PURE__ */ jsxs(Avatar, { size: "lg", className: "size-16", children: [
4482
+ !webcamOn && /* @__PURE__ */ jsxs(Avatar, { size: "lg", className: "size-20", children: [
4369
4483
  /* @__PURE__ */ jsx(AvatarImage, { src: fallbackImage, alt: name }),
4370
- /* @__PURE__ */ jsx(AvatarFallback, { className: "text-lg", children: name.charAt(0).toUpperCase() })
4484
+ /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-neutral-700 text-xl font-medium text-white", children: name.charAt(0).toUpperCase() })
4371
4485
  ] }),
4372
- /* @__PURE__ */ jsx("span", { className: "absolute bottom-2 left-2 rounded-md bg-black/50 px-2 py-0.5 text-xs text-white", children: isLocal ? `${name} (You)` : name }),
4373
- !micOn && /* @__PURE__ */ jsx("span", { className: "absolute top-2 right-2 rounded-full bg-black/50 p-1 text-white", children: /* @__PURE__ */ jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
4374
- /* @__PURE__ */ jsx("line", { x1: "1", y1: "1", x2: "23", y2: "23" }),
4375
- /* @__PURE__ */ jsx("path", { d: "M9 9v3a3 3 0 0 0 5.12 2.12M15 9.34V4a3 3 0 0 0-5.94-.6" }),
4376
- /* @__PURE__ */ jsx("path", { d: "M17 16.95A7 7 0 0 1 5 12v-2m14 0v2a7 7 0 0 1-.11 1.23" }),
4377
- /* @__PURE__ */ jsx("line", { x1: "12", y1: "19", x2: "12", y2: "23" })
4378
- ] }) })
4486
+ /* @__PURE__ */ jsxs("div", { className: "absolute inset-x-0 bottom-0 flex items-center justify-between gap-2 bg-gradient-to-t from-black/70 to-transparent px-3 py-2", children: [
4487
+ /* @__PURE__ */ jsx("span", { className: "truncate text-xs font-medium text-white drop-shadow", children: isLocal ? `${name} (You)` : name }),
4488
+ !micOn && /* @__PURE__ */ jsx(MicOff, { size: 14, className: "shrink-0 text-white/80", strokeWidth: 2.25 })
4489
+ ] })
4379
4490
  ]
4380
4491
  }
4381
4492
  );
@@ -4389,7 +4500,7 @@ var init_CallControls = __esm({
4389
4500
  init_button();
4390
4501
  init_utils2();
4391
4502
  init_call_store();
4392
- circleBtn = "size-12 rounded-full text-white transition-colors disabled:opacity-40";
4503
+ circleBtn = "size-13 rounded-full text-white transition-all duration-150 disabled:opacity-40 hover:scale-105 active:scale-95";
4393
4504
  CallControls = ({ sdk, mode }) => {
4394
4505
  const { toggleMic, toggleWebcam, localMicOn, localWebcamOn, leave } = sdk.useMeeting();
4395
4506
  const endCall = useCallStore((s) => s.endCall);
@@ -4397,38 +4508,46 @@ var init_CallControls = __esm({
4397
4508
  leave();
4398
4509
  endCall();
4399
4510
  };
4400
- return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-4 py-6", children: [
4401
- /* @__PURE__ */ jsx(
4402
- Button,
4403
- {
4404
- variant: "ghost",
4405
- size: "icon",
4406
- className: cn(circleBtn, localMicOn ? "bg-white/15 hover:bg-white/25" : "bg-white/90 text-neutral-900 hover:bg-white"),
4407
- "aria-label": localMicOn ? "Mute microphone" : "Unmute microphone",
4408
- onClick: () => toggleMic(),
4409
- children: localMicOn ? /* @__PURE__ */ jsx(Mic, { size: 20 }) : /* @__PURE__ */ jsx(MicOff, { size: 20 })
4410
- }
4411
- ),
4412
- mode === "video" && /* @__PURE__ */ jsx(
4413
- Button,
4414
- {
4415
- variant: "ghost",
4416
- size: "icon",
4417
- className: cn(circleBtn, localWebcamOn ? "bg-white/15 hover:bg-white/25" : "bg-white/90 text-neutral-900 hover:bg-white"),
4418
- "aria-label": localWebcamOn ? "Turn camera off" : "Turn camera on",
4419
- onClick: () => toggleWebcam(),
4420
- children: localWebcamOn ? /* @__PURE__ */ jsx(Video, { size: 20 }) : /* @__PURE__ */ jsx(VideoOff, { size: 20 })
4421
- }
4422
- ),
4511
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-5 py-6", children: [
4512
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 rounded-full bg-white/10 p-2 backdrop-blur-sm", children: [
4513
+ /* @__PURE__ */ jsx(
4514
+ Button,
4515
+ {
4516
+ variant: "ghost",
4517
+ size: "icon",
4518
+ className: cn(
4519
+ circleBtn,
4520
+ localMicOn ? "bg-white/10 hover:bg-white/20" : "bg-white text-neutral-900 hover:bg-white/90"
4521
+ ),
4522
+ "aria-label": localMicOn ? "Mute microphone" : "Unmute microphone",
4523
+ onClick: () => toggleMic(),
4524
+ children: localMicOn ? /* @__PURE__ */ jsx(Mic, { size: 20 }) : /* @__PURE__ */ jsx(MicOff, { size: 20 })
4525
+ }
4526
+ ),
4527
+ mode === "video" && /* @__PURE__ */ jsx(
4528
+ Button,
4529
+ {
4530
+ variant: "ghost",
4531
+ size: "icon",
4532
+ className: cn(
4533
+ circleBtn,
4534
+ localWebcamOn ? "bg-white/10 hover:bg-white/20" : "bg-white text-neutral-900 hover:bg-white/90"
4535
+ ),
4536
+ "aria-label": localWebcamOn ? "Turn camera off" : "Turn camera on",
4537
+ onClick: () => toggleWebcam(),
4538
+ children: localWebcamOn ? /* @__PURE__ */ jsx(Video, { size: 20 }) : /* @__PURE__ */ jsx(VideoOff, { size: 20 })
4539
+ }
4540
+ )
4541
+ ] }),
4423
4542
  /* @__PURE__ */ jsx(
4424
4543
  Button,
4425
4544
  {
4426
4545
  variant: "ghost",
4427
4546
  size: "icon",
4428
- className: cn(circleBtn, "bg-red-600 hover:bg-red-500"),
4547
+ className: cn(circleBtn, "bg-red-600 shadow-lg shadow-red-600/30 hover:bg-red-500"),
4429
4548
  "aria-label": "End call",
4430
4549
  onClick: handleLeave,
4431
- children: /* @__PURE__ */ jsx(Phone, { size: 20, className: "rotate-[135deg]" })
4550
+ children: /* @__PURE__ */ jsx(PhoneOff, { size: 22 })
4432
4551
  }
4433
4552
  )
4434
4553
  ] });
@@ -6033,22 +6152,69 @@ var ChatAlertDialogContent = ({
6033
6152
  };
6034
6153
 
6035
6154
  // src/call/CallOverlay.tsx
6155
+ init_avatar();
6036
6156
  init_button();
6037
6157
  init_utils2();
6038
6158
  init_call_store();
6159
+
6160
+ // src/call/useRingCountdown.ts
6161
+ init_call_types();
6162
+ var useRingCountdown = (active, callId) => {
6163
+ const [secondsLeft, setSecondsLeft] = useState(
6164
+ Math.ceil(CALL_RING_TIMEOUT_MS / 1e3)
6165
+ );
6166
+ useEffect(() => {
6167
+ if (!active) return;
6168
+ const startedAt = Date.now();
6169
+ setSecondsLeft(Math.ceil(CALL_RING_TIMEOUT_MS / 1e3));
6170
+ const id = setInterval(() => {
6171
+ const remainingMs = CALL_RING_TIMEOUT_MS - (Date.now() - startedAt);
6172
+ setSecondsLeft(Math.max(0, Math.ceil(remainingMs / 1e3)));
6173
+ }, 1e3);
6174
+ return () => clearInterval(id);
6175
+ }, [active, callId]);
6176
+ return secondsLeft;
6177
+ };
6178
+ var useCallDuration = (startedAt) => {
6179
+ const [elapsedMs, setElapsedMs] = useState(0);
6180
+ useEffect(() => {
6181
+ if (!startedAt) {
6182
+ setElapsedMs(0);
6183
+ return;
6184
+ }
6185
+ setElapsedMs(Date.now() - startedAt);
6186
+ const id = setInterval(() => setElapsedMs(Date.now() - startedAt), 1e3);
6187
+ return () => clearInterval(id);
6188
+ }, [startedAt]);
6189
+ const totalSeconds = Math.max(0, Math.floor(elapsedMs / 1e3));
6190
+ const hours = Math.floor(totalSeconds / 3600);
6191
+ const minutes = Math.floor(totalSeconds % 3600 / 60);
6192
+ const seconds = totalSeconds % 60;
6193
+ const pad = (n) => String(n).padStart(2, "0");
6194
+ return hours > 0 ? `${hours}:${pad(minutes)}:${pad(seconds)}` : `${pad(minutes)}:${pad(seconds)}`;
6195
+ };
6039
6196
  var CallSession2 = React9__default.lazy(() => Promise.resolve().then(() => (init_CallSession(), CallSession_exports)));
6040
6197
  var CallOverlay = () => {
6041
6198
  const uiStatus = useCallStore((s) => s.uiStatus);
6042
6199
  const mode = useCallStore((s) => s.mode);
6200
+ const callId = useCallStore((s) => s.callId);
6043
6201
  const meetingId = useCallStore((s) => s.meetingId);
6044
6202
  const token = useCallStore((s) => s.token);
6045
6203
  const error = useCallStore((s) => s.error);
6204
+ const callee = useCallStore((s) => s.callee);
6205
+ const caller = useCallStore((s) => s.caller);
6206
+ const callStartedAt = useCallStore((s) => s.callStartedAt);
6046
6207
  const cancelCall = useCallStore((s) => s.cancelCall);
6047
6208
  const reset = useCallStore((s) => s.reset);
6048
6209
  const [sessionError, setSessionError] = useState(null);
6210
+ const secondsLeft = useRingCountdown(uiStatus === "ringing-out", callId);
6211
+ const duration = useCallDuration(callStartedAt);
6049
6212
  const isOpen = uiStatus !== "idle" && uiStatus !== "incoming";
6050
6213
  if (!isOpen) return null;
6051
6214
  const displayError = error || sessionError;
6215
+ const peerName = callee?.name || caller?.name || "";
6216
+ const peerAvatar = callee?.avatar || caller?.profileImage || void 0;
6217
+ const isVideo = mode === "video";
6052
6218
  return /* @__PURE__ */ jsx(Dialog, { open: isOpen, onOpenChange: () => void 0, children: /* @__PURE__ */ jsx(
6053
6219
  ChatDialogContent,
6054
6220
  {
@@ -6057,7 +6223,7 @@ var CallOverlay = () => {
6057
6223
  onPointerDownOutside: (e) => e.preventDefault(),
6058
6224
  className: cn(
6059
6225
  "fixed inset-0 top-0 left-0 z-100 flex h-screen w-screen max-w-none",
6060
- "translate-x-0 translate-y-0 flex-col rounded-none border-0 bg-neutral-950 p-0 text-white"
6226
+ "translate-x-0 translate-y-0 flex-col rounded-none border-0 bg-gradient-to-b from-neutral-900 via-neutral-950 to-black p-0 text-white"
6061
6227
  ),
6062
6228
  children: displayError ? /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-4 p-6 text-center", children: [
6063
6229
  /* @__PURE__ */ jsx("p", { className: "max-w-sm text-sm text-white/80", children: displayError }),
@@ -6065,41 +6231,69 @@ var CallOverlay = () => {
6065
6231
  /* @__PURE__ */ jsx(X, { size: 16, className: "mr-1" }),
6066
6232
  " Close"
6067
6233
  ] })
6068
- ] }) : uiStatus === "in-call" && meetingId && token && mode ? /* @__PURE__ */ jsx(
6069
- React9__default.Suspense,
6070
- {
6071
- fallback: /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-3 text-white/80", children: [
6072
- /* @__PURE__ */ jsx(Loader2, { className: "size-8 animate-spin" }),
6073
- /* @__PURE__ */ jsx("p", { className: "text-sm", children: "Loading call\u2026" })
6074
- ] }),
6075
- children: /* @__PURE__ */ jsx(
6076
- CallSession2,
6077
- {
6078
- meetingId,
6079
- token,
6080
- mode,
6081
- onError: setSessionError
6082
- }
6083
- )
6084
- }
6085
- ) : /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-6 p-6 text-center", children: [
6086
- /* @__PURE__ */ jsx("div", { className: "flex size-20 items-center justify-center rounded-full bg-white/10", children: mode === "video" ? /* @__PURE__ */ jsx(Video, { size: 32 }) : /* @__PURE__ */ jsx(Phone, { size: 32 }) }),
6087
- /* @__PURE__ */ jsxs("p", { className: "text-sm text-white/80", children: [
6088
- uiStatus === "creating" && "Starting call\u2026",
6089
- uiStatus === "ringing-out" && "Calling\u2026",
6090
- uiStatus === "joining" && "Connecting\u2026"
6234
+ ] }) : uiStatus === "in-call" && meetingId && token && mode ? /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col", children: [
6235
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-2 px-4 py-3 text-sm text-white/70", children: [
6236
+ peerName && /* @__PURE__ */ jsx("span", { className: "font-medium text-white/90", children: peerName }),
6237
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "text-white/30", children: "\xB7" }),
6238
+ /* @__PURE__ */ jsx("span", { className: "tabular-nums", children: duration })
6091
6239
  ] }),
6092
- uiStatus === "ringing-out" && /* @__PURE__ */ jsx(
6093
- Button,
6240
+ /* @__PURE__ */ jsx(
6241
+ React9__default.Suspense,
6094
6242
  {
6095
- variant: "ghost",
6096
- size: "icon",
6097
- className: "size-12 rounded-full bg-red-600 text-white hover:bg-red-500",
6098
- "aria-label": "Cancel call",
6099
- onClick: cancelCall,
6100
- children: /* @__PURE__ */ jsx(PhoneOff, { size: 20 })
6243
+ fallback: /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-3 text-white/80", children: [
6244
+ /* @__PURE__ */ jsx(Loader2, { className: "size-8 animate-spin" }),
6245
+ /* @__PURE__ */ jsx("p", { className: "text-sm", children: "Loading call\u2026" })
6246
+ ] }),
6247
+ children: /* @__PURE__ */ jsx(
6248
+ CallSession2,
6249
+ {
6250
+ meetingId,
6251
+ token,
6252
+ mode,
6253
+ onError: setSessionError
6254
+ }
6255
+ )
6101
6256
  }
6102
6257
  )
6258
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-6 p-6 text-center", children: [
6259
+ /* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-center", children: [
6260
+ uiStatus === "ringing-out" && /* @__PURE__ */ jsxs(Fragment, { children: [
6261
+ /* @__PURE__ */ jsx("span", { className: "absolute inline-flex size-32 animate-ping rounded-full bg-white/10" }),
6262
+ /* @__PURE__ */ jsx(
6263
+ "span",
6264
+ {
6265
+ className: "absolute inline-flex size-32 animate-ping rounded-full bg-white/5",
6266
+ style: { animationDelay: "0.6s" }
6267
+ }
6268
+ )
6269
+ ] }),
6270
+ peerName ? /* @__PURE__ */ jsxs(Avatar, { className: "relative size-28 ring-4 ring-white/10", children: [
6271
+ /* @__PURE__ */ jsx(AvatarImage, { src: peerAvatar, alt: peerName }),
6272
+ /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-neutral-700 text-3xl font-medium text-white", children: peerName.charAt(0).toUpperCase() })
6273
+ ] }) : /* @__PURE__ */ jsx("div", { className: "relative flex size-28 items-center justify-center rounded-full bg-white/10", children: isVideo ? /* @__PURE__ */ jsx(Video, { size: 36 }) : /* @__PURE__ */ jsx(Phone, { size: 36 }) })
6274
+ ] }),
6275
+ /* @__PURE__ */ jsxs("div", { children: [
6276
+ peerName && /* @__PURE__ */ jsx("p", { className: "text-xl font-semibold tracking-tight", children: peerName }),
6277
+ /* @__PURE__ */ jsxs("p", { className: "mt-1 text-sm text-white/60", children: [
6278
+ uiStatus === "creating" && "Starting call\u2026",
6279
+ uiStatus === "ringing-out" && `${isVideo ? "Video calling" : "Calling"}\u2026 \xB7 ${secondsLeft}s`,
6280
+ uiStatus === "joining" && "Connecting\u2026"
6281
+ ] })
6282
+ ] }),
6283
+ uiStatus === "ringing-out" && /* @__PURE__ */ jsxs("div", { className: "mt-1 flex flex-col items-center gap-2", children: [
6284
+ /* @__PURE__ */ jsx(
6285
+ Button,
6286
+ {
6287
+ variant: "ghost",
6288
+ size: "icon",
6289
+ className: "size-16 rounded-full bg-red-600 text-white shadow-lg shadow-red-600/30 transition-transform hover:scale-105 hover:bg-red-500 active:scale-95",
6290
+ "aria-label": "Cancel call",
6291
+ onClick: cancelCall,
6292
+ children: /* @__PURE__ */ jsx(PhoneOff, { size: 24 })
6293
+ }
6294
+ ),
6295
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-white/60", children: "Cancel" })
6296
+ ] })
6103
6297
  ] })
6104
6298
  }
6105
6299
  ) });
@@ -6111,12 +6305,14 @@ init_utils2();
6111
6305
  init_call_store();
6112
6306
  var IncomingCallDialog = ({ ringtoneUrl }) => {
6113
6307
  const uiStatus = useCallStore((s) => s.uiStatus);
6308
+ const callId = useCallStore((s) => s.callId);
6114
6309
  const caller = useCallStore((s) => s.caller);
6115
6310
  const mode = useCallStore((s) => s.mode);
6116
6311
  const acceptCall = useCallStore((s) => s.acceptCall);
6117
6312
  const rejectCall = useCallStore((s) => s.rejectCall);
6118
6313
  const audioRef = useRef(null);
6119
6314
  const isOpen = uiStatus === "incoming";
6315
+ const secondsLeft = useRingCountdown(isOpen, callId);
6120
6316
  useEffect(() => {
6121
6317
  const el = audioRef.current;
6122
6318
  if (!el || !ringtoneUrl) return;
@@ -6129,6 +6325,7 @@ var IncomingCallDialog = ({ ringtoneUrl }) => {
6129
6325
  }, [isOpen, ringtoneUrl]);
6130
6326
  if (!isOpen) return null;
6131
6327
  const name = caller?.name || "Unknown caller";
6328
+ const isVideo = mode === "video";
6132
6329
  return /* @__PURE__ */ jsxs(Dialog, { open: isOpen, onOpenChange: () => void 0, children: [
6133
6330
  ringtoneUrl && /* @__PURE__ */ jsx("audio", { ref: audioRef, src: ringtoneUrl, loop: true }),
6134
6331
  /* @__PURE__ */ jsx(
@@ -6137,51 +6334,70 @@ var IncomingCallDialog = ({ ringtoneUrl }) => {
6137
6334
  showCloseButton: false,
6138
6335
  onEscapeKeyDown: (e) => e.preventDefault(),
6139
6336
  onPointerDownOutside: (e) => e.preventDefault(),
6140
- className: "max-w-xs rounded-2xl p-6 text-center",
6141
- children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-3", children: [
6142
- /* @__PURE__ */ jsxs(Avatar, { size: "lg", className: "size-16", children: [
6143
- /* @__PURE__ */ jsx(AvatarImage, { src: caller?.profileImage, alt: name }),
6144
- /* @__PURE__ */ jsx(AvatarFallback, { className: "text-lg", children: name.charAt(0).toUpperCase() })
6337
+ className: "w-[min(340px,calc(100vw-2rem))] max-w-none overflow-hidden rounded-3xl border-0 bg-gradient-to-b from-neutral-800 to-neutral-950 p-0 text-white shadow-2xl",
6338
+ children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-5 px-6 pt-9 pb-7", children: [
6339
+ /* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-center", children: [
6340
+ /* @__PURE__ */ jsx("span", { className: "absolute inline-flex size-28 animate-ping rounded-full bg-emerald-400/20" }),
6341
+ /* @__PURE__ */ jsx(
6342
+ "span",
6343
+ {
6344
+ className: "absolute inline-flex size-28 animate-ping rounded-full bg-emerald-400/15",
6345
+ style: { animationDelay: "0.6s" }
6346
+ }
6347
+ ),
6348
+ /* @__PURE__ */ jsxs(Avatar, { className: "relative size-24 ring-4 ring-white/10", children: [
6349
+ /* @__PURE__ */ jsx(AvatarImage, { src: caller?.profileImage, alt: name }),
6350
+ /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-neutral-700 text-2xl font-medium text-white", children: name.charAt(0).toUpperCase() })
6351
+ ] }),
6352
+ /* @__PURE__ */ jsx(
6353
+ "span",
6354
+ {
6355
+ className: cn(
6356
+ "absolute -right-1 -bottom-1 flex size-8 items-center justify-center rounded-full ring-4 ring-neutral-900",
6357
+ isVideo ? "bg-indigo-500" : "bg-emerald-500"
6358
+ ),
6359
+ children: isVideo ? /* @__PURE__ */ jsx(Video, { size: 14 }) : /* @__PURE__ */ jsx(Phone, { size: 14 })
6360
+ }
6361
+ )
6145
6362
  ] }),
6146
- /* @__PURE__ */ jsxs("div", { children: [
6147
- /* @__PURE__ */ jsx("p", { className: "text-base font-semibold text-(--chat-text)", children: name }),
6148
- /* @__PURE__ */ jsxs("p", { className: "flex items-center justify-center gap-1 text-sm text-(--chat-muted)", children: [
6149
- mode === "video" ? /* @__PURE__ */ jsx(Video, { size: 14 }) : /* @__PURE__ */ jsx(Phone, { size: 14 }),
6363
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
6364
+ /* @__PURE__ */ jsx("p", { className: "text-xl font-semibold tracking-tight", children: name }),
6365
+ /* @__PURE__ */ jsxs("p", { className: "mt-1 text-sm text-white/50", children: [
6150
6366
  "Incoming ",
6151
- mode === "video" ? "video" : "voice",
6152
- " call\u2026"
6367
+ isVideo ? "video" : "voice",
6368
+ " call \xB7 ",
6369
+ secondsLeft,
6370
+ "s"
6153
6371
  ] })
6154
6372
  ] }),
6155
- /* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-center justify-center gap-6", children: [
6156
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1", children: [
6373
+ /* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-center justify-center gap-10", children: [
6374
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2", children: [
6157
6375
  /* @__PURE__ */ jsx(
6158
6376
  Button,
6159
6377
  {
6160
6378
  variant: "ghost",
6161
6379
  size: "icon",
6162
- className: cn(
6163
- "size-12 rounded-full bg-red-600 text-white hover:bg-red-500"
6164
- ),
6380
+ className: "size-16 rounded-full bg-red-600 text-white shadow-lg shadow-red-600/30 transition-transform hover:scale-105 hover:bg-red-500 active:scale-95",
6165
6381
  "aria-label": "Decline call",
6166
6382
  onClick: () => rejectCall(),
6167
- children: /* @__PURE__ */ jsx(PhoneOff, { size: 20 })
6383
+ children: /* @__PURE__ */ jsx(PhoneOff, { size: 24 })
6168
6384
  }
6169
6385
  ),
6170
- /* @__PURE__ */ jsx("span", { className: "text-xs text-(--chat-muted)", children: "Decline" })
6386
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-white/60", children: "Decline" })
6171
6387
  ] }),
6172
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1", children: [
6388
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2", children: [
6173
6389
  /* @__PURE__ */ jsx(
6174
6390
  Button,
6175
6391
  {
6176
6392
  variant: "ghost",
6177
6393
  size: "icon",
6178
- className: "size-12 rounded-full bg-green-600 text-white hover:bg-green-500",
6394
+ className: "size-16 rounded-full bg-emerald-500 text-white shadow-lg shadow-emerald-500/30 transition-transform hover:scale-105 hover:bg-emerald-400 active:scale-95",
6179
6395
  "aria-label": "Accept call",
6180
6396
  onClick: () => acceptCall(),
6181
- children: /* @__PURE__ */ jsx(Phone, { size: 20 })
6397
+ children: /* @__PURE__ */ jsx(Phone, { size: 24 })
6182
6398
  }
6183
6399
  ),
6184
- /* @__PURE__ */ jsx("span", { className: "text-xs text-(--chat-muted)", children: "Accept" })
6400
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-white/60", children: "Accept" })
6185
6401
  ] })
6186
6402
  ] })
6187
6403
  ] })
@@ -6649,6 +6865,18 @@ var installNotificationClickBridge = (options = {}) => {
6649
6865
  };
6650
6866
 
6651
6867
  // src/hooks/useChatController.ts
6868
+ init_call_types();
6869
+ function formatCallLogText(entry) {
6870
+ const label = entry.mode === "video" ? "video" : "voice";
6871
+ if (entry.outcome === "missed") return `Missed ${label} call`;
6872
+ if (entry.outcome === "declined") return `${label === "video" ? "Video" : "Voice"} call declined`;
6873
+ if (entry.outcome === "busy") return `${label === "video" ? "Video" : "Voice"} call \xB7 not answered`;
6874
+ const totalSeconds = Math.max(0, Math.floor(entry.durationSeconds));
6875
+ const minutes = Math.floor(totalSeconds / 60);
6876
+ const seconds = totalSeconds % 60;
6877
+ const duration = `${minutes}:${String(seconds).padStart(2, "0")}`;
6878
+ return `${label === "video" ? "Video" : "Voice"} call \xB7 ${duration}`;
6879
+ }
6652
6880
  function resolveMessageType(content, attachments) {
6653
6881
  if (attachments.length === 0) return "text";
6654
6882
  if (!content.trim() && attachments.length === 1) {
@@ -6706,6 +6934,28 @@ var useChatController = () => {
6706
6934
  );
6707
6935
  }, []);
6708
6936
  const { localMessages, setLocalMessages } = useChatSync();
6937
+ useEffect(() => {
6938
+ const handleCallLog = (event) => {
6939
+ const entry = event.detail;
6940
+ if (!entry?.conversationId) return;
6941
+ const logMessage = {
6942
+ id: `call-log-${Date.now()}-${Math.random().toString(36).slice(2)}`,
6943
+ content: formatCallLogText(entry),
6944
+ sender: "system",
6945
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
6946
+ isOwnMessage: false,
6947
+ isSystemMessage: true,
6948
+ channelId: entry.conversationId,
6949
+ conversationId: entry.conversationId
6950
+ };
6951
+ setLocalMessages((prev) => ({
6952
+ ...prev,
6953
+ [entry.conversationId]: [...prev[entry.conversationId] || [], logMessage]
6954
+ }));
6955
+ };
6956
+ window.addEventListener(CALL_LOG_EVENT, handleCallLog);
6957
+ return () => window.removeEventListener(CALL_LOG_EVENT, handleCallLog);
6958
+ }, [setLocalMessages]);
6709
6959
  const emitDmSend = useStore((s) => s.emitDmSend);
6710
6960
  const emitGroupMessageSend2 = useStore((s) => s.emitGroupMessageSend);
6711
6961
  const emitMarkAsRead = useStore((s) => s.emitMarkAsRead);
@@ -10002,19 +10252,20 @@ var HeaderRightSide = ({
10002
10252
  const startCall = useCallStore((s) => s.startCall);
10003
10253
  const showPhoneCall = features.showPhoneCall ?? defaultChatFeatures.showPhoneCall;
10004
10254
  const showVideoCall = features.showVideoCall ?? defaultChatFeatures.showVideoCall;
10255
+ const callee = { name: activeChannel.name, avatar: activeChannel.avatar || activeChannel.image };
10005
10256
  const handlePhoneCall = () => {
10006
10257
  if (features.onPhoneCall) {
10007
10258
  features.onPhoneCall({ activeChannel, conversationId });
10008
10259
  return;
10009
10260
  }
10010
- if (conversationId) startCall(conversationId, "audio");
10261
+ if (conversationId) startCall(conversationId, "audio", callee);
10011
10262
  };
10012
10263
  const handleVideoCall = () => {
10013
10264
  if (features.onVideoCall) {
10014
10265
  features.onVideoCall({ activeChannel, conversationId });
10015
10266
  return;
10016
10267
  }
10017
- if (conversationId) startCall(conversationId, "video");
10268
+ if (conversationId) startCall(conversationId, "video", callee);
10018
10269
  };
10019
10270
  const headerItemGapClass = "gap-0.5";
10020
10271
  const headerIconBtnClass = "inline-flex size-6 shrink-0 items-center justify-center rounded-lg p-0 text-(--chat-muted) transition-colors hover:bg-(--chat-hover) hover:text-(--chat-text) has-[>svg]:p-0";
@@ -20716,22 +20967,7 @@ init_settings_types();
20716
20967
  init_api_service();
20717
20968
  init_call_store();
20718
20969
  init_call_api();
20719
-
20720
- // src/call/call.types.ts
20721
- var CALL_MODES = {
20722
- AUDIO: "audio",
20723
- VIDEO: "video"
20724
- };
20725
- var CALL_STATUS = {
20726
- RINGING: "ringing",
20727
- ONGOING: "ongoing",
20728
- ENDED: "ended",
20729
- MISSED: "missed",
20730
- REJECTED: "rejected",
20731
- CANCELLED: "cancelled"
20732
- };
20733
-
20734
- // src/index.ts
20970
+ init_call_types();
20735
20971
  var index_default = ChatMain_default;
20736
20972
 
20737
20973
  export { ADMIN_PERMISSION_DENIED_MESSAGE, AdminPermissionTooltip, CALLS_NOT_ALLOWED_BY_PLATFORM_MESSAGE, CALLS_NOT_CONFIGURED_MESSAGE, CALL_MODES, CALL_STATUS, CHAT_API_KEYS, CHAT_GET_API_KEYS, Calendar, CalendarDayButton, CallOverlay_default as CallOverlay, Channel, ChannelHeaderView_default as ChannelHeader, ChannelListView_default as ChannelList, ChannelListItem_default as ChannelListItem, Chat, ChatAlertsProvider, ChatAvatar_default as ChatAvatar, ChatCustomizationProvider, ChatDateJumpMenu, ChatEffectiveSettingsProvider, ChatLayout_default as ChatLayout, ChatLocaleProvider, ChatMain_default as ChatMain, ChatThemeProvider, ChatViewport, DEFAULT_EFFECTIVE_SETTINGS, DefaultChannelListItem, DefaultChatAvatar, DefaultChatLayout_default as DefaultChatLayout, ForegroundPushBridge, ForwardModalView as ForwardModal, HeaderCallActions_default as HeaderCallActions, IncomingCallDialog_default as IncomingCallDialog, LoggedUserDetails_default as LoggedUserDetails, LoggedUserSettingsContent_default as LoggedUserSettingsContent, LoggedUserSettingsDialog_default as LoggedUserSettingsDialog, LoggedUserSettingsTrigger_default as LoggedUserSettingsTrigger, ChannelMessageBoxView_default as MessageInput, MessageItemView as MessageItem, ActiveChannelMessagesView_default as MessageList, NOTIFICATION_CLICK_SW_TYPE, OPEN_CONVERSATION_EVENT, PUSH_BROADCAST_CHANNEL, PUSH_CHANGED_EVENT, PUSH_DATA_CACHE_NAME, PushNotificationToggle, apiCreateCallRoom, apiFetchCallDetail, apiFetchCallHistory, apiFetchJoinToken, apiGetPushConfig, apiGetPushPreference, apiRegisterPushToken, apiRemovePushToken, apiUpdatePushPreference, buildChannelFromPushRequest, buildLoggedUserProfile, buildVersionedApiUrl, capitalizeFirst, clampJumpDate, consumePendingOpenConversation, consumePendingOpenFromPushCache, consumePendingOpenRequest, index_default as default, defaultChatClassNames, defaultChatComponents, defaultChatFeatures, defaultChatLayoutConfig, disablePushOnThisDevice, downloadFile, enablePushOnThisDevice, fetchEffectiveSettings, getChatApiVersions, getChatBaseUrl, getChatQueryParamApis, getChatQueryParams, getChatQueryParamsByApi, getChatSocketUrl, getFirstAndLastNameOneCharacter, getResponsiveWidth, getSocketConfig, getStoredPushToken, installNotificationClickBridge, isEmpty, isPushSupported, mergeChatCustomization, mergeChatLayoutConfig, onForegroundPush, packageDefaultComponents, peekPendingOpenConversation, peekPendingOpenRequest, requestOpenConversation, resolveApiRoot, resolveApiUrl, resolveChatApiKey, resolveConversationIdFromPushData, resolveJumpDateBounds, resolveJumpPreset, resolveJumpStep, resolveSocketUrl, setChatAccessToken, setChatApiVersions, setChatBaseURL, setChatClientId, setChatPushApiVersion, setChatQueryParamApis, setChatQueryParams, setChatQueryParamsByApi, setChatSocketUrl, showNotification, smoothScrollToMessage, socket_service_default as socketService, startOfLocalDay, toDateInputValue, uniqueList, useAdminFeatureGate, useCallStore, useChatAlerts, useChatContext, useChatController, useChatCustomization, useChatCustomizationOptional, useChatFeatures, useChatFeaturesOptional, useChatLocale, useStore as useChatStore, useChatTheme, useEffectiveSettings, useEffectiveSettingsOptional, usePushNotifications };