@realtimexsco/live-chat 1.5.0 → 1.5.2
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 +98 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.mjs +98 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -2043,6 +2043,15 @@ interface CallState {
|
|
|
2043
2043
|
endCall: () => void;
|
|
2044
2044
|
/** Drop back to idle without notifying anyone (e.g. after a fatal error). */
|
|
2045
2045
|
reset: () => void;
|
|
2046
|
+
/**
|
|
2047
|
+
* Tell the server this call is over WITHOUT touching local UI state —
|
|
2048
|
+
* for when the in-call session itself crashed (e.g. VideoSDK failed to
|
|
2049
|
+
* load) and the error needs to stay on screen. The backend already
|
|
2050
|
+
* marked this call ongoing/this user busy once accepted (CALLS_API.md
|
|
2051
|
+
* §3.3); without this, that busy lock would stick until the caller/callee
|
|
2052
|
+
* explicitly closes the error (endCall()) or the 4h Redis TTL expires.
|
|
2053
|
+
*/
|
|
2054
|
+
notifyServerCallFailed: () => void;
|
|
2046
2055
|
_receiveIncoming: (payload: CallIncomingPayload) => void;
|
|
2047
2056
|
_receiveAccepted: (payload: CallAcceptedPayload) => void;
|
|
2048
2057
|
_receiveRejected: (payload: CallRejectedPayload) => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -2043,6 +2043,15 @@ interface CallState {
|
|
|
2043
2043
|
endCall: () => void;
|
|
2044
2044
|
/** Drop back to idle without notifying anyone (e.g. after a fatal error). */
|
|
2045
2045
|
reset: () => void;
|
|
2046
|
+
/**
|
|
2047
|
+
* Tell the server this call is over WITHOUT touching local UI state —
|
|
2048
|
+
* for when the in-call session itself crashed (e.g. VideoSDK failed to
|
|
2049
|
+
* load) and the error needs to stay on screen. The backend already
|
|
2050
|
+
* marked this call ongoing/this user busy once accepted (CALLS_API.md
|
|
2051
|
+
* §3.3); without this, that busy lock would stick until the caller/callee
|
|
2052
|
+
* explicitly closes the error (endCall()) or the 4h Redis TTL expires.
|
|
2053
|
+
*/
|
|
2054
|
+
notifyServerCallFailed: () => void;
|
|
2046
2055
|
_receiveIncoming: (payload: CallIncomingPayload) => void;
|
|
2047
2056
|
_receiveAccepted: (payload: CallAcceptedPayload) => void;
|
|
2048
2057
|
_receiveRejected: (payload: CallRejectedPayload) => void;
|
package/dist/index.mjs
CHANGED
|
@@ -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, CALL_LOG_EVENT;
|
|
663
663
|
var init_call_types = __esm({
|
|
664
664
|
"src/call/call.types.ts"() {
|
|
665
665
|
CALL_MODES = {
|
|
@@ -676,15 +676,22 @@ 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";
|
|
679
680
|
}
|
|
680
681
|
});
|
|
681
|
-
var ringTimer, clearRingTimer, scheduleRingTimer, idleState, useCallStore;
|
|
682
|
+
var emitCallLog, ringTimer, clearRingTimer, scheduleRingTimer, idleState, useCallStore;
|
|
682
683
|
var init_call_store = __esm({
|
|
683
684
|
"src/call/call.store.ts"() {
|
|
684
685
|
init_useStore();
|
|
685
686
|
init_socket_service2();
|
|
686
687
|
init_call_api();
|
|
687
688
|
init_call_types();
|
|
689
|
+
emitCallLog = (entry) => {
|
|
690
|
+
try {
|
|
691
|
+
window.dispatchEvent(new CustomEvent(CALL_LOG_EVENT, { detail: entry }));
|
|
692
|
+
} catch {
|
|
693
|
+
}
|
|
694
|
+
};
|
|
688
695
|
ringTimer = null;
|
|
689
696
|
clearRingTimer = () => {
|
|
690
697
|
if (ringTimer) clearTimeout(ringTimer);
|
|
@@ -782,8 +789,20 @@ var init_call_store = __esm({
|
|
|
782
789
|
clearRingTimer();
|
|
783
790
|
set({ ...idleState });
|
|
784
791
|
},
|
|
792
|
+
notifyServerCallFailed: () => {
|
|
793
|
+
const { callId } = get();
|
|
794
|
+
if (callId) {
|
|
795
|
+
socket_service_default.emitCallEnd({ callId });
|
|
796
|
+
}
|
|
797
|
+
},
|
|
785
798
|
_receiveIncoming: (payload) => {
|
|
786
|
-
|
|
799
|
+
const currentStatus = get().uiStatus;
|
|
800
|
+
if (currentStatus !== "idle") {
|
|
801
|
+
console.warn(
|
|
802
|
+
`[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.`
|
|
803
|
+
);
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
787
806
|
set({
|
|
788
807
|
uiStatus: "incoming",
|
|
789
808
|
callId: payload.callId,
|
|
@@ -826,16 +845,37 @@ var init_call_store = __esm({
|
|
|
826
845
|
_receiveCancelled: (payload) => {
|
|
827
846
|
if (get().callId !== payload.callId) return;
|
|
828
847
|
clearRingTimer();
|
|
848
|
+
const myUserId = useStore.getState().loggedUserDetails?._id;
|
|
849
|
+
if (payload.endedBy !== myUserId) {
|
|
850
|
+
emitCallLog({
|
|
851
|
+
conversationId: payload.conversationId,
|
|
852
|
+
mode: payload.mode,
|
|
853
|
+
outcome: "missed",
|
|
854
|
+
durationSeconds: 0
|
|
855
|
+
});
|
|
856
|
+
}
|
|
829
857
|
set({ ...idleState });
|
|
830
858
|
},
|
|
831
859
|
_receiveEnded: (payload) => {
|
|
832
860
|
if (get().callId !== payload.callId) return;
|
|
833
861
|
clearRingTimer();
|
|
862
|
+
emitCallLog({
|
|
863
|
+
conversationId: payload.conversationId,
|
|
864
|
+
mode: payload.mode,
|
|
865
|
+
outcome: payload.durationSeconds > 0 ? "completed" : "declined",
|
|
866
|
+
durationSeconds: payload.durationSeconds
|
|
867
|
+
});
|
|
834
868
|
set({ ...idleState });
|
|
835
869
|
},
|
|
836
870
|
_receiveBusy: (payload) => {
|
|
837
871
|
if (get().callId !== payload.callId) return;
|
|
838
872
|
clearRingTimer();
|
|
873
|
+
emitCallLog({
|
|
874
|
+
conversationId: payload.conversationId,
|
|
875
|
+
mode: payload.mode,
|
|
876
|
+
outcome: "busy",
|
|
877
|
+
durationSeconds: 0
|
|
878
|
+
});
|
|
839
879
|
set({ ...idleState, error: "That user is already on another call." });
|
|
840
880
|
},
|
|
841
881
|
// Guarded by callId like every other _receive* handler — a late/stale
|
|
@@ -844,6 +884,12 @@ var init_call_store = __esm({
|
|
|
844
884
|
_receiveMissed: (payload) => {
|
|
845
885
|
if (get().callId !== payload.callId) return;
|
|
846
886
|
clearRingTimer();
|
|
887
|
+
emitCallLog({
|
|
888
|
+
conversationId: payload.conversationId,
|
|
889
|
+
mode: payload.mode,
|
|
890
|
+
outcome: "missed",
|
|
891
|
+
durationSeconds: 0
|
|
892
|
+
});
|
|
847
893
|
set({ ...idleState });
|
|
848
894
|
}
|
|
849
895
|
}));
|
|
@@ -857,25 +903,33 @@ var init_call_listeners = __esm({
|
|
|
857
903
|
init_socket_events_constants();
|
|
858
904
|
init_call_store();
|
|
859
905
|
registerCallSocketListeners = (socket) => {
|
|
906
|
+
console.debug("[realtimex-call] registerCallSocketListeners: attached to socket", socket.id);
|
|
860
907
|
socket.on(SOCKET_EVENTS.CALL_INCOMING, (payload) => {
|
|
908
|
+
console.log("[realtimex-call] call_incoming received:", payload);
|
|
861
909
|
useCallStore.getState()._receiveIncoming(payload);
|
|
862
910
|
});
|
|
863
911
|
socket.on(SOCKET_EVENTS.CALL_ACCEPTED, (payload) => {
|
|
912
|
+
console.log("[realtimex-call] call_accepted received:", payload);
|
|
864
913
|
useCallStore.getState()._receiveAccepted(payload);
|
|
865
914
|
});
|
|
866
915
|
socket.on(SOCKET_EVENTS.CALL_REJECTED, (payload) => {
|
|
916
|
+
console.log("[realtimex-call] call_rejected received:", payload);
|
|
867
917
|
useCallStore.getState()._receiveRejected(payload);
|
|
868
918
|
});
|
|
869
919
|
socket.on(SOCKET_EVENTS.CALL_CANCELLED, (payload) => {
|
|
920
|
+
console.log("[realtimex-call] call_cancelled received:", payload);
|
|
870
921
|
useCallStore.getState()._receiveCancelled(payload);
|
|
871
922
|
});
|
|
872
923
|
socket.on(SOCKET_EVENTS.CALL_ENDED, (payload) => {
|
|
924
|
+
console.log("[realtimex-call] call_ended received:", payload);
|
|
873
925
|
useCallStore.getState()._receiveEnded(payload);
|
|
874
926
|
});
|
|
875
927
|
socket.on(SOCKET_EVENTS.CALL_BUSY, (payload) => {
|
|
928
|
+
console.log("[realtimex-call] call_busy received:", payload);
|
|
876
929
|
useCallStore.getState()._receiveBusy(payload);
|
|
877
930
|
});
|
|
878
931
|
socket.on(SOCKET_EVENTS.CALL_MISSED, (payload) => {
|
|
932
|
+
console.log("[realtimex-call] call_missed received:", payload);
|
|
879
933
|
useCallStore.getState()._receiveMissed(payload);
|
|
880
934
|
});
|
|
881
935
|
};
|
|
@@ -6158,9 +6212,16 @@ var CallOverlay = () => {
|
|
|
6158
6212
|
const callStartedAt = useCallStore((s) => s.callStartedAt);
|
|
6159
6213
|
const cancelCall = useCallStore((s) => s.cancelCall);
|
|
6160
6214
|
const reset = useCallStore((s) => s.reset);
|
|
6215
|
+
const notifyServerCallFailed = useCallStore((s) => s.notifyServerCallFailed);
|
|
6161
6216
|
const [sessionError, setSessionError] = useState(null);
|
|
6162
6217
|
const secondsLeft = useRingCountdown(uiStatus === "ringing-out", callId);
|
|
6163
6218
|
const duration = useCallDuration(callStartedAt);
|
|
6219
|
+
useEffect(() => {
|
|
6220
|
+
setSessionError(null);
|
|
6221
|
+
}, [callId]);
|
|
6222
|
+
useEffect(() => {
|
|
6223
|
+
if (sessionError) notifyServerCallFailed();
|
|
6224
|
+
}, [sessionError, notifyServerCallFailed]);
|
|
6164
6225
|
const isOpen = uiStatus !== "idle" && uiStatus !== "incoming";
|
|
6165
6226
|
if (!isOpen) return null;
|
|
6166
6227
|
const displayError = error || sessionError;
|
|
@@ -6817,6 +6878,18 @@ var installNotificationClickBridge = (options = {}) => {
|
|
|
6817
6878
|
};
|
|
6818
6879
|
|
|
6819
6880
|
// 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
|
+
}
|
|
6820
6893
|
function resolveMessageType(content, attachments) {
|
|
6821
6894
|
if (attachments.length === 0) return "text";
|
|
6822
6895
|
if (!content.trim() && attachments.length === 1) {
|
|
@@ -6874,6 +6947,28 @@ var useChatController = () => {
|
|
|
6874
6947
|
);
|
|
6875
6948
|
}, []);
|
|
6876
6949
|
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]);
|
|
6877
6972
|
const emitDmSend = useStore((s) => s.emitDmSend);
|
|
6878
6973
|
const emitGroupMessageSend2 = useStore((s) => s.emitGroupMessageSend);
|
|
6879
6974
|
const emitMarkAsRead = useStore((s) => s.emitMarkAsRead);
|