@realtimexsco/live-chat 1.4.9 → 1.4.10

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
@@ -4,16 +4,16 @@ import { create } from 'zustand';
4
4
  import { persist } from 'zustand/middleware';
5
5
  import * as React2 from 'react';
6
6
  import React2__default, { createContext, useMemo, useContext, useState, useCallback, useRef, useEffect, useLayoutEffect, useSyncExternalStore } from 'react';
7
- import { Tooltip as Tooltip$1, Slot, Avatar as Avatar$1, ScrollArea as ScrollArea$1, Popover as Popover$1, DropdownMenu as DropdownMenu$1, Dialog as Dialog$1, Switch as Switch$1, AlertDialog as AlertDialog$1 } from 'radix-ui';
7
+ import { Tooltip as Tooltip$1, Slot, Switch as Switch$1, Avatar as Avatar$1, ScrollArea as ScrollArea$1, Popover as Popover$1, DropdownMenu as DropdownMenu$1, Dialog as Dialog$1, AlertDialog as AlertDialog$1 } from 'radix-ui';
8
8
  import { clsx } from 'clsx';
9
9
  import { twMerge } from 'tailwind-merge';
10
10
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
11
11
  import { flushSync } from 'react-dom';
12
- import { Sun, Moon, Search, X, Loader2, UserPlus, ChevronDown, ArrowLeft, Users, WifiOff, Wifi, Sparkles, MessageSquareText, ChevronRight, Pin, Star, MoreVertical, Info, UserKey, ShieldUser, Paperclip, Clock, MessageSquareX, Trash2, LogOut, Ban, CheckCheck, Check, Camera, Save, Pencil, Mail, CornerUpLeft, CheckSquare, Smile, ChevronLeftIcon, ChevronRightIcon, ChevronDownIcon, MessageCircleMore, History, Shield, Send, AlertCircle, ShieldCheck, UserMinus, MessageCircle, Phone, Video, ExternalLink, Download, ChevronLeft, ZoomOut, ZoomIn, RotateCcw, Music, ArrowRight, MoreHorizontal, PinOff, StarOff, XIcon, ImageIcon, Film, Play, Pause, FileText, FileSpreadsheet, FileIcon, Eye, Captions } from 'lucide-react';
12
+ import { Sun, Moon, Search, X, Loader2, UserPlus, ChevronDown, ArrowLeft, Users, WifiOff, Wifi, Sparkles, MessageSquareText, ChevronRight, Pin, Star, MoreVertical, Info, UserKey, ShieldUser, Paperclip, Clock, MessageSquareX, Trash2, LogOut, Ban, CheckCheck, Check, Camera, Save, Pencil, Mail, CornerUpLeft, CheckSquare, Smile, ChevronLeftIcon, ChevronRightIcon, ChevronDownIcon, MessageCircleMore, History, Shield, Send, AlertCircle, ShieldCheck, UserMinus, Settings, MessageCircle, Phone, Video, ExternalLink, Download, ChevronLeft, ZoomOut, ZoomIn, RotateCcw, Music, ArrowRight, MoreHorizontal, PinOff, StarOff, XIcon, ImageIcon, Film, Play, Pause, FileText, FileSpreadsheet, FileIcon, MessageSquare, Eye, Captions } from 'lucide-react';
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 toast2, { toast, Toaster } from 'react-hot-toast';
16
+ import toast$1, { Toaster, toast } from 'react-hot-toast';
17
17
 
18
18
  var __defProp = Object.defineProperty;
19
19
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -4632,7 +4632,9 @@ init_store_helpers();
4632
4632
  var OPEN_CONVERSATION_EVENT = "realtimex:open-conversation";
4633
4633
  var NOTIFICATION_CLICK_SW_TYPE = "realtimex:notification-click";
4634
4634
  var PUSH_BROADCAST_CHANNEL = "realtimex-push";
4635
+ var PUSH_DATA_CACHE_NAME = "realtimex-push-data-v1";
4635
4636
  var PENDING_STORAGE_KEY = "realtimex:pending-open-conversation";
4637
+ var PENDING_OPEN_CACHE_PATH = "pending-open";
4636
4638
  var resolveConversationIdFromPushData = (data) => {
4637
4639
  if (!data || typeof data !== "object") return "";
4638
4640
  let fcmMsg = data.FCM_MSG;
@@ -4773,6 +4775,37 @@ var mapConversationToChannel = (conversation, loggedUserId, allUsers) => {
4773
4775
  starredCount: conversation.starredCount
4774
4776
  };
4775
4777
  };
4778
+ var stripConversationIdFromUrl = () => {
4779
+ if (typeof window === "undefined") return;
4780
+ try {
4781
+ const url = new URL(window.location.href);
4782
+ if (!url.searchParams.has("conversationId")) return;
4783
+ url.searchParams.delete("conversationId");
4784
+ const next = `${url.pathname}${url.search}${url.hash}`;
4785
+ window.history.replaceState(window.history.state, "", next);
4786
+ } catch {
4787
+ }
4788
+ };
4789
+ var cacheRequestForPath = (path) => new Request(new URL(path, window.location.origin).toString());
4790
+ var consumePendingOpenFromPushCache = async () => {
4791
+ if (typeof caches === "undefined") return null;
4792
+ try {
4793
+ const cache = await caches.open(PUSH_DATA_CACHE_NAME);
4794
+ const req = cacheRequestForPath(PENDING_OPEN_CACHE_PATH);
4795
+ const res = await cache.match(req);
4796
+ if (!res) return null;
4797
+ await cache.delete(req);
4798
+ const data = await res.json();
4799
+ const conversationId = resolveConversationIdFromPushData(data);
4800
+ if (!conversationId) return null;
4801
+ return {
4802
+ conversationId,
4803
+ ...normalizePushMeta(data)
4804
+ };
4805
+ } catch {
4806
+ return null;
4807
+ }
4808
+ };
4776
4809
  var readConversationIdFromLocation = () => {
4777
4810
  try {
4778
4811
  return new URLSearchParams(window.location.search).get("conversationId") || "";
@@ -4781,16 +4814,33 @@ var readConversationIdFromLocation = () => {
4781
4814
  }
4782
4815
  };
4783
4816
  var consumedUrlConversationIds = /* @__PURE__ */ new Set();
4817
+ var lastHandledOpenId = "";
4818
+ var lastHandledOpenAt = 0;
4819
+ var shouldHandleOpen = (conversationId) => {
4820
+ const id = String(conversationId || "").trim();
4821
+ if (!id) return false;
4822
+ const now = Date.now();
4823
+ if (lastHandledOpenId === id && now - lastHandledOpenAt < 2500) {
4824
+ return false;
4825
+ }
4826
+ lastHandledOpenId = id;
4827
+ lastHandledOpenAt = now;
4828
+ return true;
4829
+ };
4784
4830
  var handleNotificationOpen = (conversationId, pushData, options) => {
4785
4831
  const id = String(conversationId || "").trim();
4786
4832
  if (!id) {
4787
4833
  console.warn("[realtimex-push] notification open ignored \u2014 no conversationId", pushData);
4788
4834
  return;
4789
4835
  }
4836
+ if (!shouldHandleOpen(id)) {
4837
+ stripConversationIdFromUrl();
4838
+ return;
4839
+ }
4790
4840
  requestOpenConversation(id, pushData);
4791
4841
  const chatPath = options.chatPath || "/chat";
4792
- const pathWithQuery = `${chatPath}?conversationId=${encodeURIComponent(id)}`;
4793
- options.onNavigate?.(id, pathWithQuery);
4842
+ stripConversationIdFromUrl();
4843
+ options.onNavigate?.(id, chatPath);
4794
4844
  };
4795
4845
  var installNotificationClickBridge = (options = {}) => {
4796
4846
  if (typeof window === "undefined") return () => void 0;
@@ -4817,7 +4867,17 @@ var installNotificationClickBridge = (options = {}) => {
4817
4867
  if (fromUrl && !consumedUrlConversationIds.has(fromUrl)) {
4818
4868
  consumedUrlConversationIds.add(fromUrl);
4819
4869
  handleNotificationOpen(fromUrl, void 0, options);
4870
+ } else {
4871
+ stripConversationIdFromUrl();
4820
4872
  }
4873
+ void consumePendingOpenFromPushCache().then((request) => {
4874
+ if (!request?.conversationId) return;
4875
+ handleNotificationOpen(
4876
+ request.conversationId,
4877
+ request,
4878
+ options
4879
+ );
4880
+ });
4821
4881
  return () => {
4822
4882
  navigator.serviceWorker?.removeEventListener("message", onSwMessage);
4823
4883
  broadcast?.close();
@@ -6455,194 +6515,572 @@ var CreateChatDialog = (props) => {
6455
6515
  );
6456
6516
  };
6457
6517
  var CreateChatDialog_default = CreateChatDialog;
6458
- var LoggedUserDetails = ({
6459
- loggedUserDetails,
6460
- onUserSelect,
6461
- isCreateModalOpen = false,
6462
- setIsCreateModalOpen,
6463
- searchQuery = "",
6464
- setSearchQuery
6465
- }) => {
6466
- const { showColorModeToggle } = useChatTheme();
6467
- const user = {
6468
- _id: loggedUserDetails?._id || "1",
6469
- name: formatLoggedUserName(loggedUserDetails?.name),
6470
- email: loggedUserDetails?.email || "user@example.com",
6471
- role: loggedUserDetails?.role || "user",
6472
- isActive: loggedUserDetails?.isActive ?? true,
6473
- createdAt: loggedUserDetails?.createdAt ? new Date(loggedUserDetails.createdAt) : /* @__PURE__ */ new Date(),
6474
- updatedAt: loggedUserDetails?.updatedAt ? new Date(loggedUserDetails.updatedAt) : /* @__PURE__ */ new Date(),
6475
- image: loggedUserDetails?.image || void 0
6476
- };
6477
- return /* @__PURE__ */ jsxs("div", { className: "shrink-0 border-b border-(--chat-border) bg-(--chat-surface) px-3 pb-3 pt-3", children: [
6478
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-2.5", children: [
6479
- /* @__PURE__ */ jsxs("div", { className: "relative shrink-0", children: [
6480
- /* @__PURE__ */ jsxs(Avatar, { className: "size-8 ring-1 ring-(--chat-surface)", children: [
6481
- user.image ? /* @__PURE__ */ jsx(AvatarImage, { src: user.image, alt: user.name }) : null,
6482
- /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-(--chat-theme-10) text-[10px] font-medium text-(--chat-theme)", children: (user.name || "?").charAt(0).toUpperCase() })
6483
- ] }),
6484
- /* @__PURE__ */ jsx("span", { className: "absolute -bottom-0.5 -right-0.5 size-2 rounded-full border-2 border-(--chat-surface) bg-(--chat-online)" })
6485
- ] }),
6486
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
6487
- /* @__PURE__ */ jsx("h2", { className: "truncate text-xs font-medium leading-tight text-(--chat-text)", children: user.name }),
6488
- /* @__PURE__ */ jsx("p", { className: "truncate text-[10px] text-(--chat-muted)", children: user.email })
6489
- ] }),
6490
- showColorModeToggle ? /* @__PURE__ */ jsx(ChatThemeToggle_default, {}) : null
6491
- ] }),
6492
- /* @__PURE__ */ jsxs("div", { className: "mt-3 flex items-center gap-1.5", children: [
6493
- /* @__PURE__ */ jsxs("div", { className: chatSidebarSearchShellClass, children: [
6494
- /* @__PURE__ */ jsx(Search, { className: "pointer-events-none size-3.5 shrink-0 text-(--chat-muted)" }),
6495
- /* @__PURE__ */ jsx(
6496
- "input",
6497
- {
6498
- type: "text",
6499
- inputMode: "search",
6500
- enterKeyHint: "search",
6501
- placeholder: "Search conversations...",
6502
- value: searchQuery,
6503
- onChange: (e) => setSearchQuery?.(e.target.value),
6504
- className: chatSidebarSearchInputClass
6505
- }
6506
- ),
6507
- searchQuery ? /* @__PURE__ */ jsx(
6508
- "button",
6509
- {
6510
- type: "button",
6511
- onClick: () => setSearchQuery?.(""),
6512
- className: "flex size-6 shrink-0 items-center justify-center rounded-md text-(--chat-muted) transition-colors hover:bg-(--chat-hover) hover:text-(--chat-text)",
6513
- "aria-label": "Clear search",
6514
- children: /* @__PURE__ */ jsx(X, { size: 12 })
6515
- }
6516
- ) : null
6517
- ] }),
6518
- /* @__PURE__ */ jsx(
6519
- CreateChatDialog_default,
6520
- {
6521
- loggedUserDetails,
6522
- onUserSelect,
6523
- isCreateModalOpen,
6524
- setIsCreateModalOpen
6525
- }
6526
- )
6527
- ] })
6528
- ] });
6529
- };
6530
- var LoggedUserDetails_default = LoggedUserDetails;
6531
- function ScrollArea({
6532
- className,
6533
- children,
6534
- ...props
6535
- }) {
6536
- return /* @__PURE__ */ jsxs(
6537
- ScrollArea$1.Root,
6538
- {
6539
- "data-slot": "scroll-area",
6540
- className: cn("relative", className),
6541
- ...props,
6542
- children: [
6543
- /* @__PURE__ */ jsx(
6544
- ScrollArea$1.Viewport,
6545
- {
6546
- "data-slot": "scroll-area-viewport",
6547
- className: "focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1",
6548
- children
6549
- }
6550
- ),
6551
- /* @__PURE__ */ jsx(ScrollBar, {}),
6552
- /* @__PURE__ */ jsx(ScrollArea$1.Corner, {})
6553
- ]
6554
- }
6555
- );
6556
- }
6557
- function ScrollBar({
6518
+ function Switch({
6558
6519
  className,
6559
- orientation = "vertical",
6520
+ size = "default",
6560
6521
  ...props
6561
6522
  }) {
6562
6523
  return /* @__PURE__ */ jsx(
6563
- ScrollArea$1.ScrollAreaScrollbar,
6524
+ Switch$1.Root,
6564
6525
  {
6565
- "data-slot": "scroll-area-scrollbar",
6566
- orientation,
6526
+ "data-slot": "switch",
6527
+ "data-size": size,
6567
6528
  className: cn(
6568
- "flex touch-none p-px transition-colors select-none",
6569
- orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent",
6570
- orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent",
6529
+ "peer group/switch inline-flex shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-[1.15rem] data-[size=default]:w-8 data-[size=sm]:h-3.5 data-[size=sm]:w-6 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input dark:data-[state=unchecked]:bg-input/80",
6571
6530
  className
6572
6531
  ),
6573
6532
  ...props,
6574
6533
  children: /* @__PURE__ */ jsx(
6575
- ScrollArea$1.ScrollAreaThumb,
6534
+ Switch$1.Thumb,
6576
6535
  {
6577
- "data-slot": "scroll-area-thumb",
6578
- className: "bg-border relative flex-1 rounded-full"
6536
+ "data-slot": "switch-thumb",
6537
+ className: cn(
6538
+ "pointer-events-none block rounded-full bg-background ring-0 transition-transform group-data-[size=default]/switch:size-4 group-data-[size=sm]/switch:size-3 data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0 dark:data-[state=checked]:bg-primary-foreground dark:data-[state=unchecked]:bg-foreground"
6539
+ )
6579
6540
  }
6580
6541
  )
6581
6542
  }
6582
6543
  );
6583
6544
  }
6584
6545
 
6585
- // src/chat/channel-list/useChannelList.ts
6586
- init_useStore();
6587
- init_store_helpers();
6588
- var conversationDrafts = /* @__PURE__ */ new Map();
6589
- var DRAFT_PREVIEW_MAX_LENGTH = 50;
6590
- var emptyDraft = () => ({
6591
- messageInput: "",
6592
- attachments: []
6593
- });
6594
- var draftRevision = 0;
6595
- var draftListeners = /* @__PURE__ */ new Set();
6596
- function notifyDraftChange() {
6597
- draftRevision += 1;
6598
- draftListeners.forEach((listener) => listener());
6599
- }
6600
- function subscribeToDrafts(listener) {
6601
- draftListeners.add(listener);
6602
- return () => {
6603
- draftListeners.delete(listener);
6604
- };
6605
- }
6606
- function getDraftRevision() {
6607
- return draftRevision;
6608
- }
6609
- function useDraftRevision() {
6610
- return useSyncExternalStore(subscribeToDrafts, getDraftRevision, getDraftRevision);
6611
- }
6612
- function getConversationDraft(conversationId) {
6613
- if (!conversationId) return emptyDraft();
6614
- return conversationDrafts.get(conversationId) ?? emptyDraft();
6615
- }
6616
- function updateConversationDraft(conversationId, draft) {
6617
- if (!conversationId) return;
6618
- if (draft.messageInput.trim() || draft.attachments.length > 0) {
6619
- conversationDrafts.set(conversationId, {
6620
- messageInput: draft.messageInput,
6621
- attachments: draft.attachments
6622
- });
6623
- } else {
6624
- conversationDrafts.delete(conversationId);
6546
+ // src/notifications/push.service.ts
6547
+ init_client();
6548
+ var PUSH_TOKEN_STORAGE_KEY = "realtimex-push-token";
6549
+ var SERVICE_WORKER_PATH = "/firebase-messaging-sw.js";
6550
+ var PUSH_CHANGED_EVENT = "realtimex:push-changed";
6551
+ var emitPushChanged = (enabled) => {
6552
+ try {
6553
+ window.dispatchEvent(
6554
+ new CustomEvent(PUSH_CHANGED_EVENT, { detail: { enabled } })
6555
+ );
6556
+ } catch {
6625
6557
  }
6626
- notifyDraftChange();
6627
- }
6628
- function clearConversationDraft(conversationId) {
6629
- if (!conversationId) return;
6630
- if (!conversationDrafts.has(conversationId)) return;
6631
- conversationDrafts.delete(conversationId);
6632
- notifyDraftChange();
6633
- }
6634
- function getConversationDraftPreview(conversationId) {
6635
- if (!conversationId) return null;
6636
- const draft = conversationDrafts.get(conversationId);
6637
- if (!draft) return null;
6638
- const text = draft.messageInput.trim();
6639
- if (text) {
6640
- return text.length > DRAFT_PREVIEW_MAX_LENGTH ? `${text.slice(0, DRAFT_PREVIEW_MAX_LENGTH)}\u2026` : text;
6558
+ };
6559
+ var v2Url = "https://realtimex.softwareco.com/api/v2";
6560
+ var apiGetPushConfig = async () => {
6561
+ const { data } = await apiClient.get(`${v2Url}/notifications/push/config`);
6562
+ return data?.data;
6563
+ };
6564
+ var apiRegisterPushToken = async (token, deviceLabel) => {
6565
+ const { data } = await apiClient.post(`${v2Url}/notifications/push/token`, {
6566
+ token,
6567
+ deviceLabel
6568
+ });
6569
+ return data?.data;
6570
+ };
6571
+ var apiRemovePushToken = async (token) => {
6572
+ const { data } = await apiClient.delete(`${v2Url}/notifications/push/token`, {
6573
+ data: { token }
6574
+ });
6575
+ return data;
6576
+ };
6577
+ var apiGetPushPreference = async () => {
6578
+ const { data } = await apiClient.get(
6579
+ `${v2Url}/notifications/push/preference`
6580
+ );
6581
+ return data?.data;
6582
+ };
6583
+ var apiUpdatePushPreference = async (enabled) => {
6584
+ const { data } = await apiClient.patch(
6585
+ `${v2Url}/notifications/push/preference`,
6586
+ { enabled }
6587
+ );
6588
+ return data?.data;
6589
+ };
6590
+ var isPushSupported = () => typeof window !== "undefined" && "Notification" in window && "serviceWorker" in navigator && "PushManager" in window;
6591
+ var getStoredPushToken = () => {
6592
+ try {
6593
+ return localStorage.getItem(PUSH_TOKEN_STORAGE_KEY);
6594
+ } catch {
6595
+ return null;
6641
6596
  }
6642
- if (draft.attachments.length > 0) {
6643
- return draft.attachments.length === 1 ? "Attachment" : `${draft.attachments.length} attachments`;
6597
+ };
6598
+ var storePushToken = (token) => {
6599
+ try {
6600
+ if (token) localStorage.setItem(PUSH_TOKEN_STORAGE_KEY, token);
6601
+ else localStorage.removeItem(PUSH_TOKEN_STORAGE_KEY);
6602
+ } catch {
6644
6603
  }
6645
- return null;
6604
+ };
6605
+ var defaultDeviceLabel = () => {
6606
+ const ua = navigator.userAgent;
6607
+ const browser = /edg\//i.test(ua) ? "Edge" : /chrome/i.test(ua) ? "Chrome" : /safari/i.test(ua) ? "Safari" : /firefox/i.test(ua) ? "Firefox" : "Browser";
6608
+ const os = /mac/i.test(ua) ? "macOS" : /windows/i.test(ua) ? "Windows" : /android/i.test(ua) ? "Android" : /iphone|ipad/i.test(ua) ? "iOS" : /linux/i.test(ua) ? "Linux" : "Unknown OS";
6609
+ return `${browser} on ${os}`;
6610
+ };
6611
+ var loadFirebaseMessaging = async () => {
6612
+ try {
6613
+ const [{ initializeApp, getApps }, messagingModule] = await Promise.all([
6614
+ import('firebase/app'),
6615
+ import('firebase/messaging')
6616
+ ]);
6617
+ return { initializeApp, getApps, ...messagingModule };
6618
+ } catch {
6619
+ throw new Error(
6620
+ 'Push notifications need the "firebase" package \u2014 run: npm install firebase'
6621
+ );
6622
+ }
6623
+ };
6624
+ var getFirebaseMessaging = async (firebaseConfig) => {
6625
+ const fb = await loadFirebaseMessaging();
6626
+ const app = fb.getApps().length ? fb.getApps()[0] : fb.initializeApp(firebaseConfig);
6627
+ return { fb, messaging: fb.getMessaging(app) };
6628
+ };
6629
+ var enablePushOnThisDevice = async () => {
6630
+ if (!isPushSupported()) {
6631
+ throw new Error("Push notifications are not supported in this browser");
6632
+ }
6633
+ const config = await apiGetPushConfig();
6634
+ if (!config?.enabled) {
6635
+ throw new Error("Push notifications are disabled for this workspace");
6636
+ }
6637
+ if (!config.configured || !config.firebaseConfig || !config.vapidKey) {
6638
+ throw new Error(
6639
+ "Push notifications are not configured on the server yet"
6640
+ );
6641
+ }
6642
+ const permission = await Notification.requestPermission();
6643
+ if (permission !== "granted") {
6644
+ throw new Error("Notification permission was not granted");
6645
+ }
6646
+ let registration;
6647
+ try {
6648
+ registration = await navigator.serviceWorker.register(
6649
+ `${SERVICE_WORKER_PATH}?config=${encodeURIComponent(
6650
+ JSON.stringify(config.firebaseConfig)
6651
+ )}`
6652
+ );
6653
+ } catch {
6654
+ throw new Error(
6655
+ `Could not register ${SERVICE_WORKER_PATH} \u2014 copy it from node_modules/@realtimexsco/live-chat/dist/firebase-messaging-sw.js into your app's public folder`
6656
+ );
6657
+ }
6658
+ const { fb, messaging } = await getFirebaseMessaging(config.firebaseConfig);
6659
+ const token = await fb.getToken(messaging, {
6660
+ vapidKey: config.vapidKey,
6661
+ serviceWorkerRegistration: registration
6662
+ });
6663
+ if (!token) {
6664
+ throw new Error("Could not obtain a push token from Firebase");
6665
+ }
6666
+ await apiRegisterPushToken(token, defaultDeviceLabel());
6667
+ storePushToken(token);
6668
+ emitPushChanged(true);
6669
+ return token;
6670
+ };
6671
+ var disablePushOnThisDevice = async () => {
6672
+ const token = getStoredPushToken();
6673
+ if (!token) return;
6674
+ try {
6675
+ const config = await apiGetPushConfig();
6676
+ if (config?.firebaseConfig) {
6677
+ const { fb, messaging } = await getFirebaseMessaging(
6678
+ config.firebaseConfig
6679
+ );
6680
+ await fb.deleteToken(messaging).catch(() => void 0);
6681
+ }
6682
+ } catch {
6683
+ }
6684
+ await apiRemovePushToken(token).catch(() => void 0);
6685
+ storePushToken(null);
6686
+ emitPushChanged(false);
6687
+ };
6688
+ var onForegroundPush = async (callback) => {
6689
+ const config = await apiGetPushConfig();
6690
+ if (!config?.configured || !config.firebaseConfig) {
6691
+ throw new Error("Push config unavailable (not configured or API not ready)");
6692
+ }
6693
+ const { fb, messaging } = await getFirebaseMessaging(config.firebaseConfig);
6694
+ return fb.onMessage(messaging, (payload) => {
6695
+ console.log("[realtimex-push] FCM foreground payload (raw):", payload);
6696
+ console.log("[realtimex-push] FCM foreground data:", payload?.data);
6697
+ console.log("[realtimex-push] FCM foreground notification:", payload?.notification);
6698
+ callback({
6699
+ title: payload?.notification?.title,
6700
+ body: payload?.notification?.body,
6701
+ data: payload?.data
6702
+ });
6703
+ });
6704
+ };
6705
+
6706
+ // src/notifications/usePushNotifications.ts
6707
+ var usePushNotifications = () => {
6708
+ const [state, setState] = useState({
6709
+ supported: false,
6710
+ allowedByWorkspace: false,
6711
+ configured: false,
6712
+ permission: "unsupported",
6713
+ userEnabled: true,
6714
+ deviceEnabled: false,
6715
+ loading: true,
6716
+ error: null
6717
+ });
6718
+ const refresh = useCallback(async () => {
6719
+ if (!isPushSupported()) {
6720
+ setState((prev) => ({
6721
+ ...prev,
6722
+ supported: false,
6723
+ loading: false
6724
+ }));
6725
+ return;
6726
+ }
6727
+ try {
6728
+ const [config, preference] = await Promise.all([
6729
+ apiGetPushConfig(),
6730
+ apiGetPushPreference().catch(() => null)
6731
+ ]);
6732
+ setState({
6733
+ supported: true,
6734
+ allowedByWorkspace: Boolean(config?.enabled),
6735
+ configured: Boolean(config?.configured),
6736
+ permission: Notification.permission,
6737
+ userEnabled: preference?.enabled ?? true,
6738
+ deviceEnabled: Notification.permission === "granted" && Boolean(getStoredPushToken()),
6739
+ loading: false,
6740
+ error: null
6741
+ });
6742
+ } catch (error) {
6743
+ setState((prev) => ({
6744
+ ...prev,
6745
+ supported: true,
6746
+ loading: false,
6747
+ error: error instanceof Error ? error.message : "Could not load push settings"
6748
+ }));
6749
+ }
6750
+ }, []);
6751
+ useEffect(() => {
6752
+ void refresh();
6753
+ }, [refresh]);
6754
+ const enable = useCallback(async () => {
6755
+ setState((prev) => ({ ...prev, loading: true, error: null }));
6756
+ try {
6757
+ await enablePushOnThisDevice();
6758
+ await refresh();
6759
+ return true;
6760
+ } catch (error) {
6761
+ setState((prev) => ({
6762
+ ...prev,
6763
+ loading: false,
6764
+ permission: isPushSupported() ? Notification.permission : "unsupported",
6765
+ error: error instanceof Error ? error.message : "Could not enable push notifications"
6766
+ }));
6767
+ return false;
6768
+ }
6769
+ }, [refresh]);
6770
+ const disable = useCallback(async () => {
6771
+ setState((prev) => ({ ...prev, loading: true, error: null }));
6772
+ try {
6773
+ await disablePushOnThisDevice();
6774
+ } finally {
6775
+ await refresh();
6776
+ }
6777
+ }, [refresh]);
6778
+ const setUserEnabled = useCallback(
6779
+ async (enabled) => {
6780
+ setState((prev) => ({ ...prev, userEnabled: enabled }));
6781
+ try {
6782
+ await apiUpdatePushPreference(enabled);
6783
+ } catch (error) {
6784
+ setState((prev) => ({
6785
+ ...prev,
6786
+ userEnabled: !enabled,
6787
+ error: error instanceof Error ? error.message : "Could not update push preference"
6788
+ }));
6789
+ }
6790
+ },
6791
+ []
6792
+ );
6793
+ return { ...state, enable, disable, setUserEnabled, refresh };
6794
+ };
6795
+ var PushNotificationToggle = ({
6796
+ className,
6797
+ label = "Push notifications",
6798
+ description = "Get notified about new messages on this device"
6799
+ }) => {
6800
+ const push = usePushNotifications();
6801
+ if (!push.supported || !push.allowedByWorkspace || !push.configured) {
6802
+ return null;
6803
+ }
6804
+ const isOn = push.deviceEnabled && push.userEnabled;
6805
+ const permissionBlocked = push.permission === "denied";
6806
+ const handleChange = async (checked) => {
6807
+ if (checked) {
6808
+ if (!push.userEnabled) await push.setUserEnabled(true);
6809
+ if (!push.deviceEnabled) await push.enable();
6810
+ } else {
6811
+ await push.disable();
6812
+ }
6813
+ };
6814
+ return /* @__PURE__ */ jsxs(
6815
+ "div",
6816
+ {
6817
+ className: className ?? "flex items-center justify-between gap-4 rounded-xl border border-(--chat-border) bg-(--chat-surface) px-4 py-3",
6818
+ children: [
6819
+ /* @__PURE__ */ jsxs("div", { className: "space-y-0.5", children: [
6820
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-(--chat-text)", children: label }),
6821
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-(--chat-muted)", children: permissionBlocked ? "Notifications are blocked in your browser settings" : push.error ?? description })
6822
+ ] }),
6823
+ /* @__PURE__ */ jsx(
6824
+ Switch,
6825
+ {
6826
+ checked: isOn,
6827
+ disabled: push.loading || permissionBlocked,
6828
+ onCheckedChange: (checked) => void handleChange(checked),
6829
+ "aria-label": `Toggle ${label}`
6830
+ }
6831
+ )
6832
+ ]
6833
+ }
6834
+ );
6835
+ };
6836
+ var LoggedUserSettingsDialog = ({
6837
+ loggedUserDetails
6838
+ }) => {
6839
+ const [open, setOpen] = useState(false);
6840
+ const user = {
6841
+ _id: loggedUserDetails?._id || "1",
6842
+ name: formatLoggedUserName(loggedUserDetails?.name),
6843
+ email: loggedUserDetails?.email || "user@example.com",
6844
+ role: loggedUserDetails?.role || "user",
6845
+ isActive: loggedUserDetails?.isActive ?? true,
6846
+ createdAt: loggedUserDetails?.createdAt ? new Date(loggedUserDetails.createdAt) : /* @__PURE__ */ new Date(),
6847
+ updatedAt: loggedUserDetails?.updatedAt ? new Date(loggedUserDetails.updatedAt) : /* @__PURE__ */ new Date(),
6848
+ image: loggedUserDetails?.image || void 0
6849
+ };
6850
+ return /* @__PURE__ */ jsxs(Dialog, { open, onOpenChange: setOpen, children: [
6851
+ /* @__PURE__ */ jsxs(Tooltip, { children: [
6852
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
6853
+ Button,
6854
+ {
6855
+ type: "button",
6856
+ variant: "ghost",
6857
+ size: "icon",
6858
+ className: sidebarActionBtnClass,
6859
+ "aria-label": "Account settings",
6860
+ onClick: () => setOpen(true),
6861
+ children: /* @__PURE__ */ jsx(Settings, { className: "size-3.5", strokeWidth: 2 })
6862
+ }
6863
+ ) }),
6864
+ /* @__PURE__ */ jsx(TooltipContent, { side: "bottom", children: "Settings" })
6865
+ ] }),
6866
+ /* @__PURE__ */ jsxs(ChatDialogContent, { className: "gap-0 overflow-hidden p-0 sm:max-w-[380px]", children: [
6867
+ /* @__PURE__ */ jsx("div", { className: "border-b border-(--chat-border) px-5 py-4", children: /* @__PURE__ */ jsx(DialogTitle, { className: "text-left text-base font-semibold text-(--chat-text)", children: "Account settings" }) }),
6868
+ /* @__PURE__ */ jsxs("div", { className: "space-y-5 px-5 py-5", children: [
6869
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center text-center", children: [
6870
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
6871
+ /* @__PURE__ */ jsxs(Avatar, { className: "size-16 ring-2 ring-(--chat-theme-20)", children: [
6872
+ user.image ? /* @__PURE__ */ jsx(AvatarImage, { src: user.image, alt: user.name }) : null,
6873
+ /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-(--chat-theme-10) text-lg font-medium text-(--chat-theme)", children: (user.name || "?").charAt(0).toUpperCase() })
6874
+ ] }),
6875
+ /* @__PURE__ */ jsx("span", { className: "absolute bottom-0.5 right-0.5 size-3 rounded-full border-2 border-(--chat-surface) bg-(--chat-online)" })
6876
+ ] }),
6877
+ /* @__PURE__ */ jsx("h3", { className: "mt-3 text-base font-semibold text-(--chat-text)", children: user.name }),
6878
+ /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-sm text-(--chat-muted)", children: user.email }),
6879
+ /* @__PURE__ */ jsxs("p", { className: "mt-2 inline-flex items-center gap-1.5 rounded-full bg-(--chat-theme-10) px-2.5 py-0.5 text-xs font-medium text-(--chat-theme)", children: [
6880
+ /* @__PURE__ */ jsx("span", { className: "size-1.5 rounded-full bg-(--chat-online)" }),
6881
+ "Online"
6882
+ ] })
6883
+ ] }),
6884
+ /* @__PURE__ */ jsx("div", { className: "border-t border-(--chat-border) pt-4", children: /* @__PURE__ */ jsx(PushNotificationToggle, { className: "flex items-center justify-between gap-4 rounded-xl border border-(--chat-border) bg-(--chat-theme-10) px-4 py-3" }) })
6885
+ ] })
6886
+ ] })
6887
+ ] });
6888
+ };
6889
+ var LoggedUserSettingsDialog_default = LoggedUserSettingsDialog;
6890
+ var LoggedUserDetails = ({
6891
+ loggedUserDetails,
6892
+ onUserSelect,
6893
+ isCreateModalOpen = false,
6894
+ setIsCreateModalOpen,
6895
+ searchQuery = "",
6896
+ setSearchQuery
6897
+ }) => {
6898
+ const { showColorModeToggle } = useChatTheme();
6899
+ const user = {
6900
+ _id: loggedUserDetails?._id || "1",
6901
+ name: formatLoggedUserName(loggedUserDetails?.name),
6902
+ email: loggedUserDetails?.email || "user@example.com",
6903
+ role: loggedUserDetails?.role || "user",
6904
+ isActive: loggedUserDetails?.isActive ?? true,
6905
+ createdAt: loggedUserDetails?.createdAt ? new Date(loggedUserDetails.createdAt) : /* @__PURE__ */ new Date(),
6906
+ updatedAt: loggedUserDetails?.updatedAt ? new Date(loggedUserDetails.updatedAt) : /* @__PURE__ */ new Date(),
6907
+ image: loggedUserDetails?.image || void 0
6908
+ };
6909
+ return /* @__PURE__ */ jsxs("div", { className: "shrink-0 border-b border-(--chat-border) bg-(--chat-surface) px-3 pb-3 pt-3", children: [
6910
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-2.5", children: [
6911
+ /* @__PURE__ */ jsxs("div", { className: "relative shrink-0", children: [
6912
+ /* @__PURE__ */ jsxs(Avatar, { className: "size-8 ring-1 ring-(--chat-surface)", children: [
6913
+ user.image ? /* @__PURE__ */ jsx(AvatarImage, { src: user.image, alt: user.name }) : null,
6914
+ /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-(--chat-theme-10) text-[10px] font-medium text-(--chat-theme)", children: (user.name || "?").charAt(0).toUpperCase() })
6915
+ ] }),
6916
+ /* @__PURE__ */ jsx("span", { className: "absolute -bottom-0.5 -right-0.5 size-2 rounded-full border-2 border-(--chat-surface) bg-(--chat-online)" })
6917
+ ] }),
6918
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
6919
+ /* @__PURE__ */ jsxs("h2", { className: "truncate text-xs font-medium leading-tight text-(--chat-text)", children: [
6920
+ user.name,
6921
+ "123"
6922
+ ] }),
6923
+ /* @__PURE__ */ jsx("p", { className: "truncate text-[10px] text-(--chat-muted)", children: user.email })
6924
+ ] }),
6925
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-0.5", children: [
6926
+ /* @__PURE__ */ jsx(LoggedUserSettingsDialog_default, { loggedUserDetails }),
6927
+ showColorModeToggle ? /* @__PURE__ */ jsx(ChatThemeToggle_default, {}) : null
6928
+ ] })
6929
+ ] }),
6930
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 flex items-center gap-1.5", children: [
6931
+ /* @__PURE__ */ jsxs("div", { className: chatSidebarSearchShellClass, children: [
6932
+ /* @__PURE__ */ jsx(Search, { className: "pointer-events-none size-3.5 shrink-0 text-(--chat-muted)" }),
6933
+ /* @__PURE__ */ jsx(
6934
+ "input",
6935
+ {
6936
+ type: "text",
6937
+ inputMode: "search",
6938
+ enterKeyHint: "search",
6939
+ placeholder: "Search conversations...",
6940
+ value: searchQuery,
6941
+ onChange: (e) => setSearchQuery?.(e.target.value),
6942
+ className: chatSidebarSearchInputClass
6943
+ }
6944
+ ),
6945
+ searchQuery ? /* @__PURE__ */ jsx(
6946
+ "button",
6947
+ {
6948
+ type: "button",
6949
+ onClick: () => setSearchQuery?.(""),
6950
+ className: "flex size-6 shrink-0 items-center justify-center rounded-md text-(--chat-muted) transition-colors hover:bg-(--chat-hover) hover:text-(--chat-text)",
6951
+ "aria-label": "Clear search",
6952
+ children: /* @__PURE__ */ jsx(X, { size: 12 })
6953
+ }
6954
+ ) : null
6955
+ ] }),
6956
+ /* @__PURE__ */ jsx(
6957
+ CreateChatDialog_default,
6958
+ {
6959
+ loggedUserDetails,
6960
+ onUserSelect,
6961
+ isCreateModalOpen,
6962
+ setIsCreateModalOpen
6963
+ }
6964
+ )
6965
+ ] })
6966
+ ] });
6967
+ };
6968
+ var LoggedUserDetails_default = LoggedUserDetails;
6969
+ function ScrollArea({
6970
+ className,
6971
+ children,
6972
+ ...props
6973
+ }) {
6974
+ return /* @__PURE__ */ jsxs(
6975
+ ScrollArea$1.Root,
6976
+ {
6977
+ "data-slot": "scroll-area",
6978
+ className: cn("relative", className),
6979
+ ...props,
6980
+ children: [
6981
+ /* @__PURE__ */ jsx(
6982
+ ScrollArea$1.Viewport,
6983
+ {
6984
+ "data-slot": "scroll-area-viewport",
6985
+ className: "focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1",
6986
+ children
6987
+ }
6988
+ ),
6989
+ /* @__PURE__ */ jsx(ScrollBar, {}),
6990
+ /* @__PURE__ */ jsx(ScrollArea$1.Corner, {})
6991
+ ]
6992
+ }
6993
+ );
6994
+ }
6995
+ function ScrollBar({
6996
+ className,
6997
+ orientation = "vertical",
6998
+ ...props
6999
+ }) {
7000
+ return /* @__PURE__ */ jsx(
7001
+ ScrollArea$1.ScrollAreaScrollbar,
7002
+ {
7003
+ "data-slot": "scroll-area-scrollbar",
7004
+ orientation,
7005
+ className: cn(
7006
+ "flex touch-none p-px transition-colors select-none",
7007
+ orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent",
7008
+ orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent",
7009
+ className
7010
+ ),
7011
+ ...props,
7012
+ children: /* @__PURE__ */ jsx(
7013
+ ScrollArea$1.ScrollAreaThumb,
7014
+ {
7015
+ "data-slot": "scroll-area-thumb",
7016
+ className: "bg-border relative flex-1 rounded-full"
7017
+ }
7018
+ )
7019
+ }
7020
+ );
7021
+ }
7022
+
7023
+ // src/chat/channel-list/useChannelList.ts
7024
+ init_useStore();
7025
+ init_store_helpers();
7026
+ var conversationDrafts = /* @__PURE__ */ new Map();
7027
+ var DRAFT_PREVIEW_MAX_LENGTH = 50;
7028
+ var emptyDraft = () => ({
7029
+ messageInput: "",
7030
+ attachments: []
7031
+ });
7032
+ var draftRevision = 0;
7033
+ var draftListeners = /* @__PURE__ */ new Set();
7034
+ function notifyDraftChange() {
7035
+ draftRevision += 1;
7036
+ draftListeners.forEach((listener) => listener());
7037
+ }
7038
+ function subscribeToDrafts(listener) {
7039
+ draftListeners.add(listener);
7040
+ return () => {
7041
+ draftListeners.delete(listener);
7042
+ };
7043
+ }
7044
+ function getDraftRevision() {
7045
+ return draftRevision;
7046
+ }
7047
+ function useDraftRevision() {
7048
+ return useSyncExternalStore(subscribeToDrafts, getDraftRevision, getDraftRevision);
7049
+ }
7050
+ function getConversationDraft(conversationId) {
7051
+ if (!conversationId) return emptyDraft();
7052
+ return conversationDrafts.get(conversationId) ?? emptyDraft();
7053
+ }
7054
+ function updateConversationDraft(conversationId, draft) {
7055
+ if (!conversationId) return;
7056
+ if (draft.messageInput.trim() || draft.attachments.length > 0) {
7057
+ conversationDrafts.set(conversationId, {
7058
+ messageInput: draft.messageInput,
7059
+ attachments: draft.attachments
7060
+ });
7061
+ } else {
7062
+ conversationDrafts.delete(conversationId);
7063
+ }
7064
+ notifyDraftChange();
7065
+ }
7066
+ function clearConversationDraft(conversationId) {
7067
+ if (!conversationId) return;
7068
+ if (!conversationDrafts.has(conversationId)) return;
7069
+ conversationDrafts.delete(conversationId);
7070
+ notifyDraftChange();
7071
+ }
7072
+ function getConversationDraftPreview(conversationId) {
7073
+ if (!conversationId) return null;
7074
+ const draft = conversationDrafts.get(conversationId);
7075
+ if (!draft) return null;
7076
+ const text = draft.messageInput.trim();
7077
+ if (text) {
7078
+ return text.length > DRAFT_PREVIEW_MAX_LENGTH ? `${text.slice(0, DRAFT_PREVIEW_MAX_LENGTH)}\u2026` : text;
7079
+ }
7080
+ if (draft.attachments.length > 0) {
7081
+ return draft.attachments.length === 1 ? "Attachment" : `${draft.attachments.length} attachments`;
7082
+ }
7083
+ return null;
6646
7084
  }
6647
7085
  function useConversationDraft(conversationId) {
6648
7086
  const composerRef = useRef(emptyDraft());
@@ -12197,52 +12635,23 @@ var ChannelDetailsDrawer = (props) => {
12197
12635
  participantCount > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5 pb-1", children: participants.map((p, index) => {
12198
12636
  const pId = typeof p === "string" ? p : p._id;
12199
12637
  const pName = typeof p === "string" ? "Unknown" : p.name;
12200
- if (!pId) return null;
12201
- return /* @__PURE__ */ jsx(
12202
- "span",
12203
- {
12204
- className: "rounded-md border border-(--chat-border) bg-(--chat-input-bg)/50 px-2 py-0.5 text-[10px] font-medium text-(--chat-text-secondary)",
12205
- children: pName
12206
- },
12207
- `${pId}-${index}`
12208
- );
12209
- }) })
12210
- ] })
12211
- ] })
12212
- ] })
12213
- ] })
12214
- ] }) });
12215
- };
12216
- var ChannelDetailsDrawer_default = ChannelDetailsDrawer;
12217
- function Switch({
12218
- className,
12219
- size = "default",
12220
- ...props
12221
- }) {
12222
- return /* @__PURE__ */ jsx(
12223
- Switch$1.Root,
12224
- {
12225
- "data-slot": "switch",
12226
- "data-size": size,
12227
- className: cn(
12228
- "peer group/switch inline-flex shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-[1.15rem] data-[size=default]:w-8 data-[size=sm]:h-3.5 data-[size=sm]:w-6 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input dark:data-[state=unchecked]:bg-input/80",
12229
- className
12230
- ),
12231
- ...props,
12232
- children: /* @__PURE__ */ jsx(
12233
- Switch$1.Thumb,
12234
- {
12235
- "data-slot": "switch-thumb",
12236
- className: cn(
12237
- "pointer-events-none block rounded-full bg-background ring-0 transition-transform group-data-[size=default]/switch:size-4 group-data-[size=sm]/switch:size-3 data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0 dark:data-[state=checked]:bg-primary-foreground dark:data-[state=unchecked]:bg-foreground"
12238
- )
12239
- }
12240
- )
12241
- }
12242
- );
12243
- }
12244
-
12245
- // src/chat/header/PermissionDrawer.tsx
12638
+ if (!pId) return null;
12639
+ return /* @__PURE__ */ jsx(
12640
+ "span",
12641
+ {
12642
+ className: "rounded-md border border-(--chat-border) bg-(--chat-input-bg)/50 px-2 py-0.5 text-[10px] font-medium text-(--chat-text-secondary)",
12643
+ children: pName
12644
+ },
12645
+ `${pId}-${index}`
12646
+ );
12647
+ }) })
12648
+ ] })
12649
+ ] })
12650
+ ] })
12651
+ ] })
12652
+ ] }) });
12653
+ };
12654
+ var ChannelDetailsDrawer_default = ChannelDetailsDrawer;
12246
12655
  init_useStore();
12247
12656
  var PermissionDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo }) => {
12248
12657
  const updateGroupPermissions = useStore((s) => s.updateGroupPermissions);
@@ -17639,246 +18048,10 @@ function ChatViewport({
17639
18048
  children
17640
18049
  }
17641
18050
  );
17642
- }
17643
- var ChatViewport_default = ChatViewport;
17644
- var showNotification = (message, type = "info", icon, duration) => {
17645
- const options = {
17646
- icon,
17647
- duration
17648
- };
17649
- switch (type) {
17650
- case "success":
17651
- toast.success(message, options);
17652
- break;
17653
- case "error":
17654
- toast.error(message, options);
17655
- break;
17656
- case "info":
17657
- toast(message, options);
17658
- break;
17659
- case "warning":
17660
- toast(message, { ...options, icon: "\u26A0\uFE0F" });
17661
- break;
17662
- default:
17663
- toast(message, options);
17664
- }
17665
- };
17666
- var downloadFile = async (src, name) => {
17667
- try {
17668
- const link = document.createElement("a");
17669
- link.href = src;
17670
- link.setAttribute("download", name);
17671
- link.setAttribute("rel", "noopener noreferrer");
17672
- link.click();
17673
- showNotification("File Downloaded Successfully", "success");
17674
- } catch (err) {
17675
- console.error("File download failed:", err);
17676
- showNotification("Failed to download file", "error");
17677
- }
17678
- };
17679
- var getResponsiveWidth = (width) => {
17680
- const screenWidth = window.innerWidth;
17681
- if (width) {
17682
- return width;
17683
- } else if (screenWidth < 640) {
17684
- return 350;
17685
- } else if (screenWidth >= 640 && screenWidth < 1024) {
17686
- return 600;
17687
- } else if (screenWidth >= 1024 && screenWidth < 1280) {
17688
- return 800;
17689
- } else {
17690
- return 1e3;
17691
- }
17692
- };
17693
- var isEmpty = (value) => {
17694
- if (value === null || value === void 0) return true;
17695
- if (typeof value === "string") return value.trim().length === 0;
17696
- if (Array.isArray(value)) {
17697
- return value.length === 0 || value.every((item) => isEmpty(item));
17698
- }
17699
- if (typeof value === "object") {
17700
- return Object.keys(value).length === 0;
17701
- }
17702
- return false;
17703
- };
17704
- function uniqueList(list, key) {
17705
- const seen = /* @__PURE__ */ new Set();
17706
- return list.filter((item) => {
17707
- const value = item[key];
17708
- if (seen.has(value)) return false;
17709
- seen.add(value);
17710
- return true;
17711
- });
17712
- }
17713
- var capitalizeFirst = (str) => str.charAt(0).toUpperCase() + str.slice(1);
17714
- var getFirstAndLastNameOneCharacter = (name) => {
17715
- const names = name.split(" ");
17716
- return names.map((name2) => name2.charAt(0).toUpperCase()).join("");
17717
- };
17718
-
17719
- // src/notifications/ForegroundPushBridge.tsx
17720
- init_normalize_helpers();
17721
- init_useStore();
17722
-
17723
- // src/notifications/push.service.ts
17724
- init_client();
17725
- var PUSH_TOKEN_STORAGE_KEY = "realtimex-push-token";
17726
- var SERVICE_WORKER_PATH = "/firebase-messaging-sw.js";
17727
- var PUSH_CHANGED_EVENT = "realtimex:push-changed";
17728
- var emitPushChanged = (enabled) => {
17729
- try {
17730
- window.dispatchEvent(
17731
- new CustomEvent(PUSH_CHANGED_EVENT, { detail: { enabled } })
17732
- );
17733
- } catch {
17734
- }
17735
- };
17736
- var v2Url = "https://realtimex.softwareco.com/api/v2";
17737
- var apiGetPushConfig = async () => {
17738
- const { data } = await apiClient.get(`${v2Url}/notifications/push/config`);
17739
- return data?.data;
17740
- };
17741
- var apiRegisterPushToken = async (token, deviceLabel) => {
17742
- const { data } = await apiClient.post(`${v2Url}/notifications/push/token`, {
17743
- token,
17744
- deviceLabel
17745
- });
17746
- return data?.data;
17747
- };
17748
- var apiRemovePushToken = async (token) => {
17749
- const { data } = await apiClient.delete(`${v2Url}/notifications/push/token`, {
17750
- data: { token }
17751
- });
17752
- return data;
17753
- };
17754
- var apiGetPushPreference = async () => {
17755
- const { data } = await apiClient.get(
17756
- `${v2Url}/notifications/push/preference`
17757
- );
17758
- return data?.data;
17759
- };
17760
- var apiUpdatePushPreference = async (enabled) => {
17761
- const { data } = await apiClient.patch(
17762
- `${v2Url}/notifications/push/preference`,
17763
- { enabled }
17764
- );
17765
- return data?.data;
17766
- };
17767
- var isPushSupported = () => typeof window !== "undefined" && "Notification" in window && "serviceWorker" in navigator && "PushManager" in window;
17768
- var getStoredPushToken = () => {
17769
- try {
17770
- return localStorage.getItem(PUSH_TOKEN_STORAGE_KEY);
17771
- } catch {
17772
- return null;
17773
- }
17774
- };
17775
- var storePushToken = (token) => {
17776
- try {
17777
- if (token) localStorage.setItem(PUSH_TOKEN_STORAGE_KEY, token);
17778
- else localStorage.removeItem(PUSH_TOKEN_STORAGE_KEY);
17779
- } catch {
17780
- }
17781
- };
17782
- var defaultDeviceLabel = () => {
17783
- const ua = navigator.userAgent;
17784
- const browser = /edg\//i.test(ua) ? "Edge" : /chrome/i.test(ua) ? "Chrome" : /safari/i.test(ua) ? "Safari" : /firefox/i.test(ua) ? "Firefox" : "Browser";
17785
- const os = /mac/i.test(ua) ? "macOS" : /windows/i.test(ua) ? "Windows" : /android/i.test(ua) ? "Android" : /iphone|ipad/i.test(ua) ? "iOS" : /linux/i.test(ua) ? "Linux" : "Unknown OS";
17786
- return `${browser} on ${os}`;
17787
- };
17788
- var loadFirebaseMessaging = async () => {
17789
- try {
17790
- const [{ initializeApp, getApps }, messagingModule] = await Promise.all([
17791
- import('firebase/app'),
17792
- import('firebase/messaging')
17793
- ]);
17794
- return { initializeApp, getApps, ...messagingModule };
17795
- } catch {
17796
- throw new Error(
17797
- 'Push notifications need the "firebase" package \u2014 run: npm install firebase'
17798
- );
17799
- }
17800
- };
17801
- var getFirebaseMessaging = async (firebaseConfig) => {
17802
- const fb = await loadFirebaseMessaging();
17803
- const app = fb.getApps().length ? fb.getApps()[0] : fb.initializeApp(firebaseConfig);
17804
- return { fb, messaging: fb.getMessaging(app) };
17805
- };
17806
- var enablePushOnThisDevice = async () => {
17807
- if (!isPushSupported()) {
17808
- throw new Error("Push notifications are not supported in this browser");
17809
- }
17810
- const config = await apiGetPushConfig();
17811
- if (!config?.enabled) {
17812
- throw new Error("Push notifications are disabled for this workspace");
17813
- }
17814
- if (!config.configured || !config.firebaseConfig || !config.vapidKey) {
17815
- throw new Error(
17816
- "Push notifications are not configured on the server yet"
17817
- );
17818
- }
17819
- const permission = await Notification.requestPermission();
17820
- if (permission !== "granted") {
17821
- throw new Error("Notification permission was not granted");
17822
- }
17823
- let registration;
17824
- try {
17825
- registration = await navigator.serviceWorker.register(
17826
- `${SERVICE_WORKER_PATH}?config=${encodeURIComponent(
17827
- JSON.stringify(config.firebaseConfig)
17828
- )}`
17829
- );
17830
- } catch {
17831
- throw new Error(
17832
- `Could not register ${SERVICE_WORKER_PATH} \u2014 copy it from node_modules/@realtimexsco/live-chat/dist/firebase-messaging-sw.js into your app's public folder`
17833
- );
17834
- }
17835
- const { fb, messaging } = await getFirebaseMessaging(config.firebaseConfig);
17836
- const token = await fb.getToken(messaging, {
17837
- vapidKey: config.vapidKey,
17838
- serviceWorkerRegistration: registration
17839
- });
17840
- if (!token) {
17841
- throw new Error("Could not obtain a push token from Firebase");
17842
- }
17843
- await apiRegisterPushToken(token, defaultDeviceLabel());
17844
- storePushToken(token);
17845
- emitPushChanged(true);
17846
- return token;
17847
- };
17848
- var disablePushOnThisDevice = async () => {
17849
- const token = getStoredPushToken();
17850
- if (!token) return;
17851
- try {
17852
- const config = await apiGetPushConfig();
17853
- if (config?.firebaseConfig) {
17854
- const { fb, messaging } = await getFirebaseMessaging(
17855
- config.firebaseConfig
17856
- );
17857
- await fb.deleteToken(messaging).catch(() => void 0);
17858
- }
17859
- } catch {
17860
- }
17861
- await apiRemovePushToken(token).catch(() => void 0);
17862
- storePushToken(null);
17863
- emitPushChanged(false);
17864
- };
17865
- var onForegroundPush = async (callback) => {
17866
- const config = await apiGetPushConfig();
17867
- if (!config?.configured || !config.firebaseConfig) {
17868
- throw new Error("Push config unavailable (not configured or API not ready)");
17869
- }
17870
- const { fb, messaging } = await getFirebaseMessaging(config.firebaseConfig);
17871
- return fb.onMessage(messaging, (payload) => {
17872
- console.log("[realtimex-push] FCM foreground payload (raw):", payload);
17873
- console.log("[realtimex-push] FCM foreground data:", payload?.data);
17874
- console.log("[realtimex-push] FCM foreground notification:", payload?.notification);
17875
- callback({
17876
- title: payload?.notification?.title,
17877
- body: payload?.notification?.body,
17878
- data: payload?.data
17879
- });
17880
- });
17881
- };
18051
+ }
18052
+ var ChatViewport_default = ChatViewport;
18053
+ init_normalize_helpers();
18054
+ init_useStore();
17882
18055
  var RETRY_DELAYS_MS = [1e3, 3e3, 8e3, 2e4];
17883
18056
  var recentToastIds = /* @__PURE__ */ new Set();
17884
18057
  var rememberToastId = (id) => {
@@ -17892,48 +18065,95 @@ var rememberToastId = (id) => {
17892
18065
  }
17893
18066
  return true;
17894
18067
  };
17895
- var resolveToastText = (title, body) => {
17896
- if (title && body) return `${title}: ${body}`;
17897
- return title || body || "";
18068
+ var truncate = (value, max) => value.length > max ? `${value.slice(0, max - 1)}\u2026` : value;
18069
+ var PushMessageToast = ({
18070
+ t,
18071
+ title,
18072
+ body,
18073
+ onOpen
18074
+ }) => {
18075
+ const dismiss = () => toast$1.dismiss(t.id);
18076
+ const handleDismiss = (event) => {
18077
+ event.stopPropagation();
18078
+ dismiss();
18079
+ };
18080
+ const handleOpen = () => {
18081
+ dismiss();
18082
+ onOpen?.();
18083
+ };
18084
+ return /* @__PURE__ */ jsxs(
18085
+ "div",
18086
+ {
18087
+ role: "alert",
18088
+ "aria-live": "polite",
18089
+ onClick: onOpen ? handleOpen : void 0,
18090
+ onKeyDown: onOpen ? (event) => {
18091
+ if (event.key === "Enter" || event.key === " ") {
18092
+ event.preventDefault();
18093
+ handleOpen();
18094
+ }
18095
+ } : void 0,
18096
+ tabIndex: onOpen ? 0 : void 0,
18097
+ className: cn(
18098
+ "pointer-events-auto flex w-[min(320px,calc(100vw-24px))] items-start gap-3 rounded-xl border border-(--chat-border) bg-(--chat-surface) p-3 shadow-[0_8px_24px_rgba(15,23,42,0.12)] transition-[opacity,transform] duration-200 ease-out",
18099
+ onOpen && "cursor-pointer hover:border-(--chat-theme-20) hover:shadow-[0_10px_28px_rgba(15,23,42,0.16)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-(--chat-theme-30)",
18100
+ t.visible ? "translate-y-0 opacity-100" : "-translate-y-1 opacity-0"
18101
+ ),
18102
+ children: [
18103
+ /* @__PURE__ */ jsx(
18104
+ "div",
18105
+ {
18106
+ "aria-hidden": true,
18107
+ className: "flex size-9 shrink-0 items-center justify-center rounded-lg bg-(--chat-theme-10) text-(--chat-theme)",
18108
+ children: /* @__PURE__ */ jsx(MessageSquare, { className: "size-4", strokeWidth: 2.25 })
18109
+ }
18110
+ ),
18111
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 pt-0.5", children: [
18112
+ /* @__PURE__ */ jsx("p", { className: "text-[11px] font-semibold uppercase tracking-wide text-(--chat-muted)", children: "New message" }),
18113
+ /* @__PURE__ */ jsx("p", { className: "mt-0.5 truncate text-sm font-semibold leading-snug text-(--chat-text)", children: truncate(title, 40) }),
18114
+ body ? /* @__PURE__ */ jsx("p", { className: "mt-0.5 line-clamp-2 text-xs leading-relaxed text-(--chat-muted)", children: truncate(body, 72) }) : null
18115
+ ] }),
18116
+ /* @__PURE__ */ jsx(
18117
+ "button",
18118
+ {
18119
+ type: "button",
18120
+ "aria-label": "Dismiss notification",
18121
+ onClick: handleDismiss,
18122
+ className: "shrink-0 rounded-md p-1 text-(--chat-muted) transition-colors hover:bg-(--chat-hover) hover:text-(--chat-text) focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-(--chat-theme-30)",
18123
+ children: /* @__PURE__ */ jsx(X, { className: "size-4", strokeWidth: 2 })
18124
+ }
18125
+ )
18126
+ ]
18127
+ }
18128
+ );
17898
18129
  };
17899
18130
  var emitToast = (payload, onPush) => {
17900
18131
  if (onPush && onPush(payload) !== false) return;
17901
- const title = payload.title || payload.data?.title;
17902
- const body = payload.body || payload.data?.body || payload.data?.message;
17903
- const text = resolveToastText(title, body);
18132
+ const title = payload.title || payload.data?.title || "New message";
18133
+ const body = payload.body || payload.data?.body || payload.data?.message || "";
17904
18134
  const conversationId = resolveConversationIdFromPushData(payload.data);
17905
- if (!text) return;
17906
- if (conversationId) {
17907
- toast2.custom(
17908
- (t) => /* @__PURE__ */ jsx(
17909
- "button",
17910
- {
17911
- type: "button",
17912
- onClick: () => {
17913
- toast2.dismiss(t.id);
17914
- requestOpenConversation(conversationId, payload.data);
17915
- },
17916
- style: {
17917
- display: "block",
17918
- width: "100%",
17919
- textAlign: "left",
17920
- cursor: "pointer",
17921
- background: "var(--background, #fff)",
17922
- color: "var(--foreground, #111)",
17923
- border: "1px solid rgba(0,0,0,0.08)",
17924
- borderRadius: 8,
17925
- padding: "10px 14px",
17926
- boxShadow: "0 4px 12px rgba(0,0,0,0.12)",
17927
- font: "inherit"
17928
- },
17929
- children: text
17930
- }
17931
- ),
17932
- { duration: 5e3 }
17933
- );
17934
- return;
17935
- }
17936
- showNotification(text, "info");
18135
+ const messageId2 = String(
18136
+ payload.data?.messageId || payload.data?.message_id || payload.data?.messageID || ""
18137
+ );
18138
+ if (!title && !body) return;
18139
+ toast$1.custom(
18140
+ (t) => /* @__PURE__ */ jsx(
18141
+ PushMessageToast,
18142
+ {
18143
+ t,
18144
+ title,
18145
+ body: body || void 0,
18146
+ onOpen: conversationId ? () => requestOpenConversation(
18147
+ conversationId,
18148
+ payload.data
18149
+ ) : void 0
18150
+ }
18151
+ ),
18152
+ {
18153
+ duration: 5e3,
18154
+ id: messageId2 || void 0
18155
+ }
18156
+ );
17937
18157
  };
17938
18158
  var ForegroundPushBridge = ({ onPush }) => {
17939
18159
  const lastDM = useStore((s) => s.lastDM);
@@ -18071,8 +18291,28 @@ var ForegroundPushBridge = ({ onPush }) => {
18071
18291
  Toaster,
18072
18292
  {
18073
18293
  position: "top-right",
18074
- toastOptions: { duration: 4e3 },
18075
- containerStyle: { zIndex: 99999 }
18294
+ gutter: 12,
18295
+ containerClassName: "realtimex-push-toaster",
18296
+ containerStyle: {
18297
+ zIndex: 99999,
18298
+ top: 16,
18299
+ right: 16,
18300
+ width: "auto",
18301
+ maxWidth: "none"
18302
+ },
18303
+ toastOptions: {
18304
+ duration: 5e3,
18305
+ className: "!w-auto !max-w-none",
18306
+ style: {
18307
+ padding: 0,
18308
+ margin: 0,
18309
+ background: "transparent",
18310
+ boxShadow: "none",
18311
+ border: "none",
18312
+ width: "auto",
18313
+ maxWidth: "none"
18314
+ }
18315
+ }
18076
18316
  }
18077
18317
  );
18078
18318
  };
@@ -18229,6 +18469,80 @@ var getSocketConfig = (accessToken, tenantId, options) => {
18229
18469
  }
18230
18470
  };
18231
18471
  };
18472
+ var showNotification = (message, type = "info", icon, duration) => {
18473
+ const options = {
18474
+ icon,
18475
+ duration
18476
+ };
18477
+ switch (type) {
18478
+ case "success":
18479
+ toast.success(message, options);
18480
+ break;
18481
+ case "error":
18482
+ toast.error(message, options);
18483
+ break;
18484
+ case "info":
18485
+ toast(message, options);
18486
+ break;
18487
+ case "warning":
18488
+ toast(message, { ...options, icon: "\u26A0\uFE0F" });
18489
+ break;
18490
+ default:
18491
+ toast(message, options);
18492
+ }
18493
+ };
18494
+ var downloadFile = async (src, name) => {
18495
+ try {
18496
+ const link = document.createElement("a");
18497
+ link.href = src;
18498
+ link.setAttribute("download", name);
18499
+ link.setAttribute("rel", "noopener noreferrer");
18500
+ link.click();
18501
+ showNotification("File Downloaded Successfully", "success");
18502
+ } catch (err) {
18503
+ console.error("File download failed:", err);
18504
+ showNotification("Failed to download file", "error");
18505
+ }
18506
+ };
18507
+ var getResponsiveWidth = (width) => {
18508
+ const screenWidth = window.innerWidth;
18509
+ if (width) {
18510
+ return width;
18511
+ } else if (screenWidth < 640) {
18512
+ return 350;
18513
+ } else if (screenWidth >= 640 && screenWidth < 1024) {
18514
+ return 600;
18515
+ } else if (screenWidth >= 1024 && screenWidth < 1280) {
18516
+ return 800;
18517
+ } else {
18518
+ return 1e3;
18519
+ }
18520
+ };
18521
+ var isEmpty = (value) => {
18522
+ if (value === null || value === void 0) return true;
18523
+ if (typeof value === "string") return value.trim().length === 0;
18524
+ if (Array.isArray(value)) {
18525
+ return value.length === 0 || value.every((item) => isEmpty(item));
18526
+ }
18527
+ if (typeof value === "object") {
18528
+ return Object.keys(value).length === 0;
18529
+ }
18530
+ return false;
18531
+ };
18532
+ function uniqueList(list, key) {
18533
+ const seen = /* @__PURE__ */ new Set();
18534
+ return list.filter((item) => {
18535
+ const value = item[key];
18536
+ if (seen.has(value)) return false;
18537
+ seen.add(value);
18538
+ return true;
18539
+ });
18540
+ }
18541
+ var capitalizeFirst = (str) => str.charAt(0).toUpperCase() + str.slice(1);
18542
+ var getFirstAndLastNameOneCharacter = (name) => {
18543
+ const names = name.split(" ");
18544
+ return names.map((name2) => name2.charAt(0).toUpperCase()).join("");
18545
+ };
18232
18546
  var SIZE_MAP = {
18233
18547
  xs: "size-6",
18234
18548
  sm: "size-8",
@@ -18402,139 +18716,10 @@ var packageDefaultComponents = {
18402
18716
  ChatDateTimeSettings: ChatDateTimeSettings_default,
18403
18717
  ChatSocketStatus: ChatSocketStatus_default
18404
18718
  };
18405
- var usePushNotifications = () => {
18406
- const [state, setState] = useState({
18407
- supported: false,
18408
- allowedByWorkspace: false,
18409
- configured: false,
18410
- permission: "unsupported",
18411
- userEnabled: true,
18412
- deviceEnabled: false,
18413
- loading: true,
18414
- error: null
18415
- });
18416
- const refresh = useCallback(async () => {
18417
- if (!isPushSupported()) {
18418
- setState((prev) => ({
18419
- ...prev,
18420
- supported: false,
18421
- loading: false
18422
- }));
18423
- return;
18424
- }
18425
- try {
18426
- const [config, preference] = await Promise.all([
18427
- apiGetPushConfig(),
18428
- apiGetPushPreference().catch(() => null)
18429
- ]);
18430
- setState({
18431
- supported: true,
18432
- allowedByWorkspace: Boolean(config?.enabled),
18433
- configured: Boolean(config?.configured),
18434
- permission: Notification.permission,
18435
- userEnabled: preference?.enabled ?? true,
18436
- deviceEnabled: Notification.permission === "granted" && Boolean(getStoredPushToken()),
18437
- loading: false,
18438
- error: null
18439
- });
18440
- } catch (error) {
18441
- setState((prev) => ({
18442
- ...prev,
18443
- supported: true,
18444
- loading: false,
18445
- error: error instanceof Error ? error.message : "Could not load push settings"
18446
- }));
18447
- }
18448
- }, []);
18449
- useEffect(() => {
18450
- void refresh();
18451
- }, [refresh]);
18452
- const enable = useCallback(async () => {
18453
- setState((prev) => ({ ...prev, loading: true, error: null }));
18454
- try {
18455
- await enablePushOnThisDevice();
18456
- await refresh();
18457
- return true;
18458
- } catch (error) {
18459
- setState((prev) => ({
18460
- ...prev,
18461
- loading: false,
18462
- permission: isPushSupported() ? Notification.permission : "unsupported",
18463
- error: error instanceof Error ? error.message : "Could not enable push notifications"
18464
- }));
18465
- return false;
18466
- }
18467
- }, [refresh]);
18468
- const disable = useCallback(async () => {
18469
- setState((prev) => ({ ...prev, loading: true, error: null }));
18470
- try {
18471
- await disablePushOnThisDevice();
18472
- } finally {
18473
- await refresh();
18474
- }
18475
- }, [refresh]);
18476
- const setUserEnabled = useCallback(
18477
- async (enabled) => {
18478
- setState((prev) => ({ ...prev, userEnabled: enabled }));
18479
- try {
18480
- await apiUpdatePushPreference(enabled);
18481
- } catch (error) {
18482
- setState((prev) => ({
18483
- ...prev,
18484
- userEnabled: !enabled,
18485
- error: error instanceof Error ? error.message : "Could not update push preference"
18486
- }));
18487
- }
18488
- },
18489
- []
18490
- );
18491
- return { ...state, enable, disable, setUserEnabled, refresh };
18492
- };
18493
- var PushNotificationToggle = ({
18494
- className,
18495
- label = "Push notifications",
18496
- description = "Get notified about new messages on this device"
18497
- }) => {
18498
- const push = usePushNotifications();
18499
- if (!push.supported || !push.allowedByWorkspace || !push.configured) {
18500
- return null;
18501
- }
18502
- const isOn = push.deviceEnabled && push.userEnabled;
18503
- const permissionBlocked = push.permission === "denied";
18504
- const handleChange = async (checked) => {
18505
- if (checked) {
18506
- if (!push.userEnabled) await push.setUserEnabled(true);
18507
- if (!push.deviceEnabled) await push.enable();
18508
- } else {
18509
- await push.disable();
18510
- }
18511
- };
18512
- return /* @__PURE__ */ jsxs(
18513
- "div",
18514
- {
18515
- className: className ?? "flex items-center justify-between gap-4 rounded-xl border border-border bg-background px-4 py-3",
18516
- children: [
18517
- /* @__PURE__ */ jsxs("div", { className: "space-y-0.5", children: [
18518
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: label }),
18519
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: permissionBlocked ? "Notifications are blocked in your browser settings" : push.error ?? description })
18520
- ] }),
18521
- /* @__PURE__ */ jsx(
18522
- Switch,
18523
- {
18524
- checked: isOn,
18525
- disabled: push.loading || permissionBlocked,
18526
- onCheckedChange: (checked) => void handleChange(checked),
18527
- "aria-label": `Toggle ${label}`
18528
- }
18529
- )
18530
- ]
18531
- }
18532
- );
18533
- };
18534
18719
 
18535
18720
  // src/index.ts
18536
18721
  var index_default = ChatMain_default;
18537
18722
 
18538
- export { CHAT_API_KEYS, CHAT_GET_API_KEYS, Calendar, CalendarDayButton, Channel, ChannelHeaderView_default as ChannelHeader, ChannelListView_default as ChannelList, ChannelListItem_default as ChannelListItem, Chat, ChatAlertsProvider, ChatAvatar_default as ChatAvatar, ChatCustomizationProvider, ChatDateJumpMenu, ChatLayout_default as ChatLayout, ChatLocaleProvider, ChatMain_default as ChatMain, ChatThemeProvider, ChatViewport, DefaultChannelListItem, DefaultChatAvatar, DefaultChatLayout_default as DefaultChatLayout, ForegroundPushBridge, ForwardModalView as ForwardModal, HeaderCallActions_default as HeaderCallActions, LoggedUserDetails_default as LoggedUserDetails, ChannelMessageBoxView_default as MessageInput, MessageItemView as MessageItem, ActiveChannelMessagesView_default as MessageList, NOTIFICATION_CLICK_SW_TYPE, OPEN_CONVERSATION_EVENT, PUSH_BROADCAST_CHANNEL, PUSH_CHANGED_EVENT, PushNotificationToggle, apiGetPushConfig, apiGetPushPreference, apiRegisterPushToken, apiRemovePushToken, apiUpdatePushPreference, buildChannelFromPushRequest, capitalizeFirst, clampJumpDate, consumePendingOpenConversation, consumePendingOpenRequest, index_default as default, defaultChatClassNames, defaultChatComponents, defaultChatFeatures, defaultChatLayoutConfig, disablePushOnThisDevice, downloadFile, enablePushOnThisDevice, getChatBaseUrl, getChatQueryParamApis, getChatQueryParams, getChatQueryParamsByApi, getChatSocketUrl, getFirstAndLastNameOneCharacter, getResponsiveWidth, getSocketConfig, getStoredPushToken, installNotificationClickBridge, isEmpty, isPushSupported, mergeChatCustomization, mergeChatLayoutConfig, onForegroundPush, packageDefaultComponents, peekPendingOpenConversation, peekPendingOpenRequest, requestOpenConversation, resolveApiUrl, resolveChatApiKey, resolveConversationIdFromPushData, resolveJumpDateBounds, resolveJumpPreset, resolveJumpStep, resolveSocketUrl, setChatAccessToken, setChatBaseURL, setChatClientId, setChatQueryParamApis, setChatQueryParams, setChatQueryParamsByApi, setChatSocketUrl, showNotification, smoothScrollToMessage, socket_service_default as socketService, startOfLocalDay, toDateInputValue, uniqueList, useChatAlerts, useChatContext, useChatController, useChatCustomization, useChatCustomizationOptional, useChatFeatures, useChatFeaturesOptional, useChatLocale, useStore as useChatStore, useChatTheme, usePushNotifications };
18723
+ export { CHAT_API_KEYS, CHAT_GET_API_KEYS, Calendar, CalendarDayButton, Channel, ChannelHeaderView_default as ChannelHeader, ChannelListView_default as ChannelList, ChannelListItem_default as ChannelListItem, Chat, ChatAlertsProvider, ChatAvatar_default as ChatAvatar, ChatCustomizationProvider, ChatDateJumpMenu, ChatLayout_default as ChatLayout, ChatLocaleProvider, ChatMain_default as ChatMain, ChatThemeProvider, ChatViewport, DefaultChannelListItem, DefaultChatAvatar, DefaultChatLayout_default as DefaultChatLayout, ForegroundPushBridge, ForwardModalView as ForwardModal, HeaderCallActions_default as HeaderCallActions, LoggedUserDetails_default as LoggedUserDetails, ChannelMessageBoxView_default as MessageInput, MessageItemView as MessageItem, ActiveChannelMessagesView_default as MessageList, NOTIFICATION_CLICK_SW_TYPE, OPEN_CONVERSATION_EVENT, PUSH_BROADCAST_CHANNEL, PUSH_CHANGED_EVENT, PUSH_DATA_CACHE_NAME, PushNotificationToggle, apiGetPushConfig, apiGetPushPreference, apiRegisterPushToken, apiRemovePushToken, apiUpdatePushPreference, buildChannelFromPushRequest, capitalizeFirst, clampJumpDate, consumePendingOpenConversation, consumePendingOpenFromPushCache, consumePendingOpenRequest, index_default as default, defaultChatClassNames, defaultChatComponents, defaultChatFeatures, defaultChatLayoutConfig, disablePushOnThisDevice, downloadFile, enablePushOnThisDevice, getChatBaseUrl, getChatQueryParamApis, getChatQueryParams, getChatQueryParamsByApi, getChatSocketUrl, getFirstAndLastNameOneCharacter, getResponsiveWidth, getSocketConfig, getStoredPushToken, installNotificationClickBridge, isEmpty, isPushSupported, mergeChatCustomization, mergeChatLayoutConfig, onForegroundPush, packageDefaultComponents, peekPendingOpenConversation, peekPendingOpenRequest, requestOpenConversation, resolveApiUrl, resolveChatApiKey, resolveConversationIdFromPushData, resolveJumpDateBounds, resolveJumpPreset, resolveJumpStep, resolveSocketUrl, setChatAccessToken, setChatBaseURL, setChatClientId, setChatQueryParamApis, setChatQueryParams, setChatQueryParamsByApi, setChatSocketUrl, showNotification, smoothScrollToMessage, socket_service_default as socketService, startOfLocalDay, toDateInputValue, uniqueList, useChatAlerts, useChatContext, useChatController, useChatCustomization, useChatCustomizationOptional, useChatFeatures, useChatFeaturesOptional, useChatLocale, useStore as useChatStore, useChatTheme, usePushNotifications };
18539
18724
  //# sourceMappingURL=index.mjs.map
18540
18725
  //# sourceMappingURL=index.mjs.map