@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 CHANGED
@@ -687,7 +687,7 @@ var init_call_api = __esm({
687
687
  });
688
688
 
689
689
  // src/call/call.types.ts
690
- exports.CALL_MODES = void 0; exports.CALL_STATUS = void 0; var CALL_RING_TIMEOUT_MS, CLIENT_RING_FALLBACK_MS;
690
+ exports.CALL_MODES = void 0; exports.CALL_STATUS = void 0; var CALL_RING_TIMEOUT_MS, CLIENT_RING_FALLBACK_MS, CALL_LOG_EVENT;
691
691
  var init_call_types = __esm({
692
692
  "src/call/call.types.ts"() {
693
693
  exports.CALL_MODES = {
@@ -704,15 +704,22 @@ var init_call_types = __esm({
704
704
  };
705
705
  CALL_RING_TIMEOUT_MS = 4e4;
706
706
  CLIENT_RING_FALLBACK_MS = CALL_RING_TIMEOUT_MS + 5e3;
707
+ CALL_LOG_EVENT = "realtimex:call-log";
707
708
  }
708
709
  });
709
- var ringTimer, clearRingTimer, scheduleRingTimer, idleState; exports.useCallStore = void 0;
710
+ var emitCallLog, ringTimer, clearRingTimer, scheduleRingTimer, idleState; exports.useCallStore = void 0;
710
711
  var init_call_store = __esm({
711
712
  "src/call/call.store.ts"() {
712
713
  init_useStore();
713
714
  init_socket_service2();
714
715
  init_call_api();
715
716
  init_call_types();
717
+ emitCallLog = (entry) => {
718
+ try {
719
+ window.dispatchEvent(new CustomEvent(CALL_LOG_EVENT, { detail: entry }));
720
+ } catch {
721
+ }
722
+ };
716
723
  ringTimer = null;
717
724
  clearRingTimer = () => {
718
725
  if (ringTimer) clearTimeout(ringTimer);
@@ -810,8 +817,20 @@ var init_call_store = __esm({
810
817
  clearRingTimer();
811
818
  set({ ...idleState });
812
819
  },
820
+ notifyServerCallFailed: () => {
821
+ const { callId } = get();
822
+ if (callId) {
823
+ exports.socketService.emitCallEnd({ callId });
824
+ }
825
+ },
813
826
  _receiveIncoming: (payload) => {
814
- if (get().uiStatus !== "idle") return;
827
+ const currentStatus = get().uiStatus;
828
+ if (currentStatus !== "idle") {
829
+ console.warn(
830
+ `[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.`
831
+ );
832
+ return;
833
+ }
815
834
  set({
816
835
  uiStatus: "incoming",
817
836
  callId: payload.callId,
@@ -854,16 +873,37 @@ var init_call_store = __esm({
854
873
  _receiveCancelled: (payload) => {
855
874
  if (get().callId !== payload.callId) return;
856
875
  clearRingTimer();
876
+ const myUserId = exports.useChatStore.getState().loggedUserDetails?._id;
877
+ if (payload.endedBy !== myUserId) {
878
+ emitCallLog({
879
+ conversationId: payload.conversationId,
880
+ mode: payload.mode,
881
+ outcome: "missed",
882
+ durationSeconds: 0
883
+ });
884
+ }
857
885
  set({ ...idleState });
858
886
  },
859
887
  _receiveEnded: (payload) => {
860
888
  if (get().callId !== payload.callId) return;
861
889
  clearRingTimer();
890
+ emitCallLog({
891
+ conversationId: payload.conversationId,
892
+ mode: payload.mode,
893
+ outcome: payload.durationSeconds > 0 ? "completed" : "declined",
894
+ durationSeconds: payload.durationSeconds
895
+ });
862
896
  set({ ...idleState });
863
897
  },
864
898
  _receiveBusy: (payload) => {
865
899
  if (get().callId !== payload.callId) return;
866
900
  clearRingTimer();
901
+ emitCallLog({
902
+ conversationId: payload.conversationId,
903
+ mode: payload.mode,
904
+ outcome: "busy",
905
+ durationSeconds: 0
906
+ });
867
907
  set({ ...idleState, error: "That user is already on another call." });
868
908
  },
869
909
  // Guarded by callId like every other _receive* handler — a late/stale
@@ -872,6 +912,12 @@ var init_call_store = __esm({
872
912
  _receiveMissed: (payload) => {
873
913
  if (get().callId !== payload.callId) return;
874
914
  clearRingTimer();
915
+ emitCallLog({
916
+ conversationId: payload.conversationId,
917
+ mode: payload.mode,
918
+ outcome: "missed",
919
+ durationSeconds: 0
920
+ });
875
921
  set({ ...idleState });
876
922
  }
877
923
  }));
@@ -885,25 +931,33 @@ var init_call_listeners = __esm({
885
931
  init_socket_events_constants();
886
932
  init_call_store();
887
933
  registerCallSocketListeners = (socket) => {
934
+ console.debug("[realtimex-call] registerCallSocketListeners: attached to socket", socket.id);
888
935
  socket.on(SOCKET_EVENTS.CALL_INCOMING, (payload) => {
936
+ console.log("[realtimex-call] call_incoming received:", payload);
889
937
  exports.useCallStore.getState()._receiveIncoming(payload);
890
938
  });
891
939
  socket.on(SOCKET_EVENTS.CALL_ACCEPTED, (payload) => {
940
+ console.log("[realtimex-call] call_accepted received:", payload);
892
941
  exports.useCallStore.getState()._receiveAccepted(payload);
893
942
  });
894
943
  socket.on(SOCKET_EVENTS.CALL_REJECTED, (payload) => {
944
+ console.log("[realtimex-call] call_rejected received:", payload);
895
945
  exports.useCallStore.getState()._receiveRejected(payload);
896
946
  });
897
947
  socket.on(SOCKET_EVENTS.CALL_CANCELLED, (payload) => {
948
+ console.log("[realtimex-call] call_cancelled received:", payload);
898
949
  exports.useCallStore.getState()._receiveCancelled(payload);
899
950
  });
900
951
  socket.on(SOCKET_EVENTS.CALL_ENDED, (payload) => {
952
+ console.log("[realtimex-call] call_ended received:", payload);
901
953
  exports.useCallStore.getState()._receiveEnded(payload);
902
954
  });
903
955
  socket.on(SOCKET_EVENTS.CALL_BUSY, (payload) => {
956
+ console.log("[realtimex-call] call_busy received:", payload);
904
957
  exports.useCallStore.getState()._receiveBusy(payload);
905
958
  });
906
959
  socket.on(SOCKET_EVENTS.CALL_MISSED, (payload) => {
960
+ console.log("[realtimex-call] call_missed received:", payload);
907
961
  exports.useCallStore.getState()._receiveMissed(payload);
908
962
  });
909
963
  };
@@ -6186,9 +6240,16 @@ var CallOverlay = () => {
6186
6240
  const callStartedAt = exports.useCallStore((s) => s.callStartedAt);
6187
6241
  const cancelCall = exports.useCallStore((s) => s.cancelCall);
6188
6242
  const reset = exports.useCallStore((s) => s.reset);
6243
+ const notifyServerCallFailed = exports.useCallStore((s) => s.notifyServerCallFailed);
6189
6244
  const [sessionError, setSessionError] = React9.useState(null);
6190
6245
  const secondsLeft = useRingCountdown(uiStatus === "ringing-out", callId);
6191
6246
  const duration = useCallDuration(callStartedAt);
6247
+ React9.useEffect(() => {
6248
+ setSessionError(null);
6249
+ }, [callId]);
6250
+ React9.useEffect(() => {
6251
+ if (sessionError) notifyServerCallFailed();
6252
+ }, [sessionError, notifyServerCallFailed]);
6192
6253
  const isOpen = uiStatus !== "idle" && uiStatus !== "incoming";
6193
6254
  if (!isOpen) return null;
6194
6255
  const displayError = error || sessionError;
@@ -6845,6 +6906,18 @@ var installNotificationClickBridge = (options = {}) => {
6845
6906
  };
6846
6907
 
6847
6908
  // src/hooks/useChatController.ts
6909
+ init_call_types();
6910
+ function formatCallLogText(entry) {
6911
+ const label = entry.mode === "video" ? "video" : "voice";
6912
+ if (entry.outcome === "missed") return `Missed ${label} call`;
6913
+ if (entry.outcome === "declined") return `${label === "video" ? "Video" : "Voice"} call declined`;
6914
+ if (entry.outcome === "busy") return `${label === "video" ? "Video" : "Voice"} call \xB7 not answered`;
6915
+ const totalSeconds = Math.max(0, Math.floor(entry.durationSeconds));
6916
+ const minutes = Math.floor(totalSeconds / 60);
6917
+ const seconds = totalSeconds % 60;
6918
+ const duration = `${minutes}:${String(seconds).padStart(2, "0")}`;
6919
+ return `${label === "video" ? "Video" : "Voice"} call \xB7 ${duration}`;
6920
+ }
6848
6921
  function resolveMessageType(content, attachments) {
6849
6922
  if (attachments.length === 0) return "text";
6850
6923
  if (!content.trim() && attachments.length === 1) {
@@ -6902,6 +6975,28 @@ var useChatController = () => {
6902
6975
  );
6903
6976
  }, []);
6904
6977
  const { localMessages, setLocalMessages } = useChatSync();
6978
+ React9.useEffect(() => {
6979
+ const handleCallLog = (event) => {
6980
+ const entry = event.detail;
6981
+ if (!entry?.conversationId) return;
6982
+ const logMessage = {
6983
+ id: `call-log-${Date.now()}-${Math.random().toString(36).slice(2)}`,
6984
+ content: formatCallLogText(entry),
6985
+ sender: "system",
6986
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
6987
+ isOwnMessage: false,
6988
+ isSystemMessage: true,
6989
+ channelId: entry.conversationId,
6990
+ conversationId: entry.conversationId
6991
+ };
6992
+ setLocalMessages((prev) => ({
6993
+ ...prev,
6994
+ [entry.conversationId]: [...prev[entry.conversationId] || [], logMessage]
6995
+ }));
6996
+ };
6997
+ window.addEventListener(CALL_LOG_EVENT, handleCallLog);
6998
+ return () => window.removeEventListener(CALL_LOG_EVENT, handleCallLog);
6999
+ }, [setLocalMessages]);
6905
7000
  const emitDmSend = exports.useChatStore((s) => s.emitDmSend);
6906
7001
  const emitGroupMessageSend2 = exports.useChatStore((s) => s.emitGroupMessageSend);
6907
7002
  const emitMarkAsRead = exports.useChatStore((s) => s.emitMarkAsRead);