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