@realtimexsco/live-chat 1.4.11 → 1.4.13
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/LICENSE +2 -2
- package/README.md +14 -6
- package/dist/index.cjs +1170 -453
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +142 -66
- package/dist/index.d.ts +142 -66
- package/dist/index.mjs +901 -187
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +7 -7
- package/package.json +19 -4
package/dist/index.mjs
CHANGED
|
@@ -2,8 +2,8 @@ import { io } from 'socket.io-client';
|
|
|
2
2
|
import axios from 'axios';
|
|
3
3
|
import { create } from 'zustand';
|
|
4
4
|
import { persist } from 'zustand/middleware';
|
|
5
|
-
import * as
|
|
6
|
-
import
|
|
5
|
+
import * as React3 from 'react';
|
|
6
|
+
import React3__default, { createContext, useMemo, useContext, useState, useCallback, useEffect, useRef, useLayoutEffect, Fragment as Fragment$1, useSyncExternalStore } from 'react';
|
|
7
7
|
import { Tooltip as Tooltip$1, Slot, Switch as Switch$1, Dialog as Dialog$1, Avatar as Avatar$1, ScrollArea as ScrollArea$1, Popover as Popover$1, DropdownMenu as DropdownMenu$1, AlertDialog as AlertDialog$1 } from 'radix-ui';
|
|
8
8
|
import { clsx } from 'clsx';
|
|
9
9
|
import { twMerge } from 'tailwind-merge';
|
|
@@ -1054,16 +1054,27 @@ var init_connection_actions = __esm({
|
|
|
1054
1054
|
setActiveConversationId: (conversationId) => {
|
|
1055
1055
|
set((state) => {
|
|
1056
1056
|
const nextId = conversationId ?? null;
|
|
1057
|
-
|
|
1057
|
+
const prevId = state.activeConversationId ?? null;
|
|
1058
|
+
if (String(prevId ?? "") === String(nextId ?? "")) {
|
|
1058
1059
|
return state;
|
|
1059
1060
|
}
|
|
1061
|
+
const nextErrors = { ...state.conversationErrors };
|
|
1062
|
+
if (prevId) {
|
|
1063
|
+
delete nextErrors[String(prevId)];
|
|
1064
|
+
}
|
|
1060
1065
|
if (!nextId) {
|
|
1061
|
-
return {
|
|
1066
|
+
return {
|
|
1067
|
+
activeConversationId: null,
|
|
1068
|
+
globalAppError: null,
|
|
1069
|
+
conversationErrors: nextErrors
|
|
1070
|
+
};
|
|
1062
1071
|
}
|
|
1063
1072
|
const target = state.conversations.find((c) => String(c._id) === String(nextId));
|
|
1064
1073
|
const unreadAlreadyZero = !normalizeUnreadCount(target?.unreadCount, state.loggedUserDetails?._id);
|
|
1065
1074
|
return {
|
|
1066
1075
|
activeConversationId: nextId,
|
|
1076
|
+
globalAppError: null,
|
|
1077
|
+
conversationErrors: nextErrors,
|
|
1067
1078
|
conversations: unreadAlreadyZero ? state.conversations : state.conversations.map(
|
|
1068
1079
|
(c) => String(c._id) === String(nextId) ? { ...c, unreadCount: 0 } : c
|
|
1069
1080
|
)
|
|
@@ -1104,25 +1115,32 @@ var init_connection_actions = __esm({
|
|
|
1104
1115
|
type = "rate_limit";
|
|
1105
1116
|
return;
|
|
1106
1117
|
}
|
|
1118
|
+
if (conversationId) {
|
|
1119
|
+
set((state) => ({
|
|
1120
|
+
conversationErrors: {
|
|
1121
|
+
...state.conversationErrors,
|
|
1122
|
+
[conversationId]: { message, type }
|
|
1123
|
+
},
|
|
1124
|
+
globalAppError: null
|
|
1125
|
+
}));
|
|
1126
|
+
return;
|
|
1127
|
+
}
|
|
1107
1128
|
set({ globalAppError: { message, type } });
|
|
1108
1129
|
},
|
|
1109
1130
|
clearAppError: (conversationId) => {
|
|
1110
1131
|
set((state) => {
|
|
1111
|
-
|
|
1112
|
-
if (targetId) {
|
|
1132
|
+
if (conversationId) {
|
|
1113
1133
|
const nextErrors = { ...state.conversationErrors };
|
|
1114
1134
|
const nextComposer = { ...state.composerDisabledByConversation };
|
|
1115
|
-
delete nextErrors[
|
|
1116
|
-
delete nextComposer[
|
|
1135
|
+
delete nextErrors[conversationId];
|
|
1136
|
+
delete nextComposer[conversationId];
|
|
1117
1137
|
return {
|
|
1118
1138
|
conversationErrors: nextErrors,
|
|
1119
1139
|
composerDisabledByConversation: nextComposer
|
|
1120
1140
|
};
|
|
1121
1141
|
}
|
|
1122
1142
|
return {
|
|
1123
|
-
globalAppError: null
|
|
1124
|
-
conversationErrors: {},
|
|
1125
|
-
composerDisabledByConversation: {}
|
|
1143
|
+
globalAppError: null
|
|
1126
1144
|
};
|
|
1127
1145
|
});
|
|
1128
1146
|
},
|
|
@@ -1162,6 +1180,7 @@ function resolveChatApiKey(url) {
|
|
|
1162
1180
|
}
|
|
1163
1181
|
if (path.includes("/message/search-messages")) return "searchMessages";
|
|
1164
1182
|
if (path.includes("/message/searched-message/context")) return "searchMessagesContext";
|
|
1183
|
+
if (path.includes("/settings/effective")) return "effectiveSettings";
|
|
1165
1184
|
if (path.includes("/conversation/group/create")) return "createGroup";
|
|
1166
1185
|
if (path.includes("/conversation/group/permission/update")) return "updateGroupPermissions";
|
|
1167
1186
|
if (path.includes("/conversation/group/information/update")) return "updateGroupInfo";
|
|
@@ -1205,7 +1224,8 @@ var init_query_params = __esm({
|
|
|
1205
1224
|
"pinnedMessages",
|
|
1206
1225
|
"starredMessages",
|
|
1207
1226
|
"searchMessages",
|
|
1208
|
-
"searchMessagesContext"
|
|
1227
|
+
"searchMessagesContext",
|
|
1228
|
+
"effectiveSettings"
|
|
1209
1229
|
];
|
|
1210
1230
|
CHAT_API_KEYS = [
|
|
1211
1231
|
"all",
|
|
@@ -1230,8 +1250,8 @@ var init_api_version = __esm({
|
|
|
1230
1250
|
"src/services/api/api-version.ts"() {
|
|
1231
1251
|
init_client();
|
|
1232
1252
|
DEFAULT_VERSIONS = {
|
|
1233
|
-
|
|
1234
|
-
|
|
1253
|
+
v1: "v1",
|
|
1254
|
+
v2: "v2"
|
|
1235
1255
|
};
|
|
1236
1256
|
apiVersions = { ...DEFAULT_VERSIONS };
|
|
1237
1257
|
normalizeApiVersion = (version) => {
|
|
@@ -1250,7 +1270,7 @@ var init_api_version = __esm({
|
|
|
1250
1270
|
buildVersionedApiUrl = (path, options) => {
|
|
1251
1271
|
const root = resolveApiRoot(options?.baseUrl);
|
|
1252
1272
|
const version = normalizeApiVersion(
|
|
1253
|
-
options?.version ?? (options?.service ? apiVersions[options.service] : apiVersions.
|
|
1273
|
+
options?.version ?? (options?.service ? apiVersions[options.service] : apiVersions.v1)
|
|
1254
1274
|
);
|
|
1255
1275
|
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
1256
1276
|
if (!root) {
|
|
@@ -1260,23 +1280,23 @@ var init_api_version = __esm({
|
|
|
1260
1280
|
};
|
|
1261
1281
|
setChatApiVersions = (config) => {
|
|
1262
1282
|
if (!config) return;
|
|
1263
|
-
if (config.
|
|
1264
|
-
apiVersions.
|
|
1283
|
+
if (config.v1) {
|
|
1284
|
+
apiVersions.v1 = normalizeApiVersion(config.v1);
|
|
1265
1285
|
}
|
|
1266
|
-
if (config.
|
|
1267
|
-
apiVersions.
|
|
1286
|
+
if (config.v2) {
|
|
1287
|
+
apiVersions.v2 = normalizeApiVersion(config.v2);
|
|
1268
1288
|
}
|
|
1269
1289
|
};
|
|
1270
1290
|
getChatApiVersions = () => ({
|
|
1271
1291
|
...apiVersions
|
|
1272
1292
|
});
|
|
1273
1293
|
setChatPushApiVersion = (version) => {
|
|
1274
|
-
apiVersions.
|
|
1294
|
+
apiVersions.v2 = normalizeApiVersion(version);
|
|
1275
1295
|
};
|
|
1276
1296
|
syncDefaultApiVersionFromBaseUrl = (baseUrl) => {
|
|
1277
1297
|
const match = String(baseUrl || "").trim().match(/\/(v\d+)\/?$/i);
|
|
1278
1298
|
if (match?.[1]) {
|
|
1279
|
-
apiVersions.
|
|
1299
|
+
apiVersions.v1 = normalizeApiVersion(match[1]);
|
|
1280
1300
|
}
|
|
1281
1301
|
};
|
|
1282
1302
|
}
|
|
@@ -1421,6 +1441,9 @@ var init_api_constants = __esm({
|
|
|
1421
1441
|
SEARCH_MESSAGES: "/message/search-messages",
|
|
1422
1442
|
SEARCH_MESSAGES_CONTEXT: (messageId2) => `/message/searched-message/context?messageId=${messageId2}`,
|
|
1423
1443
|
BLOCK_UNBLOCK_USER: "/user/block-unblock"
|
|
1444
|
+
},
|
|
1445
|
+
SETTINGS: {
|
|
1446
|
+
PERMISSIONS: "/settings/effective"
|
|
1424
1447
|
}
|
|
1425
1448
|
};
|
|
1426
1449
|
}
|
|
@@ -1457,13 +1480,11 @@ var init_auth_api = __esm({
|
|
|
1457
1480
|
});
|
|
1458
1481
|
|
|
1459
1482
|
// src/constants/chat.constants.ts
|
|
1460
|
-
var DEFAULT_MESSAGES_LIMIT, DEFAULT_CONVERSATIONS_LIMIT,
|
|
1483
|
+
var DEFAULT_MESSAGES_LIMIT, DEFAULT_CONVERSATIONS_LIMIT, MAX_ATTACHMENT_CAPTION_LENGTH, ATTACHMENT_FILENAME_TIMESTAMP_LENGTH;
|
|
1461
1484
|
var init_chat_constants = __esm({
|
|
1462
1485
|
"src/constants/chat.constants.ts"() {
|
|
1463
1486
|
DEFAULT_MESSAGES_LIMIT = 20;
|
|
1464
1487
|
DEFAULT_CONVERSATIONS_LIMIT = 20;
|
|
1465
|
-
DM_EDIT_WINDOW_MS = 5 * 60 * 1e3;
|
|
1466
|
-
GROUP_EDIT_WINDOW_MS = 10 * 60 * 1e3;
|
|
1467
1488
|
MAX_ATTACHMENT_CAPTION_LENGTH = 100;
|
|
1468
1489
|
ATTACHMENT_FILENAME_TIMESTAMP_LENGTH = 13;
|
|
1469
1490
|
}
|
|
@@ -1666,6 +1687,212 @@ var init_uploads_api = __esm({
|
|
|
1666
1687
|
}
|
|
1667
1688
|
});
|
|
1668
1689
|
|
|
1690
|
+
// src/types/settings.types.ts
|
|
1691
|
+
var DEFAULT_EFFECTIVE_SETTINGS, ADMIN_PERMISSION_DENIED_MESSAGE, CALLS_NOT_ALLOWED_BY_PLATFORM_MESSAGE, CALLS_NOT_CONFIGURED_MESSAGE;
|
|
1692
|
+
var init_settings_types = __esm({
|
|
1693
|
+
"src/types/settings.types.ts"() {
|
|
1694
|
+
DEFAULT_EFFECTIVE_SETTINGS = {
|
|
1695
|
+
pushNotificationEnabled: true,
|
|
1696
|
+
videoCallEnabled: true,
|
|
1697
|
+
audioCallEnabled: true,
|
|
1698
|
+
blockUsersEnabled: true,
|
|
1699
|
+
calls: {
|
|
1700
|
+
allowedByPlatform: true,
|
|
1701
|
+
enabled: true,
|
|
1702
|
+
configured: true
|
|
1703
|
+
},
|
|
1704
|
+
groupPolicy: {
|
|
1705
|
+
defaults: {
|
|
1706
|
+
onlyAdminCanSendMessage: false,
|
|
1707
|
+
onlyAdminCanEditInfo: false,
|
|
1708
|
+
senderCanEditMessage: true,
|
|
1709
|
+
allowMemberAdd: true,
|
|
1710
|
+
allowMemberRemove: false,
|
|
1711
|
+
moderationEnabled: false
|
|
1712
|
+
},
|
|
1713
|
+
locked: []
|
|
1714
|
+
},
|
|
1715
|
+
messageTimers: {
|
|
1716
|
+
dmEditMinutes: 5,
|
|
1717
|
+
dmDeleteMinutes: 5,
|
|
1718
|
+
groupEditMinutes: 10,
|
|
1719
|
+
groupDeleteMinutes: 10
|
|
1720
|
+
},
|
|
1721
|
+
attachments: {
|
|
1722
|
+
enabled: true,
|
|
1723
|
+
maxFileSizeMB: 10,
|
|
1724
|
+
allowedMimeTypes: ["image/*", "video/*", "audio/*", "application/pdf"],
|
|
1725
|
+
maxAttachmentsPerMessage: 10
|
|
1726
|
+
},
|
|
1727
|
+
maxAdminsPerGroup: 5,
|
|
1728
|
+
maxParticipantsPerGroup: 100,
|
|
1729
|
+
maxPinnedMessagesPerConversation: 10,
|
|
1730
|
+
groupCreationEnabled: true
|
|
1731
|
+
};
|
|
1732
|
+
ADMIN_PERMISSION_DENIED_MESSAGE = "This feature is disabled by your administrator.";
|
|
1733
|
+
CALLS_NOT_ALLOWED_BY_PLATFORM_MESSAGE = "Calls are not allowed on this platform. Please contact your administrator.";
|
|
1734
|
+
CALLS_NOT_CONFIGURED_MESSAGE = "Calls are not configured. Please contact your administrator.";
|
|
1735
|
+
}
|
|
1736
|
+
});
|
|
1737
|
+
|
|
1738
|
+
// src/services/api/settings.api.ts
|
|
1739
|
+
function asBoolean(value, fallback) {
|
|
1740
|
+
return typeof value === "boolean" ? value : fallback;
|
|
1741
|
+
}
|
|
1742
|
+
function asPositiveNumber(value, fallback) {
|
|
1743
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
|
|
1744
|
+
}
|
|
1745
|
+
function asStringArray(value, fallback) {
|
|
1746
|
+
if (!Array.isArray(value)) return fallback;
|
|
1747
|
+
const next = value.filter((item) => typeof item === "string");
|
|
1748
|
+
return next.length > 0 ? next : fallback;
|
|
1749
|
+
}
|
|
1750
|
+
function normalizeGroupPermissions(value, fallback) {
|
|
1751
|
+
if (!value || typeof value !== "object") return { ...fallback };
|
|
1752
|
+
const raw = value;
|
|
1753
|
+
return {
|
|
1754
|
+
onlyAdminCanSendMessage: asBoolean(
|
|
1755
|
+
raw.onlyAdminCanSendMessage,
|
|
1756
|
+
fallback.onlyAdminCanSendMessage
|
|
1757
|
+
),
|
|
1758
|
+
onlyAdminCanEditInfo: asBoolean(
|
|
1759
|
+
raw.onlyAdminCanEditInfo,
|
|
1760
|
+
fallback.onlyAdminCanEditInfo
|
|
1761
|
+
),
|
|
1762
|
+
senderCanEditMessage: asBoolean(
|
|
1763
|
+
raw.senderCanEditMessage,
|
|
1764
|
+
fallback.senderCanEditMessage
|
|
1765
|
+
),
|
|
1766
|
+
allowMemberAdd: asBoolean(raw.allowMemberAdd, fallback.allowMemberAdd),
|
|
1767
|
+
allowMemberRemove: asBoolean(
|
|
1768
|
+
raw.allowMemberRemove,
|
|
1769
|
+
fallback.allowMemberRemove
|
|
1770
|
+
),
|
|
1771
|
+
moderationEnabled: asBoolean(
|
|
1772
|
+
raw.moderationEnabled,
|
|
1773
|
+
fallback.moderationEnabled
|
|
1774
|
+
)
|
|
1775
|
+
};
|
|
1776
|
+
}
|
|
1777
|
+
function normalizeCalls(value, fallback) {
|
|
1778
|
+
if (!value || typeof value !== "object") return { ...fallback };
|
|
1779
|
+
const raw = value;
|
|
1780
|
+
return {
|
|
1781
|
+
allowedByPlatform: asBoolean(
|
|
1782
|
+
raw.allowedByPlatform,
|
|
1783
|
+
fallback.allowedByPlatform
|
|
1784
|
+
),
|
|
1785
|
+
enabled: asBoolean(raw.enabled, fallback.enabled),
|
|
1786
|
+
configured: asBoolean(raw.configured, fallback.configured)
|
|
1787
|
+
};
|
|
1788
|
+
}
|
|
1789
|
+
function normalizeGroupPolicy(value, fallback) {
|
|
1790
|
+
if (!value || typeof value !== "object") {
|
|
1791
|
+
return {
|
|
1792
|
+
defaults: { ...fallback.defaults },
|
|
1793
|
+
locked: [...fallback.locked]
|
|
1794
|
+
};
|
|
1795
|
+
}
|
|
1796
|
+
const raw = value;
|
|
1797
|
+
return {
|
|
1798
|
+
defaults: normalizeGroupPermissions(raw.defaults, fallback.defaults),
|
|
1799
|
+
locked: asStringArray(raw.locked, fallback.locked)
|
|
1800
|
+
};
|
|
1801
|
+
}
|
|
1802
|
+
function normalizeMessageTimers(value, fallback) {
|
|
1803
|
+
if (!value || typeof value !== "object") return { ...fallback };
|
|
1804
|
+
const raw = value;
|
|
1805
|
+
return {
|
|
1806
|
+
dmEditMinutes: asPositiveNumber(raw.dmEditMinutes, fallback.dmEditMinutes),
|
|
1807
|
+
dmDeleteMinutes: asPositiveNumber(
|
|
1808
|
+
raw.dmDeleteMinutes,
|
|
1809
|
+
fallback.dmDeleteMinutes
|
|
1810
|
+
),
|
|
1811
|
+
groupEditMinutes: asPositiveNumber(
|
|
1812
|
+
raw.groupEditMinutes,
|
|
1813
|
+
fallback.groupEditMinutes
|
|
1814
|
+
),
|
|
1815
|
+
groupDeleteMinutes: asPositiveNumber(
|
|
1816
|
+
raw.groupDeleteMinutes,
|
|
1817
|
+
fallback.groupDeleteMinutes
|
|
1818
|
+
)
|
|
1819
|
+
};
|
|
1820
|
+
}
|
|
1821
|
+
function normalizeAttachments(value, fallback) {
|
|
1822
|
+
if (!value || typeof value !== "object") return { ...fallback };
|
|
1823
|
+
const raw = value;
|
|
1824
|
+
return {
|
|
1825
|
+
enabled: asBoolean(raw.enabled, fallback.enabled),
|
|
1826
|
+
maxFileSizeMB: asPositiveNumber(raw.maxFileSizeMB, fallback.maxFileSizeMB),
|
|
1827
|
+
allowedMimeTypes: asStringArray(
|
|
1828
|
+
raw.allowedMimeTypes,
|
|
1829
|
+
fallback.allowedMimeTypes
|
|
1830
|
+
),
|
|
1831
|
+
maxAttachmentsPerMessage: asPositiveNumber(
|
|
1832
|
+
raw.maxAttachmentsPerMessage,
|
|
1833
|
+
fallback.maxAttachmentsPerMessage
|
|
1834
|
+
)
|
|
1835
|
+
};
|
|
1836
|
+
}
|
|
1837
|
+
function normalizeEffectiveSettings(raw) {
|
|
1838
|
+
const payload = raw && typeof raw === "object" ? raw.data ?? raw : null;
|
|
1839
|
+
const source = payload && typeof payload === "object" ? payload : {};
|
|
1840
|
+
const defaults = DEFAULT_EFFECTIVE_SETTINGS;
|
|
1841
|
+
return {
|
|
1842
|
+
pushNotificationEnabled: asBoolean(
|
|
1843
|
+
source.pushNotificationEnabled,
|
|
1844
|
+
defaults.pushNotificationEnabled
|
|
1845
|
+
),
|
|
1846
|
+
videoCallEnabled: asBoolean(
|
|
1847
|
+
source.videoCallEnabled,
|
|
1848
|
+
defaults.videoCallEnabled
|
|
1849
|
+
),
|
|
1850
|
+
audioCallEnabled: asBoolean(
|
|
1851
|
+
source.audioCallEnabled,
|
|
1852
|
+
defaults.audioCallEnabled
|
|
1853
|
+
),
|
|
1854
|
+
blockUsersEnabled: asBoolean(
|
|
1855
|
+
source.blockUsersEnabled,
|
|
1856
|
+
defaults.blockUsersEnabled
|
|
1857
|
+
),
|
|
1858
|
+
calls: normalizeCalls(source.calls, defaults.calls),
|
|
1859
|
+
groupPolicy: normalizeGroupPolicy(source.groupPolicy, defaults.groupPolicy),
|
|
1860
|
+
messageTimers: normalizeMessageTimers(
|
|
1861
|
+
source.messageTimers,
|
|
1862
|
+
defaults.messageTimers
|
|
1863
|
+
),
|
|
1864
|
+
attachments: normalizeAttachments(source.attachments, defaults.attachments),
|
|
1865
|
+
maxAdminsPerGroup: asPositiveNumber(
|
|
1866
|
+
source.maxAdminsPerGroup,
|
|
1867
|
+
defaults.maxAdminsPerGroup
|
|
1868
|
+
),
|
|
1869
|
+
maxParticipantsPerGroup: asPositiveNumber(
|
|
1870
|
+
source.maxParticipantsPerGroup,
|
|
1871
|
+
defaults.maxParticipantsPerGroup
|
|
1872
|
+
),
|
|
1873
|
+
maxPinnedMessagesPerConversation: asPositiveNumber(
|
|
1874
|
+
source.maxPinnedMessagesPerConversation,
|
|
1875
|
+
defaults.maxPinnedMessagesPerConversation
|
|
1876
|
+
),
|
|
1877
|
+
groupCreationEnabled: asBoolean(
|
|
1878
|
+
source.groupCreationEnabled,
|
|
1879
|
+
defaults.groupCreationEnabled
|
|
1880
|
+
)
|
|
1881
|
+
};
|
|
1882
|
+
}
|
|
1883
|
+
var fetchEffectiveSettings;
|
|
1884
|
+
var init_settings_api = __esm({
|
|
1885
|
+
"src/services/api/settings.api.ts"() {
|
|
1886
|
+
init_api_constants();
|
|
1887
|
+
init_client();
|
|
1888
|
+
init_settings_types();
|
|
1889
|
+
fetchEffectiveSettings = async () => {
|
|
1890
|
+
const response = await apiClient.get(API_ENDPOINTS.SETTINGS.PERMISSIONS);
|
|
1891
|
+
return normalizeEffectiveSettings(response.data);
|
|
1892
|
+
};
|
|
1893
|
+
}
|
|
1894
|
+
});
|
|
1895
|
+
|
|
1669
1896
|
// src/services/api/index.ts
|
|
1670
1897
|
var init_api = __esm({
|
|
1671
1898
|
"src/services/api/index.ts"() {
|
|
@@ -1674,6 +1901,7 @@ var init_api = __esm({
|
|
|
1674
1901
|
init_messages_api();
|
|
1675
1902
|
init_groups_api();
|
|
1676
1903
|
init_uploads_api();
|
|
1904
|
+
init_settings_api();
|
|
1677
1905
|
}
|
|
1678
1906
|
});
|
|
1679
1907
|
|
|
@@ -4505,6 +4733,150 @@ var useChatCustomizationOptional = () => {
|
|
|
4505
4733
|
};
|
|
4506
4734
|
var useChatFeatures = () => useChatCustomization().features;
|
|
4507
4735
|
var useChatFeaturesOptional = () => useChatCustomizationOptional().features;
|
|
4736
|
+
|
|
4737
|
+
// src/context/ChatEffectiveSettingsContext.tsx
|
|
4738
|
+
init_settings_api();
|
|
4739
|
+
init_settings_types();
|
|
4740
|
+
var ChatEffectiveSettingsContext = createContext(null);
|
|
4741
|
+
function buildCallGate(settings, featureEnabled) {
|
|
4742
|
+
if (!settings.calls.allowedByPlatform) {
|
|
4743
|
+
return {
|
|
4744
|
+
visible: true,
|
|
4745
|
+
enabled: false,
|
|
4746
|
+
disabledReason: CALLS_NOT_ALLOWED_BY_PLATFORM_MESSAGE
|
|
4747
|
+
};
|
|
4748
|
+
}
|
|
4749
|
+
if (!settings.calls.configured) {
|
|
4750
|
+
return {
|
|
4751
|
+
visible: true,
|
|
4752
|
+
enabled: false,
|
|
4753
|
+
disabledReason: CALLS_NOT_CONFIGURED_MESSAGE
|
|
4754
|
+
};
|
|
4755
|
+
}
|
|
4756
|
+
if (!settings.calls.enabled) {
|
|
4757
|
+
return {
|
|
4758
|
+
visible: true,
|
|
4759
|
+
enabled: false,
|
|
4760
|
+
disabledReason: ADMIN_PERMISSION_DENIED_MESSAGE
|
|
4761
|
+
};
|
|
4762
|
+
}
|
|
4763
|
+
if (!featureEnabled) {
|
|
4764
|
+
return {
|
|
4765
|
+
visible: true,
|
|
4766
|
+
enabled: false,
|
|
4767
|
+
disabledReason: ADMIN_PERMISSION_DENIED_MESSAGE
|
|
4768
|
+
};
|
|
4769
|
+
}
|
|
4770
|
+
return { visible: true, enabled: true, disabledReason: null };
|
|
4771
|
+
}
|
|
4772
|
+
function ChatEffectiveSettingsProvider({
|
|
4773
|
+
children,
|
|
4774
|
+
enabled = true
|
|
4775
|
+
}) {
|
|
4776
|
+
const [settings, setSettings] = useState(
|
|
4777
|
+
DEFAULT_EFFECTIVE_SETTINGS
|
|
4778
|
+
);
|
|
4779
|
+
const [loading, setLoading] = useState(true);
|
|
4780
|
+
const [error, setError] = useState(null);
|
|
4781
|
+
const refresh = useCallback(async () => {
|
|
4782
|
+
if (!enabled) {
|
|
4783
|
+
setLoading(false);
|
|
4784
|
+
return;
|
|
4785
|
+
}
|
|
4786
|
+
setLoading(true);
|
|
4787
|
+
try {
|
|
4788
|
+
const next = await fetchEffectiveSettings();
|
|
4789
|
+
setSettings(next);
|
|
4790
|
+
setError(null);
|
|
4791
|
+
} catch (err) {
|
|
4792
|
+
console.error("Failed to fetch effective settings:", err);
|
|
4793
|
+
setError(
|
|
4794
|
+
err instanceof Error ? err.message : "Could not load chat permissions"
|
|
4795
|
+
);
|
|
4796
|
+
setSettings(DEFAULT_EFFECTIVE_SETTINGS);
|
|
4797
|
+
} finally {
|
|
4798
|
+
setLoading(false);
|
|
4799
|
+
}
|
|
4800
|
+
}, [enabled]);
|
|
4801
|
+
useEffect(() => {
|
|
4802
|
+
void refresh();
|
|
4803
|
+
}, [refresh]);
|
|
4804
|
+
const value = useMemo(() => {
|
|
4805
|
+
const isGroupPermissionLocked = (key) => settings.groupPolicy.locked.includes(key);
|
|
4806
|
+
return {
|
|
4807
|
+
settings,
|
|
4808
|
+
loading,
|
|
4809
|
+
error,
|
|
4810
|
+
refresh,
|
|
4811
|
+
isGroupPermissionLocked,
|
|
4812
|
+
getAudioCallGate: () => buildCallGate(settings, settings.audioCallEnabled),
|
|
4813
|
+
getVideoCallGate: () => buildCallGate(settings, settings.videoCallEnabled),
|
|
4814
|
+
getPushNotificationGate: () => ({
|
|
4815
|
+
visible: true,
|
|
4816
|
+
enabled: settings.pushNotificationEnabled,
|
|
4817
|
+
disabledReason: settings.pushNotificationEnabled ? null : ADMIN_PERMISSION_DENIED_MESSAGE
|
|
4818
|
+
}),
|
|
4819
|
+
getBlockUsersGate: () => ({
|
|
4820
|
+
visible: true,
|
|
4821
|
+
enabled: settings.blockUsersEnabled,
|
|
4822
|
+
disabledReason: settings.blockUsersEnabled ? null : ADMIN_PERMISSION_DENIED_MESSAGE
|
|
4823
|
+
}),
|
|
4824
|
+
getAttachmentsGate: () => ({
|
|
4825
|
+
visible: true,
|
|
4826
|
+
enabled: settings.attachments.enabled,
|
|
4827
|
+
disabledReason: settings.attachments.enabled ? null : ADMIN_PERMISSION_DENIED_MESSAGE
|
|
4828
|
+
}),
|
|
4829
|
+
getGroupCreationGate: () => ({
|
|
4830
|
+
visible: true,
|
|
4831
|
+
enabled: settings.groupCreationEnabled,
|
|
4832
|
+
disabledReason: settings.groupCreationEnabled ? null : ADMIN_PERMISSION_DENIED_MESSAGE
|
|
4833
|
+
})
|
|
4834
|
+
};
|
|
4835
|
+
}, [settings, loading, error, refresh]);
|
|
4836
|
+
return /* @__PURE__ */ jsx(ChatEffectiveSettingsContext.Provider, { value, children });
|
|
4837
|
+
}
|
|
4838
|
+
function useEffectiveSettings() {
|
|
4839
|
+
const ctx = useContext(ChatEffectiveSettingsContext);
|
|
4840
|
+
if (!ctx) {
|
|
4841
|
+
throw new Error(
|
|
4842
|
+
"useEffectiveSettings must be used within ChatEffectiveSettingsProvider"
|
|
4843
|
+
);
|
|
4844
|
+
}
|
|
4845
|
+
return ctx;
|
|
4846
|
+
}
|
|
4847
|
+
function useEffectiveSettingsOptional() {
|
|
4848
|
+
const ctx = useContext(ChatEffectiveSettingsContext);
|
|
4849
|
+
if (ctx) return ctx;
|
|
4850
|
+
return {
|
|
4851
|
+
settings: DEFAULT_EFFECTIVE_SETTINGS,
|
|
4852
|
+
loading: false,
|
|
4853
|
+
error: null,
|
|
4854
|
+
refresh: async () => void 0,
|
|
4855
|
+
isGroupPermissionLocked: () => false,
|
|
4856
|
+
getAudioCallGate: () => buildCallGate(DEFAULT_EFFECTIVE_SETTINGS, true),
|
|
4857
|
+
getVideoCallGate: () => buildCallGate(DEFAULT_EFFECTIVE_SETTINGS, true),
|
|
4858
|
+
getPushNotificationGate: () => ({
|
|
4859
|
+
visible: true,
|
|
4860
|
+
enabled: true,
|
|
4861
|
+
disabledReason: null
|
|
4862
|
+
}),
|
|
4863
|
+
getBlockUsersGate: () => ({
|
|
4864
|
+
visible: true,
|
|
4865
|
+
enabled: true,
|
|
4866
|
+
disabledReason: null
|
|
4867
|
+
}),
|
|
4868
|
+
getAttachmentsGate: () => ({
|
|
4869
|
+
visible: true,
|
|
4870
|
+
enabled: true,
|
|
4871
|
+
disabledReason: null
|
|
4872
|
+
}),
|
|
4873
|
+
getGroupCreationGate: () => ({
|
|
4874
|
+
visible: true,
|
|
4875
|
+
enabled: true,
|
|
4876
|
+
disabledReason: null
|
|
4877
|
+
})
|
|
4878
|
+
};
|
|
4879
|
+
}
|
|
4508
4880
|
var ChatContext = createContext(void 0);
|
|
4509
4881
|
var useChatContext = () => {
|
|
4510
4882
|
const context = useContext(ChatContext);
|
|
@@ -4544,7 +4916,7 @@ var Chat = ({
|
|
|
4544
4916
|
const status = useStore((s) => s.status);
|
|
4545
4917
|
const error = useStore((s) => s.error);
|
|
4546
4918
|
useChatSync();
|
|
4547
|
-
|
|
4919
|
+
React3__default.useEffect(() => {
|
|
4548
4920
|
const clientId = client?.id;
|
|
4549
4921
|
const initializeChat = async () => {
|
|
4550
4922
|
if (!clientId || !loggedUserDetails) return;
|
|
@@ -4634,28 +5006,28 @@ var Chat = ({
|
|
|
4634
5006
|
queryParamApis: queryParamApis ?? ["get"],
|
|
4635
5007
|
queryParamsByApi: queryParamsByApi ?? {}
|
|
4636
5008
|
});
|
|
4637
|
-
|
|
5009
|
+
React3__default.useEffect(() => {
|
|
4638
5010
|
setChatQueryParams(queryParams);
|
|
4639
5011
|
setChatQueryParamApis(queryParamApis);
|
|
4640
5012
|
setChatQueryParamsByApi(queryParamsByApi);
|
|
4641
5013
|
}, [queryConfigKey]);
|
|
4642
|
-
|
|
5014
|
+
React3__default.useEffect(() => {
|
|
4643
5015
|
if (lastDM && onMessageReceived) {
|
|
4644
5016
|
onMessageReceived(lastDM);
|
|
4645
5017
|
}
|
|
4646
5018
|
}, [lastDM, onMessageReceived]);
|
|
4647
|
-
|
|
5019
|
+
React3__default.useEffect(() => {
|
|
4648
5020
|
if (status === "connected" && onSocketConnected) {
|
|
4649
5021
|
const socketId = useStore.getState().socketId;
|
|
4650
5022
|
if (socketId) onSocketConnected(socketId);
|
|
4651
5023
|
}
|
|
4652
5024
|
}, [status, onSocketConnected]);
|
|
4653
|
-
|
|
5025
|
+
React3__default.useEffect(() => {
|
|
4654
5026
|
if (status === "error" && error && onSocketError) {
|
|
4655
5027
|
onSocketError(error);
|
|
4656
5028
|
}
|
|
4657
5029
|
}, [status, error, onSocketError]);
|
|
4658
|
-
const contextValue =
|
|
5030
|
+
const contextValue = React3__default.useMemo(
|
|
4659
5031
|
() => ({
|
|
4660
5032
|
onSendMessage,
|
|
4661
5033
|
client,
|
|
@@ -4675,7 +5047,7 @@ var Chat = ({
|
|
|
4675
5047
|
messagesData
|
|
4676
5048
|
]
|
|
4677
5049
|
);
|
|
4678
|
-
const customization =
|
|
5050
|
+
const customization = React3__default.useMemo(
|
|
4679
5051
|
() => ({
|
|
4680
5052
|
components: uiConfig.components,
|
|
4681
5053
|
classNames: uiConfig.classNames,
|
|
@@ -4683,7 +5055,7 @@ var Chat = ({
|
|
|
4683
5055
|
}),
|
|
4684
5056
|
[uiConfig.components, uiConfig.classNames, uiConfig.features]
|
|
4685
5057
|
);
|
|
4686
|
-
return /* @__PURE__ */ jsx(ChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(ChatCustomizationProvider, { customization, children: /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsx("div", { className: "chat-container-root flex h-full min-h-0 w-full flex-1 flex-col overflow-hidden", children: isSessionReady ? children : /* @__PURE__ */ jsx("div", { className: "flex h-full items-center justify-center text-gray-400 font-bold", children: "Initializing session..." }) }) }) }) });
|
|
5058
|
+
return /* @__PURE__ */ jsx(ChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(ChatCustomizationProvider, { customization, children: /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsx("div", { className: "chat-container-root flex h-full min-h-0 w-full flex-1 flex-col overflow-hidden", children: isSessionReady ? /* @__PURE__ */ jsx(ChatEffectiveSettingsProvider, { enabled: true, children }) : /* @__PURE__ */ jsx("div", { className: "flex h-full items-center justify-center text-gray-400 font-bold", children: "Initializing session..." }) }) }) }) });
|
|
4687
5059
|
};
|
|
4688
5060
|
|
|
4689
5061
|
// src/hooks/useChatController.ts
|
|
@@ -6086,6 +6458,8 @@ function useCreateChatDialog({
|
|
|
6086
6458
|
const fetchAllUsers = useStore((storeState) => storeState.fetchAllUsers);
|
|
6087
6459
|
const accessToken = useStore((storeState) => storeState.accessToken);
|
|
6088
6460
|
const fetchConversations2 = useStore((storeState) => storeState.fetchConversations);
|
|
6461
|
+
const { settings } = useEffectiveSettingsOptional();
|
|
6462
|
+
const maxParticipants = settings.maxParticipantsPerGroup;
|
|
6089
6463
|
const fileInputRef = useRef(null);
|
|
6090
6464
|
useEffect(() => {
|
|
6091
6465
|
if (accessToken) {
|
|
@@ -6099,9 +6473,18 @@ function useCreateChatDialog({
|
|
|
6099
6473
|
setState((prev) => {
|
|
6100
6474
|
const memberId = String(member._id);
|
|
6101
6475
|
const exists = prev.selectedMembers.some((m) => String(m._id) === memberId);
|
|
6476
|
+
if (exists) {
|
|
6477
|
+
return {
|
|
6478
|
+
...prev,
|
|
6479
|
+
selectedMembers: prev.selectedMembers.filter((m) => String(m._id) !== memberId)
|
|
6480
|
+
};
|
|
6481
|
+
}
|
|
6482
|
+
if (prev.selectedMembers.length + 1 >= maxParticipants) {
|
|
6483
|
+
return prev;
|
|
6484
|
+
}
|
|
6102
6485
|
return {
|
|
6103
6486
|
...prev,
|
|
6104
|
-
selectedMembers:
|
|
6487
|
+
selectedMembers: [...prev.selectedMembers, member]
|
|
6105
6488
|
};
|
|
6106
6489
|
});
|
|
6107
6490
|
};
|
|
@@ -6485,8 +6868,25 @@ function GroupCreateTab({
|
|
|
6485
6868
|
) })
|
|
6486
6869
|
] });
|
|
6487
6870
|
}
|
|
6871
|
+
function AdminPermissionTooltip({
|
|
6872
|
+
disabled,
|
|
6873
|
+
message,
|
|
6874
|
+
side = "top",
|
|
6875
|
+
className,
|
|
6876
|
+
children
|
|
6877
|
+
}) {
|
|
6878
|
+
if (!disabled || !message) {
|
|
6879
|
+
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
6880
|
+
}
|
|
6881
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
6882
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: cn("inline-flex", className), children }) }),
|
|
6883
|
+
/* @__PURE__ */ jsx(TooltipContent, { side, className: "max-w-[240px] text-xs", children: message })
|
|
6884
|
+
] });
|
|
6885
|
+
}
|
|
6488
6886
|
var CreateChatDialog = (props) => {
|
|
6489
6887
|
const { isCreateModalOpen = false, setIsCreateModalOpen } = props;
|
|
6888
|
+
const { getGroupCreationGate } = useEffectiveSettingsOptional();
|
|
6889
|
+
const groupCreationGate = getGroupCreationGate();
|
|
6490
6890
|
const {
|
|
6491
6891
|
state,
|
|
6492
6892
|
updateState,
|
|
@@ -6540,24 +6940,39 @@ var CreateChatDialog = (props) => {
|
|
|
6540
6940
|
) })
|
|
6541
6941
|
] }),
|
|
6542
6942
|
/* @__PURE__ */ jsx("div", { className: "grid shrink-0 grid-cols-2 gap-2 px-5", children: [
|
|
6543
|
-
{ id: "dm", label: "Message", icon: MessageCircle },
|
|
6544
|
-
{ id: "group", label: "New group", icon: Users }
|
|
6545
|
-
].map(({ id, label, icon: Icon }) => /* @__PURE__ */ jsxs(
|
|
6546
|
-
"button",
|
|
6943
|
+
{ id: "dm", label: "Message", icon: MessageCircle, disabled: false, reason: null },
|
|
6547
6944
|
{
|
|
6548
|
-
|
|
6549
|
-
|
|
6550
|
-
|
|
6551
|
-
|
|
6552
|
-
|
|
6553
|
-
|
|
6554
|
-
|
|
6555
|
-
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
|
|
6560
|
-
|
|
6945
|
+
id: "group",
|
|
6946
|
+
label: "New group",
|
|
6947
|
+
icon: Users,
|
|
6948
|
+
disabled: !groupCreationGate.enabled,
|
|
6949
|
+
reason: groupCreationGate.disabledReason
|
|
6950
|
+
}
|
|
6951
|
+
].map(({ id, label, icon: Icon, disabled, reason }) => {
|
|
6952
|
+
const tabButton = /* @__PURE__ */ jsxs(
|
|
6953
|
+
"button",
|
|
6954
|
+
{
|
|
6955
|
+
type: "button",
|
|
6956
|
+
disabled,
|
|
6957
|
+
onClick: () => {
|
|
6958
|
+
if (disabled) return;
|
|
6959
|
+
updateState({ activeTab: id });
|
|
6960
|
+
},
|
|
6961
|
+
className: cn(
|
|
6962
|
+
"flex w-full items-center justify-center gap-2 rounded-full border py-2 text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-40",
|
|
6963
|
+
state.activeTab === id ? "border-(--chat-theme-20) bg-(--chat-theme-5) text-(--chat-theme)" : "border-(--chat-border) text-(--chat-muted) hover:border-(--chat-theme-20) hover:text-(--chat-text)"
|
|
6964
|
+
),
|
|
6965
|
+
children: [
|
|
6966
|
+
/* @__PURE__ */ jsx(Icon, { className: "size-4" }),
|
|
6967
|
+
label
|
|
6968
|
+
]
|
|
6969
|
+
}
|
|
6970
|
+
);
|
|
6971
|
+
if (!disabled || !reason) {
|
|
6972
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: tabButton }, id);
|
|
6973
|
+
}
|
|
6974
|
+
return /* @__PURE__ */ jsx(AdminPermissionTooltip, { disabled: true, message: reason, children: tabButton }, id);
|
|
6975
|
+
}) }),
|
|
6561
6976
|
state.activeTab === "dm" && /* @__PURE__ */ jsx(
|
|
6562
6977
|
DmContactsTab,
|
|
6563
6978
|
{
|
|
@@ -6568,7 +6983,7 @@ var CreateChatDialog = (props) => {
|
|
|
6568
6983
|
onStartDM: handleStartDM
|
|
6569
6984
|
}
|
|
6570
6985
|
),
|
|
6571
|
-
state.activeTab === "group" && /* @__PURE__ */ jsx(
|
|
6986
|
+
state.activeTab === "group" && groupCreationGate.enabled && /* @__PURE__ */ jsx(
|
|
6572
6987
|
GroupCreateTab,
|
|
6573
6988
|
{
|
|
6574
6989
|
state,
|
|
@@ -6632,7 +7047,7 @@ var emitPushChanged = (enabled) => {
|
|
|
6632
7047
|
} catch {
|
|
6633
7048
|
}
|
|
6634
7049
|
};
|
|
6635
|
-
var pushApiUrl = (path) => buildVersionedApiUrl(path, { service: "
|
|
7050
|
+
var pushApiUrl = (path) => buildVersionedApiUrl(path, { service: "v2" });
|
|
6636
7051
|
var apiGetPushConfig = async () => {
|
|
6637
7052
|
const { data } = await apiClient.get(pushApiUrl("/notifications/push/config"));
|
|
6638
7053
|
return data?.data;
|
|
@@ -6877,14 +7292,20 @@ var PushNotificationToggle = ({
|
|
|
6877
7292
|
children
|
|
6878
7293
|
}) => {
|
|
6879
7294
|
const push = usePushNotifications();
|
|
7295
|
+
const { getPushNotificationGate } = useEffectiveSettingsOptional();
|
|
7296
|
+
const adminGate = getPushNotificationGate();
|
|
6880
7297
|
const [isToggling, setIsToggling] = useState(false);
|
|
6881
|
-
if (!push.supported
|
|
7298
|
+
if (!push.supported) {
|
|
6882
7299
|
return null;
|
|
6883
7300
|
}
|
|
6884
7301
|
const isOn = push.deviceEnabled && push.userEnabled;
|
|
6885
7302
|
const permissionBlocked = push.permission === "denied";
|
|
7303
|
+
const adminBlocked = !adminGate.enabled;
|
|
7304
|
+
const notConfigured = !push.configured;
|
|
6886
7305
|
const showLoader = isToggling;
|
|
7306
|
+
const isDisabled = showLoader || permissionBlocked || push.loading || adminBlocked || notConfigured;
|
|
6887
7307
|
const handleChange = async (checked) => {
|
|
7308
|
+
if (adminBlocked || notConfigured) return;
|
|
6888
7309
|
setIsToggling(true);
|
|
6889
7310
|
try {
|
|
6890
7311
|
if (checked) {
|
|
@@ -6897,11 +7318,12 @@ var PushNotificationToggle = ({
|
|
|
6897
7318
|
setIsToggling(false);
|
|
6898
7319
|
}
|
|
6899
7320
|
};
|
|
7321
|
+
const descriptionText = adminBlocked ? adminGate.disabledReason || description : notConfigured ? "Push notifications are not configured. Please contact your administrator." : permissionBlocked ? "Notifications are blocked in your browser settings" : push.error ?? description;
|
|
6900
7322
|
const renderProps = {
|
|
6901
7323
|
label,
|
|
6902
|
-
description:
|
|
6903
|
-
checked: isOn,
|
|
6904
|
-
disabled:
|
|
7324
|
+
description: descriptionText,
|
|
7325
|
+
checked: adminBlocked || notConfigured ? false : isOn,
|
|
7326
|
+
disabled: isDisabled,
|
|
6905
7327
|
loading: showLoader || push.loading,
|
|
6906
7328
|
permissionBlocked,
|
|
6907
7329
|
error: push.error,
|
|
@@ -6929,12 +7351,20 @@ var PushNotificationToggle = ({
|
|
|
6929
7351
|
"aria-label": "Updating push notifications"
|
|
6930
7352
|
}
|
|
6931
7353
|
) : /* @__PURE__ */ jsx(
|
|
6932
|
-
|
|
7354
|
+
AdminPermissionTooltip,
|
|
6933
7355
|
{
|
|
6934
|
-
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
|
|
7356
|
+
disabled: adminBlocked || notConfigured,
|
|
7357
|
+
message: adminBlocked ? adminGate.disabledReason : "Push notifications are not configured. Please contact your administrator.",
|
|
7358
|
+
children: /* @__PURE__ */ jsx(
|
|
7359
|
+
Switch,
|
|
7360
|
+
{
|
|
7361
|
+
checked: adminBlocked || notConfigured ? false : isOn,
|
|
7362
|
+
disabled: isDisabled,
|
|
7363
|
+
onCheckedChange: (checked) => void handleChange(checked),
|
|
7364
|
+
"aria-label": `Toggle ${label}`,
|
|
7365
|
+
className: "data-[state=checked]:bg-(--chat-theme) data-[state=unchecked]:bg-(--chat-border)"
|
|
7366
|
+
}
|
|
7367
|
+
)
|
|
6938
7368
|
}
|
|
6939
7369
|
)
|
|
6940
7370
|
]
|
|
@@ -8355,7 +8785,7 @@ function highlightSearchMatch(text, query) {
|
|
|
8355
8785
|
children: part
|
|
8356
8786
|
},
|
|
8357
8787
|
`${part}-${index}`
|
|
8358
|
-
) : /* @__PURE__ */ jsx(
|
|
8788
|
+
) : /* @__PURE__ */ jsx(React3__default.Fragment, { children: part }, `${part}-${index}`)
|
|
8359
8789
|
);
|
|
8360
8790
|
}
|
|
8361
8791
|
function getMessagePreview(message) {
|
|
@@ -8535,7 +8965,7 @@ var HeaderSearchPopover = ({
|
|
|
8535
8965
|
] });
|
|
8536
8966
|
};
|
|
8537
8967
|
var HeaderSearchPopover_default = HeaderSearchPopover;
|
|
8538
|
-
var actionBtnClass = "size-8 rounded-lg text-(--chat-muted) transition-colors hover:bg-(--chat-surface) hover:text-(--chat-text)";
|
|
8968
|
+
var actionBtnClass = "size-8 rounded-lg text-(--chat-muted) transition-colors hover:bg-(--chat-surface) hover:text-(--chat-text) disabled:opacity-40";
|
|
8539
8969
|
var DefaultHeaderCallActions = ({
|
|
8540
8970
|
activeChannel,
|
|
8541
8971
|
conversationId,
|
|
@@ -8546,48 +8976,91 @@ var DefaultHeaderCallActions = ({
|
|
|
8546
8976
|
className
|
|
8547
8977
|
}) => {
|
|
8548
8978
|
const { components, slotClassName, features } = useChatCustomizationOptional();
|
|
8979
|
+
const { getAudioCallGate, getVideoCallGate } = useEffectiveSettingsOptional();
|
|
8549
8980
|
const PhoneSlot = components.PhoneCallButton;
|
|
8550
8981
|
const VideoSlot = components.VideoCallButton;
|
|
8551
8982
|
const hideInGroups = features.hideCallActionsInGroupChats ?? false;
|
|
8983
|
+
const audioGate = getAudioCallGate();
|
|
8984
|
+
const videoGate = getVideoCallGate();
|
|
8552
8985
|
if (hideInGroups && activeChannel.isGroup) return null;
|
|
8553
8986
|
if (!showPhoneCall && !showVideoCall) return null;
|
|
8987
|
+
const phoneEnabled = showPhoneCall && audioGate.enabled;
|
|
8988
|
+
const videoEnabled = showVideoCall && videoGate.enabled;
|
|
8554
8989
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8555
8990
|
showPhoneCall && (PhoneSlot ? /* @__PURE__ */ jsx(
|
|
8556
|
-
|
|
8991
|
+
AdminPermissionTooltip,
|
|
8557
8992
|
{
|
|
8558
|
-
|
|
8559
|
-
|
|
8560
|
-
|
|
8561
|
-
|
|
8993
|
+
disabled: !audioGate.enabled,
|
|
8994
|
+
message: audioGate.disabledReason,
|
|
8995
|
+
children: /* @__PURE__ */ jsx("span", { className: "inline-flex", children: /* @__PURE__ */ jsx(
|
|
8996
|
+
PhoneSlot,
|
|
8997
|
+
{
|
|
8998
|
+
activeChannel,
|
|
8999
|
+
conversationId,
|
|
9000
|
+
onPhoneCall: phoneEnabled ? onPhoneCall : void 0,
|
|
9001
|
+
className: cn(
|
|
9002
|
+
className,
|
|
9003
|
+
slotClassName("phoneCallButton"),
|
|
9004
|
+
!audioGate.enabled && "pointer-events-none opacity-40"
|
|
9005
|
+
)
|
|
9006
|
+
}
|
|
9007
|
+
) })
|
|
8562
9008
|
}
|
|
8563
9009
|
) : /* @__PURE__ */ jsx(
|
|
8564
|
-
|
|
9010
|
+
AdminPermissionTooltip,
|
|
8565
9011
|
{
|
|
8566
|
-
|
|
8567
|
-
|
|
8568
|
-
|
|
8569
|
-
|
|
8570
|
-
|
|
8571
|
-
|
|
9012
|
+
disabled: !audioGate.enabled,
|
|
9013
|
+
message: audioGate.disabledReason,
|
|
9014
|
+
children: /* @__PURE__ */ jsx(
|
|
9015
|
+
Button,
|
|
9016
|
+
{
|
|
9017
|
+
variant: "ghost",
|
|
9018
|
+
size: "icon",
|
|
9019
|
+
className: cn(actionBtnClass, className, slotClassName("phoneCallButton")),
|
|
9020
|
+
"aria-label": "Voice call",
|
|
9021
|
+
disabled: !audioGate.enabled,
|
|
9022
|
+
onClick: phoneEnabled ? onPhoneCall : void 0,
|
|
9023
|
+
children: /* @__PURE__ */ jsx(Phone, { size: 15 })
|
|
9024
|
+
}
|
|
9025
|
+
)
|
|
8572
9026
|
}
|
|
8573
9027
|
)),
|
|
8574
9028
|
showVideoCall && (VideoSlot ? /* @__PURE__ */ jsx(
|
|
8575
|
-
|
|
9029
|
+
AdminPermissionTooltip,
|
|
8576
9030
|
{
|
|
8577
|
-
|
|
8578
|
-
|
|
8579
|
-
|
|
8580
|
-
|
|
9031
|
+
disabled: !videoGate.enabled,
|
|
9032
|
+
message: videoGate.disabledReason,
|
|
9033
|
+
children: /* @__PURE__ */ jsx("span", { className: "inline-flex", children: /* @__PURE__ */ jsx(
|
|
9034
|
+
VideoSlot,
|
|
9035
|
+
{
|
|
9036
|
+
activeChannel,
|
|
9037
|
+
conversationId,
|
|
9038
|
+
onVideoCall: videoEnabled ? onVideoCall : void 0,
|
|
9039
|
+
className: cn(
|
|
9040
|
+
className,
|
|
9041
|
+
slotClassName("videoCallButton"),
|
|
9042
|
+
!videoGate.enabled && "pointer-events-none opacity-40"
|
|
9043
|
+
)
|
|
9044
|
+
}
|
|
9045
|
+
) })
|
|
8581
9046
|
}
|
|
8582
9047
|
) : /* @__PURE__ */ jsx(
|
|
8583
|
-
|
|
9048
|
+
AdminPermissionTooltip,
|
|
8584
9049
|
{
|
|
8585
|
-
|
|
8586
|
-
|
|
8587
|
-
|
|
8588
|
-
|
|
8589
|
-
|
|
8590
|
-
|
|
9050
|
+
disabled: !videoGate.enabled,
|
|
9051
|
+
message: videoGate.disabledReason,
|
|
9052
|
+
children: /* @__PURE__ */ jsx(
|
|
9053
|
+
Button,
|
|
9054
|
+
{
|
|
9055
|
+
variant: "ghost",
|
|
9056
|
+
size: "icon",
|
|
9057
|
+
className: cn(actionBtnClass, className, slotClassName("videoCallButton")),
|
|
9058
|
+
"aria-label": "Video call",
|
|
9059
|
+
disabled: !videoGate.enabled,
|
|
9060
|
+
onClick: videoEnabled ? onVideoCall : void 0,
|
|
9061
|
+
children: /* @__PURE__ */ jsx(Video, { size: 15 })
|
|
9062
|
+
}
|
|
9063
|
+
)
|
|
8591
9064
|
}
|
|
8592
9065
|
))
|
|
8593
9066
|
] });
|
|
@@ -8609,19 +9082,38 @@ function OptionsMenuItem({
|
|
|
8609
9082
|
icon: Icon,
|
|
8610
9083
|
label,
|
|
8611
9084
|
onSelect,
|
|
8612
|
-
destructive = false
|
|
9085
|
+
destructive = false,
|
|
9086
|
+
disabled = false,
|
|
9087
|
+
disabledReason
|
|
8613
9088
|
}) {
|
|
8614
|
-
|
|
9089
|
+
const item = /* @__PURE__ */ jsxs(
|
|
8615
9090
|
DropdownMenuItem,
|
|
8616
9091
|
{
|
|
8617
|
-
className:
|
|
8618
|
-
|
|
9092
|
+
className: cn(
|
|
9093
|
+
destructive ? chatOptionsMenuItemDestructiveClass : chatOptionsMenuItemClass,
|
|
9094
|
+
disabled && "pointer-events-none opacity-40"
|
|
9095
|
+
),
|
|
9096
|
+
disabled,
|
|
9097
|
+
onSelect: (event) => {
|
|
9098
|
+
if (disabled) {
|
|
9099
|
+
event.preventDefault();
|
|
9100
|
+
return;
|
|
9101
|
+
}
|
|
9102
|
+
onSelect?.();
|
|
9103
|
+
},
|
|
8619
9104
|
children: [
|
|
8620
9105
|
/* @__PURE__ */ jsx(Icon, { strokeWidth: 1.75 }),
|
|
8621
9106
|
/* @__PURE__ */ jsx("span", { className: "flex-1", children: label })
|
|
8622
9107
|
]
|
|
8623
9108
|
}
|
|
8624
9109
|
);
|
|
9110
|
+
if (!disabled || !disabledReason) {
|
|
9111
|
+
return item;
|
|
9112
|
+
}
|
|
9113
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
9114
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx("div", { className: "w-full", children: item }) }),
|
|
9115
|
+
/* @__PURE__ */ jsx(TooltipContent, { side: "left", className: "max-w-[220px] text-xs", children: disabledReason })
|
|
9116
|
+
] });
|
|
8625
9117
|
}
|
|
8626
9118
|
var HeaderRightSide = ({
|
|
8627
9119
|
activeChannel,
|
|
@@ -8656,6 +9148,8 @@ var HeaderRightSide = ({
|
|
|
8656
9148
|
const { scopeClassName, themeStyles, showColorModeToggle } = useChatTheme();
|
|
8657
9149
|
const { showDateTimeSettings } = useChatLocale();
|
|
8658
9150
|
const features = useChatFeaturesOptional();
|
|
9151
|
+
const { getBlockUsersGate } = useEffectiveSettingsOptional();
|
|
9152
|
+
const blockUsersGate = getBlockUsersGate();
|
|
8659
9153
|
const showPhoneCall = features.showPhoneCall ?? defaultChatFeatures.showPhoneCall;
|
|
8660
9154
|
const showVideoCall = features.showVideoCall ?? defaultChatFeatures.showVideoCall;
|
|
8661
9155
|
const handlePhoneCall = () => {
|
|
@@ -8804,7 +9298,9 @@ var HeaderRightSide = ({
|
|
|
8804
9298
|
icon: Ban,
|
|
8805
9299
|
label: isBlocked ? "Unblock User" : "Block User",
|
|
8806
9300
|
onSelect: onToggleBlock,
|
|
8807
|
-
destructive: true
|
|
9301
|
+
destructive: true,
|
|
9302
|
+
disabled: !blockUsersGate.enabled,
|
|
9303
|
+
disabledReason: blockUsersGate.disabledReason
|
|
8808
9304
|
}
|
|
8809
9305
|
)
|
|
8810
9306
|
]
|
|
@@ -12844,17 +13340,24 @@ var ChannelDetailsDrawer = (props) => {
|
|
|
12844
13340
|
};
|
|
12845
13341
|
var ChannelDetailsDrawer_default = ChannelDetailsDrawer;
|
|
12846
13342
|
init_useStore();
|
|
13343
|
+
init_settings_types();
|
|
12847
13344
|
var PermissionDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo }) => {
|
|
12848
13345
|
const updateGroupPermissions = useStore((s) => s.updateGroupPermissions);
|
|
13346
|
+
const { settings, isGroupPermissionLocked } = useEffectiveSettingsOptional();
|
|
12849
13347
|
const [permissions, setPermissions] = useState(null);
|
|
12850
13348
|
const [isSaving, setIsSaving] = useState(false);
|
|
12851
13349
|
useEffect(() => {
|
|
12852
13350
|
if (conversationInfo?.groupPermissions) {
|
|
12853
13351
|
setPermissions(conversationInfo.groupPermissions);
|
|
13352
|
+
return;
|
|
12854
13353
|
}
|
|
12855
|
-
|
|
13354
|
+
if (isOpen) {
|
|
13355
|
+
setPermissions({ ...settings.groupPolicy.defaults });
|
|
13356
|
+
}
|
|
13357
|
+
}, [conversationInfo, isOpen, settings.groupPolicy.defaults]);
|
|
12856
13358
|
if (!conversationId || !permissions) return null;
|
|
12857
13359
|
const handleToggle = (key) => {
|
|
13360
|
+
if (isGroupPermissionLocked(key)) return;
|
|
12858
13361
|
setPermissions((prev) => prev ? { ...prev, [key]: !prev[key] } : null);
|
|
12859
13362
|
};
|
|
12860
13363
|
const handleSave = async () => {
|
|
@@ -12886,31 +13389,43 @@ var PermissionDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo
|
|
|
12886
13389
|
/* @__PURE__ */ jsxs("div", { className: cn(chatSheetBodyClass, "flex flex-col px-2.5 py-2"), children: [
|
|
12887
13390
|
/* @__PURE__ */ jsxs("section", { className: "mb-2.5 flex-1", children: [
|
|
12888
13391
|
/* @__PURE__ */ jsx("h3", { className: "mb-1 px-0.5 text-[10px] font-semibold uppercase tracking-wide text-(--chat-muted)", children: "Permissions" }),
|
|
12889
|
-
/* @__PURE__ */ jsx("div", { className: "rounded-lg border border-(--chat-border) px-3", children: permissionItems.map((item, index) =>
|
|
12890
|
-
|
|
12891
|
-
|
|
12892
|
-
|
|
12893
|
-
|
|
12894
|
-
|
|
12895
|
-
|
|
12896
|
-
|
|
12897
|
-
|
|
12898
|
-
|
|
12899
|
-
/* @__PURE__ */
|
|
12900
|
-
|
|
12901
|
-
|
|
12902
|
-
|
|
12903
|
-
|
|
12904
|
-
|
|
12905
|
-
|
|
12906
|
-
|
|
12907
|
-
|
|
12908
|
-
|
|
12909
|
-
|
|
12910
|
-
|
|
12911
|
-
|
|
12912
|
-
|
|
12913
|
-
|
|
13392
|
+
/* @__PURE__ */ jsx("div", { className: "rounded-lg border border-(--chat-border) px-3", children: permissionItems.map((item, index) => {
|
|
13393
|
+
const locked = isGroupPermissionLocked(item.key);
|
|
13394
|
+
return /* @__PURE__ */ jsxs(
|
|
13395
|
+
"div",
|
|
13396
|
+
{
|
|
13397
|
+
className: cn(
|
|
13398
|
+
"flex items-start justify-between gap-3 py-2.5",
|
|
13399
|
+
index < permissionItems.length - 1 && "border-b border-(--chat-border)"
|
|
13400
|
+
),
|
|
13401
|
+
children: [
|
|
13402
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-0.5", children: [
|
|
13403
|
+
/* @__PURE__ */ jsx("p", { className: "text-[12px] font-semibold leading-snug text-(--chat-text)", children: item.label }),
|
|
13404
|
+
/* @__PURE__ */ jsx("p", { className: "text-[10px] leading-relaxed text-(--chat-muted)", children: item.desc }),
|
|
13405
|
+
locked ? /* @__PURE__ */ jsx("p", { className: "text-[10px] font-medium text-(--chat-theme)", children: "Locked by administrator" }) : null
|
|
13406
|
+
] }),
|
|
13407
|
+
/* @__PURE__ */ jsx(
|
|
13408
|
+
AdminPermissionTooltip,
|
|
13409
|
+
{
|
|
13410
|
+
disabled: locked,
|
|
13411
|
+
message: ADMIN_PERMISSION_DENIED_MESSAGE,
|
|
13412
|
+
children: /* @__PURE__ */ jsx(
|
|
13413
|
+
Switch,
|
|
13414
|
+
{
|
|
13415
|
+
size: "sm",
|
|
13416
|
+
className: "mt-0.5 shrink-0 data-[state=checked]:bg-(--chat-theme) data-[state=unchecked]:bg-(--chat-border)",
|
|
13417
|
+
disabled: locked,
|
|
13418
|
+
checked: item.inverted ? !permissions[item.key] : permissions[item.key],
|
|
13419
|
+
onCheckedChange: () => handleToggle(item.key)
|
|
13420
|
+
}
|
|
13421
|
+
)
|
|
13422
|
+
}
|
|
13423
|
+
)
|
|
13424
|
+
]
|
|
13425
|
+
},
|
|
13426
|
+
item.key
|
|
13427
|
+
);
|
|
13428
|
+
}) })
|
|
12914
13429
|
] }),
|
|
12915
13430
|
/* @__PURE__ */ jsx("div", { className: "sticky bottom-0 border-t border-(--chat-border) bg-(--chat-surface) px-0.5 pt-2.5 pb-1", children: /* @__PURE__ */ jsx(
|
|
12916
13431
|
Button,
|
|
@@ -12940,6 +13455,8 @@ function useAdminsDrawer({ conversationId, conversationInfo }) {
|
|
|
12940
13455
|
const [isManaging, setIsManaging] = useState(null);
|
|
12941
13456
|
const manageGroupAdmins = useStore((s) => s.manageGroupAdmins);
|
|
12942
13457
|
const { isOwner } = useGroupInfo(conversationId);
|
|
13458
|
+
const { settings } = useEffectiveSettingsOptional();
|
|
13459
|
+
const maxAdmins = settings.maxAdminsPerGroup;
|
|
12943
13460
|
const participants = useMemo(
|
|
12944
13461
|
() => conversationInfo?.participants ?? [],
|
|
12945
13462
|
[conversationInfo?.participants]
|
|
@@ -12979,8 +13496,16 @@ function useAdminsDrawer({ conversationId, conversationInfo }) {
|
|
|
12979
13496
|
}),
|
|
12980
13497
|
[filteredParticipants, adminIds, ownerId]
|
|
12981
13498
|
);
|
|
13499
|
+
const adminCount = admins.length + (ownerId ? 1 : 0);
|
|
13500
|
+
const atAdminLimit = adminCount >= maxAdmins;
|
|
12982
13501
|
const handleManageAdmin = async (userId, type) => {
|
|
12983
13502
|
if (!conversationId) return;
|
|
13503
|
+
if (type === "add" && adminCount >= maxAdmins) {
|
|
13504
|
+
useStore.getState().handleAppError(
|
|
13505
|
+
`You can have up to ${maxAdmins} admins in this group.`
|
|
13506
|
+
);
|
|
13507
|
+
return;
|
|
13508
|
+
}
|
|
12984
13509
|
setIsManaging(userId);
|
|
12985
13510
|
try {
|
|
12986
13511
|
await manageGroupAdmins({
|
|
@@ -12992,7 +13517,6 @@ function useAdminsDrawer({ conversationId, conversationInfo }) {
|
|
|
12992
13517
|
setIsManaging(null);
|
|
12993
13518
|
}
|
|
12994
13519
|
};
|
|
12995
|
-
const adminCount = admins.length + (ownerId ? 1 : 0);
|
|
12996
13520
|
return {
|
|
12997
13521
|
searchQuery,
|
|
12998
13522
|
setSearchQuery,
|
|
@@ -13004,6 +13528,8 @@ function useAdminsDrawer({ conversationId, conversationInfo }) {
|
|
|
13004
13528
|
promotableParticipants,
|
|
13005
13529
|
handleManageAdmin,
|
|
13006
13530
|
adminCount,
|
|
13531
|
+
maxAdmins,
|
|
13532
|
+
atAdminLimit,
|
|
13007
13533
|
hasRequiredData: Boolean(conversationId && conversationInfo)
|
|
13008
13534
|
};
|
|
13009
13535
|
}
|
|
@@ -13016,6 +13542,8 @@ function AdminParticipantRow({
|
|
|
13016
13542
|
isAdmin,
|
|
13017
13543
|
showPromote,
|
|
13018
13544
|
showDemote,
|
|
13545
|
+
promoteDisabled = false,
|
|
13546
|
+
promoteDisabledReason,
|
|
13019
13547
|
isOwnerViewer,
|
|
13020
13548
|
isManaging,
|
|
13021
13549
|
onManageAdmin
|
|
@@ -13056,14 +13584,24 @@ function AdminParticipantRow({
|
|
|
13056
13584
|
}
|
|
13057
13585
|
),
|
|
13058
13586
|
showPromote && isOwnerViewer && /* @__PURE__ */ jsx(
|
|
13059
|
-
|
|
13587
|
+
AdminPermissionTooltip,
|
|
13060
13588
|
{
|
|
13061
|
-
|
|
13062
|
-
|
|
13063
|
-
|
|
13064
|
-
|
|
13065
|
-
|
|
13066
|
-
|
|
13589
|
+
disabled: promoteDisabled,
|
|
13590
|
+
message: promoteDisabledReason,
|
|
13591
|
+
children: /* @__PURE__ */ jsx(
|
|
13592
|
+
Button,
|
|
13593
|
+
{
|
|
13594
|
+
variant: "ghost",
|
|
13595
|
+
size: "sm",
|
|
13596
|
+
className: "size-7 rounded-md p-0 text-(--chat-muted) hover:bg-(--chat-theme-10) hover:text-(--chat-theme) disabled:opacity-40",
|
|
13597
|
+
onClick: () => {
|
|
13598
|
+
if (promoteDisabled) return;
|
|
13599
|
+
onManageAdmin(memberId, "add");
|
|
13600
|
+
},
|
|
13601
|
+
disabled: isManaging === memberId || promoteDisabled,
|
|
13602
|
+
children: isManaging === memberId ? /* @__PURE__ */ jsx(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx(UserPlus, { size: 13 })
|
|
13603
|
+
}
|
|
13604
|
+
)
|
|
13067
13605
|
}
|
|
13068
13606
|
)
|
|
13069
13607
|
] })
|
|
@@ -13087,7 +13625,9 @@ function AdminParticipantList({
|
|
|
13087
13625
|
isAdmin,
|
|
13088
13626
|
onManageAdmin,
|
|
13089
13627
|
showPromote,
|
|
13090
|
-
showDemoteForAdmins
|
|
13628
|
+
showDemoteForAdmins,
|
|
13629
|
+
promoteDisabled = false,
|
|
13630
|
+
promoteDisabledReason
|
|
13091
13631
|
}) {
|
|
13092
13632
|
return /* @__PURE__ */ jsx(Fragment, { children: members.map((member, index) => {
|
|
13093
13633
|
const { memberId, memberName, memberEmail, memberImage } = getMemberFields(member);
|
|
@@ -13105,6 +13645,8 @@ function AdminParticipantList({
|
|
|
13105
13645
|
isAdmin: userIsAdmin,
|
|
13106
13646
|
showPromote: showPromote && !userIsAdmin && !userIsOwner,
|
|
13107
13647
|
showDemote: showDemoteForAdmins ? userIsAdmin && !userIsOwner : false,
|
|
13648
|
+
promoteDisabled,
|
|
13649
|
+
promoteDisabledReason,
|
|
13108
13650
|
isOwnerViewer,
|
|
13109
13651
|
isManaging,
|
|
13110
13652
|
onManageAdmin
|
|
@@ -13124,6 +13666,8 @@ var AdminsDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13124
13666
|
promotableParticipants,
|
|
13125
13667
|
handleManageAdmin,
|
|
13126
13668
|
adminCount,
|
|
13669
|
+
maxAdmins,
|
|
13670
|
+
atAdminLimit,
|
|
13127
13671
|
hasRequiredData
|
|
13128
13672
|
} = useAdminsDrawer({ conversationId, conversationInfo });
|
|
13129
13673
|
if (!hasRequiredData) return null;
|
|
@@ -13143,7 +13687,10 @@ var AdminsDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13143
13687
|
/* @__PURE__ */ jsx(SheetTitle, { className: chatSheetTitleClass, children: "Group Administrators" }),
|
|
13144
13688
|
/* @__PURE__ */ jsx("span", { className: "rounded-full bg-(--chat-theme-10) px-2 py-0.5 text-[11px] font-medium leading-none text-(--chat-theme)", children: adminCount })
|
|
13145
13689
|
] }),
|
|
13146
|
-
/* @__PURE__ */
|
|
13690
|
+
/* @__PURE__ */ jsxs("p", { className: chatSheetSubtitleClass, children: [
|
|
13691
|
+
"Manage who can adjust group settings and members",
|
|
13692
|
+
maxAdmins ? ` (max ${maxAdmins}).` : "."
|
|
13693
|
+
] })
|
|
13147
13694
|
] }),
|
|
13148
13695
|
/* @__PURE__ */ jsxs("div", { className: cn(chatSheetBodyClass, "px-2.5 py-2"), children: [
|
|
13149
13696
|
/* @__PURE__ */ jsx("div", { className: "mb-2.5 px-0.5", children: /* @__PURE__ */ jsx(
|
|
@@ -13186,7 +13733,9 @@ var AdminsDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13186
13733
|
ownerId,
|
|
13187
13734
|
isAdmin,
|
|
13188
13735
|
onManageAdmin: handleManageAdmin,
|
|
13189
|
-
showPromote: true
|
|
13736
|
+
showPromote: true,
|
|
13737
|
+
promoteDisabled: atAdminLimit,
|
|
13738
|
+
promoteDisabledReason: `Maximum ${maxAdmins} admins allowed in this group.`
|
|
13190
13739
|
}
|
|
13191
13740
|
) })
|
|
13192
13741
|
] }),
|
|
@@ -13203,7 +13752,9 @@ var AdminsDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13203
13752
|
isAdmin,
|
|
13204
13753
|
onManageAdmin: handleManageAdmin,
|
|
13205
13754
|
showPromote: true,
|
|
13206
|
-
showDemoteForAdmins: true
|
|
13755
|
+
showDemoteForAdmins: true,
|
|
13756
|
+
promoteDisabled: atAdminLimit,
|
|
13757
|
+
promoteDisabledReason: `Maximum ${maxAdmins} admins allowed in this group.`
|
|
13207
13758
|
}
|
|
13208
13759
|
) })
|
|
13209
13760
|
] }),
|
|
@@ -13231,9 +13782,12 @@ var MembersDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13231
13782
|
);
|
|
13232
13783
|
}, [allUsers, searchQuery]);
|
|
13233
13784
|
const { userPermissions } = useGroupInfo(conversationId);
|
|
13785
|
+
const { settings } = useEffectiveSettingsOptional();
|
|
13786
|
+
const maxParticipants = settings.maxParticipantsPerGroup;
|
|
13234
13787
|
if (!conversationId || !conversationInfo) return null;
|
|
13235
13788
|
const participants = conversationInfo.participants || [];
|
|
13236
13789
|
const admins = conversationInfo.groupAdmins || [];
|
|
13790
|
+
const atParticipantLimit = participants.length >= maxParticipants;
|
|
13237
13791
|
let ownerId = null;
|
|
13238
13792
|
if (conversationInfo.owner) {
|
|
13239
13793
|
ownerId = typeof conversationInfo.owner === "object" && conversationInfo.owner !== null ? conversationInfo.owner._id || conversationInfo.owner.id : conversationInfo.owner;
|
|
@@ -13287,14 +13841,24 @@ var MembersDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13287
13841
|
}
|
|
13288
13842
|
),
|
|
13289
13843
|
options.showAdd && /* @__PURE__ */ jsx(
|
|
13290
|
-
|
|
13844
|
+
AdminPermissionTooltip,
|
|
13291
13845
|
{
|
|
13292
|
-
|
|
13293
|
-
|
|
13294
|
-
|
|
13295
|
-
|
|
13296
|
-
|
|
13297
|
-
|
|
13846
|
+
disabled: atParticipantLimit,
|
|
13847
|
+
message: `Maximum ${maxParticipants} participants allowed in this group.`,
|
|
13848
|
+
children: /* @__PURE__ */ jsx(
|
|
13849
|
+
Button,
|
|
13850
|
+
{
|
|
13851
|
+
variant: "ghost",
|
|
13852
|
+
size: "sm",
|
|
13853
|
+
className: "size-7 rounded-md p-0 text-(--chat-muted) hover:bg-(--chat-theme-10) hover:text-(--chat-theme) disabled:opacity-40",
|
|
13854
|
+
onClick: () => {
|
|
13855
|
+
if (atParticipantLimit) return;
|
|
13856
|
+
handleManageMember(memberId, "add");
|
|
13857
|
+
},
|
|
13858
|
+
disabled: isManaging === memberId || atParticipantLimit,
|
|
13859
|
+
children: isManaging === memberId ? /* @__PURE__ */ jsx(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx(UserPlus, { size: 13 })
|
|
13860
|
+
}
|
|
13861
|
+
)
|
|
13298
13862
|
}
|
|
13299
13863
|
)
|
|
13300
13864
|
] })
|
|
@@ -13316,7 +13880,11 @@ var MembersDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13316
13880
|
/* @__PURE__ */ jsx(SheetTitle, { className: chatSheetTitleClass, children: "Group Management" }),
|
|
13317
13881
|
/* @__PURE__ */ jsx("span", { className: "rounded-full bg-(--chat-theme-10) px-2 py-0.5 text-[11px] font-medium leading-none text-(--chat-theme)", children: participants.length })
|
|
13318
13882
|
] }),
|
|
13319
|
-
/* @__PURE__ */
|
|
13883
|
+
/* @__PURE__ */ jsxs("p", { className: chatSheetSubtitleClass, children: [
|
|
13884
|
+
"Manage members and invite people (max ",
|
|
13885
|
+
maxParticipants,
|
|
13886
|
+
")."
|
|
13887
|
+
] })
|
|
13320
13888
|
] }),
|
|
13321
13889
|
/* @__PURE__ */ jsxs("div", { className: cn(chatSheetBodyClass, "px-2.5 py-2"), children: [
|
|
13322
13890
|
!searchQuery && /* @__PURE__ */ jsxs("section", { className: "mb-2.5", children: [
|
|
@@ -13458,6 +14026,8 @@ init_store_helpers();
|
|
|
13458
14026
|
function useBlockUser(activeChannel, conversationId, onActiveChannelPatch) {
|
|
13459
14027
|
const loggedUserDetails = useStore((s) => s.loggedUserDetails);
|
|
13460
14028
|
const composerDisabledByConversation = useStore((s) => s.composerDisabledByConversation);
|
|
14029
|
+
const { getBlockUsersGate } = useEffectiveSettingsOptional();
|
|
14030
|
+
const blockUsersGate = getBlockUsersGate();
|
|
13461
14031
|
const [isBlocking, setIsBlocking] = useState(false);
|
|
13462
14032
|
const resolvedConversationId = conversationId ?? activeChannel?.conversationId ?? null;
|
|
13463
14033
|
const composerDisabledReason = resolvedConversationId ? composerDisabledByConversation[resolvedConversationId] : void 0;
|
|
@@ -13479,6 +14049,12 @@ function useBlockUser(activeChannel, conversationId, onActiveChannelPatch) {
|
|
|
13479
14049
|
const toggleBlock = useCallback(async () => {
|
|
13480
14050
|
if (!activeChannel?.id || activeChannel.isGroup) return false;
|
|
13481
14051
|
const nextBlocked = !isBlocked;
|
|
14052
|
+
if (nextBlocked && !blockUsersGate.enabled) {
|
|
14053
|
+
useStore.getState().handleAppError(
|
|
14054
|
+
blockUsersGate.disabledReason || "Blocking users is disabled by your administrator."
|
|
14055
|
+
);
|
|
14056
|
+
return false;
|
|
14057
|
+
}
|
|
13482
14058
|
const type = nextBlocked ? "block" : "unblock";
|
|
13483
14059
|
try {
|
|
13484
14060
|
setIsBlocking(true);
|
|
@@ -13499,8 +14075,8 @@ function useBlockUser(activeChannel, conversationId, onActiveChannelPatch) {
|
|
|
13499
14075
|
} finally {
|
|
13500
14076
|
setIsBlocking(false);
|
|
13501
14077
|
}
|
|
13502
|
-
}, [activeChannel, isBlocked, onActiveChannelPatch, resolvedConversationId]);
|
|
13503
|
-
return { isBlocked, isBlocking, toggleBlock };
|
|
14078
|
+
}, [activeChannel, isBlocked, onActiveChannelPatch, resolvedConversationId, blockUsersGate]);
|
|
14079
|
+
return { isBlocked, isBlocking, toggleBlock, blockUsersGate };
|
|
13504
14080
|
}
|
|
13505
14081
|
|
|
13506
14082
|
// src/chat/channel-header/useChannelHeader.ts
|
|
@@ -14036,6 +14612,7 @@ var MessageReactions_default = MessageReactions;
|
|
|
14036
14612
|
var MessageToolbar = ({
|
|
14037
14613
|
isSender,
|
|
14038
14614
|
isRecent,
|
|
14615
|
+
isWithinDeleteWindow = isRecent,
|
|
14039
14616
|
isPinned,
|
|
14040
14617
|
isStarred,
|
|
14041
14618
|
isPinPending,
|
|
@@ -14059,7 +14636,7 @@ var MessageToolbar = ({
|
|
|
14059
14636
|
}) => {
|
|
14060
14637
|
const { isDark, scopeClassName, themeStyles } = useChatTheme();
|
|
14061
14638
|
const showDeleteMenu = isSender || hasAttachments || attachmentDeleteMode;
|
|
14062
|
-
const showDeleteForEveryone = isSender &&
|
|
14639
|
+
const showDeleteForEveryone = isSender && isWithinDeleteWindow;
|
|
14063
14640
|
return /* @__PURE__ */ jsxs(
|
|
14064
14641
|
"div",
|
|
14065
14642
|
{
|
|
@@ -14381,16 +14958,68 @@ function resolveForwardItems(selectedKeys, messages) {
|
|
|
14381
14958
|
}
|
|
14382
14959
|
|
|
14383
14960
|
// src/chat/lib/chat-edit-window.ts
|
|
14384
|
-
|
|
14385
|
-
|
|
14386
|
-
|
|
14961
|
+
init_settings_types();
|
|
14962
|
+
|
|
14963
|
+
// src/lib/effective-settings.helpers.ts
|
|
14964
|
+
function minutesToMs(minutes) {
|
|
14965
|
+
return Math.max(0, minutes) * 60 * 1e3;
|
|
14966
|
+
}
|
|
14967
|
+
function getEditWindowMs(timers, isGroup) {
|
|
14968
|
+
return minutesToMs(isGroup ? timers.groupEditMinutes : timers.dmEditMinutes);
|
|
14387
14969
|
}
|
|
14388
|
-
function
|
|
14970
|
+
function getDeleteWindowMs(timers, isGroup) {
|
|
14971
|
+
return minutesToMs(
|
|
14972
|
+
isGroup ? timers.groupDeleteMinutes : timers.dmDeleteMinutes
|
|
14973
|
+
);
|
|
14974
|
+
}
|
|
14975
|
+
function isWithinWindow(createdAt, windowMs) {
|
|
14389
14976
|
if (!createdAt) return false;
|
|
14390
14977
|
const date = new Date(createdAt);
|
|
14391
14978
|
if (isNaN(date.getTime())) return false;
|
|
14392
14979
|
const diff = Date.now() - date.getTime();
|
|
14393
|
-
return diff >= 0 && diff <
|
|
14980
|
+
return diff >= 0 && diff < windowMs;
|
|
14981
|
+
}
|
|
14982
|
+
function isWithinMessageEditWindow(createdAt, timers, isGroup) {
|
|
14983
|
+
return isWithinWindow(createdAt, getEditWindowMs(timers, isGroup));
|
|
14984
|
+
}
|
|
14985
|
+
function isWithinMessageDeleteWindow(createdAt, timers, isGroup) {
|
|
14986
|
+
return isWithinWindow(createdAt, getDeleteWindowMs(timers, isGroup));
|
|
14987
|
+
}
|
|
14988
|
+
function allowsAllMimeTypes(allowedMimeTypes) {
|
|
14989
|
+
return allowedMimeTypes.some((pattern) => {
|
|
14990
|
+
const normalized = pattern.trim().toLowerCase();
|
|
14991
|
+
return normalized === "*" || normalized === "*/*";
|
|
14992
|
+
});
|
|
14993
|
+
}
|
|
14994
|
+
function matchesAllowedMimeType(fileType, allowedMimeTypes) {
|
|
14995
|
+
if (!allowedMimeTypes.length) return false;
|
|
14996
|
+
if (allowsAllMimeTypes(allowedMimeTypes)) return true;
|
|
14997
|
+
const mime = (fileType || "application/octet-stream").toLowerCase();
|
|
14998
|
+
return allowedMimeTypes.some((pattern) => {
|
|
14999
|
+
const normalized = pattern.trim().toLowerCase();
|
|
15000
|
+
if (!normalized) return false;
|
|
15001
|
+
if (normalized.endsWith("/*")) {
|
|
15002
|
+
const prefix = normalized.slice(0, -1);
|
|
15003
|
+
return mime.startsWith(prefix);
|
|
15004
|
+
}
|
|
15005
|
+
return mime === normalized;
|
|
15006
|
+
});
|
|
15007
|
+
}
|
|
15008
|
+
function buildAcceptFromMimeTypes(allowedMimeTypes) {
|
|
15009
|
+
if (allowsAllMimeTypes(allowedMimeTypes)) return "";
|
|
15010
|
+
return allowedMimeTypes.map((type) => type.trim()).filter(Boolean).join(",");
|
|
15011
|
+
}
|
|
15012
|
+
function formatFileSizeMB(sizeBytes) {
|
|
15013
|
+
return `${(sizeBytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
15014
|
+
}
|
|
15015
|
+
|
|
15016
|
+
// src/chat/lib/chat-edit-window.ts
|
|
15017
|
+
var FALLBACK_TIMERS = DEFAULT_EFFECTIVE_SETTINGS.messageTimers;
|
|
15018
|
+
function isWithinMessageEditWindow2(createdAt, isGroup, timers = FALLBACK_TIMERS) {
|
|
15019
|
+
return isWithinMessageEditWindow(createdAt, timers, isGroup);
|
|
15020
|
+
}
|
|
15021
|
+
function isWithinMessageDeleteWindow2(createdAt, isGroup, timers = FALLBACK_TIMERS) {
|
|
15022
|
+
return isWithinMessageDeleteWindow(createdAt, timers, isGroup);
|
|
14394
15023
|
}
|
|
14395
15024
|
|
|
14396
15025
|
// src/chat/message-item/useMessageItemActions.ts
|
|
@@ -14468,6 +15097,9 @@ function useMessageItemActions({
|
|
|
14468
15097
|
const canUnpin = !isPinned || isPinnedByMe;
|
|
14469
15098
|
const { userPermissions } = useGroupInfo(conversationId || null);
|
|
14470
15099
|
const { formatMessageTime } = useChatLocale();
|
|
15100
|
+
const { settings } = useEffectiveSettingsOptional();
|
|
15101
|
+
const messageTimers = settings.messageTimers;
|
|
15102
|
+
const maxPinnedMessages = settings.maxPinnedMessagesPerConversation;
|
|
14471
15103
|
const visibleAttachments = getVisibleAttachments(attachments);
|
|
14472
15104
|
const hasAttachments = visibleAttachments.length > 0;
|
|
14473
15105
|
const hasMultiAttachments = hasAttachments && messageUsesAttachmentSelection({ attachments: visibleAttachments });
|
|
@@ -14484,7 +15116,8 @@ function useMessageItemActions({
|
|
|
14484
15116
|
const hasText = Boolean(message?.trim());
|
|
14485
15117
|
const isSelected = !!mid && !!selectedKeys && isMessageWhollySelected(selectedKeys, mid) && !hasMultiAttachments;
|
|
14486
15118
|
const canEdit = (!isGroup || userPermissions.canEditMessage) && hasText;
|
|
14487
|
-
const isWithinEditWindow = () =>
|
|
15119
|
+
const isWithinEditWindow = () => isWithinMessageEditWindow2(createdAt, isGroup, messageTimers);
|
|
15120
|
+
const isWithinDeleteWindow = () => isWithinMessageDeleteWindow2(createdAt, isGroup, messageTimers);
|
|
14488
15121
|
const canEditAttachmentCaption = isSender && isWithinEditWindow() && (!isGroup || userPermissions.canEditMessage) && !isDeletedForEveryone && !!mid;
|
|
14489
15122
|
const handleAttachmentCaptionClick = (attachment) => {
|
|
14490
15123
|
if (!canEditAttachmentCaption) return;
|
|
@@ -14653,6 +15286,15 @@ function useMessageItemActions({
|
|
|
14653
15286
|
});
|
|
14654
15287
|
}
|
|
14655
15288
|
} else {
|
|
15289
|
+
if (conversationId) {
|
|
15290
|
+
const pinnedCount = (pinnedMessagesByConversation[conversationId] || []).length || useStore.getState().liveConversationCounts[conversationId]?.pinnedCount || 0;
|
|
15291
|
+
if (pinnedCount >= maxPinnedMessages) {
|
|
15292
|
+
useStore.getState().handleAppError(
|
|
15293
|
+
`You can pin up to ${maxPinnedMessages} messages in this conversation.`
|
|
15294
|
+
);
|
|
15295
|
+
return;
|
|
15296
|
+
}
|
|
15297
|
+
}
|
|
14656
15298
|
if (isGroup) {
|
|
14657
15299
|
if (!conversationId) return;
|
|
14658
15300
|
emitGroupPin({
|
|
@@ -14711,6 +15353,7 @@ function useMessageItemActions({
|
|
|
14711
15353
|
canUnpin,
|
|
14712
15354
|
canEdit,
|
|
14713
15355
|
isWithinEditWindow,
|
|
15356
|
+
isWithinDeleteWindow,
|
|
14714
15357
|
canEditAttachmentCaption,
|
|
14715
15358
|
visibleAttachments,
|
|
14716
15359
|
hasAttachments,
|
|
@@ -14742,7 +15385,7 @@ function useMessageItemActions({
|
|
|
14742
15385
|
}
|
|
14743
15386
|
|
|
14744
15387
|
// src/chat/lib/reply-preview.ts
|
|
14745
|
-
function
|
|
15388
|
+
function normalizeAttachments2(replyTo, loggedUserId) {
|
|
14746
15389
|
const raw = replyTo?.attachments;
|
|
14747
15390
|
if (!Array.isArray(raw) || raw.length === 0) return [];
|
|
14748
15391
|
return raw.map((att, index) => {
|
|
@@ -14755,7 +15398,7 @@ function resolveReplyToMessage(replyTo, messagesById, loggedUserId) {
|
|
|
14755
15398
|
if (typeof replyTo === "object" && (replyTo.content?.trim() || replyTo.attachments?.length)) {
|
|
14756
15399
|
return {
|
|
14757
15400
|
...replyTo,
|
|
14758
|
-
attachments:
|
|
15401
|
+
attachments: normalizeAttachments2(replyTo, loggedUserId)
|
|
14759
15402
|
};
|
|
14760
15403
|
}
|
|
14761
15404
|
const replyId = String(
|
|
@@ -15192,6 +15835,7 @@ function MessageItemView(props) {
|
|
|
15192
15835
|
canUnpin,
|
|
15193
15836
|
canEdit,
|
|
15194
15837
|
isWithinEditWindow,
|
|
15838
|
+
isWithinDeleteWindow,
|
|
15195
15839
|
canEditAttachmentCaption,
|
|
15196
15840
|
visibleAttachments,
|
|
15197
15841
|
hasAttachments,
|
|
@@ -15283,6 +15927,7 @@ function MessageItemView(props) {
|
|
|
15283
15927
|
{
|
|
15284
15928
|
isSender,
|
|
15285
15929
|
isRecent: isWithinEditWindow(),
|
|
15930
|
+
isWithinDeleteWindow: isWithinDeleteWindow(),
|
|
15286
15931
|
messageId: mid,
|
|
15287
15932
|
isPinned,
|
|
15288
15933
|
isStarred,
|
|
@@ -15577,6 +16222,7 @@ function MessageSelectionBar({
|
|
|
15577
16222
|
}
|
|
15578
16223
|
|
|
15579
16224
|
// src/chat/active-channel-messages/utils.ts
|
|
16225
|
+
init_settings_types();
|
|
15580
16226
|
var getMessageSenderId2 = (msg) => msg ? String(msg.senderId || msg.sender?._id || "") : "";
|
|
15581
16227
|
var isLikelyObjectId = (value) => /^[a-f\d]{24}$/i.test(value);
|
|
15582
16228
|
function resolveGroupSenderDisplay(message, allUsers = [], participants = []) {
|
|
@@ -15608,7 +16254,7 @@ var isSameMessageSide = (a, b, isGroupChat) => {
|
|
|
15608
16254
|
const bId = getMessageSenderId2(b);
|
|
15609
16255
|
return aId !== "" && aId === bId;
|
|
15610
16256
|
};
|
|
15611
|
-
function canDeleteSelectionForEveryone(selectedKeys, messages, isGroup) {
|
|
16257
|
+
function canDeleteSelectionForEveryone(selectedKeys, messages, isGroup, timers = DEFAULT_EFFECTIVE_SETTINGS.messageTimers) {
|
|
15612
16258
|
if (selectedKeys.size === 0) return false;
|
|
15613
16259
|
const parsed = [...selectedKeys].map((key) => parseSelectionKey(key));
|
|
15614
16260
|
const messageIds = new Set(parsed.map((entry) => entry.messageId));
|
|
@@ -15616,7 +16262,7 @@ function canDeleteSelectionForEveryone(selectedKeys, messages, isGroup) {
|
|
|
15616
16262
|
const messageId2 = [...messageIds][0];
|
|
15617
16263
|
const message = messages.find((entry) => String(entry._id || entry.id) === messageId2);
|
|
15618
16264
|
if (!message?.isOwnMessage) return false;
|
|
15619
|
-
if (!
|
|
16265
|
+
if (!isWithinMessageDeleteWindow2(message.timestamp, isGroup, timers)) return false;
|
|
15620
16266
|
const hasAttachmentKey = parsed.some((entry) => entry.attachmentId);
|
|
15621
16267
|
if (!hasAttachmentKey) {
|
|
15622
16268
|
return selectedKeys.size === 1;
|
|
@@ -15785,6 +16431,8 @@ function useActiveChannelMessages({
|
|
|
15785
16431
|
const emitDmDelete = useStore((s) => s.emitDmDelete);
|
|
15786
16432
|
const emitGroupDelete = useStore((s) => s.emitGroupDelete);
|
|
15787
16433
|
const loggedUserDetails = useStore((s) => s.loggedUserDetails);
|
|
16434
|
+
const { settings } = useEffectiveSettingsOptional();
|
|
16435
|
+
const messageTimers = settings.messageTimers;
|
|
15788
16436
|
const scrollContainerRef = useRef(null);
|
|
15789
16437
|
const bottomRef = useRef(null);
|
|
15790
16438
|
const messageListInitializedRef = useRef(false);
|
|
@@ -15903,8 +16551,13 @@ function useActiveChannelMessages({
|
|
|
15903
16551
|
}, []);
|
|
15904
16552
|
const selectedForwardItems = resolveForwardItems(selectedKeys, displayMessages);
|
|
15905
16553
|
const canDeleteForEveryone = useMemo(
|
|
15906
|
-
() => canDeleteSelectionForEveryone(
|
|
15907
|
-
|
|
16554
|
+
() => canDeleteSelectionForEveryone(
|
|
16555
|
+
selectedKeys,
|
|
16556
|
+
displayMessages,
|
|
16557
|
+
!!activeChannel?.isGroup,
|
|
16558
|
+
messageTimers
|
|
16559
|
+
),
|
|
16560
|
+
[selectedKeys, displayMessages, activeChannel?.isGroup, messageTimers]
|
|
15908
16561
|
);
|
|
15909
16562
|
const emitSelectionDelete = useCallback(
|
|
15910
16563
|
(deleteType) => {
|
|
@@ -15912,7 +16565,8 @@ function useActiveChannelMessages({
|
|
|
15912
16565
|
if (deleteType === "everyone" && !canDeleteSelectionForEveryone(
|
|
15913
16566
|
selectedKeys,
|
|
15914
16567
|
displayMessages,
|
|
15915
|
-
!!activeChannel?.isGroup
|
|
16568
|
+
!!activeChannel?.isGroup,
|
|
16569
|
+
messageTimers
|
|
15916
16570
|
)) {
|
|
15917
16571
|
return;
|
|
15918
16572
|
}
|
|
@@ -15953,7 +16607,8 @@ function useActiveChannelMessages({
|
|
|
15953
16607
|
conversationId,
|
|
15954
16608
|
emitGroupDelete,
|
|
15955
16609
|
emitDmDelete,
|
|
15956
|
-
clearSelection
|
|
16610
|
+
clearSelection,
|
|
16611
|
+
messageTimers
|
|
15957
16612
|
]
|
|
15958
16613
|
);
|
|
15959
16614
|
const handleBatchDeleteForMe = useCallback(() => {
|
|
@@ -16291,8 +16946,8 @@ function CalendarDayButton({
|
|
|
16291
16946
|
...props
|
|
16292
16947
|
}) {
|
|
16293
16948
|
const defaultClassNames = getDefaultClassNames();
|
|
16294
|
-
const ref =
|
|
16295
|
-
|
|
16949
|
+
const ref = React3.useRef(null);
|
|
16950
|
+
React3.useEffect(() => {
|
|
16296
16951
|
if (modifiers.focused) ref.current?.focus();
|
|
16297
16952
|
}, [modifiers.focused]);
|
|
16298
16953
|
return /* @__PURE__ */ jsx(
|
|
@@ -17196,7 +17851,6 @@ var getAttachmentType = (file) => {
|
|
|
17196
17851
|
};
|
|
17197
17852
|
|
|
17198
17853
|
// src/chat/channel-message-box/useChannelMessageBox.ts
|
|
17199
|
-
var MAX_ATTACHMENTS = COMPOSER_MAX_ATTACHMENTS;
|
|
17200
17854
|
function useChannelMessageBox({
|
|
17201
17855
|
activeChannel,
|
|
17202
17856
|
conversationId,
|
|
@@ -17210,6 +17864,12 @@ function useChannelMessageBox({
|
|
|
17210
17864
|
conversationId,
|
|
17211
17865
|
onActiveChannelPatch
|
|
17212
17866
|
);
|
|
17867
|
+
const { settings, getAttachmentsGate } = useEffectiveSettingsOptional();
|
|
17868
|
+
const attachmentsGate = getAttachmentsGate();
|
|
17869
|
+
const maxAttachments = settings.attachments.maxAttachmentsPerMessage;
|
|
17870
|
+
const maxFileSizeBytes = settings.attachments.maxFileSizeMB * 1024 * 1024;
|
|
17871
|
+
const allowedMimeTypes = settings.attachments.allowedMimeTypes;
|
|
17872
|
+
const acceptAttribute = buildAcceptFromMimeTypes(allowedMimeTypes);
|
|
17213
17873
|
const [state, setState] = useState({
|
|
17214
17874
|
messageInput: "",
|
|
17215
17875
|
attachments: [],
|
|
@@ -17234,10 +17894,10 @@ function useChannelMessageBox({
|
|
|
17234
17894
|
const composerDisabledReason = conversationId ? composerDisabledByConversation[conversationId] : void 0;
|
|
17235
17895
|
const fileInputRef = useRef(null);
|
|
17236
17896
|
const attachmentsCountRef = useRef(0);
|
|
17237
|
-
|
|
17897
|
+
React3__default.useEffect(() => {
|
|
17238
17898
|
attachmentsCountRef.current = state.attachments.length;
|
|
17239
17899
|
}, [state.attachments.length]);
|
|
17240
|
-
|
|
17900
|
+
React3__default.useEffect(() => {
|
|
17241
17901
|
const draft = {
|
|
17242
17902
|
messageInput: state.messageInput,
|
|
17243
17903
|
attachments: state.attachments
|
|
@@ -17245,7 +17905,7 @@ function useChannelMessageBox({
|
|
|
17245
17905
|
syncComposerRef(draft);
|
|
17246
17906
|
updateConversationDraft(conversationIdRef.current, draft);
|
|
17247
17907
|
}, [state.messageInput, state.attachments, syncComposerRef]);
|
|
17248
|
-
|
|
17908
|
+
React3__default.useEffect(() => {
|
|
17249
17909
|
if (typingTimeoutRef.current) {
|
|
17250
17910
|
clearTimeout(typingTimeoutRef.current);
|
|
17251
17911
|
typingTimeoutRef.current = null;
|
|
@@ -17305,21 +17965,52 @@ function useChannelMessageBox({
|
|
|
17305
17965
|
const handleFileChange = (e) => {
|
|
17306
17966
|
const files = e.target.files ? Array.from(e.target.files) : [];
|
|
17307
17967
|
if (!files.length) return;
|
|
17968
|
+
if (!attachmentsGate.enabled) {
|
|
17969
|
+
updateState({
|
|
17970
|
+
attachmentError: attachmentsGate.disabledReason || "Attachments are disabled by your administrator."
|
|
17971
|
+
});
|
|
17972
|
+
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
17973
|
+
return;
|
|
17974
|
+
}
|
|
17308
17975
|
const currentCount = attachmentsCountRef.current;
|
|
17309
|
-
const remaining =
|
|
17976
|
+
const remaining = maxAttachments - currentCount;
|
|
17310
17977
|
if (remaining <= 0) {
|
|
17311
|
-
updateState({ attachmentError: `Maximum ${
|
|
17978
|
+
updateState({ attachmentError: `Maximum ${maxAttachments} files allowed` });
|
|
17979
|
+
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
17980
|
+
return;
|
|
17981
|
+
}
|
|
17982
|
+
const validFiles = [];
|
|
17983
|
+
const rejectionMessages = [];
|
|
17984
|
+
for (const file of files) {
|
|
17985
|
+
if (!matchesAllowedMimeType(file.type, allowedMimeTypes)) {
|
|
17986
|
+
rejectionMessages.push(`"${file.name}" type is not allowed`);
|
|
17987
|
+
continue;
|
|
17988
|
+
}
|
|
17989
|
+
if (file.size > maxFileSizeBytes) {
|
|
17990
|
+
rejectionMessages.push(
|
|
17991
|
+
`"${file.name}" exceeds ${settings.attachments.maxFileSizeMB} MB (got ${formatFileSizeMB(file.size)})`
|
|
17992
|
+
);
|
|
17993
|
+
continue;
|
|
17994
|
+
}
|
|
17995
|
+
validFiles.push(file);
|
|
17996
|
+
}
|
|
17997
|
+
if (validFiles.length === 0) {
|
|
17998
|
+
updateState({
|
|
17999
|
+
attachmentError: rejectionMessages[0] || "Selected files are not allowed"
|
|
18000
|
+
});
|
|
17312
18001
|
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
17313
18002
|
return;
|
|
17314
18003
|
}
|
|
17315
|
-
if (
|
|
18004
|
+
if (validFiles.length > remaining) {
|
|
17316
18005
|
updateState({
|
|
17317
18006
|
attachmentError: `You can upload only ${remaining} more file${remaining > 1 ? "s" : ""}`
|
|
17318
18007
|
});
|
|
18008
|
+
} else if (rejectionMessages.length > 0) {
|
|
18009
|
+
updateState({ attachmentError: rejectionMessages[0] });
|
|
17319
18010
|
} else {
|
|
17320
18011
|
updateState({ attachmentError: "" });
|
|
17321
18012
|
}
|
|
17322
|
-
const filesToAdd =
|
|
18013
|
+
const filesToAdd = validFiles.slice(0, remaining);
|
|
17323
18014
|
attachmentsCountRef.current = currentCount + filesToAdd.length;
|
|
17324
18015
|
const newAttachments = filesToAdd.map((file) => ({
|
|
17325
18016
|
id: `att-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
@@ -17376,7 +18067,7 @@ function useChannelMessageBox({
|
|
|
17376
18067
|
return {
|
|
17377
18068
|
...prev,
|
|
17378
18069
|
attachments: nextAttachments,
|
|
17379
|
-
attachmentError: nextAttachments.length <
|
|
18070
|
+
attachmentError: nextAttachments.length < maxAttachments ? "" : prev.attachmentError
|
|
17380
18071
|
};
|
|
17381
18072
|
});
|
|
17382
18073
|
};
|
|
@@ -17483,7 +18174,10 @@ function useChannelMessageBox({
|
|
|
17483
18174
|
onlyAdminCanSendMessage,
|
|
17484
18175
|
fileInputRef,
|
|
17485
18176
|
hasUploadingAttachments,
|
|
17486
|
-
maxAttachments
|
|
18177
|
+
maxAttachments,
|
|
18178
|
+
acceptAttribute,
|
|
18179
|
+
attachmentsEnabled: attachmentsGate.enabled,
|
|
18180
|
+
attachmentsDisabledReason: attachmentsGate.disabledReason,
|
|
17487
18181
|
handleInputChange,
|
|
17488
18182
|
handleFileChange,
|
|
17489
18183
|
handleRemoveAttachment,
|
|
@@ -17511,6 +18205,9 @@ var ChannelMessageBoxView = (props) => {
|
|
|
17511
18205
|
fileInputRef,
|
|
17512
18206
|
hasUploadingAttachments,
|
|
17513
18207
|
maxAttachments,
|
|
18208
|
+
acceptAttribute,
|
|
18209
|
+
attachmentsEnabled,
|
|
18210
|
+
attachmentsDisabledReason,
|
|
17514
18211
|
handleInputChange,
|
|
17515
18212
|
handleFileChange,
|
|
17516
18213
|
handleRemoveAttachment,
|
|
@@ -17608,16 +18305,23 @@ var ChannelMessageBoxView = (props) => {
|
|
|
17608
18305
|
),
|
|
17609
18306
|
/* @__PURE__ */ jsxs("div", { className: "flex items-end gap-1.5 p-1.5", children: [
|
|
17610
18307
|
/* @__PURE__ */ jsx(
|
|
17611
|
-
|
|
18308
|
+
AdminPermissionTooltip,
|
|
17612
18309
|
{
|
|
17613
|
-
|
|
17614
|
-
|
|
17615
|
-
|
|
17616
|
-
|
|
17617
|
-
|
|
17618
|
-
|
|
17619
|
-
|
|
17620
|
-
|
|
18310
|
+
disabled: !attachmentsEnabled,
|
|
18311
|
+
message: attachmentsDisabledReason,
|
|
18312
|
+
children: /* @__PURE__ */ jsx(
|
|
18313
|
+
Button,
|
|
18314
|
+
{
|
|
18315
|
+
type: "button",
|
|
18316
|
+
variant: "ghost",
|
|
18317
|
+
size: "icon",
|
|
18318
|
+
className: "shrink-0 size-9 rounded-xl text-(--chat-muted) transition-all hover:bg-(--chat-hover) hover:text-(--chat-text) disabled:opacity-40",
|
|
18319
|
+
onClick: () => attachmentsEnabled && !hasUploadingAttachments && fileInputRef.current?.click(),
|
|
18320
|
+
disabled: !attachmentsEnabled || hasUploadingAttachments,
|
|
18321
|
+
"aria-label": "Attach files",
|
|
18322
|
+
children: /* @__PURE__ */ jsx(Paperclip, { size: 16 })
|
|
18323
|
+
}
|
|
18324
|
+
)
|
|
17621
18325
|
}
|
|
17622
18326
|
),
|
|
17623
18327
|
/* @__PURE__ */ jsx(
|
|
@@ -17627,8 +18331,9 @@ var ChannelMessageBoxView = (props) => {
|
|
|
17627
18331
|
ref: fileInputRef,
|
|
17628
18332
|
className: "hidden",
|
|
17629
18333
|
multiple: true,
|
|
17630
|
-
accept:
|
|
17631
|
-
onChange: handleFileChange
|
|
18334
|
+
accept: acceptAttribute || void 0,
|
|
18335
|
+
onChange: handleFileChange,
|
|
18336
|
+
disabled: !attachmentsEnabled
|
|
17632
18337
|
}
|
|
17633
18338
|
),
|
|
17634
18339
|
/* @__PURE__ */ jsxs(Popover, { children: [
|
|
@@ -17916,6 +18621,7 @@ var ChatPanelAlerts = () => {
|
|
|
17916
18621
|
const globalAppError = useStore((s) => s.globalAppError);
|
|
17917
18622
|
const conversationErrors = useStore((s) => s.conversationErrors);
|
|
17918
18623
|
const clearAppError = useStore((s) => s.clearAppError);
|
|
18624
|
+
const setRateLimitResetAt = useStore((s) => s.setRateLimitResetAt);
|
|
17919
18625
|
const rateLimitResetAt2 = useStore((s) => s.rateLimitResetAt);
|
|
17920
18626
|
const [now, setNow] = useState(() => Date.now());
|
|
17921
18627
|
const conversationAppError = activeConversationId ? conversationErrors[activeConversationId] ?? null : null;
|
|
@@ -17952,7 +18658,7 @@ var ChatPanelAlerts = () => {
|
|
|
17952
18658
|
onDismiss: () => clearAppError(activeConversationId)
|
|
17953
18659
|
});
|
|
17954
18660
|
}
|
|
17955
|
-
if (globalAppError?.message) {
|
|
18661
|
+
if (!activeConversationId && globalAppError?.message) {
|
|
17956
18662
|
push({
|
|
17957
18663
|
id: `global-app-error-${globalAppError.type}`,
|
|
17958
18664
|
type: "error",
|
|
@@ -17967,7 +18673,8 @@ var ChatPanelAlerts = () => {
|
|
|
17967
18673
|
id: "rate-limit",
|
|
17968
18674
|
type: "warning",
|
|
17969
18675
|
message: `Too many requests. Please wait ${seconds}s before trying again.`,
|
|
17970
|
-
icon: AlertCircle
|
|
18676
|
+
icon: AlertCircle,
|
|
18677
|
+
onDismiss: () => setRateLimitResetAt(0)
|
|
17971
18678
|
});
|
|
17972
18679
|
}
|
|
17973
18680
|
if (info?.trim()) {
|
|
@@ -17990,7 +18697,8 @@ var ChatPanelAlerts = () => {
|
|
|
17990
18697
|
onDismissError,
|
|
17991
18698
|
onDismissInfo,
|
|
17992
18699
|
info,
|
|
17993
|
-
clearAppError
|
|
18700
|
+
clearAppError,
|
|
18701
|
+
setRateLimitResetAt
|
|
17994
18702
|
]);
|
|
17995
18703
|
if (alerts.length === 0) return null;
|
|
17996
18704
|
return /* @__PURE__ */ jsx("div", { className: "shrink-0 space-y-2 border-b border-(--chat-border) bg-(--chat-surface) px-4 py-2.5", children: alerts.map((alert) => {
|
|
@@ -18006,16 +18714,20 @@ var ChatPanelAlerts = () => {
|
|
|
18006
18714
|
children: [
|
|
18007
18715
|
/* @__PURE__ */ jsx(Icon, { className: "size-3.5 shrink-0", "aria-hidden": true }),
|
|
18008
18716
|
/* @__PURE__ */ jsx("p", { className: "min-w-0 flex-1 leading-relaxed", children: alert.message }),
|
|
18009
|
-
alert.onDismiss
|
|
18717
|
+
alert.onDismiss ? /* @__PURE__ */ jsx(
|
|
18010
18718
|
"button",
|
|
18011
18719
|
{
|
|
18012
18720
|
type: "button",
|
|
18013
|
-
onClick:
|
|
18721
|
+
onClick: (event) => {
|
|
18722
|
+
event.preventDefault();
|
|
18723
|
+
event.stopPropagation();
|
|
18724
|
+
alert.onDismiss?.();
|
|
18725
|
+
},
|
|
18014
18726
|
className: "shrink-0 rounded-md p-0.5 opacity-70 transition-opacity hover:opacity-100",
|
|
18015
18727
|
"aria-label": "Dismiss",
|
|
18016
18728
|
children: /* @__PURE__ */ jsx(X, { className: "size-3.5" })
|
|
18017
18729
|
}
|
|
18018
|
-
)
|
|
18730
|
+
) : null
|
|
18019
18731
|
]
|
|
18020
18732
|
},
|
|
18021
18733
|
alert.id
|
|
@@ -18543,8 +19255,8 @@ var ChatMain = ({
|
|
|
18543
19255
|
viewportHeight = "full",
|
|
18544
19256
|
viewportClassName
|
|
18545
19257
|
}) => {
|
|
18546
|
-
const clientObj =
|
|
18547
|
-
const uiConfigObj =
|
|
19258
|
+
const clientObj = React3__default.useMemo(() => ({ id: clientId }), [clientId]);
|
|
19259
|
+
const uiConfigObj = React3__default.useMemo(
|
|
18548
19260
|
() => ({
|
|
18549
19261
|
...uiConfig || {},
|
|
18550
19262
|
components: { ...uiConfig?.components, ...components },
|
|
@@ -18915,8 +19627,10 @@ var packageDefaultComponents = {
|
|
|
18915
19627
|
};
|
|
18916
19628
|
|
|
18917
19629
|
// src/index.ts
|
|
19630
|
+
init_settings_types();
|
|
19631
|
+
init_api_service();
|
|
18918
19632
|
var index_default = ChatMain_default;
|
|
18919
19633
|
|
|
18920
|
-
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, LoggedUserSettingsContent_default as LoggedUserSettingsContent, LoggedUserSettingsDialog_default as LoggedUserSettingsDialog, LoggedUserSettingsTrigger_default as LoggedUserSettingsTrigger, 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, buildLoggedUserProfile, buildVersionedApiUrl, capitalizeFirst, clampJumpDate, consumePendingOpenConversation, consumePendingOpenFromPushCache, consumePendingOpenRequest, index_default as default, defaultChatClassNames, defaultChatComponents, defaultChatFeatures, defaultChatLayoutConfig, disablePushOnThisDevice, downloadFile, enablePushOnThisDevice, getChatApiVersions, getChatBaseUrl, getChatQueryParamApis, getChatQueryParams, getChatQueryParamsByApi, getChatSocketUrl, getFirstAndLastNameOneCharacter, getResponsiveWidth, getSocketConfig, getStoredPushToken, installNotificationClickBridge, isEmpty, isPushSupported, mergeChatCustomization, mergeChatLayoutConfig, onForegroundPush, packageDefaultComponents, peekPendingOpenConversation, peekPendingOpenRequest, requestOpenConversation, resolveApiRoot, resolveApiUrl, resolveChatApiKey, resolveConversationIdFromPushData, resolveJumpDateBounds, resolveJumpPreset, resolveJumpStep, resolveSocketUrl, setChatAccessToken, setChatApiVersions, setChatBaseURL, setChatClientId, setChatPushApiVersion, 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 };
|
|
19634
|
+
export { ADMIN_PERMISSION_DENIED_MESSAGE, CALLS_NOT_ALLOWED_BY_PLATFORM_MESSAGE, CALLS_NOT_CONFIGURED_MESSAGE, 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, ChatEffectiveSettingsProvider, ChatLayout_default as ChatLayout, ChatLocaleProvider, ChatMain_default as ChatMain, ChatThemeProvider, ChatViewport, DEFAULT_EFFECTIVE_SETTINGS, DefaultChannelListItem, DefaultChatAvatar, DefaultChatLayout_default as DefaultChatLayout, ForegroundPushBridge, ForwardModalView as ForwardModal, HeaderCallActions_default as HeaderCallActions, LoggedUserDetails_default as LoggedUserDetails, LoggedUserSettingsContent_default as LoggedUserSettingsContent, LoggedUserSettingsDialog_default as LoggedUserSettingsDialog, LoggedUserSettingsTrigger_default as LoggedUserSettingsTrigger, 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, buildLoggedUserProfile, buildVersionedApiUrl, capitalizeFirst, clampJumpDate, consumePendingOpenConversation, consumePendingOpenFromPushCache, consumePendingOpenRequest, index_default as default, defaultChatClassNames, defaultChatComponents, defaultChatFeatures, defaultChatLayoutConfig, disablePushOnThisDevice, downloadFile, enablePushOnThisDevice, fetchEffectiveSettings, getChatApiVersions, getChatBaseUrl, getChatQueryParamApis, getChatQueryParams, getChatQueryParamsByApi, getChatSocketUrl, getFirstAndLastNameOneCharacter, getResponsiveWidth, getSocketConfig, getStoredPushToken, installNotificationClickBridge, isEmpty, isPushSupported, mergeChatCustomization, mergeChatLayoutConfig, onForegroundPush, packageDefaultComponents, peekPendingOpenConversation, peekPendingOpenRequest, requestOpenConversation, resolveApiRoot, resolveApiUrl, resolveChatApiKey, resolveConversationIdFromPushData, resolveJumpDateBounds, resolveJumpPreset, resolveJumpStep, resolveSocketUrl, setChatAccessToken, setChatApiVersions, setChatBaseURL, setChatClientId, setChatPushApiVersion, 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, useEffectiveSettings, useEffectiveSettingsOptional, usePushNotifications };
|
|
18921
19635
|
//# sourceMappingURL=index.mjs.map
|
|
18922
19636
|
//# sourceMappingURL=index.mjs.map
|