@realtimexsco/live-chat 1.4.9 → 1.4.11
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/firebase-messaging-sw.js +312 -71
- package/dist/index.cjs +1029 -641
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +128 -37
- package/dist/index.d.ts +128 -37
- package/dist/index.mjs +1019 -637
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +11 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -16,7 +16,7 @@ var lucideReact = require('lucide-react');
|
|
|
16
16
|
var classVarianceAuthority = require('class-variance-authority');
|
|
17
17
|
var EmojiPicker = require('emoji-picker-react');
|
|
18
18
|
var reactDayPicker = require('react-day-picker');
|
|
19
|
-
var
|
|
19
|
+
var toast = require('react-hot-toast');
|
|
20
20
|
|
|
21
21
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
22
22
|
|
|
@@ -41,7 +41,7 @@ function _interopNamespace(e) {
|
|
|
41
41
|
var axios__default = /*#__PURE__*/_interopDefault(axios);
|
|
42
42
|
var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
|
|
43
43
|
var EmojiPicker__default = /*#__PURE__*/_interopDefault(EmojiPicker);
|
|
44
|
-
var
|
|
44
|
+
var toast__default = /*#__PURE__*/_interopDefault(toast);
|
|
45
45
|
|
|
46
46
|
var __defProp = Object.defineProperty;
|
|
47
47
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -1251,6 +1251,64 @@ var init_query_params = __esm({
|
|
|
1251
1251
|
];
|
|
1252
1252
|
}
|
|
1253
1253
|
});
|
|
1254
|
+
|
|
1255
|
+
// src/services/api/api-version.ts
|
|
1256
|
+
var DEFAULT_VERSIONS, apiVersions, normalizeApiVersion; exports.resolveApiRoot = void 0; exports.buildVersionedApiUrl = void 0; exports.setChatApiVersions = void 0; exports.getChatApiVersions = void 0; exports.setChatPushApiVersion = void 0; var syncDefaultApiVersionFromBaseUrl;
|
|
1257
|
+
var init_api_version = __esm({
|
|
1258
|
+
"src/services/api/api-version.ts"() {
|
|
1259
|
+
init_client();
|
|
1260
|
+
DEFAULT_VERSIONS = {
|
|
1261
|
+
default: "v1",
|
|
1262
|
+
push: "v2"
|
|
1263
|
+
};
|
|
1264
|
+
apiVersions = { ...DEFAULT_VERSIONS };
|
|
1265
|
+
normalizeApiVersion = (version) => {
|
|
1266
|
+
const raw = String(version || "v1").trim().replace(/^\/+|\/+$/g, "");
|
|
1267
|
+
if (!raw) return "v1";
|
|
1268
|
+
return /^v\d+$/i.test(raw) ? raw.toLowerCase() : `v${raw}`;
|
|
1269
|
+
};
|
|
1270
|
+
exports.resolveApiRoot = (baseUrl) => {
|
|
1271
|
+
const raw = String(
|
|
1272
|
+
baseUrl || exports.getChatBaseUrl() || apiClient.defaults.baseURL || ""
|
|
1273
|
+
).trim().replace(/\/$/, "");
|
|
1274
|
+
if (!raw) return "";
|
|
1275
|
+
const withoutVersion = raw.replace(/\/v\d+$/i, "");
|
|
1276
|
+
return withoutVersion || raw;
|
|
1277
|
+
};
|
|
1278
|
+
exports.buildVersionedApiUrl = (path, options) => {
|
|
1279
|
+
const root = exports.resolveApiRoot(options?.baseUrl);
|
|
1280
|
+
const version = normalizeApiVersion(
|
|
1281
|
+
options?.version ?? (options?.service ? apiVersions[options.service] : apiVersions.default)
|
|
1282
|
+
);
|
|
1283
|
+
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
1284
|
+
if (!root) {
|
|
1285
|
+
return `/${version}${normalizedPath}`;
|
|
1286
|
+
}
|
|
1287
|
+
return `${root}/${version}${normalizedPath}`;
|
|
1288
|
+
};
|
|
1289
|
+
exports.setChatApiVersions = (config) => {
|
|
1290
|
+
if (!config) return;
|
|
1291
|
+
if (config.default) {
|
|
1292
|
+
apiVersions.default = normalizeApiVersion(config.default);
|
|
1293
|
+
}
|
|
1294
|
+
if (config.push) {
|
|
1295
|
+
apiVersions.push = normalizeApiVersion(config.push);
|
|
1296
|
+
}
|
|
1297
|
+
};
|
|
1298
|
+
exports.getChatApiVersions = () => ({
|
|
1299
|
+
...apiVersions
|
|
1300
|
+
});
|
|
1301
|
+
exports.setChatPushApiVersion = (version) => {
|
|
1302
|
+
apiVersions.push = normalizeApiVersion(version);
|
|
1303
|
+
};
|
|
1304
|
+
syncDefaultApiVersionFromBaseUrl = (baseUrl) => {
|
|
1305
|
+
const match = String(baseUrl || "").trim().match(/\/(v\d+)\/?$/i);
|
|
1306
|
+
if (match?.[1]) {
|
|
1307
|
+
apiVersions.default = normalizeApiVersion(match[1]);
|
|
1308
|
+
}
|
|
1309
|
+
};
|
|
1310
|
+
}
|
|
1311
|
+
});
|
|
1254
1312
|
function resolveParamsForRequest(url, method) {
|
|
1255
1313
|
const apiKey = resolveChatApiKey(url);
|
|
1256
1314
|
const httpMethod = (method || "get").toLowerCase();
|
|
@@ -1267,7 +1325,9 @@ var chatClientId, chatAccessToken, chatBaseUrl, chatSocketUrl, chatQueryParams,
|
|
|
1267
1325
|
var init_client = __esm({
|
|
1268
1326
|
"src/services/api/client.ts"() {
|
|
1269
1327
|
init_query_params();
|
|
1328
|
+
init_api_version();
|
|
1270
1329
|
init_query_params();
|
|
1330
|
+
init_api_version();
|
|
1271
1331
|
chatClientId = "";
|
|
1272
1332
|
chatAccessToken = "";
|
|
1273
1333
|
chatBaseUrl = "";
|
|
@@ -1285,6 +1345,7 @@ var init_client = __esm({
|
|
|
1285
1345
|
exports.setChatBaseURL = (url) => {
|
|
1286
1346
|
chatBaseUrl = url.trim();
|
|
1287
1347
|
apiClient.defaults.baseURL = chatBaseUrl;
|
|
1348
|
+
syncDefaultApiVersionFromBaseUrl(chatBaseUrl);
|
|
1288
1349
|
};
|
|
1289
1350
|
exports.getChatBaseUrl = () => chatBaseUrl;
|
|
1290
1351
|
exports.setChatSocketUrl = (url) => {
|
|
@@ -3750,7 +3811,7 @@ function resolveApiUrl(apiUrl) {
|
|
|
3750
3811
|
function resolveSocketUrl(socketUrl, apiUrl) {
|
|
3751
3812
|
const explicit = (socketUrl ?? "").trim();
|
|
3752
3813
|
if (explicit) return explicit;
|
|
3753
|
-
return resolveApiUrl(apiUrl).replace(/\/api\/
|
|
3814
|
+
return resolveApiUrl(apiUrl).replace(/\/api\/v\d+\/?$/i, "");
|
|
3754
3815
|
}
|
|
3755
3816
|
|
|
3756
3817
|
// src/hooks/chat-sync/useChatSync.ts
|
|
@@ -4497,6 +4558,7 @@ var Chat = ({
|
|
|
4497
4558
|
queryParams,
|
|
4498
4559
|
queryParamApis,
|
|
4499
4560
|
queryParamsByApi,
|
|
4561
|
+
apiVersions: apiVersions2,
|
|
4500
4562
|
channelsData,
|
|
4501
4563
|
messagesData,
|
|
4502
4564
|
onMessageReceived,
|
|
@@ -4522,6 +4584,7 @@ var Chat = ({
|
|
|
4522
4584
|
const resolvedApiUrl = resolveApiUrl(apiUrl);
|
|
4523
4585
|
const resolvedSocketUrl = resolveSocketUrl(socketUrl, resolvedApiUrl);
|
|
4524
4586
|
if (resolvedApiUrl) exports.setChatBaseURL(resolvedApiUrl);
|
|
4587
|
+
exports.setChatApiVersions(apiVersions2);
|
|
4525
4588
|
if (resolvedSocketUrl) exports.setChatSocketUrl(resolvedSocketUrl);
|
|
4526
4589
|
let currentToken = accessToken || "";
|
|
4527
4590
|
let sessionUser = resolveUserFromAccessToken(currentToken, loggedUserDetails);
|
|
@@ -4660,7 +4723,9 @@ init_store_helpers();
|
|
|
4660
4723
|
var OPEN_CONVERSATION_EVENT = "realtimex:open-conversation";
|
|
4661
4724
|
var NOTIFICATION_CLICK_SW_TYPE = "realtimex:notification-click";
|
|
4662
4725
|
var PUSH_BROADCAST_CHANNEL = "realtimex-push";
|
|
4726
|
+
var PUSH_DATA_CACHE_NAME = "realtimex-push-data-v1";
|
|
4663
4727
|
var PENDING_STORAGE_KEY = "realtimex:pending-open-conversation";
|
|
4728
|
+
var PENDING_OPEN_CACHE_PATH = "pending-open";
|
|
4664
4729
|
var resolveConversationIdFromPushData = (data) => {
|
|
4665
4730
|
if (!data || typeof data !== "object") return "";
|
|
4666
4731
|
let fcmMsg = data.FCM_MSG;
|
|
@@ -4801,6 +4866,37 @@ var mapConversationToChannel = (conversation, loggedUserId, allUsers) => {
|
|
|
4801
4866
|
starredCount: conversation.starredCount
|
|
4802
4867
|
};
|
|
4803
4868
|
};
|
|
4869
|
+
var stripConversationIdFromUrl = () => {
|
|
4870
|
+
if (typeof window === "undefined") return;
|
|
4871
|
+
try {
|
|
4872
|
+
const url = new URL(window.location.href);
|
|
4873
|
+
if (!url.searchParams.has("conversationId")) return;
|
|
4874
|
+
url.searchParams.delete("conversationId");
|
|
4875
|
+
const next = `${url.pathname}${url.search}${url.hash}`;
|
|
4876
|
+
window.history.replaceState(window.history.state, "", next);
|
|
4877
|
+
} catch {
|
|
4878
|
+
}
|
|
4879
|
+
};
|
|
4880
|
+
var cacheRequestForPath = (path) => new Request(new URL(path, window.location.origin).toString());
|
|
4881
|
+
var consumePendingOpenFromPushCache = async () => {
|
|
4882
|
+
if (typeof caches === "undefined") return null;
|
|
4883
|
+
try {
|
|
4884
|
+
const cache = await caches.open(PUSH_DATA_CACHE_NAME);
|
|
4885
|
+
const req = cacheRequestForPath(PENDING_OPEN_CACHE_PATH);
|
|
4886
|
+
const res = await cache.match(req);
|
|
4887
|
+
if (!res) return null;
|
|
4888
|
+
await cache.delete(req);
|
|
4889
|
+
const data = await res.json();
|
|
4890
|
+
const conversationId = resolveConversationIdFromPushData(data);
|
|
4891
|
+
if (!conversationId) return null;
|
|
4892
|
+
return {
|
|
4893
|
+
conversationId,
|
|
4894
|
+
...normalizePushMeta(data)
|
|
4895
|
+
};
|
|
4896
|
+
} catch {
|
|
4897
|
+
return null;
|
|
4898
|
+
}
|
|
4899
|
+
};
|
|
4804
4900
|
var readConversationIdFromLocation = () => {
|
|
4805
4901
|
try {
|
|
4806
4902
|
return new URLSearchParams(window.location.search).get("conversationId") || "";
|
|
@@ -4809,16 +4905,33 @@ var readConversationIdFromLocation = () => {
|
|
|
4809
4905
|
}
|
|
4810
4906
|
};
|
|
4811
4907
|
var consumedUrlConversationIds = /* @__PURE__ */ new Set();
|
|
4908
|
+
var lastHandledOpenId = "";
|
|
4909
|
+
var lastHandledOpenAt = 0;
|
|
4910
|
+
var shouldHandleOpen = (conversationId) => {
|
|
4911
|
+
const id = String(conversationId || "").trim();
|
|
4912
|
+
if (!id) return false;
|
|
4913
|
+
const now = Date.now();
|
|
4914
|
+
if (lastHandledOpenId === id && now - lastHandledOpenAt < 2500) {
|
|
4915
|
+
return false;
|
|
4916
|
+
}
|
|
4917
|
+
lastHandledOpenId = id;
|
|
4918
|
+
lastHandledOpenAt = now;
|
|
4919
|
+
return true;
|
|
4920
|
+
};
|
|
4812
4921
|
var handleNotificationOpen = (conversationId, pushData, options) => {
|
|
4813
4922
|
const id = String(conversationId || "").trim();
|
|
4814
4923
|
if (!id) {
|
|
4815
4924
|
console.warn("[realtimex-push] notification open ignored \u2014 no conversationId", pushData);
|
|
4816
4925
|
return;
|
|
4817
4926
|
}
|
|
4927
|
+
if (!shouldHandleOpen(id)) {
|
|
4928
|
+
stripConversationIdFromUrl();
|
|
4929
|
+
return;
|
|
4930
|
+
}
|
|
4818
4931
|
requestOpenConversation(id, pushData);
|
|
4819
4932
|
const chatPath = options.chatPath || "/chat";
|
|
4820
|
-
|
|
4821
|
-
options.onNavigate?.(id,
|
|
4933
|
+
stripConversationIdFromUrl();
|
|
4934
|
+
options.onNavigate?.(id, chatPath);
|
|
4822
4935
|
};
|
|
4823
4936
|
var installNotificationClickBridge = (options = {}) => {
|
|
4824
4937
|
if (typeof window === "undefined") return () => void 0;
|
|
@@ -4845,7 +4958,17 @@ var installNotificationClickBridge = (options = {}) => {
|
|
|
4845
4958
|
if (fromUrl && !consumedUrlConversationIds.has(fromUrl)) {
|
|
4846
4959
|
consumedUrlConversationIds.add(fromUrl);
|
|
4847
4960
|
handleNotificationOpen(fromUrl, void 0, options);
|
|
4961
|
+
} else {
|
|
4962
|
+
stripConversationIdFromUrl();
|
|
4848
4963
|
}
|
|
4964
|
+
void consumePendingOpenFromPushCache().then((request) => {
|
|
4965
|
+
if (!request?.conversationId) return;
|
|
4966
|
+
handleNotificationOpen(
|
|
4967
|
+
request.conversationId,
|
|
4968
|
+
request,
|
|
4969
|
+
options
|
|
4970
|
+
);
|
|
4971
|
+
});
|
|
4849
4972
|
return () => {
|
|
4850
4973
|
navigator.serviceWorker?.removeEventListener("message", onSwMessage);
|
|
4851
4974
|
broadcast?.close();
|
|
@@ -5579,6 +5702,18 @@ function formatMemberName(name) {
|
|
|
5579
5702
|
function formatLoggedUserName(name) {
|
|
5580
5703
|
return name ? name.charAt(0).toUpperCase() + name.slice(1) : "User";
|
|
5581
5704
|
}
|
|
5705
|
+
|
|
5706
|
+
// src/chat/sidebar/build-logged-user-profile.ts
|
|
5707
|
+
var buildLoggedUserProfile = (loggedUserDetails) => ({
|
|
5708
|
+
_id: loggedUserDetails?._id || "1",
|
|
5709
|
+
name: formatLoggedUserName(loggedUserDetails?.name),
|
|
5710
|
+
email: loggedUserDetails?.email || "user@example.com",
|
|
5711
|
+
role: loggedUserDetails?.role || "user",
|
|
5712
|
+
isActive: loggedUserDetails?.isActive ?? true,
|
|
5713
|
+
createdAt: loggedUserDetails?.createdAt ? new Date(loggedUserDetails.createdAt) : /* @__PURE__ */ new Date(),
|
|
5714
|
+
updatedAt: loggedUserDetails?.updatedAt ? new Date(loggedUserDetails.updatedAt) : /* @__PURE__ */ new Date(),
|
|
5715
|
+
image: loggedUserDetails?.image || void 0
|
|
5716
|
+
});
|
|
5582
5717
|
function Dialog({
|
|
5583
5718
|
...props
|
|
5584
5719
|
}) {
|
|
@@ -6483,194 +6618,688 @@ var CreateChatDialog = (props) => {
|
|
|
6483
6618
|
);
|
|
6484
6619
|
};
|
|
6485
6620
|
var CreateChatDialog_default = CreateChatDialog;
|
|
6486
|
-
|
|
6487
|
-
loggedUserDetails,
|
|
6488
|
-
onUserSelect,
|
|
6489
|
-
isCreateModalOpen = false,
|
|
6490
|
-
setIsCreateModalOpen,
|
|
6491
|
-
searchQuery = "",
|
|
6492
|
-
setSearchQuery
|
|
6493
|
-
}) => {
|
|
6494
|
-
const { showColorModeToggle } = useChatTheme();
|
|
6495
|
-
const user = {
|
|
6496
|
-
_id: loggedUserDetails?._id || "1",
|
|
6497
|
-
name: formatLoggedUserName(loggedUserDetails?.name),
|
|
6498
|
-
email: loggedUserDetails?.email || "user@example.com",
|
|
6499
|
-
role: loggedUserDetails?.role || "user",
|
|
6500
|
-
isActive: loggedUserDetails?.isActive ?? true,
|
|
6501
|
-
createdAt: loggedUserDetails?.createdAt ? new Date(loggedUserDetails.createdAt) : /* @__PURE__ */ new Date(),
|
|
6502
|
-
updatedAt: loggedUserDetails?.updatedAt ? new Date(loggedUserDetails.updatedAt) : /* @__PURE__ */ new Date(),
|
|
6503
|
-
image: loggedUserDetails?.image || void 0
|
|
6504
|
-
};
|
|
6505
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 border-b border-(--chat-border) bg-(--chat-surface) px-3 pb-3 pt-3", children: [
|
|
6506
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-center gap-2.5", children: [
|
|
6507
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative shrink-0", children: [
|
|
6508
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: "size-8 ring-1 ring-(--chat-surface)", children: [
|
|
6509
|
-
user.image ? /* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: user.image, alt: user.name }) : null,
|
|
6510
|
-
/* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { className: "bg-(--chat-theme-10) text-[10px] font-medium text-(--chat-theme)", children: (user.name || "?").charAt(0).toUpperCase() })
|
|
6511
|
-
] }),
|
|
6512
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -bottom-0.5 -right-0.5 size-2 rounded-full border-2 border-(--chat-surface) bg-(--chat-online)" })
|
|
6513
|
-
] }),
|
|
6514
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
6515
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "truncate text-xs font-medium leading-tight text-(--chat-text)", children: user.name }),
|
|
6516
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-[10px] text-(--chat-muted)", children: user.email })
|
|
6517
|
-
] }),
|
|
6518
|
-
showColorModeToggle ? /* @__PURE__ */ jsxRuntime.jsx(ChatThemeToggle_default, {}) : null
|
|
6519
|
-
] }),
|
|
6520
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 flex items-center gap-1.5", children: [
|
|
6521
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: chatSidebarSearchShellClass, children: [
|
|
6522
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "pointer-events-none size-3.5 shrink-0 text-(--chat-muted)" }),
|
|
6523
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6524
|
-
"input",
|
|
6525
|
-
{
|
|
6526
|
-
type: "text",
|
|
6527
|
-
inputMode: "search",
|
|
6528
|
-
enterKeyHint: "search",
|
|
6529
|
-
placeholder: "Search conversations...",
|
|
6530
|
-
value: searchQuery,
|
|
6531
|
-
onChange: (e) => setSearchQuery?.(e.target.value),
|
|
6532
|
-
className: chatSidebarSearchInputClass
|
|
6533
|
-
}
|
|
6534
|
-
),
|
|
6535
|
-
searchQuery ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
6536
|
-
"button",
|
|
6537
|
-
{
|
|
6538
|
-
type: "button",
|
|
6539
|
-
onClick: () => setSearchQuery?.(""),
|
|
6540
|
-
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)",
|
|
6541
|
-
"aria-label": "Clear search",
|
|
6542
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 12 })
|
|
6543
|
-
}
|
|
6544
|
-
) : null
|
|
6545
|
-
] }),
|
|
6546
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6547
|
-
CreateChatDialog_default,
|
|
6548
|
-
{
|
|
6549
|
-
loggedUserDetails,
|
|
6550
|
-
onUserSelect,
|
|
6551
|
-
isCreateModalOpen,
|
|
6552
|
-
setIsCreateModalOpen
|
|
6553
|
-
}
|
|
6554
|
-
)
|
|
6555
|
-
] })
|
|
6556
|
-
] });
|
|
6557
|
-
};
|
|
6558
|
-
var LoggedUserDetails_default = LoggedUserDetails;
|
|
6559
|
-
function ScrollArea({
|
|
6560
|
-
className,
|
|
6561
|
-
children,
|
|
6562
|
-
...props
|
|
6563
|
-
}) {
|
|
6564
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6565
|
-
radixUi.ScrollArea.Root,
|
|
6566
|
-
{
|
|
6567
|
-
"data-slot": "scroll-area",
|
|
6568
|
-
className: cn("relative", className),
|
|
6569
|
-
...props,
|
|
6570
|
-
children: [
|
|
6571
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6572
|
-
radixUi.ScrollArea.Viewport,
|
|
6573
|
-
{
|
|
6574
|
-
"data-slot": "scroll-area-viewport",
|
|
6575
|
-
className: "focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1",
|
|
6576
|
-
children
|
|
6577
|
-
}
|
|
6578
|
-
),
|
|
6579
|
-
/* @__PURE__ */ jsxRuntime.jsx(ScrollBar, {}),
|
|
6580
|
-
/* @__PURE__ */ jsxRuntime.jsx(radixUi.ScrollArea.Corner, {})
|
|
6581
|
-
]
|
|
6582
|
-
}
|
|
6583
|
-
);
|
|
6584
|
-
}
|
|
6585
|
-
function ScrollBar({
|
|
6621
|
+
function Switch({
|
|
6586
6622
|
className,
|
|
6587
|
-
|
|
6623
|
+
size = "default",
|
|
6588
6624
|
...props
|
|
6589
6625
|
}) {
|
|
6590
6626
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6591
|
-
radixUi.
|
|
6627
|
+
radixUi.Switch.Root,
|
|
6592
6628
|
{
|
|
6593
|
-
"data-slot": "
|
|
6594
|
-
|
|
6629
|
+
"data-slot": "switch",
|
|
6630
|
+
"data-size": size,
|
|
6595
6631
|
className: cn(
|
|
6596
|
-
"flex
|
|
6597
|
-
orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent",
|
|
6598
|
-
orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent",
|
|
6632
|
+
"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",
|
|
6599
6633
|
className
|
|
6600
6634
|
),
|
|
6601
6635
|
...props,
|
|
6602
6636
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6603
|
-
radixUi.
|
|
6637
|
+
radixUi.Switch.Thumb,
|
|
6604
6638
|
{
|
|
6605
|
-
"data-slot": "
|
|
6606
|
-
className:
|
|
6639
|
+
"data-slot": "switch-thumb",
|
|
6640
|
+
className: cn(
|
|
6641
|
+
"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"
|
|
6642
|
+
)
|
|
6607
6643
|
}
|
|
6608
6644
|
)
|
|
6609
6645
|
}
|
|
6610
6646
|
);
|
|
6611
6647
|
}
|
|
6612
6648
|
|
|
6613
|
-
// src/
|
|
6614
|
-
|
|
6615
|
-
|
|
6616
|
-
var
|
|
6617
|
-
var
|
|
6618
|
-
var
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
draftRevision += 1;
|
|
6626
|
-
draftListeners.forEach((listener) => listener());
|
|
6627
|
-
}
|
|
6628
|
-
function subscribeToDrafts(listener) {
|
|
6629
|
-
draftListeners.add(listener);
|
|
6630
|
-
return () => {
|
|
6631
|
-
draftListeners.delete(listener);
|
|
6632
|
-
};
|
|
6633
|
-
}
|
|
6634
|
-
function getDraftRevision() {
|
|
6635
|
-
return draftRevision;
|
|
6636
|
-
}
|
|
6637
|
-
function useDraftRevision() {
|
|
6638
|
-
return React2.useSyncExternalStore(subscribeToDrafts, getDraftRevision, getDraftRevision);
|
|
6639
|
-
}
|
|
6640
|
-
function getConversationDraft(conversationId) {
|
|
6641
|
-
if (!conversationId) return emptyDraft();
|
|
6642
|
-
return conversationDrafts.get(conversationId) ?? emptyDraft();
|
|
6643
|
-
}
|
|
6644
|
-
function updateConversationDraft(conversationId, draft) {
|
|
6645
|
-
if (!conversationId) return;
|
|
6646
|
-
if (draft.messageInput.trim() || draft.attachments.length > 0) {
|
|
6647
|
-
conversationDrafts.set(conversationId, {
|
|
6648
|
-
messageInput: draft.messageInput,
|
|
6649
|
-
attachments: draft.attachments
|
|
6650
|
-
});
|
|
6651
|
-
} else {
|
|
6652
|
-
conversationDrafts.delete(conversationId);
|
|
6653
|
-
}
|
|
6654
|
-
notifyDraftChange();
|
|
6655
|
-
}
|
|
6656
|
-
function clearConversationDraft(conversationId) {
|
|
6657
|
-
if (!conversationId) return;
|
|
6658
|
-
if (!conversationDrafts.has(conversationId)) return;
|
|
6659
|
-
conversationDrafts.delete(conversationId);
|
|
6660
|
-
notifyDraftChange();
|
|
6661
|
-
}
|
|
6662
|
-
function getConversationDraftPreview(conversationId) {
|
|
6663
|
-
if (!conversationId) return null;
|
|
6664
|
-
const draft = conversationDrafts.get(conversationId);
|
|
6665
|
-
if (!draft) return null;
|
|
6666
|
-
const text = draft.messageInput.trim();
|
|
6667
|
-
if (text) {
|
|
6668
|
-
return text.length > DRAFT_PREVIEW_MAX_LENGTH ? `${text.slice(0, DRAFT_PREVIEW_MAX_LENGTH)}\u2026` : text;
|
|
6649
|
+
// src/notifications/push.service.ts
|
|
6650
|
+
init_client();
|
|
6651
|
+
init_api_version();
|
|
6652
|
+
var PUSH_TOKEN_STORAGE_KEY = "realtimex-push-token";
|
|
6653
|
+
var SERVICE_WORKER_PATH = "/firebase-messaging-sw.js";
|
|
6654
|
+
var PUSH_CHANGED_EVENT = "realtimex:push-changed";
|
|
6655
|
+
var emitPushChanged = (enabled) => {
|
|
6656
|
+
try {
|
|
6657
|
+
window.dispatchEvent(
|
|
6658
|
+
new CustomEvent(PUSH_CHANGED_EVENT, { detail: { enabled } })
|
|
6659
|
+
);
|
|
6660
|
+
} catch {
|
|
6669
6661
|
}
|
|
6670
|
-
|
|
6671
|
-
|
|
6662
|
+
};
|
|
6663
|
+
var pushApiUrl = (path) => exports.buildVersionedApiUrl(path, { service: "push" });
|
|
6664
|
+
var apiGetPushConfig = async () => {
|
|
6665
|
+
const { data } = await apiClient.get(pushApiUrl("/notifications/push/config"));
|
|
6666
|
+
return data?.data;
|
|
6667
|
+
};
|
|
6668
|
+
var apiRegisterPushToken = async (token, deviceLabel) => {
|
|
6669
|
+
const { data } = await apiClient.post(pushApiUrl("/notifications/push/token"), {
|
|
6670
|
+
token,
|
|
6671
|
+
deviceLabel
|
|
6672
|
+
});
|
|
6673
|
+
return data?.data;
|
|
6674
|
+
};
|
|
6675
|
+
var apiRemovePushToken = async (token) => {
|
|
6676
|
+
const { data } = await apiClient.delete(pushApiUrl("/notifications/push/token"), {
|
|
6677
|
+
data: { token }
|
|
6678
|
+
});
|
|
6679
|
+
return data;
|
|
6680
|
+
};
|
|
6681
|
+
var apiGetPushPreference = async () => {
|
|
6682
|
+
const { data } = await apiClient.get(
|
|
6683
|
+
pushApiUrl("/notifications/push/preference")
|
|
6684
|
+
);
|
|
6685
|
+
return data?.data;
|
|
6686
|
+
};
|
|
6687
|
+
var apiUpdatePushPreference = async (enabled) => {
|
|
6688
|
+
const { data } = await apiClient.patch(
|
|
6689
|
+
pushApiUrl("/notifications/push/preference"),
|
|
6690
|
+
{ enabled }
|
|
6691
|
+
);
|
|
6692
|
+
return data?.data;
|
|
6693
|
+
};
|
|
6694
|
+
var isPushSupported = () => typeof window !== "undefined" && "Notification" in window && "serviceWorker" in navigator && "PushManager" in window;
|
|
6695
|
+
var getStoredPushToken = () => {
|
|
6696
|
+
try {
|
|
6697
|
+
return localStorage.getItem(PUSH_TOKEN_STORAGE_KEY);
|
|
6698
|
+
} catch {
|
|
6699
|
+
return null;
|
|
6672
6700
|
}
|
|
6673
|
-
|
|
6701
|
+
};
|
|
6702
|
+
var storePushToken = (token) => {
|
|
6703
|
+
try {
|
|
6704
|
+
if (token) localStorage.setItem(PUSH_TOKEN_STORAGE_KEY, token);
|
|
6705
|
+
else localStorage.removeItem(PUSH_TOKEN_STORAGE_KEY);
|
|
6706
|
+
} catch {
|
|
6707
|
+
}
|
|
6708
|
+
};
|
|
6709
|
+
var defaultDeviceLabel = () => {
|
|
6710
|
+
const ua = navigator.userAgent;
|
|
6711
|
+
const browser = /edg\//i.test(ua) ? "Edge" : /chrome/i.test(ua) ? "Chrome" : /safari/i.test(ua) ? "Safari" : /firefox/i.test(ua) ? "Firefox" : "Browser";
|
|
6712
|
+
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";
|
|
6713
|
+
return `${browser} on ${os}`;
|
|
6714
|
+
};
|
|
6715
|
+
var loadFirebaseMessaging = async () => {
|
|
6716
|
+
try {
|
|
6717
|
+
const [{ initializeApp, getApps }, messagingModule] = await Promise.all([
|
|
6718
|
+
import('firebase/app'),
|
|
6719
|
+
import('firebase/messaging')
|
|
6720
|
+
]);
|
|
6721
|
+
return { initializeApp, getApps, ...messagingModule };
|
|
6722
|
+
} catch {
|
|
6723
|
+
throw new Error(
|
|
6724
|
+
'Push notifications need the "firebase" package \u2014 run: npm install firebase'
|
|
6725
|
+
);
|
|
6726
|
+
}
|
|
6727
|
+
};
|
|
6728
|
+
var getFirebaseMessaging = async (firebaseConfig) => {
|
|
6729
|
+
const fb = await loadFirebaseMessaging();
|
|
6730
|
+
const app = fb.getApps().length ? fb.getApps()[0] : fb.initializeApp(firebaseConfig);
|
|
6731
|
+
return { fb, messaging: fb.getMessaging(app) };
|
|
6732
|
+
};
|
|
6733
|
+
var enablePushOnThisDevice = async () => {
|
|
6734
|
+
if (!isPushSupported()) {
|
|
6735
|
+
throw new Error("Push notifications are not supported in this browser");
|
|
6736
|
+
}
|
|
6737
|
+
const config = await apiGetPushConfig();
|
|
6738
|
+
if (!config?.enabled) {
|
|
6739
|
+
throw new Error("Push notifications are disabled for this workspace");
|
|
6740
|
+
}
|
|
6741
|
+
if (!config.configured || !config.firebaseConfig || !config.vapidKey) {
|
|
6742
|
+
throw new Error(
|
|
6743
|
+
"Push notifications are not configured on the server yet"
|
|
6744
|
+
);
|
|
6745
|
+
}
|
|
6746
|
+
const permission = await Notification.requestPermission();
|
|
6747
|
+
if (permission !== "granted") {
|
|
6748
|
+
throw new Error("Notification permission was not granted");
|
|
6749
|
+
}
|
|
6750
|
+
let registration;
|
|
6751
|
+
try {
|
|
6752
|
+
registration = await navigator.serviceWorker.register(
|
|
6753
|
+
`${SERVICE_WORKER_PATH}?config=${encodeURIComponent(
|
|
6754
|
+
JSON.stringify(config.firebaseConfig)
|
|
6755
|
+
)}`
|
|
6756
|
+
);
|
|
6757
|
+
} catch {
|
|
6758
|
+
throw new Error(
|
|
6759
|
+
`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`
|
|
6760
|
+
);
|
|
6761
|
+
}
|
|
6762
|
+
const { fb, messaging } = await getFirebaseMessaging(config.firebaseConfig);
|
|
6763
|
+
const token = await fb.getToken(messaging, {
|
|
6764
|
+
vapidKey: config.vapidKey,
|
|
6765
|
+
serviceWorkerRegistration: registration
|
|
6766
|
+
});
|
|
6767
|
+
if (!token) {
|
|
6768
|
+
throw new Error("Could not obtain a push token from Firebase");
|
|
6769
|
+
}
|
|
6770
|
+
await apiRegisterPushToken(token, defaultDeviceLabel());
|
|
6771
|
+
storePushToken(token);
|
|
6772
|
+
emitPushChanged(true);
|
|
6773
|
+
return token;
|
|
6774
|
+
};
|
|
6775
|
+
var disablePushOnThisDevice = async () => {
|
|
6776
|
+
const token = getStoredPushToken();
|
|
6777
|
+
if (!token) return;
|
|
6778
|
+
try {
|
|
6779
|
+
const config = await apiGetPushConfig();
|
|
6780
|
+
if (config?.firebaseConfig) {
|
|
6781
|
+
const { fb, messaging } = await getFirebaseMessaging(
|
|
6782
|
+
config.firebaseConfig
|
|
6783
|
+
);
|
|
6784
|
+
await fb.deleteToken(messaging).catch(() => void 0);
|
|
6785
|
+
}
|
|
6786
|
+
} catch {
|
|
6787
|
+
}
|
|
6788
|
+
await apiRemovePushToken(token).catch(() => void 0);
|
|
6789
|
+
storePushToken(null);
|
|
6790
|
+
emitPushChanged(false);
|
|
6791
|
+
};
|
|
6792
|
+
var onForegroundPush = async (callback) => {
|
|
6793
|
+
const config = await apiGetPushConfig();
|
|
6794
|
+
if (!config?.configured || !config.firebaseConfig) {
|
|
6795
|
+
throw new Error("Push config unavailable (not configured or API not ready)");
|
|
6796
|
+
}
|
|
6797
|
+
const { fb, messaging } = await getFirebaseMessaging(config.firebaseConfig);
|
|
6798
|
+
return fb.onMessage(messaging, (payload) => {
|
|
6799
|
+
console.log("[realtimex-push] FCM foreground payload (raw):", payload);
|
|
6800
|
+
console.log("[realtimex-push] FCM foreground data:", payload?.data);
|
|
6801
|
+
console.log("[realtimex-push] FCM foreground notification:", payload?.notification);
|
|
6802
|
+
callback({
|
|
6803
|
+
title: payload?.notification?.title,
|
|
6804
|
+
body: payload?.notification?.body,
|
|
6805
|
+
data: payload?.data
|
|
6806
|
+
});
|
|
6807
|
+
});
|
|
6808
|
+
};
|
|
6809
|
+
|
|
6810
|
+
// src/notifications/usePushNotifications.ts
|
|
6811
|
+
var usePushNotifications = () => {
|
|
6812
|
+
const [state, setState] = React2.useState({
|
|
6813
|
+
supported: false,
|
|
6814
|
+
allowedByWorkspace: false,
|
|
6815
|
+
configured: false,
|
|
6816
|
+
permission: "unsupported",
|
|
6817
|
+
userEnabled: true,
|
|
6818
|
+
deviceEnabled: false,
|
|
6819
|
+
loading: true,
|
|
6820
|
+
error: null
|
|
6821
|
+
});
|
|
6822
|
+
const refresh = React2.useCallback(async () => {
|
|
6823
|
+
if (!isPushSupported()) {
|
|
6824
|
+
setState((prev) => ({
|
|
6825
|
+
...prev,
|
|
6826
|
+
supported: false,
|
|
6827
|
+
loading: false
|
|
6828
|
+
}));
|
|
6829
|
+
return;
|
|
6830
|
+
}
|
|
6831
|
+
try {
|
|
6832
|
+
const [config, preference] = await Promise.all([
|
|
6833
|
+
apiGetPushConfig(),
|
|
6834
|
+
apiGetPushPreference().catch(() => null)
|
|
6835
|
+
]);
|
|
6836
|
+
setState({
|
|
6837
|
+
supported: true,
|
|
6838
|
+
allowedByWorkspace: Boolean(config?.enabled),
|
|
6839
|
+
configured: Boolean(config?.configured),
|
|
6840
|
+
permission: Notification.permission,
|
|
6841
|
+
userEnabled: preference?.enabled ?? true,
|
|
6842
|
+
deviceEnabled: Notification.permission === "granted" && Boolean(getStoredPushToken()),
|
|
6843
|
+
loading: false,
|
|
6844
|
+
error: null
|
|
6845
|
+
});
|
|
6846
|
+
} catch (error) {
|
|
6847
|
+
setState((prev) => ({
|
|
6848
|
+
...prev,
|
|
6849
|
+
supported: true,
|
|
6850
|
+
loading: false,
|
|
6851
|
+
error: error instanceof Error ? error.message : "Could not load push settings"
|
|
6852
|
+
}));
|
|
6853
|
+
}
|
|
6854
|
+
}, []);
|
|
6855
|
+
React2.useEffect(() => {
|
|
6856
|
+
void refresh();
|
|
6857
|
+
}, [refresh]);
|
|
6858
|
+
const enable = React2.useCallback(async () => {
|
|
6859
|
+
setState((prev) => ({ ...prev, loading: true, error: null }));
|
|
6860
|
+
try {
|
|
6861
|
+
await enablePushOnThisDevice();
|
|
6862
|
+
await refresh();
|
|
6863
|
+
return true;
|
|
6864
|
+
} catch (error) {
|
|
6865
|
+
setState((prev) => ({
|
|
6866
|
+
...prev,
|
|
6867
|
+
loading: false,
|
|
6868
|
+
permission: isPushSupported() ? Notification.permission : "unsupported",
|
|
6869
|
+
error: error instanceof Error ? error.message : "Could not enable push notifications"
|
|
6870
|
+
}));
|
|
6871
|
+
return false;
|
|
6872
|
+
}
|
|
6873
|
+
}, [refresh]);
|
|
6874
|
+
const disable = React2.useCallback(async () => {
|
|
6875
|
+
setState((prev) => ({ ...prev, loading: true, error: null }));
|
|
6876
|
+
try {
|
|
6877
|
+
await disablePushOnThisDevice();
|
|
6878
|
+
} finally {
|
|
6879
|
+
await refresh();
|
|
6880
|
+
}
|
|
6881
|
+
}, [refresh]);
|
|
6882
|
+
const setUserEnabled = React2.useCallback(
|
|
6883
|
+
async (enabled) => {
|
|
6884
|
+
setState((prev) => ({ ...prev, loading: true, error: null }));
|
|
6885
|
+
try {
|
|
6886
|
+
await apiUpdatePushPreference(enabled);
|
|
6887
|
+
setState((prev) => ({ ...prev, userEnabled: enabled, loading: false }));
|
|
6888
|
+
} catch (error) {
|
|
6889
|
+
setState((prev) => ({
|
|
6890
|
+
...prev,
|
|
6891
|
+
userEnabled: !enabled,
|
|
6892
|
+
loading: false,
|
|
6893
|
+
error: error instanceof Error ? error.message : "Could not update push preference"
|
|
6894
|
+
}));
|
|
6895
|
+
}
|
|
6896
|
+
},
|
|
6897
|
+
[]
|
|
6898
|
+
);
|
|
6899
|
+
return { ...state, enable, disable, setUserEnabled, refresh };
|
|
6900
|
+
};
|
|
6901
|
+
var PushNotificationToggle = ({
|
|
6902
|
+
className,
|
|
6903
|
+
label = "Push notifications",
|
|
6904
|
+
description = "Get notified about new messages on this device",
|
|
6905
|
+
children
|
|
6906
|
+
}) => {
|
|
6907
|
+
const push = usePushNotifications();
|
|
6908
|
+
const [isToggling, setIsToggling] = React2.useState(false);
|
|
6909
|
+
if (!push.supported || !push.allowedByWorkspace || !push.configured) {
|
|
6910
|
+
return null;
|
|
6911
|
+
}
|
|
6912
|
+
const isOn = push.deviceEnabled && push.userEnabled;
|
|
6913
|
+
const permissionBlocked = push.permission === "denied";
|
|
6914
|
+
const showLoader = isToggling;
|
|
6915
|
+
const handleChange = async (checked) => {
|
|
6916
|
+
setIsToggling(true);
|
|
6917
|
+
try {
|
|
6918
|
+
if (checked) {
|
|
6919
|
+
if (!push.userEnabled) await push.setUserEnabled(true);
|
|
6920
|
+
if (!push.deviceEnabled) await push.enable();
|
|
6921
|
+
} else {
|
|
6922
|
+
await push.disable();
|
|
6923
|
+
}
|
|
6924
|
+
} finally {
|
|
6925
|
+
setIsToggling(false);
|
|
6926
|
+
}
|
|
6927
|
+
};
|
|
6928
|
+
const renderProps = {
|
|
6929
|
+
label,
|
|
6930
|
+
description: permissionBlocked ? "Notifications are blocked in your browser settings" : push.error ?? description,
|
|
6931
|
+
checked: isOn,
|
|
6932
|
+
disabled: showLoader || permissionBlocked || push.loading,
|
|
6933
|
+
loading: showLoader || push.loading,
|
|
6934
|
+
permissionBlocked,
|
|
6935
|
+
error: push.error,
|
|
6936
|
+
onCheckedChange: (checked) => void handleChange(checked)
|
|
6937
|
+
};
|
|
6938
|
+
if (children) {
|
|
6939
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children(renderProps) });
|
|
6940
|
+
}
|
|
6941
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6942
|
+
"div",
|
|
6943
|
+
{
|
|
6944
|
+
className: cn(
|
|
6945
|
+
"flex items-center justify-between gap-4 rounded-xl border border-(--chat-border) bg-(--chat-surface) px-4 py-3",
|
|
6946
|
+
className
|
|
6947
|
+
),
|
|
6948
|
+
children: [
|
|
6949
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
|
|
6950
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-(--chat-text)", children: label }),
|
|
6951
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-(--chat-muted)", children: renderProps.description })
|
|
6952
|
+
] }),
|
|
6953
|
+
showLoader ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
6954
|
+
lucideReact.Loader2,
|
|
6955
|
+
{
|
|
6956
|
+
className: "size-5 shrink-0 animate-spin text-(--chat-theme)",
|
|
6957
|
+
"aria-label": "Updating push notifications"
|
|
6958
|
+
}
|
|
6959
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
6960
|
+
Switch,
|
|
6961
|
+
{
|
|
6962
|
+
checked: isOn,
|
|
6963
|
+
disabled: permissionBlocked || push.loading,
|
|
6964
|
+
onCheckedChange: (checked) => void handleChange(checked),
|
|
6965
|
+
"aria-label": `Toggle ${label}`
|
|
6966
|
+
}
|
|
6967
|
+
)
|
|
6968
|
+
]
|
|
6969
|
+
}
|
|
6970
|
+
);
|
|
6971
|
+
};
|
|
6972
|
+
var LoggedUserSettingsContent = ({
|
|
6973
|
+
user,
|
|
6974
|
+
title = "Account settings",
|
|
6975
|
+
showProfile = true,
|
|
6976
|
+
showPushToggle = true,
|
|
6977
|
+
className
|
|
6978
|
+
}) => {
|
|
6979
|
+
const { resolveComponent, slotClassName } = useChatCustomization();
|
|
6980
|
+
const PushToggleSlot = resolveComponent(
|
|
6981
|
+
"PushNotificationToggle",
|
|
6982
|
+
PushNotificationToggle
|
|
6983
|
+
);
|
|
6984
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
6985
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6986
|
+
"div",
|
|
6987
|
+
{
|
|
6988
|
+
className: cn(
|
|
6989
|
+
"border-b border-(--chat-border) px-5 py-4",
|
|
6990
|
+
slotClassName("loggedUserSettingsHeader")
|
|
6991
|
+
),
|
|
6992
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { className: "text-left text-base font-semibold text-(--chat-text)", children: title })
|
|
6993
|
+
}
|
|
6994
|
+
),
|
|
6995
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6996
|
+
"div",
|
|
6997
|
+
{
|
|
6998
|
+
className: cn(
|
|
6999
|
+
"space-y-5 px-5 py-5",
|
|
7000
|
+
slotClassName("loggedUserSettingsContent", className)
|
|
7001
|
+
),
|
|
7002
|
+
children: [
|
|
7003
|
+
showProfile ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center text-center", children: [
|
|
7004
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
7005
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7006
|
+
Avatar,
|
|
7007
|
+
{
|
|
7008
|
+
className: cn(
|
|
7009
|
+
"size-16 ring-2 ring-(--chat-theme-20)",
|
|
7010
|
+
slotClassName("loggedUserSettingsAvatar")
|
|
7011
|
+
),
|
|
7012
|
+
children: [
|
|
7013
|
+
user.image ? /* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: user.image, alt: user.name }) : null,
|
|
7014
|
+
/* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { className: "bg-(--chat-theme-10) text-lg font-medium text-(--chat-theme)", children: (user.name || "?").charAt(0).toUpperCase() })
|
|
7015
|
+
]
|
|
7016
|
+
}
|
|
7017
|
+
),
|
|
7018
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute bottom-0.5 right-0.5 size-3 rounded-full border-2 border-(--chat-surface) bg-(--chat-online)" })
|
|
7019
|
+
] }),
|
|
7020
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mt-3 text-base font-semibold text-(--chat-text)", children: user.name }),
|
|
7021
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 text-sm text-(--chat-muted)", children: user.email }),
|
|
7022
|
+
/* @__PURE__ */ jsxRuntime.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: [
|
|
7023
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "size-1.5 rounded-full bg-(--chat-online)" }),
|
|
7024
|
+
"Online"
|
|
7025
|
+
] })
|
|
7026
|
+
] }) : null,
|
|
7027
|
+
showPushToggle ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-(--chat-border) pt-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7028
|
+
PushToggleSlot,
|
|
7029
|
+
{
|
|
7030
|
+
className: cn(
|
|
7031
|
+
"flex items-center justify-between gap-4 rounded-xl border border-(--chat-border) bg-(--chat-theme-10) px-4 py-3",
|
|
7032
|
+
slotClassName("pushNotificationToggle")
|
|
7033
|
+
)
|
|
7034
|
+
}
|
|
7035
|
+
) }) : null
|
|
7036
|
+
]
|
|
7037
|
+
}
|
|
7038
|
+
)
|
|
7039
|
+
] });
|
|
7040
|
+
};
|
|
7041
|
+
var LoggedUserSettingsContent_default = LoggedUserSettingsContent;
|
|
7042
|
+
var LoggedUserSettingsTrigger = ({
|
|
7043
|
+
onClick,
|
|
7044
|
+
className,
|
|
7045
|
+
tooltip = "Settings",
|
|
7046
|
+
ariaLabel = "Account settings"
|
|
7047
|
+
}) => {
|
|
7048
|
+
const { slotClassName } = useChatCustomization();
|
|
7049
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
|
|
7050
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7051
|
+
Button,
|
|
7052
|
+
{
|
|
7053
|
+
type: "button",
|
|
7054
|
+
variant: "ghost",
|
|
7055
|
+
size: "icon",
|
|
7056
|
+
className: cn(
|
|
7057
|
+
sidebarActionBtnClass,
|
|
7058
|
+
slotClassName("loggedUserSettingsTrigger", className)
|
|
7059
|
+
),
|
|
7060
|
+
"aria-label": ariaLabel,
|
|
7061
|
+
onClick,
|
|
7062
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings, { className: "size-3.5", strokeWidth: 2 })
|
|
7063
|
+
}
|
|
7064
|
+
) }),
|
|
7065
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "bottom", children: tooltip })
|
|
7066
|
+
] });
|
|
7067
|
+
};
|
|
7068
|
+
var LoggedUserSettingsTrigger_default = LoggedUserSettingsTrigger;
|
|
7069
|
+
var LoggedUserSettingsDialog = ({
|
|
7070
|
+
loggedUserDetails,
|
|
7071
|
+
open: controlledOpen,
|
|
7072
|
+
onOpenChange: controlledOnOpenChange,
|
|
7073
|
+
title,
|
|
7074
|
+
showProfile = true,
|
|
7075
|
+
showPushToggle = true,
|
|
7076
|
+
className
|
|
7077
|
+
}) => {
|
|
7078
|
+
const { resolveComponent, slotClassName } = useChatCustomization();
|
|
7079
|
+
const [internalOpen, setInternalOpen] = React2.useState(false);
|
|
7080
|
+
const open = controlledOpen ?? internalOpen;
|
|
7081
|
+
const onOpenChange = controlledOnOpenChange ?? setInternalOpen;
|
|
7082
|
+
const TriggerSlot = resolveComponent(
|
|
7083
|
+
"LoggedUserSettingsTrigger",
|
|
7084
|
+
LoggedUserSettingsTrigger_default
|
|
7085
|
+
);
|
|
7086
|
+
const ContentSlot = resolveComponent(
|
|
7087
|
+
"LoggedUserSettingsContent",
|
|
7088
|
+
LoggedUserSettingsContent_default
|
|
7089
|
+
);
|
|
7090
|
+
const user = buildLoggedUserProfile(loggedUserDetails);
|
|
7091
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Dialog, { open, onOpenChange, children: [
|
|
7092
|
+
/* @__PURE__ */ jsxRuntime.jsx(TriggerSlot, { onClick: () => onOpenChange(true) }),
|
|
7093
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7094
|
+
ChatDialogContent,
|
|
7095
|
+
{
|
|
7096
|
+
className: cn(
|
|
7097
|
+
"gap-0 overflow-hidden p-0 sm:max-w-[380px]",
|
|
7098
|
+
slotClassName("loggedUserSettingsDialog", className)
|
|
7099
|
+
),
|
|
7100
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7101
|
+
ContentSlot,
|
|
7102
|
+
{
|
|
7103
|
+
loggedUserDetails,
|
|
7104
|
+
user,
|
|
7105
|
+
onClose: () => onOpenChange(false),
|
|
7106
|
+
title,
|
|
7107
|
+
showProfile,
|
|
7108
|
+
showPushToggle
|
|
7109
|
+
}
|
|
7110
|
+
)
|
|
7111
|
+
}
|
|
7112
|
+
)
|
|
7113
|
+
] });
|
|
7114
|
+
};
|
|
7115
|
+
var LoggedUserSettingsDialog_default = LoggedUserSettingsDialog;
|
|
7116
|
+
var LoggedUserDetails = ({
|
|
7117
|
+
loggedUserDetails,
|
|
7118
|
+
onUserSelect,
|
|
7119
|
+
isCreateModalOpen = false,
|
|
7120
|
+
setIsCreateModalOpen,
|
|
7121
|
+
searchQuery = "",
|
|
7122
|
+
setSearchQuery
|
|
7123
|
+
}) => {
|
|
7124
|
+
const { showColorModeToggle } = useChatTheme();
|
|
7125
|
+
const { resolveComponent } = useChatCustomization();
|
|
7126
|
+
const SettingsDialogSlot = resolveComponent(
|
|
7127
|
+
"LoggedUserSettingsDialog",
|
|
7128
|
+
LoggedUserSettingsDialog_default
|
|
7129
|
+
);
|
|
7130
|
+
const user = buildLoggedUserProfile(loggedUserDetails);
|
|
7131
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 border-b border-(--chat-border) bg-(--chat-surface) px-3 pb-3 pt-3", children: [
|
|
7132
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-center gap-2.5", children: [
|
|
7133
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative shrink-0", children: [
|
|
7134
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: "size-8 ring-1 ring-(--chat-surface)", children: [
|
|
7135
|
+
user.image ? /* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: user.image, alt: user.name }) : null,
|
|
7136
|
+
/* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { className: "bg-(--chat-theme-10) text-[10px] font-medium text-(--chat-theme)", children: (user.name || "?").charAt(0).toUpperCase() })
|
|
7137
|
+
] }),
|
|
7138
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -bottom-0.5 -right-0.5 size-2 rounded-full border-2 border-(--chat-surface) bg-(--chat-online)" })
|
|
7139
|
+
] }),
|
|
7140
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
7141
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "truncate text-xs font-medium leading-tight text-(--chat-text)", children: user.name }),
|
|
7142
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-[10px] text-(--chat-muted)", children: user.email })
|
|
7143
|
+
] }),
|
|
7144
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-0.5", children: [
|
|
7145
|
+
/* @__PURE__ */ jsxRuntime.jsx(SettingsDialogSlot, { loggedUserDetails }),
|
|
7146
|
+
showColorModeToggle ? /* @__PURE__ */ jsxRuntime.jsx(ChatThemeToggle_default, {}) : null
|
|
7147
|
+
] })
|
|
7148
|
+
] }),
|
|
7149
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 flex items-center gap-1.5", children: [
|
|
7150
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: chatSidebarSearchShellClass, children: [
|
|
7151
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "pointer-events-none size-3.5 shrink-0 text-(--chat-muted)" }),
|
|
7152
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7153
|
+
"input",
|
|
7154
|
+
{
|
|
7155
|
+
type: "text",
|
|
7156
|
+
inputMode: "search",
|
|
7157
|
+
enterKeyHint: "search",
|
|
7158
|
+
placeholder: "Search conversations...",
|
|
7159
|
+
value: searchQuery,
|
|
7160
|
+
onChange: (e) => setSearchQuery?.(e.target.value),
|
|
7161
|
+
className: chatSidebarSearchInputClass
|
|
7162
|
+
}
|
|
7163
|
+
),
|
|
7164
|
+
searchQuery ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
7165
|
+
"button",
|
|
7166
|
+
{
|
|
7167
|
+
type: "button",
|
|
7168
|
+
onClick: () => setSearchQuery?.(""),
|
|
7169
|
+
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)",
|
|
7170
|
+
"aria-label": "Clear search",
|
|
7171
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 12 })
|
|
7172
|
+
}
|
|
7173
|
+
) : null
|
|
7174
|
+
] }),
|
|
7175
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7176
|
+
CreateChatDialog_default,
|
|
7177
|
+
{
|
|
7178
|
+
loggedUserDetails,
|
|
7179
|
+
onUserSelect,
|
|
7180
|
+
isCreateModalOpen,
|
|
7181
|
+
setIsCreateModalOpen
|
|
7182
|
+
}
|
|
7183
|
+
)
|
|
7184
|
+
] })
|
|
7185
|
+
] });
|
|
7186
|
+
};
|
|
7187
|
+
var LoggedUserDetails_default = LoggedUserDetails;
|
|
7188
|
+
function ScrollArea({
|
|
7189
|
+
className,
|
|
7190
|
+
children,
|
|
7191
|
+
...props
|
|
7192
|
+
}) {
|
|
7193
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7194
|
+
radixUi.ScrollArea.Root,
|
|
7195
|
+
{
|
|
7196
|
+
"data-slot": "scroll-area",
|
|
7197
|
+
className: cn("relative", className),
|
|
7198
|
+
...props,
|
|
7199
|
+
children: [
|
|
7200
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7201
|
+
radixUi.ScrollArea.Viewport,
|
|
7202
|
+
{
|
|
7203
|
+
"data-slot": "scroll-area-viewport",
|
|
7204
|
+
className: "focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1",
|
|
7205
|
+
children
|
|
7206
|
+
}
|
|
7207
|
+
),
|
|
7208
|
+
/* @__PURE__ */ jsxRuntime.jsx(ScrollBar, {}),
|
|
7209
|
+
/* @__PURE__ */ jsxRuntime.jsx(radixUi.ScrollArea.Corner, {})
|
|
7210
|
+
]
|
|
7211
|
+
}
|
|
7212
|
+
);
|
|
7213
|
+
}
|
|
7214
|
+
function ScrollBar({
|
|
7215
|
+
className,
|
|
7216
|
+
orientation = "vertical",
|
|
7217
|
+
...props
|
|
7218
|
+
}) {
|
|
7219
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7220
|
+
radixUi.ScrollArea.ScrollAreaScrollbar,
|
|
7221
|
+
{
|
|
7222
|
+
"data-slot": "scroll-area-scrollbar",
|
|
7223
|
+
orientation,
|
|
7224
|
+
className: cn(
|
|
7225
|
+
"flex touch-none p-px transition-colors select-none",
|
|
7226
|
+
orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent",
|
|
7227
|
+
orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent",
|
|
7228
|
+
className
|
|
7229
|
+
),
|
|
7230
|
+
...props,
|
|
7231
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7232
|
+
radixUi.ScrollArea.ScrollAreaThumb,
|
|
7233
|
+
{
|
|
7234
|
+
"data-slot": "scroll-area-thumb",
|
|
7235
|
+
className: "bg-border relative flex-1 rounded-full"
|
|
7236
|
+
}
|
|
7237
|
+
)
|
|
7238
|
+
}
|
|
7239
|
+
);
|
|
7240
|
+
}
|
|
7241
|
+
|
|
7242
|
+
// src/chat/channel-list/useChannelList.ts
|
|
7243
|
+
init_useStore();
|
|
7244
|
+
init_store_helpers();
|
|
7245
|
+
var conversationDrafts = /* @__PURE__ */ new Map();
|
|
7246
|
+
var DRAFT_PREVIEW_MAX_LENGTH = 50;
|
|
7247
|
+
var emptyDraft = () => ({
|
|
7248
|
+
messageInput: "",
|
|
7249
|
+
attachments: []
|
|
7250
|
+
});
|
|
7251
|
+
var draftRevision = 0;
|
|
7252
|
+
var draftListeners = /* @__PURE__ */ new Set();
|
|
7253
|
+
function notifyDraftChange() {
|
|
7254
|
+
draftRevision += 1;
|
|
7255
|
+
draftListeners.forEach((listener) => listener());
|
|
7256
|
+
}
|
|
7257
|
+
function subscribeToDrafts(listener) {
|
|
7258
|
+
draftListeners.add(listener);
|
|
7259
|
+
return () => {
|
|
7260
|
+
draftListeners.delete(listener);
|
|
7261
|
+
};
|
|
7262
|
+
}
|
|
7263
|
+
function getDraftRevision() {
|
|
7264
|
+
return draftRevision;
|
|
7265
|
+
}
|
|
7266
|
+
function useDraftRevision() {
|
|
7267
|
+
return React2.useSyncExternalStore(subscribeToDrafts, getDraftRevision, getDraftRevision);
|
|
7268
|
+
}
|
|
7269
|
+
function getConversationDraft(conversationId) {
|
|
7270
|
+
if (!conversationId) return emptyDraft();
|
|
7271
|
+
return conversationDrafts.get(conversationId) ?? emptyDraft();
|
|
7272
|
+
}
|
|
7273
|
+
function updateConversationDraft(conversationId, draft) {
|
|
7274
|
+
if (!conversationId) return;
|
|
7275
|
+
if (draft.messageInput.trim() || draft.attachments.length > 0) {
|
|
7276
|
+
conversationDrafts.set(conversationId, {
|
|
7277
|
+
messageInput: draft.messageInput,
|
|
7278
|
+
attachments: draft.attachments
|
|
7279
|
+
});
|
|
7280
|
+
} else {
|
|
7281
|
+
conversationDrafts.delete(conversationId);
|
|
7282
|
+
}
|
|
7283
|
+
notifyDraftChange();
|
|
7284
|
+
}
|
|
7285
|
+
function clearConversationDraft(conversationId) {
|
|
7286
|
+
if (!conversationId) return;
|
|
7287
|
+
if (!conversationDrafts.has(conversationId)) return;
|
|
7288
|
+
conversationDrafts.delete(conversationId);
|
|
7289
|
+
notifyDraftChange();
|
|
7290
|
+
}
|
|
7291
|
+
function getConversationDraftPreview(conversationId) {
|
|
7292
|
+
if (!conversationId) return null;
|
|
7293
|
+
const draft = conversationDrafts.get(conversationId);
|
|
7294
|
+
if (!draft) return null;
|
|
7295
|
+
const text = draft.messageInput.trim();
|
|
7296
|
+
if (text) {
|
|
7297
|
+
return text.length > DRAFT_PREVIEW_MAX_LENGTH ? `${text.slice(0, DRAFT_PREVIEW_MAX_LENGTH)}\u2026` : text;
|
|
7298
|
+
}
|
|
7299
|
+
if (draft.attachments.length > 0) {
|
|
7300
|
+
return draft.attachments.length === 1 ? "Attachment" : `${draft.attachments.length} attachments`;
|
|
7301
|
+
}
|
|
7302
|
+
return null;
|
|
6674
7303
|
}
|
|
6675
7304
|
function useConversationDraft(conversationId) {
|
|
6676
7305
|
const composerRef = React2.useRef(emptyDraft());
|
|
@@ -12226,51 +12855,22 @@ var ChannelDetailsDrawer = (props) => {
|
|
|
12226
12855
|
const pId = typeof p === "string" ? p : p._id;
|
|
12227
12856
|
const pName = typeof p === "string" ? "Unknown" : p.name;
|
|
12228
12857
|
if (!pId) return null;
|
|
12229
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
12230
|
-
"span",
|
|
12231
|
-
{
|
|
12232
|
-
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)",
|
|
12233
|
-
children: pName
|
|
12234
|
-
},
|
|
12235
|
-
`${pId}-${index}`
|
|
12236
|
-
);
|
|
12237
|
-
}) })
|
|
12238
|
-
] })
|
|
12239
|
-
] })
|
|
12240
|
-
] })
|
|
12241
|
-
] })
|
|
12242
|
-
] }) });
|
|
12243
|
-
};
|
|
12244
|
-
var ChannelDetailsDrawer_default = ChannelDetailsDrawer;
|
|
12245
|
-
function Switch({
|
|
12246
|
-
className,
|
|
12247
|
-
size = "default",
|
|
12248
|
-
...props
|
|
12249
|
-
}) {
|
|
12250
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
12251
|
-
radixUi.Switch.Root,
|
|
12252
|
-
{
|
|
12253
|
-
"data-slot": "switch",
|
|
12254
|
-
"data-size": size,
|
|
12255
|
-
className: cn(
|
|
12256
|
-
"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",
|
|
12257
|
-
className
|
|
12258
|
-
),
|
|
12259
|
-
...props,
|
|
12260
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12261
|
-
radixUi.Switch.Thumb,
|
|
12262
|
-
{
|
|
12263
|
-
"data-slot": "switch-thumb",
|
|
12264
|
-
className: cn(
|
|
12265
|
-
"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"
|
|
12266
|
-
)
|
|
12267
|
-
}
|
|
12268
|
-
)
|
|
12269
|
-
}
|
|
12270
|
-
);
|
|
12271
|
-
}
|
|
12272
|
-
|
|
12273
|
-
// src/chat/header/PermissionDrawer.tsx
|
|
12858
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
12859
|
+
"span",
|
|
12860
|
+
{
|
|
12861
|
+
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)",
|
|
12862
|
+
children: pName
|
|
12863
|
+
},
|
|
12864
|
+
`${pId}-${index}`
|
|
12865
|
+
);
|
|
12866
|
+
}) })
|
|
12867
|
+
] })
|
|
12868
|
+
] })
|
|
12869
|
+
] })
|
|
12870
|
+
] })
|
|
12871
|
+
] }) });
|
|
12872
|
+
};
|
|
12873
|
+
var ChannelDetailsDrawer_default = ChannelDetailsDrawer;
|
|
12274
12874
|
init_useStore();
|
|
12275
12875
|
var PermissionDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo }) => {
|
|
12276
12876
|
const updateGroupPermissions = exports.useChatStore((s) => s.updateGroupPermissions);
|
|
@@ -17655,258 +18255,22 @@ function ChatViewport({
|
|
|
17655
18255
|
style
|
|
17656
18256
|
}) {
|
|
17657
18257
|
const resolved = resolveViewportHeight(height);
|
|
17658
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17659
|
-
"div",
|
|
17660
|
-
{
|
|
17661
|
-
className: cn(
|
|
17662
|
-
"chat-package-viewport flex min-h-0 w-full flex-col overflow-hidden",
|
|
17663
|
-
resolved.className,
|
|
17664
|
-
className
|
|
17665
|
-
),
|
|
17666
|
-
style: { ...resolved.style, ...style },
|
|
17667
|
-
children
|
|
17668
|
-
}
|
|
17669
|
-
);
|
|
17670
|
-
}
|
|
17671
|
-
var ChatViewport_default = ChatViewport;
|
|
17672
|
-
|
|
17673
|
-
|
|
17674
|
-
icon,
|
|
17675
|
-
duration
|
|
17676
|
-
};
|
|
17677
|
-
switch (type) {
|
|
17678
|
-
case "success":
|
|
17679
|
-
toast2.toast.success(message, options);
|
|
17680
|
-
break;
|
|
17681
|
-
case "error":
|
|
17682
|
-
toast2.toast.error(message, options);
|
|
17683
|
-
break;
|
|
17684
|
-
case "info":
|
|
17685
|
-
toast2.toast(message, options);
|
|
17686
|
-
break;
|
|
17687
|
-
case "warning":
|
|
17688
|
-
toast2.toast(message, { ...options, icon: "\u26A0\uFE0F" });
|
|
17689
|
-
break;
|
|
17690
|
-
default:
|
|
17691
|
-
toast2.toast(message, options);
|
|
17692
|
-
}
|
|
17693
|
-
};
|
|
17694
|
-
var downloadFile = async (src, name) => {
|
|
17695
|
-
try {
|
|
17696
|
-
const link = document.createElement("a");
|
|
17697
|
-
link.href = src;
|
|
17698
|
-
link.setAttribute("download", name);
|
|
17699
|
-
link.setAttribute("rel", "noopener noreferrer");
|
|
17700
|
-
link.click();
|
|
17701
|
-
showNotification("File Downloaded Successfully", "success");
|
|
17702
|
-
} catch (err) {
|
|
17703
|
-
console.error("File download failed:", err);
|
|
17704
|
-
showNotification("Failed to download file", "error");
|
|
17705
|
-
}
|
|
17706
|
-
};
|
|
17707
|
-
var getResponsiveWidth = (width) => {
|
|
17708
|
-
const screenWidth = window.innerWidth;
|
|
17709
|
-
if (width) {
|
|
17710
|
-
return width;
|
|
17711
|
-
} else if (screenWidth < 640) {
|
|
17712
|
-
return 350;
|
|
17713
|
-
} else if (screenWidth >= 640 && screenWidth < 1024) {
|
|
17714
|
-
return 600;
|
|
17715
|
-
} else if (screenWidth >= 1024 && screenWidth < 1280) {
|
|
17716
|
-
return 800;
|
|
17717
|
-
} else {
|
|
17718
|
-
return 1e3;
|
|
17719
|
-
}
|
|
17720
|
-
};
|
|
17721
|
-
var isEmpty = (value) => {
|
|
17722
|
-
if (value === null || value === void 0) return true;
|
|
17723
|
-
if (typeof value === "string") return value.trim().length === 0;
|
|
17724
|
-
if (Array.isArray(value)) {
|
|
17725
|
-
return value.length === 0 || value.every((item) => isEmpty(item));
|
|
17726
|
-
}
|
|
17727
|
-
if (typeof value === "object") {
|
|
17728
|
-
return Object.keys(value).length === 0;
|
|
17729
|
-
}
|
|
17730
|
-
return false;
|
|
17731
|
-
};
|
|
17732
|
-
function uniqueList(list, key) {
|
|
17733
|
-
const seen = /* @__PURE__ */ new Set();
|
|
17734
|
-
return list.filter((item) => {
|
|
17735
|
-
const value = item[key];
|
|
17736
|
-
if (seen.has(value)) return false;
|
|
17737
|
-
seen.add(value);
|
|
17738
|
-
return true;
|
|
17739
|
-
});
|
|
17740
|
-
}
|
|
17741
|
-
var capitalizeFirst = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
17742
|
-
var getFirstAndLastNameOneCharacter = (name) => {
|
|
17743
|
-
const names = name.split(" ");
|
|
17744
|
-
return names.map((name2) => name2.charAt(0).toUpperCase()).join("");
|
|
17745
|
-
};
|
|
17746
|
-
|
|
17747
|
-
// src/notifications/ForegroundPushBridge.tsx
|
|
17748
|
-
init_normalize_helpers();
|
|
17749
|
-
init_useStore();
|
|
17750
|
-
|
|
17751
|
-
// src/notifications/push.service.ts
|
|
17752
|
-
init_client();
|
|
17753
|
-
var PUSH_TOKEN_STORAGE_KEY = "realtimex-push-token";
|
|
17754
|
-
var SERVICE_WORKER_PATH = "/firebase-messaging-sw.js";
|
|
17755
|
-
var PUSH_CHANGED_EVENT = "realtimex:push-changed";
|
|
17756
|
-
var emitPushChanged = (enabled) => {
|
|
17757
|
-
try {
|
|
17758
|
-
window.dispatchEvent(
|
|
17759
|
-
new CustomEvent(PUSH_CHANGED_EVENT, { detail: { enabled } })
|
|
17760
|
-
);
|
|
17761
|
-
} catch {
|
|
17762
|
-
}
|
|
17763
|
-
};
|
|
17764
|
-
var v2Url = "https://realtimex.softwareco.com/api/v2";
|
|
17765
|
-
var apiGetPushConfig = async () => {
|
|
17766
|
-
const { data } = await apiClient.get(`${v2Url}/notifications/push/config`);
|
|
17767
|
-
return data?.data;
|
|
17768
|
-
};
|
|
17769
|
-
var apiRegisterPushToken = async (token, deviceLabel) => {
|
|
17770
|
-
const { data } = await apiClient.post(`${v2Url}/notifications/push/token`, {
|
|
17771
|
-
token,
|
|
17772
|
-
deviceLabel
|
|
17773
|
-
});
|
|
17774
|
-
return data?.data;
|
|
17775
|
-
};
|
|
17776
|
-
var apiRemovePushToken = async (token) => {
|
|
17777
|
-
const { data } = await apiClient.delete(`${v2Url}/notifications/push/token`, {
|
|
17778
|
-
data: { token }
|
|
17779
|
-
});
|
|
17780
|
-
return data;
|
|
17781
|
-
};
|
|
17782
|
-
var apiGetPushPreference = async () => {
|
|
17783
|
-
const { data } = await apiClient.get(
|
|
17784
|
-
`${v2Url}/notifications/push/preference`
|
|
17785
|
-
);
|
|
17786
|
-
return data?.data;
|
|
17787
|
-
};
|
|
17788
|
-
var apiUpdatePushPreference = async (enabled) => {
|
|
17789
|
-
const { data } = await apiClient.patch(
|
|
17790
|
-
`${v2Url}/notifications/push/preference`,
|
|
17791
|
-
{ enabled }
|
|
17792
|
-
);
|
|
17793
|
-
return data?.data;
|
|
17794
|
-
};
|
|
17795
|
-
var isPushSupported = () => typeof window !== "undefined" && "Notification" in window && "serviceWorker" in navigator && "PushManager" in window;
|
|
17796
|
-
var getStoredPushToken = () => {
|
|
17797
|
-
try {
|
|
17798
|
-
return localStorage.getItem(PUSH_TOKEN_STORAGE_KEY);
|
|
17799
|
-
} catch {
|
|
17800
|
-
return null;
|
|
17801
|
-
}
|
|
17802
|
-
};
|
|
17803
|
-
var storePushToken = (token) => {
|
|
17804
|
-
try {
|
|
17805
|
-
if (token) localStorage.setItem(PUSH_TOKEN_STORAGE_KEY, token);
|
|
17806
|
-
else localStorage.removeItem(PUSH_TOKEN_STORAGE_KEY);
|
|
17807
|
-
} catch {
|
|
17808
|
-
}
|
|
17809
|
-
};
|
|
17810
|
-
var defaultDeviceLabel = () => {
|
|
17811
|
-
const ua = navigator.userAgent;
|
|
17812
|
-
const browser = /edg\//i.test(ua) ? "Edge" : /chrome/i.test(ua) ? "Chrome" : /safari/i.test(ua) ? "Safari" : /firefox/i.test(ua) ? "Firefox" : "Browser";
|
|
17813
|
-
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";
|
|
17814
|
-
return `${browser} on ${os}`;
|
|
17815
|
-
};
|
|
17816
|
-
var loadFirebaseMessaging = async () => {
|
|
17817
|
-
try {
|
|
17818
|
-
const [{ initializeApp, getApps }, messagingModule] = await Promise.all([
|
|
17819
|
-
import('firebase/app'),
|
|
17820
|
-
import('firebase/messaging')
|
|
17821
|
-
]);
|
|
17822
|
-
return { initializeApp, getApps, ...messagingModule };
|
|
17823
|
-
} catch {
|
|
17824
|
-
throw new Error(
|
|
17825
|
-
'Push notifications need the "firebase" package \u2014 run: npm install firebase'
|
|
17826
|
-
);
|
|
17827
|
-
}
|
|
17828
|
-
};
|
|
17829
|
-
var getFirebaseMessaging = async (firebaseConfig) => {
|
|
17830
|
-
const fb = await loadFirebaseMessaging();
|
|
17831
|
-
const app = fb.getApps().length ? fb.getApps()[0] : fb.initializeApp(firebaseConfig);
|
|
17832
|
-
return { fb, messaging: fb.getMessaging(app) };
|
|
17833
|
-
};
|
|
17834
|
-
var enablePushOnThisDevice = async () => {
|
|
17835
|
-
if (!isPushSupported()) {
|
|
17836
|
-
throw new Error("Push notifications are not supported in this browser");
|
|
17837
|
-
}
|
|
17838
|
-
const config = await apiGetPushConfig();
|
|
17839
|
-
if (!config?.enabled) {
|
|
17840
|
-
throw new Error("Push notifications are disabled for this workspace");
|
|
17841
|
-
}
|
|
17842
|
-
if (!config.configured || !config.firebaseConfig || !config.vapidKey) {
|
|
17843
|
-
throw new Error(
|
|
17844
|
-
"Push notifications are not configured on the server yet"
|
|
17845
|
-
);
|
|
17846
|
-
}
|
|
17847
|
-
const permission = await Notification.requestPermission();
|
|
17848
|
-
if (permission !== "granted") {
|
|
17849
|
-
throw new Error("Notification permission was not granted");
|
|
17850
|
-
}
|
|
17851
|
-
let registration;
|
|
17852
|
-
try {
|
|
17853
|
-
registration = await navigator.serviceWorker.register(
|
|
17854
|
-
`${SERVICE_WORKER_PATH}?config=${encodeURIComponent(
|
|
17855
|
-
JSON.stringify(config.firebaseConfig)
|
|
17856
|
-
)}`
|
|
17857
|
-
);
|
|
17858
|
-
} catch {
|
|
17859
|
-
throw new Error(
|
|
17860
|
-
`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`
|
|
17861
|
-
);
|
|
17862
|
-
}
|
|
17863
|
-
const { fb, messaging } = await getFirebaseMessaging(config.firebaseConfig);
|
|
17864
|
-
const token = await fb.getToken(messaging, {
|
|
17865
|
-
vapidKey: config.vapidKey,
|
|
17866
|
-
serviceWorkerRegistration: registration
|
|
17867
|
-
});
|
|
17868
|
-
if (!token) {
|
|
17869
|
-
throw new Error("Could not obtain a push token from Firebase");
|
|
17870
|
-
}
|
|
17871
|
-
await apiRegisterPushToken(token, defaultDeviceLabel());
|
|
17872
|
-
storePushToken(token);
|
|
17873
|
-
emitPushChanged(true);
|
|
17874
|
-
return token;
|
|
17875
|
-
};
|
|
17876
|
-
var disablePushOnThisDevice = async () => {
|
|
17877
|
-
const token = getStoredPushToken();
|
|
17878
|
-
if (!token) return;
|
|
17879
|
-
try {
|
|
17880
|
-
const config = await apiGetPushConfig();
|
|
17881
|
-
if (config?.firebaseConfig) {
|
|
17882
|
-
const { fb, messaging } = await getFirebaseMessaging(
|
|
17883
|
-
config.firebaseConfig
|
|
17884
|
-
);
|
|
17885
|
-
await fb.deleteToken(messaging).catch(() => void 0);
|
|
17886
|
-
}
|
|
17887
|
-
} catch {
|
|
17888
|
-
}
|
|
17889
|
-
await apiRemovePushToken(token).catch(() => void 0);
|
|
17890
|
-
storePushToken(null);
|
|
17891
|
-
emitPushChanged(false);
|
|
17892
|
-
};
|
|
17893
|
-
var onForegroundPush = async (callback) => {
|
|
17894
|
-
const config = await apiGetPushConfig();
|
|
17895
|
-
if (!config?.configured || !config.firebaseConfig) {
|
|
17896
|
-
throw new Error("Push config unavailable (not configured or API not ready)");
|
|
17897
|
-
}
|
|
17898
|
-
const { fb, messaging } = await getFirebaseMessaging(config.firebaseConfig);
|
|
17899
|
-
return fb.onMessage(messaging, (payload) => {
|
|
17900
|
-
console.log("[realtimex-push] FCM foreground payload (raw):", payload);
|
|
17901
|
-
console.log("[realtimex-push] FCM foreground data:", payload?.data);
|
|
17902
|
-
console.log("[realtimex-push] FCM foreground notification:", payload?.notification);
|
|
17903
|
-
callback({
|
|
17904
|
-
title: payload?.notification?.title,
|
|
17905
|
-
body: payload?.notification?.body,
|
|
17906
|
-
data: payload?.data
|
|
17907
|
-
});
|
|
17908
|
-
});
|
|
17909
|
-
};
|
|
18258
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18259
|
+
"div",
|
|
18260
|
+
{
|
|
18261
|
+
className: cn(
|
|
18262
|
+
"chat-package-viewport flex min-h-0 w-full flex-col overflow-hidden",
|
|
18263
|
+
resolved.className,
|
|
18264
|
+
className
|
|
18265
|
+
),
|
|
18266
|
+
style: { ...resolved.style, ...style },
|
|
18267
|
+
children
|
|
18268
|
+
}
|
|
18269
|
+
);
|
|
18270
|
+
}
|
|
18271
|
+
var ChatViewport_default = ChatViewport;
|
|
18272
|
+
init_normalize_helpers();
|
|
18273
|
+
init_useStore();
|
|
17910
18274
|
var RETRY_DELAYS_MS = [1e3, 3e3, 8e3, 2e4];
|
|
17911
18275
|
var recentToastIds = /* @__PURE__ */ new Set();
|
|
17912
18276
|
var rememberToastId = (id) => {
|
|
@@ -17920,48 +18284,95 @@ var rememberToastId = (id) => {
|
|
|
17920
18284
|
}
|
|
17921
18285
|
return true;
|
|
17922
18286
|
};
|
|
17923
|
-
var
|
|
17924
|
-
|
|
17925
|
-
|
|
18287
|
+
var truncate = (value, max) => value.length > max ? `${value.slice(0, max - 1)}\u2026` : value;
|
|
18288
|
+
var PushMessageToast = ({
|
|
18289
|
+
t,
|
|
18290
|
+
title,
|
|
18291
|
+
body,
|
|
18292
|
+
onOpen
|
|
18293
|
+
}) => {
|
|
18294
|
+
const dismiss = () => toast__default.default.dismiss(t.id);
|
|
18295
|
+
const handleDismiss = (event) => {
|
|
18296
|
+
event.stopPropagation();
|
|
18297
|
+
dismiss();
|
|
18298
|
+
};
|
|
18299
|
+
const handleOpen = () => {
|
|
18300
|
+
dismiss();
|
|
18301
|
+
onOpen?.();
|
|
18302
|
+
};
|
|
18303
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
18304
|
+
"div",
|
|
18305
|
+
{
|
|
18306
|
+
role: "alert",
|
|
18307
|
+
"aria-live": "polite",
|
|
18308
|
+
onClick: onOpen ? handleOpen : void 0,
|
|
18309
|
+
onKeyDown: onOpen ? (event) => {
|
|
18310
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
18311
|
+
event.preventDefault();
|
|
18312
|
+
handleOpen();
|
|
18313
|
+
}
|
|
18314
|
+
} : void 0,
|
|
18315
|
+
tabIndex: onOpen ? 0 : void 0,
|
|
18316
|
+
className: cn(
|
|
18317
|
+
"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",
|
|
18318
|
+
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)",
|
|
18319
|
+
t.visible ? "translate-y-0 opacity-100" : "-translate-y-1 opacity-0"
|
|
18320
|
+
),
|
|
18321
|
+
children: [
|
|
18322
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18323
|
+
"div",
|
|
18324
|
+
{
|
|
18325
|
+
"aria-hidden": true,
|
|
18326
|
+
className: "flex size-9 shrink-0 items-center justify-center rounded-lg bg-(--chat-theme-10) text-(--chat-theme)",
|
|
18327
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquare, { className: "size-4", strokeWidth: 2.25 })
|
|
18328
|
+
}
|
|
18329
|
+
),
|
|
18330
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1 pt-0.5", children: [
|
|
18331
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] font-semibold uppercase tracking-wide text-(--chat-muted)", children: "New message" }),
|
|
18332
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 truncate text-sm font-semibold leading-snug text-(--chat-text)", children: truncate(title, 40) }),
|
|
18333
|
+
body ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 line-clamp-2 text-xs leading-relaxed text-(--chat-muted)", children: truncate(body, 72) }) : null
|
|
18334
|
+
] }),
|
|
18335
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18336
|
+
"button",
|
|
18337
|
+
{
|
|
18338
|
+
type: "button",
|
|
18339
|
+
"aria-label": "Dismiss notification",
|
|
18340
|
+
onClick: handleDismiss,
|
|
18341
|
+
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)",
|
|
18342
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-4", strokeWidth: 2 })
|
|
18343
|
+
}
|
|
18344
|
+
)
|
|
18345
|
+
]
|
|
18346
|
+
}
|
|
18347
|
+
);
|
|
17926
18348
|
};
|
|
17927
18349
|
var emitToast = (payload, onPush) => {
|
|
17928
18350
|
if (onPush && onPush(payload) !== false) return;
|
|
17929
|
-
const title = payload.title || payload.data?.title;
|
|
17930
|
-
const body = payload.body || payload.data?.body || payload.data?.message;
|
|
17931
|
-
const text = resolveToastText(title, body);
|
|
18351
|
+
const title = payload.title || payload.data?.title || "New message";
|
|
18352
|
+
const body = payload.body || payload.data?.body || payload.data?.message || "";
|
|
17932
18353
|
const conversationId = resolveConversationIdFromPushData(payload.data);
|
|
17933
|
-
|
|
17934
|
-
|
|
17935
|
-
|
|
17936
|
-
|
|
17937
|
-
|
|
17938
|
-
|
|
17939
|
-
|
|
17940
|
-
|
|
17941
|
-
|
|
17942
|
-
|
|
17943
|
-
|
|
17944
|
-
|
|
17945
|
-
|
|
17946
|
-
|
|
17947
|
-
|
|
17948
|
-
|
|
17949
|
-
|
|
17950
|
-
|
|
17951
|
-
|
|
17952
|
-
|
|
17953
|
-
|
|
17954
|
-
|
|
17955
|
-
font: "inherit"
|
|
17956
|
-
},
|
|
17957
|
-
children: text
|
|
17958
|
-
}
|
|
17959
|
-
),
|
|
17960
|
-
{ duration: 5e3 }
|
|
17961
|
-
);
|
|
17962
|
-
return;
|
|
17963
|
-
}
|
|
17964
|
-
showNotification(text, "info");
|
|
18354
|
+
const messageId2 = String(
|
|
18355
|
+
payload.data?.messageId || payload.data?.message_id || payload.data?.messageID || ""
|
|
18356
|
+
);
|
|
18357
|
+
if (!title && !body) return;
|
|
18358
|
+
toast__default.default.custom(
|
|
18359
|
+
(t) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
18360
|
+
PushMessageToast,
|
|
18361
|
+
{
|
|
18362
|
+
t,
|
|
18363
|
+
title,
|
|
18364
|
+
body: body || void 0,
|
|
18365
|
+
onOpen: conversationId ? () => requestOpenConversation(
|
|
18366
|
+
conversationId,
|
|
18367
|
+
payload.data
|
|
18368
|
+
) : void 0
|
|
18369
|
+
}
|
|
18370
|
+
),
|
|
18371
|
+
{
|
|
18372
|
+
duration: 5e3,
|
|
18373
|
+
id: messageId2 || void 0
|
|
18374
|
+
}
|
|
18375
|
+
);
|
|
17965
18376
|
};
|
|
17966
18377
|
var ForegroundPushBridge = ({ onPush }) => {
|
|
17967
18378
|
const lastDM = exports.useChatStore((s) => s.lastDM);
|
|
@@ -18096,11 +18507,31 @@ var ForegroundPushBridge = ({ onPush }) => {
|
|
|
18096
18507
|
return () => window.removeEventListener(OPEN_CONVERSATION_EVENT, onOpen);
|
|
18097
18508
|
}, []);
|
|
18098
18509
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18099
|
-
|
|
18510
|
+
toast.Toaster,
|
|
18100
18511
|
{
|
|
18101
18512
|
position: "top-right",
|
|
18102
|
-
|
|
18103
|
-
|
|
18513
|
+
gutter: 12,
|
|
18514
|
+
containerClassName: "realtimex-push-toaster",
|
|
18515
|
+
containerStyle: {
|
|
18516
|
+
zIndex: 99999,
|
|
18517
|
+
top: 16,
|
|
18518
|
+
right: 16,
|
|
18519
|
+
width: "auto",
|
|
18520
|
+
maxWidth: "none"
|
|
18521
|
+
},
|
|
18522
|
+
toastOptions: {
|
|
18523
|
+
duration: 5e3,
|
|
18524
|
+
className: "!w-auto !max-w-none",
|
|
18525
|
+
style: {
|
|
18526
|
+
padding: 0,
|
|
18527
|
+
margin: 0,
|
|
18528
|
+
background: "transparent",
|
|
18529
|
+
boxShadow: "none",
|
|
18530
|
+
border: "none",
|
|
18531
|
+
width: "auto",
|
|
18532
|
+
maxWidth: "none"
|
|
18533
|
+
}
|
|
18534
|
+
}
|
|
18104
18535
|
}
|
|
18105
18536
|
);
|
|
18106
18537
|
};
|
|
@@ -18113,6 +18544,7 @@ var ChatMain = ({
|
|
|
18113
18544
|
queryParams,
|
|
18114
18545
|
queryParamApis,
|
|
18115
18546
|
queryParamsByApi,
|
|
18547
|
+
apiVersions: apiVersions2,
|
|
18116
18548
|
themeColor = "#7494ec",
|
|
18117
18549
|
theme,
|
|
18118
18550
|
uiConfig,
|
|
@@ -18182,6 +18614,7 @@ var ChatMain = ({
|
|
|
18182
18614
|
queryParams,
|
|
18183
18615
|
queryParamApis,
|
|
18184
18616
|
queryParamsByApi,
|
|
18617
|
+
apiVersions: apiVersions2,
|
|
18185
18618
|
children: [
|
|
18186
18619
|
/* @__PURE__ */ jsxRuntime.jsx(ForegroundPushBridge, {}),
|
|
18187
18620
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -18257,6 +18690,80 @@ var getSocketConfig = (accessToken, tenantId, options) => {
|
|
|
18257
18690
|
}
|
|
18258
18691
|
};
|
|
18259
18692
|
};
|
|
18693
|
+
var showNotification = (message, type = "info", icon, duration) => {
|
|
18694
|
+
const options = {
|
|
18695
|
+
icon,
|
|
18696
|
+
duration
|
|
18697
|
+
};
|
|
18698
|
+
switch (type) {
|
|
18699
|
+
case "success":
|
|
18700
|
+
toast.toast.success(message, options);
|
|
18701
|
+
break;
|
|
18702
|
+
case "error":
|
|
18703
|
+
toast.toast.error(message, options);
|
|
18704
|
+
break;
|
|
18705
|
+
case "info":
|
|
18706
|
+
toast.toast(message, options);
|
|
18707
|
+
break;
|
|
18708
|
+
case "warning":
|
|
18709
|
+
toast.toast(message, { ...options, icon: "\u26A0\uFE0F" });
|
|
18710
|
+
break;
|
|
18711
|
+
default:
|
|
18712
|
+
toast.toast(message, options);
|
|
18713
|
+
}
|
|
18714
|
+
};
|
|
18715
|
+
var downloadFile = async (src, name) => {
|
|
18716
|
+
try {
|
|
18717
|
+
const link = document.createElement("a");
|
|
18718
|
+
link.href = src;
|
|
18719
|
+
link.setAttribute("download", name);
|
|
18720
|
+
link.setAttribute("rel", "noopener noreferrer");
|
|
18721
|
+
link.click();
|
|
18722
|
+
showNotification("File Downloaded Successfully", "success");
|
|
18723
|
+
} catch (err) {
|
|
18724
|
+
console.error("File download failed:", err);
|
|
18725
|
+
showNotification("Failed to download file", "error");
|
|
18726
|
+
}
|
|
18727
|
+
};
|
|
18728
|
+
var getResponsiveWidth = (width) => {
|
|
18729
|
+
const screenWidth = window.innerWidth;
|
|
18730
|
+
if (width) {
|
|
18731
|
+
return width;
|
|
18732
|
+
} else if (screenWidth < 640) {
|
|
18733
|
+
return 350;
|
|
18734
|
+
} else if (screenWidth >= 640 && screenWidth < 1024) {
|
|
18735
|
+
return 600;
|
|
18736
|
+
} else if (screenWidth >= 1024 && screenWidth < 1280) {
|
|
18737
|
+
return 800;
|
|
18738
|
+
} else {
|
|
18739
|
+
return 1e3;
|
|
18740
|
+
}
|
|
18741
|
+
};
|
|
18742
|
+
var isEmpty = (value) => {
|
|
18743
|
+
if (value === null || value === void 0) return true;
|
|
18744
|
+
if (typeof value === "string") return value.trim().length === 0;
|
|
18745
|
+
if (Array.isArray(value)) {
|
|
18746
|
+
return value.length === 0 || value.every((item) => isEmpty(item));
|
|
18747
|
+
}
|
|
18748
|
+
if (typeof value === "object") {
|
|
18749
|
+
return Object.keys(value).length === 0;
|
|
18750
|
+
}
|
|
18751
|
+
return false;
|
|
18752
|
+
};
|
|
18753
|
+
function uniqueList(list, key) {
|
|
18754
|
+
const seen = /* @__PURE__ */ new Set();
|
|
18755
|
+
return list.filter((item) => {
|
|
18756
|
+
const value = item[key];
|
|
18757
|
+
if (seen.has(value)) return false;
|
|
18758
|
+
seen.add(value);
|
|
18759
|
+
return true;
|
|
18760
|
+
});
|
|
18761
|
+
}
|
|
18762
|
+
var capitalizeFirst = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
18763
|
+
var getFirstAndLastNameOneCharacter = (name) => {
|
|
18764
|
+
const names = name.split(" ");
|
|
18765
|
+
return names.map((name2) => name2.charAt(0).toUpperCase()).join("");
|
|
18766
|
+
};
|
|
18260
18767
|
var SIZE_MAP = {
|
|
18261
18768
|
xs: "size-6",
|
|
18262
18769
|
sm: "size-8",
|
|
@@ -18400,6 +18907,10 @@ var ChannelListItem_default = ChannelListItem2;
|
|
|
18400
18907
|
var packageDefaultComponents = {
|
|
18401
18908
|
ChatLayout: DefaultChatLayout_default,
|
|
18402
18909
|
LoggedUserDetails: LoggedUserDetails_default,
|
|
18910
|
+
LoggedUserSettingsDialog: LoggedUserSettingsDialog_default,
|
|
18911
|
+
LoggedUserSettingsTrigger: LoggedUserSettingsTrigger_default,
|
|
18912
|
+
LoggedUserSettingsContent: LoggedUserSettingsContent_default,
|
|
18913
|
+
PushNotificationToggle,
|
|
18403
18914
|
ChannelList: ChannelListView_default,
|
|
18404
18915
|
ChannelListItem: DefaultChannelListItem,
|
|
18405
18916
|
ChannelHeader: ChannelHeaderView_default,
|
|
@@ -18430,135 +18941,6 @@ var packageDefaultComponents = {
|
|
|
18430
18941
|
ChatDateTimeSettings: ChatDateTimeSettings_default,
|
|
18431
18942
|
ChatSocketStatus: ChatSocketStatus_default
|
|
18432
18943
|
};
|
|
18433
|
-
var usePushNotifications = () => {
|
|
18434
|
-
const [state, setState] = React2.useState({
|
|
18435
|
-
supported: false,
|
|
18436
|
-
allowedByWorkspace: false,
|
|
18437
|
-
configured: false,
|
|
18438
|
-
permission: "unsupported",
|
|
18439
|
-
userEnabled: true,
|
|
18440
|
-
deviceEnabled: false,
|
|
18441
|
-
loading: true,
|
|
18442
|
-
error: null
|
|
18443
|
-
});
|
|
18444
|
-
const refresh = React2.useCallback(async () => {
|
|
18445
|
-
if (!isPushSupported()) {
|
|
18446
|
-
setState((prev) => ({
|
|
18447
|
-
...prev,
|
|
18448
|
-
supported: false,
|
|
18449
|
-
loading: false
|
|
18450
|
-
}));
|
|
18451
|
-
return;
|
|
18452
|
-
}
|
|
18453
|
-
try {
|
|
18454
|
-
const [config, preference] = await Promise.all([
|
|
18455
|
-
apiGetPushConfig(),
|
|
18456
|
-
apiGetPushPreference().catch(() => null)
|
|
18457
|
-
]);
|
|
18458
|
-
setState({
|
|
18459
|
-
supported: true,
|
|
18460
|
-
allowedByWorkspace: Boolean(config?.enabled),
|
|
18461
|
-
configured: Boolean(config?.configured),
|
|
18462
|
-
permission: Notification.permission,
|
|
18463
|
-
userEnabled: preference?.enabled ?? true,
|
|
18464
|
-
deviceEnabled: Notification.permission === "granted" && Boolean(getStoredPushToken()),
|
|
18465
|
-
loading: false,
|
|
18466
|
-
error: null
|
|
18467
|
-
});
|
|
18468
|
-
} catch (error) {
|
|
18469
|
-
setState((prev) => ({
|
|
18470
|
-
...prev,
|
|
18471
|
-
supported: true,
|
|
18472
|
-
loading: false,
|
|
18473
|
-
error: error instanceof Error ? error.message : "Could not load push settings"
|
|
18474
|
-
}));
|
|
18475
|
-
}
|
|
18476
|
-
}, []);
|
|
18477
|
-
React2.useEffect(() => {
|
|
18478
|
-
void refresh();
|
|
18479
|
-
}, [refresh]);
|
|
18480
|
-
const enable = React2.useCallback(async () => {
|
|
18481
|
-
setState((prev) => ({ ...prev, loading: true, error: null }));
|
|
18482
|
-
try {
|
|
18483
|
-
await enablePushOnThisDevice();
|
|
18484
|
-
await refresh();
|
|
18485
|
-
return true;
|
|
18486
|
-
} catch (error) {
|
|
18487
|
-
setState((prev) => ({
|
|
18488
|
-
...prev,
|
|
18489
|
-
loading: false,
|
|
18490
|
-
permission: isPushSupported() ? Notification.permission : "unsupported",
|
|
18491
|
-
error: error instanceof Error ? error.message : "Could not enable push notifications"
|
|
18492
|
-
}));
|
|
18493
|
-
return false;
|
|
18494
|
-
}
|
|
18495
|
-
}, [refresh]);
|
|
18496
|
-
const disable = React2.useCallback(async () => {
|
|
18497
|
-
setState((prev) => ({ ...prev, loading: true, error: null }));
|
|
18498
|
-
try {
|
|
18499
|
-
await disablePushOnThisDevice();
|
|
18500
|
-
} finally {
|
|
18501
|
-
await refresh();
|
|
18502
|
-
}
|
|
18503
|
-
}, [refresh]);
|
|
18504
|
-
const setUserEnabled = React2.useCallback(
|
|
18505
|
-
async (enabled) => {
|
|
18506
|
-
setState((prev) => ({ ...prev, userEnabled: enabled }));
|
|
18507
|
-
try {
|
|
18508
|
-
await apiUpdatePushPreference(enabled);
|
|
18509
|
-
} catch (error) {
|
|
18510
|
-
setState((prev) => ({
|
|
18511
|
-
...prev,
|
|
18512
|
-
userEnabled: !enabled,
|
|
18513
|
-
error: error instanceof Error ? error.message : "Could not update push preference"
|
|
18514
|
-
}));
|
|
18515
|
-
}
|
|
18516
|
-
},
|
|
18517
|
-
[]
|
|
18518
|
-
);
|
|
18519
|
-
return { ...state, enable, disable, setUserEnabled, refresh };
|
|
18520
|
-
};
|
|
18521
|
-
var PushNotificationToggle = ({
|
|
18522
|
-
className,
|
|
18523
|
-
label = "Push notifications",
|
|
18524
|
-
description = "Get notified about new messages on this device"
|
|
18525
|
-
}) => {
|
|
18526
|
-
const push = usePushNotifications();
|
|
18527
|
-
if (!push.supported || !push.allowedByWorkspace || !push.configured) {
|
|
18528
|
-
return null;
|
|
18529
|
-
}
|
|
18530
|
-
const isOn = push.deviceEnabled && push.userEnabled;
|
|
18531
|
-
const permissionBlocked = push.permission === "denied";
|
|
18532
|
-
const handleChange = async (checked) => {
|
|
18533
|
-
if (checked) {
|
|
18534
|
-
if (!push.userEnabled) await push.setUserEnabled(true);
|
|
18535
|
-
if (!push.deviceEnabled) await push.enable();
|
|
18536
|
-
} else {
|
|
18537
|
-
await push.disable();
|
|
18538
|
-
}
|
|
18539
|
-
};
|
|
18540
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
18541
|
-
"div",
|
|
18542
|
-
{
|
|
18543
|
-
className: className ?? "flex items-center justify-between gap-4 rounded-xl border border-border bg-background px-4 py-3",
|
|
18544
|
-
children: [
|
|
18545
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
|
|
18546
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-foreground", children: label }),
|
|
18547
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: permissionBlocked ? "Notifications are blocked in your browser settings" : push.error ?? description })
|
|
18548
|
-
] }),
|
|
18549
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18550
|
-
Switch,
|
|
18551
|
-
{
|
|
18552
|
-
checked: isOn,
|
|
18553
|
-
disabled: push.loading || permissionBlocked,
|
|
18554
|
-
onCheckedChange: (checked) => void handleChange(checked),
|
|
18555
|
-
"aria-label": `Toggle ${label}`
|
|
18556
|
-
}
|
|
18557
|
-
)
|
|
18558
|
-
]
|
|
18559
|
-
}
|
|
18560
|
-
);
|
|
18561
|
-
};
|
|
18562
18944
|
|
|
18563
18945
|
// src/index.ts
|
|
18564
18946
|
var index_default = ChatMain_default;
|
|
@@ -18586,6 +18968,9 @@ exports.ForegroundPushBridge = ForegroundPushBridge;
|
|
|
18586
18968
|
exports.ForwardModal = ForwardModalView;
|
|
18587
18969
|
exports.HeaderCallActions = HeaderCallActions_default;
|
|
18588
18970
|
exports.LoggedUserDetails = LoggedUserDetails_default;
|
|
18971
|
+
exports.LoggedUserSettingsContent = LoggedUserSettingsContent_default;
|
|
18972
|
+
exports.LoggedUserSettingsDialog = LoggedUserSettingsDialog_default;
|
|
18973
|
+
exports.LoggedUserSettingsTrigger = LoggedUserSettingsTrigger_default;
|
|
18589
18974
|
exports.MessageInput = ChannelMessageBoxView_default;
|
|
18590
18975
|
exports.MessageItem = MessageItemView;
|
|
18591
18976
|
exports.MessageList = ActiveChannelMessagesView_default;
|
|
@@ -18593,6 +18978,7 @@ exports.NOTIFICATION_CLICK_SW_TYPE = NOTIFICATION_CLICK_SW_TYPE;
|
|
|
18593
18978
|
exports.OPEN_CONVERSATION_EVENT = OPEN_CONVERSATION_EVENT;
|
|
18594
18979
|
exports.PUSH_BROADCAST_CHANNEL = PUSH_BROADCAST_CHANNEL;
|
|
18595
18980
|
exports.PUSH_CHANGED_EVENT = PUSH_CHANGED_EVENT;
|
|
18981
|
+
exports.PUSH_DATA_CACHE_NAME = PUSH_DATA_CACHE_NAME;
|
|
18596
18982
|
exports.PushNotificationToggle = PushNotificationToggle;
|
|
18597
18983
|
exports.apiGetPushConfig = apiGetPushConfig;
|
|
18598
18984
|
exports.apiGetPushPreference = apiGetPushPreference;
|
|
@@ -18600,9 +18986,11 @@ exports.apiRegisterPushToken = apiRegisterPushToken;
|
|
|
18600
18986
|
exports.apiRemovePushToken = apiRemovePushToken;
|
|
18601
18987
|
exports.apiUpdatePushPreference = apiUpdatePushPreference;
|
|
18602
18988
|
exports.buildChannelFromPushRequest = buildChannelFromPushRequest;
|
|
18989
|
+
exports.buildLoggedUserProfile = buildLoggedUserProfile;
|
|
18603
18990
|
exports.capitalizeFirst = capitalizeFirst;
|
|
18604
18991
|
exports.clampJumpDate = clampJumpDate;
|
|
18605
18992
|
exports.consumePendingOpenConversation = consumePendingOpenConversation;
|
|
18993
|
+
exports.consumePendingOpenFromPushCache = consumePendingOpenFromPushCache;
|
|
18606
18994
|
exports.consumePendingOpenRequest = consumePendingOpenRequest;
|
|
18607
18995
|
exports.default = index_default;
|
|
18608
18996
|
exports.defaultChatClassNames = defaultChatClassNames;
|