@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.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);
|
|
@@ -789,6 +782,12 @@ var init_call_store = __esm({
|
|
|
789
782
|
clearRingTimer();
|
|
790
783
|
set({ ...idleState });
|
|
791
784
|
},
|
|
785
|
+
notifyServerCallFailed: () => {
|
|
786
|
+
const { callId } = get();
|
|
787
|
+
if (callId) {
|
|
788
|
+
socket_service_default.emitCallEnd({ callId });
|
|
789
|
+
}
|
|
790
|
+
},
|
|
792
791
|
_receiveIncoming: (payload) => {
|
|
793
792
|
const currentStatus = get().uiStatus;
|
|
794
793
|
if (currentStatus !== "idle") {
|
|
@@ -837,53 +836,60 @@ var init_call_store = __esm({
|
|
|
837
836
|
}));
|
|
838
837
|
},
|
|
839
838
|
_receiveCancelled: (payload) => {
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
outcome: "missed",
|
|
848
|
-
durationSeconds: 0
|
|
849
|
-
});
|
|
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;
|
|
850
846
|
}
|
|
847
|
+
clearRingTimer();
|
|
851
848
|
set({ ...idleState });
|
|
852
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.
|
|
853
855
|
_receiveEnded: (payload) => {
|
|
854
856
|
if (get().callId !== payload.callId) return;
|
|
855
857
|
clearRingTimer();
|
|
856
|
-
emitCallLog({
|
|
857
|
-
conversationId: payload.conversationId,
|
|
858
|
-
mode: payload.mode,
|
|
859
|
-
outcome: payload.durationSeconds > 0 ? "completed" : "declined",
|
|
860
|
-
durationSeconds: payload.durationSeconds
|
|
861
|
-
});
|
|
862
858
|
set({ ...idleState });
|
|
863
859
|
},
|
|
864
860
|
_receiveBusy: (payload) => {
|
|
865
|
-
|
|
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
|
+
}
|
|
866
869
|
clearRingTimer();
|
|
867
|
-
emitCallLog({
|
|
868
|
-
conversationId: payload.conversationId,
|
|
869
|
-
mode: payload.mode,
|
|
870
|
-
outcome: "busy",
|
|
871
|
-
durationSeconds: 0
|
|
872
|
-
});
|
|
873
870
|
set({ ...idleState, error: "That user is already on another call." });
|
|
874
871
|
},
|
|
875
872
|
// Guarded by callId like every other _receive* handler — a late/stale
|
|
876
873
|
// call_missed for a call that has already ended (accepted, rejected,
|
|
877
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.
|
|
878
883
|
_receiveMissed: (payload) => {
|
|
879
|
-
|
|
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
|
+
}
|
|
880
892
|
clearRingTimer();
|
|
881
|
-
emitCallLog({
|
|
882
|
-
conversationId: payload.conversationId,
|
|
883
|
-
mode: payload.mode,
|
|
884
|
-
outcome: "missed",
|
|
885
|
-
durationSeconds: 0
|
|
886
|
-
});
|
|
887
893
|
set({ ...idleState });
|
|
888
894
|
}
|
|
889
895
|
}));
|
|
@@ -4294,6 +4300,58 @@ var init_utils2 = __esm({
|
|
|
4294
4300
|
"src/lib/utils.ts"() {
|
|
4295
4301
|
}
|
|
4296
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
|
+
});
|
|
4297
4355
|
function Button({
|
|
4298
4356
|
className,
|
|
4299
4357
|
variant = "default",
|
|
@@ -4348,58 +4406,6 @@ var init_button = __esm({
|
|
|
4348
4406
|
);
|
|
4349
4407
|
}
|
|
4350
4408
|
});
|
|
4351
|
-
function Avatar({
|
|
4352
|
-
className,
|
|
4353
|
-
size = "default",
|
|
4354
|
-
...props
|
|
4355
|
-
}) {
|
|
4356
|
-
return /* @__PURE__ */ jsx(
|
|
4357
|
-
Avatar$1.Root,
|
|
4358
|
-
{
|
|
4359
|
-
"data-slot": "avatar",
|
|
4360
|
-
"data-size": size,
|
|
4361
|
-
className: cn(
|
|
4362
|
-
"group/avatar relative flex size-8 shrink-0 overflow-hidden rounded-full select-none data-[size=lg]:size-10 data-[size=sm]:size-6",
|
|
4363
|
-
className
|
|
4364
|
-
),
|
|
4365
|
-
...props
|
|
4366
|
-
}
|
|
4367
|
-
);
|
|
4368
|
-
}
|
|
4369
|
-
function AvatarImage({
|
|
4370
|
-
className,
|
|
4371
|
-
...props
|
|
4372
|
-
}) {
|
|
4373
|
-
return /* @__PURE__ */ jsx(
|
|
4374
|
-
Avatar$1.Image,
|
|
4375
|
-
{
|
|
4376
|
-
"data-slot": "avatar-image",
|
|
4377
|
-
className: cn("aspect-square size-full", className),
|
|
4378
|
-
...props
|
|
4379
|
-
}
|
|
4380
|
-
);
|
|
4381
|
-
}
|
|
4382
|
-
function AvatarFallback({
|
|
4383
|
-
className,
|
|
4384
|
-
...props
|
|
4385
|
-
}) {
|
|
4386
|
-
return /* @__PURE__ */ jsx(
|
|
4387
|
-
Avatar$1.Fallback,
|
|
4388
|
-
{
|
|
4389
|
-
"data-slot": "avatar-fallback",
|
|
4390
|
-
className: cn(
|
|
4391
|
-
"bg-muted text-muted-foreground flex size-full items-center justify-center rounded-full text-sm group-data-[size=sm]/avatar:text-xs",
|
|
4392
|
-
className
|
|
4393
|
-
),
|
|
4394
|
-
...props
|
|
4395
|
-
}
|
|
4396
|
-
);
|
|
4397
|
-
}
|
|
4398
|
-
var init_avatar = __esm({
|
|
4399
|
-
"src/ui/avatar.tsx"() {
|
|
4400
|
-
init_utils2();
|
|
4401
|
-
}
|
|
4402
|
-
});
|
|
4403
4409
|
|
|
4404
4410
|
// src/call/videosdk.loader.ts
|
|
4405
4411
|
var loadVideoSDK;
|
|
@@ -4435,6 +4441,7 @@ var init_ParticipantView = __esm({
|
|
|
4435
4441
|
const { webcamStream, micStream, webcamOn, micOn, displayName, isActiveSpeaker } = sdk.useParticipant(participantId);
|
|
4436
4442
|
const videoRef = useRef(null);
|
|
4437
4443
|
const audioRef = useRef(null);
|
|
4444
|
+
const [hasFrame, setHasFrame] = useState(false);
|
|
4438
4445
|
useEffect(() => {
|
|
4439
4446
|
const el = videoRef.current;
|
|
4440
4447
|
if (!el) return;
|
|
@@ -4443,6 +4450,7 @@ var init_ParticipantView = __esm({
|
|
|
4443
4450
|
el.play().catch(() => void 0);
|
|
4444
4451
|
} else {
|
|
4445
4452
|
el.srcObject = null;
|
|
4453
|
+
setHasFrame(false);
|
|
4446
4454
|
}
|
|
4447
4455
|
}, [webcamOn, webcamStream]);
|
|
4448
4456
|
useEffect(() => {
|
|
@@ -4457,6 +4465,7 @@ var init_ParticipantView = __esm({
|
|
|
4457
4465
|
}
|
|
4458
4466
|
}, [micOn, micStream, isLocal]);
|
|
4459
4467
|
const name = displayName || fallbackName || "Participant";
|
|
4468
|
+
const showVideo = webcamOn && hasFrame;
|
|
4460
4469
|
return /* @__PURE__ */ jsxs(
|
|
4461
4470
|
"div",
|
|
4462
4471
|
{
|
|
@@ -4472,14 +4481,15 @@ var init_ParticipantView = __esm({
|
|
|
4472
4481
|
ref: videoRef,
|
|
4473
4482
|
muted: isLocal,
|
|
4474
4483
|
playsInline: true,
|
|
4484
|
+
onPlaying: () => setHasFrame(true),
|
|
4475
4485
|
className: cn(
|
|
4476
4486
|
"size-full object-cover",
|
|
4477
|
-
|
|
4487
|
+
showVideo ? "block" : "hidden"
|
|
4478
4488
|
)
|
|
4479
4489
|
}
|
|
4480
4490
|
),
|
|
4481
4491
|
!isLocal && /* @__PURE__ */ jsx("audio", { ref: audioRef, autoPlay: true, playsInline: true }),
|
|
4482
|
-
!
|
|
4492
|
+
!showVideo && /* @__PURE__ */ jsxs(Avatar, { size: "lg", className: "size-20", children: [
|
|
4483
4493
|
/* @__PURE__ */ jsx(AvatarImage, { src: fallbackImage, alt: name }),
|
|
4484
4494
|
/* @__PURE__ */ jsx(AvatarFallback, { className: "bg-neutral-700 text-xl font-medium text-white", children: name.charAt(0).toUpperCase() })
|
|
4485
4495
|
] }),
|
|
@@ -4494,6 +4504,53 @@ var init_ParticipantView = __esm({
|
|
|
4494
4504
|
ParticipantView_default = ParticipantView;
|
|
4495
4505
|
}
|
|
4496
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
|
+
});
|
|
4497
4554
|
var circleBtn, CallControls, CallControls_default;
|
|
4498
4555
|
var init_CallControls = __esm({
|
|
4499
4556
|
"src/call/CallControls.tsx"() {
|
|
@@ -4559,9 +4616,10 @@ var MeetingView, MeetingView_default;
|
|
|
4559
4616
|
var init_MeetingView = __esm({
|
|
4560
4617
|
"src/call/MeetingView.tsx"() {
|
|
4561
4618
|
init_ParticipantView();
|
|
4619
|
+
init_AudioCallView();
|
|
4562
4620
|
init_CallControls();
|
|
4563
4621
|
init_call_store();
|
|
4564
|
-
MeetingView = ({ sdk, mode }) => {
|
|
4622
|
+
MeetingView = ({ sdk, mode, peerName, peerAvatar }) => {
|
|
4565
4623
|
const endCall = useCallStore((s) => s.endCall);
|
|
4566
4624
|
const [hasJoined, setHasJoined] = useState(false);
|
|
4567
4625
|
const hasJoinedRef = useRef(false);
|
|
@@ -4584,7 +4642,23 @@ var init_MeetingView = __esm({
|
|
|
4584
4642
|
/* @__PURE__ */ jsx("p", { className: "text-sm", children: "Connecting\u2026" })
|
|
4585
4643
|
] });
|
|
4586
4644
|
}
|
|
4587
|
-
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
|
+
}
|
|
4588
4662
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col", children: [
|
|
4589
4663
|
/* @__PURE__ */ jsxs(
|
|
4590
4664
|
"div",
|
|
@@ -4598,7 +4672,16 @@ var init_MeetingView = __esm({
|
|
|
4598
4672
|
},
|
|
4599
4673
|
children: [
|
|
4600
4674
|
localParticipant?.id && /* @__PURE__ */ jsx(ParticipantView_default, { sdk, participantId: localParticipant.id, isLocal: true }),
|
|
4601
|
-
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
|
+
))
|
|
4602
4685
|
]
|
|
4603
4686
|
}
|
|
4604
4687
|
),
|
|
@@ -4620,7 +4703,14 @@ var init_CallSession = __esm({
|
|
|
4620
4703
|
init_useStore();
|
|
4621
4704
|
init_videosdk_loader();
|
|
4622
4705
|
init_MeetingView();
|
|
4623
|
-
CallSession = ({
|
|
4706
|
+
CallSession = ({
|
|
4707
|
+
meetingId,
|
|
4708
|
+
token,
|
|
4709
|
+
mode,
|
|
4710
|
+
peerName,
|
|
4711
|
+
peerAvatar,
|
|
4712
|
+
onError
|
|
4713
|
+
}) => {
|
|
4624
4714
|
const [sdk, setSdk] = useState(null);
|
|
4625
4715
|
const userId = useStore((s) => s.loggedUserDetails?._id);
|
|
4626
4716
|
const userName = useStore((s) => s.loggedUserDetails?.name);
|
|
@@ -4661,7 +4751,7 @@ var init_CallSession = __esm({
|
|
|
4661
4751
|
token,
|
|
4662
4752
|
reinitialiseMeetingOnConfigChange: false,
|
|
4663
4753
|
joinWithoutUserInteraction: true,
|
|
4664
|
-
children: /* @__PURE__ */ jsx(MeetingView_default, { sdk, mode })
|
|
4754
|
+
children: /* @__PURE__ */ jsx(MeetingView_default, { sdk, mode, peerName, peerAvatar })
|
|
4665
4755
|
}
|
|
4666
4756
|
);
|
|
4667
4757
|
};
|
|
@@ -5613,6 +5703,167 @@ function useEffectiveSettingsOptional() {
|
|
|
5613
5703
|
};
|
|
5614
5704
|
}
|
|
5615
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
|
+
|
|
5616
5867
|
// src/ui/dialog.tsx
|
|
5617
5868
|
init_utils2();
|
|
5618
5869
|
function Dialog({
|
|
@@ -6151,154 +6402,7 @@ var ChatAlertDialogContent = ({
|
|
|
6151
6402
|
);
|
|
6152
6403
|
};
|
|
6153
6404
|
|
|
6154
|
-
// src/call/
|
|
6155
|
-
init_avatar();
|
|
6156
|
-
init_button();
|
|
6157
|
-
init_utils2();
|
|
6158
|
-
init_call_store();
|
|
6159
|
-
|
|
6160
|
-
// src/call/useRingCountdown.ts
|
|
6161
|
-
init_call_types();
|
|
6162
|
-
var useRingCountdown = (active, callId) => {
|
|
6163
|
-
const [secondsLeft, setSecondsLeft] = useState(
|
|
6164
|
-
Math.ceil(CALL_RING_TIMEOUT_MS / 1e3)
|
|
6165
|
-
);
|
|
6166
|
-
useEffect(() => {
|
|
6167
|
-
if (!active) return;
|
|
6168
|
-
const startedAt = Date.now();
|
|
6169
|
-
setSecondsLeft(Math.ceil(CALL_RING_TIMEOUT_MS / 1e3));
|
|
6170
|
-
const id = setInterval(() => {
|
|
6171
|
-
const remainingMs = CALL_RING_TIMEOUT_MS - (Date.now() - startedAt);
|
|
6172
|
-
setSecondsLeft(Math.max(0, Math.ceil(remainingMs / 1e3)));
|
|
6173
|
-
}, 1e3);
|
|
6174
|
-
return () => clearInterval(id);
|
|
6175
|
-
}, [active, callId]);
|
|
6176
|
-
return secondsLeft;
|
|
6177
|
-
};
|
|
6178
|
-
var useCallDuration = (startedAt) => {
|
|
6179
|
-
const [elapsedMs, setElapsedMs] = useState(0);
|
|
6180
|
-
useEffect(() => {
|
|
6181
|
-
if (!startedAt) {
|
|
6182
|
-
setElapsedMs(0);
|
|
6183
|
-
return;
|
|
6184
|
-
}
|
|
6185
|
-
setElapsedMs(Date.now() - startedAt);
|
|
6186
|
-
const id = setInterval(() => setElapsedMs(Date.now() - startedAt), 1e3);
|
|
6187
|
-
return () => clearInterval(id);
|
|
6188
|
-
}, [startedAt]);
|
|
6189
|
-
const totalSeconds = Math.max(0, Math.floor(elapsedMs / 1e3));
|
|
6190
|
-
const hours = Math.floor(totalSeconds / 3600);
|
|
6191
|
-
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
6192
|
-
const seconds = totalSeconds % 60;
|
|
6193
|
-
const pad = (n) => String(n).padStart(2, "0");
|
|
6194
|
-
return hours > 0 ? `${hours}:${pad(minutes)}:${pad(seconds)}` : `${pad(minutes)}:${pad(seconds)}`;
|
|
6195
|
-
};
|
|
6196
|
-
var CallSession2 = React9__default.lazy(() => Promise.resolve().then(() => (init_CallSession(), CallSession_exports)));
|
|
6197
|
-
var CallOverlay = () => {
|
|
6198
|
-
const uiStatus = useCallStore((s) => s.uiStatus);
|
|
6199
|
-
const mode = useCallStore((s) => s.mode);
|
|
6200
|
-
const callId = useCallStore((s) => s.callId);
|
|
6201
|
-
const meetingId = useCallStore((s) => s.meetingId);
|
|
6202
|
-
const token = useCallStore((s) => s.token);
|
|
6203
|
-
const error = useCallStore((s) => s.error);
|
|
6204
|
-
const callee = useCallStore((s) => s.callee);
|
|
6205
|
-
const caller = useCallStore((s) => s.caller);
|
|
6206
|
-
const callStartedAt = useCallStore((s) => s.callStartedAt);
|
|
6207
|
-
const cancelCall = useCallStore((s) => s.cancelCall);
|
|
6208
|
-
const reset = useCallStore((s) => s.reset);
|
|
6209
|
-
const [sessionError, setSessionError] = useState(null);
|
|
6210
|
-
const secondsLeft = useRingCountdown(uiStatus === "ringing-out", callId);
|
|
6211
|
-
const duration = useCallDuration(callStartedAt);
|
|
6212
|
-
const isOpen = uiStatus !== "idle" && uiStatus !== "incoming";
|
|
6213
|
-
if (!isOpen) return null;
|
|
6214
|
-
const displayError = error || sessionError;
|
|
6215
|
-
const peerName = callee?.name || caller?.name || "";
|
|
6216
|
-
const peerAvatar = callee?.avatar || caller?.profileImage || void 0;
|
|
6217
|
-
const isVideo = mode === "video";
|
|
6218
|
-
return /* @__PURE__ */ jsx(Dialog, { open: isOpen, onOpenChange: () => void 0, children: /* @__PURE__ */ jsx(
|
|
6219
|
-
ChatDialogContent,
|
|
6220
|
-
{
|
|
6221
|
-
showCloseButton: false,
|
|
6222
|
-
onEscapeKeyDown: (e) => e.preventDefault(),
|
|
6223
|
-
onPointerDownOutside: (e) => e.preventDefault(),
|
|
6224
|
-
className: cn(
|
|
6225
|
-
"fixed inset-0 top-0 left-0 z-100 flex h-screen w-screen max-w-none",
|
|
6226
|
-
"translate-x-0 translate-y-0 flex-col rounded-none border-0 bg-gradient-to-b from-neutral-900 via-neutral-950 to-black p-0 text-white"
|
|
6227
|
-
),
|
|
6228
|
-
children: displayError ? /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-4 p-6 text-center", children: [
|
|
6229
|
-
/* @__PURE__ */ jsx("p", { className: "max-w-sm text-sm text-white/80", children: displayError }),
|
|
6230
|
-
/* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: reset, children: [
|
|
6231
|
-
/* @__PURE__ */ jsx(X, { size: 16, className: "mr-1" }),
|
|
6232
|
-
" Close"
|
|
6233
|
-
] })
|
|
6234
|
-
] }) : uiStatus === "in-call" && meetingId && token && mode ? /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col", children: [
|
|
6235
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-2 px-4 py-3 text-sm text-white/70", children: [
|
|
6236
|
-
peerName && /* @__PURE__ */ jsx("span", { className: "font-medium text-white/90", children: peerName }),
|
|
6237
|
-
/* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "text-white/30", children: "\xB7" }),
|
|
6238
|
-
/* @__PURE__ */ jsx("span", { className: "tabular-nums", children: duration })
|
|
6239
|
-
] }),
|
|
6240
|
-
/* @__PURE__ */ jsx(
|
|
6241
|
-
React9__default.Suspense,
|
|
6242
|
-
{
|
|
6243
|
-
fallback: /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-3 text-white/80", children: [
|
|
6244
|
-
/* @__PURE__ */ jsx(Loader2, { className: "size-8 animate-spin" }),
|
|
6245
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm", children: "Loading call\u2026" })
|
|
6246
|
-
] }),
|
|
6247
|
-
children: /* @__PURE__ */ jsx(
|
|
6248
|
-
CallSession2,
|
|
6249
|
-
{
|
|
6250
|
-
meetingId,
|
|
6251
|
-
token,
|
|
6252
|
-
mode,
|
|
6253
|
-
onError: setSessionError
|
|
6254
|
-
}
|
|
6255
|
-
)
|
|
6256
|
-
}
|
|
6257
|
-
)
|
|
6258
|
-
] }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-6 p-6 text-center", children: [
|
|
6259
|
-
/* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-center", children: [
|
|
6260
|
-
uiStatus === "ringing-out" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6261
|
-
/* @__PURE__ */ jsx("span", { className: "absolute inline-flex size-32 animate-ping rounded-full bg-white/10" }),
|
|
6262
|
-
/* @__PURE__ */ jsx(
|
|
6263
|
-
"span",
|
|
6264
|
-
{
|
|
6265
|
-
className: "absolute inline-flex size-32 animate-ping rounded-full bg-white/5",
|
|
6266
|
-
style: { animationDelay: "0.6s" }
|
|
6267
|
-
}
|
|
6268
|
-
)
|
|
6269
|
-
] }),
|
|
6270
|
-
peerName ? /* @__PURE__ */ jsxs(Avatar, { className: "relative size-28 ring-4 ring-white/10", children: [
|
|
6271
|
-
/* @__PURE__ */ jsx(AvatarImage, { src: peerAvatar, alt: peerName }),
|
|
6272
|
-
/* @__PURE__ */ jsx(AvatarFallback, { className: "bg-neutral-700 text-3xl font-medium text-white", children: peerName.charAt(0).toUpperCase() })
|
|
6273
|
-
] }) : /* @__PURE__ */ jsx("div", { className: "relative flex size-28 items-center justify-center rounded-full bg-white/10", children: isVideo ? /* @__PURE__ */ jsx(Video, { size: 36 }) : /* @__PURE__ */ jsx(Phone, { size: 36 }) })
|
|
6274
|
-
] }),
|
|
6275
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
6276
|
-
peerName && /* @__PURE__ */ jsx("p", { className: "text-xl font-semibold tracking-tight", children: peerName }),
|
|
6277
|
-
/* @__PURE__ */ jsxs("p", { className: "mt-1 text-sm text-white/60", children: [
|
|
6278
|
-
uiStatus === "creating" && "Starting call\u2026",
|
|
6279
|
-
uiStatus === "ringing-out" && `${isVideo ? "Video calling" : "Calling"}\u2026 \xB7 ${secondsLeft}s`,
|
|
6280
|
-
uiStatus === "joining" && "Connecting\u2026"
|
|
6281
|
-
] })
|
|
6282
|
-
] }),
|
|
6283
|
-
uiStatus === "ringing-out" && /* @__PURE__ */ jsxs("div", { className: "mt-1 flex flex-col items-center gap-2", children: [
|
|
6284
|
-
/* @__PURE__ */ jsx(
|
|
6285
|
-
Button,
|
|
6286
|
-
{
|
|
6287
|
-
variant: "ghost",
|
|
6288
|
-
size: "icon",
|
|
6289
|
-
className: "size-16 rounded-full bg-red-600 text-white shadow-lg shadow-red-600/30 transition-transform hover:scale-105 hover:bg-red-500 active:scale-95",
|
|
6290
|
-
"aria-label": "Cancel call",
|
|
6291
|
-
onClick: cancelCall,
|
|
6292
|
-
children: /* @__PURE__ */ jsx(PhoneOff, { size: 24 })
|
|
6293
|
-
}
|
|
6294
|
-
),
|
|
6295
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-white/60", children: "Cancel" })
|
|
6296
|
-
] })
|
|
6297
|
-
] })
|
|
6298
|
-
}
|
|
6299
|
-
) });
|
|
6300
|
-
};
|
|
6301
|
-
var CallOverlay_default = CallOverlay;
|
|
6405
|
+
// src/call/IncomingCallDialog.tsx
|
|
6302
6406
|
init_avatar();
|
|
6303
6407
|
init_button();
|
|
6304
6408
|
init_utils2();
|
|
@@ -6865,18 +6969,6 @@ var installNotificationClickBridge = (options = {}) => {
|
|
|
6865
6969
|
};
|
|
6866
6970
|
|
|
6867
6971
|
// src/hooks/useChatController.ts
|
|
6868
|
-
init_call_types();
|
|
6869
|
-
function formatCallLogText(entry) {
|
|
6870
|
-
const label = entry.mode === "video" ? "video" : "voice";
|
|
6871
|
-
if (entry.outcome === "missed") return `Missed ${label} call`;
|
|
6872
|
-
if (entry.outcome === "declined") return `${label === "video" ? "Video" : "Voice"} call declined`;
|
|
6873
|
-
if (entry.outcome === "busy") return `${label === "video" ? "Video" : "Voice"} call \xB7 not answered`;
|
|
6874
|
-
const totalSeconds = Math.max(0, Math.floor(entry.durationSeconds));
|
|
6875
|
-
const minutes = Math.floor(totalSeconds / 60);
|
|
6876
|
-
const seconds = totalSeconds % 60;
|
|
6877
|
-
const duration = `${minutes}:${String(seconds).padStart(2, "0")}`;
|
|
6878
|
-
return `${label === "video" ? "Video" : "Voice"} call \xB7 ${duration}`;
|
|
6879
|
-
}
|
|
6880
6972
|
function resolveMessageType(content, attachments) {
|
|
6881
6973
|
if (attachments.length === 0) return "text";
|
|
6882
6974
|
if (!content.trim() && attachments.length === 1) {
|
|
@@ -6934,28 +7026,6 @@ var useChatController = () => {
|
|
|
6934
7026
|
);
|
|
6935
7027
|
}, []);
|
|
6936
7028
|
const { localMessages, setLocalMessages } = useChatSync();
|
|
6937
|
-
useEffect(() => {
|
|
6938
|
-
const handleCallLog = (event) => {
|
|
6939
|
-
const entry = event.detail;
|
|
6940
|
-
if (!entry?.conversationId) return;
|
|
6941
|
-
const logMessage = {
|
|
6942
|
-
id: `call-log-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
6943
|
-
content: formatCallLogText(entry),
|
|
6944
|
-
sender: "system",
|
|
6945
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6946
|
-
isOwnMessage: false,
|
|
6947
|
-
isSystemMessage: true,
|
|
6948
|
-
channelId: entry.conversationId,
|
|
6949
|
-
conversationId: entry.conversationId
|
|
6950
|
-
};
|
|
6951
|
-
setLocalMessages((prev) => ({
|
|
6952
|
-
...prev,
|
|
6953
|
-
[entry.conversationId]: [...prev[entry.conversationId] || [], logMessage]
|
|
6954
|
-
}));
|
|
6955
|
-
};
|
|
6956
|
-
window.addEventListener(CALL_LOG_EVENT, handleCallLog);
|
|
6957
|
-
return () => window.removeEventListener(CALL_LOG_EVENT, handleCallLog);
|
|
6958
|
-
}, [setLocalMessages]);
|
|
6959
7029
|
const emitDmSend = useStore((s) => s.emitDmSend);
|
|
6960
7030
|
const emitGroupMessageSend2 = useStore((s) => s.emitGroupMessageSend);
|
|
6961
7031
|
const emitMarkAsRead = useStore((s) => s.emitMarkAsRead);
|