@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.mjs
CHANGED
|
@@ -4,13 +4,13 @@ import { io } from 'socket.io-client';
|
|
|
4
4
|
import { persist } from 'zustand/middleware';
|
|
5
5
|
import { clsx } from 'clsx';
|
|
6
6
|
import { twMerge } from 'tailwind-merge';
|
|
7
|
-
import {
|
|
8
|
-
import { Dialog as Dialog$1, Slot, Avatar as Avatar$1, Tooltip as Tooltip$1, Switch as Switch$1, ScrollArea as ScrollArea$1, Popover as Popover$1, DropdownMenu as DropdownMenu$1, AlertDialog as AlertDialog$1 } from 'radix-ui';
|
|
7
|
+
import { Slot, Avatar as Avatar$1, Dialog as Dialog$1, Tooltip as Tooltip$1, Switch as Switch$1, ScrollArea as ScrollArea$1, Popover as Popover$1, DropdownMenu as DropdownMenu$1, AlertDialog as AlertDialog$1 } from 'radix-ui';
|
|
9
8
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
9
|
+
import { cva } from 'class-variance-authority';
|
|
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
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
|
-
import { flushSync } from 'react-dom';
|
|
13
|
+
import { createPortal, flushSync } from 'react-dom';
|
|
14
14
|
import EmojiPicker, { Theme } from 'emoji-picker-react';
|
|
15
15
|
import { getDefaultClassNames, DayPicker } from 'react-day-picker';
|
|
16
16
|
import toast$1, { Toaster, toast } from 'react-hot-toast';
|
|
@@ -659,7 +659,7 @@ var init_call_api = __esm({
|
|
|
659
659
|
});
|
|
660
660
|
|
|
661
661
|
// src/call/call.types.ts
|
|
662
|
-
var CALL_MODES, CALL_STATUS, CALL_RING_TIMEOUT_MS, CLIENT_RING_FALLBACK_MS
|
|
662
|
+
var CALL_MODES, CALL_STATUS, CALL_RING_TIMEOUT_MS, CLIENT_RING_FALLBACK_MS;
|
|
663
663
|
var init_call_types = __esm({
|
|
664
664
|
"src/call/call.types.ts"() {
|
|
665
665
|
CALL_MODES = {
|
|
@@ -676,22 +676,15 @@ var init_call_types = __esm({
|
|
|
676
676
|
};
|
|
677
677
|
CALL_RING_TIMEOUT_MS = 4e4;
|
|
678
678
|
CLIENT_RING_FALLBACK_MS = CALL_RING_TIMEOUT_MS + 5e3;
|
|
679
|
-
CALL_LOG_EVENT = "realtimex:call-log";
|
|
680
679
|
}
|
|
681
680
|
});
|
|
682
|
-
var
|
|
681
|
+
var ringTimer, clearRingTimer, scheduleRingTimer, idleState, useCallStore;
|
|
683
682
|
var init_call_store = __esm({
|
|
684
683
|
"src/call/call.store.ts"() {
|
|
685
684
|
init_useStore();
|
|
686
685
|
init_socket_service2();
|
|
687
686
|
init_call_api();
|
|
688
687
|
init_call_types();
|
|
689
|
-
emitCallLog = (entry) => {
|
|
690
|
-
try {
|
|
691
|
-
window.dispatchEvent(new CustomEvent(CALL_LOG_EVENT, { detail: entry }));
|
|
692
|
-
} catch {
|
|
693
|
-
}
|
|
694
|
-
};
|
|
695
688
|
ringTimer = null;
|
|
696
689
|
clearRingTimer = () => {
|
|
697
690
|
if (ringTimer) clearTimeout(ringTimer);
|
|
@@ -843,53 +836,60 @@ var init_call_store = __esm({
|
|
|
843
836
|
}));
|
|
844
837
|
},
|
|
845
838
|
_receiveCancelled: (payload) => {
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
outcome: "missed",
|
|
854
|
-
durationSeconds: 0
|
|
855
|
-
});
|
|
839
|
+
const state = get();
|
|
840
|
+
if (state.callId !== payload.callId) return;
|
|
841
|
+
if (state.uiStatus === "in-call") {
|
|
842
|
+
console.warn(
|
|
843
|
+
`[realtimex-call] call_cancelled for ${payload.callId} ignored \u2014 this call is already in-call locally; treating as a stale event.`
|
|
844
|
+
);
|
|
845
|
+
return;
|
|
856
846
|
}
|
|
847
|
+
clearRingTimer();
|
|
857
848
|
set({ ...idleState });
|
|
858
849
|
},
|
|
850
|
+
// Missed/ended/declined/etc. call log messages are now persisted by the
|
|
851
|
+
// backend as real chat messages (CALLS_API.md §3.5) — they arrive
|
|
852
|
+
// through the normal dm_receive/group_message_receive pipeline with
|
|
853
|
+
// isSystemMessage: true, so they render automatically with zero extra
|
|
854
|
+
// code here. Nothing to do on this event beyond resetting local state.
|
|
859
855
|
_receiveEnded: (payload) => {
|
|
860
856
|
if (get().callId !== payload.callId) return;
|
|
861
857
|
clearRingTimer();
|
|
862
|
-
emitCallLog({
|
|
863
|
-
conversationId: payload.conversationId,
|
|
864
|
-
mode: payload.mode,
|
|
865
|
-
outcome: payload.durationSeconds > 0 ? "completed" : "declined",
|
|
866
|
-
durationSeconds: payload.durationSeconds
|
|
867
|
-
});
|
|
868
858
|
set({ ...idleState });
|
|
869
859
|
},
|
|
870
860
|
_receiveBusy: (payload) => {
|
|
871
|
-
|
|
861
|
+
const state = get();
|
|
862
|
+
if (state.callId !== payload.callId) return;
|
|
863
|
+
if (state.uiStatus === "in-call") {
|
|
864
|
+
console.warn(
|
|
865
|
+
`[realtimex-call] call_busy for ${payload.callId} ignored \u2014 this call is already in-call locally; treating as a stale event.`
|
|
866
|
+
);
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
872
869
|
clearRingTimer();
|
|
873
|
-
emitCallLog({
|
|
874
|
-
conversationId: payload.conversationId,
|
|
875
|
-
mode: payload.mode,
|
|
876
|
-
outcome: "busy",
|
|
877
|
-
durationSeconds: 0
|
|
878
|
-
});
|
|
879
870
|
set({ ...idleState, error: "That user is already on another call." });
|
|
880
871
|
},
|
|
881
872
|
// Guarded by callId like every other _receive* handler — a late/stale
|
|
882
873
|
// call_missed for a call that has already ended (accepted, rejected,
|
|
883
874
|
// or replaced by a new one) must not clobber whatever is happening now.
|
|
875
|
+
//
|
|
876
|
+
// Live testing once caught the backend's 40s ring-timeout firing
|
|
877
|
+
// call_missed for a callId that was already call_accepted (timer not
|
|
878
|
+
// cancelled on accept). Backend has since added an atomic
|
|
879
|
+
// only-from-ringing guard (CALLS_API.md §3.3) so this should no longer
|
|
880
|
+
// happen — the uiStatus check below is kept as defense-in-depth rather
|
|
881
|
+
// than removed, since it costs nothing and a regression here would
|
|
882
|
+
// otherwise kill a live call outright.
|
|
884
883
|
_receiveMissed: (payload) => {
|
|
885
|
-
|
|
884
|
+
const state = get();
|
|
885
|
+
if (state.callId !== payload.callId) return;
|
|
886
|
+
if (state.uiStatus === "in-call") {
|
|
887
|
+
console.warn(
|
|
888
|
+
`[realtimex-call] call_missed for ${payload.callId} ignored \u2014 this call is already in-call locally; treating as a stale event.`
|
|
889
|
+
);
|
|
890
|
+
return;
|
|
891
|
+
}
|
|
886
892
|
clearRingTimer();
|
|
887
|
-
emitCallLog({
|
|
888
|
-
conversationId: payload.conversationId,
|
|
889
|
-
mode: payload.mode,
|
|
890
|
-
outcome: "missed",
|
|
891
|
-
durationSeconds: 0
|
|
892
|
-
});
|
|
893
893
|
set({ ...idleState });
|
|
894
894
|
}
|
|
895
895
|
}));
|
|
@@ -4300,6 +4300,58 @@ var init_utils2 = __esm({
|
|
|
4300
4300
|
"src/lib/utils.ts"() {
|
|
4301
4301
|
}
|
|
4302
4302
|
});
|
|
4303
|
+
function Avatar({
|
|
4304
|
+
className,
|
|
4305
|
+
size = "default",
|
|
4306
|
+
...props
|
|
4307
|
+
}) {
|
|
4308
|
+
return /* @__PURE__ */ jsx(
|
|
4309
|
+
Avatar$1.Root,
|
|
4310
|
+
{
|
|
4311
|
+
"data-slot": "avatar",
|
|
4312
|
+
"data-size": size,
|
|
4313
|
+
className: cn(
|
|
4314
|
+
"group/avatar relative flex size-8 shrink-0 overflow-hidden rounded-full select-none data-[size=lg]:size-10 data-[size=sm]:size-6",
|
|
4315
|
+
className
|
|
4316
|
+
),
|
|
4317
|
+
...props
|
|
4318
|
+
}
|
|
4319
|
+
);
|
|
4320
|
+
}
|
|
4321
|
+
function AvatarImage({
|
|
4322
|
+
className,
|
|
4323
|
+
...props
|
|
4324
|
+
}) {
|
|
4325
|
+
return /* @__PURE__ */ jsx(
|
|
4326
|
+
Avatar$1.Image,
|
|
4327
|
+
{
|
|
4328
|
+
"data-slot": "avatar-image",
|
|
4329
|
+
className: cn("aspect-square size-full", className),
|
|
4330
|
+
...props
|
|
4331
|
+
}
|
|
4332
|
+
);
|
|
4333
|
+
}
|
|
4334
|
+
function AvatarFallback({
|
|
4335
|
+
className,
|
|
4336
|
+
...props
|
|
4337
|
+
}) {
|
|
4338
|
+
return /* @__PURE__ */ jsx(
|
|
4339
|
+
Avatar$1.Fallback,
|
|
4340
|
+
{
|
|
4341
|
+
"data-slot": "avatar-fallback",
|
|
4342
|
+
className: cn(
|
|
4343
|
+
"bg-muted text-muted-foreground flex size-full items-center justify-center rounded-full text-sm group-data-[size=sm]/avatar:text-xs",
|
|
4344
|
+
className
|
|
4345
|
+
),
|
|
4346
|
+
...props
|
|
4347
|
+
}
|
|
4348
|
+
);
|
|
4349
|
+
}
|
|
4350
|
+
var init_avatar = __esm({
|
|
4351
|
+
"src/ui/avatar.tsx"() {
|
|
4352
|
+
init_utils2();
|
|
4353
|
+
}
|
|
4354
|
+
});
|
|
4303
4355
|
function Button({
|
|
4304
4356
|
className,
|
|
4305
4357
|
variant = "default",
|
|
@@ -4354,58 +4406,6 @@ var init_button = __esm({
|
|
|
4354
4406
|
);
|
|
4355
4407
|
}
|
|
4356
4408
|
});
|
|
4357
|
-
function Avatar({
|
|
4358
|
-
className,
|
|
4359
|
-
size = "default",
|
|
4360
|
-
...props
|
|
4361
|
-
}) {
|
|
4362
|
-
return /* @__PURE__ */ jsx(
|
|
4363
|
-
Avatar$1.Root,
|
|
4364
|
-
{
|
|
4365
|
-
"data-slot": "avatar",
|
|
4366
|
-
"data-size": size,
|
|
4367
|
-
className: cn(
|
|
4368
|
-
"group/avatar relative flex size-8 shrink-0 overflow-hidden rounded-full select-none data-[size=lg]:size-10 data-[size=sm]:size-6",
|
|
4369
|
-
className
|
|
4370
|
-
),
|
|
4371
|
-
...props
|
|
4372
|
-
}
|
|
4373
|
-
);
|
|
4374
|
-
}
|
|
4375
|
-
function AvatarImage({
|
|
4376
|
-
className,
|
|
4377
|
-
...props
|
|
4378
|
-
}) {
|
|
4379
|
-
return /* @__PURE__ */ jsx(
|
|
4380
|
-
Avatar$1.Image,
|
|
4381
|
-
{
|
|
4382
|
-
"data-slot": "avatar-image",
|
|
4383
|
-
className: cn("aspect-square size-full", className),
|
|
4384
|
-
...props
|
|
4385
|
-
}
|
|
4386
|
-
);
|
|
4387
|
-
}
|
|
4388
|
-
function AvatarFallback({
|
|
4389
|
-
className,
|
|
4390
|
-
...props
|
|
4391
|
-
}) {
|
|
4392
|
-
return /* @__PURE__ */ jsx(
|
|
4393
|
-
Avatar$1.Fallback,
|
|
4394
|
-
{
|
|
4395
|
-
"data-slot": "avatar-fallback",
|
|
4396
|
-
className: cn(
|
|
4397
|
-
"bg-muted text-muted-foreground flex size-full items-center justify-center rounded-full text-sm group-data-[size=sm]/avatar:text-xs",
|
|
4398
|
-
className
|
|
4399
|
-
),
|
|
4400
|
-
...props
|
|
4401
|
-
}
|
|
4402
|
-
);
|
|
4403
|
-
}
|
|
4404
|
-
var init_avatar = __esm({
|
|
4405
|
-
"src/ui/avatar.tsx"() {
|
|
4406
|
-
init_utils2();
|
|
4407
|
-
}
|
|
4408
|
-
});
|
|
4409
4409
|
|
|
4410
4410
|
// src/call/videosdk.loader.ts
|
|
4411
4411
|
var loadVideoSDK;
|
|
@@ -4441,6 +4441,7 @@ var init_ParticipantView = __esm({
|
|
|
4441
4441
|
const { webcamStream, micStream, webcamOn, micOn, displayName, isActiveSpeaker } = sdk.useParticipant(participantId);
|
|
4442
4442
|
const videoRef = useRef(null);
|
|
4443
4443
|
const audioRef = useRef(null);
|
|
4444
|
+
const [hasFrame, setHasFrame] = useState(false);
|
|
4444
4445
|
useEffect(() => {
|
|
4445
4446
|
const el = videoRef.current;
|
|
4446
4447
|
if (!el) return;
|
|
@@ -4449,6 +4450,7 @@ var init_ParticipantView = __esm({
|
|
|
4449
4450
|
el.play().catch(() => void 0);
|
|
4450
4451
|
} else {
|
|
4451
4452
|
el.srcObject = null;
|
|
4453
|
+
setHasFrame(false);
|
|
4452
4454
|
}
|
|
4453
4455
|
}, [webcamOn, webcamStream]);
|
|
4454
4456
|
useEffect(() => {
|
|
@@ -4463,6 +4465,7 @@ var init_ParticipantView = __esm({
|
|
|
4463
4465
|
}
|
|
4464
4466
|
}, [micOn, micStream, isLocal]);
|
|
4465
4467
|
const name = displayName || fallbackName || "Participant";
|
|
4468
|
+
const showVideo = webcamOn && hasFrame;
|
|
4466
4469
|
return /* @__PURE__ */ jsxs(
|
|
4467
4470
|
"div",
|
|
4468
4471
|
{
|
|
@@ -4478,14 +4481,15 @@ var init_ParticipantView = __esm({
|
|
|
4478
4481
|
ref: videoRef,
|
|
4479
4482
|
muted: isLocal,
|
|
4480
4483
|
playsInline: true,
|
|
4484
|
+
onPlaying: () => setHasFrame(true),
|
|
4481
4485
|
className: cn(
|
|
4482
4486
|
"size-full object-cover",
|
|
4483
|
-
|
|
4487
|
+
showVideo ? "block" : "hidden"
|
|
4484
4488
|
)
|
|
4485
4489
|
}
|
|
4486
4490
|
),
|
|
4487
4491
|
!isLocal && /* @__PURE__ */ jsx("audio", { ref: audioRef, autoPlay: true, playsInline: true }),
|
|
4488
|
-
!
|
|
4492
|
+
!showVideo && /* @__PURE__ */ jsxs(Avatar, { size: "lg", className: "size-20", children: [
|
|
4489
4493
|
/* @__PURE__ */ jsx(AvatarImage, { src: fallbackImage, alt: name }),
|
|
4490
4494
|
/* @__PURE__ */ jsx(AvatarFallback, { className: "bg-neutral-700 text-xl font-medium text-white", children: name.charAt(0).toUpperCase() })
|
|
4491
4495
|
] }),
|
|
@@ -4500,6 +4504,53 @@ var init_ParticipantView = __esm({
|
|
|
4500
4504
|
ParticipantView_default = ParticipantView;
|
|
4501
4505
|
}
|
|
4502
4506
|
});
|
|
4507
|
+
var AudioCallView, AudioCallView_default;
|
|
4508
|
+
var init_AudioCallView = __esm({
|
|
4509
|
+
"src/call/AudioCallView.tsx"() {
|
|
4510
|
+
init_avatar();
|
|
4511
|
+
init_utils2();
|
|
4512
|
+
AudioCallView = ({
|
|
4513
|
+
sdk,
|
|
4514
|
+
remoteParticipantId,
|
|
4515
|
+
peerName,
|
|
4516
|
+
peerAvatar
|
|
4517
|
+
}) => {
|
|
4518
|
+
const remote = remoteParticipantId ? sdk.useParticipant(remoteParticipantId) : null;
|
|
4519
|
+
const name = remote?.displayName || peerName || "In call";
|
|
4520
|
+
const isSpeaking = !!remote?.isActiveSpeaker && remote?.micOn;
|
|
4521
|
+
const isMuted = remote != null && !remote.micOn;
|
|
4522
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-6 p-6 text-center", children: [
|
|
4523
|
+
/* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-center", children: [
|
|
4524
|
+
/* @__PURE__ */ jsx(
|
|
4525
|
+
"span",
|
|
4526
|
+
{
|
|
4527
|
+
className: cn(
|
|
4528
|
+
"absolute inline-flex size-36 rounded-full bg-emerald-400/15 transition-opacity duration-300",
|
|
4529
|
+
isSpeaking ? "animate-ping opacity-100" : "opacity-0"
|
|
4530
|
+
)
|
|
4531
|
+
}
|
|
4532
|
+
),
|
|
4533
|
+
/* @__PURE__ */ jsxs(
|
|
4534
|
+
Avatar,
|
|
4535
|
+
{
|
|
4536
|
+
className: cn(
|
|
4537
|
+
"relative size-28 ring-4 transition-colors duration-300",
|
|
4538
|
+
isSpeaking ? "ring-emerald-400/80" : "ring-white/10"
|
|
4539
|
+
),
|
|
4540
|
+
children: [
|
|
4541
|
+
/* @__PURE__ */ jsx(AvatarImage, { src: peerAvatar, alt: name }),
|
|
4542
|
+
/* @__PURE__ */ jsx(AvatarFallback, { className: "bg-neutral-700 text-3xl font-medium text-white", children: name.charAt(0).toUpperCase() })
|
|
4543
|
+
]
|
|
4544
|
+
}
|
|
4545
|
+
),
|
|
4546
|
+
isMuted && /* @__PURE__ */ 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__ */ jsx(MicOff, { size: 16, className: "text-white/80" }) })
|
|
4547
|
+
] }),
|
|
4548
|
+
/* @__PURE__ */ jsx("p", { className: "text-xl font-semibold tracking-tight", children: name })
|
|
4549
|
+
] });
|
|
4550
|
+
};
|
|
4551
|
+
AudioCallView_default = AudioCallView;
|
|
4552
|
+
}
|
|
4553
|
+
});
|
|
4503
4554
|
var circleBtn, CallControls, CallControls_default;
|
|
4504
4555
|
var init_CallControls = __esm({
|
|
4505
4556
|
"src/call/CallControls.tsx"() {
|
|
@@ -4565,9 +4616,10 @@ var MeetingView, MeetingView_default;
|
|
|
4565
4616
|
var init_MeetingView = __esm({
|
|
4566
4617
|
"src/call/MeetingView.tsx"() {
|
|
4567
4618
|
init_ParticipantView();
|
|
4619
|
+
init_AudioCallView();
|
|
4568
4620
|
init_CallControls();
|
|
4569
4621
|
init_call_store();
|
|
4570
|
-
MeetingView = ({ sdk, mode }) => {
|
|
4622
|
+
MeetingView = ({ sdk, mode, peerName, peerAvatar }) => {
|
|
4571
4623
|
const endCall = useCallStore((s) => s.endCall);
|
|
4572
4624
|
const [hasJoined, setHasJoined] = useState(false);
|
|
4573
4625
|
const hasJoinedRef = useRef(false);
|
|
@@ -4590,7 +4642,23 @@ var init_MeetingView = __esm({
|
|
|
4590
4642
|
/* @__PURE__ */ jsx("p", { className: "text-sm", children: "Connecting\u2026" })
|
|
4591
4643
|
] });
|
|
4592
4644
|
}
|
|
4593
|
-
const remoteIds = Array.from(participants.keys())
|
|
4645
|
+
const remoteIds = Array.from(participants.keys()).filter(
|
|
4646
|
+
(id) => id !== localParticipant?.id
|
|
4647
|
+
);
|
|
4648
|
+
if (mode === "audio") {
|
|
4649
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col", children: [
|
|
4650
|
+
/* @__PURE__ */ jsx(
|
|
4651
|
+
AudioCallView_default,
|
|
4652
|
+
{
|
|
4653
|
+
sdk,
|
|
4654
|
+
remoteParticipantId: remoteIds[0],
|
|
4655
|
+
peerName,
|
|
4656
|
+
peerAvatar
|
|
4657
|
+
}
|
|
4658
|
+
),
|
|
4659
|
+
/* @__PURE__ */ jsx(CallControls_default, { sdk, mode })
|
|
4660
|
+
] });
|
|
4661
|
+
}
|
|
4594
4662
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col", children: [
|
|
4595
4663
|
/* @__PURE__ */ jsxs(
|
|
4596
4664
|
"div",
|
|
@@ -4604,7 +4672,16 @@ var init_MeetingView = __esm({
|
|
|
4604
4672
|
},
|
|
4605
4673
|
children: [
|
|
4606
4674
|
localParticipant?.id && /* @__PURE__ */ jsx(ParticipantView_default, { sdk, participantId: localParticipant.id, isLocal: true }),
|
|
4607
|
-
remoteIds.map((id) => /* @__PURE__ */ jsx(
|
|
4675
|
+
remoteIds.map((id) => /* @__PURE__ */ jsx(
|
|
4676
|
+
ParticipantView_default,
|
|
4677
|
+
{
|
|
4678
|
+
sdk,
|
|
4679
|
+
participantId: id,
|
|
4680
|
+
fallbackName: peerName,
|
|
4681
|
+
fallbackImage: peerAvatar
|
|
4682
|
+
},
|
|
4683
|
+
id
|
|
4684
|
+
))
|
|
4608
4685
|
]
|
|
4609
4686
|
}
|
|
4610
4687
|
),
|
|
@@ -4626,7 +4703,14 @@ var init_CallSession = __esm({
|
|
|
4626
4703
|
init_useStore();
|
|
4627
4704
|
init_videosdk_loader();
|
|
4628
4705
|
init_MeetingView();
|
|
4629
|
-
CallSession = ({
|
|
4706
|
+
CallSession = ({
|
|
4707
|
+
meetingId,
|
|
4708
|
+
token,
|
|
4709
|
+
mode,
|
|
4710
|
+
peerName,
|
|
4711
|
+
peerAvatar,
|
|
4712
|
+
onError
|
|
4713
|
+
}) => {
|
|
4630
4714
|
const [sdk, setSdk] = useState(null);
|
|
4631
4715
|
const userId = useStore((s) => s.loggedUserDetails?._id);
|
|
4632
4716
|
const userName = useStore((s) => s.loggedUserDetails?.name);
|
|
@@ -4667,7 +4751,7 @@ var init_CallSession = __esm({
|
|
|
4667
4751
|
token,
|
|
4668
4752
|
reinitialiseMeetingOnConfigChange: false,
|
|
4669
4753
|
joinWithoutUserInteraction: true,
|
|
4670
|
-
children: /* @__PURE__ */ jsx(MeetingView_default, { sdk, mode })
|
|
4754
|
+
children: /* @__PURE__ */ jsx(MeetingView_default, { sdk, mode, peerName, peerAvatar })
|
|
4671
4755
|
}
|
|
4672
4756
|
);
|
|
4673
4757
|
};
|
|
@@ -5619,6 +5703,167 @@ function useEffectiveSettingsOptional() {
|
|
|
5619
5703
|
};
|
|
5620
5704
|
}
|
|
5621
5705
|
|
|
5706
|
+
// src/call/CallOverlay.tsx
|
|
5707
|
+
init_avatar();
|
|
5708
|
+
init_button();
|
|
5709
|
+
init_call_store();
|
|
5710
|
+
|
|
5711
|
+
// src/call/useRingCountdown.ts
|
|
5712
|
+
init_call_types();
|
|
5713
|
+
var useRingCountdown = (active, callId) => {
|
|
5714
|
+
const [secondsLeft, setSecondsLeft] = useState(
|
|
5715
|
+
Math.ceil(CALL_RING_TIMEOUT_MS / 1e3)
|
|
5716
|
+
);
|
|
5717
|
+
useEffect(() => {
|
|
5718
|
+
if (!active) return;
|
|
5719
|
+
const startedAt = Date.now();
|
|
5720
|
+
setSecondsLeft(Math.ceil(CALL_RING_TIMEOUT_MS / 1e3));
|
|
5721
|
+
const id = setInterval(() => {
|
|
5722
|
+
const remainingMs = CALL_RING_TIMEOUT_MS - (Date.now() - startedAt);
|
|
5723
|
+
setSecondsLeft(Math.max(0, Math.ceil(remainingMs / 1e3)));
|
|
5724
|
+
}, 1e3);
|
|
5725
|
+
return () => clearInterval(id);
|
|
5726
|
+
}, [active, callId]);
|
|
5727
|
+
return secondsLeft;
|
|
5728
|
+
};
|
|
5729
|
+
var useCallDuration = (startedAt) => {
|
|
5730
|
+
const [elapsedMs, setElapsedMs] = useState(0);
|
|
5731
|
+
useEffect(() => {
|
|
5732
|
+
if (!startedAt) {
|
|
5733
|
+
setElapsedMs(0);
|
|
5734
|
+
return;
|
|
5735
|
+
}
|
|
5736
|
+
setElapsedMs(Date.now() - startedAt);
|
|
5737
|
+
const id = setInterval(() => setElapsedMs(Date.now() - startedAt), 1e3);
|
|
5738
|
+
return () => clearInterval(id);
|
|
5739
|
+
}, [startedAt]);
|
|
5740
|
+
const totalSeconds = Math.max(0, Math.floor(elapsedMs / 1e3));
|
|
5741
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
5742
|
+
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
5743
|
+
const seconds = totalSeconds % 60;
|
|
5744
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
5745
|
+
return hours > 0 ? `${hours}:${pad(minutes)}:${pad(seconds)}` : `${pad(minutes)}:${pad(seconds)}`;
|
|
5746
|
+
};
|
|
5747
|
+
var CallSession2 = React9__default.lazy(() => Promise.resolve().then(() => (init_CallSession(), CallSession_exports)));
|
|
5748
|
+
var CallOverlay = () => {
|
|
5749
|
+
const uiStatus = useCallStore((s) => s.uiStatus);
|
|
5750
|
+
const mode = useCallStore((s) => s.mode);
|
|
5751
|
+
const callId = useCallStore((s) => s.callId);
|
|
5752
|
+
const meetingId = useCallStore((s) => s.meetingId);
|
|
5753
|
+
const token = useCallStore((s) => s.token);
|
|
5754
|
+
const error = useCallStore((s) => s.error);
|
|
5755
|
+
const callee = useCallStore((s) => s.callee);
|
|
5756
|
+
const caller = useCallStore((s) => s.caller);
|
|
5757
|
+
const callStartedAt = useCallStore((s) => s.callStartedAt);
|
|
5758
|
+
const cancelCall = useCallStore((s) => s.cancelCall);
|
|
5759
|
+
const reset = useCallStore((s) => s.reset);
|
|
5760
|
+
const notifyServerCallFailed = useCallStore((s) => s.notifyServerCallFailed);
|
|
5761
|
+
const [sessionError, setSessionError] = useState(null);
|
|
5762
|
+
const secondsLeft = useRingCountdown(uiStatus === "ringing-out", callId);
|
|
5763
|
+
const duration = useCallDuration(callStartedAt);
|
|
5764
|
+
useEffect(() => {
|
|
5765
|
+
setSessionError(null);
|
|
5766
|
+
}, [callId]);
|
|
5767
|
+
useEffect(() => {
|
|
5768
|
+
if (sessionError) notifyServerCallFailed();
|
|
5769
|
+
}, [sessionError, notifyServerCallFailed]);
|
|
5770
|
+
const isOpen = uiStatus !== "idle" && uiStatus !== "incoming";
|
|
5771
|
+
if (!isOpen || typeof document === "undefined") return null;
|
|
5772
|
+
const displayError = error || sessionError;
|
|
5773
|
+
const peerName = callee?.name || caller?.name || "";
|
|
5774
|
+
const peerAvatar = callee?.avatar || caller?.profileImage || void 0;
|
|
5775
|
+
const isVideo = mode === "video";
|
|
5776
|
+
return createPortal(
|
|
5777
|
+
/* @__PURE__ */ jsx(
|
|
5778
|
+
"div",
|
|
5779
|
+
{
|
|
5780
|
+
style: {
|
|
5781
|
+
position: "fixed",
|
|
5782
|
+
inset: 0,
|
|
5783
|
+
width: "100vw",
|
|
5784
|
+
height: "100vh",
|
|
5785
|
+
zIndex: 2147483647
|
|
5786
|
+
},
|
|
5787
|
+
className: "flex flex-col overflow-hidden bg-gradient-to-b from-neutral-900 via-neutral-950 to-black text-white",
|
|
5788
|
+
children: displayError ? /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-4 p-6 text-center", children: [
|
|
5789
|
+
/* @__PURE__ */ jsx("p", { className: "max-w-sm text-sm text-white/80", children: displayError }),
|
|
5790
|
+
/* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: reset, children: [
|
|
5791
|
+
/* @__PURE__ */ jsx(X, { size: 16, className: "mr-1" }),
|
|
5792
|
+
" Close"
|
|
5793
|
+
] })
|
|
5794
|
+
] }) : uiStatus === "in-call" && meetingId && token && mode ? /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col", children: [
|
|
5795
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-2 px-4 py-3 text-sm text-white/70", children: [
|
|
5796
|
+
peerName && /* @__PURE__ */ jsx("span", { className: "font-medium text-white/90", children: peerName }),
|
|
5797
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "text-white/30", children: "\xB7" }),
|
|
5798
|
+
/* @__PURE__ */ jsx("span", { className: "tabular-nums", children: duration })
|
|
5799
|
+
] }),
|
|
5800
|
+
/* @__PURE__ */ jsx(
|
|
5801
|
+
React9__default.Suspense,
|
|
5802
|
+
{
|
|
5803
|
+
fallback: /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-3 text-white/80", children: [
|
|
5804
|
+
/* @__PURE__ */ jsx(Loader2, { className: "size-8 animate-spin" }),
|
|
5805
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm", children: "Loading call\u2026" })
|
|
5806
|
+
] }),
|
|
5807
|
+
children: /* @__PURE__ */ jsx(
|
|
5808
|
+
CallSession2,
|
|
5809
|
+
{
|
|
5810
|
+
meetingId,
|
|
5811
|
+
token,
|
|
5812
|
+
mode,
|
|
5813
|
+
peerName,
|
|
5814
|
+
peerAvatar,
|
|
5815
|
+
onError: setSessionError
|
|
5816
|
+
}
|
|
5817
|
+
)
|
|
5818
|
+
}
|
|
5819
|
+
)
|
|
5820
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-6 p-6 text-center", children: [
|
|
5821
|
+
/* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-center", children: [
|
|
5822
|
+
uiStatus === "ringing-out" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5823
|
+
/* @__PURE__ */ jsx("span", { className: "absolute inline-flex size-32 animate-ping rounded-full bg-white/10" }),
|
|
5824
|
+
/* @__PURE__ */ jsx(
|
|
5825
|
+
"span",
|
|
5826
|
+
{
|
|
5827
|
+
className: "absolute inline-flex size-32 animate-ping rounded-full bg-white/5",
|
|
5828
|
+
style: { animationDelay: "0.6s" }
|
|
5829
|
+
}
|
|
5830
|
+
)
|
|
5831
|
+
] }),
|
|
5832
|
+
peerName ? /* @__PURE__ */ jsxs(Avatar, { className: "relative size-28 ring-4 ring-white/10", children: [
|
|
5833
|
+
/* @__PURE__ */ jsx(AvatarImage, { src: peerAvatar, alt: peerName }),
|
|
5834
|
+
/* @__PURE__ */ jsx(AvatarFallback, { className: "bg-neutral-700 text-3xl font-medium text-white", children: peerName.charAt(0).toUpperCase() })
|
|
5835
|
+
] }) : /* @__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 }) })
|
|
5836
|
+
] }),
|
|
5837
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
5838
|
+
peerName && /* @__PURE__ */ jsx("p", { className: "text-xl font-semibold tracking-tight", children: peerName }),
|
|
5839
|
+
/* @__PURE__ */ jsxs("p", { className: "mt-1 text-sm text-white/60", children: [
|
|
5840
|
+
uiStatus === "creating" && "Starting call\u2026",
|
|
5841
|
+
uiStatus === "ringing-out" && `${isVideo ? "Video calling" : "Calling"}\u2026 \xB7 ${secondsLeft}s`,
|
|
5842
|
+
uiStatus === "joining" && "Connecting\u2026"
|
|
5843
|
+
] })
|
|
5844
|
+
] }),
|
|
5845
|
+
uiStatus === "ringing-out" && /* @__PURE__ */ jsxs("div", { className: "mt-1 flex flex-col items-center gap-2", children: [
|
|
5846
|
+
/* @__PURE__ */ jsx(
|
|
5847
|
+
Button,
|
|
5848
|
+
{
|
|
5849
|
+
variant: "ghost",
|
|
5850
|
+
size: "icon",
|
|
5851
|
+
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",
|
|
5852
|
+
"aria-label": "Cancel call",
|
|
5853
|
+
onClick: cancelCall,
|
|
5854
|
+
children: /* @__PURE__ */ jsx(PhoneOff, { size: 24 })
|
|
5855
|
+
}
|
|
5856
|
+
),
|
|
5857
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-white/60", children: "Cancel" })
|
|
5858
|
+
] })
|
|
5859
|
+
] })
|
|
5860
|
+
}
|
|
5861
|
+
),
|
|
5862
|
+
document.body
|
|
5863
|
+
);
|
|
5864
|
+
};
|
|
5865
|
+
var CallOverlay_default = CallOverlay;
|
|
5866
|
+
|
|
5622
5867
|
// src/ui/dialog.tsx
|
|
5623
5868
|
init_utils2();
|
|
5624
5869
|
function Dialog({
|
|
@@ -6157,161 +6402,7 @@ var ChatAlertDialogContent = ({
|
|
|
6157
6402
|
);
|
|
6158
6403
|
};
|
|
6159
6404
|
|
|
6160
|
-
// src/call/
|
|
6161
|
-
init_avatar();
|
|
6162
|
-
init_button();
|
|
6163
|
-
init_utils2();
|
|
6164
|
-
init_call_store();
|
|
6165
|
-
|
|
6166
|
-
// src/call/useRingCountdown.ts
|
|
6167
|
-
init_call_types();
|
|
6168
|
-
var useRingCountdown = (active, callId) => {
|
|
6169
|
-
const [secondsLeft, setSecondsLeft] = useState(
|
|
6170
|
-
Math.ceil(CALL_RING_TIMEOUT_MS / 1e3)
|
|
6171
|
-
);
|
|
6172
|
-
useEffect(() => {
|
|
6173
|
-
if (!active) return;
|
|
6174
|
-
const startedAt = Date.now();
|
|
6175
|
-
setSecondsLeft(Math.ceil(CALL_RING_TIMEOUT_MS / 1e3));
|
|
6176
|
-
const id = setInterval(() => {
|
|
6177
|
-
const remainingMs = CALL_RING_TIMEOUT_MS - (Date.now() - startedAt);
|
|
6178
|
-
setSecondsLeft(Math.max(0, Math.ceil(remainingMs / 1e3)));
|
|
6179
|
-
}, 1e3);
|
|
6180
|
-
return () => clearInterval(id);
|
|
6181
|
-
}, [active, callId]);
|
|
6182
|
-
return secondsLeft;
|
|
6183
|
-
};
|
|
6184
|
-
var useCallDuration = (startedAt) => {
|
|
6185
|
-
const [elapsedMs, setElapsedMs] = useState(0);
|
|
6186
|
-
useEffect(() => {
|
|
6187
|
-
if (!startedAt) {
|
|
6188
|
-
setElapsedMs(0);
|
|
6189
|
-
return;
|
|
6190
|
-
}
|
|
6191
|
-
setElapsedMs(Date.now() - startedAt);
|
|
6192
|
-
const id = setInterval(() => setElapsedMs(Date.now() - startedAt), 1e3);
|
|
6193
|
-
return () => clearInterval(id);
|
|
6194
|
-
}, [startedAt]);
|
|
6195
|
-
const totalSeconds = Math.max(0, Math.floor(elapsedMs / 1e3));
|
|
6196
|
-
const hours = Math.floor(totalSeconds / 3600);
|
|
6197
|
-
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
6198
|
-
const seconds = totalSeconds % 60;
|
|
6199
|
-
const pad = (n) => String(n).padStart(2, "0");
|
|
6200
|
-
return hours > 0 ? `${hours}:${pad(minutes)}:${pad(seconds)}` : `${pad(minutes)}:${pad(seconds)}`;
|
|
6201
|
-
};
|
|
6202
|
-
var CallSession2 = React9__default.lazy(() => Promise.resolve().then(() => (init_CallSession(), CallSession_exports)));
|
|
6203
|
-
var CallOverlay = () => {
|
|
6204
|
-
const uiStatus = useCallStore((s) => s.uiStatus);
|
|
6205
|
-
const mode = useCallStore((s) => s.mode);
|
|
6206
|
-
const callId = useCallStore((s) => s.callId);
|
|
6207
|
-
const meetingId = useCallStore((s) => s.meetingId);
|
|
6208
|
-
const token = useCallStore((s) => s.token);
|
|
6209
|
-
const error = useCallStore((s) => s.error);
|
|
6210
|
-
const callee = useCallStore((s) => s.callee);
|
|
6211
|
-
const caller = useCallStore((s) => s.caller);
|
|
6212
|
-
const callStartedAt = useCallStore((s) => s.callStartedAt);
|
|
6213
|
-
const cancelCall = useCallStore((s) => s.cancelCall);
|
|
6214
|
-
const reset = useCallStore((s) => s.reset);
|
|
6215
|
-
const notifyServerCallFailed = useCallStore((s) => s.notifyServerCallFailed);
|
|
6216
|
-
const [sessionError, setSessionError] = useState(null);
|
|
6217
|
-
const secondsLeft = useRingCountdown(uiStatus === "ringing-out", callId);
|
|
6218
|
-
const duration = useCallDuration(callStartedAt);
|
|
6219
|
-
useEffect(() => {
|
|
6220
|
-
setSessionError(null);
|
|
6221
|
-
}, [callId]);
|
|
6222
|
-
useEffect(() => {
|
|
6223
|
-
if (sessionError) notifyServerCallFailed();
|
|
6224
|
-
}, [sessionError, notifyServerCallFailed]);
|
|
6225
|
-
const isOpen = uiStatus !== "idle" && uiStatus !== "incoming";
|
|
6226
|
-
if (!isOpen) return null;
|
|
6227
|
-
const displayError = error || sessionError;
|
|
6228
|
-
const peerName = callee?.name || caller?.name || "";
|
|
6229
|
-
const peerAvatar = callee?.avatar || caller?.profileImage || void 0;
|
|
6230
|
-
const isVideo = mode === "video";
|
|
6231
|
-
return /* @__PURE__ */ jsx(Dialog, { open: isOpen, onOpenChange: () => void 0, children: /* @__PURE__ */ jsx(
|
|
6232
|
-
ChatDialogContent,
|
|
6233
|
-
{
|
|
6234
|
-
showCloseButton: false,
|
|
6235
|
-
onEscapeKeyDown: (e) => e.preventDefault(),
|
|
6236
|
-
onPointerDownOutside: (e) => e.preventDefault(),
|
|
6237
|
-
className: cn(
|
|
6238
|
-
"fixed inset-0 top-0 left-0 z-100 flex h-screen w-screen max-w-none",
|
|
6239
|
-
"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"
|
|
6240
|
-
),
|
|
6241
|
-
children: displayError ? /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-4 p-6 text-center", children: [
|
|
6242
|
-
/* @__PURE__ */ jsx("p", { className: "max-w-sm text-sm text-white/80", children: displayError }),
|
|
6243
|
-
/* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: reset, children: [
|
|
6244
|
-
/* @__PURE__ */ jsx(X, { size: 16, className: "mr-1" }),
|
|
6245
|
-
" Close"
|
|
6246
|
-
] })
|
|
6247
|
-
] }) : uiStatus === "in-call" && meetingId && token && mode ? /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col", children: [
|
|
6248
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-2 px-4 py-3 text-sm text-white/70", children: [
|
|
6249
|
-
peerName && /* @__PURE__ */ jsx("span", { className: "font-medium text-white/90", children: peerName }),
|
|
6250
|
-
/* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "text-white/30", children: "\xB7" }),
|
|
6251
|
-
/* @__PURE__ */ jsx("span", { className: "tabular-nums", children: duration })
|
|
6252
|
-
] }),
|
|
6253
|
-
/* @__PURE__ */ jsx(
|
|
6254
|
-
React9__default.Suspense,
|
|
6255
|
-
{
|
|
6256
|
-
fallback: /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-3 text-white/80", children: [
|
|
6257
|
-
/* @__PURE__ */ jsx(Loader2, { className: "size-8 animate-spin" }),
|
|
6258
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm", children: "Loading call\u2026" })
|
|
6259
|
-
] }),
|
|
6260
|
-
children: /* @__PURE__ */ jsx(
|
|
6261
|
-
CallSession2,
|
|
6262
|
-
{
|
|
6263
|
-
meetingId,
|
|
6264
|
-
token,
|
|
6265
|
-
mode,
|
|
6266
|
-
onError: setSessionError
|
|
6267
|
-
}
|
|
6268
|
-
)
|
|
6269
|
-
}
|
|
6270
|
-
)
|
|
6271
|
-
] }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-6 p-6 text-center", children: [
|
|
6272
|
-
/* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-center", children: [
|
|
6273
|
-
uiStatus === "ringing-out" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6274
|
-
/* @__PURE__ */ jsx("span", { className: "absolute inline-flex size-32 animate-ping rounded-full bg-white/10" }),
|
|
6275
|
-
/* @__PURE__ */ jsx(
|
|
6276
|
-
"span",
|
|
6277
|
-
{
|
|
6278
|
-
className: "absolute inline-flex size-32 animate-ping rounded-full bg-white/5",
|
|
6279
|
-
style: { animationDelay: "0.6s" }
|
|
6280
|
-
}
|
|
6281
|
-
)
|
|
6282
|
-
] }),
|
|
6283
|
-
peerName ? /* @__PURE__ */ jsxs(Avatar, { className: "relative size-28 ring-4 ring-white/10", children: [
|
|
6284
|
-
/* @__PURE__ */ jsx(AvatarImage, { src: peerAvatar, alt: peerName }),
|
|
6285
|
-
/* @__PURE__ */ jsx(AvatarFallback, { className: "bg-neutral-700 text-3xl font-medium text-white", children: peerName.charAt(0).toUpperCase() })
|
|
6286
|
-
] }) : /* @__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 }) })
|
|
6287
|
-
] }),
|
|
6288
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
6289
|
-
peerName && /* @__PURE__ */ jsx("p", { className: "text-xl font-semibold tracking-tight", children: peerName }),
|
|
6290
|
-
/* @__PURE__ */ jsxs("p", { className: "mt-1 text-sm text-white/60", children: [
|
|
6291
|
-
uiStatus === "creating" && "Starting call\u2026",
|
|
6292
|
-
uiStatus === "ringing-out" && `${isVideo ? "Video calling" : "Calling"}\u2026 \xB7 ${secondsLeft}s`,
|
|
6293
|
-
uiStatus === "joining" && "Connecting\u2026"
|
|
6294
|
-
] })
|
|
6295
|
-
] }),
|
|
6296
|
-
uiStatus === "ringing-out" && /* @__PURE__ */ jsxs("div", { className: "mt-1 flex flex-col items-center gap-2", children: [
|
|
6297
|
-
/* @__PURE__ */ jsx(
|
|
6298
|
-
Button,
|
|
6299
|
-
{
|
|
6300
|
-
variant: "ghost",
|
|
6301
|
-
size: "icon",
|
|
6302
|
-
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",
|
|
6303
|
-
"aria-label": "Cancel call",
|
|
6304
|
-
onClick: cancelCall,
|
|
6305
|
-
children: /* @__PURE__ */ jsx(PhoneOff, { size: 24 })
|
|
6306
|
-
}
|
|
6307
|
-
),
|
|
6308
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-white/60", children: "Cancel" })
|
|
6309
|
-
] })
|
|
6310
|
-
] })
|
|
6311
|
-
}
|
|
6312
|
-
) });
|
|
6313
|
-
};
|
|
6314
|
-
var CallOverlay_default = CallOverlay;
|
|
6405
|
+
// src/call/IncomingCallDialog.tsx
|
|
6315
6406
|
init_avatar();
|
|
6316
6407
|
init_button();
|
|
6317
6408
|
init_utils2();
|
|
@@ -6878,18 +6969,6 @@ var installNotificationClickBridge = (options = {}) => {
|
|
|
6878
6969
|
};
|
|
6879
6970
|
|
|
6880
6971
|
// src/hooks/useChatController.ts
|
|
6881
|
-
init_call_types();
|
|
6882
|
-
function formatCallLogText(entry) {
|
|
6883
|
-
const label = entry.mode === "video" ? "video" : "voice";
|
|
6884
|
-
if (entry.outcome === "missed") return `Missed ${label} call`;
|
|
6885
|
-
if (entry.outcome === "declined") return `${label === "video" ? "Video" : "Voice"} call declined`;
|
|
6886
|
-
if (entry.outcome === "busy") return `${label === "video" ? "Video" : "Voice"} call \xB7 not answered`;
|
|
6887
|
-
const totalSeconds = Math.max(0, Math.floor(entry.durationSeconds));
|
|
6888
|
-
const minutes = Math.floor(totalSeconds / 60);
|
|
6889
|
-
const seconds = totalSeconds % 60;
|
|
6890
|
-
const duration = `${minutes}:${String(seconds).padStart(2, "0")}`;
|
|
6891
|
-
return `${label === "video" ? "Video" : "Voice"} call \xB7 ${duration}`;
|
|
6892
|
-
}
|
|
6893
6972
|
function resolveMessageType(content, attachments) {
|
|
6894
6973
|
if (attachments.length === 0) return "text";
|
|
6895
6974
|
if (!content.trim() && attachments.length === 1) {
|
|
@@ -6947,28 +7026,6 @@ var useChatController = () => {
|
|
|
6947
7026
|
);
|
|
6948
7027
|
}, []);
|
|
6949
7028
|
const { localMessages, setLocalMessages } = useChatSync();
|
|
6950
|
-
useEffect(() => {
|
|
6951
|
-
const handleCallLog = (event) => {
|
|
6952
|
-
const entry = event.detail;
|
|
6953
|
-
if (!entry?.conversationId) return;
|
|
6954
|
-
const logMessage = {
|
|
6955
|
-
id: `call-log-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
6956
|
-
content: formatCallLogText(entry),
|
|
6957
|
-
sender: "system",
|
|
6958
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6959
|
-
isOwnMessage: false,
|
|
6960
|
-
isSystemMessage: true,
|
|
6961
|
-
channelId: entry.conversationId,
|
|
6962
|
-
conversationId: entry.conversationId
|
|
6963
|
-
};
|
|
6964
|
-
setLocalMessages((prev) => ({
|
|
6965
|
-
...prev,
|
|
6966
|
-
[entry.conversationId]: [...prev[entry.conversationId] || [], logMessage]
|
|
6967
|
-
}));
|
|
6968
|
-
};
|
|
6969
|
-
window.addEventListener(CALL_LOG_EVENT, handleCallLog);
|
|
6970
|
-
return () => window.removeEventListener(CALL_LOG_EVENT, handleCallLog);
|
|
6971
|
-
}, [setLocalMessages]);
|
|
6972
7029
|
const emitDmSend = useStore((s) => s.emitDmSend);
|
|
6973
7030
|
const emitGroupMessageSend2 = useStore((s) => s.emitGroupMessageSend);
|
|
6974
7031
|
const emitMarkAsRead = useStore((s) => s.emitMarkAsRead);
|