@realtimexsco/live-chat 1.4.4 → 1.4.6

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
@@ -17458,6 +17458,7 @@ var getFirstAndLastNameOneCharacter = (name) => {
17458
17458
  };
17459
17459
 
17460
17460
  // src/notifications/ForegroundPushBridge.tsx
17461
+ init_normalize_helpers();
17461
17462
  init_useStore();
17462
17463
 
17463
17464
  // src/notifications/push.service.ts
@@ -17604,7 +17605,9 @@ var disablePushOnThisDevice = async () => {
17604
17605
  };
17605
17606
  var onForegroundPush = async (callback) => {
17606
17607
  const config = await apiGetPushConfig();
17607
- if (!config?.configured || !config.firebaseConfig) return () => void 0;
17608
+ if (!config?.configured || !config.firebaseConfig) {
17609
+ throw new Error("Push config unavailable (not configured or API not ready)");
17610
+ }
17608
17611
  const { fb, messaging } = await getFirebaseMessaging(config.firebaseConfig);
17609
17612
  return fb.onMessage(messaging, (payload) => {
17610
17613
  callback({
@@ -17614,27 +17617,127 @@ var onForegroundPush = async (callback) => {
17614
17617
  });
17615
17618
  });
17616
17619
  };
17617
-
17618
- // src/notifications/ForegroundPushBridge.tsx
17620
+ var RETRY_DELAYS_MS = [1e3, 3e3, 8e3, 2e4];
17621
+ var recentToastIds = /* @__PURE__ */ new Set();
17622
+ var rememberToastId = (id) => {
17623
+ if (!id) return true;
17624
+ if (recentToastIds.has(id)) return false;
17625
+ recentToastIds.add(id);
17626
+ if (recentToastIds.size > 100) {
17627
+ const keep = [...recentToastIds].slice(-50);
17628
+ recentToastIds.clear();
17629
+ keep.forEach((value) => recentToastIds.add(value));
17630
+ }
17631
+ return true;
17632
+ };
17633
+ var resolveIncomingConversationId = (data) => String(
17634
+ data?.conversationId || data?.conversation_id || data?.conversationID || ""
17635
+ );
17636
+ var resolveToastText = (title, body) => {
17637
+ if (title && body) return `${title}: ${body}`;
17638
+ return title || body || "";
17639
+ };
17640
+ var emitToast = (payload, onPush) => {
17641
+ if (onPush && onPush(payload) !== false) return;
17642
+ const title = payload.title || payload.data?.title;
17643
+ const body = payload.body || payload.data?.body || payload.data?.message;
17644
+ const text = resolveToastText(title, body);
17645
+ if (text) showNotification(text, "info");
17646
+ };
17619
17647
  var ForegroundPushBridge = ({ onPush }) => {
17648
+ const lastDM = exports.useChatStore((s) => s.lastDM);
17649
+ const onPushRef = React2.useRef(onPush);
17650
+ onPushRef.current = onPush;
17651
+ React2.useEffect(() => {
17652
+ if (!lastDM) return;
17653
+ if (typeof document !== "undefined" && document.visibilityState !== "visible") {
17654
+ return;
17655
+ }
17656
+ const state = exports.useChatStore.getState();
17657
+ const loggedUserId = String(state.loggedUserDetails?._id || "");
17658
+ const conversationId = String(
17659
+ resolveConversationIdForIncomingMessage(
17660
+ lastDM,
17661
+ state.conversations,
17662
+ loggedUserId
17663
+ ) || lastDM.conversationId || ""
17664
+ );
17665
+ const messageId2 = String(lastDM._id || lastDM.id || "");
17666
+ const activeId = String(state.activeConversationId || "");
17667
+ const senderId = String(
17668
+ lastDM.sender?._id || lastDM.sender || lastDM.fromUserId || ""
17669
+ );
17670
+ if (!conversationId) return;
17671
+ if (loggedUserId && senderId && senderId === loggedUserId) return;
17672
+ if (activeId && conversationId === activeId) return;
17673
+ if (!rememberToastId(messageId2)) return;
17674
+ const isGroup = !!(lastDM.isGroup || lastDM.groupName || lastDM.conversationType === "group");
17675
+ const title = isGroup ? lastDM.groupName || lastDM.name || "Group" : lastDM.sender?.name || "New message";
17676
+ const body = typeof lastDM.content === "string" ? lastDM.content : lastDM.message?.content || (lastDM.attachments?.length ? "Sent an attachment" : "");
17677
+ console.debug("[realtimex-push] socket \u2192 toast:", {
17678
+ title,
17679
+ conversationId,
17680
+ activeConversationId: activeId
17681
+ });
17682
+ emitToast(
17683
+ {
17684
+ title,
17685
+ body,
17686
+ data: { conversationId, messageId: messageId2 }
17687
+ },
17688
+ onPushRef.current
17689
+ );
17690
+ }, [lastDM]);
17620
17691
  React2.useEffect(() => {
17621
17692
  let unsubscribe = null;
17693
+ let retryTimer = null;
17622
17694
  let cancelled = false;
17623
17695
  const handlePayload = (payload) => {
17624
- const incoming = payload.data?.conversationId;
17625
- const activeId = exports.useChatStore.getState().activeConversationId;
17626
- if (incoming && activeId && incoming === activeId) return;
17627
- if (onPush && onPush(payload) !== false) return;
17628
- const text = payload.title ? payload.body ? `${payload.title}: ${payload.body}` : payload.title : payload.body;
17629
- if (text) showNotification(text, "info");
17696
+ const incoming = resolveIncomingConversationId(payload.data);
17697
+ const activeId = String(
17698
+ exports.useChatStore.getState().activeConversationId || ""
17699
+ );
17700
+ const messageId2 = String(
17701
+ payload.data?.messageId || payload.data?.message_id || payload.data?.messageID || ""
17702
+ );
17703
+ if (incoming && activeId && incoming === activeId) {
17704
+ console.debug(
17705
+ "[realtimex-push] foreground push suppressed (conversation open):",
17706
+ incoming
17707
+ );
17708
+ return;
17709
+ }
17710
+ if (!rememberToastId(messageId2)) return;
17711
+ console.debug("[realtimex-push] foreground push \u2192 toast:", {
17712
+ title: payload.title,
17713
+ conversationId: incoming,
17714
+ activeConversationId: activeId
17715
+ });
17716
+ emitToast(payload, onPushRef.current);
17630
17717
  };
17631
- const start = async () => {
17718
+ const start = async (attempt = 0) => {
17632
17719
  if (cancelled || unsubscribe || !getStoredPushToken()) return;
17633
17720
  try {
17634
17721
  const stop = await onForegroundPush(handlePayload);
17635
17722
  if (cancelled) stop();
17636
- else unsubscribe = stop;
17637
- } catch {
17723
+ else {
17724
+ unsubscribe = stop;
17725
+ console.debug(
17726
+ "[realtimex-push] foreground listener active"
17727
+ );
17728
+ }
17729
+ } catch (error) {
17730
+ if (cancelled || attempt >= RETRY_DELAYS_MS.length) {
17731
+ console.debug(
17732
+ "[realtimex-push] foreground listener NOT started:",
17733
+ error instanceof Error ? error.message : error
17734
+ );
17735
+ return;
17736
+ }
17737
+ retryTimer = setTimeout(
17738
+ () => void start(attempt + 1),
17739
+ RETRY_DELAYS_MS[attempt]
17740
+ );
17638
17741
  }
17639
17742
  };
17640
17743
  void start();
@@ -17649,11 +17752,19 @@ var ForegroundPushBridge = ({ onPush }) => {
17649
17752
  window.addEventListener(PUSH_CHANGED_EVENT, onPushChanged);
17650
17753
  return () => {
17651
17754
  cancelled = true;
17755
+ if (retryTimer) clearTimeout(retryTimer);
17652
17756
  unsubscribe?.();
17653
17757
  window.removeEventListener(PUSH_CHANGED_EVENT, onPushChanged);
17654
17758
  };
17655
- }, [onPush]);
17656
- return null;
17759
+ }, []);
17760
+ return /* @__PURE__ */ jsxRuntime.jsx(
17761
+ reactHotToast.Toaster,
17762
+ {
17763
+ position: "top-right",
17764
+ toastOptions: { duration: 4e3 },
17765
+ containerStyle: { zIndex: 99999 }
17766
+ }
17767
+ );
17657
17768
  };
17658
17769
  var ChatMain = ({
17659
17770
  clientId,