@realtimexsco/live-chat 1.5.0 → 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/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);
@@ -783,7 +790,13 @@ var init_call_store = __esm({
783
790
  set({ ...idleState });
784
791
  },
785
792
  _receiveIncoming: (payload) => {
786
- if (get().uiStatus !== "idle") return;
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
+ }
787
800
  set({
788
801
  uiStatus: "incoming",
789
802
  callId: payload.callId,
@@ -826,16 +839,37 @@ var init_call_store = __esm({
826
839
  _receiveCancelled: (payload) => {
827
840
  if (get().callId !== payload.callId) return;
828
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
+ }
829
851
  set({ ...idleState });
830
852
  },
831
853
  _receiveEnded: (payload) => {
832
854
  if (get().callId !== payload.callId) return;
833
855
  clearRingTimer();
856
+ emitCallLog({
857
+ conversationId: payload.conversationId,
858
+ mode: payload.mode,
859
+ outcome: payload.durationSeconds > 0 ? "completed" : "declined",
860
+ durationSeconds: payload.durationSeconds
861
+ });
834
862
  set({ ...idleState });
835
863
  },
836
864
  _receiveBusy: (payload) => {
837
865
  if (get().callId !== payload.callId) return;
838
866
  clearRingTimer();
867
+ emitCallLog({
868
+ conversationId: payload.conversationId,
869
+ mode: payload.mode,
870
+ outcome: "busy",
871
+ durationSeconds: 0
872
+ });
839
873
  set({ ...idleState, error: "That user is already on another call." });
840
874
  },
841
875
  // Guarded by callId like every other _receive* handler — a late/stale
@@ -844,6 +878,12 @@ var init_call_store = __esm({
844
878
  _receiveMissed: (payload) => {
845
879
  if (get().callId !== payload.callId) return;
846
880
  clearRingTimer();
881
+ emitCallLog({
882
+ conversationId: payload.conversationId,
883
+ mode: payload.mode,
884
+ outcome: "missed",
885
+ durationSeconds: 0
886
+ });
847
887
  set({ ...idleState });
848
888
  }
849
889
  }));
@@ -857,25 +897,33 @@ var init_call_listeners = __esm({
857
897
  init_socket_events_constants();
858
898
  init_call_store();
859
899
  registerCallSocketListeners = (socket) => {
900
+ console.debug("[realtimex-call] registerCallSocketListeners: attached to socket", socket.id);
860
901
  socket.on(SOCKET_EVENTS.CALL_INCOMING, (payload) => {
902
+ console.log("[realtimex-call] call_incoming received:", payload);
861
903
  useCallStore.getState()._receiveIncoming(payload);
862
904
  });
863
905
  socket.on(SOCKET_EVENTS.CALL_ACCEPTED, (payload) => {
906
+ console.log("[realtimex-call] call_accepted received:", payload);
864
907
  useCallStore.getState()._receiveAccepted(payload);
865
908
  });
866
909
  socket.on(SOCKET_EVENTS.CALL_REJECTED, (payload) => {
910
+ console.log("[realtimex-call] call_rejected received:", payload);
867
911
  useCallStore.getState()._receiveRejected(payload);
868
912
  });
869
913
  socket.on(SOCKET_EVENTS.CALL_CANCELLED, (payload) => {
914
+ console.log("[realtimex-call] call_cancelled received:", payload);
870
915
  useCallStore.getState()._receiveCancelled(payload);
871
916
  });
872
917
  socket.on(SOCKET_EVENTS.CALL_ENDED, (payload) => {
918
+ console.log("[realtimex-call] call_ended received:", payload);
873
919
  useCallStore.getState()._receiveEnded(payload);
874
920
  });
875
921
  socket.on(SOCKET_EVENTS.CALL_BUSY, (payload) => {
922
+ console.log("[realtimex-call] call_busy received:", payload);
876
923
  useCallStore.getState()._receiveBusy(payload);
877
924
  });
878
925
  socket.on(SOCKET_EVENTS.CALL_MISSED, (payload) => {
926
+ console.log("[realtimex-call] call_missed received:", payload);
879
927
  useCallStore.getState()._receiveMissed(payload);
880
928
  });
881
929
  };
@@ -6817,6 +6865,18 @@ var installNotificationClickBridge = (options = {}) => {
6817
6865
  };
6818
6866
 
6819
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
+ }
6820
6880
  function resolveMessageType(content, attachments) {
6821
6881
  if (attachments.length === 0) return "text";
6822
6882
  if (!content.trim() && attachments.length === 1) {
@@ -6874,6 +6934,28 @@ var useChatController = () => {
6874
6934
  );
6875
6935
  }, []);
6876
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]);
6877
6959
  const emitDmSend = useStore((s) => s.emitDmSend);
6878
6960
  const emitGroupMessageSend2 = useStore((s) => s.emitGroupMessageSend);
6879
6961
  const emitMarkAsRead = useStore((s) => s.emitMarkAsRead);