@realtimexsco/live-chat 1.5.2 → 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 +345 -288
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +347 -290
- 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);
|
|
@@ -871,53 +864,60 @@ var init_call_store = __esm({
|
|
|
871
864
|
}));
|
|
872
865
|
},
|
|
873
866
|
_receiveCancelled: (payload) => {
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
outcome: "missed",
|
|
882
|
-
durationSeconds: 0
|
|
883
|
-
});
|
|
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;
|
|
884
874
|
}
|
|
875
|
+
clearRingTimer();
|
|
885
876
|
set({ ...idleState });
|
|
886
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.
|
|
887
883
|
_receiveEnded: (payload) => {
|
|
888
884
|
if (get().callId !== payload.callId) return;
|
|
889
885
|
clearRingTimer();
|
|
890
|
-
emitCallLog({
|
|
891
|
-
conversationId: payload.conversationId,
|
|
892
|
-
mode: payload.mode,
|
|
893
|
-
outcome: payload.durationSeconds > 0 ? "completed" : "declined",
|
|
894
|
-
durationSeconds: payload.durationSeconds
|
|
895
|
-
});
|
|
896
886
|
set({ ...idleState });
|
|
897
887
|
},
|
|
898
888
|
_receiveBusy: (payload) => {
|
|
899
|
-
|
|
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
|
+
}
|
|
900
897
|
clearRingTimer();
|
|
901
|
-
emitCallLog({
|
|
902
|
-
conversationId: payload.conversationId,
|
|
903
|
-
mode: payload.mode,
|
|
904
|
-
outcome: "busy",
|
|
905
|
-
durationSeconds: 0
|
|
906
|
-
});
|
|
907
898
|
set({ ...idleState, error: "That user is already on another call." });
|
|
908
899
|
},
|
|
909
900
|
// Guarded by callId like every other _receive* handler — a late/stale
|
|
910
901
|
// call_missed for a call that has already ended (accepted, rejected,
|
|
911
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.
|
|
912
911
|
_receiveMissed: (payload) => {
|
|
913
|
-
|
|
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
|
+
}
|
|
914
920
|
clearRingTimer();
|
|
915
|
-
emitCallLog({
|
|
916
|
-
conversationId: payload.conversationId,
|
|
917
|
-
mode: payload.mode,
|
|
918
|
-
outcome: "missed",
|
|
919
|
-
durationSeconds: 0
|
|
920
|
-
});
|
|
921
921
|
set({ ...idleState });
|
|
922
922
|
}
|
|
923
923
|
}));
|
|
@@ -4328,6 +4328,58 @@ var init_utils2 = __esm({
|
|
|
4328
4328
|
"src/lib/utils.ts"() {
|
|
4329
4329
|
}
|
|
4330
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
|
+
});
|
|
4331
4383
|
function Button({
|
|
4332
4384
|
className,
|
|
4333
4385
|
variant = "default",
|
|
@@ -4382,58 +4434,6 @@ var init_button = __esm({
|
|
|
4382
4434
|
);
|
|
4383
4435
|
}
|
|
4384
4436
|
});
|
|
4385
|
-
function Avatar({
|
|
4386
|
-
className,
|
|
4387
|
-
size = "default",
|
|
4388
|
-
...props
|
|
4389
|
-
}) {
|
|
4390
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4391
|
-
radixUi.Avatar.Root,
|
|
4392
|
-
{
|
|
4393
|
-
"data-slot": "avatar",
|
|
4394
|
-
"data-size": size,
|
|
4395
|
-
className: cn(
|
|
4396
|
-
"group/avatar relative flex size-8 shrink-0 overflow-hidden rounded-full select-none data-[size=lg]:size-10 data-[size=sm]:size-6",
|
|
4397
|
-
className
|
|
4398
|
-
),
|
|
4399
|
-
...props
|
|
4400
|
-
}
|
|
4401
|
-
);
|
|
4402
|
-
}
|
|
4403
|
-
function AvatarImage({
|
|
4404
|
-
className,
|
|
4405
|
-
...props
|
|
4406
|
-
}) {
|
|
4407
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4408
|
-
radixUi.Avatar.Image,
|
|
4409
|
-
{
|
|
4410
|
-
"data-slot": "avatar-image",
|
|
4411
|
-
className: cn("aspect-square size-full", className),
|
|
4412
|
-
...props
|
|
4413
|
-
}
|
|
4414
|
-
);
|
|
4415
|
-
}
|
|
4416
|
-
function AvatarFallback({
|
|
4417
|
-
className,
|
|
4418
|
-
...props
|
|
4419
|
-
}) {
|
|
4420
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4421
|
-
radixUi.Avatar.Fallback,
|
|
4422
|
-
{
|
|
4423
|
-
"data-slot": "avatar-fallback",
|
|
4424
|
-
className: cn(
|
|
4425
|
-
"bg-muted text-muted-foreground flex size-full items-center justify-center rounded-full text-sm group-data-[size=sm]/avatar:text-xs",
|
|
4426
|
-
className
|
|
4427
|
-
),
|
|
4428
|
-
...props
|
|
4429
|
-
}
|
|
4430
|
-
);
|
|
4431
|
-
}
|
|
4432
|
-
var init_avatar = __esm({
|
|
4433
|
-
"src/ui/avatar.tsx"() {
|
|
4434
|
-
init_utils2();
|
|
4435
|
-
}
|
|
4436
|
-
});
|
|
4437
4437
|
|
|
4438
4438
|
// src/call/videosdk.loader.ts
|
|
4439
4439
|
var loadVideoSDK;
|
|
@@ -4469,6 +4469,7 @@ var init_ParticipantView = __esm({
|
|
|
4469
4469
|
const { webcamStream, micStream, webcamOn, micOn, displayName, isActiveSpeaker } = sdk.useParticipant(participantId);
|
|
4470
4470
|
const videoRef = React9.useRef(null);
|
|
4471
4471
|
const audioRef = React9.useRef(null);
|
|
4472
|
+
const [hasFrame, setHasFrame] = React9.useState(false);
|
|
4472
4473
|
React9.useEffect(() => {
|
|
4473
4474
|
const el = videoRef.current;
|
|
4474
4475
|
if (!el) return;
|
|
@@ -4477,6 +4478,7 @@ var init_ParticipantView = __esm({
|
|
|
4477
4478
|
el.play().catch(() => void 0);
|
|
4478
4479
|
} else {
|
|
4479
4480
|
el.srcObject = null;
|
|
4481
|
+
setHasFrame(false);
|
|
4480
4482
|
}
|
|
4481
4483
|
}, [webcamOn, webcamStream]);
|
|
4482
4484
|
React9.useEffect(() => {
|
|
@@ -4491,6 +4493,7 @@ var init_ParticipantView = __esm({
|
|
|
4491
4493
|
}
|
|
4492
4494
|
}, [micOn, micStream, isLocal]);
|
|
4493
4495
|
const name = displayName || fallbackName || "Participant";
|
|
4496
|
+
const showVideo = webcamOn && hasFrame;
|
|
4494
4497
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4495
4498
|
"div",
|
|
4496
4499
|
{
|
|
@@ -4506,14 +4509,15 @@ var init_ParticipantView = __esm({
|
|
|
4506
4509
|
ref: videoRef,
|
|
4507
4510
|
muted: isLocal,
|
|
4508
4511
|
playsInline: true,
|
|
4512
|
+
onPlaying: () => setHasFrame(true),
|
|
4509
4513
|
className: cn(
|
|
4510
4514
|
"size-full object-cover",
|
|
4511
|
-
|
|
4515
|
+
showVideo ? "block" : "hidden"
|
|
4512
4516
|
)
|
|
4513
4517
|
}
|
|
4514
4518
|
),
|
|
4515
4519
|
!isLocal && /* @__PURE__ */ jsxRuntime.jsx("audio", { ref: audioRef, autoPlay: true, playsInline: true }),
|
|
4516
|
-
!
|
|
4520
|
+
!showVideo && /* @__PURE__ */ jsxRuntime.jsxs(Avatar, { size: "lg", className: "size-20", children: [
|
|
4517
4521
|
/* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: fallbackImage, alt: name }),
|
|
4518
4522
|
/* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { className: "bg-neutral-700 text-xl font-medium text-white", children: name.charAt(0).toUpperCase() })
|
|
4519
4523
|
] }),
|
|
@@ -4528,6 +4532,53 @@ var init_ParticipantView = __esm({
|
|
|
4528
4532
|
ParticipantView_default = ParticipantView;
|
|
4529
4533
|
}
|
|
4530
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
|
+
});
|
|
4531
4582
|
var circleBtn, CallControls, CallControls_default;
|
|
4532
4583
|
var init_CallControls = __esm({
|
|
4533
4584
|
"src/call/CallControls.tsx"() {
|
|
@@ -4593,9 +4644,10 @@ var MeetingView, MeetingView_default;
|
|
|
4593
4644
|
var init_MeetingView = __esm({
|
|
4594
4645
|
"src/call/MeetingView.tsx"() {
|
|
4595
4646
|
init_ParticipantView();
|
|
4647
|
+
init_AudioCallView();
|
|
4596
4648
|
init_CallControls();
|
|
4597
4649
|
init_call_store();
|
|
4598
|
-
MeetingView = ({ sdk, mode }) => {
|
|
4650
|
+
MeetingView = ({ sdk, mode, peerName, peerAvatar }) => {
|
|
4599
4651
|
const endCall = exports.useCallStore((s) => s.endCall);
|
|
4600
4652
|
const [hasJoined, setHasJoined] = React9.useState(false);
|
|
4601
4653
|
const hasJoinedRef = React9.useRef(false);
|
|
@@ -4618,7 +4670,23 @@ var init_MeetingView = __esm({
|
|
|
4618
4670
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: "Connecting\u2026" })
|
|
4619
4671
|
] });
|
|
4620
4672
|
}
|
|
4621
|
-
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
|
+
}
|
|
4622
4690
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col", children: [
|
|
4623
4691
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4624
4692
|
"div",
|
|
@@ -4632,7 +4700,16 @@ var init_MeetingView = __esm({
|
|
|
4632
4700
|
},
|
|
4633
4701
|
children: [
|
|
4634
4702
|
localParticipant?.id && /* @__PURE__ */ jsxRuntime.jsx(ParticipantView_default, { sdk, participantId: localParticipant.id, isLocal: true }),
|
|
4635
|
-
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
|
+
))
|
|
4636
4713
|
]
|
|
4637
4714
|
}
|
|
4638
4715
|
),
|
|
@@ -4654,7 +4731,14 @@ var init_CallSession = __esm({
|
|
|
4654
4731
|
init_useStore();
|
|
4655
4732
|
init_videosdk_loader();
|
|
4656
4733
|
init_MeetingView();
|
|
4657
|
-
CallSession = ({
|
|
4734
|
+
CallSession = ({
|
|
4735
|
+
meetingId,
|
|
4736
|
+
token,
|
|
4737
|
+
mode,
|
|
4738
|
+
peerName,
|
|
4739
|
+
peerAvatar,
|
|
4740
|
+
onError
|
|
4741
|
+
}) => {
|
|
4658
4742
|
const [sdk, setSdk] = React9.useState(null);
|
|
4659
4743
|
const userId = exports.useChatStore((s) => s.loggedUserDetails?._id);
|
|
4660
4744
|
const userName = exports.useChatStore((s) => s.loggedUserDetails?.name);
|
|
@@ -4695,7 +4779,7 @@ var init_CallSession = __esm({
|
|
|
4695
4779
|
token,
|
|
4696
4780
|
reinitialiseMeetingOnConfigChange: false,
|
|
4697
4781
|
joinWithoutUserInteraction: true,
|
|
4698
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(MeetingView_default, { sdk, mode })
|
|
4782
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(MeetingView_default, { sdk, mode, peerName, peerAvatar })
|
|
4699
4783
|
}
|
|
4700
4784
|
);
|
|
4701
4785
|
};
|
|
@@ -5647,6 +5731,167 @@ function useEffectiveSettingsOptional() {
|
|
|
5647
5731
|
};
|
|
5648
5732
|
}
|
|
5649
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
|
+
|
|
5650
5895
|
// src/ui/dialog.tsx
|
|
5651
5896
|
init_utils2();
|
|
5652
5897
|
function Dialog({
|
|
@@ -6185,161 +6430,7 @@ var ChatAlertDialogContent = ({
|
|
|
6185
6430
|
);
|
|
6186
6431
|
};
|
|
6187
6432
|
|
|
6188
|
-
// src/call/
|
|
6189
|
-
init_avatar();
|
|
6190
|
-
init_button();
|
|
6191
|
-
init_utils2();
|
|
6192
|
-
init_call_store();
|
|
6193
|
-
|
|
6194
|
-
// src/call/useRingCountdown.ts
|
|
6195
|
-
init_call_types();
|
|
6196
|
-
var useRingCountdown = (active, callId) => {
|
|
6197
|
-
const [secondsLeft, setSecondsLeft] = React9.useState(
|
|
6198
|
-
Math.ceil(CALL_RING_TIMEOUT_MS / 1e3)
|
|
6199
|
-
);
|
|
6200
|
-
React9.useEffect(() => {
|
|
6201
|
-
if (!active) return;
|
|
6202
|
-
const startedAt = Date.now();
|
|
6203
|
-
setSecondsLeft(Math.ceil(CALL_RING_TIMEOUT_MS / 1e3));
|
|
6204
|
-
const id = setInterval(() => {
|
|
6205
|
-
const remainingMs = CALL_RING_TIMEOUT_MS - (Date.now() - startedAt);
|
|
6206
|
-
setSecondsLeft(Math.max(0, Math.ceil(remainingMs / 1e3)));
|
|
6207
|
-
}, 1e3);
|
|
6208
|
-
return () => clearInterval(id);
|
|
6209
|
-
}, [active, callId]);
|
|
6210
|
-
return secondsLeft;
|
|
6211
|
-
};
|
|
6212
|
-
var useCallDuration = (startedAt) => {
|
|
6213
|
-
const [elapsedMs, setElapsedMs] = React9.useState(0);
|
|
6214
|
-
React9.useEffect(() => {
|
|
6215
|
-
if (!startedAt) {
|
|
6216
|
-
setElapsedMs(0);
|
|
6217
|
-
return;
|
|
6218
|
-
}
|
|
6219
|
-
setElapsedMs(Date.now() - startedAt);
|
|
6220
|
-
const id = setInterval(() => setElapsedMs(Date.now() - startedAt), 1e3);
|
|
6221
|
-
return () => clearInterval(id);
|
|
6222
|
-
}, [startedAt]);
|
|
6223
|
-
const totalSeconds = Math.max(0, Math.floor(elapsedMs / 1e3));
|
|
6224
|
-
const hours = Math.floor(totalSeconds / 3600);
|
|
6225
|
-
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
6226
|
-
const seconds = totalSeconds % 60;
|
|
6227
|
-
const pad = (n) => String(n).padStart(2, "0");
|
|
6228
|
-
return hours > 0 ? `${hours}:${pad(minutes)}:${pad(seconds)}` : `${pad(minutes)}:${pad(seconds)}`;
|
|
6229
|
-
};
|
|
6230
|
-
var CallSession2 = React9__namespace.default.lazy(() => Promise.resolve().then(() => (init_CallSession(), CallSession_exports)));
|
|
6231
|
-
var CallOverlay = () => {
|
|
6232
|
-
const uiStatus = exports.useCallStore((s) => s.uiStatus);
|
|
6233
|
-
const mode = exports.useCallStore((s) => s.mode);
|
|
6234
|
-
const callId = exports.useCallStore((s) => s.callId);
|
|
6235
|
-
const meetingId = exports.useCallStore((s) => s.meetingId);
|
|
6236
|
-
const token = exports.useCallStore((s) => s.token);
|
|
6237
|
-
const error = exports.useCallStore((s) => s.error);
|
|
6238
|
-
const callee = exports.useCallStore((s) => s.callee);
|
|
6239
|
-
const caller = exports.useCallStore((s) => s.caller);
|
|
6240
|
-
const callStartedAt = exports.useCallStore((s) => s.callStartedAt);
|
|
6241
|
-
const cancelCall = exports.useCallStore((s) => s.cancelCall);
|
|
6242
|
-
const reset = exports.useCallStore((s) => s.reset);
|
|
6243
|
-
const notifyServerCallFailed = exports.useCallStore((s) => s.notifyServerCallFailed);
|
|
6244
|
-
const [sessionError, setSessionError] = React9.useState(null);
|
|
6245
|
-
const secondsLeft = useRingCountdown(uiStatus === "ringing-out", callId);
|
|
6246
|
-
const duration = useCallDuration(callStartedAt);
|
|
6247
|
-
React9.useEffect(() => {
|
|
6248
|
-
setSessionError(null);
|
|
6249
|
-
}, [callId]);
|
|
6250
|
-
React9.useEffect(() => {
|
|
6251
|
-
if (sessionError) notifyServerCallFailed();
|
|
6252
|
-
}, [sessionError, notifyServerCallFailed]);
|
|
6253
|
-
const isOpen = uiStatus !== "idle" && uiStatus !== "incoming";
|
|
6254
|
-
if (!isOpen) return null;
|
|
6255
|
-
const displayError = error || sessionError;
|
|
6256
|
-
const peerName = callee?.name || caller?.name || "";
|
|
6257
|
-
const peerAvatar = callee?.avatar || caller?.profileImage || void 0;
|
|
6258
|
-
const isVideo = mode === "video";
|
|
6259
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: isOpen, onOpenChange: () => void 0, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6260
|
-
ChatDialogContent,
|
|
6261
|
-
{
|
|
6262
|
-
showCloseButton: false,
|
|
6263
|
-
onEscapeKeyDown: (e) => e.preventDefault(),
|
|
6264
|
-
onPointerDownOutside: (e) => e.preventDefault(),
|
|
6265
|
-
className: cn(
|
|
6266
|
-
"fixed inset-0 top-0 left-0 z-100 flex h-screen w-screen max-w-none",
|
|
6267
|
-
"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"
|
|
6268
|
-
),
|
|
6269
|
-
children: displayError ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-4 p-6 text-center", children: [
|
|
6270
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-sm text-sm text-white/80", children: displayError }),
|
|
6271
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "secondary", onClick: reset, children: [
|
|
6272
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 16, className: "mr-1" }),
|
|
6273
|
-
" Close"
|
|
6274
|
-
] })
|
|
6275
|
-
] }) : uiStatus === "in-call" && meetingId && token && mode ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col", children: [
|
|
6276
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-2 px-4 py-3 text-sm text-white/70", children: [
|
|
6277
|
-
peerName && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-white/90", children: peerName }),
|
|
6278
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "text-white/30", children: "\xB7" }),
|
|
6279
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "tabular-nums", children: duration })
|
|
6280
|
-
] }),
|
|
6281
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6282
|
-
React9__namespace.default.Suspense,
|
|
6283
|
-
{
|
|
6284
|
-
fallback: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-3 text-white/80", children: [
|
|
6285
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-8 animate-spin" }),
|
|
6286
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: "Loading call\u2026" })
|
|
6287
|
-
] }),
|
|
6288
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6289
|
-
CallSession2,
|
|
6290
|
-
{
|
|
6291
|
-
meetingId,
|
|
6292
|
-
token,
|
|
6293
|
-
mode,
|
|
6294
|
-
onError: setSessionError
|
|
6295
|
-
}
|
|
6296
|
-
)
|
|
6297
|
-
}
|
|
6298
|
-
)
|
|
6299
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-6 p-6 text-center", children: [
|
|
6300
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex items-center justify-center", children: [
|
|
6301
|
-
uiStatus === "ringing-out" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
6302
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inline-flex size-32 animate-ping rounded-full bg-white/10" }),
|
|
6303
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6304
|
-
"span",
|
|
6305
|
-
{
|
|
6306
|
-
className: "absolute inline-flex size-32 animate-ping rounded-full bg-white/5",
|
|
6307
|
-
style: { animationDelay: "0.6s" }
|
|
6308
|
-
}
|
|
6309
|
-
)
|
|
6310
|
-
] }),
|
|
6311
|
-
peerName ? /* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: "relative size-28 ring-4 ring-white/10", children: [
|
|
6312
|
-
/* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: peerAvatar, alt: peerName }),
|
|
6313
|
-
/* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { className: "bg-neutral-700 text-3xl font-medium text-white", children: peerName.charAt(0).toUpperCase() })
|
|
6314
|
-
] }) : /* @__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 }) })
|
|
6315
|
-
] }),
|
|
6316
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
6317
|
-
peerName && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xl font-semibold tracking-tight", children: peerName }),
|
|
6318
|
-
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-1 text-sm text-white/60", children: [
|
|
6319
|
-
uiStatus === "creating" && "Starting call\u2026",
|
|
6320
|
-
uiStatus === "ringing-out" && `${isVideo ? "Video calling" : "Calling"}\u2026 \xB7 ${secondsLeft}s`,
|
|
6321
|
-
uiStatus === "joining" && "Connecting\u2026"
|
|
6322
|
-
] })
|
|
6323
|
-
] }),
|
|
6324
|
-
uiStatus === "ringing-out" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 flex flex-col items-center gap-2", children: [
|
|
6325
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6326
|
-
Button,
|
|
6327
|
-
{
|
|
6328
|
-
variant: "ghost",
|
|
6329
|
-
size: "icon",
|
|
6330
|
-
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",
|
|
6331
|
-
"aria-label": "Cancel call",
|
|
6332
|
-
onClick: cancelCall,
|
|
6333
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PhoneOff, { size: 24 })
|
|
6334
|
-
}
|
|
6335
|
-
),
|
|
6336
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-white/60", children: "Cancel" })
|
|
6337
|
-
] })
|
|
6338
|
-
] })
|
|
6339
|
-
}
|
|
6340
|
-
) });
|
|
6341
|
-
};
|
|
6342
|
-
var CallOverlay_default = CallOverlay;
|
|
6433
|
+
// src/call/IncomingCallDialog.tsx
|
|
6343
6434
|
init_avatar();
|
|
6344
6435
|
init_button();
|
|
6345
6436
|
init_utils2();
|
|
@@ -6906,18 +6997,6 @@ var installNotificationClickBridge = (options = {}) => {
|
|
|
6906
6997
|
};
|
|
6907
6998
|
|
|
6908
6999
|
// src/hooks/useChatController.ts
|
|
6909
|
-
init_call_types();
|
|
6910
|
-
function formatCallLogText(entry) {
|
|
6911
|
-
const label = entry.mode === "video" ? "video" : "voice";
|
|
6912
|
-
if (entry.outcome === "missed") return `Missed ${label} call`;
|
|
6913
|
-
if (entry.outcome === "declined") return `${label === "video" ? "Video" : "Voice"} call declined`;
|
|
6914
|
-
if (entry.outcome === "busy") return `${label === "video" ? "Video" : "Voice"} call \xB7 not answered`;
|
|
6915
|
-
const totalSeconds = Math.max(0, Math.floor(entry.durationSeconds));
|
|
6916
|
-
const minutes = Math.floor(totalSeconds / 60);
|
|
6917
|
-
const seconds = totalSeconds % 60;
|
|
6918
|
-
const duration = `${minutes}:${String(seconds).padStart(2, "0")}`;
|
|
6919
|
-
return `${label === "video" ? "Video" : "Voice"} call \xB7 ${duration}`;
|
|
6920
|
-
}
|
|
6921
7000
|
function resolveMessageType(content, attachments) {
|
|
6922
7001
|
if (attachments.length === 0) return "text";
|
|
6923
7002
|
if (!content.trim() && attachments.length === 1) {
|
|
@@ -6975,28 +7054,6 @@ var useChatController = () => {
|
|
|
6975
7054
|
);
|
|
6976
7055
|
}, []);
|
|
6977
7056
|
const { localMessages, setLocalMessages } = useChatSync();
|
|
6978
|
-
React9.useEffect(() => {
|
|
6979
|
-
const handleCallLog = (event) => {
|
|
6980
|
-
const entry = event.detail;
|
|
6981
|
-
if (!entry?.conversationId) return;
|
|
6982
|
-
const logMessage = {
|
|
6983
|
-
id: `call-log-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
6984
|
-
content: formatCallLogText(entry),
|
|
6985
|
-
sender: "system",
|
|
6986
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6987
|
-
isOwnMessage: false,
|
|
6988
|
-
isSystemMessage: true,
|
|
6989
|
-
channelId: entry.conversationId,
|
|
6990
|
-
conversationId: entry.conversationId
|
|
6991
|
-
};
|
|
6992
|
-
setLocalMessages((prev) => ({
|
|
6993
|
-
...prev,
|
|
6994
|
-
[entry.conversationId]: [...prev[entry.conversationId] || [], logMessage]
|
|
6995
|
-
}));
|
|
6996
|
-
};
|
|
6997
|
-
window.addEventListener(CALL_LOG_EVENT, handleCallLog);
|
|
6998
|
-
return () => window.removeEventListener(CALL_LOG_EVENT, handleCallLog);
|
|
6999
|
-
}, [setLocalMessages]);
|
|
7000
7057
|
const emitDmSend = exports.useChatStore((s) => s.emitDmSend);
|
|
7001
7058
|
const emitGroupMessageSend2 = exports.useChatStore((s) => s.emitGroupMessageSend);
|
|
7002
7059
|
const emitMarkAsRead = exports.useChatStore((s) => s.emitMarkAsRead);
|