@realtimexsco/live-chat 1.5.1 → 1.5.3
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.cjs +351 -281
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.mjs +353 -283
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -8,9 +8,9 @@ var socket_ioClient = require('socket.io-client');
|
|
|
8
8
|
var middleware = require('zustand/middleware');
|
|
9
9
|
var clsx = require('clsx');
|
|
10
10
|
var tailwindMerge = require('tailwind-merge');
|
|
11
|
-
var classVarianceAuthority = require('class-variance-authority');
|
|
12
11
|
var radixUi = require('radix-ui');
|
|
13
12
|
var jsxRuntime = require('react/jsx-runtime');
|
|
13
|
+
var classVarianceAuthority = require('class-variance-authority');
|
|
14
14
|
var React9 = require('react');
|
|
15
15
|
var lucideReact = require('lucide-react');
|
|
16
16
|
var reactDom = require('react-dom');
|
|
@@ -687,7 +687,7 @@ var init_call_api = __esm({
|
|
|
687
687
|
});
|
|
688
688
|
|
|
689
689
|
// src/call/call.types.ts
|
|
690
|
-
exports.CALL_MODES = void 0; exports.CALL_STATUS = void 0; var CALL_RING_TIMEOUT_MS, CLIENT_RING_FALLBACK_MS
|
|
690
|
+
exports.CALL_MODES = void 0; exports.CALL_STATUS = void 0; var CALL_RING_TIMEOUT_MS, CLIENT_RING_FALLBACK_MS;
|
|
691
691
|
var init_call_types = __esm({
|
|
692
692
|
"src/call/call.types.ts"() {
|
|
693
693
|
exports.CALL_MODES = {
|
|
@@ -704,22 +704,15 @@ var init_call_types = __esm({
|
|
|
704
704
|
};
|
|
705
705
|
CALL_RING_TIMEOUT_MS = 4e4;
|
|
706
706
|
CLIENT_RING_FALLBACK_MS = CALL_RING_TIMEOUT_MS + 5e3;
|
|
707
|
-
CALL_LOG_EVENT = "realtimex:call-log";
|
|
708
707
|
}
|
|
709
708
|
});
|
|
710
|
-
var
|
|
709
|
+
var ringTimer, clearRingTimer, scheduleRingTimer, idleState; exports.useCallStore = void 0;
|
|
711
710
|
var init_call_store = __esm({
|
|
712
711
|
"src/call/call.store.ts"() {
|
|
713
712
|
init_useStore();
|
|
714
713
|
init_socket_service2();
|
|
715
714
|
init_call_api();
|
|
716
715
|
init_call_types();
|
|
717
|
-
emitCallLog = (entry) => {
|
|
718
|
-
try {
|
|
719
|
-
window.dispatchEvent(new CustomEvent(CALL_LOG_EVENT, { detail: entry }));
|
|
720
|
-
} catch {
|
|
721
|
-
}
|
|
722
|
-
};
|
|
723
716
|
ringTimer = null;
|
|
724
717
|
clearRingTimer = () => {
|
|
725
718
|
if (ringTimer) clearTimeout(ringTimer);
|
|
@@ -817,6 +810,12 @@ var init_call_store = __esm({
|
|
|
817
810
|
clearRingTimer();
|
|
818
811
|
set({ ...idleState });
|
|
819
812
|
},
|
|
813
|
+
notifyServerCallFailed: () => {
|
|
814
|
+
const { callId } = get();
|
|
815
|
+
if (callId) {
|
|
816
|
+
exports.socketService.emitCallEnd({ callId });
|
|
817
|
+
}
|
|
818
|
+
},
|
|
820
819
|
_receiveIncoming: (payload) => {
|
|
821
820
|
const currentStatus = get().uiStatus;
|
|
822
821
|
if (currentStatus !== "idle") {
|
|
@@ -865,53 +864,60 @@ var init_call_store = __esm({
|
|
|
865
864
|
}));
|
|
866
865
|
},
|
|
867
866
|
_receiveCancelled: (payload) => {
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
outcome: "missed",
|
|
876
|
-
durationSeconds: 0
|
|
877
|
-
});
|
|
867
|
+
const state = get();
|
|
868
|
+
if (state.callId !== payload.callId) return;
|
|
869
|
+
if (state.uiStatus === "in-call") {
|
|
870
|
+
console.warn(
|
|
871
|
+
`[realtimex-call] call_cancelled for ${payload.callId} ignored \u2014 this call is already in-call locally; treating as a stale event.`
|
|
872
|
+
);
|
|
873
|
+
return;
|
|
878
874
|
}
|
|
875
|
+
clearRingTimer();
|
|
879
876
|
set({ ...idleState });
|
|
880
877
|
},
|
|
878
|
+
// Missed/ended/declined/etc. call log messages are now persisted by the
|
|
879
|
+
// backend as real chat messages (CALLS_API.md §3.5) — they arrive
|
|
880
|
+
// through the normal dm_receive/group_message_receive pipeline with
|
|
881
|
+
// isSystemMessage: true, so they render automatically with zero extra
|
|
882
|
+
// code here. Nothing to do on this event beyond resetting local state.
|
|
881
883
|
_receiveEnded: (payload) => {
|
|
882
884
|
if (get().callId !== payload.callId) return;
|
|
883
885
|
clearRingTimer();
|
|
884
|
-
emitCallLog({
|
|
885
|
-
conversationId: payload.conversationId,
|
|
886
|
-
mode: payload.mode,
|
|
887
|
-
outcome: payload.durationSeconds > 0 ? "completed" : "declined",
|
|
888
|
-
durationSeconds: payload.durationSeconds
|
|
889
|
-
});
|
|
890
886
|
set({ ...idleState });
|
|
891
887
|
},
|
|
892
888
|
_receiveBusy: (payload) => {
|
|
893
|
-
|
|
889
|
+
const state = get();
|
|
890
|
+
if (state.callId !== payload.callId) return;
|
|
891
|
+
if (state.uiStatus === "in-call") {
|
|
892
|
+
console.warn(
|
|
893
|
+
`[realtimex-call] call_busy for ${payload.callId} ignored \u2014 this call is already in-call locally; treating as a stale event.`
|
|
894
|
+
);
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
894
897
|
clearRingTimer();
|
|
895
|
-
emitCallLog({
|
|
896
|
-
conversationId: payload.conversationId,
|
|
897
|
-
mode: payload.mode,
|
|
898
|
-
outcome: "busy",
|
|
899
|
-
durationSeconds: 0
|
|
900
|
-
});
|
|
901
898
|
set({ ...idleState, error: "That user is already on another call." });
|
|
902
899
|
},
|
|
903
900
|
// Guarded by callId like every other _receive* handler — a late/stale
|
|
904
901
|
// call_missed for a call that has already ended (accepted, rejected,
|
|
905
902
|
// or replaced by a new one) must not clobber whatever is happening now.
|
|
903
|
+
//
|
|
904
|
+
// Live testing once caught the backend's 40s ring-timeout firing
|
|
905
|
+
// call_missed for a callId that was already call_accepted (timer not
|
|
906
|
+
// cancelled on accept). Backend has since added an atomic
|
|
907
|
+
// only-from-ringing guard (CALLS_API.md §3.3) so this should no longer
|
|
908
|
+
// happen — the uiStatus check below is kept as defense-in-depth rather
|
|
909
|
+
// than removed, since it costs nothing and a regression here would
|
|
910
|
+
// otherwise kill a live call outright.
|
|
906
911
|
_receiveMissed: (payload) => {
|
|
907
|
-
|
|
912
|
+
const state = get();
|
|
913
|
+
if (state.callId !== payload.callId) return;
|
|
914
|
+
if (state.uiStatus === "in-call") {
|
|
915
|
+
console.warn(
|
|
916
|
+
`[realtimex-call] call_missed for ${payload.callId} ignored \u2014 this call is already in-call locally; treating as a stale event.`
|
|
917
|
+
);
|
|
918
|
+
return;
|
|
919
|
+
}
|
|
908
920
|
clearRingTimer();
|
|
909
|
-
emitCallLog({
|
|
910
|
-
conversationId: payload.conversationId,
|
|
911
|
-
mode: payload.mode,
|
|
912
|
-
outcome: "missed",
|
|
913
|
-
durationSeconds: 0
|
|
914
|
-
});
|
|
915
921
|
set({ ...idleState });
|
|
916
922
|
}
|
|
917
923
|
}));
|
|
@@ -4322,6 +4328,58 @@ var init_utils2 = __esm({
|
|
|
4322
4328
|
"src/lib/utils.ts"() {
|
|
4323
4329
|
}
|
|
4324
4330
|
});
|
|
4331
|
+
function Avatar({
|
|
4332
|
+
className,
|
|
4333
|
+
size = "default",
|
|
4334
|
+
...props
|
|
4335
|
+
}) {
|
|
4336
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4337
|
+
radixUi.Avatar.Root,
|
|
4338
|
+
{
|
|
4339
|
+
"data-slot": "avatar",
|
|
4340
|
+
"data-size": size,
|
|
4341
|
+
className: cn(
|
|
4342
|
+
"group/avatar relative flex size-8 shrink-0 overflow-hidden rounded-full select-none data-[size=lg]:size-10 data-[size=sm]:size-6",
|
|
4343
|
+
className
|
|
4344
|
+
),
|
|
4345
|
+
...props
|
|
4346
|
+
}
|
|
4347
|
+
);
|
|
4348
|
+
}
|
|
4349
|
+
function AvatarImage({
|
|
4350
|
+
className,
|
|
4351
|
+
...props
|
|
4352
|
+
}) {
|
|
4353
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4354
|
+
radixUi.Avatar.Image,
|
|
4355
|
+
{
|
|
4356
|
+
"data-slot": "avatar-image",
|
|
4357
|
+
className: cn("aspect-square size-full", className),
|
|
4358
|
+
...props
|
|
4359
|
+
}
|
|
4360
|
+
);
|
|
4361
|
+
}
|
|
4362
|
+
function AvatarFallback({
|
|
4363
|
+
className,
|
|
4364
|
+
...props
|
|
4365
|
+
}) {
|
|
4366
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4367
|
+
radixUi.Avatar.Fallback,
|
|
4368
|
+
{
|
|
4369
|
+
"data-slot": "avatar-fallback",
|
|
4370
|
+
className: cn(
|
|
4371
|
+
"bg-muted text-muted-foreground flex size-full items-center justify-center rounded-full text-sm group-data-[size=sm]/avatar:text-xs",
|
|
4372
|
+
className
|
|
4373
|
+
),
|
|
4374
|
+
...props
|
|
4375
|
+
}
|
|
4376
|
+
);
|
|
4377
|
+
}
|
|
4378
|
+
var init_avatar = __esm({
|
|
4379
|
+
"src/ui/avatar.tsx"() {
|
|
4380
|
+
init_utils2();
|
|
4381
|
+
}
|
|
4382
|
+
});
|
|
4325
4383
|
function Button({
|
|
4326
4384
|
className,
|
|
4327
4385
|
variant = "default",
|
|
@@ -4376,58 +4434,6 @@ var init_button = __esm({
|
|
|
4376
4434
|
);
|
|
4377
4435
|
}
|
|
4378
4436
|
});
|
|
4379
|
-
function Avatar({
|
|
4380
|
-
className,
|
|
4381
|
-
size = "default",
|
|
4382
|
-
...props
|
|
4383
|
-
}) {
|
|
4384
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4385
|
-
radixUi.Avatar.Root,
|
|
4386
|
-
{
|
|
4387
|
-
"data-slot": "avatar",
|
|
4388
|
-
"data-size": size,
|
|
4389
|
-
className: cn(
|
|
4390
|
-
"group/avatar relative flex size-8 shrink-0 overflow-hidden rounded-full select-none data-[size=lg]:size-10 data-[size=sm]:size-6",
|
|
4391
|
-
className
|
|
4392
|
-
),
|
|
4393
|
-
...props
|
|
4394
|
-
}
|
|
4395
|
-
);
|
|
4396
|
-
}
|
|
4397
|
-
function AvatarImage({
|
|
4398
|
-
className,
|
|
4399
|
-
...props
|
|
4400
|
-
}) {
|
|
4401
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4402
|
-
radixUi.Avatar.Image,
|
|
4403
|
-
{
|
|
4404
|
-
"data-slot": "avatar-image",
|
|
4405
|
-
className: cn("aspect-square size-full", className),
|
|
4406
|
-
...props
|
|
4407
|
-
}
|
|
4408
|
-
);
|
|
4409
|
-
}
|
|
4410
|
-
function AvatarFallback({
|
|
4411
|
-
className,
|
|
4412
|
-
...props
|
|
4413
|
-
}) {
|
|
4414
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4415
|
-
radixUi.Avatar.Fallback,
|
|
4416
|
-
{
|
|
4417
|
-
"data-slot": "avatar-fallback",
|
|
4418
|
-
className: cn(
|
|
4419
|
-
"bg-muted text-muted-foreground flex size-full items-center justify-center rounded-full text-sm group-data-[size=sm]/avatar:text-xs",
|
|
4420
|
-
className
|
|
4421
|
-
),
|
|
4422
|
-
...props
|
|
4423
|
-
}
|
|
4424
|
-
);
|
|
4425
|
-
}
|
|
4426
|
-
var init_avatar = __esm({
|
|
4427
|
-
"src/ui/avatar.tsx"() {
|
|
4428
|
-
init_utils2();
|
|
4429
|
-
}
|
|
4430
|
-
});
|
|
4431
4437
|
|
|
4432
4438
|
// src/call/videosdk.loader.ts
|
|
4433
4439
|
var loadVideoSDK;
|
|
@@ -4463,6 +4469,7 @@ var init_ParticipantView = __esm({
|
|
|
4463
4469
|
const { webcamStream, micStream, webcamOn, micOn, displayName, isActiveSpeaker } = sdk.useParticipant(participantId);
|
|
4464
4470
|
const videoRef = React9.useRef(null);
|
|
4465
4471
|
const audioRef = React9.useRef(null);
|
|
4472
|
+
const [hasFrame, setHasFrame] = React9.useState(false);
|
|
4466
4473
|
React9.useEffect(() => {
|
|
4467
4474
|
const el = videoRef.current;
|
|
4468
4475
|
if (!el) return;
|
|
@@ -4471,6 +4478,7 @@ var init_ParticipantView = __esm({
|
|
|
4471
4478
|
el.play().catch(() => void 0);
|
|
4472
4479
|
} else {
|
|
4473
4480
|
el.srcObject = null;
|
|
4481
|
+
setHasFrame(false);
|
|
4474
4482
|
}
|
|
4475
4483
|
}, [webcamOn, webcamStream]);
|
|
4476
4484
|
React9.useEffect(() => {
|
|
@@ -4485,6 +4493,7 @@ var init_ParticipantView = __esm({
|
|
|
4485
4493
|
}
|
|
4486
4494
|
}, [micOn, micStream, isLocal]);
|
|
4487
4495
|
const name = displayName || fallbackName || "Participant";
|
|
4496
|
+
const showVideo = webcamOn && hasFrame;
|
|
4488
4497
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4489
4498
|
"div",
|
|
4490
4499
|
{
|
|
@@ -4500,14 +4509,15 @@ var init_ParticipantView = __esm({
|
|
|
4500
4509
|
ref: videoRef,
|
|
4501
4510
|
muted: isLocal,
|
|
4502
4511
|
playsInline: true,
|
|
4512
|
+
onPlaying: () => setHasFrame(true),
|
|
4503
4513
|
className: cn(
|
|
4504
4514
|
"size-full object-cover",
|
|
4505
|
-
|
|
4515
|
+
showVideo ? "block" : "hidden"
|
|
4506
4516
|
)
|
|
4507
4517
|
}
|
|
4508
4518
|
),
|
|
4509
4519
|
!isLocal && /* @__PURE__ */ jsxRuntime.jsx("audio", { ref: audioRef, autoPlay: true, playsInline: true }),
|
|
4510
|
-
!
|
|
4520
|
+
!showVideo && /* @__PURE__ */ jsxRuntime.jsxs(Avatar, { size: "lg", className: "size-20", children: [
|
|
4511
4521
|
/* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: fallbackImage, alt: name }),
|
|
4512
4522
|
/* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { className: "bg-neutral-700 text-xl font-medium text-white", children: name.charAt(0).toUpperCase() })
|
|
4513
4523
|
] }),
|
|
@@ -4522,6 +4532,53 @@ var init_ParticipantView = __esm({
|
|
|
4522
4532
|
ParticipantView_default = ParticipantView;
|
|
4523
4533
|
}
|
|
4524
4534
|
});
|
|
4535
|
+
var AudioCallView, AudioCallView_default;
|
|
4536
|
+
var init_AudioCallView = __esm({
|
|
4537
|
+
"src/call/AudioCallView.tsx"() {
|
|
4538
|
+
init_avatar();
|
|
4539
|
+
init_utils2();
|
|
4540
|
+
AudioCallView = ({
|
|
4541
|
+
sdk,
|
|
4542
|
+
remoteParticipantId,
|
|
4543
|
+
peerName,
|
|
4544
|
+
peerAvatar
|
|
4545
|
+
}) => {
|
|
4546
|
+
const remote = remoteParticipantId ? sdk.useParticipant(remoteParticipantId) : null;
|
|
4547
|
+
const name = remote?.displayName || peerName || "In call";
|
|
4548
|
+
const isSpeaking = !!remote?.isActiveSpeaker && remote?.micOn;
|
|
4549
|
+
const isMuted = remote != null && !remote.micOn;
|
|
4550
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-6 p-6 text-center", children: [
|
|
4551
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex items-center justify-center", children: [
|
|
4552
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4553
|
+
"span",
|
|
4554
|
+
{
|
|
4555
|
+
className: cn(
|
|
4556
|
+
"absolute inline-flex size-36 rounded-full bg-emerald-400/15 transition-opacity duration-300",
|
|
4557
|
+
isSpeaking ? "animate-ping opacity-100" : "opacity-0"
|
|
4558
|
+
)
|
|
4559
|
+
}
|
|
4560
|
+
),
|
|
4561
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4562
|
+
Avatar,
|
|
4563
|
+
{
|
|
4564
|
+
className: cn(
|
|
4565
|
+
"relative size-28 ring-4 transition-colors duration-300",
|
|
4566
|
+
isSpeaking ? "ring-emerald-400/80" : "ring-white/10"
|
|
4567
|
+
),
|
|
4568
|
+
children: [
|
|
4569
|
+
/* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: peerAvatar, alt: name }),
|
|
4570
|
+
/* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { className: "bg-neutral-700 text-3xl font-medium text-white", children: name.charAt(0).toUpperCase() })
|
|
4571
|
+
]
|
|
4572
|
+
}
|
|
4573
|
+
),
|
|
4574
|
+
isMuted && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -right-1 -bottom-1 flex size-9 items-center justify-center rounded-full bg-neutral-700 ring-4 ring-neutral-900", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MicOff, { size: 16, className: "text-white/80" }) })
|
|
4575
|
+
] }),
|
|
4576
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xl font-semibold tracking-tight", children: name })
|
|
4577
|
+
] });
|
|
4578
|
+
};
|
|
4579
|
+
AudioCallView_default = AudioCallView;
|
|
4580
|
+
}
|
|
4581
|
+
});
|
|
4525
4582
|
var circleBtn, CallControls, CallControls_default;
|
|
4526
4583
|
var init_CallControls = __esm({
|
|
4527
4584
|
"src/call/CallControls.tsx"() {
|
|
@@ -4587,9 +4644,10 @@ var MeetingView, MeetingView_default;
|
|
|
4587
4644
|
var init_MeetingView = __esm({
|
|
4588
4645
|
"src/call/MeetingView.tsx"() {
|
|
4589
4646
|
init_ParticipantView();
|
|
4647
|
+
init_AudioCallView();
|
|
4590
4648
|
init_CallControls();
|
|
4591
4649
|
init_call_store();
|
|
4592
|
-
MeetingView = ({ sdk, mode }) => {
|
|
4650
|
+
MeetingView = ({ sdk, mode, peerName, peerAvatar }) => {
|
|
4593
4651
|
const endCall = exports.useCallStore((s) => s.endCall);
|
|
4594
4652
|
const [hasJoined, setHasJoined] = React9.useState(false);
|
|
4595
4653
|
const hasJoinedRef = React9.useRef(false);
|
|
@@ -4612,7 +4670,23 @@ var init_MeetingView = __esm({
|
|
|
4612
4670
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: "Connecting\u2026" })
|
|
4613
4671
|
] });
|
|
4614
4672
|
}
|
|
4615
|
-
const remoteIds = Array.from(participants.keys())
|
|
4673
|
+
const remoteIds = Array.from(participants.keys()).filter(
|
|
4674
|
+
(id) => id !== localParticipant?.id
|
|
4675
|
+
);
|
|
4676
|
+
if (mode === "audio") {
|
|
4677
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col", children: [
|
|
4678
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4679
|
+
AudioCallView_default,
|
|
4680
|
+
{
|
|
4681
|
+
sdk,
|
|
4682
|
+
remoteParticipantId: remoteIds[0],
|
|
4683
|
+
peerName,
|
|
4684
|
+
peerAvatar
|
|
4685
|
+
}
|
|
4686
|
+
),
|
|
4687
|
+
/* @__PURE__ */ jsxRuntime.jsx(CallControls_default, { sdk, mode })
|
|
4688
|
+
] });
|
|
4689
|
+
}
|
|
4616
4690
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col", children: [
|
|
4617
4691
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4618
4692
|
"div",
|
|
@@ -4626,7 +4700,16 @@ var init_MeetingView = __esm({
|
|
|
4626
4700
|
},
|
|
4627
4701
|
children: [
|
|
4628
4702
|
localParticipant?.id && /* @__PURE__ */ jsxRuntime.jsx(ParticipantView_default, { sdk, participantId: localParticipant.id, isLocal: true }),
|
|
4629
|
-
remoteIds.map((id) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
4703
|
+
remoteIds.map((id) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
4704
|
+
ParticipantView_default,
|
|
4705
|
+
{
|
|
4706
|
+
sdk,
|
|
4707
|
+
participantId: id,
|
|
4708
|
+
fallbackName: peerName,
|
|
4709
|
+
fallbackImage: peerAvatar
|
|
4710
|
+
},
|
|
4711
|
+
id
|
|
4712
|
+
))
|
|
4630
4713
|
]
|
|
4631
4714
|
}
|
|
4632
4715
|
),
|
|
@@ -4648,7 +4731,14 @@ var init_CallSession = __esm({
|
|
|
4648
4731
|
init_useStore();
|
|
4649
4732
|
init_videosdk_loader();
|
|
4650
4733
|
init_MeetingView();
|
|
4651
|
-
CallSession = ({
|
|
4734
|
+
CallSession = ({
|
|
4735
|
+
meetingId,
|
|
4736
|
+
token,
|
|
4737
|
+
mode,
|
|
4738
|
+
peerName,
|
|
4739
|
+
peerAvatar,
|
|
4740
|
+
onError
|
|
4741
|
+
}) => {
|
|
4652
4742
|
const [sdk, setSdk] = React9.useState(null);
|
|
4653
4743
|
const userId = exports.useChatStore((s) => s.loggedUserDetails?._id);
|
|
4654
4744
|
const userName = exports.useChatStore((s) => s.loggedUserDetails?.name);
|
|
@@ -4689,7 +4779,7 @@ var init_CallSession = __esm({
|
|
|
4689
4779
|
token,
|
|
4690
4780
|
reinitialiseMeetingOnConfigChange: false,
|
|
4691
4781
|
joinWithoutUserInteraction: true,
|
|
4692
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(MeetingView_default, { sdk, mode })
|
|
4782
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(MeetingView_default, { sdk, mode, peerName, peerAvatar })
|
|
4693
4783
|
}
|
|
4694
4784
|
);
|
|
4695
4785
|
};
|
|
@@ -5641,6 +5731,167 @@ function useEffectiveSettingsOptional() {
|
|
|
5641
5731
|
};
|
|
5642
5732
|
}
|
|
5643
5733
|
|
|
5734
|
+
// src/call/CallOverlay.tsx
|
|
5735
|
+
init_avatar();
|
|
5736
|
+
init_button();
|
|
5737
|
+
init_call_store();
|
|
5738
|
+
|
|
5739
|
+
// src/call/useRingCountdown.ts
|
|
5740
|
+
init_call_types();
|
|
5741
|
+
var useRingCountdown = (active, callId) => {
|
|
5742
|
+
const [secondsLeft, setSecondsLeft] = React9.useState(
|
|
5743
|
+
Math.ceil(CALL_RING_TIMEOUT_MS / 1e3)
|
|
5744
|
+
);
|
|
5745
|
+
React9.useEffect(() => {
|
|
5746
|
+
if (!active) return;
|
|
5747
|
+
const startedAt = Date.now();
|
|
5748
|
+
setSecondsLeft(Math.ceil(CALL_RING_TIMEOUT_MS / 1e3));
|
|
5749
|
+
const id = setInterval(() => {
|
|
5750
|
+
const remainingMs = CALL_RING_TIMEOUT_MS - (Date.now() - startedAt);
|
|
5751
|
+
setSecondsLeft(Math.max(0, Math.ceil(remainingMs / 1e3)));
|
|
5752
|
+
}, 1e3);
|
|
5753
|
+
return () => clearInterval(id);
|
|
5754
|
+
}, [active, callId]);
|
|
5755
|
+
return secondsLeft;
|
|
5756
|
+
};
|
|
5757
|
+
var useCallDuration = (startedAt) => {
|
|
5758
|
+
const [elapsedMs, setElapsedMs] = React9.useState(0);
|
|
5759
|
+
React9.useEffect(() => {
|
|
5760
|
+
if (!startedAt) {
|
|
5761
|
+
setElapsedMs(0);
|
|
5762
|
+
return;
|
|
5763
|
+
}
|
|
5764
|
+
setElapsedMs(Date.now() - startedAt);
|
|
5765
|
+
const id = setInterval(() => setElapsedMs(Date.now() - startedAt), 1e3);
|
|
5766
|
+
return () => clearInterval(id);
|
|
5767
|
+
}, [startedAt]);
|
|
5768
|
+
const totalSeconds = Math.max(0, Math.floor(elapsedMs / 1e3));
|
|
5769
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
5770
|
+
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
5771
|
+
const seconds = totalSeconds % 60;
|
|
5772
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
5773
|
+
return hours > 0 ? `${hours}:${pad(minutes)}:${pad(seconds)}` : `${pad(minutes)}:${pad(seconds)}`;
|
|
5774
|
+
};
|
|
5775
|
+
var CallSession2 = React9__namespace.default.lazy(() => Promise.resolve().then(() => (init_CallSession(), CallSession_exports)));
|
|
5776
|
+
var CallOverlay = () => {
|
|
5777
|
+
const uiStatus = exports.useCallStore((s) => s.uiStatus);
|
|
5778
|
+
const mode = exports.useCallStore((s) => s.mode);
|
|
5779
|
+
const callId = exports.useCallStore((s) => s.callId);
|
|
5780
|
+
const meetingId = exports.useCallStore((s) => s.meetingId);
|
|
5781
|
+
const token = exports.useCallStore((s) => s.token);
|
|
5782
|
+
const error = exports.useCallStore((s) => s.error);
|
|
5783
|
+
const callee = exports.useCallStore((s) => s.callee);
|
|
5784
|
+
const caller = exports.useCallStore((s) => s.caller);
|
|
5785
|
+
const callStartedAt = exports.useCallStore((s) => s.callStartedAt);
|
|
5786
|
+
const cancelCall = exports.useCallStore((s) => s.cancelCall);
|
|
5787
|
+
const reset = exports.useCallStore((s) => s.reset);
|
|
5788
|
+
const notifyServerCallFailed = exports.useCallStore((s) => s.notifyServerCallFailed);
|
|
5789
|
+
const [sessionError, setSessionError] = React9.useState(null);
|
|
5790
|
+
const secondsLeft = useRingCountdown(uiStatus === "ringing-out", callId);
|
|
5791
|
+
const duration = useCallDuration(callStartedAt);
|
|
5792
|
+
React9.useEffect(() => {
|
|
5793
|
+
setSessionError(null);
|
|
5794
|
+
}, [callId]);
|
|
5795
|
+
React9.useEffect(() => {
|
|
5796
|
+
if (sessionError) notifyServerCallFailed();
|
|
5797
|
+
}, [sessionError, notifyServerCallFailed]);
|
|
5798
|
+
const isOpen = uiStatus !== "idle" && uiStatus !== "incoming";
|
|
5799
|
+
if (!isOpen || typeof document === "undefined") return null;
|
|
5800
|
+
const displayError = error || sessionError;
|
|
5801
|
+
const peerName = callee?.name || caller?.name || "";
|
|
5802
|
+
const peerAvatar = callee?.avatar || caller?.profileImage || void 0;
|
|
5803
|
+
const isVideo = mode === "video";
|
|
5804
|
+
return reactDom.createPortal(
|
|
5805
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5806
|
+
"div",
|
|
5807
|
+
{
|
|
5808
|
+
style: {
|
|
5809
|
+
position: "fixed",
|
|
5810
|
+
inset: 0,
|
|
5811
|
+
width: "100vw",
|
|
5812
|
+
height: "100vh",
|
|
5813
|
+
zIndex: 2147483647
|
|
5814
|
+
},
|
|
5815
|
+
className: "flex flex-col overflow-hidden bg-gradient-to-b from-neutral-900 via-neutral-950 to-black text-white",
|
|
5816
|
+
children: displayError ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-4 p-6 text-center", children: [
|
|
5817
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-sm text-sm text-white/80", children: displayError }),
|
|
5818
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "secondary", onClick: reset, children: [
|
|
5819
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 16, className: "mr-1" }),
|
|
5820
|
+
" Close"
|
|
5821
|
+
] })
|
|
5822
|
+
] }) : uiStatus === "in-call" && meetingId && token && mode ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col", children: [
|
|
5823
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-2 px-4 py-3 text-sm text-white/70", children: [
|
|
5824
|
+
peerName && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-white/90", children: peerName }),
|
|
5825
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "text-white/30", children: "\xB7" }),
|
|
5826
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "tabular-nums", children: duration })
|
|
5827
|
+
] }),
|
|
5828
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5829
|
+
React9__namespace.default.Suspense,
|
|
5830
|
+
{
|
|
5831
|
+
fallback: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-3 text-white/80", children: [
|
|
5832
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-8 animate-spin" }),
|
|
5833
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: "Loading call\u2026" })
|
|
5834
|
+
] }),
|
|
5835
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5836
|
+
CallSession2,
|
|
5837
|
+
{
|
|
5838
|
+
meetingId,
|
|
5839
|
+
token,
|
|
5840
|
+
mode,
|
|
5841
|
+
peerName,
|
|
5842
|
+
peerAvatar,
|
|
5843
|
+
onError: setSessionError
|
|
5844
|
+
}
|
|
5845
|
+
)
|
|
5846
|
+
}
|
|
5847
|
+
)
|
|
5848
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-6 p-6 text-center", children: [
|
|
5849
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex items-center justify-center", children: [
|
|
5850
|
+
uiStatus === "ringing-out" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5851
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inline-flex size-32 animate-ping rounded-full bg-white/10" }),
|
|
5852
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5853
|
+
"span",
|
|
5854
|
+
{
|
|
5855
|
+
className: "absolute inline-flex size-32 animate-ping rounded-full bg-white/5",
|
|
5856
|
+
style: { animationDelay: "0.6s" }
|
|
5857
|
+
}
|
|
5858
|
+
)
|
|
5859
|
+
] }),
|
|
5860
|
+
peerName ? /* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: "relative size-28 ring-4 ring-white/10", children: [
|
|
5861
|
+
/* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: peerAvatar, alt: peerName }),
|
|
5862
|
+
/* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { className: "bg-neutral-700 text-3xl font-medium text-white", children: peerName.charAt(0).toUpperCase() })
|
|
5863
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative flex size-28 items-center justify-center rounded-full bg-white/10", children: isVideo ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Video, { size: 36 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Phone, { size: 36 }) })
|
|
5864
|
+
] }),
|
|
5865
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
5866
|
+
peerName && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xl font-semibold tracking-tight", children: peerName }),
|
|
5867
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-1 text-sm text-white/60", children: [
|
|
5868
|
+
uiStatus === "creating" && "Starting call\u2026",
|
|
5869
|
+
uiStatus === "ringing-out" && `${isVideo ? "Video calling" : "Calling"}\u2026 \xB7 ${secondsLeft}s`,
|
|
5870
|
+
uiStatus === "joining" && "Connecting\u2026"
|
|
5871
|
+
] })
|
|
5872
|
+
] }),
|
|
5873
|
+
uiStatus === "ringing-out" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 flex flex-col items-center gap-2", children: [
|
|
5874
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5875
|
+
Button,
|
|
5876
|
+
{
|
|
5877
|
+
variant: "ghost",
|
|
5878
|
+
size: "icon",
|
|
5879
|
+
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",
|
|
5880
|
+
"aria-label": "Cancel call",
|
|
5881
|
+
onClick: cancelCall,
|
|
5882
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PhoneOff, { size: 24 })
|
|
5883
|
+
}
|
|
5884
|
+
),
|
|
5885
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-white/60", children: "Cancel" })
|
|
5886
|
+
] })
|
|
5887
|
+
] })
|
|
5888
|
+
}
|
|
5889
|
+
),
|
|
5890
|
+
document.body
|
|
5891
|
+
);
|
|
5892
|
+
};
|
|
5893
|
+
var CallOverlay_default = CallOverlay;
|
|
5894
|
+
|
|
5644
5895
|
// src/ui/dialog.tsx
|
|
5645
5896
|
init_utils2();
|
|
5646
5897
|
function Dialog({
|
|
@@ -6179,154 +6430,7 @@ var ChatAlertDialogContent = ({
|
|
|
6179
6430
|
);
|
|
6180
6431
|
};
|
|
6181
6432
|
|
|
6182
|
-
// src/call/
|
|
6183
|
-
init_avatar();
|
|
6184
|
-
init_button();
|
|
6185
|
-
init_utils2();
|
|
6186
|
-
init_call_store();
|
|
6187
|
-
|
|
6188
|
-
// src/call/useRingCountdown.ts
|
|
6189
|
-
init_call_types();
|
|
6190
|
-
var useRingCountdown = (active, callId) => {
|
|
6191
|
-
const [secondsLeft, setSecondsLeft] = React9.useState(
|
|
6192
|
-
Math.ceil(CALL_RING_TIMEOUT_MS / 1e3)
|
|
6193
|
-
);
|
|
6194
|
-
React9.useEffect(() => {
|
|
6195
|
-
if (!active) return;
|
|
6196
|
-
const startedAt = Date.now();
|
|
6197
|
-
setSecondsLeft(Math.ceil(CALL_RING_TIMEOUT_MS / 1e3));
|
|
6198
|
-
const id = setInterval(() => {
|
|
6199
|
-
const remainingMs = CALL_RING_TIMEOUT_MS - (Date.now() - startedAt);
|
|
6200
|
-
setSecondsLeft(Math.max(0, Math.ceil(remainingMs / 1e3)));
|
|
6201
|
-
}, 1e3);
|
|
6202
|
-
return () => clearInterval(id);
|
|
6203
|
-
}, [active, callId]);
|
|
6204
|
-
return secondsLeft;
|
|
6205
|
-
};
|
|
6206
|
-
var useCallDuration = (startedAt) => {
|
|
6207
|
-
const [elapsedMs, setElapsedMs] = React9.useState(0);
|
|
6208
|
-
React9.useEffect(() => {
|
|
6209
|
-
if (!startedAt) {
|
|
6210
|
-
setElapsedMs(0);
|
|
6211
|
-
return;
|
|
6212
|
-
}
|
|
6213
|
-
setElapsedMs(Date.now() - startedAt);
|
|
6214
|
-
const id = setInterval(() => setElapsedMs(Date.now() - startedAt), 1e3);
|
|
6215
|
-
return () => clearInterval(id);
|
|
6216
|
-
}, [startedAt]);
|
|
6217
|
-
const totalSeconds = Math.max(0, Math.floor(elapsedMs / 1e3));
|
|
6218
|
-
const hours = Math.floor(totalSeconds / 3600);
|
|
6219
|
-
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
6220
|
-
const seconds = totalSeconds % 60;
|
|
6221
|
-
const pad = (n) => String(n).padStart(2, "0");
|
|
6222
|
-
return hours > 0 ? `${hours}:${pad(minutes)}:${pad(seconds)}` : `${pad(minutes)}:${pad(seconds)}`;
|
|
6223
|
-
};
|
|
6224
|
-
var CallSession2 = React9__namespace.default.lazy(() => Promise.resolve().then(() => (init_CallSession(), CallSession_exports)));
|
|
6225
|
-
var CallOverlay = () => {
|
|
6226
|
-
const uiStatus = exports.useCallStore((s) => s.uiStatus);
|
|
6227
|
-
const mode = exports.useCallStore((s) => s.mode);
|
|
6228
|
-
const callId = exports.useCallStore((s) => s.callId);
|
|
6229
|
-
const meetingId = exports.useCallStore((s) => s.meetingId);
|
|
6230
|
-
const token = exports.useCallStore((s) => s.token);
|
|
6231
|
-
const error = exports.useCallStore((s) => s.error);
|
|
6232
|
-
const callee = exports.useCallStore((s) => s.callee);
|
|
6233
|
-
const caller = exports.useCallStore((s) => s.caller);
|
|
6234
|
-
const callStartedAt = exports.useCallStore((s) => s.callStartedAt);
|
|
6235
|
-
const cancelCall = exports.useCallStore((s) => s.cancelCall);
|
|
6236
|
-
const reset = exports.useCallStore((s) => s.reset);
|
|
6237
|
-
const [sessionError, setSessionError] = React9.useState(null);
|
|
6238
|
-
const secondsLeft = useRingCountdown(uiStatus === "ringing-out", callId);
|
|
6239
|
-
const duration = useCallDuration(callStartedAt);
|
|
6240
|
-
const isOpen = uiStatus !== "idle" && uiStatus !== "incoming";
|
|
6241
|
-
if (!isOpen) return null;
|
|
6242
|
-
const displayError = error || sessionError;
|
|
6243
|
-
const peerName = callee?.name || caller?.name || "";
|
|
6244
|
-
const peerAvatar = callee?.avatar || caller?.profileImage || void 0;
|
|
6245
|
-
const isVideo = mode === "video";
|
|
6246
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: isOpen, onOpenChange: () => void 0, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6247
|
-
ChatDialogContent,
|
|
6248
|
-
{
|
|
6249
|
-
showCloseButton: false,
|
|
6250
|
-
onEscapeKeyDown: (e) => e.preventDefault(),
|
|
6251
|
-
onPointerDownOutside: (e) => e.preventDefault(),
|
|
6252
|
-
className: cn(
|
|
6253
|
-
"fixed inset-0 top-0 left-0 z-100 flex h-screen w-screen max-w-none",
|
|
6254
|
-
"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"
|
|
6255
|
-
),
|
|
6256
|
-
children: displayError ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-4 p-6 text-center", children: [
|
|
6257
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-sm text-sm text-white/80", children: displayError }),
|
|
6258
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "secondary", onClick: reset, children: [
|
|
6259
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 16, className: "mr-1" }),
|
|
6260
|
-
" Close"
|
|
6261
|
-
] })
|
|
6262
|
-
] }) : uiStatus === "in-call" && meetingId && token && mode ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col", children: [
|
|
6263
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-2 px-4 py-3 text-sm text-white/70", children: [
|
|
6264
|
-
peerName && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-white/90", children: peerName }),
|
|
6265
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "text-white/30", children: "\xB7" }),
|
|
6266
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "tabular-nums", children: duration })
|
|
6267
|
-
] }),
|
|
6268
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6269
|
-
React9__namespace.default.Suspense,
|
|
6270
|
-
{
|
|
6271
|
-
fallback: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-3 text-white/80", children: [
|
|
6272
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-8 animate-spin" }),
|
|
6273
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: "Loading call\u2026" })
|
|
6274
|
-
] }),
|
|
6275
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6276
|
-
CallSession2,
|
|
6277
|
-
{
|
|
6278
|
-
meetingId,
|
|
6279
|
-
token,
|
|
6280
|
-
mode,
|
|
6281
|
-
onError: setSessionError
|
|
6282
|
-
}
|
|
6283
|
-
)
|
|
6284
|
-
}
|
|
6285
|
-
)
|
|
6286
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-6 p-6 text-center", children: [
|
|
6287
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex items-center justify-center", children: [
|
|
6288
|
-
uiStatus === "ringing-out" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
6289
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inline-flex size-32 animate-ping rounded-full bg-white/10" }),
|
|
6290
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6291
|
-
"span",
|
|
6292
|
-
{
|
|
6293
|
-
className: "absolute inline-flex size-32 animate-ping rounded-full bg-white/5",
|
|
6294
|
-
style: { animationDelay: "0.6s" }
|
|
6295
|
-
}
|
|
6296
|
-
)
|
|
6297
|
-
] }),
|
|
6298
|
-
peerName ? /* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: "relative size-28 ring-4 ring-white/10", children: [
|
|
6299
|
-
/* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: peerAvatar, alt: peerName }),
|
|
6300
|
-
/* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { className: "bg-neutral-700 text-3xl font-medium text-white", children: peerName.charAt(0).toUpperCase() })
|
|
6301
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative flex size-28 items-center justify-center rounded-full bg-white/10", children: isVideo ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Video, { size: 36 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Phone, { size: 36 }) })
|
|
6302
|
-
] }),
|
|
6303
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
6304
|
-
peerName && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xl font-semibold tracking-tight", children: peerName }),
|
|
6305
|
-
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-1 text-sm text-white/60", children: [
|
|
6306
|
-
uiStatus === "creating" && "Starting call\u2026",
|
|
6307
|
-
uiStatus === "ringing-out" && `${isVideo ? "Video calling" : "Calling"}\u2026 \xB7 ${secondsLeft}s`,
|
|
6308
|
-
uiStatus === "joining" && "Connecting\u2026"
|
|
6309
|
-
] })
|
|
6310
|
-
] }),
|
|
6311
|
-
uiStatus === "ringing-out" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 flex flex-col items-center gap-2", children: [
|
|
6312
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6313
|
-
Button,
|
|
6314
|
-
{
|
|
6315
|
-
variant: "ghost",
|
|
6316
|
-
size: "icon",
|
|
6317
|
-
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",
|
|
6318
|
-
"aria-label": "Cancel call",
|
|
6319
|
-
onClick: cancelCall,
|
|
6320
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PhoneOff, { size: 24 })
|
|
6321
|
-
}
|
|
6322
|
-
),
|
|
6323
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-white/60", children: "Cancel" })
|
|
6324
|
-
] })
|
|
6325
|
-
] })
|
|
6326
|
-
}
|
|
6327
|
-
) });
|
|
6328
|
-
};
|
|
6329
|
-
var CallOverlay_default = CallOverlay;
|
|
6433
|
+
// src/call/IncomingCallDialog.tsx
|
|
6330
6434
|
init_avatar();
|
|
6331
6435
|
init_button();
|
|
6332
6436
|
init_utils2();
|
|
@@ -6893,18 +6997,6 @@ var installNotificationClickBridge = (options = {}) => {
|
|
|
6893
6997
|
};
|
|
6894
6998
|
|
|
6895
6999
|
// src/hooks/useChatController.ts
|
|
6896
|
-
init_call_types();
|
|
6897
|
-
function formatCallLogText(entry) {
|
|
6898
|
-
const label = entry.mode === "video" ? "video" : "voice";
|
|
6899
|
-
if (entry.outcome === "missed") return `Missed ${label} call`;
|
|
6900
|
-
if (entry.outcome === "declined") return `${label === "video" ? "Video" : "Voice"} call declined`;
|
|
6901
|
-
if (entry.outcome === "busy") return `${label === "video" ? "Video" : "Voice"} call \xB7 not answered`;
|
|
6902
|
-
const totalSeconds = Math.max(0, Math.floor(entry.durationSeconds));
|
|
6903
|
-
const minutes = Math.floor(totalSeconds / 60);
|
|
6904
|
-
const seconds = totalSeconds % 60;
|
|
6905
|
-
const duration = `${minutes}:${String(seconds).padStart(2, "0")}`;
|
|
6906
|
-
return `${label === "video" ? "Video" : "Voice"} call \xB7 ${duration}`;
|
|
6907
|
-
}
|
|
6908
7000
|
function resolveMessageType(content, attachments) {
|
|
6909
7001
|
if (attachments.length === 0) return "text";
|
|
6910
7002
|
if (!content.trim() && attachments.length === 1) {
|
|
@@ -6962,28 +7054,6 @@ var useChatController = () => {
|
|
|
6962
7054
|
);
|
|
6963
7055
|
}, []);
|
|
6964
7056
|
const { localMessages, setLocalMessages } = useChatSync();
|
|
6965
|
-
React9.useEffect(() => {
|
|
6966
|
-
const handleCallLog = (event) => {
|
|
6967
|
-
const entry = event.detail;
|
|
6968
|
-
if (!entry?.conversationId) return;
|
|
6969
|
-
const logMessage = {
|
|
6970
|
-
id: `call-log-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
6971
|
-
content: formatCallLogText(entry),
|
|
6972
|
-
sender: "system",
|
|
6973
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6974
|
-
isOwnMessage: false,
|
|
6975
|
-
isSystemMessage: true,
|
|
6976
|
-
channelId: entry.conversationId,
|
|
6977
|
-
conversationId: entry.conversationId
|
|
6978
|
-
};
|
|
6979
|
-
setLocalMessages((prev) => ({
|
|
6980
|
-
...prev,
|
|
6981
|
-
[entry.conversationId]: [...prev[entry.conversationId] || [], logMessage]
|
|
6982
|
-
}));
|
|
6983
|
-
};
|
|
6984
|
-
window.addEventListener(CALL_LOG_EVENT, handleCallLog);
|
|
6985
|
-
return () => window.removeEventListener(CALL_LOG_EVENT, handleCallLog);
|
|
6986
|
-
}, [setLocalMessages]);
|
|
6987
7057
|
const emitDmSend = exports.useChatStore((s) => s.emitDmSend);
|
|
6988
7058
|
const emitGroupMessageSend2 = exports.useChatStore((s) => s.emitGroupMessageSend);
|
|
6989
7059
|
const emitMarkAsRead = exports.useChatStore((s) => s.emitMarkAsRead);
|