@realtimexsco/live-chat 1.4.11 → 1.4.12
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 +6 -6
- package/dist/index.cjs +1107 -438
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +139 -66
- package/dist/index.d.ts +139 -66
- package/dist/index.mjs +838 -172
- package/dist/index.mjs.map +1 -1
- 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';
|
|
@@ -1162,6 +1162,7 @@ function resolveChatApiKey(url) {
|
|
|
1162
1162
|
}
|
|
1163
1163
|
if (path.includes("/message/search-messages")) return "searchMessages";
|
|
1164
1164
|
if (path.includes("/message/searched-message/context")) return "searchMessagesContext";
|
|
1165
|
+
if (path.includes("/settings/effective")) return "effectiveSettings";
|
|
1165
1166
|
if (path.includes("/conversation/group/create")) return "createGroup";
|
|
1166
1167
|
if (path.includes("/conversation/group/permission/update")) return "updateGroupPermissions";
|
|
1167
1168
|
if (path.includes("/conversation/group/information/update")) return "updateGroupInfo";
|
|
@@ -1205,7 +1206,8 @@ var init_query_params = __esm({
|
|
|
1205
1206
|
"pinnedMessages",
|
|
1206
1207
|
"starredMessages",
|
|
1207
1208
|
"searchMessages",
|
|
1208
|
-
"searchMessagesContext"
|
|
1209
|
+
"searchMessagesContext",
|
|
1210
|
+
"effectiveSettings"
|
|
1209
1211
|
];
|
|
1210
1212
|
CHAT_API_KEYS = [
|
|
1211
1213
|
"all",
|
|
@@ -1230,8 +1232,8 @@ var init_api_version = __esm({
|
|
|
1230
1232
|
"src/services/api/api-version.ts"() {
|
|
1231
1233
|
init_client();
|
|
1232
1234
|
DEFAULT_VERSIONS = {
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
+
v1: "v1",
|
|
1236
|
+
v2: "v2"
|
|
1235
1237
|
};
|
|
1236
1238
|
apiVersions = { ...DEFAULT_VERSIONS };
|
|
1237
1239
|
normalizeApiVersion = (version) => {
|
|
@@ -1250,7 +1252,7 @@ var init_api_version = __esm({
|
|
|
1250
1252
|
buildVersionedApiUrl = (path, options) => {
|
|
1251
1253
|
const root = resolveApiRoot(options?.baseUrl);
|
|
1252
1254
|
const version = normalizeApiVersion(
|
|
1253
|
-
options?.version ?? (options?.service ? apiVersions[options.service] : apiVersions.
|
|
1255
|
+
options?.version ?? (options?.service ? apiVersions[options.service] : apiVersions.v1)
|
|
1254
1256
|
);
|
|
1255
1257
|
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
1256
1258
|
if (!root) {
|
|
@@ -1260,23 +1262,23 @@ var init_api_version = __esm({
|
|
|
1260
1262
|
};
|
|
1261
1263
|
setChatApiVersions = (config) => {
|
|
1262
1264
|
if (!config) return;
|
|
1263
|
-
if (config.
|
|
1264
|
-
apiVersions.
|
|
1265
|
+
if (config.v1) {
|
|
1266
|
+
apiVersions.v1 = normalizeApiVersion(config.v1);
|
|
1265
1267
|
}
|
|
1266
|
-
if (config.
|
|
1267
|
-
apiVersions.
|
|
1268
|
+
if (config.v2) {
|
|
1269
|
+
apiVersions.v2 = normalizeApiVersion(config.v2);
|
|
1268
1270
|
}
|
|
1269
1271
|
};
|
|
1270
1272
|
getChatApiVersions = () => ({
|
|
1271
1273
|
...apiVersions
|
|
1272
1274
|
});
|
|
1273
1275
|
setChatPushApiVersion = (version) => {
|
|
1274
|
-
apiVersions.
|
|
1276
|
+
apiVersions.v2 = normalizeApiVersion(version);
|
|
1275
1277
|
};
|
|
1276
1278
|
syncDefaultApiVersionFromBaseUrl = (baseUrl) => {
|
|
1277
1279
|
const match = String(baseUrl || "").trim().match(/\/(v\d+)\/?$/i);
|
|
1278
1280
|
if (match?.[1]) {
|
|
1279
|
-
apiVersions.
|
|
1281
|
+
apiVersions.v1 = normalizeApiVersion(match[1]);
|
|
1280
1282
|
}
|
|
1281
1283
|
};
|
|
1282
1284
|
}
|
|
@@ -1421,6 +1423,9 @@ var init_api_constants = __esm({
|
|
|
1421
1423
|
SEARCH_MESSAGES: "/message/search-messages",
|
|
1422
1424
|
SEARCH_MESSAGES_CONTEXT: (messageId2) => `/message/searched-message/context?messageId=${messageId2}`,
|
|
1423
1425
|
BLOCK_UNBLOCK_USER: "/user/block-unblock"
|
|
1426
|
+
},
|
|
1427
|
+
SETTINGS: {
|
|
1428
|
+
PERMISSIONS: "/settings/effective"
|
|
1424
1429
|
}
|
|
1425
1430
|
};
|
|
1426
1431
|
}
|
|
@@ -1457,13 +1462,11 @@ var init_auth_api = __esm({
|
|
|
1457
1462
|
});
|
|
1458
1463
|
|
|
1459
1464
|
// src/constants/chat.constants.ts
|
|
1460
|
-
var DEFAULT_MESSAGES_LIMIT, DEFAULT_CONVERSATIONS_LIMIT,
|
|
1465
|
+
var DEFAULT_MESSAGES_LIMIT, DEFAULT_CONVERSATIONS_LIMIT, MAX_ATTACHMENT_CAPTION_LENGTH, ATTACHMENT_FILENAME_TIMESTAMP_LENGTH;
|
|
1461
1466
|
var init_chat_constants = __esm({
|
|
1462
1467
|
"src/constants/chat.constants.ts"() {
|
|
1463
1468
|
DEFAULT_MESSAGES_LIMIT = 20;
|
|
1464
1469
|
DEFAULT_CONVERSATIONS_LIMIT = 20;
|
|
1465
|
-
DM_EDIT_WINDOW_MS = 5 * 60 * 1e3;
|
|
1466
|
-
GROUP_EDIT_WINDOW_MS = 10 * 60 * 1e3;
|
|
1467
1470
|
MAX_ATTACHMENT_CAPTION_LENGTH = 100;
|
|
1468
1471
|
ATTACHMENT_FILENAME_TIMESTAMP_LENGTH = 13;
|
|
1469
1472
|
}
|
|
@@ -1666,6 +1669,206 @@ var init_uploads_api = __esm({
|
|
|
1666
1669
|
}
|
|
1667
1670
|
});
|
|
1668
1671
|
|
|
1672
|
+
// src/types/settings.types.ts
|
|
1673
|
+
var DEFAULT_EFFECTIVE_SETTINGS, ADMIN_PERMISSION_DENIED_MESSAGE, CALLS_NOT_CONFIGURED_MESSAGE;
|
|
1674
|
+
var init_settings_types = __esm({
|
|
1675
|
+
"src/types/settings.types.ts"() {
|
|
1676
|
+
DEFAULT_EFFECTIVE_SETTINGS = {
|
|
1677
|
+
pushNotificationEnabled: true,
|
|
1678
|
+
videoCallEnabled: true,
|
|
1679
|
+
audioCallEnabled: true,
|
|
1680
|
+
blockUsersEnabled: true,
|
|
1681
|
+
calls: {
|
|
1682
|
+
enabled: true,
|
|
1683
|
+
configured: true
|
|
1684
|
+
},
|
|
1685
|
+
groupPolicy: {
|
|
1686
|
+
defaults: {
|
|
1687
|
+
onlyAdminCanSendMessage: false,
|
|
1688
|
+
onlyAdminCanEditInfo: false,
|
|
1689
|
+
senderCanEditMessage: true,
|
|
1690
|
+
allowMemberAdd: true,
|
|
1691
|
+
allowMemberRemove: false,
|
|
1692
|
+
moderationEnabled: false
|
|
1693
|
+
},
|
|
1694
|
+
locked: []
|
|
1695
|
+
},
|
|
1696
|
+
messageTimers: {
|
|
1697
|
+
dmEditMinutes: 5,
|
|
1698
|
+
dmDeleteMinutes: 5,
|
|
1699
|
+
groupEditMinutes: 10,
|
|
1700
|
+
groupDeleteMinutes: 10
|
|
1701
|
+
},
|
|
1702
|
+
attachments: {
|
|
1703
|
+
enabled: true,
|
|
1704
|
+
maxFileSizeMB: 10,
|
|
1705
|
+
allowedMimeTypes: ["image/*", "video/*", "audio/*", "application/pdf"],
|
|
1706
|
+
maxAttachmentsPerMessage: 10
|
|
1707
|
+
},
|
|
1708
|
+
maxAdminsPerGroup: 5,
|
|
1709
|
+
maxParticipantsPerGroup: 100,
|
|
1710
|
+
maxPinnedMessagesPerConversation: 10,
|
|
1711
|
+
groupCreationEnabled: true
|
|
1712
|
+
};
|
|
1713
|
+
ADMIN_PERMISSION_DENIED_MESSAGE = "This feature is disabled by your administrator.";
|
|
1714
|
+
CALLS_NOT_CONFIGURED_MESSAGE = "Calls are not configured. Please contact your administrator.";
|
|
1715
|
+
}
|
|
1716
|
+
});
|
|
1717
|
+
|
|
1718
|
+
// src/services/api/settings.api.ts
|
|
1719
|
+
function asBoolean(value, fallback) {
|
|
1720
|
+
return typeof value === "boolean" ? value : fallback;
|
|
1721
|
+
}
|
|
1722
|
+
function asPositiveNumber(value, fallback) {
|
|
1723
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
|
|
1724
|
+
}
|
|
1725
|
+
function asStringArray(value, fallback) {
|
|
1726
|
+
if (!Array.isArray(value)) return fallback;
|
|
1727
|
+
const next = value.filter((item) => typeof item === "string");
|
|
1728
|
+
return next.length > 0 ? next : fallback;
|
|
1729
|
+
}
|
|
1730
|
+
function normalizeGroupPermissions(value, fallback) {
|
|
1731
|
+
if (!value || typeof value !== "object") return { ...fallback };
|
|
1732
|
+
const raw = value;
|
|
1733
|
+
return {
|
|
1734
|
+
onlyAdminCanSendMessage: asBoolean(
|
|
1735
|
+
raw.onlyAdminCanSendMessage,
|
|
1736
|
+
fallback.onlyAdminCanSendMessage
|
|
1737
|
+
),
|
|
1738
|
+
onlyAdminCanEditInfo: asBoolean(
|
|
1739
|
+
raw.onlyAdminCanEditInfo,
|
|
1740
|
+
fallback.onlyAdminCanEditInfo
|
|
1741
|
+
),
|
|
1742
|
+
senderCanEditMessage: asBoolean(
|
|
1743
|
+
raw.senderCanEditMessage,
|
|
1744
|
+
fallback.senderCanEditMessage
|
|
1745
|
+
),
|
|
1746
|
+
allowMemberAdd: asBoolean(raw.allowMemberAdd, fallback.allowMemberAdd),
|
|
1747
|
+
allowMemberRemove: asBoolean(
|
|
1748
|
+
raw.allowMemberRemove,
|
|
1749
|
+
fallback.allowMemberRemove
|
|
1750
|
+
),
|
|
1751
|
+
moderationEnabled: asBoolean(
|
|
1752
|
+
raw.moderationEnabled,
|
|
1753
|
+
fallback.moderationEnabled
|
|
1754
|
+
)
|
|
1755
|
+
};
|
|
1756
|
+
}
|
|
1757
|
+
function normalizeCalls(value, fallback) {
|
|
1758
|
+
if (!value || typeof value !== "object") return { ...fallback };
|
|
1759
|
+
const raw = value;
|
|
1760
|
+
return {
|
|
1761
|
+
enabled: asBoolean(raw.enabled, fallback.enabled),
|
|
1762
|
+
configured: asBoolean(raw.configured, fallback.configured)
|
|
1763
|
+
};
|
|
1764
|
+
}
|
|
1765
|
+
function normalizeGroupPolicy(value, fallback) {
|
|
1766
|
+
if (!value || typeof value !== "object") {
|
|
1767
|
+
return {
|
|
1768
|
+
defaults: { ...fallback.defaults },
|
|
1769
|
+
locked: [...fallback.locked]
|
|
1770
|
+
};
|
|
1771
|
+
}
|
|
1772
|
+
const raw = value;
|
|
1773
|
+
return {
|
|
1774
|
+
defaults: normalizeGroupPermissions(raw.defaults, fallback.defaults),
|
|
1775
|
+
locked: asStringArray(raw.locked, fallback.locked)
|
|
1776
|
+
};
|
|
1777
|
+
}
|
|
1778
|
+
function normalizeMessageTimers(value, fallback) {
|
|
1779
|
+
if (!value || typeof value !== "object") return { ...fallback };
|
|
1780
|
+
const raw = value;
|
|
1781
|
+
return {
|
|
1782
|
+
dmEditMinutes: asPositiveNumber(raw.dmEditMinutes, fallback.dmEditMinutes),
|
|
1783
|
+
dmDeleteMinutes: asPositiveNumber(
|
|
1784
|
+
raw.dmDeleteMinutes,
|
|
1785
|
+
fallback.dmDeleteMinutes
|
|
1786
|
+
),
|
|
1787
|
+
groupEditMinutes: asPositiveNumber(
|
|
1788
|
+
raw.groupEditMinutes,
|
|
1789
|
+
fallback.groupEditMinutes
|
|
1790
|
+
),
|
|
1791
|
+
groupDeleteMinutes: asPositiveNumber(
|
|
1792
|
+
raw.groupDeleteMinutes,
|
|
1793
|
+
fallback.groupDeleteMinutes
|
|
1794
|
+
)
|
|
1795
|
+
};
|
|
1796
|
+
}
|
|
1797
|
+
function normalizeAttachments(value, fallback) {
|
|
1798
|
+
if (!value || typeof value !== "object") return { ...fallback };
|
|
1799
|
+
const raw = value;
|
|
1800
|
+
return {
|
|
1801
|
+
enabled: asBoolean(raw.enabled, fallback.enabled),
|
|
1802
|
+
maxFileSizeMB: asPositiveNumber(raw.maxFileSizeMB, fallback.maxFileSizeMB),
|
|
1803
|
+
allowedMimeTypes: asStringArray(
|
|
1804
|
+
raw.allowedMimeTypes,
|
|
1805
|
+
fallback.allowedMimeTypes
|
|
1806
|
+
),
|
|
1807
|
+
maxAttachmentsPerMessage: asPositiveNumber(
|
|
1808
|
+
raw.maxAttachmentsPerMessage,
|
|
1809
|
+
fallback.maxAttachmentsPerMessage
|
|
1810
|
+
)
|
|
1811
|
+
};
|
|
1812
|
+
}
|
|
1813
|
+
function normalizeEffectiveSettings(raw) {
|
|
1814
|
+
const payload = raw && typeof raw === "object" ? raw.data ?? raw : null;
|
|
1815
|
+
const source = payload && typeof payload === "object" ? payload : {};
|
|
1816
|
+
const defaults = DEFAULT_EFFECTIVE_SETTINGS;
|
|
1817
|
+
return {
|
|
1818
|
+
pushNotificationEnabled: asBoolean(
|
|
1819
|
+
source.pushNotificationEnabled,
|
|
1820
|
+
defaults.pushNotificationEnabled
|
|
1821
|
+
),
|
|
1822
|
+
videoCallEnabled: asBoolean(
|
|
1823
|
+
source.videoCallEnabled,
|
|
1824
|
+
defaults.videoCallEnabled
|
|
1825
|
+
),
|
|
1826
|
+
audioCallEnabled: asBoolean(
|
|
1827
|
+
source.audioCallEnabled,
|
|
1828
|
+
defaults.audioCallEnabled
|
|
1829
|
+
),
|
|
1830
|
+
blockUsersEnabled: asBoolean(
|
|
1831
|
+
source.blockUsersEnabled,
|
|
1832
|
+
defaults.blockUsersEnabled
|
|
1833
|
+
),
|
|
1834
|
+
calls: normalizeCalls(source.calls, defaults.calls),
|
|
1835
|
+
groupPolicy: normalizeGroupPolicy(source.groupPolicy, defaults.groupPolicy),
|
|
1836
|
+
messageTimers: normalizeMessageTimers(
|
|
1837
|
+
source.messageTimers,
|
|
1838
|
+
defaults.messageTimers
|
|
1839
|
+
),
|
|
1840
|
+
attachments: normalizeAttachments(source.attachments, defaults.attachments),
|
|
1841
|
+
maxAdminsPerGroup: asPositiveNumber(
|
|
1842
|
+
source.maxAdminsPerGroup,
|
|
1843
|
+
defaults.maxAdminsPerGroup
|
|
1844
|
+
),
|
|
1845
|
+
maxParticipantsPerGroup: asPositiveNumber(
|
|
1846
|
+
source.maxParticipantsPerGroup,
|
|
1847
|
+
defaults.maxParticipantsPerGroup
|
|
1848
|
+
),
|
|
1849
|
+
maxPinnedMessagesPerConversation: asPositiveNumber(
|
|
1850
|
+
source.maxPinnedMessagesPerConversation,
|
|
1851
|
+
defaults.maxPinnedMessagesPerConversation
|
|
1852
|
+
),
|
|
1853
|
+
groupCreationEnabled: asBoolean(
|
|
1854
|
+
source.groupCreationEnabled,
|
|
1855
|
+
defaults.groupCreationEnabled
|
|
1856
|
+
)
|
|
1857
|
+
};
|
|
1858
|
+
}
|
|
1859
|
+
var fetchEffectiveSettings;
|
|
1860
|
+
var init_settings_api = __esm({
|
|
1861
|
+
"src/services/api/settings.api.ts"() {
|
|
1862
|
+
init_api_constants();
|
|
1863
|
+
init_client();
|
|
1864
|
+
init_settings_types();
|
|
1865
|
+
fetchEffectiveSettings = async () => {
|
|
1866
|
+
const response = await apiClient.get(API_ENDPOINTS.SETTINGS.PERMISSIONS);
|
|
1867
|
+
return normalizeEffectiveSettings(response.data);
|
|
1868
|
+
};
|
|
1869
|
+
}
|
|
1870
|
+
});
|
|
1871
|
+
|
|
1669
1872
|
// src/services/api/index.ts
|
|
1670
1873
|
var init_api = __esm({
|
|
1671
1874
|
"src/services/api/index.ts"() {
|
|
@@ -1674,6 +1877,7 @@ var init_api = __esm({
|
|
|
1674
1877
|
init_messages_api();
|
|
1675
1878
|
init_groups_api();
|
|
1676
1879
|
init_uploads_api();
|
|
1880
|
+
init_settings_api();
|
|
1677
1881
|
}
|
|
1678
1882
|
});
|
|
1679
1883
|
|
|
@@ -4505,6 +4709,143 @@ var useChatCustomizationOptional = () => {
|
|
|
4505
4709
|
};
|
|
4506
4710
|
var useChatFeatures = () => useChatCustomization().features;
|
|
4507
4711
|
var useChatFeaturesOptional = () => useChatCustomizationOptional().features;
|
|
4712
|
+
|
|
4713
|
+
// src/context/ChatEffectiveSettingsContext.tsx
|
|
4714
|
+
init_settings_api();
|
|
4715
|
+
init_settings_types();
|
|
4716
|
+
var ChatEffectiveSettingsContext = createContext(null);
|
|
4717
|
+
function buildCallGate(settings, featureEnabled) {
|
|
4718
|
+
if (!settings.calls.configured) {
|
|
4719
|
+
return {
|
|
4720
|
+
visible: true,
|
|
4721
|
+
enabled: false,
|
|
4722
|
+
disabledReason: CALLS_NOT_CONFIGURED_MESSAGE
|
|
4723
|
+
};
|
|
4724
|
+
}
|
|
4725
|
+
if (!settings.calls.enabled) {
|
|
4726
|
+
return {
|
|
4727
|
+
visible: true,
|
|
4728
|
+
enabled: false,
|
|
4729
|
+
disabledReason: ADMIN_PERMISSION_DENIED_MESSAGE
|
|
4730
|
+
};
|
|
4731
|
+
}
|
|
4732
|
+
if (!featureEnabled) {
|
|
4733
|
+
return {
|
|
4734
|
+
visible: true,
|
|
4735
|
+
enabled: false,
|
|
4736
|
+
disabledReason: ADMIN_PERMISSION_DENIED_MESSAGE
|
|
4737
|
+
};
|
|
4738
|
+
}
|
|
4739
|
+
return { visible: true, enabled: true, disabledReason: null };
|
|
4740
|
+
}
|
|
4741
|
+
function ChatEffectiveSettingsProvider({
|
|
4742
|
+
children,
|
|
4743
|
+
enabled = true
|
|
4744
|
+
}) {
|
|
4745
|
+
const [settings, setSettings] = useState(
|
|
4746
|
+
DEFAULT_EFFECTIVE_SETTINGS
|
|
4747
|
+
);
|
|
4748
|
+
const [loading, setLoading] = useState(true);
|
|
4749
|
+
const [error, setError] = useState(null);
|
|
4750
|
+
const refresh = useCallback(async () => {
|
|
4751
|
+
if (!enabled) {
|
|
4752
|
+
setLoading(false);
|
|
4753
|
+
return;
|
|
4754
|
+
}
|
|
4755
|
+
setLoading(true);
|
|
4756
|
+
try {
|
|
4757
|
+
const next = await fetchEffectiveSettings();
|
|
4758
|
+
setSettings(next);
|
|
4759
|
+
setError(null);
|
|
4760
|
+
} catch (err) {
|
|
4761
|
+
console.error("Failed to fetch effective settings:", err);
|
|
4762
|
+
setError(
|
|
4763
|
+
err instanceof Error ? err.message : "Could not load chat permissions"
|
|
4764
|
+
);
|
|
4765
|
+
setSettings(DEFAULT_EFFECTIVE_SETTINGS);
|
|
4766
|
+
} finally {
|
|
4767
|
+
setLoading(false);
|
|
4768
|
+
}
|
|
4769
|
+
}, [enabled]);
|
|
4770
|
+
useEffect(() => {
|
|
4771
|
+
void refresh();
|
|
4772
|
+
}, [refresh]);
|
|
4773
|
+
const value = useMemo(() => {
|
|
4774
|
+
const isGroupPermissionLocked = (key) => settings.groupPolicy.locked.includes(key);
|
|
4775
|
+
return {
|
|
4776
|
+
settings,
|
|
4777
|
+
loading,
|
|
4778
|
+
error,
|
|
4779
|
+
refresh,
|
|
4780
|
+
isGroupPermissionLocked,
|
|
4781
|
+
getAudioCallGate: () => buildCallGate(settings, settings.audioCallEnabled),
|
|
4782
|
+
getVideoCallGate: () => buildCallGate(settings, settings.videoCallEnabled),
|
|
4783
|
+
getPushNotificationGate: () => ({
|
|
4784
|
+
visible: true,
|
|
4785
|
+
enabled: settings.pushNotificationEnabled,
|
|
4786
|
+
disabledReason: settings.pushNotificationEnabled ? null : ADMIN_PERMISSION_DENIED_MESSAGE
|
|
4787
|
+
}),
|
|
4788
|
+
getBlockUsersGate: () => ({
|
|
4789
|
+
visible: true,
|
|
4790
|
+
enabled: settings.blockUsersEnabled,
|
|
4791
|
+
disabledReason: settings.blockUsersEnabled ? null : ADMIN_PERMISSION_DENIED_MESSAGE
|
|
4792
|
+
}),
|
|
4793
|
+
getAttachmentsGate: () => ({
|
|
4794
|
+
visible: true,
|
|
4795
|
+
enabled: settings.attachments.enabled,
|
|
4796
|
+
disabledReason: settings.attachments.enabled ? null : ADMIN_PERMISSION_DENIED_MESSAGE
|
|
4797
|
+
}),
|
|
4798
|
+
getGroupCreationGate: () => ({
|
|
4799
|
+
visible: true,
|
|
4800
|
+
enabled: settings.groupCreationEnabled,
|
|
4801
|
+
disabledReason: settings.groupCreationEnabled ? null : ADMIN_PERMISSION_DENIED_MESSAGE
|
|
4802
|
+
})
|
|
4803
|
+
};
|
|
4804
|
+
}, [settings, loading, error, refresh]);
|
|
4805
|
+
return /* @__PURE__ */ jsx(ChatEffectiveSettingsContext.Provider, { value, children });
|
|
4806
|
+
}
|
|
4807
|
+
function useEffectiveSettings() {
|
|
4808
|
+
const ctx = useContext(ChatEffectiveSettingsContext);
|
|
4809
|
+
if (!ctx) {
|
|
4810
|
+
throw new Error(
|
|
4811
|
+
"useEffectiveSettings must be used within ChatEffectiveSettingsProvider"
|
|
4812
|
+
);
|
|
4813
|
+
}
|
|
4814
|
+
return ctx;
|
|
4815
|
+
}
|
|
4816
|
+
function useEffectiveSettingsOptional() {
|
|
4817
|
+
const ctx = useContext(ChatEffectiveSettingsContext);
|
|
4818
|
+
if (ctx) return ctx;
|
|
4819
|
+
return {
|
|
4820
|
+
settings: DEFAULT_EFFECTIVE_SETTINGS,
|
|
4821
|
+
loading: false,
|
|
4822
|
+
error: null,
|
|
4823
|
+
refresh: async () => void 0,
|
|
4824
|
+
isGroupPermissionLocked: () => false,
|
|
4825
|
+
getAudioCallGate: () => buildCallGate(DEFAULT_EFFECTIVE_SETTINGS, true),
|
|
4826
|
+
getVideoCallGate: () => buildCallGate(DEFAULT_EFFECTIVE_SETTINGS, true),
|
|
4827
|
+
getPushNotificationGate: () => ({
|
|
4828
|
+
visible: true,
|
|
4829
|
+
enabled: true,
|
|
4830
|
+
disabledReason: null
|
|
4831
|
+
}),
|
|
4832
|
+
getBlockUsersGate: () => ({
|
|
4833
|
+
visible: true,
|
|
4834
|
+
enabled: true,
|
|
4835
|
+
disabledReason: null
|
|
4836
|
+
}),
|
|
4837
|
+
getAttachmentsGate: () => ({
|
|
4838
|
+
visible: true,
|
|
4839
|
+
enabled: true,
|
|
4840
|
+
disabledReason: null
|
|
4841
|
+
}),
|
|
4842
|
+
getGroupCreationGate: () => ({
|
|
4843
|
+
visible: true,
|
|
4844
|
+
enabled: true,
|
|
4845
|
+
disabledReason: null
|
|
4846
|
+
})
|
|
4847
|
+
};
|
|
4848
|
+
}
|
|
4508
4849
|
var ChatContext = createContext(void 0);
|
|
4509
4850
|
var useChatContext = () => {
|
|
4510
4851
|
const context = useContext(ChatContext);
|
|
@@ -4544,7 +4885,7 @@ var Chat = ({
|
|
|
4544
4885
|
const status = useStore((s) => s.status);
|
|
4545
4886
|
const error = useStore((s) => s.error);
|
|
4546
4887
|
useChatSync();
|
|
4547
|
-
|
|
4888
|
+
React3__default.useEffect(() => {
|
|
4548
4889
|
const clientId = client?.id;
|
|
4549
4890
|
const initializeChat = async () => {
|
|
4550
4891
|
if (!clientId || !loggedUserDetails) return;
|
|
@@ -4634,28 +4975,28 @@ var Chat = ({
|
|
|
4634
4975
|
queryParamApis: queryParamApis ?? ["get"],
|
|
4635
4976
|
queryParamsByApi: queryParamsByApi ?? {}
|
|
4636
4977
|
});
|
|
4637
|
-
|
|
4978
|
+
React3__default.useEffect(() => {
|
|
4638
4979
|
setChatQueryParams(queryParams);
|
|
4639
4980
|
setChatQueryParamApis(queryParamApis);
|
|
4640
4981
|
setChatQueryParamsByApi(queryParamsByApi);
|
|
4641
4982
|
}, [queryConfigKey]);
|
|
4642
|
-
|
|
4983
|
+
React3__default.useEffect(() => {
|
|
4643
4984
|
if (lastDM && onMessageReceived) {
|
|
4644
4985
|
onMessageReceived(lastDM);
|
|
4645
4986
|
}
|
|
4646
4987
|
}, [lastDM, onMessageReceived]);
|
|
4647
|
-
|
|
4988
|
+
React3__default.useEffect(() => {
|
|
4648
4989
|
if (status === "connected" && onSocketConnected) {
|
|
4649
4990
|
const socketId = useStore.getState().socketId;
|
|
4650
4991
|
if (socketId) onSocketConnected(socketId);
|
|
4651
4992
|
}
|
|
4652
4993
|
}, [status, onSocketConnected]);
|
|
4653
|
-
|
|
4994
|
+
React3__default.useEffect(() => {
|
|
4654
4995
|
if (status === "error" && error && onSocketError) {
|
|
4655
4996
|
onSocketError(error);
|
|
4656
4997
|
}
|
|
4657
4998
|
}, [status, error, onSocketError]);
|
|
4658
|
-
const contextValue =
|
|
4999
|
+
const contextValue = React3__default.useMemo(
|
|
4659
5000
|
() => ({
|
|
4660
5001
|
onSendMessage,
|
|
4661
5002
|
client,
|
|
@@ -4675,7 +5016,7 @@ var Chat = ({
|
|
|
4675
5016
|
messagesData
|
|
4676
5017
|
]
|
|
4677
5018
|
);
|
|
4678
|
-
const customization =
|
|
5019
|
+
const customization = React3__default.useMemo(
|
|
4679
5020
|
() => ({
|
|
4680
5021
|
components: uiConfig.components,
|
|
4681
5022
|
classNames: uiConfig.classNames,
|
|
@@ -4683,7 +5024,7 @@ var Chat = ({
|
|
|
4683
5024
|
}),
|
|
4684
5025
|
[uiConfig.components, uiConfig.classNames, uiConfig.features]
|
|
4685
5026
|
);
|
|
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..." }) }) }) }) });
|
|
5027
|
+
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
5028
|
};
|
|
4688
5029
|
|
|
4689
5030
|
// src/hooks/useChatController.ts
|
|
@@ -6086,6 +6427,8 @@ function useCreateChatDialog({
|
|
|
6086
6427
|
const fetchAllUsers = useStore((storeState) => storeState.fetchAllUsers);
|
|
6087
6428
|
const accessToken = useStore((storeState) => storeState.accessToken);
|
|
6088
6429
|
const fetchConversations2 = useStore((storeState) => storeState.fetchConversations);
|
|
6430
|
+
const { settings } = useEffectiveSettingsOptional();
|
|
6431
|
+
const maxParticipants = settings.maxParticipantsPerGroup;
|
|
6089
6432
|
const fileInputRef = useRef(null);
|
|
6090
6433
|
useEffect(() => {
|
|
6091
6434
|
if (accessToken) {
|
|
@@ -6099,9 +6442,18 @@ function useCreateChatDialog({
|
|
|
6099
6442
|
setState((prev) => {
|
|
6100
6443
|
const memberId = String(member._id);
|
|
6101
6444
|
const exists = prev.selectedMembers.some((m) => String(m._id) === memberId);
|
|
6445
|
+
if (exists) {
|
|
6446
|
+
return {
|
|
6447
|
+
...prev,
|
|
6448
|
+
selectedMembers: prev.selectedMembers.filter((m) => String(m._id) !== memberId)
|
|
6449
|
+
};
|
|
6450
|
+
}
|
|
6451
|
+
if (prev.selectedMembers.length + 1 >= maxParticipants) {
|
|
6452
|
+
return prev;
|
|
6453
|
+
}
|
|
6102
6454
|
return {
|
|
6103
6455
|
...prev,
|
|
6104
|
-
selectedMembers:
|
|
6456
|
+
selectedMembers: [...prev.selectedMembers, member]
|
|
6105
6457
|
};
|
|
6106
6458
|
});
|
|
6107
6459
|
};
|
|
@@ -6485,8 +6837,25 @@ function GroupCreateTab({
|
|
|
6485
6837
|
) })
|
|
6486
6838
|
] });
|
|
6487
6839
|
}
|
|
6840
|
+
function AdminPermissionTooltip({
|
|
6841
|
+
disabled,
|
|
6842
|
+
message,
|
|
6843
|
+
side = "top",
|
|
6844
|
+
className,
|
|
6845
|
+
children
|
|
6846
|
+
}) {
|
|
6847
|
+
if (!disabled || !message) {
|
|
6848
|
+
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
6849
|
+
}
|
|
6850
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
6851
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx("span", { className: cn("inline-flex", className), children }) }),
|
|
6852
|
+
/* @__PURE__ */ jsx(TooltipContent, { side, className: "max-w-[240px] text-xs", children: message })
|
|
6853
|
+
] });
|
|
6854
|
+
}
|
|
6488
6855
|
var CreateChatDialog = (props) => {
|
|
6489
6856
|
const { isCreateModalOpen = false, setIsCreateModalOpen } = props;
|
|
6857
|
+
const { getGroupCreationGate } = useEffectiveSettingsOptional();
|
|
6858
|
+
const groupCreationGate = getGroupCreationGate();
|
|
6490
6859
|
const {
|
|
6491
6860
|
state,
|
|
6492
6861
|
updateState,
|
|
@@ -6540,24 +6909,39 @@ var CreateChatDialog = (props) => {
|
|
|
6540
6909
|
) })
|
|
6541
6910
|
] }),
|
|
6542
6911
|
/* @__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",
|
|
6912
|
+
{ id: "dm", label: "Message", icon: MessageCircle, disabled: false, reason: null },
|
|
6547
6913
|
{
|
|
6548
|
-
|
|
6549
|
-
|
|
6550
|
-
|
|
6551
|
-
|
|
6552
|
-
|
|
6553
|
-
|
|
6554
|
-
|
|
6555
|
-
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
|
|
6560
|
-
|
|
6914
|
+
id: "group",
|
|
6915
|
+
label: "New group",
|
|
6916
|
+
icon: Users,
|
|
6917
|
+
disabled: !groupCreationGate.enabled,
|
|
6918
|
+
reason: groupCreationGate.disabledReason
|
|
6919
|
+
}
|
|
6920
|
+
].map(({ id, label, icon: Icon, disabled, reason }) => {
|
|
6921
|
+
const tabButton = /* @__PURE__ */ jsxs(
|
|
6922
|
+
"button",
|
|
6923
|
+
{
|
|
6924
|
+
type: "button",
|
|
6925
|
+
disabled,
|
|
6926
|
+
onClick: () => {
|
|
6927
|
+
if (disabled) return;
|
|
6928
|
+
updateState({ activeTab: id });
|
|
6929
|
+
},
|
|
6930
|
+
className: cn(
|
|
6931
|
+
"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",
|
|
6932
|
+
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)"
|
|
6933
|
+
),
|
|
6934
|
+
children: [
|
|
6935
|
+
/* @__PURE__ */ jsx(Icon, { className: "size-4" }),
|
|
6936
|
+
label
|
|
6937
|
+
]
|
|
6938
|
+
}
|
|
6939
|
+
);
|
|
6940
|
+
if (!disabled || !reason) {
|
|
6941
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: tabButton }, id);
|
|
6942
|
+
}
|
|
6943
|
+
return /* @__PURE__ */ jsx(AdminPermissionTooltip, { disabled: true, message: reason, children: tabButton }, id);
|
|
6944
|
+
}) }),
|
|
6561
6945
|
state.activeTab === "dm" && /* @__PURE__ */ jsx(
|
|
6562
6946
|
DmContactsTab,
|
|
6563
6947
|
{
|
|
@@ -6568,7 +6952,7 @@ var CreateChatDialog = (props) => {
|
|
|
6568
6952
|
onStartDM: handleStartDM
|
|
6569
6953
|
}
|
|
6570
6954
|
),
|
|
6571
|
-
state.activeTab === "group" && /* @__PURE__ */ jsx(
|
|
6955
|
+
state.activeTab === "group" && groupCreationGate.enabled && /* @__PURE__ */ jsx(
|
|
6572
6956
|
GroupCreateTab,
|
|
6573
6957
|
{
|
|
6574
6958
|
state,
|
|
@@ -6632,7 +7016,7 @@ var emitPushChanged = (enabled) => {
|
|
|
6632
7016
|
} catch {
|
|
6633
7017
|
}
|
|
6634
7018
|
};
|
|
6635
|
-
var pushApiUrl = (path) => buildVersionedApiUrl(path, { service: "
|
|
7019
|
+
var pushApiUrl = (path) => buildVersionedApiUrl(path, { service: "v2" });
|
|
6636
7020
|
var apiGetPushConfig = async () => {
|
|
6637
7021
|
const { data } = await apiClient.get(pushApiUrl("/notifications/push/config"));
|
|
6638
7022
|
return data?.data;
|
|
@@ -6877,14 +7261,20 @@ var PushNotificationToggle = ({
|
|
|
6877
7261
|
children
|
|
6878
7262
|
}) => {
|
|
6879
7263
|
const push = usePushNotifications();
|
|
7264
|
+
const { getPushNotificationGate } = useEffectiveSettingsOptional();
|
|
7265
|
+
const adminGate = getPushNotificationGate();
|
|
6880
7266
|
const [isToggling, setIsToggling] = useState(false);
|
|
6881
|
-
if (!push.supported
|
|
7267
|
+
if (!push.supported) {
|
|
6882
7268
|
return null;
|
|
6883
7269
|
}
|
|
6884
7270
|
const isOn = push.deviceEnabled && push.userEnabled;
|
|
6885
7271
|
const permissionBlocked = push.permission === "denied";
|
|
7272
|
+
const adminBlocked = !adminGate.enabled;
|
|
7273
|
+
const notConfigured = !push.configured;
|
|
6886
7274
|
const showLoader = isToggling;
|
|
7275
|
+
const isDisabled = showLoader || permissionBlocked || push.loading || adminBlocked || notConfigured;
|
|
6887
7276
|
const handleChange = async (checked) => {
|
|
7277
|
+
if (adminBlocked || notConfigured) return;
|
|
6888
7278
|
setIsToggling(true);
|
|
6889
7279
|
try {
|
|
6890
7280
|
if (checked) {
|
|
@@ -6897,11 +7287,12 @@ var PushNotificationToggle = ({
|
|
|
6897
7287
|
setIsToggling(false);
|
|
6898
7288
|
}
|
|
6899
7289
|
};
|
|
7290
|
+
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
7291
|
const renderProps = {
|
|
6901
7292
|
label,
|
|
6902
|
-
description:
|
|
6903
|
-
checked: isOn,
|
|
6904
|
-
disabled:
|
|
7293
|
+
description: descriptionText,
|
|
7294
|
+
checked: adminBlocked || notConfigured ? false : isOn,
|
|
7295
|
+
disabled: isDisabled,
|
|
6905
7296
|
loading: showLoader || push.loading,
|
|
6906
7297
|
permissionBlocked,
|
|
6907
7298
|
error: push.error,
|
|
@@ -6929,12 +7320,19 @@ var PushNotificationToggle = ({
|
|
|
6929
7320
|
"aria-label": "Updating push notifications"
|
|
6930
7321
|
}
|
|
6931
7322
|
) : /* @__PURE__ */ jsx(
|
|
6932
|
-
|
|
7323
|
+
AdminPermissionTooltip,
|
|
6933
7324
|
{
|
|
6934
|
-
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
|
|
7325
|
+
disabled: adminBlocked || notConfigured,
|
|
7326
|
+
message: adminBlocked ? adminGate.disabledReason : "Push notifications are not configured. Please contact your administrator.",
|
|
7327
|
+
children: /* @__PURE__ */ jsx(
|
|
7328
|
+
Switch,
|
|
7329
|
+
{
|
|
7330
|
+
checked: adminBlocked || notConfigured ? false : isOn,
|
|
7331
|
+
disabled: isDisabled,
|
|
7332
|
+
onCheckedChange: (checked) => void handleChange(checked),
|
|
7333
|
+
"aria-label": `Toggle ${label}`
|
|
7334
|
+
}
|
|
7335
|
+
)
|
|
6938
7336
|
}
|
|
6939
7337
|
)
|
|
6940
7338
|
]
|
|
@@ -8355,7 +8753,7 @@ function highlightSearchMatch(text, query) {
|
|
|
8355
8753
|
children: part
|
|
8356
8754
|
},
|
|
8357
8755
|
`${part}-${index}`
|
|
8358
|
-
) : /* @__PURE__ */ jsx(
|
|
8756
|
+
) : /* @__PURE__ */ jsx(React3__default.Fragment, { children: part }, `${part}-${index}`)
|
|
8359
8757
|
);
|
|
8360
8758
|
}
|
|
8361
8759
|
function getMessagePreview(message) {
|
|
@@ -8535,7 +8933,7 @@ var HeaderSearchPopover = ({
|
|
|
8535
8933
|
] });
|
|
8536
8934
|
};
|
|
8537
8935
|
var HeaderSearchPopover_default = HeaderSearchPopover;
|
|
8538
|
-
var actionBtnClass = "size-8 rounded-lg text-(--chat-muted) transition-colors hover:bg-(--chat-surface) hover:text-(--chat-text)";
|
|
8936
|
+
var actionBtnClass = "size-8 rounded-lg text-(--chat-muted) transition-colors hover:bg-(--chat-surface) hover:text-(--chat-text) disabled:pointer-events-none disabled:opacity-40";
|
|
8539
8937
|
var DefaultHeaderCallActions = ({
|
|
8540
8938
|
activeChannel,
|
|
8541
8939
|
conversationId,
|
|
@@ -8546,48 +8944,91 @@ var DefaultHeaderCallActions = ({
|
|
|
8546
8944
|
className
|
|
8547
8945
|
}) => {
|
|
8548
8946
|
const { components, slotClassName, features } = useChatCustomizationOptional();
|
|
8947
|
+
const { getAudioCallGate, getVideoCallGate } = useEffectiveSettingsOptional();
|
|
8549
8948
|
const PhoneSlot = components.PhoneCallButton;
|
|
8550
8949
|
const VideoSlot = components.VideoCallButton;
|
|
8551
8950
|
const hideInGroups = features.hideCallActionsInGroupChats ?? false;
|
|
8951
|
+
const audioGate = getAudioCallGate();
|
|
8952
|
+
const videoGate = getVideoCallGate();
|
|
8552
8953
|
if (hideInGroups && activeChannel.isGroup) return null;
|
|
8553
8954
|
if (!showPhoneCall && !showVideoCall) return null;
|
|
8955
|
+
const phoneEnabled = showPhoneCall && audioGate.enabled;
|
|
8956
|
+
const videoEnabled = showVideoCall && videoGate.enabled;
|
|
8554
8957
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8555
8958
|
showPhoneCall && (PhoneSlot ? /* @__PURE__ */ jsx(
|
|
8556
|
-
|
|
8959
|
+
AdminPermissionTooltip,
|
|
8557
8960
|
{
|
|
8558
|
-
|
|
8559
|
-
|
|
8560
|
-
|
|
8561
|
-
|
|
8961
|
+
disabled: !audioGate.enabled,
|
|
8962
|
+
message: audioGate.disabledReason,
|
|
8963
|
+
children: /* @__PURE__ */ jsx("span", { className: "inline-flex", children: /* @__PURE__ */ jsx(
|
|
8964
|
+
PhoneSlot,
|
|
8965
|
+
{
|
|
8966
|
+
activeChannel,
|
|
8967
|
+
conversationId,
|
|
8968
|
+
onPhoneCall: phoneEnabled ? onPhoneCall : void 0,
|
|
8969
|
+
className: cn(
|
|
8970
|
+
className,
|
|
8971
|
+
slotClassName("phoneCallButton"),
|
|
8972
|
+
!audioGate.enabled && "pointer-events-none opacity-40"
|
|
8973
|
+
)
|
|
8974
|
+
}
|
|
8975
|
+
) })
|
|
8562
8976
|
}
|
|
8563
8977
|
) : /* @__PURE__ */ jsx(
|
|
8564
|
-
|
|
8978
|
+
AdminPermissionTooltip,
|
|
8565
8979
|
{
|
|
8566
|
-
|
|
8567
|
-
|
|
8568
|
-
|
|
8569
|
-
|
|
8570
|
-
|
|
8571
|
-
|
|
8980
|
+
disabled: !audioGate.enabled,
|
|
8981
|
+
message: audioGate.disabledReason,
|
|
8982
|
+
children: /* @__PURE__ */ jsx(
|
|
8983
|
+
Button,
|
|
8984
|
+
{
|
|
8985
|
+
variant: "ghost",
|
|
8986
|
+
size: "icon",
|
|
8987
|
+
className: cn(actionBtnClass, className, slotClassName("phoneCallButton")),
|
|
8988
|
+
"aria-label": "Voice call",
|
|
8989
|
+
disabled: !audioGate.enabled,
|
|
8990
|
+
onClick: phoneEnabled ? onPhoneCall : void 0,
|
|
8991
|
+
children: /* @__PURE__ */ jsx(Phone, { size: 15 })
|
|
8992
|
+
}
|
|
8993
|
+
)
|
|
8572
8994
|
}
|
|
8573
8995
|
)),
|
|
8574
8996
|
showVideoCall && (VideoSlot ? /* @__PURE__ */ jsx(
|
|
8575
|
-
|
|
8997
|
+
AdminPermissionTooltip,
|
|
8576
8998
|
{
|
|
8577
|
-
|
|
8578
|
-
|
|
8579
|
-
|
|
8580
|
-
|
|
8999
|
+
disabled: !videoGate.enabled,
|
|
9000
|
+
message: videoGate.disabledReason,
|
|
9001
|
+
children: /* @__PURE__ */ jsx("span", { className: "inline-flex", children: /* @__PURE__ */ jsx(
|
|
9002
|
+
VideoSlot,
|
|
9003
|
+
{
|
|
9004
|
+
activeChannel,
|
|
9005
|
+
conversationId,
|
|
9006
|
+
onVideoCall: videoEnabled ? onVideoCall : void 0,
|
|
9007
|
+
className: cn(
|
|
9008
|
+
className,
|
|
9009
|
+
slotClassName("videoCallButton"),
|
|
9010
|
+
!videoGate.enabled && "pointer-events-none opacity-40"
|
|
9011
|
+
)
|
|
9012
|
+
}
|
|
9013
|
+
) })
|
|
8581
9014
|
}
|
|
8582
9015
|
) : /* @__PURE__ */ jsx(
|
|
8583
|
-
|
|
9016
|
+
AdminPermissionTooltip,
|
|
8584
9017
|
{
|
|
8585
|
-
|
|
8586
|
-
|
|
8587
|
-
|
|
8588
|
-
|
|
8589
|
-
|
|
8590
|
-
|
|
9018
|
+
disabled: !videoGate.enabled,
|
|
9019
|
+
message: videoGate.disabledReason,
|
|
9020
|
+
children: /* @__PURE__ */ jsx(
|
|
9021
|
+
Button,
|
|
9022
|
+
{
|
|
9023
|
+
variant: "ghost",
|
|
9024
|
+
size: "icon",
|
|
9025
|
+
className: cn(actionBtnClass, className, slotClassName("videoCallButton")),
|
|
9026
|
+
"aria-label": "Video call",
|
|
9027
|
+
disabled: !videoGate.enabled,
|
|
9028
|
+
onClick: videoEnabled ? onVideoCall : void 0,
|
|
9029
|
+
children: /* @__PURE__ */ jsx(Video, { size: 15 })
|
|
9030
|
+
}
|
|
9031
|
+
)
|
|
8591
9032
|
}
|
|
8592
9033
|
))
|
|
8593
9034
|
] });
|
|
@@ -8609,19 +9050,38 @@ function OptionsMenuItem({
|
|
|
8609
9050
|
icon: Icon,
|
|
8610
9051
|
label,
|
|
8611
9052
|
onSelect,
|
|
8612
|
-
destructive = false
|
|
9053
|
+
destructive = false,
|
|
9054
|
+
disabled = false,
|
|
9055
|
+
disabledReason
|
|
8613
9056
|
}) {
|
|
8614
|
-
|
|
9057
|
+
const item = /* @__PURE__ */ jsxs(
|
|
8615
9058
|
DropdownMenuItem,
|
|
8616
9059
|
{
|
|
8617
|
-
className:
|
|
8618
|
-
|
|
9060
|
+
className: cn(
|
|
9061
|
+
destructive ? chatOptionsMenuItemDestructiveClass : chatOptionsMenuItemClass,
|
|
9062
|
+
disabled && "pointer-events-none opacity-40"
|
|
9063
|
+
),
|
|
9064
|
+
disabled,
|
|
9065
|
+
onSelect: (event) => {
|
|
9066
|
+
if (disabled) {
|
|
9067
|
+
event.preventDefault();
|
|
9068
|
+
return;
|
|
9069
|
+
}
|
|
9070
|
+
onSelect?.();
|
|
9071
|
+
},
|
|
8619
9072
|
children: [
|
|
8620
9073
|
/* @__PURE__ */ jsx(Icon, { strokeWidth: 1.75 }),
|
|
8621
9074
|
/* @__PURE__ */ jsx("span", { className: "flex-1", children: label })
|
|
8622
9075
|
]
|
|
8623
9076
|
}
|
|
8624
9077
|
);
|
|
9078
|
+
if (!disabled || !disabledReason) {
|
|
9079
|
+
return item;
|
|
9080
|
+
}
|
|
9081
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
9082
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx("div", { className: "w-full", children: item }) }),
|
|
9083
|
+
/* @__PURE__ */ jsx(TooltipContent, { side: "left", className: "max-w-[220px] text-xs", children: disabledReason })
|
|
9084
|
+
] });
|
|
8625
9085
|
}
|
|
8626
9086
|
var HeaderRightSide = ({
|
|
8627
9087
|
activeChannel,
|
|
@@ -8656,6 +9116,8 @@ var HeaderRightSide = ({
|
|
|
8656
9116
|
const { scopeClassName, themeStyles, showColorModeToggle } = useChatTheme();
|
|
8657
9117
|
const { showDateTimeSettings } = useChatLocale();
|
|
8658
9118
|
const features = useChatFeaturesOptional();
|
|
9119
|
+
const { getBlockUsersGate } = useEffectiveSettingsOptional();
|
|
9120
|
+
const blockUsersGate = getBlockUsersGate();
|
|
8659
9121
|
const showPhoneCall = features.showPhoneCall ?? defaultChatFeatures.showPhoneCall;
|
|
8660
9122
|
const showVideoCall = features.showVideoCall ?? defaultChatFeatures.showVideoCall;
|
|
8661
9123
|
const handlePhoneCall = () => {
|
|
@@ -8804,7 +9266,9 @@ var HeaderRightSide = ({
|
|
|
8804
9266
|
icon: Ban,
|
|
8805
9267
|
label: isBlocked ? "Unblock User" : "Block User",
|
|
8806
9268
|
onSelect: onToggleBlock,
|
|
8807
|
-
destructive: true
|
|
9269
|
+
destructive: true,
|
|
9270
|
+
disabled: !blockUsersGate.enabled,
|
|
9271
|
+
disabledReason: blockUsersGate.disabledReason
|
|
8808
9272
|
}
|
|
8809
9273
|
)
|
|
8810
9274
|
]
|
|
@@ -12844,17 +13308,24 @@ var ChannelDetailsDrawer = (props) => {
|
|
|
12844
13308
|
};
|
|
12845
13309
|
var ChannelDetailsDrawer_default = ChannelDetailsDrawer;
|
|
12846
13310
|
init_useStore();
|
|
13311
|
+
init_settings_types();
|
|
12847
13312
|
var PermissionDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo }) => {
|
|
12848
13313
|
const updateGroupPermissions = useStore((s) => s.updateGroupPermissions);
|
|
13314
|
+
const { settings, isGroupPermissionLocked } = useEffectiveSettingsOptional();
|
|
12849
13315
|
const [permissions, setPermissions] = useState(null);
|
|
12850
13316
|
const [isSaving, setIsSaving] = useState(false);
|
|
12851
13317
|
useEffect(() => {
|
|
12852
13318
|
if (conversationInfo?.groupPermissions) {
|
|
12853
13319
|
setPermissions(conversationInfo.groupPermissions);
|
|
13320
|
+
return;
|
|
12854
13321
|
}
|
|
12855
|
-
|
|
13322
|
+
if (isOpen) {
|
|
13323
|
+
setPermissions({ ...settings.groupPolicy.defaults });
|
|
13324
|
+
}
|
|
13325
|
+
}, [conversationInfo, isOpen, settings.groupPolicy.defaults]);
|
|
12856
13326
|
if (!conversationId || !permissions) return null;
|
|
12857
13327
|
const handleToggle = (key) => {
|
|
13328
|
+
if (isGroupPermissionLocked(key)) return;
|
|
12858
13329
|
setPermissions((prev) => prev ? { ...prev, [key]: !prev[key] } : null);
|
|
12859
13330
|
};
|
|
12860
13331
|
const handleSave = async () => {
|
|
@@ -12886,31 +13357,43 @@ var PermissionDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo
|
|
|
12886
13357
|
/* @__PURE__ */ jsxs("div", { className: cn(chatSheetBodyClass, "flex flex-col px-2.5 py-2"), children: [
|
|
12887
13358
|
/* @__PURE__ */ jsxs("section", { className: "mb-2.5 flex-1", children: [
|
|
12888
13359
|
/* @__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
|
-
|
|
13360
|
+
/* @__PURE__ */ jsx("div", { className: "rounded-lg border border-(--chat-border) px-3", children: permissionItems.map((item, index) => {
|
|
13361
|
+
const locked = isGroupPermissionLocked(item.key);
|
|
13362
|
+
return /* @__PURE__ */ jsxs(
|
|
13363
|
+
"div",
|
|
13364
|
+
{
|
|
13365
|
+
className: cn(
|
|
13366
|
+
"flex items-start justify-between gap-3 py-2.5",
|
|
13367
|
+
index < permissionItems.length - 1 && "border-b border-(--chat-border)"
|
|
13368
|
+
),
|
|
13369
|
+
children: [
|
|
13370
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-0.5", children: [
|
|
13371
|
+
/* @__PURE__ */ jsx("p", { className: "text-[12px] font-semibold leading-snug text-(--chat-text)", children: item.label }),
|
|
13372
|
+
/* @__PURE__ */ jsx("p", { className: "text-[10px] leading-relaxed text-(--chat-muted)", children: item.desc }),
|
|
13373
|
+
locked ? /* @__PURE__ */ jsx("p", { className: "text-[10px] font-medium text-(--chat-theme)", children: "Locked by administrator" }) : null
|
|
13374
|
+
] }),
|
|
13375
|
+
/* @__PURE__ */ jsx(
|
|
13376
|
+
AdminPermissionTooltip,
|
|
13377
|
+
{
|
|
13378
|
+
disabled: locked,
|
|
13379
|
+
message: ADMIN_PERMISSION_DENIED_MESSAGE,
|
|
13380
|
+
children: /* @__PURE__ */ jsx(
|
|
13381
|
+
Switch,
|
|
13382
|
+
{
|
|
13383
|
+
size: "sm",
|
|
13384
|
+
className: "mt-0.5 shrink-0 data-[state=checked]:bg-(--chat-theme) data-[state=unchecked]:bg-(--chat-border)",
|
|
13385
|
+
disabled: locked,
|
|
13386
|
+
checked: item.inverted ? !permissions[item.key] : permissions[item.key],
|
|
13387
|
+
onCheckedChange: () => handleToggle(item.key)
|
|
13388
|
+
}
|
|
13389
|
+
)
|
|
13390
|
+
}
|
|
13391
|
+
)
|
|
13392
|
+
]
|
|
13393
|
+
},
|
|
13394
|
+
item.key
|
|
13395
|
+
);
|
|
13396
|
+
}) })
|
|
12914
13397
|
] }),
|
|
12915
13398
|
/* @__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
13399
|
Button,
|
|
@@ -12940,6 +13423,8 @@ function useAdminsDrawer({ conversationId, conversationInfo }) {
|
|
|
12940
13423
|
const [isManaging, setIsManaging] = useState(null);
|
|
12941
13424
|
const manageGroupAdmins = useStore((s) => s.manageGroupAdmins);
|
|
12942
13425
|
const { isOwner } = useGroupInfo(conversationId);
|
|
13426
|
+
const { settings } = useEffectiveSettingsOptional();
|
|
13427
|
+
const maxAdmins = settings.maxAdminsPerGroup;
|
|
12943
13428
|
const participants = useMemo(
|
|
12944
13429
|
() => conversationInfo?.participants ?? [],
|
|
12945
13430
|
[conversationInfo?.participants]
|
|
@@ -12979,8 +13464,16 @@ function useAdminsDrawer({ conversationId, conversationInfo }) {
|
|
|
12979
13464
|
}),
|
|
12980
13465
|
[filteredParticipants, adminIds, ownerId]
|
|
12981
13466
|
);
|
|
13467
|
+
const adminCount = admins.length + (ownerId ? 1 : 0);
|
|
13468
|
+
const atAdminLimit = adminCount >= maxAdmins;
|
|
12982
13469
|
const handleManageAdmin = async (userId, type) => {
|
|
12983
13470
|
if (!conversationId) return;
|
|
13471
|
+
if (type === "add" && adminCount >= maxAdmins) {
|
|
13472
|
+
useStore.getState().handleAppError(
|
|
13473
|
+
`You can have up to ${maxAdmins} admins in this group.`
|
|
13474
|
+
);
|
|
13475
|
+
return;
|
|
13476
|
+
}
|
|
12984
13477
|
setIsManaging(userId);
|
|
12985
13478
|
try {
|
|
12986
13479
|
await manageGroupAdmins({
|
|
@@ -12992,7 +13485,6 @@ function useAdminsDrawer({ conversationId, conversationInfo }) {
|
|
|
12992
13485
|
setIsManaging(null);
|
|
12993
13486
|
}
|
|
12994
13487
|
};
|
|
12995
|
-
const adminCount = admins.length + (ownerId ? 1 : 0);
|
|
12996
13488
|
return {
|
|
12997
13489
|
searchQuery,
|
|
12998
13490
|
setSearchQuery,
|
|
@@ -13004,6 +13496,8 @@ function useAdminsDrawer({ conversationId, conversationInfo }) {
|
|
|
13004
13496
|
promotableParticipants,
|
|
13005
13497
|
handleManageAdmin,
|
|
13006
13498
|
adminCount,
|
|
13499
|
+
maxAdmins,
|
|
13500
|
+
atAdminLimit,
|
|
13007
13501
|
hasRequiredData: Boolean(conversationId && conversationInfo)
|
|
13008
13502
|
};
|
|
13009
13503
|
}
|
|
@@ -13016,6 +13510,8 @@ function AdminParticipantRow({
|
|
|
13016
13510
|
isAdmin,
|
|
13017
13511
|
showPromote,
|
|
13018
13512
|
showDemote,
|
|
13513
|
+
promoteDisabled = false,
|
|
13514
|
+
promoteDisabledReason,
|
|
13019
13515
|
isOwnerViewer,
|
|
13020
13516
|
isManaging,
|
|
13021
13517
|
onManageAdmin
|
|
@@ -13056,14 +13552,24 @@ function AdminParticipantRow({
|
|
|
13056
13552
|
}
|
|
13057
13553
|
),
|
|
13058
13554
|
showPromote && isOwnerViewer && /* @__PURE__ */ jsx(
|
|
13059
|
-
|
|
13555
|
+
AdminPermissionTooltip,
|
|
13060
13556
|
{
|
|
13061
|
-
|
|
13062
|
-
|
|
13063
|
-
|
|
13064
|
-
|
|
13065
|
-
|
|
13066
|
-
|
|
13557
|
+
disabled: promoteDisabled,
|
|
13558
|
+
message: promoteDisabledReason,
|
|
13559
|
+
children: /* @__PURE__ */ jsx(
|
|
13560
|
+
Button,
|
|
13561
|
+
{
|
|
13562
|
+
variant: "ghost",
|
|
13563
|
+
size: "sm",
|
|
13564
|
+
className: "size-7 rounded-md p-0 text-(--chat-muted) hover:bg-(--chat-theme-10) hover:text-(--chat-theme) disabled:opacity-40",
|
|
13565
|
+
onClick: () => {
|
|
13566
|
+
if (promoteDisabled) return;
|
|
13567
|
+
onManageAdmin(memberId, "add");
|
|
13568
|
+
},
|
|
13569
|
+
disabled: isManaging === memberId || promoteDisabled,
|
|
13570
|
+
children: isManaging === memberId ? /* @__PURE__ */ jsx(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx(UserPlus, { size: 13 })
|
|
13571
|
+
}
|
|
13572
|
+
)
|
|
13067
13573
|
}
|
|
13068
13574
|
)
|
|
13069
13575
|
] })
|
|
@@ -13087,7 +13593,9 @@ function AdminParticipantList({
|
|
|
13087
13593
|
isAdmin,
|
|
13088
13594
|
onManageAdmin,
|
|
13089
13595
|
showPromote,
|
|
13090
|
-
showDemoteForAdmins
|
|
13596
|
+
showDemoteForAdmins,
|
|
13597
|
+
promoteDisabled = false,
|
|
13598
|
+
promoteDisabledReason
|
|
13091
13599
|
}) {
|
|
13092
13600
|
return /* @__PURE__ */ jsx(Fragment, { children: members.map((member, index) => {
|
|
13093
13601
|
const { memberId, memberName, memberEmail, memberImage } = getMemberFields(member);
|
|
@@ -13105,6 +13613,8 @@ function AdminParticipantList({
|
|
|
13105
13613
|
isAdmin: userIsAdmin,
|
|
13106
13614
|
showPromote: showPromote && !userIsAdmin && !userIsOwner,
|
|
13107
13615
|
showDemote: showDemoteForAdmins ? userIsAdmin && !userIsOwner : false,
|
|
13616
|
+
promoteDisabled,
|
|
13617
|
+
promoteDisabledReason,
|
|
13108
13618
|
isOwnerViewer,
|
|
13109
13619
|
isManaging,
|
|
13110
13620
|
onManageAdmin
|
|
@@ -13124,6 +13634,8 @@ var AdminsDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13124
13634
|
promotableParticipants,
|
|
13125
13635
|
handleManageAdmin,
|
|
13126
13636
|
adminCount,
|
|
13637
|
+
maxAdmins,
|
|
13638
|
+
atAdminLimit,
|
|
13127
13639
|
hasRequiredData
|
|
13128
13640
|
} = useAdminsDrawer({ conversationId, conversationInfo });
|
|
13129
13641
|
if (!hasRequiredData) return null;
|
|
@@ -13143,7 +13655,10 @@ var AdminsDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13143
13655
|
/* @__PURE__ */ jsx(SheetTitle, { className: chatSheetTitleClass, children: "Group Administrators" }),
|
|
13144
13656
|
/* @__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
13657
|
] }),
|
|
13146
|
-
/* @__PURE__ */
|
|
13658
|
+
/* @__PURE__ */ jsxs("p", { className: chatSheetSubtitleClass, children: [
|
|
13659
|
+
"Manage who can adjust group settings and members",
|
|
13660
|
+
maxAdmins ? ` (max ${maxAdmins}).` : "."
|
|
13661
|
+
] })
|
|
13147
13662
|
] }),
|
|
13148
13663
|
/* @__PURE__ */ jsxs("div", { className: cn(chatSheetBodyClass, "px-2.5 py-2"), children: [
|
|
13149
13664
|
/* @__PURE__ */ jsx("div", { className: "mb-2.5 px-0.5", children: /* @__PURE__ */ jsx(
|
|
@@ -13186,7 +13701,9 @@ var AdminsDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13186
13701
|
ownerId,
|
|
13187
13702
|
isAdmin,
|
|
13188
13703
|
onManageAdmin: handleManageAdmin,
|
|
13189
|
-
showPromote: true
|
|
13704
|
+
showPromote: true,
|
|
13705
|
+
promoteDisabled: atAdminLimit,
|
|
13706
|
+
promoteDisabledReason: `Maximum ${maxAdmins} admins allowed in this group.`
|
|
13190
13707
|
}
|
|
13191
13708
|
) })
|
|
13192
13709
|
] }),
|
|
@@ -13203,7 +13720,9 @@ var AdminsDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13203
13720
|
isAdmin,
|
|
13204
13721
|
onManageAdmin: handleManageAdmin,
|
|
13205
13722
|
showPromote: true,
|
|
13206
|
-
showDemoteForAdmins: true
|
|
13723
|
+
showDemoteForAdmins: true,
|
|
13724
|
+
promoteDisabled: atAdminLimit,
|
|
13725
|
+
promoteDisabledReason: `Maximum ${maxAdmins} admins allowed in this group.`
|
|
13207
13726
|
}
|
|
13208
13727
|
) })
|
|
13209
13728
|
] }),
|
|
@@ -13231,9 +13750,12 @@ var MembersDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13231
13750
|
);
|
|
13232
13751
|
}, [allUsers, searchQuery]);
|
|
13233
13752
|
const { userPermissions } = useGroupInfo(conversationId);
|
|
13753
|
+
const { settings } = useEffectiveSettingsOptional();
|
|
13754
|
+
const maxParticipants = settings.maxParticipantsPerGroup;
|
|
13234
13755
|
if (!conversationId || !conversationInfo) return null;
|
|
13235
13756
|
const participants = conversationInfo.participants || [];
|
|
13236
13757
|
const admins = conversationInfo.groupAdmins || [];
|
|
13758
|
+
const atParticipantLimit = participants.length >= maxParticipants;
|
|
13237
13759
|
let ownerId = null;
|
|
13238
13760
|
if (conversationInfo.owner) {
|
|
13239
13761
|
ownerId = typeof conversationInfo.owner === "object" && conversationInfo.owner !== null ? conversationInfo.owner._id || conversationInfo.owner.id : conversationInfo.owner;
|
|
@@ -13287,14 +13809,24 @@ var MembersDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13287
13809
|
}
|
|
13288
13810
|
),
|
|
13289
13811
|
options.showAdd && /* @__PURE__ */ jsx(
|
|
13290
|
-
|
|
13812
|
+
AdminPermissionTooltip,
|
|
13291
13813
|
{
|
|
13292
|
-
|
|
13293
|
-
|
|
13294
|
-
|
|
13295
|
-
|
|
13296
|
-
|
|
13297
|
-
|
|
13814
|
+
disabled: atParticipantLimit,
|
|
13815
|
+
message: `Maximum ${maxParticipants} participants allowed in this group.`,
|
|
13816
|
+
children: /* @__PURE__ */ jsx(
|
|
13817
|
+
Button,
|
|
13818
|
+
{
|
|
13819
|
+
variant: "ghost",
|
|
13820
|
+
size: "sm",
|
|
13821
|
+
className: "size-7 rounded-md p-0 text-(--chat-muted) hover:bg-(--chat-theme-10) hover:text-(--chat-theme) disabled:opacity-40",
|
|
13822
|
+
onClick: () => {
|
|
13823
|
+
if (atParticipantLimit) return;
|
|
13824
|
+
handleManageMember(memberId, "add");
|
|
13825
|
+
},
|
|
13826
|
+
disabled: isManaging === memberId || atParticipantLimit,
|
|
13827
|
+
children: isManaging === memberId ? /* @__PURE__ */ jsx(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx(UserPlus, { size: 13 })
|
|
13828
|
+
}
|
|
13829
|
+
)
|
|
13298
13830
|
}
|
|
13299
13831
|
)
|
|
13300
13832
|
] })
|
|
@@ -13316,7 +13848,11 @@ var MembersDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13316
13848
|
/* @__PURE__ */ jsx(SheetTitle, { className: chatSheetTitleClass, children: "Group Management" }),
|
|
13317
13849
|
/* @__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
13850
|
] }),
|
|
13319
|
-
/* @__PURE__ */
|
|
13851
|
+
/* @__PURE__ */ jsxs("p", { className: chatSheetSubtitleClass, children: [
|
|
13852
|
+
"Manage members and invite people (max ",
|
|
13853
|
+
maxParticipants,
|
|
13854
|
+
")."
|
|
13855
|
+
] })
|
|
13320
13856
|
] }),
|
|
13321
13857
|
/* @__PURE__ */ jsxs("div", { className: cn(chatSheetBodyClass, "px-2.5 py-2"), children: [
|
|
13322
13858
|
!searchQuery && /* @__PURE__ */ jsxs("section", { className: "mb-2.5", children: [
|
|
@@ -13458,6 +13994,8 @@ init_store_helpers();
|
|
|
13458
13994
|
function useBlockUser(activeChannel, conversationId, onActiveChannelPatch) {
|
|
13459
13995
|
const loggedUserDetails = useStore((s) => s.loggedUserDetails);
|
|
13460
13996
|
const composerDisabledByConversation = useStore((s) => s.composerDisabledByConversation);
|
|
13997
|
+
const { getBlockUsersGate } = useEffectiveSettingsOptional();
|
|
13998
|
+
const blockUsersGate = getBlockUsersGate();
|
|
13461
13999
|
const [isBlocking, setIsBlocking] = useState(false);
|
|
13462
14000
|
const resolvedConversationId = conversationId ?? activeChannel?.conversationId ?? null;
|
|
13463
14001
|
const composerDisabledReason = resolvedConversationId ? composerDisabledByConversation[resolvedConversationId] : void 0;
|
|
@@ -13479,6 +14017,12 @@ function useBlockUser(activeChannel, conversationId, onActiveChannelPatch) {
|
|
|
13479
14017
|
const toggleBlock = useCallback(async () => {
|
|
13480
14018
|
if (!activeChannel?.id || activeChannel.isGroup) return false;
|
|
13481
14019
|
const nextBlocked = !isBlocked;
|
|
14020
|
+
if (nextBlocked && !blockUsersGate.enabled) {
|
|
14021
|
+
useStore.getState().handleAppError(
|
|
14022
|
+
blockUsersGate.disabledReason || "Blocking users is disabled by your administrator."
|
|
14023
|
+
);
|
|
14024
|
+
return false;
|
|
14025
|
+
}
|
|
13482
14026
|
const type = nextBlocked ? "block" : "unblock";
|
|
13483
14027
|
try {
|
|
13484
14028
|
setIsBlocking(true);
|
|
@@ -13499,8 +14043,8 @@ function useBlockUser(activeChannel, conversationId, onActiveChannelPatch) {
|
|
|
13499
14043
|
} finally {
|
|
13500
14044
|
setIsBlocking(false);
|
|
13501
14045
|
}
|
|
13502
|
-
}, [activeChannel, isBlocked, onActiveChannelPatch, resolvedConversationId]);
|
|
13503
|
-
return { isBlocked, isBlocking, toggleBlock };
|
|
14046
|
+
}, [activeChannel, isBlocked, onActiveChannelPatch, resolvedConversationId, blockUsersGate]);
|
|
14047
|
+
return { isBlocked, isBlocking, toggleBlock, blockUsersGate };
|
|
13504
14048
|
}
|
|
13505
14049
|
|
|
13506
14050
|
// src/chat/channel-header/useChannelHeader.ts
|
|
@@ -14036,6 +14580,7 @@ var MessageReactions_default = MessageReactions;
|
|
|
14036
14580
|
var MessageToolbar = ({
|
|
14037
14581
|
isSender,
|
|
14038
14582
|
isRecent,
|
|
14583
|
+
isWithinDeleteWindow = isRecent,
|
|
14039
14584
|
isPinned,
|
|
14040
14585
|
isStarred,
|
|
14041
14586
|
isPinPending,
|
|
@@ -14059,7 +14604,7 @@ var MessageToolbar = ({
|
|
|
14059
14604
|
}) => {
|
|
14060
14605
|
const { isDark, scopeClassName, themeStyles } = useChatTheme();
|
|
14061
14606
|
const showDeleteMenu = isSender || hasAttachments || attachmentDeleteMode;
|
|
14062
|
-
const showDeleteForEveryone = isSender &&
|
|
14607
|
+
const showDeleteForEveryone = isSender && isWithinDeleteWindow;
|
|
14063
14608
|
return /* @__PURE__ */ jsxs(
|
|
14064
14609
|
"div",
|
|
14065
14610
|
{
|
|
@@ -14381,16 +14926,59 @@ function resolveForwardItems(selectedKeys, messages) {
|
|
|
14381
14926
|
}
|
|
14382
14927
|
|
|
14383
14928
|
// src/chat/lib/chat-edit-window.ts
|
|
14384
|
-
|
|
14385
|
-
|
|
14386
|
-
|
|
14929
|
+
init_settings_types();
|
|
14930
|
+
|
|
14931
|
+
// src/lib/effective-settings.helpers.ts
|
|
14932
|
+
function minutesToMs(minutes) {
|
|
14933
|
+
return Math.max(0, minutes) * 60 * 1e3;
|
|
14934
|
+
}
|
|
14935
|
+
function getEditWindowMs(timers, isGroup) {
|
|
14936
|
+
return minutesToMs(isGroup ? timers.groupEditMinutes : timers.dmEditMinutes);
|
|
14937
|
+
}
|
|
14938
|
+
function getDeleteWindowMs(timers, isGroup) {
|
|
14939
|
+
return minutesToMs(
|
|
14940
|
+
isGroup ? timers.groupDeleteMinutes : timers.dmDeleteMinutes
|
|
14941
|
+
);
|
|
14387
14942
|
}
|
|
14388
|
-
function
|
|
14943
|
+
function isWithinWindow(createdAt, windowMs) {
|
|
14389
14944
|
if (!createdAt) return false;
|
|
14390
14945
|
const date = new Date(createdAt);
|
|
14391
14946
|
if (isNaN(date.getTime())) return false;
|
|
14392
14947
|
const diff = Date.now() - date.getTime();
|
|
14393
|
-
return diff >= 0 && diff <
|
|
14948
|
+
return diff >= 0 && diff < windowMs;
|
|
14949
|
+
}
|
|
14950
|
+
function isWithinMessageEditWindow(createdAt, timers, isGroup) {
|
|
14951
|
+
return isWithinWindow(createdAt, getEditWindowMs(timers, isGroup));
|
|
14952
|
+
}
|
|
14953
|
+
function isWithinMessageDeleteWindow(createdAt, timers, isGroup) {
|
|
14954
|
+
return isWithinWindow(createdAt, getDeleteWindowMs(timers, isGroup));
|
|
14955
|
+
}
|
|
14956
|
+
function matchesAllowedMimeType(fileType, allowedMimeTypes) {
|
|
14957
|
+
const mime = (fileType || "application/octet-stream").toLowerCase();
|
|
14958
|
+
return allowedMimeTypes.some((pattern) => {
|
|
14959
|
+
const normalized = pattern.trim().toLowerCase();
|
|
14960
|
+
if (!normalized) return false;
|
|
14961
|
+
if (normalized.endsWith("/*")) {
|
|
14962
|
+
const prefix = normalized.slice(0, -1);
|
|
14963
|
+
return mime.startsWith(prefix);
|
|
14964
|
+
}
|
|
14965
|
+
return mime === normalized;
|
|
14966
|
+
});
|
|
14967
|
+
}
|
|
14968
|
+
function buildAcceptFromMimeTypes(allowedMimeTypes) {
|
|
14969
|
+
return allowedMimeTypes.map((type) => type.trim()).filter(Boolean).join(",");
|
|
14970
|
+
}
|
|
14971
|
+
function formatFileSizeMB(sizeBytes) {
|
|
14972
|
+
return `${(sizeBytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
14973
|
+
}
|
|
14974
|
+
|
|
14975
|
+
// src/chat/lib/chat-edit-window.ts
|
|
14976
|
+
var FALLBACK_TIMERS = DEFAULT_EFFECTIVE_SETTINGS.messageTimers;
|
|
14977
|
+
function isWithinMessageEditWindow2(createdAt, isGroup, timers = FALLBACK_TIMERS) {
|
|
14978
|
+
return isWithinMessageEditWindow(createdAt, timers, isGroup);
|
|
14979
|
+
}
|
|
14980
|
+
function isWithinMessageDeleteWindow2(createdAt, isGroup, timers = FALLBACK_TIMERS) {
|
|
14981
|
+
return isWithinMessageDeleteWindow(createdAt, timers, isGroup);
|
|
14394
14982
|
}
|
|
14395
14983
|
|
|
14396
14984
|
// src/chat/message-item/useMessageItemActions.ts
|
|
@@ -14468,6 +15056,9 @@ function useMessageItemActions({
|
|
|
14468
15056
|
const canUnpin = !isPinned || isPinnedByMe;
|
|
14469
15057
|
const { userPermissions } = useGroupInfo(conversationId || null);
|
|
14470
15058
|
const { formatMessageTime } = useChatLocale();
|
|
15059
|
+
const { settings } = useEffectiveSettingsOptional();
|
|
15060
|
+
const messageTimers = settings.messageTimers;
|
|
15061
|
+
const maxPinnedMessages = settings.maxPinnedMessagesPerConversation;
|
|
14471
15062
|
const visibleAttachments = getVisibleAttachments(attachments);
|
|
14472
15063
|
const hasAttachments = visibleAttachments.length > 0;
|
|
14473
15064
|
const hasMultiAttachments = hasAttachments && messageUsesAttachmentSelection({ attachments: visibleAttachments });
|
|
@@ -14484,7 +15075,8 @@ function useMessageItemActions({
|
|
|
14484
15075
|
const hasText = Boolean(message?.trim());
|
|
14485
15076
|
const isSelected = !!mid && !!selectedKeys && isMessageWhollySelected(selectedKeys, mid) && !hasMultiAttachments;
|
|
14486
15077
|
const canEdit = (!isGroup || userPermissions.canEditMessage) && hasText;
|
|
14487
|
-
const isWithinEditWindow = () =>
|
|
15078
|
+
const isWithinEditWindow = () => isWithinMessageEditWindow2(createdAt, isGroup, messageTimers);
|
|
15079
|
+
const isWithinDeleteWindow = () => isWithinMessageDeleteWindow2(createdAt, isGroup, messageTimers);
|
|
14488
15080
|
const canEditAttachmentCaption = isSender && isWithinEditWindow() && (!isGroup || userPermissions.canEditMessage) && !isDeletedForEveryone && !!mid;
|
|
14489
15081
|
const handleAttachmentCaptionClick = (attachment) => {
|
|
14490
15082
|
if (!canEditAttachmentCaption) return;
|
|
@@ -14653,6 +15245,15 @@ function useMessageItemActions({
|
|
|
14653
15245
|
});
|
|
14654
15246
|
}
|
|
14655
15247
|
} else {
|
|
15248
|
+
if (conversationId) {
|
|
15249
|
+
const pinnedCount = (pinnedMessagesByConversation[conversationId] || []).length || useStore.getState().liveConversationCounts[conversationId]?.pinnedCount || 0;
|
|
15250
|
+
if (pinnedCount >= maxPinnedMessages) {
|
|
15251
|
+
useStore.getState().handleAppError(
|
|
15252
|
+
`You can pin up to ${maxPinnedMessages} messages in this conversation.`
|
|
15253
|
+
);
|
|
15254
|
+
return;
|
|
15255
|
+
}
|
|
15256
|
+
}
|
|
14656
15257
|
if (isGroup) {
|
|
14657
15258
|
if (!conversationId) return;
|
|
14658
15259
|
emitGroupPin({
|
|
@@ -14711,6 +15312,7 @@ function useMessageItemActions({
|
|
|
14711
15312
|
canUnpin,
|
|
14712
15313
|
canEdit,
|
|
14713
15314
|
isWithinEditWindow,
|
|
15315
|
+
isWithinDeleteWindow,
|
|
14714
15316
|
canEditAttachmentCaption,
|
|
14715
15317
|
visibleAttachments,
|
|
14716
15318
|
hasAttachments,
|
|
@@ -14742,7 +15344,7 @@ function useMessageItemActions({
|
|
|
14742
15344
|
}
|
|
14743
15345
|
|
|
14744
15346
|
// src/chat/lib/reply-preview.ts
|
|
14745
|
-
function
|
|
15347
|
+
function normalizeAttachments2(replyTo, loggedUserId) {
|
|
14746
15348
|
const raw = replyTo?.attachments;
|
|
14747
15349
|
if (!Array.isArray(raw) || raw.length === 0) return [];
|
|
14748
15350
|
return raw.map((att, index) => {
|
|
@@ -14755,7 +15357,7 @@ function resolveReplyToMessage(replyTo, messagesById, loggedUserId) {
|
|
|
14755
15357
|
if (typeof replyTo === "object" && (replyTo.content?.trim() || replyTo.attachments?.length)) {
|
|
14756
15358
|
return {
|
|
14757
15359
|
...replyTo,
|
|
14758
|
-
attachments:
|
|
15360
|
+
attachments: normalizeAttachments2(replyTo, loggedUserId)
|
|
14759
15361
|
};
|
|
14760
15362
|
}
|
|
14761
15363
|
const replyId = String(
|
|
@@ -15192,6 +15794,7 @@ function MessageItemView(props) {
|
|
|
15192
15794
|
canUnpin,
|
|
15193
15795
|
canEdit,
|
|
15194
15796
|
isWithinEditWindow,
|
|
15797
|
+
isWithinDeleteWindow,
|
|
15195
15798
|
canEditAttachmentCaption,
|
|
15196
15799
|
visibleAttachments,
|
|
15197
15800
|
hasAttachments,
|
|
@@ -15283,6 +15886,7 @@ function MessageItemView(props) {
|
|
|
15283
15886
|
{
|
|
15284
15887
|
isSender,
|
|
15285
15888
|
isRecent: isWithinEditWindow(),
|
|
15889
|
+
isWithinDeleteWindow: isWithinDeleteWindow(),
|
|
15286
15890
|
messageId: mid,
|
|
15287
15891
|
isPinned,
|
|
15288
15892
|
isStarred,
|
|
@@ -15577,6 +16181,7 @@ function MessageSelectionBar({
|
|
|
15577
16181
|
}
|
|
15578
16182
|
|
|
15579
16183
|
// src/chat/active-channel-messages/utils.ts
|
|
16184
|
+
init_settings_types();
|
|
15580
16185
|
var getMessageSenderId2 = (msg) => msg ? String(msg.senderId || msg.sender?._id || "") : "";
|
|
15581
16186
|
var isLikelyObjectId = (value) => /^[a-f\d]{24}$/i.test(value);
|
|
15582
16187
|
function resolveGroupSenderDisplay(message, allUsers = [], participants = []) {
|
|
@@ -15608,7 +16213,7 @@ var isSameMessageSide = (a, b, isGroupChat) => {
|
|
|
15608
16213
|
const bId = getMessageSenderId2(b);
|
|
15609
16214
|
return aId !== "" && aId === bId;
|
|
15610
16215
|
};
|
|
15611
|
-
function canDeleteSelectionForEveryone(selectedKeys, messages, isGroup) {
|
|
16216
|
+
function canDeleteSelectionForEveryone(selectedKeys, messages, isGroup, timers = DEFAULT_EFFECTIVE_SETTINGS.messageTimers) {
|
|
15612
16217
|
if (selectedKeys.size === 0) return false;
|
|
15613
16218
|
const parsed = [...selectedKeys].map((key) => parseSelectionKey(key));
|
|
15614
16219
|
const messageIds = new Set(parsed.map((entry) => entry.messageId));
|
|
@@ -15616,7 +16221,7 @@ function canDeleteSelectionForEveryone(selectedKeys, messages, isGroup) {
|
|
|
15616
16221
|
const messageId2 = [...messageIds][0];
|
|
15617
16222
|
const message = messages.find((entry) => String(entry._id || entry.id) === messageId2);
|
|
15618
16223
|
if (!message?.isOwnMessage) return false;
|
|
15619
|
-
if (!
|
|
16224
|
+
if (!isWithinMessageDeleteWindow2(message.timestamp, isGroup, timers)) return false;
|
|
15620
16225
|
const hasAttachmentKey = parsed.some((entry) => entry.attachmentId);
|
|
15621
16226
|
if (!hasAttachmentKey) {
|
|
15622
16227
|
return selectedKeys.size === 1;
|
|
@@ -15785,6 +16390,8 @@ function useActiveChannelMessages({
|
|
|
15785
16390
|
const emitDmDelete = useStore((s) => s.emitDmDelete);
|
|
15786
16391
|
const emitGroupDelete = useStore((s) => s.emitGroupDelete);
|
|
15787
16392
|
const loggedUserDetails = useStore((s) => s.loggedUserDetails);
|
|
16393
|
+
const { settings } = useEffectiveSettingsOptional();
|
|
16394
|
+
const messageTimers = settings.messageTimers;
|
|
15788
16395
|
const scrollContainerRef = useRef(null);
|
|
15789
16396
|
const bottomRef = useRef(null);
|
|
15790
16397
|
const messageListInitializedRef = useRef(false);
|
|
@@ -15903,8 +16510,13 @@ function useActiveChannelMessages({
|
|
|
15903
16510
|
}, []);
|
|
15904
16511
|
const selectedForwardItems = resolveForwardItems(selectedKeys, displayMessages);
|
|
15905
16512
|
const canDeleteForEveryone = useMemo(
|
|
15906
|
-
() => canDeleteSelectionForEveryone(
|
|
15907
|
-
|
|
16513
|
+
() => canDeleteSelectionForEveryone(
|
|
16514
|
+
selectedKeys,
|
|
16515
|
+
displayMessages,
|
|
16516
|
+
!!activeChannel?.isGroup,
|
|
16517
|
+
messageTimers
|
|
16518
|
+
),
|
|
16519
|
+
[selectedKeys, displayMessages, activeChannel?.isGroup, messageTimers]
|
|
15908
16520
|
);
|
|
15909
16521
|
const emitSelectionDelete = useCallback(
|
|
15910
16522
|
(deleteType) => {
|
|
@@ -15912,7 +16524,8 @@ function useActiveChannelMessages({
|
|
|
15912
16524
|
if (deleteType === "everyone" && !canDeleteSelectionForEveryone(
|
|
15913
16525
|
selectedKeys,
|
|
15914
16526
|
displayMessages,
|
|
15915
|
-
!!activeChannel?.isGroup
|
|
16527
|
+
!!activeChannel?.isGroup,
|
|
16528
|
+
messageTimers
|
|
15916
16529
|
)) {
|
|
15917
16530
|
return;
|
|
15918
16531
|
}
|
|
@@ -15953,7 +16566,8 @@ function useActiveChannelMessages({
|
|
|
15953
16566
|
conversationId,
|
|
15954
16567
|
emitGroupDelete,
|
|
15955
16568
|
emitDmDelete,
|
|
15956
|
-
clearSelection
|
|
16569
|
+
clearSelection,
|
|
16570
|
+
messageTimers
|
|
15957
16571
|
]
|
|
15958
16572
|
);
|
|
15959
16573
|
const handleBatchDeleteForMe = useCallback(() => {
|
|
@@ -16291,8 +16905,8 @@ function CalendarDayButton({
|
|
|
16291
16905
|
...props
|
|
16292
16906
|
}) {
|
|
16293
16907
|
const defaultClassNames = getDefaultClassNames();
|
|
16294
|
-
const ref =
|
|
16295
|
-
|
|
16908
|
+
const ref = React3.useRef(null);
|
|
16909
|
+
React3.useEffect(() => {
|
|
16296
16910
|
if (modifiers.focused) ref.current?.focus();
|
|
16297
16911
|
}, [modifiers.focused]);
|
|
16298
16912
|
return /* @__PURE__ */ jsx(
|
|
@@ -17196,7 +17810,6 @@ var getAttachmentType = (file) => {
|
|
|
17196
17810
|
};
|
|
17197
17811
|
|
|
17198
17812
|
// src/chat/channel-message-box/useChannelMessageBox.ts
|
|
17199
|
-
var MAX_ATTACHMENTS = COMPOSER_MAX_ATTACHMENTS;
|
|
17200
17813
|
function useChannelMessageBox({
|
|
17201
17814
|
activeChannel,
|
|
17202
17815
|
conversationId,
|
|
@@ -17210,6 +17823,12 @@ function useChannelMessageBox({
|
|
|
17210
17823
|
conversationId,
|
|
17211
17824
|
onActiveChannelPatch
|
|
17212
17825
|
);
|
|
17826
|
+
const { settings, getAttachmentsGate } = useEffectiveSettingsOptional();
|
|
17827
|
+
const attachmentsGate = getAttachmentsGate();
|
|
17828
|
+
const maxAttachments = settings.attachments.maxAttachmentsPerMessage;
|
|
17829
|
+
const maxFileSizeBytes = settings.attachments.maxFileSizeMB * 1024 * 1024;
|
|
17830
|
+
const allowedMimeTypes = settings.attachments.allowedMimeTypes;
|
|
17831
|
+
const acceptAttribute = buildAcceptFromMimeTypes(allowedMimeTypes);
|
|
17213
17832
|
const [state, setState] = useState({
|
|
17214
17833
|
messageInput: "",
|
|
17215
17834
|
attachments: [],
|
|
@@ -17234,10 +17853,10 @@ function useChannelMessageBox({
|
|
|
17234
17853
|
const composerDisabledReason = conversationId ? composerDisabledByConversation[conversationId] : void 0;
|
|
17235
17854
|
const fileInputRef = useRef(null);
|
|
17236
17855
|
const attachmentsCountRef = useRef(0);
|
|
17237
|
-
|
|
17856
|
+
React3__default.useEffect(() => {
|
|
17238
17857
|
attachmentsCountRef.current = state.attachments.length;
|
|
17239
17858
|
}, [state.attachments.length]);
|
|
17240
|
-
|
|
17859
|
+
React3__default.useEffect(() => {
|
|
17241
17860
|
const draft = {
|
|
17242
17861
|
messageInput: state.messageInput,
|
|
17243
17862
|
attachments: state.attachments
|
|
@@ -17245,7 +17864,7 @@ function useChannelMessageBox({
|
|
|
17245
17864
|
syncComposerRef(draft);
|
|
17246
17865
|
updateConversationDraft(conversationIdRef.current, draft);
|
|
17247
17866
|
}, [state.messageInput, state.attachments, syncComposerRef]);
|
|
17248
|
-
|
|
17867
|
+
React3__default.useEffect(() => {
|
|
17249
17868
|
if (typingTimeoutRef.current) {
|
|
17250
17869
|
clearTimeout(typingTimeoutRef.current);
|
|
17251
17870
|
typingTimeoutRef.current = null;
|
|
@@ -17305,21 +17924,52 @@ function useChannelMessageBox({
|
|
|
17305
17924
|
const handleFileChange = (e) => {
|
|
17306
17925
|
const files = e.target.files ? Array.from(e.target.files) : [];
|
|
17307
17926
|
if (!files.length) return;
|
|
17927
|
+
if (!attachmentsGate.enabled) {
|
|
17928
|
+
updateState({
|
|
17929
|
+
attachmentError: attachmentsGate.disabledReason || "Attachments are disabled by your administrator."
|
|
17930
|
+
});
|
|
17931
|
+
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
17932
|
+
return;
|
|
17933
|
+
}
|
|
17308
17934
|
const currentCount = attachmentsCountRef.current;
|
|
17309
|
-
const remaining =
|
|
17935
|
+
const remaining = maxAttachments - currentCount;
|
|
17310
17936
|
if (remaining <= 0) {
|
|
17311
|
-
updateState({ attachmentError: `Maximum ${
|
|
17937
|
+
updateState({ attachmentError: `Maximum ${maxAttachments} files allowed` });
|
|
17312
17938
|
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
17313
17939
|
return;
|
|
17314
17940
|
}
|
|
17315
|
-
|
|
17941
|
+
const validFiles = [];
|
|
17942
|
+
const rejectionMessages = [];
|
|
17943
|
+
for (const file of files) {
|
|
17944
|
+
if (!matchesAllowedMimeType(file.type, allowedMimeTypes)) {
|
|
17945
|
+
rejectionMessages.push(`"${file.name}" type is not allowed`);
|
|
17946
|
+
continue;
|
|
17947
|
+
}
|
|
17948
|
+
if (file.size > maxFileSizeBytes) {
|
|
17949
|
+
rejectionMessages.push(
|
|
17950
|
+
`"${file.name}" exceeds ${settings.attachments.maxFileSizeMB} MB (got ${formatFileSizeMB(file.size)})`
|
|
17951
|
+
);
|
|
17952
|
+
continue;
|
|
17953
|
+
}
|
|
17954
|
+
validFiles.push(file);
|
|
17955
|
+
}
|
|
17956
|
+
if (validFiles.length === 0) {
|
|
17957
|
+
updateState({
|
|
17958
|
+
attachmentError: rejectionMessages[0] || "Selected files are not allowed"
|
|
17959
|
+
});
|
|
17960
|
+
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
17961
|
+
return;
|
|
17962
|
+
}
|
|
17963
|
+
if (validFiles.length > remaining) {
|
|
17316
17964
|
updateState({
|
|
17317
17965
|
attachmentError: `You can upload only ${remaining} more file${remaining > 1 ? "s" : ""}`
|
|
17318
17966
|
});
|
|
17967
|
+
} else if (rejectionMessages.length > 0) {
|
|
17968
|
+
updateState({ attachmentError: rejectionMessages[0] });
|
|
17319
17969
|
} else {
|
|
17320
17970
|
updateState({ attachmentError: "" });
|
|
17321
17971
|
}
|
|
17322
|
-
const filesToAdd =
|
|
17972
|
+
const filesToAdd = validFiles.slice(0, remaining);
|
|
17323
17973
|
attachmentsCountRef.current = currentCount + filesToAdd.length;
|
|
17324
17974
|
const newAttachments = filesToAdd.map((file) => ({
|
|
17325
17975
|
id: `att-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
@@ -17376,7 +18026,7 @@ function useChannelMessageBox({
|
|
|
17376
18026
|
return {
|
|
17377
18027
|
...prev,
|
|
17378
18028
|
attachments: nextAttachments,
|
|
17379
|
-
attachmentError: nextAttachments.length <
|
|
18029
|
+
attachmentError: nextAttachments.length < maxAttachments ? "" : prev.attachmentError
|
|
17380
18030
|
};
|
|
17381
18031
|
});
|
|
17382
18032
|
};
|
|
@@ -17483,7 +18133,10 @@ function useChannelMessageBox({
|
|
|
17483
18133
|
onlyAdminCanSendMessage,
|
|
17484
18134
|
fileInputRef,
|
|
17485
18135
|
hasUploadingAttachments,
|
|
17486
|
-
maxAttachments
|
|
18136
|
+
maxAttachments,
|
|
18137
|
+
acceptAttribute,
|
|
18138
|
+
attachmentsEnabled: attachmentsGate.enabled,
|
|
18139
|
+
attachmentsDisabledReason: attachmentsGate.disabledReason,
|
|
17487
18140
|
handleInputChange,
|
|
17488
18141
|
handleFileChange,
|
|
17489
18142
|
handleRemoveAttachment,
|
|
@@ -17511,6 +18164,9 @@ var ChannelMessageBoxView = (props) => {
|
|
|
17511
18164
|
fileInputRef,
|
|
17512
18165
|
hasUploadingAttachments,
|
|
17513
18166
|
maxAttachments,
|
|
18167
|
+
acceptAttribute,
|
|
18168
|
+
attachmentsEnabled,
|
|
18169
|
+
attachmentsDisabledReason,
|
|
17514
18170
|
handleInputChange,
|
|
17515
18171
|
handleFileChange,
|
|
17516
18172
|
handleRemoveAttachment,
|
|
@@ -17608,16 +18264,23 @@ var ChannelMessageBoxView = (props) => {
|
|
|
17608
18264
|
),
|
|
17609
18265
|
/* @__PURE__ */ jsxs("div", { className: "flex items-end gap-1.5 p-1.5", children: [
|
|
17610
18266
|
/* @__PURE__ */ jsx(
|
|
17611
|
-
|
|
18267
|
+
AdminPermissionTooltip,
|
|
17612
18268
|
{
|
|
17613
|
-
|
|
17614
|
-
|
|
17615
|
-
|
|
17616
|
-
|
|
17617
|
-
|
|
17618
|
-
|
|
17619
|
-
|
|
17620
|
-
|
|
18269
|
+
disabled: !attachmentsEnabled,
|
|
18270
|
+
message: attachmentsDisabledReason,
|
|
18271
|
+
children: /* @__PURE__ */ jsx(
|
|
18272
|
+
Button,
|
|
18273
|
+
{
|
|
18274
|
+
type: "button",
|
|
18275
|
+
variant: "ghost",
|
|
18276
|
+
size: "icon",
|
|
18277
|
+
className: "shrink-0 size-9 rounded-xl text-(--chat-muted) transition-all hover:bg-(--chat-hover) hover:text-(--chat-text) disabled:opacity-40",
|
|
18278
|
+
onClick: () => attachmentsEnabled && !hasUploadingAttachments && fileInputRef.current?.click(),
|
|
18279
|
+
disabled: !attachmentsEnabled || hasUploadingAttachments,
|
|
18280
|
+
"aria-label": "Attach files",
|
|
18281
|
+
children: /* @__PURE__ */ jsx(Paperclip, { size: 16 })
|
|
18282
|
+
}
|
|
18283
|
+
)
|
|
17621
18284
|
}
|
|
17622
18285
|
),
|
|
17623
18286
|
/* @__PURE__ */ jsx(
|
|
@@ -17627,8 +18290,9 @@ var ChannelMessageBoxView = (props) => {
|
|
|
17627
18290
|
ref: fileInputRef,
|
|
17628
18291
|
className: "hidden",
|
|
17629
18292
|
multiple: true,
|
|
17630
|
-
accept:
|
|
17631
|
-
onChange: handleFileChange
|
|
18293
|
+
accept: acceptAttribute || void 0,
|
|
18294
|
+
onChange: handleFileChange,
|
|
18295
|
+
disabled: !attachmentsEnabled
|
|
17632
18296
|
}
|
|
17633
18297
|
),
|
|
17634
18298
|
/* @__PURE__ */ jsxs(Popover, { children: [
|
|
@@ -18543,8 +19207,8 @@ var ChatMain = ({
|
|
|
18543
19207
|
viewportHeight = "full",
|
|
18544
19208
|
viewportClassName
|
|
18545
19209
|
}) => {
|
|
18546
|
-
const clientObj =
|
|
18547
|
-
const uiConfigObj =
|
|
19210
|
+
const clientObj = React3__default.useMemo(() => ({ id: clientId }), [clientId]);
|
|
19211
|
+
const uiConfigObj = React3__default.useMemo(
|
|
18548
19212
|
() => ({
|
|
18549
19213
|
...uiConfig || {},
|
|
18550
19214
|
components: { ...uiConfig?.components, ...components },
|
|
@@ -18915,8 +19579,10 @@ var packageDefaultComponents = {
|
|
|
18915
19579
|
};
|
|
18916
19580
|
|
|
18917
19581
|
// src/index.ts
|
|
19582
|
+
init_settings_types();
|
|
19583
|
+
init_api_service();
|
|
18918
19584
|
var index_default = ChatMain_default;
|
|
18919
19585
|
|
|
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 };
|
|
19586
|
+
export { ADMIN_PERMISSION_DENIED_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
19587
|
//# sourceMappingURL=index.mjs.map
|
|
18922
19588
|
//# sourceMappingURL=index.mjs.map
|