@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.d.mts CHANGED
@@ -1648,18 +1648,6 @@ interface ForegroundPushBridgeProps {
1648
1648
  */
1649
1649
  onPush?: (payload: ForegroundPushPayload) => void | boolean;
1650
1650
  }
1651
- /**
1652
- * Slack-style routing for pushes that arrive while the tab is FOCUSED
1653
- * (unfocused tabs / other apps are handled by the service worker, which shows
1654
- * the OS notification):
1655
- *
1656
- * - message belongs to the conversation currently open → suppressed
1657
- * entirely (the user is already reading it)
1658
- * - any other conversation → in-app toast
1659
- *
1660
- * Mounted automatically by ChatMain; does nothing until this device has
1661
- * opted in to push (no firebase import, no listeners).
1662
- */
1663
- declare const ForegroundPushBridge: ({ onPush }: ForegroundPushBridgeProps) => null;
1651
+ declare const ForegroundPushBridge: ({ onPush }: ForegroundPushBridgeProps) => React.JSX.Element;
1664
1652
 
1665
1653
  export { type ActiveChannelMessagesSlotProps, type AdminsDrawerSlotProps, type AttachmentsDrawerSlotProps, type AvatarSlotProps, CHAT_API_KEYS, CHAT_GET_API_KEYS, Calendar, CalendarDayButton, Channel, type ChannelDetailsDrawerSlotProps, ChannelHeaderView as ChannelHeader, type ChannelHeaderSlotProps, ChannelListView as ChannelList, ChannelListItem, type ChannelListItemSlotProps, type ChannelListSlotProps, type ChannelMessageBoxSlotProps, Chat, type ChatActionModalSlotProps, ChatAlertsProvider, type ChatApiKey, ChatAvatar, type ChatCallContext, type ChatClassNames, type ChatColorMode, type ChatComponents, type ChatCustomizationConfig, ChatCustomizationProvider, ChatDateJumpMenu, type ChatDateTimePreferences, type ChatFeatures, type ChatGetApiKey, ChatLayout, type ChatLayoutConfig, type ChatLayoutSlotProps, ChatLocaleProvider, ChatMain, type ChatPanelAlertsSlotProps, type ChatQueryParams, type ChatQueryParamsByApi, ChatThemeProvider, ChatViewport, type ChatViewportHeight, DefaultChannelListItem, DefaultChatAvatar, DefaultChatLayout, ForegroundPushBridge, type ForegroundPushBridgeProps, type ForegroundPushPayload, ForwardModalView as ForwardModal, type ForwardModalSlotProps, HeaderCallActions, type HeaderCallActionsSlotProps, type HeaderLeftSideSlotProps, type HeaderRightSideSlotProps, type HeaderSearchOverlaySlotProps, type IAttachment, type IChannel, type IDMDelete, type IDMEditMessage, type IDMForward, type IDMMessage, type IDMPin, type IDMReaction, type IDMRead, type IDMStar, type IDMTyping, type IDMUnstar, type IMessage, type ISocketConfig, type JumpToPreset, LoggedUserDetails, type LoggedUserDetailsSlotProps, type MembersDrawerSlotProps, type MessageAttachmentsSlotProps, ChannelMessageBoxView as MessageInput, MessageItemView as MessageItem, type MessageItemSlotProps, ActiveChannelMessagesView as MessageList, type MessageReactionsSlotProps, type MessageReplySnippetSlotProps, type MessageStatusSlotProps, type MessageToolbarSlotProps, PUSH_CHANGED_EVENT, type PendingJump, type PermissionDrawerSlotProps, type PhoneCallButtonSlotProps, type PinnedMessagesDrawerSlotProps, type PushConfig, PushNotificationToggle, type PushNotificationToggleProps, type PushNotificationsState, type PushPreference, type StarredMessagesDrawerSlotProps, type UIConfig, type UsePushNotifications, type VideoCallButtonSlotProps, apiGetPushConfig, apiGetPushPreference, apiRegisterPushToken, apiRemovePushToken, apiUpdatePushPreference, capitalizeFirst, clampJumpDate, ChatMain as default, defaultChatClassNames, defaultChatComponents, defaultChatFeatures, defaultChatLayoutConfig, disablePushOnThisDevice, downloadFile, enablePushOnThisDevice, getChatBaseUrl, getChatQueryParamApis, getChatQueryParams, getChatQueryParamsByApi, getChatSocketUrl, getFirstAndLastNameOneCharacter, getResponsiveWidth, getSocketConfig, getStoredPushToken, isEmpty, isPushSupported, mergeChatCustomization, mergeChatLayoutConfig, onForegroundPush, packageDefaultComponents, resolveApiUrl, resolveChatApiKey, resolveJumpDateBounds, resolveJumpPreset, resolveJumpStep, resolveSocketUrl, setChatAccessToken, setChatBaseURL, setChatClientId, setChatQueryParamApis, setChatQueryParams, setChatQueryParamsByApi, setChatSocketUrl, showNotification, smoothScrollToMessage, socketService, startOfLocalDay, toDateInputValue, uniqueList, useChatAlerts, useChatContext, useChatController, useChatCustomization, useChatCustomizationOptional, useChatFeatures, useChatFeaturesOptional, useChatLocale, useStore as useChatStore, useChatTheme, usePushNotifications };
package/dist/index.d.ts CHANGED
@@ -1648,18 +1648,6 @@ interface ForegroundPushBridgeProps {
1648
1648
  */
1649
1649
  onPush?: (payload: ForegroundPushPayload) => void | boolean;
1650
1650
  }
1651
- /**
1652
- * Slack-style routing for pushes that arrive while the tab is FOCUSED
1653
- * (unfocused tabs / other apps are handled by the service worker, which shows
1654
- * the OS notification):
1655
- *
1656
- * - message belongs to the conversation currently open → suppressed
1657
- * entirely (the user is already reading it)
1658
- * - any other conversation → in-app toast
1659
- *
1660
- * Mounted automatically by ChatMain; does nothing until this device has
1661
- * opted in to push (no firebase import, no listeners).
1662
- */
1663
- declare const ForegroundPushBridge: ({ onPush }: ForegroundPushBridgeProps) => null;
1651
+ declare const ForegroundPushBridge: ({ onPush }: ForegroundPushBridgeProps) => React.JSX.Element;
1664
1652
 
1665
1653
  export { type ActiveChannelMessagesSlotProps, type AdminsDrawerSlotProps, type AttachmentsDrawerSlotProps, type AvatarSlotProps, CHAT_API_KEYS, CHAT_GET_API_KEYS, Calendar, CalendarDayButton, Channel, type ChannelDetailsDrawerSlotProps, ChannelHeaderView as ChannelHeader, type ChannelHeaderSlotProps, ChannelListView as ChannelList, ChannelListItem, type ChannelListItemSlotProps, type ChannelListSlotProps, type ChannelMessageBoxSlotProps, Chat, type ChatActionModalSlotProps, ChatAlertsProvider, type ChatApiKey, ChatAvatar, type ChatCallContext, type ChatClassNames, type ChatColorMode, type ChatComponents, type ChatCustomizationConfig, ChatCustomizationProvider, ChatDateJumpMenu, type ChatDateTimePreferences, type ChatFeatures, type ChatGetApiKey, ChatLayout, type ChatLayoutConfig, type ChatLayoutSlotProps, ChatLocaleProvider, ChatMain, type ChatPanelAlertsSlotProps, type ChatQueryParams, type ChatQueryParamsByApi, ChatThemeProvider, ChatViewport, type ChatViewportHeight, DefaultChannelListItem, DefaultChatAvatar, DefaultChatLayout, ForegroundPushBridge, type ForegroundPushBridgeProps, type ForegroundPushPayload, ForwardModalView as ForwardModal, type ForwardModalSlotProps, HeaderCallActions, type HeaderCallActionsSlotProps, type HeaderLeftSideSlotProps, type HeaderRightSideSlotProps, type HeaderSearchOverlaySlotProps, type IAttachment, type IChannel, type IDMDelete, type IDMEditMessage, type IDMForward, type IDMMessage, type IDMPin, type IDMReaction, type IDMRead, type IDMStar, type IDMTyping, type IDMUnstar, type IMessage, type ISocketConfig, type JumpToPreset, LoggedUserDetails, type LoggedUserDetailsSlotProps, type MembersDrawerSlotProps, type MessageAttachmentsSlotProps, ChannelMessageBoxView as MessageInput, MessageItemView as MessageItem, type MessageItemSlotProps, ActiveChannelMessagesView as MessageList, type MessageReactionsSlotProps, type MessageReplySnippetSlotProps, type MessageStatusSlotProps, type MessageToolbarSlotProps, PUSH_CHANGED_EVENT, type PendingJump, type PermissionDrawerSlotProps, type PhoneCallButtonSlotProps, type PinnedMessagesDrawerSlotProps, type PushConfig, PushNotificationToggle, type PushNotificationToggleProps, type PushNotificationsState, type PushPreference, type StarredMessagesDrawerSlotProps, type UIConfig, type UsePushNotifications, type VideoCallButtonSlotProps, apiGetPushConfig, apiGetPushPreference, apiRegisterPushToken, apiRemovePushToken, apiUpdatePushPreference, capitalizeFirst, clampJumpDate, ChatMain as default, defaultChatClassNames, defaultChatComponents, defaultChatFeatures, defaultChatLayoutConfig, disablePushOnThisDevice, downloadFile, enablePushOnThisDevice, getChatBaseUrl, getChatQueryParamApis, getChatQueryParams, getChatQueryParamsByApi, getChatSocketUrl, getFirstAndLastNameOneCharacter, getResponsiveWidth, getSocketConfig, getStoredPushToken, isEmpty, isPushSupported, mergeChatCustomization, mergeChatLayoutConfig, onForegroundPush, packageDefaultComponents, resolveApiUrl, resolveChatApiKey, resolveJumpDateBounds, resolveJumpPreset, resolveJumpStep, resolveSocketUrl, setChatAccessToken, setChatBaseURL, setChatClientId, setChatQueryParamApis, setChatQueryParams, setChatQueryParamsByApi, setChatSocketUrl, showNotification, smoothScrollToMessage, socketService, startOfLocalDay, toDateInputValue, uniqueList, useChatAlerts, useChatContext, useChatController, useChatCustomization, useChatCustomizationOptional, useChatFeatures, useChatFeaturesOptional, useChatLocale, useStore as useChatStore, useChatTheme, usePushNotifications };
package/dist/index.mjs CHANGED
@@ -13,7 +13,7 @@ import { Sun, Moon, Search, X, Loader2, UserPlus, ChevronDown, ArrowLeft, Users,
13
13
  import { cva } from 'class-variance-authority';
14
14
  import EmojiPicker, { Theme } from 'emoji-picker-react';
15
15
  import { getDefaultClassNames, DayPicker } from 'react-day-picker';
16
- import { toast } from 'react-hot-toast';
16
+ import { toast, Toaster } from 'react-hot-toast';
17
17
 
18
18
  var __defProp = Object.defineProperty;
19
19
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -17431,6 +17431,7 @@ var getFirstAndLastNameOneCharacter = (name) => {
17431
17431
  };
17432
17432
 
17433
17433
  // src/notifications/ForegroundPushBridge.tsx
17434
+ init_normalize_helpers();
17434
17435
  init_useStore();
17435
17436
 
17436
17437
  // src/notifications/push.service.ts
@@ -17577,7 +17578,9 @@ var disablePushOnThisDevice = async () => {
17577
17578
  };
17578
17579
  var onForegroundPush = async (callback) => {
17579
17580
  const config = await apiGetPushConfig();
17580
- if (!config?.configured || !config.firebaseConfig) return () => void 0;
17581
+ if (!config?.configured || !config.firebaseConfig) {
17582
+ throw new Error("Push config unavailable (not configured or API not ready)");
17583
+ }
17581
17584
  const { fb, messaging } = await getFirebaseMessaging(config.firebaseConfig);
17582
17585
  return fb.onMessage(messaging, (payload) => {
17583
17586
  callback({
@@ -17587,27 +17590,127 @@ var onForegroundPush = async (callback) => {
17587
17590
  });
17588
17591
  });
17589
17592
  };
17590
-
17591
- // src/notifications/ForegroundPushBridge.tsx
17593
+ var RETRY_DELAYS_MS = [1e3, 3e3, 8e3, 2e4];
17594
+ var recentToastIds = /* @__PURE__ */ new Set();
17595
+ var rememberToastId = (id) => {
17596
+ if (!id) return true;
17597
+ if (recentToastIds.has(id)) return false;
17598
+ recentToastIds.add(id);
17599
+ if (recentToastIds.size > 100) {
17600
+ const keep = [...recentToastIds].slice(-50);
17601
+ recentToastIds.clear();
17602
+ keep.forEach((value) => recentToastIds.add(value));
17603
+ }
17604
+ return true;
17605
+ };
17606
+ var resolveIncomingConversationId = (data) => String(
17607
+ data?.conversationId || data?.conversation_id || data?.conversationID || ""
17608
+ );
17609
+ var resolveToastText = (title, body) => {
17610
+ if (title && body) return `${title}: ${body}`;
17611
+ return title || body || "";
17612
+ };
17613
+ var emitToast = (payload, onPush) => {
17614
+ if (onPush && onPush(payload) !== false) return;
17615
+ const title = payload.title || payload.data?.title;
17616
+ const body = payload.body || payload.data?.body || payload.data?.message;
17617
+ const text = resolveToastText(title, body);
17618
+ if (text) showNotification(text, "info");
17619
+ };
17592
17620
  var ForegroundPushBridge = ({ onPush }) => {
17621
+ const lastDM = useStore((s) => s.lastDM);
17622
+ const onPushRef = useRef(onPush);
17623
+ onPushRef.current = onPush;
17624
+ useEffect(() => {
17625
+ if (!lastDM) return;
17626
+ if (typeof document !== "undefined" && document.visibilityState !== "visible") {
17627
+ return;
17628
+ }
17629
+ const state = useStore.getState();
17630
+ const loggedUserId = String(state.loggedUserDetails?._id || "");
17631
+ const conversationId = String(
17632
+ resolveConversationIdForIncomingMessage(
17633
+ lastDM,
17634
+ state.conversations,
17635
+ loggedUserId
17636
+ ) || lastDM.conversationId || ""
17637
+ );
17638
+ const messageId2 = String(lastDM._id || lastDM.id || "");
17639
+ const activeId = String(state.activeConversationId || "");
17640
+ const senderId = String(
17641
+ lastDM.sender?._id || lastDM.sender || lastDM.fromUserId || ""
17642
+ );
17643
+ if (!conversationId) return;
17644
+ if (loggedUserId && senderId && senderId === loggedUserId) return;
17645
+ if (activeId && conversationId === activeId) return;
17646
+ if (!rememberToastId(messageId2)) return;
17647
+ const isGroup = !!(lastDM.isGroup || lastDM.groupName || lastDM.conversationType === "group");
17648
+ const title = isGroup ? lastDM.groupName || lastDM.name || "Group" : lastDM.sender?.name || "New message";
17649
+ const body = typeof lastDM.content === "string" ? lastDM.content : lastDM.message?.content || (lastDM.attachments?.length ? "Sent an attachment" : "");
17650
+ console.debug("[realtimex-push] socket \u2192 toast:", {
17651
+ title,
17652
+ conversationId,
17653
+ activeConversationId: activeId
17654
+ });
17655
+ emitToast(
17656
+ {
17657
+ title,
17658
+ body,
17659
+ data: { conversationId, messageId: messageId2 }
17660
+ },
17661
+ onPushRef.current
17662
+ );
17663
+ }, [lastDM]);
17593
17664
  useEffect(() => {
17594
17665
  let unsubscribe = null;
17666
+ let retryTimer = null;
17595
17667
  let cancelled = false;
17596
17668
  const handlePayload = (payload) => {
17597
- const incoming = payload.data?.conversationId;
17598
- const activeId = useStore.getState().activeConversationId;
17599
- if (incoming && activeId && incoming === activeId) return;
17600
- if (onPush && onPush(payload) !== false) return;
17601
- const text = payload.title ? payload.body ? `${payload.title}: ${payload.body}` : payload.title : payload.body;
17602
- if (text) showNotification(text, "info");
17669
+ const incoming = resolveIncomingConversationId(payload.data);
17670
+ const activeId = String(
17671
+ useStore.getState().activeConversationId || ""
17672
+ );
17673
+ const messageId2 = String(
17674
+ payload.data?.messageId || payload.data?.message_id || payload.data?.messageID || ""
17675
+ );
17676
+ if (incoming && activeId && incoming === activeId) {
17677
+ console.debug(
17678
+ "[realtimex-push] foreground push suppressed (conversation open):",
17679
+ incoming
17680
+ );
17681
+ return;
17682
+ }
17683
+ if (!rememberToastId(messageId2)) return;
17684
+ console.debug("[realtimex-push] foreground push \u2192 toast:", {
17685
+ title: payload.title,
17686
+ conversationId: incoming,
17687
+ activeConversationId: activeId
17688
+ });
17689
+ emitToast(payload, onPushRef.current);
17603
17690
  };
17604
- const start = async () => {
17691
+ const start = async (attempt = 0) => {
17605
17692
  if (cancelled || unsubscribe || !getStoredPushToken()) return;
17606
17693
  try {
17607
17694
  const stop = await onForegroundPush(handlePayload);
17608
17695
  if (cancelled) stop();
17609
- else unsubscribe = stop;
17610
- } catch {
17696
+ else {
17697
+ unsubscribe = stop;
17698
+ console.debug(
17699
+ "[realtimex-push] foreground listener active"
17700
+ );
17701
+ }
17702
+ } catch (error) {
17703
+ if (cancelled || attempt >= RETRY_DELAYS_MS.length) {
17704
+ console.debug(
17705
+ "[realtimex-push] foreground listener NOT started:",
17706
+ error instanceof Error ? error.message : error
17707
+ );
17708
+ return;
17709
+ }
17710
+ retryTimer = setTimeout(
17711
+ () => void start(attempt + 1),
17712
+ RETRY_DELAYS_MS[attempt]
17713
+ );
17611
17714
  }
17612
17715
  };
17613
17716
  void start();
@@ -17622,11 +17725,19 @@ var ForegroundPushBridge = ({ onPush }) => {
17622
17725
  window.addEventListener(PUSH_CHANGED_EVENT, onPushChanged);
17623
17726
  return () => {
17624
17727
  cancelled = true;
17728
+ if (retryTimer) clearTimeout(retryTimer);
17625
17729
  unsubscribe?.();
17626
17730
  window.removeEventListener(PUSH_CHANGED_EVENT, onPushChanged);
17627
17731
  };
17628
- }, [onPush]);
17629
- return null;
17732
+ }, []);
17733
+ return /* @__PURE__ */ jsx(
17734
+ Toaster,
17735
+ {
17736
+ position: "top-right",
17737
+ toastOptions: { duration: 4e3 },
17738
+ containerStyle: { zIndex: 99999 }
17739
+ }
17740
+ );
17630
17741
  };
17631
17742
  var ChatMain = ({
17632
17743
  clientId,