@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.cjs
CHANGED
|
@@ -6,7 +6,7 @@ var socket_ioClient = require('socket.io-client');
|
|
|
6
6
|
var axios = require('axios');
|
|
7
7
|
var zustand = require('zustand');
|
|
8
8
|
var middleware = require('zustand/middleware');
|
|
9
|
-
var
|
|
9
|
+
var React3 = require('react');
|
|
10
10
|
var radixUi = require('radix-ui');
|
|
11
11
|
var clsx = require('clsx');
|
|
12
12
|
var tailwindMerge = require('tailwind-merge');
|
|
@@ -39,7 +39,7 @@ function _interopNamespace(e) {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
var axios__default = /*#__PURE__*/_interopDefault(axios);
|
|
42
|
-
var
|
|
42
|
+
var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
|
|
43
43
|
var EmojiPicker__default = /*#__PURE__*/_interopDefault(EmojiPicker);
|
|
44
44
|
var toast__default = /*#__PURE__*/_interopDefault(toast);
|
|
45
45
|
|
|
@@ -1190,6 +1190,7 @@ function resolveChatApiKey(url) {
|
|
|
1190
1190
|
}
|
|
1191
1191
|
if (path.includes("/message/search-messages")) return "searchMessages";
|
|
1192
1192
|
if (path.includes("/message/searched-message/context")) return "searchMessagesContext";
|
|
1193
|
+
if (path.includes("/settings/effective")) return "effectiveSettings";
|
|
1193
1194
|
if (path.includes("/conversation/group/create")) return "createGroup";
|
|
1194
1195
|
if (path.includes("/conversation/group/permission/update")) return "updateGroupPermissions";
|
|
1195
1196
|
if (path.includes("/conversation/group/information/update")) return "updateGroupInfo";
|
|
@@ -1233,7 +1234,8 @@ var init_query_params = __esm({
|
|
|
1233
1234
|
"pinnedMessages",
|
|
1234
1235
|
"starredMessages",
|
|
1235
1236
|
"searchMessages",
|
|
1236
|
-
"searchMessagesContext"
|
|
1237
|
+
"searchMessagesContext",
|
|
1238
|
+
"effectiveSettings"
|
|
1237
1239
|
];
|
|
1238
1240
|
exports.CHAT_API_KEYS = [
|
|
1239
1241
|
"all",
|
|
@@ -1258,8 +1260,8 @@ var init_api_version = __esm({
|
|
|
1258
1260
|
"src/services/api/api-version.ts"() {
|
|
1259
1261
|
init_client();
|
|
1260
1262
|
DEFAULT_VERSIONS = {
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
+
v1: "v1",
|
|
1264
|
+
v2: "v2"
|
|
1263
1265
|
};
|
|
1264
1266
|
apiVersions = { ...DEFAULT_VERSIONS };
|
|
1265
1267
|
normalizeApiVersion = (version) => {
|
|
@@ -1278,7 +1280,7 @@ var init_api_version = __esm({
|
|
|
1278
1280
|
exports.buildVersionedApiUrl = (path, options) => {
|
|
1279
1281
|
const root = exports.resolveApiRoot(options?.baseUrl);
|
|
1280
1282
|
const version = normalizeApiVersion(
|
|
1281
|
-
options?.version ?? (options?.service ? apiVersions[options.service] : apiVersions.
|
|
1283
|
+
options?.version ?? (options?.service ? apiVersions[options.service] : apiVersions.v1)
|
|
1282
1284
|
);
|
|
1283
1285
|
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
1284
1286
|
if (!root) {
|
|
@@ -1288,23 +1290,23 @@ var init_api_version = __esm({
|
|
|
1288
1290
|
};
|
|
1289
1291
|
exports.setChatApiVersions = (config) => {
|
|
1290
1292
|
if (!config) return;
|
|
1291
|
-
if (config.
|
|
1292
|
-
apiVersions.
|
|
1293
|
+
if (config.v1) {
|
|
1294
|
+
apiVersions.v1 = normalizeApiVersion(config.v1);
|
|
1293
1295
|
}
|
|
1294
|
-
if (config.
|
|
1295
|
-
apiVersions.
|
|
1296
|
+
if (config.v2) {
|
|
1297
|
+
apiVersions.v2 = normalizeApiVersion(config.v2);
|
|
1296
1298
|
}
|
|
1297
1299
|
};
|
|
1298
1300
|
exports.getChatApiVersions = () => ({
|
|
1299
1301
|
...apiVersions
|
|
1300
1302
|
});
|
|
1301
1303
|
exports.setChatPushApiVersion = (version) => {
|
|
1302
|
-
apiVersions.
|
|
1304
|
+
apiVersions.v2 = normalizeApiVersion(version);
|
|
1303
1305
|
};
|
|
1304
1306
|
syncDefaultApiVersionFromBaseUrl = (baseUrl) => {
|
|
1305
1307
|
const match = String(baseUrl || "").trim().match(/\/(v\d+)\/?$/i);
|
|
1306
1308
|
if (match?.[1]) {
|
|
1307
|
-
apiVersions.
|
|
1309
|
+
apiVersions.v1 = normalizeApiVersion(match[1]);
|
|
1308
1310
|
}
|
|
1309
1311
|
};
|
|
1310
1312
|
}
|
|
@@ -1449,6 +1451,9 @@ var init_api_constants = __esm({
|
|
|
1449
1451
|
SEARCH_MESSAGES: "/message/search-messages",
|
|
1450
1452
|
SEARCH_MESSAGES_CONTEXT: (messageId2) => `/message/searched-message/context?messageId=${messageId2}`,
|
|
1451
1453
|
BLOCK_UNBLOCK_USER: "/user/block-unblock"
|
|
1454
|
+
},
|
|
1455
|
+
SETTINGS: {
|
|
1456
|
+
PERMISSIONS: "/settings/effective"
|
|
1452
1457
|
}
|
|
1453
1458
|
};
|
|
1454
1459
|
}
|
|
@@ -1485,13 +1490,11 @@ var init_auth_api = __esm({
|
|
|
1485
1490
|
});
|
|
1486
1491
|
|
|
1487
1492
|
// src/constants/chat.constants.ts
|
|
1488
|
-
var DEFAULT_MESSAGES_LIMIT, DEFAULT_CONVERSATIONS_LIMIT,
|
|
1493
|
+
var DEFAULT_MESSAGES_LIMIT, DEFAULT_CONVERSATIONS_LIMIT, MAX_ATTACHMENT_CAPTION_LENGTH, ATTACHMENT_FILENAME_TIMESTAMP_LENGTH;
|
|
1489
1494
|
var init_chat_constants = __esm({
|
|
1490
1495
|
"src/constants/chat.constants.ts"() {
|
|
1491
1496
|
DEFAULT_MESSAGES_LIMIT = 20;
|
|
1492
1497
|
DEFAULT_CONVERSATIONS_LIMIT = 20;
|
|
1493
|
-
DM_EDIT_WINDOW_MS = 5 * 60 * 1e3;
|
|
1494
|
-
GROUP_EDIT_WINDOW_MS = 10 * 60 * 1e3;
|
|
1495
1498
|
MAX_ATTACHMENT_CAPTION_LENGTH = 100;
|
|
1496
1499
|
ATTACHMENT_FILENAME_TIMESTAMP_LENGTH = 13;
|
|
1497
1500
|
}
|
|
@@ -1694,6 +1697,206 @@ var init_uploads_api = __esm({
|
|
|
1694
1697
|
}
|
|
1695
1698
|
});
|
|
1696
1699
|
|
|
1700
|
+
// src/types/settings.types.ts
|
|
1701
|
+
exports.DEFAULT_EFFECTIVE_SETTINGS = void 0; exports.ADMIN_PERMISSION_DENIED_MESSAGE = void 0; exports.CALLS_NOT_CONFIGURED_MESSAGE = void 0;
|
|
1702
|
+
var init_settings_types = __esm({
|
|
1703
|
+
"src/types/settings.types.ts"() {
|
|
1704
|
+
exports.DEFAULT_EFFECTIVE_SETTINGS = {
|
|
1705
|
+
pushNotificationEnabled: true,
|
|
1706
|
+
videoCallEnabled: true,
|
|
1707
|
+
audioCallEnabled: true,
|
|
1708
|
+
blockUsersEnabled: true,
|
|
1709
|
+
calls: {
|
|
1710
|
+
enabled: true,
|
|
1711
|
+
configured: true
|
|
1712
|
+
},
|
|
1713
|
+
groupPolicy: {
|
|
1714
|
+
defaults: {
|
|
1715
|
+
onlyAdminCanSendMessage: false,
|
|
1716
|
+
onlyAdminCanEditInfo: false,
|
|
1717
|
+
senderCanEditMessage: true,
|
|
1718
|
+
allowMemberAdd: true,
|
|
1719
|
+
allowMemberRemove: false,
|
|
1720
|
+
moderationEnabled: false
|
|
1721
|
+
},
|
|
1722
|
+
locked: []
|
|
1723
|
+
},
|
|
1724
|
+
messageTimers: {
|
|
1725
|
+
dmEditMinutes: 5,
|
|
1726
|
+
dmDeleteMinutes: 5,
|
|
1727
|
+
groupEditMinutes: 10,
|
|
1728
|
+
groupDeleteMinutes: 10
|
|
1729
|
+
},
|
|
1730
|
+
attachments: {
|
|
1731
|
+
enabled: true,
|
|
1732
|
+
maxFileSizeMB: 10,
|
|
1733
|
+
allowedMimeTypes: ["image/*", "video/*", "audio/*", "application/pdf"],
|
|
1734
|
+
maxAttachmentsPerMessage: 10
|
|
1735
|
+
},
|
|
1736
|
+
maxAdminsPerGroup: 5,
|
|
1737
|
+
maxParticipantsPerGroup: 100,
|
|
1738
|
+
maxPinnedMessagesPerConversation: 10,
|
|
1739
|
+
groupCreationEnabled: true
|
|
1740
|
+
};
|
|
1741
|
+
exports.ADMIN_PERMISSION_DENIED_MESSAGE = "This feature is disabled by your administrator.";
|
|
1742
|
+
exports.CALLS_NOT_CONFIGURED_MESSAGE = "Calls are not configured. Please contact your administrator.";
|
|
1743
|
+
}
|
|
1744
|
+
});
|
|
1745
|
+
|
|
1746
|
+
// src/services/api/settings.api.ts
|
|
1747
|
+
function asBoolean(value, fallback) {
|
|
1748
|
+
return typeof value === "boolean" ? value : fallback;
|
|
1749
|
+
}
|
|
1750
|
+
function asPositiveNumber(value, fallback) {
|
|
1751
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
|
|
1752
|
+
}
|
|
1753
|
+
function asStringArray(value, fallback) {
|
|
1754
|
+
if (!Array.isArray(value)) return fallback;
|
|
1755
|
+
const next = value.filter((item) => typeof item === "string");
|
|
1756
|
+
return next.length > 0 ? next : fallback;
|
|
1757
|
+
}
|
|
1758
|
+
function normalizeGroupPermissions(value, fallback) {
|
|
1759
|
+
if (!value || typeof value !== "object") return { ...fallback };
|
|
1760
|
+
const raw = value;
|
|
1761
|
+
return {
|
|
1762
|
+
onlyAdminCanSendMessage: asBoolean(
|
|
1763
|
+
raw.onlyAdminCanSendMessage,
|
|
1764
|
+
fallback.onlyAdminCanSendMessage
|
|
1765
|
+
),
|
|
1766
|
+
onlyAdminCanEditInfo: asBoolean(
|
|
1767
|
+
raw.onlyAdminCanEditInfo,
|
|
1768
|
+
fallback.onlyAdminCanEditInfo
|
|
1769
|
+
),
|
|
1770
|
+
senderCanEditMessage: asBoolean(
|
|
1771
|
+
raw.senderCanEditMessage,
|
|
1772
|
+
fallback.senderCanEditMessage
|
|
1773
|
+
),
|
|
1774
|
+
allowMemberAdd: asBoolean(raw.allowMemberAdd, fallback.allowMemberAdd),
|
|
1775
|
+
allowMemberRemove: asBoolean(
|
|
1776
|
+
raw.allowMemberRemove,
|
|
1777
|
+
fallback.allowMemberRemove
|
|
1778
|
+
),
|
|
1779
|
+
moderationEnabled: asBoolean(
|
|
1780
|
+
raw.moderationEnabled,
|
|
1781
|
+
fallback.moderationEnabled
|
|
1782
|
+
)
|
|
1783
|
+
};
|
|
1784
|
+
}
|
|
1785
|
+
function normalizeCalls(value, fallback) {
|
|
1786
|
+
if (!value || typeof value !== "object") return { ...fallback };
|
|
1787
|
+
const raw = value;
|
|
1788
|
+
return {
|
|
1789
|
+
enabled: asBoolean(raw.enabled, fallback.enabled),
|
|
1790
|
+
configured: asBoolean(raw.configured, fallback.configured)
|
|
1791
|
+
};
|
|
1792
|
+
}
|
|
1793
|
+
function normalizeGroupPolicy(value, fallback) {
|
|
1794
|
+
if (!value || typeof value !== "object") {
|
|
1795
|
+
return {
|
|
1796
|
+
defaults: { ...fallback.defaults },
|
|
1797
|
+
locked: [...fallback.locked]
|
|
1798
|
+
};
|
|
1799
|
+
}
|
|
1800
|
+
const raw = value;
|
|
1801
|
+
return {
|
|
1802
|
+
defaults: normalizeGroupPermissions(raw.defaults, fallback.defaults),
|
|
1803
|
+
locked: asStringArray(raw.locked, fallback.locked)
|
|
1804
|
+
};
|
|
1805
|
+
}
|
|
1806
|
+
function normalizeMessageTimers(value, fallback) {
|
|
1807
|
+
if (!value || typeof value !== "object") return { ...fallback };
|
|
1808
|
+
const raw = value;
|
|
1809
|
+
return {
|
|
1810
|
+
dmEditMinutes: asPositiveNumber(raw.dmEditMinutes, fallback.dmEditMinutes),
|
|
1811
|
+
dmDeleteMinutes: asPositiveNumber(
|
|
1812
|
+
raw.dmDeleteMinutes,
|
|
1813
|
+
fallback.dmDeleteMinutes
|
|
1814
|
+
),
|
|
1815
|
+
groupEditMinutes: asPositiveNumber(
|
|
1816
|
+
raw.groupEditMinutes,
|
|
1817
|
+
fallback.groupEditMinutes
|
|
1818
|
+
),
|
|
1819
|
+
groupDeleteMinutes: asPositiveNumber(
|
|
1820
|
+
raw.groupDeleteMinutes,
|
|
1821
|
+
fallback.groupDeleteMinutes
|
|
1822
|
+
)
|
|
1823
|
+
};
|
|
1824
|
+
}
|
|
1825
|
+
function normalizeAttachments(value, fallback) {
|
|
1826
|
+
if (!value || typeof value !== "object") return { ...fallback };
|
|
1827
|
+
const raw = value;
|
|
1828
|
+
return {
|
|
1829
|
+
enabled: asBoolean(raw.enabled, fallback.enabled),
|
|
1830
|
+
maxFileSizeMB: asPositiveNumber(raw.maxFileSizeMB, fallback.maxFileSizeMB),
|
|
1831
|
+
allowedMimeTypes: asStringArray(
|
|
1832
|
+
raw.allowedMimeTypes,
|
|
1833
|
+
fallback.allowedMimeTypes
|
|
1834
|
+
),
|
|
1835
|
+
maxAttachmentsPerMessage: asPositiveNumber(
|
|
1836
|
+
raw.maxAttachmentsPerMessage,
|
|
1837
|
+
fallback.maxAttachmentsPerMessage
|
|
1838
|
+
)
|
|
1839
|
+
};
|
|
1840
|
+
}
|
|
1841
|
+
function normalizeEffectiveSettings(raw) {
|
|
1842
|
+
const payload = raw && typeof raw === "object" ? raw.data ?? raw : null;
|
|
1843
|
+
const source = payload && typeof payload === "object" ? payload : {};
|
|
1844
|
+
const defaults = exports.DEFAULT_EFFECTIVE_SETTINGS;
|
|
1845
|
+
return {
|
|
1846
|
+
pushNotificationEnabled: asBoolean(
|
|
1847
|
+
source.pushNotificationEnabled,
|
|
1848
|
+
defaults.pushNotificationEnabled
|
|
1849
|
+
),
|
|
1850
|
+
videoCallEnabled: asBoolean(
|
|
1851
|
+
source.videoCallEnabled,
|
|
1852
|
+
defaults.videoCallEnabled
|
|
1853
|
+
),
|
|
1854
|
+
audioCallEnabled: asBoolean(
|
|
1855
|
+
source.audioCallEnabled,
|
|
1856
|
+
defaults.audioCallEnabled
|
|
1857
|
+
),
|
|
1858
|
+
blockUsersEnabled: asBoolean(
|
|
1859
|
+
source.blockUsersEnabled,
|
|
1860
|
+
defaults.blockUsersEnabled
|
|
1861
|
+
),
|
|
1862
|
+
calls: normalizeCalls(source.calls, defaults.calls),
|
|
1863
|
+
groupPolicy: normalizeGroupPolicy(source.groupPolicy, defaults.groupPolicy),
|
|
1864
|
+
messageTimers: normalizeMessageTimers(
|
|
1865
|
+
source.messageTimers,
|
|
1866
|
+
defaults.messageTimers
|
|
1867
|
+
),
|
|
1868
|
+
attachments: normalizeAttachments(source.attachments, defaults.attachments),
|
|
1869
|
+
maxAdminsPerGroup: asPositiveNumber(
|
|
1870
|
+
source.maxAdminsPerGroup,
|
|
1871
|
+
defaults.maxAdminsPerGroup
|
|
1872
|
+
),
|
|
1873
|
+
maxParticipantsPerGroup: asPositiveNumber(
|
|
1874
|
+
source.maxParticipantsPerGroup,
|
|
1875
|
+
defaults.maxParticipantsPerGroup
|
|
1876
|
+
),
|
|
1877
|
+
maxPinnedMessagesPerConversation: asPositiveNumber(
|
|
1878
|
+
source.maxPinnedMessagesPerConversation,
|
|
1879
|
+
defaults.maxPinnedMessagesPerConversation
|
|
1880
|
+
),
|
|
1881
|
+
groupCreationEnabled: asBoolean(
|
|
1882
|
+
source.groupCreationEnabled,
|
|
1883
|
+
defaults.groupCreationEnabled
|
|
1884
|
+
)
|
|
1885
|
+
};
|
|
1886
|
+
}
|
|
1887
|
+
exports.fetchEffectiveSettings = void 0;
|
|
1888
|
+
var init_settings_api = __esm({
|
|
1889
|
+
"src/services/api/settings.api.ts"() {
|
|
1890
|
+
init_api_constants();
|
|
1891
|
+
init_client();
|
|
1892
|
+
init_settings_types();
|
|
1893
|
+
exports.fetchEffectiveSettings = async () => {
|
|
1894
|
+
const response = await apiClient.get(API_ENDPOINTS.SETTINGS.PERMISSIONS);
|
|
1895
|
+
return normalizeEffectiveSettings(response.data);
|
|
1896
|
+
};
|
|
1897
|
+
}
|
|
1898
|
+
});
|
|
1899
|
+
|
|
1697
1900
|
// src/services/api/index.ts
|
|
1698
1901
|
var init_api = __esm({
|
|
1699
1902
|
"src/services/api/index.ts"() {
|
|
@@ -1702,6 +1905,7 @@ var init_api = __esm({
|
|
|
1702
1905
|
init_messages_api();
|
|
1703
1906
|
init_groups_api();
|
|
1704
1907
|
init_uploads_api();
|
|
1908
|
+
init_settings_api();
|
|
1705
1909
|
}
|
|
1706
1910
|
});
|
|
1707
1911
|
|
|
@@ -4385,7 +4589,7 @@ var syncLocalMessagesOnDmMarkRead = (prev, lastDMMarkRead, conversations, logged
|
|
|
4385
4589
|
|
|
4386
4590
|
// src/hooks/chat-sync/useChatSync.ts
|
|
4387
4591
|
var useChatSync = () => {
|
|
4388
|
-
const [localMessages, setLocalMessages] =
|
|
4592
|
+
const [localMessages, setLocalMessages] = React3.useState({});
|
|
4389
4593
|
const lastDM = useSocketStore((s) => s.lastDM);
|
|
4390
4594
|
const lastEditDM = useSocketStore((s) => s.lastEditDM);
|
|
4391
4595
|
const lastDeleteDM = useSocketStore((s) => s.lastDeleteDM);
|
|
@@ -4398,17 +4602,17 @@ var useChatSync = () => {
|
|
|
4398
4602
|
const messagesByConversation = useSocketStore((s) => s.messagesByConversation);
|
|
4399
4603
|
const messagesMetadata = useSocketStore((s) => s.messagesMetadata);
|
|
4400
4604
|
const loggedUserDetails = useAuthStore((s) => s.loggedUserDetails);
|
|
4401
|
-
|
|
4605
|
+
React3.useEffect(() => {
|
|
4402
4606
|
setLocalMessages(
|
|
4403
4607
|
(prev) => syncLocalMessagesOnStoreClear(prev, messagesByConversation, messagesMetadata)
|
|
4404
4608
|
);
|
|
4405
4609
|
}, [messagesByConversation, messagesMetadata]);
|
|
4406
|
-
|
|
4610
|
+
React3.useEffect(() => {
|
|
4407
4611
|
if (lastPinUpdate) {
|
|
4408
4612
|
setLocalMessages((prev) => syncLocalMessagesOnPinUpdate(prev, lastPinUpdate));
|
|
4409
4613
|
}
|
|
4410
4614
|
}, [lastPinUpdate]);
|
|
4411
|
-
|
|
4615
|
+
React3.useEffect(() => {
|
|
4412
4616
|
if (lastStarUpdate) {
|
|
4413
4617
|
setLocalMessages((prev) => {
|
|
4414
4618
|
const next = syncLocalMessagesOnStarUpdate(
|
|
@@ -4420,18 +4624,18 @@ var useChatSync = () => {
|
|
|
4420
4624
|
});
|
|
4421
4625
|
}
|
|
4422
4626
|
}, [lastStarUpdate, loggedUserDetails?._id]);
|
|
4423
|
-
|
|
4627
|
+
React3.useEffect(() => {
|
|
4424
4628
|
if (!lastReactionUpdate) return;
|
|
4425
4629
|
setLocalMessages(
|
|
4426
4630
|
(prev) => syncLocalMessagesOnReactionUpdate(prev, lastReactionUpdate, messagesByConversation)
|
|
4427
4631
|
);
|
|
4428
4632
|
}, [lastReactionUpdate, messagesByConversation]);
|
|
4429
|
-
|
|
4633
|
+
React3.useEffect(() => {
|
|
4430
4634
|
if (lastDeleteDM) {
|
|
4431
4635
|
setLocalMessages((prev) => syncLocalMessagesOnDelete(prev, lastDeleteDM));
|
|
4432
4636
|
}
|
|
4433
4637
|
}, [lastDeleteDM]);
|
|
4434
|
-
|
|
4638
|
+
React3.useEffect(() => {
|
|
4435
4639
|
if (lastEditDM) {
|
|
4436
4640
|
setLocalMessages((prev) => {
|
|
4437
4641
|
const next = syncLocalMessagesOnEdit(prev, lastEditDM);
|
|
@@ -4439,7 +4643,7 @@ var useChatSync = () => {
|
|
|
4439
4643
|
});
|
|
4440
4644
|
}
|
|
4441
4645
|
}, [lastEditDM]);
|
|
4442
|
-
|
|
4646
|
+
React3.useEffect(() => {
|
|
4443
4647
|
if (!lastDM) return;
|
|
4444
4648
|
const result = buildIncomingMessageFromDM(
|
|
4445
4649
|
lastDM,
|
|
@@ -4451,14 +4655,14 @@ var useChatSync = () => {
|
|
|
4451
4655
|
(prev) => applyMessageUpdate(prev, result.storageKey, result.incomingMsg, result.isMe)
|
|
4452
4656
|
);
|
|
4453
4657
|
}, [lastDM, loggedUserDetails, conversations]);
|
|
4454
|
-
|
|
4658
|
+
React3.useEffect(() => {
|
|
4455
4659
|
if (lastStatusUpdate) {
|
|
4456
4660
|
setLocalMessages(
|
|
4457
4661
|
(prev) => syncLocalMessagesOnStatusUpdate(prev, lastStatusUpdate, loggedUserDetails)
|
|
4458
4662
|
);
|
|
4459
4663
|
}
|
|
4460
4664
|
}, [lastStatusUpdate, loggedUserDetails]);
|
|
4461
|
-
|
|
4665
|
+
React3.useEffect(() => {
|
|
4462
4666
|
if (lastDMMarkRead) {
|
|
4463
4667
|
setLocalMessages((prev) => {
|
|
4464
4668
|
const next = syncLocalMessagesOnDmMarkRead(
|
|
@@ -4488,16 +4692,16 @@ var mergeChatCustomization = (config) => ({
|
|
|
4488
4692
|
classNames: { ...defaultChatClassNames, ...config?.classNames ?? {} },
|
|
4489
4693
|
features: { ...defaultChatFeatures, ...config?.features ?? {} }
|
|
4490
4694
|
});
|
|
4491
|
-
var ChatCustomizationContext =
|
|
4695
|
+
var ChatCustomizationContext = React3.createContext(void 0);
|
|
4492
4696
|
var ChatCustomizationProvider = ({
|
|
4493
4697
|
children,
|
|
4494
4698
|
customization
|
|
4495
4699
|
}) => {
|
|
4496
|
-
const merged =
|
|
4700
|
+
const merged = React3.useMemo(
|
|
4497
4701
|
() => mergeChatCustomization(customization),
|
|
4498
4702
|
[customization]
|
|
4499
4703
|
);
|
|
4500
|
-
const value =
|
|
4704
|
+
const value = React3.useMemo(
|
|
4501
4705
|
() => ({
|
|
4502
4706
|
components: merged.components,
|
|
4503
4707
|
classNames: merged.classNames,
|
|
@@ -4513,7 +4717,7 @@ var ChatCustomizationProvider = ({
|
|
|
4513
4717
|
return /* @__PURE__ */ jsxRuntime.jsx(ChatCustomizationContext.Provider, { value, children });
|
|
4514
4718
|
};
|
|
4515
4719
|
var useChatCustomization = () => {
|
|
4516
|
-
const context =
|
|
4720
|
+
const context = React3.useContext(ChatCustomizationContext);
|
|
4517
4721
|
if (!context) {
|
|
4518
4722
|
throw new Error(
|
|
4519
4723
|
"useChatCustomization must be used within ChatCustomizationProvider"
|
|
@@ -4522,7 +4726,7 @@ var useChatCustomization = () => {
|
|
|
4522
4726
|
return context;
|
|
4523
4727
|
};
|
|
4524
4728
|
var useChatCustomizationOptional = () => {
|
|
4525
|
-
const context =
|
|
4729
|
+
const context = React3.useContext(ChatCustomizationContext);
|
|
4526
4730
|
return context ?? {
|
|
4527
4731
|
components: {},
|
|
4528
4732
|
classNames: {},
|
|
@@ -4533,9 +4737,146 @@ var useChatCustomizationOptional = () => {
|
|
|
4533
4737
|
};
|
|
4534
4738
|
var useChatFeatures = () => useChatCustomization().features;
|
|
4535
4739
|
var useChatFeaturesOptional = () => useChatCustomizationOptional().features;
|
|
4536
|
-
|
|
4740
|
+
|
|
4741
|
+
// src/context/ChatEffectiveSettingsContext.tsx
|
|
4742
|
+
init_settings_api();
|
|
4743
|
+
init_settings_types();
|
|
4744
|
+
var ChatEffectiveSettingsContext = React3.createContext(null);
|
|
4745
|
+
function buildCallGate(settings, featureEnabled) {
|
|
4746
|
+
if (!settings.calls.configured) {
|
|
4747
|
+
return {
|
|
4748
|
+
visible: true,
|
|
4749
|
+
enabled: false,
|
|
4750
|
+
disabledReason: exports.CALLS_NOT_CONFIGURED_MESSAGE
|
|
4751
|
+
};
|
|
4752
|
+
}
|
|
4753
|
+
if (!settings.calls.enabled) {
|
|
4754
|
+
return {
|
|
4755
|
+
visible: true,
|
|
4756
|
+
enabled: false,
|
|
4757
|
+
disabledReason: exports.ADMIN_PERMISSION_DENIED_MESSAGE
|
|
4758
|
+
};
|
|
4759
|
+
}
|
|
4760
|
+
if (!featureEnabled) {
|
|
4761
|
+
return {
|
|
4762
|
+
visible: true,
|
|
4763
|
+
enabled: false,
|
|
4764
|
+
disabledReason: exports.ADMIN_PERMISSION_DENIED_MESSAGE
|
|
4765
|
+
};
|
|
4766
|
+
}
|
|
4767
|
+
return { visible: true, enabled: true, disabledReason: null };
|
|
4768
|
+
}
|
|
4769
|
+
function ChatEffectiveSettingsProvider({
|
|
4770
|
+
children,
|
|
4771
|
+
enabled = true
|
|
4772
|
+
}) {
|
|
4773
|
+
const [settings, setSettings] = React3.useState(
|
|
4774
|
+
exports.DEFAULT_EFFECTIVE_SETTINGS
|
|
4775
|
+
);
|
|
4776
|
+
const [loading, setLoading] = React3.useState(true);
|
|
4777
|
+
const [error, setError] = React3.useState(null);
|
|
4778
|
+
const refresh = React3.useCallback(async () => {
|
|
4779
|
+
if (!enabled) {
|
|
4780
|
+
setLoading(false);
|
|
4781
|
+
return;
|
|
4782
|
+
}
|
|
4783
|
+
setLoading(true);
|
|
4784
|
+
try {
|
|
4785
|
+
const next = await exports.fetchEffectiveSettings();
|
|
4786
|
+
setSettings(next);
|
|
4787
|
+
setError(null);
|
|
4788
|
+
} catch (err) {
|
|
4789
|
+
console.error("Failed to fetch effective settings:", err);
|
|
4790
|
+
setError(
|
|
4791
|
+
err instanceof Error ? err.message : "Could not load chat permissions"
|
|
4792
|
+
);
|
|
4793
|
+
setSettings(exports.DEFAULT_EFFECTIVE_SETTINGS);
|
|
4794
|
+
} finally {
|
|
4795
|
+
setLoading(false);
|
|
4796
|
+
}
|
|
4797
|
+
}, [enabled]);
|
|
4798
|
+
React3.useEffect(() => {
|
|
4799
|
+
void refresh();
|
|
4800
|
+
}, [refresh]);
|
|
4801
|
+
const value = React3.useMemo(() => {
|
|
4802
|
+
const isGroupPermissionLocked = (key) => settings.groupPolicy.locked.includes(key);
|
|
4803
|
+
return {
|
|
4804
|
+
settings,
|
|
4805
|
+
loading,
|
|
4806
|
+
error,
|
|
4807
|
+
refresh,
|
|
4808
|
+
isGroupPermissionLocked,
|
|
4809
|
+
getAudioCallGate: () => buildCallGate(settings, settings.audioCallEnabled),
|
|
4810
|
+
getVideoCallGate: () => buildCallGate(settings, settings.videoCallEnabled),
|
|
4811
|
+
getPushNotificationGate: () => ({
|
|
4812
|
+
visible: true,
|
|
4813
|
+
enabled: settings.pushNotificationEnabled,
|
|
4814
|
+
disabledReason: settings.pushNotificationEnabled ? null : exports.ADMIN_PERMISSION_DENIED_MESSAGE
|
|
4815
|
+
}),
|
|
4816
|
+
getBlockUsersGate: () => ({
|
|
4817
|
+
visible: true,
|
|
4818
|
+
enabled: settings.blockUsersEnabled,
|
|
4819
|
+
disabledReason: settings.blockUsersEnabled ? null : exports.ADMIN_PERMISSION_DENIED_MESSAGE
|
|
4820
|
+
}),
|
|
4821
|
+
getAttachmentsGate: () => ({
|
|
4822
|
+
visible: true,
|
|
4823
|
+
enabled: settings.attachments.enabled,
|
|
4824
|
+
disabledReason: settings.attachments.enabled ? null : exports.ADMIN_PERMISSION_DENIED_MESSAGE
|
|
4825
|
+
}),
|
|
4826
|
+
getGroupCreationGate: () => ({
|
|
4827
|
+
visible: true,
|
|
4828
|
+
enabled: settings.groupCreationEnabled,
|
|
4829
|
+
disabledReason: settings.groupCreationEnabled ? null : exports.ADMIN_PERMISSION_DENIED_MESSAGE
|
|
4830
|
+
})
|
|
4831
|
+
};
|
|
4832
|
+
}, [settings, loading, error, refresh]);
|
|
4833
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChatEffectiveSettingsContext.Provider, { value, children });
|
|
4834
|
+
}
|
|
4835
|
+
function useEffectiveSettings() {
|
|
4836
|
+
const ctx = React3.useContext(ChatEffectiveSettingsContext);
|
|
4837
|
+
if (!ctx) {
|
|
4838
|
+
throw new Error(
|
|
4839
|
+
"useEffectiveSettings must be used within ChatEffectiveSettingsProvider"
|
|
4840
|
+
);
|
|
4841
|
+
}
|
|
4842
|
+
return ctx;
|
|
4843
|
+
}
|
|
4844
|
+
function useEffectiveSettingsOptional() {
|
|
4845
|
+
const ctx = React3.useContext(ChatEffectiveSettingsContext);
|
|
4846
|
+
if (ctx) return ctx;
|
|
4847
|
+
return {
|
|
4848
|
+
settings: exports.DEFAULT_EFFECTIVE_SETTINGS,
|
|
4849
|
+
loading: false,
|
|
4850
|
+
error: null,
|
|
4851
|
+
refresh: async () => void 0,
|
|
4852
|
+
isGroupPermissionLocked: () => false,
|
|
4853
|
+
getAudioCallGate: () => buildCallGate(exports.DEFAULT_EFFECTIVE_SETTINGS, true),
|
|
4854
|
+
getVideoCallGate: () => buildCallGate(exports.DEFAULT_EFFECTIVE_SETTINGS, true),
|
|
4855
|
+
getPushNotificationGate: () => ({
|
|
4856
|
+
visible: true,
|
|
4857
|
+
enabled: true,
|
|
4858
|
+
disabledReason: null
|
|
4859
|
+
}),
|
|
4860
|
+
getBlockUsersGate: () => ({
|
|
4861
|
+
visible: true,
|
|
4862
|
+
enabled: true,
|
|
4863
|
+
disabledReason: null
|
|
4864
|
+
}),
|
|
4865
|
+
getAttachmentsGate: () => ({
|
|
4866
|
+
visible: true,
|
|
4867
|
+
enabled: true,
|
|
4868
|
+
disabledReason: null
|
|
4869
|
+
}),
|
|
4870
|
+
getGroupCreationGate: () => ({
|
|
4871
|
+
visible: true,
|
|
4872
|
+
enabled: true,
|
|
4873
|
+
disabledReason: null
|
|
4874
|
+
})
|
|
4875
|
+
};
|
|
4876
|
+
}
|
|
4877
|
+
var ChatContext = React3.createContext(void 0);
|
|
4537
4878
|
var useChatContext = () => {
|
|
4538
|
-
const context =
|
|
4879
|
+
const context = React3.useContext(ChatContext);
|
|
4539
4880
|
if (!context) {
|
|
4540
4881
|
throw new Error("useChatContext must be used within a Chat provider");
|
|
4541
4882
|
}
|
|
@@ -4572,7 +4913,7 @@ var Chat = ({
|
|
|
4572
4913
|
const status = exports.useChatStore((s) => s.status);
|
|
4573
4914
|
const error = exports.useChatStore((s) => s.error);
|
|
4574
4915
|
useChatSync();
|
|
4575
|
-
|
|
4916
|
+
React3__namespace.default.useEffect(() => {
|
|
4576
4917
|
const clientId = client?.id;
|
|
4577
4918
|
const initializeChat = async () => {
|
|
4578
4919
|
if (!clientId || !loggedUserDetails) return;
|
|
@@ -4662,28 +5003,28 @@ var Chat = ({
|
|
|
4662
5003
|
queryParamApis: queryParamApis ?? ["get"],
|
|
4663
5004
|
queryParamsByApi: queryParamsByApi ?? {}
|
|
4664
5005
|
});
|
|
4665
|
-
|
|
5006
|
+
React3__namespace.default.useEffect(() => {
|
|
4666
5007
|
exports.setChatQueryParams(queryParams);
|
|
4667
5008
|
exports.setChatQueryParamApis(queryParamApis);
|
|
4668
5009
|
exports.setChatQueryParamsByApi(queryParamsByApi);
|
|
4669
5010
|
}, [queryConfigKey]);
|
|
4670
|
-
|
|
5011
|
+
React3__namespace.default.useEffect(() => {
|
|
4671
5012
|
if (lastDM && onMessageReceived) {
|
|
4672
5013
|
onMessageReceived(lastDM);
|
|
4673
5014
|
}
|
|
4674
5015
|
}, [lastDM, onMessageReceived]);
|
|
4675
|
-
|
|
5016
|
+
React3__namespace.default.useEffect(() => {
|
|
4676
5017
|
if (status === "connected" && onSocketConnected) {
|
|
4677
5018
|
const socketId = exports.useChatStore.getState().socketId;
|
|
4678
5019
|
if (socketId) onSocketConnected(socketId);
|
|
4679
5020
|
}
|
|
4680
5021
|
}, [status, onSocketConnected]);
|
|
4681
|
-
|
|
5022
|
+
React3__namespace.default.useEffect(() => {
|
|
4682
5023
|
if (status === "error" && error && onSocketError) {
|
|
4683
5024
|
onSocketError(error);
|
|
4684
5025
|
}
|
|
4685
5026
|
}, [status, error, onSocketError]);
|
|
4686
|
-
const contextValue =
|
|
5027
|
+
const contextValue = React3__namespace.default.useMemo(
|
|
4687
5028
|
() => ({
|
|
4688
5029
|
onSendMessage,
|
|
4689
5030
|
client,
|
|
@@ -4703,7 +5044,7 @@ var Chat = ({
|
|
|
4703
5044
|
messagesData
|
|
4704
5045
|
]
|
|
4705
5046
|
);
|
|
4706
|
-
const customization =
|
|
5047
|
+
const customization = React3__namespace.default.useMemo(
|
|
4707
5048
|
() => ({
|
|
4708
5049
|
components: uiConfig.components,
|
|
4709
5050
|
classNames: uiConfig.classNames,
|
|
@@ -4711,7 +5052,7 @@ var Chat = ({
|
|
|
4711
5052
|
}),
|
|
4712
5053
|
[uiConfig.components, uiConfig.classNames, uiConfig.features]
|
|
4713
5054
|
);
|
|
4714
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(ChatCustomizationProvider, { customization, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "chat-container-root flex h-full min-h-0 w-full flex-1 flex-col overflow-hidden", children: isSessionReady ? children : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center text-gray-400 font-bold", children: "Initializing session..." }) }) }) }) });
|
|
5055
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(ChatCustomizationProvider, { customization, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "chat-container-root flex h-full min-h-0 w-full flex-1 flex-col overflow-hidden", children: isSessionReady ? /* @__PURE__ */ jsxRuntime.jsx(ChatEffectiveSettingsProvider, { enabled: true, children }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center text-gray-400 font-bold", children: "Initializing session..." }) }) }) }) });
|
|
4715
5056
|
};
|
|
4716
5057
|
|
|
4717
5058
|
// src/hooks/useChatController.ts
|
|
@@ -5009,7 +5350,7 @@ function toDisplayAttachments(attachments) {
|
|
|
5009
5350
|
}));
|
|
5010
5351
|
}
|
|
5011
5352
|
var useChatController = () => {
|
|
5012
|
-
const [state, setState] =
|
|
5353
|
+
const [state, setState] = React3.useState({
|
|
5013
5354
|
activeChannel: null,
|
|
5014
5355
|
activeConversationId: null,
|
|
5015
5356
|
replyToMessage: null,
|
|
@@ -5019,15 +5360,15 @@ var useChatController = () => {
|
|
|
5019
5360
|
debouncedSearch: "",
|
|
5020
5361
|
isCreateModalOpen: false
|
|
5021
5362
|
});
|
|
5022
|
-
const updateState =
|
|
5363
|
+
const updateState = React3.useCallback((updates) => {
|
|
5023
5364
|
setState((prev) => ({ ...prev, ...updates }));
|
|
5024
5365
|
}, []);
|
|
5025
|
-
const handleSelectionModeChange =
|
|
5366
|
+
const handleSelectionModeChange = React3.useCallback((active) => {
|
|
5026
5367
|
setState(
|
|
5027
5368
|
(prev) => prev.isMessageSelectionMode === active ? prev : { ...prev, isMessageSelectionMode: active }
|
|
5028
5369
|
);
|
|
5029
5370
|
}, []);
|
|
5030
|
-
const handleActiveChannelPatch =
|
|
5371
|
+
const handleActiveChannelPatch = React3.useCallback((patch) => {
|
|
5031
5372
|
setState(
|
|
5032
5373
|
(prev) => prev.activeChannel ? { ...prev, activeChannel: { ...prev.activeChannel, ...patch } } : prev
|
|
5033
5374
|
);
|
|
@@ -5051,11 +5392,11 @@ var useChatController = () => {
|
|
|
5051
5392
|
const allUsers = exports.useChatStore((s) => s.allUsers);
|
|
5052
5393
|
const isFetchingConversations = exports.useChatStore((s) => s.isFetchingConversations);
|
|
5053
5394
|
const conversations = exports.useChatStore((s) => s.conversations);
|
|
5054
|
-
const [pendingOpenRequest, setPendingOpenRequest] =
|
|
5395
|
+
const [pendingOpenRequest, setPendingOpenRequest] = React3.useState(() => peekPendingOpenRequest());
|
|
5055
5396
|
const conversationsLength = exports.useChatStore(
|
|
5056
5397
|
(s) => state.activeChannel?.conversationId ? 0 : s.conversations.length
|
|
5057
5398
|
);
|
|
5058
|
-
const lastConversationActionsRef =
|
|
5399
|
+
const lastConversationActionsRef = React3.useRef(null);
|
|
5059
5400
|
const activeChannelId = state.activeChannel?.id;
|
|
5060
5401
|
const activeChannelConvId = state.activeChannel?.conversationId;
|
|
5061
5402
|
const activeChannelIsGroup = !!state.activeChannel?.isGroup;
|
|
@@ -5080,7 +5421,7 @@ var useChatController = () => {
|
|
|
5080
5421
|
isGroupConversation(latestInfo)
|
|
5081
5422
|
].join("|");
|
|
5082
5423
|
});
|
|
5083
|
-
|
|
5424
|
+
React3.useEffect(() => {
|
|
5084
5425
|
const onOpen = (event) => {
|
|
5085
5426
|
const detail = event.detail;
|
|
5086
5427
|
if (detail?.conversationId) {
|
|
@@ -5097,7 +5438,7 @@ var useChatController = () => {
|
|
|
5097
5438
|
window.addEventListener(OPEN_CONVERSATION_EVENT, onOpen);
|
|
5098
5439
|
return () => window.removeEventListener(OPEN_CONVERSATION_EVENT, onOpen);
|
|
5099
5440
|
}, []);
|
|
5100
|
-
|
|
5441
|
+
React3.useEffect(() => {
|
|
5101
5442
|
if (!pendingOpenRequest?.conversationId || !loggedUserDetails) return;
|
|
5102
5443
|
let cancelled = false;
|
|
5103
5444
|
const openPending = async () => {
|
|
@@ -5163,13 +5504,13 @@ var useChatController = () => {
|
|
|
5163
5504
|
allUsers,
|
|
5164
5505
|
fetchConversationInfo2
|
|
5165
5506
|
]);
|
|
5166
|
-
|
|
5507
|
+
React3.useEffect(() => {
|
|
5167
5508
|
const handler = setTimeout(() => {
|
|
5168
5509
|
updateState({ debouncedSearch: state.searchQuery });
|
|
5169
5510
|
}, 400);
|
|
5170
5511
|
return () => clearTimeout(handler);
|
|
5171
5512
|
}, [state.searchQuery, updateState]);
|
|
5172
|
-
|
|
5513
|
+
React3.useEffect(() => {
|
|
5173
5514
|
if (!state.activeChannel || !loggedUserDetails) {
|
|
5174
5515
|
setState(
|
|
5175
5516
|
(prev) => prev.activeConversationId === null ? prev : { ...prev, activeConversationId: null }
|
|
@@ -5185,7 +5526,7 @@ var useChatController = () => {
|
|
|
5185
5526
|
(prev) => prev.activeConversationId === nextId ? prev : { ...prev, activeConversationId: nextId }
|
|
5186
5527
|
);
|
|
5187
5528
|
}, [state.activeChannel, loggedUserDetails, conversationsLength]);
|
|
5188
|
-
|
|
5529
|
+
React3.useEffect(() => {
|
|
5189
5530
|
if (!lastDM?.conversationId || !loggedUserDetails) return;
|
|
5190
5531
|
const convId = String(lastDM.conversationId);
|
|
5191
5532
|
const senderId = String(lastDM.sender?._id || lastDM.sender || "");
|
|
@@ -5218,7 +5559,7 @@ var useChatController = () => {
|
|
|
5218
5559
|
};
|
|
5219
5560
|
});
|
|
5220
5561
|
}, [lastDM, loggedUserDetails]);
|
|
5221
|
-
const resolvedLocalMessages =
|
|
5562
|
+
const resolvedLocalMessages = React3.useMemo(
|
|
5222
5563
|
() => resolveLocalMessagesForChannel(
|
|
5223
5564
|
localMessages,
|
|
5224
5565
|
state.activeConversationId,
|
|
@@ -5226,7 +5567,7 @@ var useChatController = () => {
|
|
|
5226
5567
|
),
|
|
5227
5568
|
[localMessages, state.activeConversationId, state.activeChannel?.id]
|
|
5228
5569
|
);
|
|
5229
|
-
const resolvedConversationMessages =
|
|
5570
|
+
const resolvedConversationMessages = React3.useMemo(() => {
|
|
5230
5571
|
if (state.activeConversationId) {
|
|
5231
5572
|
return messagesByConversation[state.activeConversationId] || [];
|
|
5232
5573
|
}
|
|
@@ -5234,7 +5575,7 @@ var useChatController = () => {
|
|
|
5234
5575
|
const groupConversationId = String(state.activeChannel.id);
|
|
5235
5576
|
return messagesByConversation[groupConversationId] || [];
|
|
5236
5577
|
}, [messagesByConversation, state.activeConversationId, state.activeChannel]);
|
|
5237
|
-
|
|
5578
|
+
React3.useEffect(() => {
|
|
5238
5579
|
if (!activeChannelSyncKey || !state.activeChannel) return;
|
|
5239
5580
|
const [convId, pinned, starred, isLeft, isBlocked, isGroup] = activeChannelSyncKey.split("|");
|
|
5240
5581
|
setState((prev) => {
|
|
@@ -5257,10 +5598,10 @@ var useChatController = () => {
|
|
|
5257
5598
|
};
|
|
5258
5599
|
});
|
|
5259
5600
|
}, [activeChannelSyncKey, state.activeChannel]);
|
|
5260
|
-
|
|
5601
|
+
React3.useEffect(() => {
|
|
5261
5602
|
setActiveConversationId(state.activeConversationId);
|
|
5262
5603
|
}, [state.activeConversationId, setActiveConversationId]);
|
|
5263
|
-
|
|
5604
|
+
React3.useEffect(() => {
|
|
5264
5605
|
if (!state.activeConversationId || !state.activeChannel || !loggedUserDetails) {
|
|
5265
5606
|
lastConversationActionsRef.current = null;
|
|
5266
5607
|
return;
|
|
@@ -5307,7 +5648,7 @@ var useChatController = () => {
|
|
|
5307
5648
|
emitGroupMarkRead,
|
|
5308
5649
|
emitMarkAsRead
|
|
5309
5650
|
]);
|
|
5310
|
-
|
|
5651
|
+
React3.useEffect(() => {
|
|
5311
5652
|
if (globalAppError?.type === "participant" && state.activeChannel) {
|
|
5312
5653
|
updateState({ activeChannel: null, activeConversationId: null });
|
|
5313
5654
|
}
|
|
@@ -5484,7 +5825,7 @@ function withThemeTransition(apply) {
|
|
|
5484
5825
|
}
|
|
5485
5826
|
reactDom.flushSync(apply);
|
|
5486
5827
|
}
|
|
5487
|
-
var ChatThemeContext =
|
|
5828
|
+
var ChatThemeContext = React3.createContext(null);
|
|
5488
5829
|
var ChatThemeProvider = ({
|
|
5489
5830
|
children,
|
|
5490
5831
|
themeColor,
|
|
@@ -5494,10 +5835,10 @@ var ChatThemeProvider = ({
|
|
|
5494
5835
|
showColorModeToggle = true
|
|
5495
5836
|
}) => {
|
|
5496
5837
|
const isControlled = colorMode !== void 0;
|
|
5497
|
-
const [internalMode, setInternalMode] =
|
|
5498
|
-
const [isThemeTransitionReady, setIsThemeTransitionReady] =
|
|
5499
|
-
const skipThemeTransitionRef =
|
|
5500
|
-
|
|
5838
|
+
const [internalMode, setInternalMode] = React3.useState(defaultColorMode);
|
|
5839
|
+
const [isThemeTransitionReady, setIsThemeTransitionReady] = React3.useState(false);
|
|
5840
|
+
const skipThemeTransitionRef = React3.useRef(true);
|
|
5841
|
+
React3.useLayoutEffect(() => {
|
|
5501
5842
|
if (!isControlled) {
|
|
5502
5843
|
const stored = loadChatColorMode();
|
|
5503
5844
|
if (stored) {
|
|
@@ -5512,7 +5853,7 @@ var ChatThemeProvider = ({
|
|
|
5512
5853
|
}, [isControlled]);
|
|
5513
5854
|
const resolvedMode = isControlled ? colorMode : internalMode;
|
|
5514
5855
|
const isDark = resolvedMode === "dark";
|
|
5515
|
-
const setColorMode =
|
|
5856
|
+
const setColorMode = React3.useCallback(
|
|
5516
5857
|
(mode) => {
|
|
5517
5858
|
const apply = () => {
|
|
5518
5859
|
if (!isControlled) {
|
|
@@ -5529,10 +5870,10 @@ var ChatThemeProvider = ({
|
|
|
5529
5870
|
},
|
|
5530
5871
|
[isControlled, onColorModeChange]
|
|
5531
5872
|
);
|
|
5532
|
-
const toggleColorMode =
|
|
5873
|
+
const toggleColorMode = React3.useCallback(() => {
|
|
5533
5874
|
setColorMode(resolvedMode === "dark" ? "light" : "dark");
|
|
5534
5875
|
}, [resolvedMode, setColorMode]);
|
|
5535
|
-
const value =
|
|
5876
|
+
const value = React3.useMemo(
|
|
5536
5877
|
() => ({
|
|
5537
5878
|
colorMode: resolvedMode,
|
|
5538
5879
|
isDark,
|
|
@@ -5560,7 +5901,7 @@ var ChatThemeProvider = ({
|
|
|
5560
5901
|
return /* @__PURE__ */ jsxRuntime.jsx(ChatThemeContext.Provider, { value, children });
|
|
5561
5902
|
};
|
|
5562
5903
|
var useChatTheme = () => {
|
|
5563
|
-
const context =
|
|
5904
|
+
const context = React3.useContext(ChatThemeContext);
|
|
5564
5905
|
if (!context) {
|
|
5565
5906
|
throw new Error("useChatTheme must be used within ChatThemeProvider");
|
|
5566
5907
|
}
|
|
@@ -6105,7 +6446,7 @@ function useCreateChatDialog({
|
|
|
6105
6446
|
onUserSelect,
|
|
6106
6447
|
setIsCreateModalOpen
|
|
6107
6448
|
}) {
|
|
6108
|
-
const [state, setState] =
|
|
6449
|
+
const [state, setState] = React3.useState(initialState);
|
|
6109
6450
|
const updateState = (updates) => {
|
|
6110
6451
|
setState((prev) => ({ ...prev, ...updates }));
|
|
6111
6452
|
};
|
|
@@ -6114,8 +6455,10 @@ function useCreateChatDialog({
|
|
|
6114
6455
|
const fetchAllUsers = exports.useChatStore((storeState) => storeState.fetchAllUsers);
|
|
6115
6456
|
const accessToken = exports.useChatStore((storeState) => storeState.accessToken);
|
|
6116
6457
|
const fetchConversations2 = exports.useChatStore((storeState) => storeState.fetchConversations);
|
|
6117
|
-
const
|
|
6118
|
-
|
|
6458
|
+
const { settings } = useEffectiveSettingsOptional();
|
|
6459
|
+
const maxParticipants = settings.maxParticipantsPerGroup;
|
|
6460
|
+
const fileInputRef = React3.useRef(null);
|
|
6461
|
+
React3.useEffect(() => {
|
|
6119
6462
|
if (accessToken) {
|
|
6120
6463
|
fetchAllUsers();
|
|
6121
6464
|
}
|
|
@@ -6127,9 +6470,18 @@ function useCreateChatDialog({
|
|
|
6127
6470
|
setState((prev) => {
|
|
6128
6471
|
const memberId = String(member._id);
|
|
6129
6472
|
const exists = prev.selectedMembers.some((m) => String(m._id) === memberId);
|
|
6473
|
+
if (exists) {
|
|
6474
|
+
return {
|
|
6475
|
+
...prev,
|
|
6476
|
+
selectedMembers: prev.selectedMembers.filter((m) => String(m._id) !== memberId)
|
|
6477
|
+
};
|
|
6478
|
+
}
|
|
6479
|
+
if (prev.selectedMembers.length + 1 >= maxParticipants) {
|
|
6480
|
+
return prev;
|
|
6481
|
+
}
|
|
6130
6482
|
return {
|
|
6131
6483
|
...prev,
|
|
6132
|
-
selectedMembers:
|
|
6484
|
+
selectedMembers: [...prev.selectedMembers, member]
|
|
6133
6485
|
};
|
|
6134
6486
|
});
|
|
6135
6487
|
};
|
|
@@ -6513,8 +6865,25 @@ function GroupCreateTab({
|
|
|
6513
6865
|
) })
|
|
6514
6866
|
] });
|
|
6515
6867
|
}
|
|
6868
|
+
function AdminPermissionTooltip({
|
|
6869
|
+
disabled,
|
|
6870
|
+
message,
|
|
6871
|
+
side = "top",
|
|
6872
|
+
className,
|
|
6873
|
+
children
|
|
6874
|
+
}) {
|
|
6875
|
+
if (!disabled || !message) {
|
|
6876
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
|
|
6877
|
+
}
|
|
6878
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
|
|
6879
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("inline-flex", className), children }) }),
|
|
6880
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side, className: "max-w-[240px] text-xs", children: message })
|
|
6881
|
+
] });
|
|
6882
|
+
}
|
|
6516
6883
|
var CreateChatDialog = (props) => {
|
|
6517
6884
|
const { isCreateModalOpen = false, setIsCreateModalOpen } = props;
|
|
6885
|
+
const { getGroupCreationGate } = useEffectiveSettingsOptional();
|
|
6886
|
+
const groupCreationGate = getGroupCreationGate();
|
|
6518
6887
|
const {
|
|
6519
6888
|
state,
|
|
6520
6889
|
updateState,
|
|
@@ -6568,24 +6937,39 @@ var CreateChatDialog = (props) => {
|
|
|
6568
6937
|
) })
|
|
6569
6938
|
] }),
|
|
6570
6939
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid shrink-0 grid-cols-2 gap-2 px-5", children: [
|
|
6571
|
-
{ id: "dm", label: "Message", icon: lucideReact.MessageCircle },
|
|
6572
|
-
{ id: "group", label: "New group", icon: lucideReact.Users }
|
|
6573
|
-
].map(({ id, label, icon: Icon }) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6574
|
-
"button",
|
|
6940
|
+
{ id: "dm", label: "Message", icon: lucideReact.MessageCircle, disabled: false, reason: null },
|
|
6575
6941
|
{
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
|
|
6583
|
-
|
|
6584
|
-
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
|
|
6942
|
+
id: "group",
|
|
6943
|
+
label: "New group",
|
|
6944
|
+
icon: lucideReact.Users,
|
|
6945
|
+
disabled: !groupCreationGate.enabled,
|
|
6946
|
+
reason: groupCreationGate.disabledReason
|
|
6947
|
+
}
|
|
6948
|
+
].map(({ id, label, icon: Icon, disabled, reason }) => {
|
|
6949
|
+
const tabButton = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6950
|
+
"button",
|
|
6951
|
+
{
|
|
6952
|
+
type: "button",
|
|
6953
|
+
disabled,
|
|
6954
|
+
onClick: () => {
|
|
6955
|
+
if (disabled) return;
|
|
6956
|
+
updateState({ activeTab: id });
|
|
6957
|
+
},
|
|
6958
|
+
className: cn(
|
|
6959
|
+
"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",
|
|
6960
|
+
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)"
|
|
6961
|
+
),
|
|
6962
|
+
children: [
|
|
6963
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "size-4" }),
|
|
6964
|
+
label
|
|
6965
|
+
]
|
|
6966
|
+
}
|
|
6967
|
+
);
|
|
6968
|
+
if (!disabled || !reason) {
|
|
6969
|
+
return /* @__PURE__ */ jsxRuntime.jsx(React3.Fragment, { children: tabButton }, id);
|
|
6970
|
+
}
|
|
6971
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AdminPermissionTooltip, { disabled: true, message: reason, children: tabButton }, id);
|
|
6972
|
+
}) }),
|
|
6589
6973
|
state.activeTab === "dm" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6590
6974
|
DmContactsTab,
|
|
6591
6975
|
{
|
|
@@ -6596,7 +6980,7 @@ var CreateChatDialog = (props) => {
|
|
|
6596
6980
|
onStartDM: handleStartDM
|
|
6597
6981
|
}
|
|
6598
6982
|
),
|
|
6599
|
-
state.activeTab === "group" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6983
|
+
state.activeTab === "group" && groupCreationGate.enabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6600
6984
|
GroupCreateTab,
|
|
6601
6985
|
{
|
|
6602
6986
|
state,
|
|
@@ -6660,7 +7044,7 @@ var emitPushChanged = (enabled) => {
|
|
|
6660
7044
|
} catch {
|
|
6661
7045
|
}
|
|
6662
7046
|
};
|
|
6663
|
-
var pushApiUrl = (path) => exports.buildVersionedApiUrl(path, { service: "
|
|
7047
|
+
var pushApiUrl = (path) => exports.buildVersionedApiUrl(path, { service: "v2" });
|
|
6664
7048
|
var apiGetPushConfig = async () => {
|
|
6665
7049
|
const { data } = await apiClient.get(pushApiUrl("/notifications/push/config"));
|
|
6666
7050
|
return data?.data;
|
|
@@ -6809,7 +7193,7 @@ var onForegroundPush = async (callback) => {
|
|
|
6809
7193
|
|
|
6810
7194
|
// src/notifications/usePushNotifications.ts
|
|
6811
7195
|
var usePushNotifications = () => {
|
|
6812
|
-
const [state, setState] =
|
|
7196
|
+
const [state, setState] = React3.useState({
|
|
6813
7197
|
supported: false,
|
|
6814
7198
|
allowedByWorkspace: false,
|
|
6815
7199
|
configured: false,
|
|
@@ -6819,7 +7203,7 @@ var usePushNotifications = () => {
|
|
|
6819
7203
|
loading: true,
|
|
6820
7204
|
error: null
|
|
6821
7205
|
});
|
|
6822
|
-
const refresh =
|
|
7206
|
+
const refresh = React3.useCallback(async () => {
|
|
6823
7207
|
if (!isPushSupported()) {
|
|
6824
7208
|
setState((prev) => ({
|
|
6825
7209
|
...prev,
|
|
@@ -6852,10 +7236,10 @@ var usePushNotifications = () => {
|
|
|
6852
7236
|
}));
|
|
6853
7237
|
}
|
|
6854
7238
|
}, []);
|
|
6855
|
-
|
|
7239
|
+
React3.useEffect(() => {
|
|
6856
7240
|
void refresh();
|
|
6857
7241
|
}, [refresh]);
|
|
6858
|
-
const enable =
|
|
7242
|
+
const enable = React3.useCallback(async () => {
|
|
6859
7243
|
setState((prev) => ({ ...prev, loading: true, error: null }));
|
|
6860
7244
|
try {
|
|
6861
7245
|
await enablePushOnThisDevice();
|
|
@@ -6871,7 +7255,7 @@ var usePushNotifications = () => {
|
|
|
6871
7255
|
return false;
|
|
6872
7256
|
}
|
|
6873
7257
|
}, [refresh]);
|
|
6874
|
-
const disable =
|
|
7258
|
+
const disable = React3.useCallback(async () => {
|
|
6875
7259
|
setState((prev) => ({ ...prev, loading: true, error: null }));
|
|
6876
7260
|
try {
|
|
6877
7261
|
await disablePushOnThisDevice();
|
|
@@ -6879,7 +7263,7 @@ var usePushNotifications = () => {
|
|
|
6879
7263
|
await refresh();
|
|
6880
7264
|
}
|
|
6881
7265
|
}, [refresh]);
|
|
6882
|
-
const setUserEnabled =
|
|
7266
|
+
const setUserEnabled = React3.useCallback(
|
|
6883
7267
|
async (enabled) => {
|
|
6884
7268
|
setState((prev) => ({ ...prev, loading: true, error: null }));
|
|
6885
7269
|
try {
|
|
@@ -6905,14 +7289,20 @@ var PushNotificationToggle = ({
|
|
|
6905
7289
|
children
|
|
6906
7290
|
}) => {
|
|
6907
7291
|
const push = usePushNotifications();
|
|
6908
|
-
const
|
|
6909
|
-
|
|
7292
|
+
const { getPushNotificationGate } = useEffectiveSettingsOptional();
|
|
7293
|
+
const adminGate = getPushNotificationGate();
|
|
7294
|
+
const [isToggling, setIsToggling] = React3.useState(false);
|
|
7295
|
+
if (!push.supported) {
|
|
6910
7296
|
return null;
|
|
6911
7297
|
}
|
|
6912
7298
|
const isOn = push.deviceEnabled && push.userEnabled;
|
|
6913
7299
|
const permissionBlocked = push.permission === "denied";
|
|
7300
|
+
const adminBlocked = !adminGate.enabled;
|
|
7301
|
+
const notConfigured = !push.configured;
|
|
6914
7302
|
const showLoader = isToggling;
|
|
7303
|
+
const isDisabled = showLoader || permissionBlocked || push.loading || adminBlocked || notConfigured;
|
|
6915
7304
|
const handleChange = async (checked) => {
|
|
7305
|
+
if (adminBlocked || notConfigured) return;
|
|
6916
7306
|
setIsToggling(true);
|
|
6917
7307
|
try {
|
|
6918
7308
|
if (checked) {
|
|
@@ -6925,11 +7315,12 @@ var PushNotificationToggle = ({
|
|
|
6925
7315
|
setIsToggling(false);
|
|
6926
7316
|
}
|
|
6927
7317
|
};
|
|
7318
|
+
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;
|
|
6928
7319
|
const renderProps = {
|
|
6929
7320
|
label,
|
|
6930
|
-
description:
|
|
6931
|
-
checked: isOn,
|
|
6932
|
-
disabled:
|
|
7321
|
+
description: descriptionText,
|
|
7322
|
+
checked: adminBlocked || notConfigured ? false : isOn,
|
|
7323
|
+
disabled: isDisabled,
|
|
6933
7324
|
loading: showLoader || push.loading,
|
|
6934
7325
|
permissionBlocked,
|
|
6935
7326
|
error: push.error,
|
|
@@ -6957,12 +7348,19 @@ var PushNotificationToggle = ({
|
|
|
6957
7348
|
"aria-label": "Updating push notifications"
|
|
6958
7349
|
}
|
|
6959
7350
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
6960
|
-
|
|
7351
|
+
AdminPermissionTooltip,
|
|
6961
7352
|
{
|
|
6962
|
-
|
|
6963
|
-
|
|
6964
|
-
|
|
6965
|
-
|
|
7353
|
+
disabled: adminBlocked || notConfigured,
|
|
7354
|
+
message: adminBlocked ? adminGate.disabledReason : "Push notifications are not configured. Please contact your administrator.",
|
|
7355
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7356
|
+
Switch,
|
|
7357
|
+
{
|
|
7358
|
+
checked: adminBlocked || notConfigured ? false : isOn,
|
|
7359
|
+
disabled: isDisabled,
|
|
7360
|
+
onCheckedChange: (checked) => void handleChange(checked),
|
|
7361
|
+
"aria-label": `Toggle ${label}`
|
|
7362
|
+
}
|
|
7363
|
+
)
|
|
6966
7364
|
}
|
|
6967
7365
|
)
|
|
6968
7366
|
]
|
|
@@ -7076,7 +7474,7 @@ var LoggedUserSettingsDialog = ({
|
|
|
7076
7474
|
className
|
|
7077
7475
|
}) => {
|
|
7078
7476
|
const { resolveComponent, slotClassName } = useChatCustomization();
|
|
7079
|
-
const [internalOpen, setInternalOpen] =
|
|
7477
|
+
const [internalOpen, setInternalOpen] = React3.useState(false);
|
|
7080
7478
|
const open = controlledOpen ?? internalOpen;
|
|
7081
7479
|
const onOpenChange = controlledOnOpenChange ?? setInternalOpen;
|
|
7082
7480
|
const TriggerSlot = resolveComponent(
|
|
@@ -7264,7 +7662,7 @@ function getDraftRevision() {
|
|
|
7264
7662
|
return draftRevision;
|
|
7265
7663
|
}
|
|
7266
7664
|
function useDraftRevision() {
|
|
7267
|
-
return
|
|
7665
|
+
return React3.useSyncExternalStore(subscribeToDrafts, getDraftRevision, getDraftRevision);
|
|
7268
7666
|
}
|
|
7269
7667
|
function getConversationDraft(conversationId) {
|
|
7270
7668
|
if (!conversationId) return emptyDraft();
|
|
@@ -7302,11 +7700,11 @@ function getConversationDraftPreview(conversationId) {
|
|
|
7302
7700
|
return null;
|
|
7303
7701
|
}
|
|
7304
7702
|
function useConversationDraft(conversationId) {
|
|
7305
|
-
const composerRef =
|
|
7306
|
-
const syncComposerRef =
|
|
7703
|
+
const composerRef = React3.useRef(emptyDraft());
|
|
7704
|
+
const syncComposerRef = React3.useCallback((draft) => {
|
|
7307
7705
|
composerRef.current = draft;
|
|
7308
7706
|
}, []);
|
|
7309
|
-
|
|
7707
|
+
React3.useEffect(() => {
|
|
7310
7708
|
const id = conversationId;
|
|
7311
7709
|
return () => {
|
|
7312
7710
|
if (!id) return;
|
|
@@ -7525,7 +7923,7 @@ var saveChatDateTimePreferences = (prefs) => {
|
|
|
7525
7923
|
} catch {
|
|
7526
7924
|
}
|
|
7527
7925
|
};
|
|
7528
|
-
var ChatLocaleContext =
|
|
7926
|
+
var ChatLocaleContext = React3.createContext(null);
|
|
7529
7927
|
var resolveInitialPrefs = (defaults) => {
|
|
7530
7928
|
const stored = loadChatDateTimePreferences();
|
|
7531
7929
|
const fallback = resolveStoredPrefs(defaults);
|
|
@@ -7552,7 +7950,7 @@ var ChatLocaleProvider = ({
|
|
|
7552
7950
|
const localeControlled = controlledLocale !== void 0;
|
|
7553
7951
|
const timeZoneControlled = controlledTimeZone !== void 0;
|
|
7554
7952
|
const hour12Controlled = controlledHour12 !== void 0;
|
|
7555
|
-
const [internalPrefs, setInternalPrefs] =
|
|
7953
|
+
const [internalPrefs, setInternalPrefs] = React3.useState(
|
|
7556
7954
|
() => resolveInitialPrefs({
|
|
7557
7955
|
locale: defaultLocale,
|
|
7558
7956
|
timeZone: defaultTimeZone,
|
|
@@ -7562,7 +7960,7 @@ var ChatLocaleProvider = ({
|
|
|
7562
7960
|
const resolvedLocale = localeControlled ? controlledLocale : internalPrefs.locale;
|
|
7563
7961
|
const resolvedTimeZone = timeZoneControlled ? controlledTimeZone : internalPrefs.timeZone;
|
|
7564
7962
|
const resolvedHour12 = hour12Controlled ? controlledHour12 ?? getDefaultHour12() : internalPrefs.hour12 ?? getDefaultHour12();
|
|
7565
|
-
const updatePrefs =
|
|
7963
|
+
const updatePrefs = React3.useCallback(
|
|
7566
7964
|
(updates) => {
|
|
7567
7965
|
const next = {
|
|
7568
7966
|
locale: updates.locale !== void 0 ? updates.locale : resolvedLocale,
|
|
@@ -7591,19 +7989,19 @@ var ChatLocaleProvider = ({
|
|
|
7591
7989
|
onDateTimePreferencesChange
|
|
7592
7990
|
]
|
|
7593
7991
|
);
|
|
7594
|
-
const setLocale =
|
|
7992
|
+
const setLocale = React3.useCallback(
|
|
7595
7993
|
(locale) => updatePrefs({ locale }),
|
|
7596
7994
|
[updatePrefs]
|
|
7597
7995
|
);
|
|
7598
|
-
const setTimeZone =
|
|
7996
|
+
const setTimeZone = React3.useCallback(
|
|
7599
7997
|
(timeZone) => updatePrefs({ timeZone }),
|
|
7600
7998
|
[updatePrefs]
|
|
7601
7999
|
);
|
|
7602
|
-
const setHour12 =
|
|
8000
|
+
const setHour12 = React3.useCallback(
|
|
7603
8001
|
(hour12) => updatePrefs({ hour12 }),
|
|
7604
8002
|
[updatePrefs]
|
|
7605
8003
|
);
|
|
7606
|
-
const prefs =
|
|
8004
|
+
const prefs = React3.useMemo(
|
|
7607
8005
|
() => ({
|
|
7608
8006
|
locale: resolvedLocale,
|
|
7609
8007
|
timeZone: resolvedTimeZone,
|
|
@@ -7611,8 +8009,8 @@ var ChatLocaleProvider = ({
|
|
|
7611
8009
|
}),
|
|
7612
8010
|
[resolvedLocale, resolvedTimeZone, resolvedHour12]
|
|
7613
8011
|
);
|
|
7614
|
-
const formatters =
|
|
7615
|
-
const value =
|
|
8012
|
+
const formatters = React3.useMemo(() => createChatDateTimeFormatters(prefs), [prefs]);
|
|
8013
|
+
const value = React3.useMemo(
|
|
7616
8014
|
() => ({
|
|
7617
8015
|
...formatters,
|
|
7618
8016
|
locale: resolvedLocale,
|
|
@@ -7637,7 +8035,7 @@ var ChatLocaleProvider = ({
|
|
|
7637
8035
|
return /* @__PURE__ */ jsxRuntime.jsx(ChatLocaleContext.Provider, { value, children });
|
|
7638
8036
|
};
|
|
7639
8037
|
var useChatLocale = () => {
|
|
7640
|
-
const context =
|
|
8038
|
+
const context = React3.useContext(ChatLocaleContext);
|
|
7641
8039
|
if (!context) {
|
|
7642
8040
|
throw new Error("useChatLocale must be used within ChatLocaleProvider");
|
|
7643
8041
|
}
|
|
@@ -7759,15 +8157,15 @@ function useChannelList({ debouncedSearch = "" }) {
|
|
|
7759
8157
|
const conversationsPage = exports.useChatStore((s) => s.conversationsPage);
|
|
7760
8158
|
const accessToken = exports.useChatStore((s) => s.accessToken);
|
|
7761
8159
|
const loggedUserDetails = exports.useChatStore((s) => s.loggedUserDetails);
|
|
7762
|
-
const lastFetchKeyRef =
|
|
8160
|
+
const lastFetchKeyRef = React3.useRef(null);
|
|
7763
8161
|
useDraftRevision();
|
|
7764
8162
|
const { formatSidebarTime } = useChatLocale();
|
|
7765
|
-
|
|
8163
|
+
React3.useEffect(() => {
|
|
7766
8164
|
if (accessToken) {
|
|
7767
8165
|
exports.useChatStore.getState().fetchAllUsers();
|
|
7768
8166
|
}
|
|
7769
8167
|
}, [accessToken]);
|
|
7770
|
-
|
|
8168
|
+
React3.useEffect(() => {
|
|
7771
8169
|
if (!accessToken) return;
|
|
7772
8170
|
const fetchKey = debouncedSearch;
|
|
7773
8171
|
if (lastFetchKeyRef.current === fetchKey) return;
|
|
@@ -7779,7 +8177,7 @@ function useChannelList({ debouncedSearch = "" }) {
|
|
|
7779
8177
|
}
|
|
7780
8178
|
fetchConversations2(DEFAULT_CONVERSATIONS_LIMIT, 1, debouncedSearch, true);
|
|
7781
8179
|
}, [accessToken, debouncedSearch]);
|
|
7782
|
-
const mappedChannels =
|
|
8180
|
+
const mappedChannels = React3.useMemo(() => {
|
|
7783
8181
|
const safeConversations = Array.isArray(conversations) ? conversations : [];
|
|
7784
8182
|
const seenConversationIds = /* @__PURE__ */ new Set();
|
|
7785
8183
|
return safeConversations.map((c) => {
|
|
@@ -8383,7 +8781,7 @@ function highlightSearchMatch(text, query) {
|
|
|
8383
8781
|
children: part
|
|
8384
8782
|
},
|
|
8385
8783
|
`${part}-${index}`
|
|
8386
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
8784
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(React3__namespace.default.Fragment, { children: part }, `${part}-${index}`)
|
|
8387
8785
|
);
|
|
8388
8786
|
}
|
|
8389
8787
|
function getMessagePreview(message) {
|
|
@@ -8430,14 +8828,14 @@ var HeaderSearchPopover = ({
|
|
|
8430
8828
|
}) => {
|
|
8431
8829
|
const { scopeClassName, themeStyles } = useChatTheme();
|
|
8432
8830
|
const { formatMessageTime, formatShortDate } = useChatLocale();
|
|
8433
|
-
const inputRef =
|
|
8434
|
-
|
|
8831
|
+
const inputRef = React3.useRef(null);
|
|
8832
|
+
React3.useEffect(() => {
|
|
8435
8833
|
if (!open) return;
|
|
8436
8834
|
const timer = window.setTimeout(() => inputRef.current?.focus(), 0);
|
|
8437
8835
|
return () => window.clearTimeout(timer);
|
|
8438
8836
|
}, [open]);
|
|
8439
8837
|
const showResults = searchQuery.trim().length > 0;
|
|
8440
|
-
const resultCountLabel =
|
|
8838
|
+
const resultCountLabel = React3.useMemo(() => {
|
|
8441
8839
|
if (!searchResults.length) return "0 results";
|
|
8442
8840
|
return `${searchResults.length}${hasMore ? "+" : ""} result${searchResults.length === 1 ? "" : "s"}`;
|
|
8443
8841
|
}, [hasMore, searchResults.length]);
|
|
@@ -8563,7 +8961,7 @@ var HeaderSearchPopover = ({
|
|
|
8563
8961
|
] });
|
|
8564
8962
|
};
|
|
8565
8963
|
var HeaderSearchPopover_default = HeaderSearchPopover;
|
|
8566
|
-
var actionBtnClass = "size-8 rounded-lg text-(--chat-muted) transition-colors hover:bg-(--chat-surface) hover:text-(--chat-text)";
|
|
8964
|
+
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";
|
|
8567
8965
|
var DefaultHeaderCallActions = ({
|
|
8568
8966
|
activeChannel,
|
|
8569
8967
|
conversationId,
|
|
@@ -8574,48 +8972,91 @@ var DefaultHeaderCallActions = ({
|
|
|
8574
8972
|
className
|
|
8575
8973
|
}) => {
|
|
8576
8974
|
const { components, slotClassName, features } = useChatCustomizationOptional();
|
|
8975
|
+
const { getAudioCallGate, getVideoCallGate } = useEffectiveSettingsOptional();
|
|
8577
8976
|
const PhoneSlot = components.PhoneCallButton;
|
|
8578
8977
|
const VideoSlot = components.VideoCallButton;
|
|
8579
8978
|
const hideInGroups = features.hideCallActionsInGroupChats ?? false;
|
|
8979
|
+
const audioGate = getAudioCallGate();
|
|
8980
|
+
const videoGate = getVideoCallGate();
|
|
8580
8981
|
if (hideInGroups && activeChannel.isGroup) return null;
|
|
8581
8982
|
if (!showPhoneCall && !showVideoCall) return null;
|
|
8983
|
+
const phoneEnabled = showPhoneCall && audioGate.enabled;
|
|
8984
|
+
const videoEnabled = showVideoCall && videoGate.enabled;
|
|
8582
8985
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8583
8986
|
showPhoneCall && (PhoneSlot ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8584
|
-
|
|
8987
|
+
AdminPermissionTooltip,
|
|
8585
8988
|
{
|
|
8586
|
-
|
|
8587
|
-
|
|
8588
|
-
|
|
8589
|
-
|
|
8989
|
+
disabled: !audioGate.enabled,
|
|
8990
|
+
message: audioGate.disabledReason,
|
|
8991
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8992
|
+
PhoneSlot,
|
|
8993
|
+
{
|
|
8994
|
+
activeChannel,
|
|
8995
|
+
conversationId,
|
|
8996
|
+
onPhoneCall: phoneEnabled ? onPhoneCall : void 0,
|
|
8997
|
+
className: cn(
|
|
8998
|
+
className,
|
|
8999
|
+
slotClassName("phoneCallButton"),
|
|
9000
|
+
!audioGate.enabled && "pointer-events-none opacity-40"
|
|
9001
|
+
)
|
|
9002
|
+
}
|
|
9003
|
+
) })
|
|
8590
9004
|
}
|
|
8591
9005
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
8592
|
-
|
|
9006
|
+
AdminPermissionTooltip,
|
|
8593
9007
|
{
|
|
8594
|
-
|
|
8595
|
-
|
|
8596
|
-
|
|
8597
|
-
|
|
8598
|
-
|
|
8599
|
-
|
|
9008
|
+
disabled: !audioGate.enabled,
|
|
9009
|
+
message: audioGate.disabledReason,
|
|
9010
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9011
|
+
Button,
|
|
9012
|
+
{
|
|
9013
|
+
variant: "ghost",
|
|
9014
|
+
size: "icon",
|
|
9015
|
+
className: cn(actionBtnClass, className, slotClassName("phoneCallButton")),
|
|
9016
|
+
"aria-label": "Voice call",
|
|
9017
|
+
disabled: !audioGate.enabled,
|
|
9018
|
+
onClick: phoneEnabled ? onPhoneCall : void 0,
|
|
9019
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Phone, { size: 15 })
|
|
9020
|
+
}
|
|
9021
|
+
)
|
|
8600
9022
|
}
|
|
8601
9023
|
)),
|
|
8602
9024
|
showVideoCall && (VideoSlot ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8603
|
-
|
|
9025
|
+
AdminPermissionTooltip,
|
|
8604
9026
|
{
|
|
8605
|
-
|
|
8606
|
-
|
|
8607
|
-
|
|
8608
|
-
|
|
9027
|
+
disabled: !videoGate.enabled,
|
|
9028
|
+
message: videoGate.disabledReason,
|
|
9029
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9030
|
+
VideoSlot,
|
|
9031
|
+
{
|
|
9032
|
+
activeChannel,
|
|
9033
|
+
conversationId,
|
|
9034
|
+
onVideoCall: videoEnabled ? onVideoCall : void 0,
|
|
9035
|
+
className: cn(
|
|
9036
|
+
className,
|
|
9037
|
+
slotClassName("videoCallButton"),
|
|
9038
|
+
!videoGate.enabled && "pointer-events-none opacity-40"
|
|
9039
|
+
)
|
|
9040
|
+
}
|
|
9041
|
+
) })
|
|
8609
9042
|
}
|
|
8610
9043
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
8611
|
-
|
|
9044
|
+
AdminPermissionTooltip,
|
|
8612
9045
|
{
|
|
8613
|
-
|
|
8614
|
-
|
|
8615
|
-
|
|
8616
|
-
|
|
8617
|
-
|
|
8618
|
-
|
|
9046
|
+
disabled: !videoGate.enabled,
|
|
9047
|
+
message: videoGate.disabledReason,
|
|
9048
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9049
|
+
Button,
|
|
9050
|
+
{
|
|
9051
|
+
variant: "ghost",
|
|
9052
|
+
size: "icon",
|
|
9053
|
+
className: cn(actionBtnClass, className, slotClassName("videoCallButton")),
|
|
9054
|
+
"aria-label": "Video call",
|
|
9055
|
+
disabled: !videoGate.enabled,
|
|
9056
|
+
onClick: videoEnabled ? onVideoCall : void 0,
|
|
9057
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Video, { size: 15 })
|
|
9058
|
+
}
|
|
9059
|
+
)
|
|
8619
9060
|
}
|
|
8620
9061
|
))
|
|
8621
9062
|
] });
|
|
@@ -8637,19 +9078,38 @@ function OptionsMenuItem({
|
|
|
8637
9078
|
icon: Icon,
|
|
8638
9079
|
label,
|
|
8639
9080
|
onSelect,
|
|
8640
|
-
destructive = false
|
|
9081
|
+
destructive = false,
|
|
9082
|
+
disabled = false,
|
|
9083
|
+
disabledReason
|
|
8641
9084
|
}) {
|
|
8642
|
-
|
|
9085
|
+
const item = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8643
9086
|
DropdownMenuItem,
|
|
8644
9087
|
{
|
|
8645
|
-
className:
|
|
8646
|
-
|
|
9088
|
+
className: cn(
|
|
9089
|
+
destructive ? chatOptionsMenuItemDestructiveClass : chatOptionsMenuItemClass,
|
|
9090
|
+
disabled && "pointer-events-none opacity-40"
|
|
9091
|
+
),
|
|
9092
|
+
disabled,
|
|
9093
|
+
onSelect: (event) => {
|
|
9094
|
+
if (disabled) {
|
|
9095
|
+
event.preventDefault();
|
|
9096
|
+
return;
|
|
9097
|
+
}
|
|
9098
|
+
onSelect?.();
|
|
9099
|
+
},
|
|
8647
9100
|
children: [
|
|
8648
9101
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { strokeWidth: 1.75 }),
|
|
8649
9102
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: label })
|
|
8650
9103
|
]
|
|
8651
9104
|
}
|
|
8652
9105
|
);
|
|
9106
|
+
if (!disabled || !disabledReason) {
|
|
9107
|
+
return item;
|
|
9108
|
+
}
|
|
9109
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
|
|
9110
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full", children: item }) }),
|
|
9111
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "left", className: "max-w-[220px] text-xs", children: disabledReason })
|
|
9112
|
+
] });
|
|
8653
9113
|
}
|
|
8654
9114
|
var HeaderRightSide = ({
|
|
8655
9115
|
activeChannel,
|
|
@@ -8684,6 +9144,8 @@ var HeaderRightSide = ({
|
|
|
8684
9144
|
const { scopeClassName, themeStyles, showColorModeToggle } = useChatTheme();
|
|
8685
9145
|
const { showDateTimeSettings } = useChatLocale();
|
|
8686
9146
|
const features = useChatFeaturesOptional();
|
|
9147
|
+
const { getBlockUsersGate } = useEffectiveSettingsOptional();
|
|
9148
|
+
const blockUsersGate = getBlockUsersGate();
|
|
8687
9149
|
const showPhoneCall = features.showPhoneCall ?? defaultChatFeatures.showPhoneCall;
|
|
8688
9150
|
const showVideoCall = features.showVideoCall ?? defaultChatFeatures.showVideoCall;
|
|
8689
9151
|
const handlePhoneCall = () => {
|
|
@@ -8832,7 +9294,9 @@ var HeaderRightSide = ({
|
|
|
8832
9294
|
icon: lucideReact.Ban,
|
|
8833
9295
|
label: isBlocked ? "Unblock User" : "Block User",
|
|
8834
9296
|
onSelect: onToggleBlock,
|
|
8835
|
-
destructive: true
|
|
9297
|
+
destructive: true,
|
|
9298
|
+
disabled: !blockUsersGate.enabled,
|
|
9299
|
+
disabledReason: blockUsersGate.disabledReason
|
|
8836
9300
|
}
|
|
8837
9301
|
)
|
|
8838
9302
|
]
|
|
@@ -9203,13 +9667,13 @@ function AudioAttachmentPlayer({
|
|
|
9203
9667
|
showDownload = true,
|
|
9204
9668
|
downloadName
|
|
9205
9669
|
}) {
|
|
9206
|
-
const audioRef =
|
|
9207
|
-
const [isPlaying, setIsPlaying] =
|
|
9208
|
-
const [currentTime, setCurrentTime] =
|
|
9209
|
-
const [duration, setDuration] =
|
|
9670
|
+
const audioRef = React3.useRef(null);
|
|
9671
|
+
const [isPlaying, setIsPlaying] = React3.useState(false);
|
|
9672
|
+
const [currentTime, setCurrentTime] = React3.useState(0);
|
|
9673
|
+
const [duration, setDuration] = React3.useState(durationProp ?? 0);
|
|
9210
9674
|
const resolvedDuration = duration > 0 ? duration : 0;
|
|
9211
9675
|
const progressPercent = resolvedDuration > 0 ? Math.min(100, currentTime / resolvedDuration * 100) : 0;
|
|
9212
|
-
const togglePlay =
|
|
9676
|
+
const togglePlay = React3.useCallback(async () => {
|
|
9213
9677
|
const audio = audioRef.current;
|
|
9214
9678
|
if (!audio || !url) return;
|
|
9215
9679
|
if (audio.paused) {
|
|
@@ -9231,7 +9695,7 @@ function AudioAttachmentPlayer({
|
|
|
9231
9695
|
audio.currentTime = next;
|
|
9232
9696
|
setCurrentTime(next);
|
|
9233
9697
|
};
|
|
9234
|
-
|
|
9698
|
+
React3.useEffect(() => {
|
|
9235
9699
|
const audio = audioRef.current;
|
|
9236
9700
|
if (!audio) return;
|
|
9237
9701
|
const onTimeUpdate = () => setCurrentTime(audio.currentTime);
|
|
@@ -9259,7 +9723,7 @@ function AudioAttachmentPlayer({
|
|
|
9259
9723
|
audio.removeEventListener("play", onPlay);
|
|
9260
9724
|
};
|
|
9261
9725
|
}, [url]);
|
|
9262
|
-
|
|
9726
|
+
React3.useEffect(() => {
|
|
9263
9727
|
if (durationProp && durationProp > 0) {
|
|
9264
9728
|
setDuration(durationProp);
|
|
9265
9729
|
}
|
|
@@ -9381,12 +9845,12 @@ function VideoAttachmentPlayer({
|
|
|
9381
9845
|
downloadName,
|
|
9382
9846
|
onOpenPreview
|
|
9383
9847
|
}) {
|
|
9384
|
-
const videoRef =
|
|
9385
|
-
const [isPlaying, setIsPlaying] =
|
|
9386
|
-
const [duration, setDuration] =
|
|
9848
|
+
const videoRef = React3.useRef(null);
|
|
9849
|
+
const [isPlaying, setIsPlaying] = React3.useState(false);
|
|
9850
|
+
const [duration, setDuration] = React3.useState(durationProp ?? 0);
|
|
9387
9851
|
const onThemeBubble = inBubble && isSender;
|
|
9388
9852
|
const resolvedDuration = duration > 0 ? duration : 0;
|
|
9389
|
-
const togglePlay =
|
|
9853
|
+
const togglePlay = React3.useCallback(async () => {
|
|
9390
9854
|
const video = videoRef.current;
|
|
9391
9855
|
if (!video || !url) return;
|
|
9392
9856
|
if (video.paused) {
|
|
@@ -9401,7 +9865,7 @@ function VideoAttachmentPlayer({
|
|
|
9401
9865
|
setIsPlaying(false);
|
|
9402
9866
|
}
|
|
9403
9867
|
}, [url]);
|
|
9404
|
-
|
|
9868
|
+
React3.useEffect(() => {
|
|
9405
9869
|
if (durationProp && durationProp > 0) {
|
|
9406
9870
|
setDuration(durationProp);
|
|
9407
9871
|
}
|
|
@@ -9679,10 +10143,10 @@ async function fetchAuthenticatedBlob(url) {
|
|
|
9679
10143
|
return response.blob();
|
|
9680
10144
|
}
|
|
9681
10145
|
function PdfPreviewPanel({ url, name }) {
|
|
9682
|
-
const [blobUrl, setBlobUrl] =
|
|
9683
|
-
const [fallbackUrl, setFallbackUrl] =
|
|
9684
|
-
const [loading, setLoading] =
|
|
9685
|
-
|
|
10146
|
+
const [blobUrl, setBlobUrl] = React3.useState(null);
|
|
10147
|
+
const [fallbackUrl, setFallbackUrl] = React3.useState(null);
|
|
10148
|
+
const [loading, setLoading] = React3.useState(true);
|
|
10149
|
+
React3.useEffect(() => {
|
|
9686
10150
|
let active = true;
|
|
9687
10151
|
let objectUrl = null;
|
|
9688
10152
|
const loadPdf = async () => {
|
|
@@ -10186,60 +10650,60 @@ function AttachmentImageLightbox({
|
|
|
10186
10650
|
onSaveCaption,
|
|
10187
10651
|
initialCaptionEditing = false
|
|
10188
10652
|
}) {
|
|
10189
|
-
const [index, setIndex] =
|
|
10190
|
-
const [zoom, setZoom] =
|
|
10191
|
-
const [pan, setPan] =
|
|
10192
|
-
const [imageVersion, setImageVersion] =
|
|
10193
|
-
const [localCaptions, setLocalCaptions] =
|
|
10194
|
-
const [captionDraft, setCaptionDraft] =
|
|
10195
|
-
const [isCaptionEditing, setIsCaptionEditing] =
|
|
10196
|
-
const thumbRefs =
|
|
10197
|
-
const captionInputRef =
|
|
10198
|
-
const touchStartX =
|
|
10199
|
-
const isPanning =
|
|
10200
|
-
const panStart =
|
|
10653
|
+
const [index, setIndex] = React3.useState(initialIndex);
|
|
10654
|
+
const [zoom, setZoom] = React3.useState(1);
|
|
10655
|
+
const [pan, setPan] = React3.useState({ x: 0, y: 0 });
|
|
10656
|
+
const [imageVersion, setImageVersion] = React3.useState(0);
|
|
10657
|
+
const [localCaptions, setLocalCaptions] = React3.useState({});
|
|
10658
|
+
const [captionDraft, setCaptionDraft] = React3.useState("");
|
|
10659
|
+
const [isCaptionEditing, setIsCaptionEditing] = React3.useState(false);
|
|
10660
|
+
const thumbRefs = React3.useRef([]);
|
|
10661
|
+
const captionInputRef = React3.useRef(null);
|
|
10662
|
+
const touchStartX = React3.useRef(null);
|
|
10663
|
+
const isPanning = React3.useRef(false);
|
|
10664
|
+
const panStart = React3.useRef({ x: 0, y: 0, originX: 0, originY: 0 });
|
|
10201
10665
|
const canEdit = canEditCaption && !!onSaveCaption;
|
|
10202
|
-
|
|
10666
|
+
React3.useEffect(() => {
|
|
10203
10667
|
setIndex(initialIndex);
|
|
10204
10668
|
}, [initialIndex]);
|
|
10205
|
-
const resetView =
|
|
10669
|
+
const resetView = React3.useCallback(() => {
|
|
10206
10670
|
setZoom(1);
|
|
10207
10671
|
setPan({ x: 0, y: 0 });
|
|
10208
10672
|
}, []);
|
|
10209
|
-
const reloadImage =
|
|
10673
|
+
const reloadImage = React3.useCallback(() => {
|
|
10210
10674
|
resetView();
|
|
10211
10675
|
setImageVersion((version) => version + 1);
|
|
10212
10676
|
}, [resetView]);
|
|
10213
|
-
|
|
10677
|
+
React3.useEffect(() => {
|
|
10214
10678
|
resetView();
|
|
10215
10679
|
setIsCaptionEditing(false);
|
|
10216
10680
|
}, [index, resetView]);
|
|
10217
|
-
|
|
10681
|
+
React3.useEffect(() => {
|
|
10218
10682
|
if (!initialCaptionEditing || !canEdit) return;
|
|
10219
10683
|
setIsCaptionEditing(true);
|
|
10220
10684
|
}, [initialCaptionEditing, canEdit]);
|
|
10221
|
-
|
|
10685
|
+
React3.useEffect(() => {
|
|
10222
10686
|
if (!isCaptionEditing) return;
|
|
10223
10687
|
const id = window.setTimeout(() => captionInputRef.current?.focus(), 40);
|
|
10224
10688
|
return () => window.clearTimeout(id);
|
|
10225
10689
|
}, [isCaptionEditing]);
|
|
10226
|
-
const goPrev =
|
|
10690
|
+
const goPrev = React3.useCallback(() => {
|
|
10227
10691
|
setIndex((current2) => current2 > 0 ? current2 - 1 : images.length - 1);
|
|
10228
10692
|
}, [images.length]);
|
|
10229
|
-
const goNext =
|
|
10693
|
+
const goNext = React3.useCallback(() => {
|
|
10230
10694
|
setIndex((current2) => current2 < images.length - 1 ? current2 + 1 : 0);
|
|
10231
10695
|
}, [images.length]);
|
|
10232
|
-
const zoomIn =
|
|
10696
|
+
const zoomIn = React3.useCallback(() => {
|
|
10233
10697
|
setZoom((current2) => clampZoom(Number((current2 + ZOOM_STEP).toFixed(2))));
|
|
10234
10698
|
}, []);
|
|
10235
|
-
const zoomOut =
|
|
10699
|
+
const zoomOut = React3.useCallback(() => {
|
|
10236
10700
|
setZoom((current2) => {
|
|
10237
10701
|
const next = clampZoom(Number((current2 - ZOOM_STEP).toFixed(2)));
|
|
10238
10702
|
if (next <= MIN_ZOOM) setPan({ x: 0, y: 0 });
|
|
10239
10703
|
return next;
|
|
10240
10704
|
});
|
|
10241
10705
|
}, []);
|
|
10242
|
-
|
|
10706
|
+
React3.useEffect(() => {
|
|
10243
10707
|
const onKeyDown = (event) => {
|
|
10244
10708
|
const tag = event.target?.tagName;
|
|
10245
10709
|
const isTyping = tag === "INPUT" || tag === "TEXTAREA";
|
|
@@ -10253,14 +10717,14 @@ function AttachmentImageLightbox({
|
|
|
10253
10717
|
window.addEventListener("keydown", onKeyDown);
|
|
10254
10718
|
return () => window.removeEventListener("keydown", onKeyDown);
|
|
10255
10719
|
}, [goPrev, goNext, zoomIn, zoomOut, resetView]);
|
|
10256
|
-
|
|
10720
|
+
React3.useEffect(() => {
|
|
10257
10721
|
thumbRefs.current[index]?.scrollIntoView({
|
|
10258
10722
|
behavior: "smooth",
|
|
10259
10723
|
block: "nearest",
|
|
10260
10724
|
inline: "center"
|
|
10261
10725
|
});
|
|
10262
10726
|
}, [index]);
|
|
10263
|
-
|
|
10727
|
+
React3.useEffect(() => {
|
|
10264
10728
|
const attachment = images[index];
|
|
10265
10729
|
if (!attachment) return;
|
|
10266
10730
|
setCaptionDraft(getCaptionForAttachment(attachment, localCaptions));
|
|
@@ -10731,7 +11195,7 @@ function MessageAttachmentGrid({
|
|
|
10731
11195
|
onToggleAttachmentSelect,
|
|
10732
11196
|
onAttachmentHover
|
|
10733
11197
|
}) {
|
|
10734
|
-
const [lightboxIndex, setLightboxIndex] =
|
|
11198
|
+
const [lightboxIndex, setLightboxIndex] = React3.useState(null);
|
|
10735
11199
|
if (!images.length) return null;
|
|
10736
11200
|
const visible = images.slice(0, MAX_VISIBLE);
|
|
10737
11201
|
const overflow = images.length - MAX_VISIBLE;
|
|
@@ -10951,7 +11415,7 @@ function MessageAttachmentsImageSection({
|
|
|
10951
11415
|
hoveredAttachmentId,
|
|
10952
11416
|
onAttachmentHover
|
|
10953
11417
|
}) {
|
|
10954
|
-
const [lightboxIndex, setLightboxIndex] =
|
|
11418
|
+
const [lightboxIndex, setLightboxIndex] = React3.useState(null);
|
|
10955
11419
|
if (images.length === 0) return null;
|
|
10956
11420
|
const renderMediaMetaOverlay = () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
10957
11421
|
MediaMetaOverlay,
|
|
@@ -11426,7 +11890,7 @@ function MessageAttachmentsView({
|
|
|
11426
11890
|
senderName,
|
|
11427
11891
|
senderId
|
|
11428
11892
|
}) {
|
|
11429
|
-
const [documentPreview, setDocumentPreview] =
|
|
11893
|
+
const [documentPreview, setDocumentPreview] = React3.useState(null);
|
|
11430
11894
|
const visibleAttachments = getVisibleAttachments(attachments);
|
|
11431
11895
|
if (isDeletedForEveryone || visibleAttachments.length === 0) return null;
|
|
11432
11896
|
const messageCaption = caption?.trim() || "";
|
|
@@ -11811,8 +12275,8 @@ var SavedMessagesDrawer = ({
|
|
|
11811
12275
|
const conversationMessages = exports.useChatStore(
|
|
11812
12276
|
(s) => conversationId ? s.messagesByConversation[conversationId] ?? EMPTY_CONVERSATION_MESSAGES : EMPTY_CONVERSATION_MESSAGES
|
|
11813
12277
|
);
|
|
11814
|
-
const [searchQuery, setSearchQuery] =
|
|
11815
|
-
const parsedEntries =
|
|
12278
|
+
const [searchQuery, setSearchQuery] = React3.useState("");
|
|
12279
|
+
const parsedEntries = React3.useMemo(() => {
|
|
11816
12280
|
return messages.map((msg) => ({
|
|
11817
12281
|
msg,
|
|
11818
12282
|
item: parseSavedMessage(msg, {
|
|
@@ -11833,7 +12297,7 @@ var SavedMessagesDrawer = ({
|
|
|
11833
12297
|
variant,
|
|
11834
12298
|
prefs
|
|
11835
12299
|
]);
|
|
11836
|
-
const groupedEntries =
|
|
12300
|
+
const groupedEntries = React3.useMemo(() => {
|
|
11837
12301
|
const query = searchQuery.trim().toLowerCase();
|
|
11838
12302
|
const filtered = parsedEntries.filter(({ item, msg }) => {
|
|
11839
12303
|
if (!query) return true;
|
|
@@ -12106,15 +12570,15 @@ function SectionScrollArea({
|
|
|
12106
12570
|
onLoadMore,
|
|
12107
12571
|
dependencyKey
|
|
12108
12572
|
}) {
|
|
12109
|
-
const scrollRef =
|
|
12110
|
-
const [showArrow, setShowArrow] =
|
|
12111
|
-
const updateArrow =
|
|
12573
|
+
const scrollRef = React3.useRef(null);
|
|
12574
|
+
const [showArrow, setShowArrow] = React3.useState(false);
|
|
12575
|
+
const updateArrow = React3.useCallback(() => {
|
|
12112
12576
|
const el = scrollRef.current;
|
|
12113
12577
|
if (!el) return;
|
|
12114
12578
|
const canScrollDown = el.scrollHeight - el.scrollTop - el.clientHeight > 6;
|
|
12115
12579
|
setShowArrow(canScrollDown || hasMoreToLoad);
|
|
12116
12580
|
}, [hasMoreToLoad]);
|
|
12117
|
-
|
|
12581
|
+
React3.useEffect(() => {
|
|
12118
12582
|
updateArrow();
|
|
12119
12583
|
const el = scrollRef.current;
|
|
12120
12584
|
if (!el) return;
|
|
@@ -12290,31 +12754,31 @@ var AttachmentsDrawer = ({ isOpen, onOpenChange, conversationId }) => {
|
|
|
12290
12754
|
const messagesByConversation = exports.useChatStore((s) => s.messagesByConversation);
|
|
12291
12755
|
const messagesMetadata = exports.useChatStore((s) => s.messagesMetadata);
|
|
12292
12756
|
const fetchMessages2 = exports.useChatStore((s) => s.fetchMessages);
|
|
12293
|
-
const [sectionVisibleCount, setSectionVisibleCount] =
|
|
12294
|
-
const [documentPreview, setDocumentPreview] =
|
|
12295
|
-
const [imageLightboxIndex, setImageLightboxIndex] =
|
|
12757
|
+
const [sectionVisibleCount, setSectionVisibleCount] = React3.useState({});
|
|
12758
|
+
const [documentPreview, setDocumentPreview] = React3.useState(null);
|
|
12759
|
+
const [imageLightboxIndex, setImageLightboxIndex] = React3.useState(null);
|
|
12296
12760
|
const hasLoadedMessages = conversationId ? Boolean(messagesMetadata[conversationId]?.isFirstPage) : false;
|
|
12297
12761
|
const isLoading = isOpen && !!conversationId && !hasLoadedMessages;
|
|
12298
|
-
|
|
12762
|
+
React3.useEffect(() => {
|
|
12299
12763
|
if (!isOpen) {
|
|
12300
12764
|
setSectionVisibleCount({});
|
|
12301
12765
|
setDocumentPreview(null);
|
|
12302
12766
|
setImageLightboxIndex(null);
|
|
12303
12767
|
}
|
|
12304
12768
|
}, [isOpen]);
|
|
12305
|
-
|
|
12769
|
+
React3.useEffect(() => {
|
|
12306
12770
|
setSectionVisibleCount({});
|
|
12307
12771
|
}, [conversationId]);
|
|
12308
|
-
|
|
12772
|
+
React3.useEffect(() => {
|
|
12309
12773
|
if (!isOpen || !conversationId || hasLoadedMessages) return;
|
|
12310
12774
|
fetchMessages2(conversationId);
|
|
12311
12775
|
}, [isOpen, conversationId, hasLoadedMessages, fetchMessages2]);
|
|
12312
|
-
const attachments =
|
|
12776
|
+
const attachments = React3.useMemo(() => {
|
|
12313
12777
|
if (!conversationId) return [];
|
|
12314
12778
|
const messages = messagesByConversation[conversationId] || [];
|
|
12315
12779
|
return collectConversationAttachments(messages);
|
|
12316
12780
|
}, [conversationId, messagesByConversation]);
|
|
12317
|
-
const imageLightboxItems =
|
|
12781
|
+
const imageLightboxItems = React3.useMemo(
|
|
12318
12782
|
() => attachments.filter((item) => item.type === "image").map((item) => ({
|
|
12319
12783
|
id: item.id,
|
|
12320
12784
|
url: item.url,
|
|
@@ -12323,14 +12787,14 @@ var AttachmentsDrawer = ({ isOpen, onOpenChange, conversationId }) => {
|
|
|
12323
12787
|
})),
|
|
12324
12788
|
[attachments]
|
|
12325
12789
|
);
|
|
12326
|
-
const openImagePreview =
|
|
12790
|
+
const openImagePreview = React3.useCallback(
|
|
12327
12791
|
(item) => {
|
|
12328
12792
|
const index = imageLightboxItems.findIndex((entry) => entry.id === item.id);
|
|
12329
12793
|
if (index >= 0) setImageLightboxIndex(index);
|
|
12330
12794
|
},
|
|
12331
12795
|
[imageLightboxItems]
|
|
12332
12796
|
);
|
|
12333
|
-
const grouped =
|
|
12797
|
+
const grouped = React3.useMemo(() => {
|
|
12334
12798
|
const map = /* @__PURE__ */ new Map();
|
|
12335
12799
|
for (const item of attachments) {
|
|
12336
12800
|
const bucket = map.get(item.type) ?? [];
|
|
@@ -12430,13 +12894,13 @@ var useGroupInfo = (conversationId) => {
|
|
|
12430
12894
|
const conversationInfos = exports.useChatStore((s) => s.conversationInfos);
|
|
12431
12895
|
const loggedUserDetails = exports.useChatStore((s) => s.loggedUserDetails);
|
|
12432
12896
|
const info = conversationId ? conversationInfos[conversationId] : null;
|
|
12433
|
-
const isAdmin =
|
|
12897
|
+
const isAdmin = React3.useMemo(() => {
|
|
12434
12898
|
if (!info || !loggedUserDetails) return false;
|
|
12435
12899
|
return info.groupAdmins?.some(
|
|
12436
12900
|
(admin) => (typeof admin === "string" ? admin : admin._id) === String(loggedUserDetails._id)
|
|
12437
12901
|
) || false;
|
|
12438
12902
|
}, [info, loggedUserDetails]);
|
|
12439
|
-
const isOwner =
|
|
12903
|
+
const isOwner = React3.useMemo(() => {
|
|
12440
12904
|
if (!info || !loggedUserDetails) return false;
|
|
12441
12905
|
let ownerId = null;
|
|
12442
12906
|
if (info.owner) {
|
|
@@ -12445,7 +12909,7 @@ var useGroupInfo = (conversationId) => {
|
|
|
12445
12909
|
return String(ownerId) === String(loggedUserDetails._id);
|
|
12446
12910
|
}, [info, loggedUserDetails]);
|
|
12447
12911
|
const permissions = info?.groupPermissions || null;
|
|
12448
|
-
const userPermissions =
|
|
12912
|
+
const userPermissions = React3.useMemo(() => {
|
|
12449
12913
|
return {
|
|
12450
12914
|
canSendMessage: isOwner || isAdmin || !permissions?.onlyAdminCanSendMessage,
|
|
12451
12915
|
canEditInfo: isOwner || isAdmin || !permissions?.onlyAdminCanEditInfo,
|
|
@@ -12494,21 +12958,21 @@ function useChannelDetailsDrawer({
|
|
|
12494
12958
|
const conversationId = conversationInfo?._id || activeChannel?.conversationId || storeActiveConversationId || null;
|
|
12495
12959
|
const { userPermissions } = useGroupInfo(conversationId);
|
|
12496
12960
|
const { formatLongDate } = useChatLocale();
|
|
12497
|
-
const storeConversation =
|
|
12961
|
+
const storeConversation = React3.useMemo(
|
|
12498
12962
|
() => conversations.find((c) => conversationId && String(c._id) === String(conversationId)),
|
|
12499
12963
|
[conversations, conversationId]
|
|
12500
12964
|
);
|
|
12501
|
-
const isGroupChannel =
|
|
12965
|
+
const isGroupChannel = React3.useMemo(() => {
|
|
12502
12966
|
if (storeConversation) {
|
|
12503
12967
|
return storeConversation.conversationType === "group" || !!storeConversation.isGroup;
|
|
12504
12968
|
}
|
|
12505
12969
|
return !!activeChannel?.isGroup;
|
|
12506
12970
|
}, [storeConversation, activeChannel?.isGroup]);
|
|
12507
|
-
const participantsSource =
|
|
12971
|
+
const participantsSource = React3.useMemo(
|
|
12508
12972
|
() => conversationInfo?.participants || storeConversation?.participants || [],
|
|
12509
12973
|
[conversationInfo?.participants, storeConversation?.participants]
|
|
12510
12974
|
);
|
|
12511
|
-
const resolvedOtherParticipant =
|
|
12975
|
+
const resolvedOtherParticipant = React3.useMemo(() => {
|
|
12512
12976
|
if (isGroupChannel) return { id: "", user: null };
|
|
12513
12977
|
return resolveOtherParticipant(
|
|
12514
12978
|
{
|
|
@@ -12527,7 +12991,7 @@ function useChannelDetailsDrawer({
|
|
|
12527
12991
|
allUsers
|
|
12528
12992
|
]);
|
|
12529
12993
|
const otherUser = resolvedOtherParticipant.user;
|
|
12530
|
-
const otherUserEmail =
|
|
12994
|
+
const otherUserEmail = React3.useMemo(() => {
|
|
12531
12995
|
if (isGroupChannel) return null;
|
|
12532
12996
|
const fromResolved = resolvedOtherParticipant.user?.email?.trim();
|
|
12533
12997
|
if (fromResolved) return fromResolved;
|
|
@@ -12535,7 +12999,7 @@ function useChannelDetailsDrawer({
|
|
|
12535
12999
|
if (!otherId) return null;
|
|
12536
13000
|
return allUsers.find((user) => String(user._id) === String(otherId))?.email?.trim() || activeChannel?.email?.trim() || null;
|
|
12537
13001
|
}, [isGroupChannel, resolvedOtherParticipant.id, resolvedOtherParticipant.user?.email, allUsers, activeChannel?.email]);
|
|
12538
|
-
const resolvedCreatedAt =
|
|
13002
|
+
const resolvedCreatedAt = React3.useMemo(
|
|
12539
13003
|
() => pickDate(
|
|
12540
13004
|
conversationInfo?.createdAt,
|
|
12541
13005
|
conversationInfo?.updatedAt,
|
|
@@ -12548,9 +13012,9 @@ function useChannelDetailsDrawer({
|
|
|
12548
13012
|
),
|
|
12549
13013
|
[conversationInfo, storeConversation, otherUser, conversationId, messagesByConversation]
|
|
12550
13014
|
);
|
|
12551
|
-
const [detailsLoading, setDetailsLoading] =
|
|
12552
|
-
const fetchStartedRef =
|
|
12553
|
-
|
|
13015
|
+
const [detailsLoading, setDetailsLoading] = React3.useState(false);
|
|
13016
|
+
const fetchStartedRef = React3.useRef(null);
|
|
13017
|
+
React3.useEffect(() => {
|
|
12554
13018
|
if (!isOpen) {
|
|
12555
13019
|
fetchStartedRef.current = null;
|
|
12556
13020
|
setDetailsLoading(false);
|
|
@@ -12592,16 +13056,16 @@ function useChannelDetailsDrawer({
|
|
|
12592
13056
|
};
|
|
12593
13057
|
}, [isOpen, conversationId, isGroupChannel, fetchAllUsers]);
|
|
12594
13058
|
const canEditInfo = activeChannel ? userPermissions.canEditInfo : false;
|
|
12595
|
-
const [isEditing, setIsEditing] =
|
|
12596
|
-
const [name, setName] =
|
|
12597
|
-
const [description, setDescription] =
|
|
12598
|
-
const [image, setImage] =
|
|
12599
|
-
const [uploadedImageUrl, setUploadedImageUrl] =
|
|
12600
|
-
const [imageUploadStatus, setImageUploadStatus] =
|
|
12601
|
-
const [imageUploadError, setImageUploadError] =
|
|
12602
|
-
const [isSaving, setIsSaving] =
|
|
12603
|
-
const fileInputRef =
|
|
12604
|
-
|
|
13059
|
+
const [isEditing, setIsEditing] = React3.useState(false);
|
|
13060
|
+
const [name, setName] = React3.useState("");
|
|
13061
|
+
const [description, setDescription] = React3.useState("");
|
|
13062
|
+
const [image, setImage] = React3.useState(null);
|
|
13063
|
+
const [uploadedImageUrl, setUploadedImageUrl] = React3.useState(null);
|
|
13064
|
+
const [imageUploadStatus, setImageUploadStatus] = React3.useState("idle");
|
|
13065
|
+
const [imageUploadError, setImageUploadError] = React3.useState(null);
|
|
13066
|
+
const [isSaving, setIsSaving] = React3.useState(false);
|
|
13067
|
+
const fileInputRef = React3.useRef(null);
|
|
13068
|
+
React3.useEffect(() => {
|
|
12605
13069
|
if (conversationInfo) {
|
|
12606
13070
|
setName(conversationInfo.groupName || activeChannel?.name || "");
|
|
12607
13071
|
setDescription(conversationInfo.groupDescription || "");
|
|
@@ -12872,17 +13336,24 @@ var ChannelDetailsDrawer = (props) => {
|
|
|
12872
13336
|
};
|
|
12873
13337
|
var ChannelDetailsDrawer_default = ChannelDetailsDrawer;
|
|
12874
13338
|
init_useStore();
|
|
13339
|
+
init_settings_types();
|
|
12875
13340
|
var PermissionDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo }) => {
|
|
12876
13341
|
const updateGroupPermissions = exports.useChatStore((s) => s.updateGroupPermissions);
|
|
12877
|
-
const
|
|
12878
|
-
const [
|
|
12879
|
-
|
|
13342
|
+
const { settings, isGroupPermissionLocked } = useEffectiveSettingsOptional();
|
|
13343
|
+
const [permissions, setPermissions] = React3.useState(null);
|
|
13344
|
+
const [isSaving, setIsSaving] = React3.useState(false);
|
|
13345
|
+
React3.useEffect(() => {
|
|
12880
13346
|
if (conversationInfo?.groupPermissions) {
|
|
12881
13347
|
setPermissions(conversationInfo.groupPermissions);
|
|
13348
|
+
return;
|
|
13349
|
+
}
|
|
13350
|
+
if (isOpen) {
|
|
13351
|
+
setPermissions({ ...settings.groupPolicy.defaults });
|
|
12882
13352
|
}
|
|
12883
|
-
}, [conversationInfo]);
|
|
13353
|
+
}, [conversationInfo, isOpen, settings.groupPolicy.defaults]);
|
|
12884
13354
|
if (!conversationId || !permissions) return null;
|
|
12885
13355
|
const handleToggle = (key) => {
|
|
13356
|
+
if (isGroupPermissionLocked(key)) return;
|
|
12886
13357
|
setPermissions((prev) => prev ? { ...prev, [key]: !prev[key] } : null);
|
|
12887
13358
|
};
|
|
12888
13359
|
const handleSave = async () => {
|
|
@@ -12914,31 +13385,43 @@ var PermissionDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo
|
|
|
12914
13385
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(chatSheetBodyClass, "flex flex-col px-2.5 py-2"), children: [
|
|
12915
13386
|
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "mb-2.5 flex-1", children: [
|
|
12916
13387
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-1 px-0.5 text-[10px] font-semibold uppercase tracking-wide text-(--chat-muted)", children: "Permissions" }),
|
|
12917
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-(--chat-border) px-3", children: permissionItems.map((item, index) =>
|
|
12918
|
-
|
|
12919
|
-
|
|
12920
|
-
|
|
12921
|
-
|
|
12922
|
-
|
|
12923
|
-
|
|
12924
|
-
|
|
12925
|
-
|
|
12926
|
-
|
|
12927
|
-
/* @__PURE__ */ jsxRuntime.
|
|
12928
|
-
|
|
12929
|
-
|
|
12930
|
-
|
|
12931
|
-
|
|
12932
|
-
|
|
12933
|
-
|
|
12934
|
-
|
|
12935
|
-
|
|
12936
|
-
|
|
12937
|
-
|
|
12938
|
-
|
|
12939
|
-
|
|
12940
|
-
|
|
12941
|
-
|
|
13388
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-(--chat-border) px-3", children: permissionItems.map((item, index) => {
|
|
13389
|
+
const locked = isGroupPermissionLocked(item.key);
|
|
13390
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
13391
|
+
"div",
|
|
13392
|
+
{
|
|
13393
|
+
className: cn(
|
|
13394
|
+
"flex items-start justify-between gap-3 py-2.5",
|
|
13395
|
+
index < permissionItems.length - 1 && "border-b border-(--chat-border)"
|
|
13396
|
+
),
|
|
13397
|
+
children: [
|
|
13398
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-0.5", children: [
|
|
13399
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[12px] font-semibold leading-snug text-(--chat-text)", children: item.label }),
|
|
13400
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] leading-relaxed text-(--chat-muted)", children: item.desc }),
|
|
13401
|
+
locked ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] font-medium text-(--chat-theme)", children: "Locked by administrator" }) : null
|
|
13402
|
+
] }),
|
|
13403
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13404
|
+
AdminPermissionTooltip,
|
|
13405
|
+
{
|
|
13406
|
+
disabled: locked,
|
|
13407
|
+
message: exports.ADMIN_PERMISSION_DENIED_MESSAGE,
|
|
13408
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
13409
|
+
Switch,
|
|
13410
|
+
{
|
|
13411
|
+
size: "sm",
|
|
13412
|
+
className: "mt-0.5 shrink-0 data-[state=checked]:bg-(--chat-theme) data-[state=unchecked]:bg-(--chat-border)",
|
|
13413
|
+
disabled: locked,
|
|
13414
|
+
checked: item.inverted ? !permissions[item.key] : permissions[item.key],
|
|
13415
|
+
onCheckedChange: () => handleToggle(item.key)
|
|
13416
|
+
}
|
|
13417
|
+
)
|
|
13418
|
+
}
|
|
13419
|
+
)
|
|
13420
|
+
]
|
|
13421
|
+
},
|
|
13422
|
+
item.key
|
|
13423
|
+
);
|
|
13424
|
+
}) })
|
|
12942
13425
|
] }),
|
|
12943
13426
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky bottom-0 border-t border-(--chat-border) bg-(--chat-surface) px-0.5 pt-2.5 pb-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12944
13427
|
Button,
|
|
@@ -12964,51 +13447,61 @@ var PermissionDrawer_default = PermissionDrawer;
|
|
|
12964
13447
|
// src/chat/header/admins-drawer/useAdminsDrawer.ts
|
|
12965
13448
|
init_useStore();
|
|
12966
13449
|
function useAdminsDrawer({ conversationId, conversationInfo }) {
|
|
12967
|
-
const [searchQuery, setSearchQuery] =
|
|
12968
|
-
const [isManaging, setIsManaging] =
|
|
13450
|
+
const [searchQuery, setSearchQuery] = React3.useState("");
|
|
13451
|
+
const [isManaging, setIsManaging] = React3.useState(null);
|
|
12969
13452
|
const manageGroupAdmins = exports.useChatStore((s) => s.manageGroupAdmins);
|
|
12970
13453
|
const { isOwner } = useGroupInfo(conversationId);
|
|
12971
|
-
const
|
|
13454
|
+
const { settings } = useEffectiveSettingsOptional();
|
|
13455
|
+
const maxAdmins = settings.maxAdminsPerGroup;
|
|
13456
|
+
const participants = React3.useMemo(
|
|
12972
13457
|
() => conversationInfo?.participants ?? [],
|
|
12973
13458
|
[conversationInfo?.participants]
|
|
12974
13459
|
);
|
|
12975
|
-
const admins =
|
|
13460
|
+
const admins = React3.useMemo(
|
|
12976
13461
|
() => conversationInfo?.groupAdmins ?? [],
|
|
12977
13462
|
[conversationInfo?.groupAdmins]
|
|
12978
13463
|
);
|
|
12979
|
-
const ownerId =
|
|
13464
|
+
const ownerId = React3.useMemo(() => {
|
|
12980
13465
|
if (!conversationInfo?.owner) return null;
|
|
12981
13466
|
return typeof conversationInfo.owner === "object" && conversationInfo.owner !== null ? conversationInfo.owner._id || conversationInfo.owner.id : conversationInfo.owner;
|
|
12982
13467
|
}, [conversationInfo?.owner]);
|
|
12983
|
-
const adminIds =
|
|
13468
|
+
const adminIds = React3.useMemo(
|
|
12984
13469
|
() => new Set(
|
|
12985
13470
|
admins.map((a) => typeof a === "string" ? a : a._id).filter((id) => Boolean(id))
|
|
12986
13471
|
),
|
|
12987
13472
|
[admins]
|
|
12988
13473
|
);
|
|
12989
|
-
const isAdmin =
|
|
12990
|
-
const filteredParticipants =
|
|
13474
|
+
const isAdmin = React3.useCallback((userId) => adminIds.has(userId), [adminIds]);
|
|
13475
|
+
const filteredParticipants = React3.useMemo(() => {
|
|
12991
13476
|
if (!searchQuery.trim()) return participants;
|
|
12992
13477
|
return participants.filter(
|
|
12993
13478
|
(p) => p.name?.toLowerCase().includes(searchQuery.toLowerCase()) || p.email?.toLowerCase().includes(searchQuery.toLowerCase())
|
|
12994
13479
|
);
|
|
12995
13480
|
}, [participants, searchQuery]);
|
|
12996
|
-
const adminParticipants =
|
|
13481
|
+
const adminParticipants = React3.useMemo(
|
|
12997
13482
|
() => filteredParticipants.filter((p) => {
|
|
12998
13483
|
const id = typeof p === "string" ? p : p._id;
|
|
12999
13484
|
return id && (adminIds.has(id) || id === ownerId);
|
|
13000
13485
|
}),
|
|
13001
13486
|
[filteredParticipants, adminIds, ownerId]
|
|
13002
13487
|
);
|
|
13003
|
-
const promotableParticipants =
|
|
13488
|
+
const promotableParticipants = React3.useMemo(
|
|
13004
13489
|
() => filteredParticipants.filter((p) => {
|
|
13005
13490
|
const id = typeof p === "string" ? p : p._id;
|
|
13006
13491
|
return id && id !== ownerId && !adminIds.has(id);
|
|
13007
13492
|
}),
|
|
13008
13493
|
[filteredParticipants, adminIds, ownerId]
|
|
13009
13494
|
);
|
|
13495
|
+
const adminCount = admins.length + (ownerId ? 1 : 0);
|
|
13496
|
+
const atAdminLimit = adminCount >= maxAdmins;
|
|
13010
13497
|
const handleManageAdmin = async (userId, type) => {
|
|
13011
13498
|
if (!conversationId) return;
|
|
13499
|
+
if (type === "add" && adminCount >= maxAdmins) {
|
|
13500
|
+
exports.useChatStore.getState().handleAppError(
|
|
13501
|
+
`You can have up to ${maxAdmins} admins in this group.`
|
|
13502
|
+
);
|
|
13503
|
+
return;
|
|
13504
|
+
}
|
|
13012
13505
|
setIsManaging(userId);
|
|
13013
13506
|
try {
|
|
13014
13507
|
await manageGroupAdmins({
|
|
@@ -13020,7 +13513,6 @@ function useAdminsDrawer({ conversationId, conversationInfo }) {
|
|
|
13020
13513
|
setIsManaging(null);
|
|
13021
13514
|
}
|
|
13022
13515
|
};
|
|
13023
|
-
const adminCount = admins.length + (ownerId ? 1 : 0);
|
|
13024
13516
|
return {
|
|
13025
13517
|
searchQuery,
|
|
13026
13518
|
setSearchQuery,
|
|
@@ -13032,6 +13524,8 @@ function useAdminsDrawer({ conversationId, conversationInfo }) {
|
|
|
13032
13524
|
promotableParticipants,
|
|
13033
13525
|
handleManageAdmin,
|
|
13034
13526
|
adminCount,
|
|
13527
|
+
maxAdmins,
|
|
13528
|
+
atAdminLimit,
|
|
13035
13529
|
hasRequiredData: Boolean(conversationId && conversationInfo)
|
|
13036
13530
|
};
|
|
13037
13531
|
}
|
|
@@ -13044,6 +13538,8 @@ function AdminParticipantRow({
|
|
|
13044
13538
|
isAdmin,
|
|
13045
13539
|
showPromote,
|
|
13046
13540
|
showDemote,
|
|
13541
|
+
promoteDisabled = false,
|
|
13542
|
+
promoteDisabledReason,
|
|
13047
13543
|
isOwnerViewer,
|
|
13048
13544
|
isManaging,
|
|
13049
13545
|
onManageAdmin
|
|
@@ -13084,14 +13580,24 @@ function AdminParticipantRow({
|
|
|
13084
13580
|
}
|
|
13085
13581
|
),
|
|
13086
13582
|
showPromote && isOwnerViewer && /* @__PURE__ */ jsxRuntime.jsx(
|
|
13087
|
-
|
|
13583
|
+
AdminPermissionTooltip,
|
|
13088
13584
|
{
|
|
13089
|
-
|
|
13090
|
-
|
|
13091
|
-
|
|
13092
|
-
|
|
13093
|
-
|
|
13094
|
-
|
|
13585
|
+
disabled: promoteDisabled,
|
|
13586
|
+
message: promoteDisabledReason,
|
|
13587
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
13588
|
+
Button,
|
|
13589
|
+
{
|
|
13590
|
+
variant: "ghost",
|
|
13591
|
+
size: "sm",
|
|
13592
|
+
className: "size-7 rounded-md p-0 text-(--chat-muted) hover:bg-(--chat-theme-10) hover:text-(--chat-theme) disabled:opacity-40",
|
|
13593
|
+
onClick: () => {
|
|
13594
|
+
if (promoteDisabled) return;
|
|
13595
|
+
onManageAdmin(memberId, "add");
|
|
13596
|
+
},
|
|
13597
|
+
disabled: isManaging === memberId || promoteDisabled,
|
|
13598
|
+
children: isManaging === memberId ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UserPlus, { size: 13 })
|
|
13599
|
+
}
|
|
13600
|
+
)
|
|
13095
13601
|
}
|
|
13096
13602
|
)
|
|
13097
13603
|
] })
|
|
@@ -13115,7 +13621,9 @@ function AdminParticipantList({
|
|
|
13115
13621
|
isAdmin,
|
|
13116
13622
|
onManageAdmin,
|
|
13117
13623
|
showPromote,
|
|
13118
|
-
showDemoteForAdmins
|
|
13624
|
+
showDemoteForAdmins,
|
|
13625
|
+
promoteDisabled = false,
|
|
13626
|
+
promoteDisabledReason
|
|
13119
13627
|
}) {
|
|
13120
13628
|
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: members.map((member, index) => {
|
|
13121
13629
|
const { memberId, memberName, memberEmail, memberImage } = getMemberFields(member);
|
|
@@ -13133,6 +13641,8 @@ function AdminParticipantList({
|
|
|
13133
13641
|
isAdmin: userIsAdmin,
|
|
13134
13642
|
showPromote: showPromote && !userIsAdmin && !userIsOwner,
|
|
13135
13643
|
showDemote: showDemoteForAdmins ? userIsAdmin && !userIsOwner : false,
|
|
13644
|
+
promoteDisabled,
|
|
13645
|
+
promoteDisabledReason,
|
|
13136
13646
|
isOwnerViewer,
|
|
13137
13647
|
isManaging,
|
|
13138
13648
|
onManageAdmin
|
|
@@ -13152,6 +13662,8 @@ var AdminsDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13152
13662
|
promotableParticipants,
|
|
13153
13663
|
handleManageAdmin,
|
|
13154
13664
|
adminCount,
|
|
13665
|
+
maxAdmins,
|
|
13666
|
+
atAdminLimit,
|
|
13155
13667
|
hasRequiredData
|
|
13156
13668
|
} = useAdminsDrawer({ conversationId, conversationInfo });
|
|
13157
13669
|
if (!hasRequiredData) return null;
|
|
@@ -13171,7 +13683,10 @@ var AdminsDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13171
13683
|
/* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: chatSheetTitleClass, children: "Group Administrators" }),
|
|
13172
13684
|
/* @__PURE__ */ jsxRuntime.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 })
|
|
13173
13685
|
] }),
|
|
13174
|
-
/* @__PURE__ */ jsxRuntime.
|
|
13686
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: chatSheetSubtitleClass, children: [
|
|
13687
|
+
"Manage who can adjust group settings and members",
|
|
13688
|
+
maxAdmins ? ` (max ${maxAdmins}).` : "."
|
|
13689
|
+
] })
|
|
13175
13690
|
] }),
|
|
13176
13691
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(chatSheetBodyClass, "px-2.5 py-2"), children: [
|
|
13177
13692
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2.5 px-0.5", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -13214,7 +13729,9 @@ var AdminsDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13214
13729
|
ownerId,
|
|
13215
13730
|
isAdmin,
|
|
13216
13731
|
onManageAdmin: handleManageAdmin,
|
|
13217
|
-
showPromote: true
|
|
13732
|
+
showPromote: true,
|
|
13733
|
+
promoteDisabled: atAdminLimit,
|
|
13734
|
+
promoteDisabledReason: `Maximum ${maxAdmins} admins allowed in this group.`
|
|
13218
13735
|
}
|
|
13219
13736
|
) })
|
|
13220
13737
|
] }),
|
|
@@ -13231,7 +13748,9 @@ var AdminsDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13231
13748
|
isAdmin,
|
|
13232
13749
|
onManageAdmin: handleManageAdmin,
|
|
13233
13750
|
showPromote: true,
|
|
13234
|
-
showDemoteForAdmins: true
|
|
13751
|
+
showDemoteForAdmins: true,
|
|
13752
|
+
promoteDisabled: atAdminLimit,
|
|
13753
|
+
promoteDisabledReason: `Maximum ${maxAdmins} admins allowed in this group.`
|
|
13235
13754
|
}
|
|
13236
13755
|
) })
|
|
13237
13756
|
] }),
|
|
@@ -13247,21 +13766,24 @@ var AdminsDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13247
13766
|
var AdminsDrawer_default = AdminsDrawer;
|
|
13248
13767
|
init_useStore();
|
|
13249
13768
|
var MembersDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo }) => {
|
|
13250
|
-
const [searchQuery, setSearchQuery] =
|
|
13251
|
-
const [isManaging, setIsManaging] =
|
|
13769
|
+
const [searchQuery, setSearchQuery] = React3.useState("");
|
|
13770
|
+
const [isManaging, setIsManaging] = React3.useState(null);
|
|
13252
13771
|
const allUsers = exports.useChatStore((s) => s.allUsers);
|
|
13253
13772
|
const manageGroupMembers = exports.useChatStore((s) => s.manageGroupMembers);
|
|
13254
13773
|
const loggedUserDetails = exports.useChatStore((s) => s.loggedUserDetails);
|
|
13255
|
-
const filteredUsers =
|
|
13774
|
+
const filteredUsers = React3.useMemo(() => {
|
|
13256
13775
|
if (!searchQuery.trim()) return allUsers;
|
|
13257
13776
|
return allUsers.filter(
|
|
13258
13777
|
(u) => u.name?.toLowerCase().includes(searchQuery.toLowerCase()) || u.email?.toLowerCase().includes(searchQuery.toLowerCase())
|
|
13259
13778
|
);
|
|
13260
13779
|
}, [allUsers, searchQuery]);
|
|
13261
13780
|
const { userPermissions } = useGroupInfo(conversationId);
|
|
13781
|
+
const { settings } = useEffectiveSettingsOptional();
|
|
13782
|
+
const maxParticipants = settings.maxParticipantsPerGroup;
|
|
13262
13783
|
if (!conversationId || !conversationInfo) return null;
|
|
13263
13784
|
const participants = conversationInfo.participants || [];
|
|
13264
13785
|
const admins = conversationInfo.groupAdmins || [];
|
|
13786
|
+
const atParticipantLimit = participants.length >= maxParticipants;
|
|
13265
13787
|
let ownerId = null;
|
|
13266
13788
|
if (conversationInfo.owner) {
|
|
13267
13789
|
ownerId = typeof conversationInfo.owner === "object" && conversationInfo.owner !== null ? conversationInfo.owner._id || conversationInfo.owner.id : conversationInfo.owner;
|
|
@@ -13315,14 +13837,24 @@ var MembersDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13315
13837
|
}
|
|
13316
13838
|
),
|
|
13317
13839
|
options.showAdd && /* @__PURE__ */ jsxRuntime.jsx(
|
|
13318
|
-
|
|
13840
|
+
AdminPermissionTooltip,
|
|
13319
13841
|
{
|
|
13320
|
-
|
|
13321
|
-
|
|
13322
|
-
|
|
13323
|
-
|
|
13324
|
-
|
|
13325
|
-
|
|
13842
|
+
disabled: atParticipantLimit,
|
|
13843
|
+
message: `Maximum ${maxParticipants} participants allowed in this group.`,
|
|
13844
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
13845
|
+
Button,
|
|
13846
|
+
{
|
|
13847
|
+
variant: "ghost",
|
|
13848
|
+
size: "sm",
|
|
13849
|
+
className: "size-7 rounded-md p-0 text-(--chat-muted) hover:bg-(--chat-theme-10) hover:text-(--chat-theme) disabled:opacity-40",
|
|
13850
|
+
onClick: () => {
|
|
13851
|
+
if (atParticipantLimit) return;
|
|
13852
|
+
handleManageMember(memberId, "add");
|
|
13853
|
+
},
|
|
13854
|
+
disabled: isManaging === memberId || atParticipantLimit,
|
|
13855
|
+
children: isManaging === memberId ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UserPlus, { size: 13 })
|
|
13856
|
+
}
|
|
13857
|
+
)
|
|
13326
13858
|
}
|
|
13327
13859
|
)
|
|
13328
13860
|
] })
|
|
@@ -13344,7 +13876,11 @@ var MembersDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13344
13876
|
/* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: chatSheetTitleClass, children: "Group Management" }),
|
|
13345
13877
|
/* @__PURE__ */ jsxRuntime.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 })
|
|
13346
13878
|
] }),
|
|
13347
|
-
/* @__PURE__ */ jsxRuntime.
|
|
13879
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: chatSheetSubtitleClass, children: [
|
|
13880
|
+
"Manage members and invite people (max ",
|
|
13881
|
+
maxParticipants,
|
|
13882
|
+
")."
|
|
13883
|
+
] })
|
|
13348
13884
|
] }),
|
|
13349
13885
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(chatSheetBodyClass, "px-2.5 py-2"), children: [
|
|
13350
13886
|
!searchQuery && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "mb-2.5", children: [
|
|
@@ -13465,8 +14001,8 @@ var ChatActionModal_default = ChatActionModal;
|
|
|
13465
14001
|
// src/chat/channel-header/useChannelHeader.ts
|
|
13466
14002
|
init_useStore();
|
|
13467
14003
|
function useDebounce(value, delay) {
|
|
13468
|
-
const [debouncedValue, setDebouncedValue] =
|
|
13469
|
-
|
|
14004
|
+
const [debouncedValue, setDebouncedValue] = React3.useState(value);
|
|
14005
|
+
React3.useEffect(() => {
|
|
13470
14006
|
const timer = setTimeout(() => setDebouncedValue(value), delay);
|
|
13471
14007
|
return () => {
|
|
13472
14008
|
clearTimeout(timer);
|
|
@@ -13486,7 +14022,9 @@ init_store_helpers();
|
|
|
13486
14022
|
function useBlockUser(activeChannel, conversationId, onActiveChannelPatch) {
|
|
13487
14023
|
const loggedUserDetails = exports.useChatStore((s) => s.loggedUserDetails);
|
|
13488
14024
|
const composerDisabledByConversation = exports.useChatStore((s) => s.composerDisabledByConversation);
|
|
13489
|
-
const
|
|
14025
|
+
const { getBlockUsersGate } = useEffectiveSettingsOptional();
|
|
14026
|
+
const blockUsersGate = getBlockUsersGate();
|
|
14027
|
+
const [isBlocking, setIsBlocking] = React3.useState(false);
|
|
13490
14028
|
const resolvedConversationId = conversationId ?? activeChannel?.conversationId ?? null;
|
|
13491
14029
|
const composerDisabledReason = resolvedConversationId ? composerDisabledByConversation[resolvedConversationId] : void 0;
|
|
13492
14030
|
const isBlockedFromConversation = exports.useChatStore((s) => {
|
|
@@ -13504,9 +14042,15 @@ function useBlockUser(activeChannel, conversationId, onActiveChannelPatch) {
|
|
|
13504
14042
|
return !!conv?.isBlocked || !!activeChannel.isBlocked;
|
|
13505
14043
|
});
|
|
13506
14044
|
const isBlocked = isBlockedFromConversation || !activeChannel?.isGroup && !!composerDisabledReason && /block/i.test(composerDisabledReason);
|
|
13507
|
-
const toggleBlock =
|
|
14045
|
+
const toggleBlock = React3.useCallback(async () => {
|
|
13508
14046
|
if (!activeChannel?.id || activeChannel.isGroup) return false;
|
|
13509
14047
|
const nextBlocked = !isBlocked;
|
|
14048
|
+
if (nextBlocked && !blockUsersGate.enabled) {
|
|
14049
|
+
exports.useChatStore.getState().handleAppError(
|
|
14050
|
+
blockUsersGate.disabledReason || "Blocking users is disabled by your administrator."
|
|
14051
|
+
);
|
|
14052
|
+
return false;
|
|
14053
|
+
}
|
|
13510
14054
|
const type = nextBlocked ? "block" : "unblock";
|
|
13511
14055
|
try {
|
|
13512
14056
|
setIsBlocking(true);
|
|
@@ -13527,8 +14071,8 @@ function useBlockUser(activeChannel, conversationId, onActiveChannelPatch) {
|
|
|
13527
14071
|
} finally {
|
|
13528
14072
|
setIsBlocking(false);
|
|
13529
14073
|
}
|
|
13530
|
-
}, [activeChannel, isBlocked, onActiveChannelPatch, resolvedConversationId]);
|
|
13531
|
-
return { isBlocked, isBlocking, toggleBlock };
|
|
14074
|
+
}, [activeChannel, isBlocked, onActiveChannelPatch, resolvedConversationId, blockUsersGate]);
|
|
14075
|
+
return { isBlocked, isBlocking, toggleBlock, blockUsersGate };
|
|
13532
14076
|
}
|
|
13533
14077
|
|
|
13534
14078
|
// src/chat/channel-header/useChannelHeader.ts
|
|
@@ -13561,8 +14105,8 @@ function useChannelHeader({
|
|
|
13561
14105
|
onBack,
|
|
13562
14106
|
onActiveChannelPatch
|
|
13563
14107
|
}) {
|
|
13564
|
-
const [state, setState] =
|
|
13565
|
-
const updateState =
|
|
14108
|
+
const [state, setState] = React3.useState(initialState2);
|
|
14109
|
+
const updateState = React3.useCallback((updates) => {
|
|
13566
14110
|
setState((prev) => ({ ...prev, ...updates }));
|
|
13567
14111
|
}, []);
|
|
13568
14112
|
const { formatLongDate } = useChatLocale();
|
|
@@ -13602,7 +14146,7 @@ function useChannelHeader({
|
|
|
13602
14146
|
const setSearchedMessageId = exports.useChatStore((s) => s.setSearchedMessageId);
|
|
13603
14147
|
const isSearchActive = exports.useChatStore((s) => s.isSearchActive);
|
|
13604
14148
|
const debouncedSearch = useDebounce(state.searchQuery, 800);
|
|
13605
|
-
const handleSearch =
|
|
14149
|
+
const handleSearch = React3.useCallback(async (query, cursor) => {
|
|
13606
14150
|
if (!conversationId) return;
|
|
13607
14151
|
const isFirstPage = !cursor;
|
|
13608
14152
|
updateState({ isSearching: isFirstPage, isLoadingMoreSearch: !isFirstPage });
|
|
@@ -13623,7 +14167,7 @@ function useChannelHeader({
|
|
|
13623
14167
|
updateState({ isSearching: false, isLoadingMoreSearch: false });
|
|
13624
14168
|
}
|
|
13625
14169
|
}, [conversationId, updateState]);
|
|
13626
|
-
|
|
14170
|
+
React3.useEffect(() => {
|
|
13627
14171
|
if (debouncedSearch && conversationId) {
|
|
13628
14172
|
updateState({ searchCursor: null, searchHasMore: false });
|
|
13629
14173
|
handleSearch(debouncedSearch);
|
|
@@ -13657,32 +14201,32 @@ function useChannelHeader({
|
|
|
13657
14201
|
handleCloseSearch();
|
|
13658
14202
|
};
|
|
13659
14203
|
const canViewMembers = isAdmin || userPermissions.canAddMember || userPermissions.canRemoveMember;
|
|
13660
|
-
const prevIsClearingRef =
|
|
13661
|
-
|
|
14204
|
+
const prevIsClearingRef = React3.useRef(isClearingChat);
|
|
14205
|
+
React3.useEffect(() => {
|
|
13662
14206
|
if (prevIsClearingRef.current === true && !isClearingChat) {
|
|
13663
14207
|
updateState({ isClearChatAlertOpen: false });
|
|
13664
14208
|
}
|
|
13665
14209
|
prevIsClearingRef.current = isClearingChat;
|
|
13666
14210
|
}, [isClearingChat, updateState]);
|
|
13667
|
-
const prevIsDeletingRef =
|
|
13668
|
-
|
|
14211
|
+
const prevIsDeletingRef = React3.useRef(isDeletingConversation);
|
|
14212
|
+
React3.useEffect(() => {
|
|
13669
14213
|
if (prevIsDeletingRef.current === true && !isDeletingConversation) {
|
|
13670
14214
|
updateState({ isDeletingConversationAlertOpen: false });
|
|
13671
14215
|
onBack?.();
|
|
13672
14216
|
}
|
|
13673
14217
|
prevIsDeletingRef.current = isDeletingConversation;
|
|
13674
14218
|
}, [isDeletingConversation, onBack, updateState]);
|
|
13675
|
-
|
|
14219
|
+
React3.useEffect(() => {
|
|
13676
14220
|
if (state.isPinOpen && conversationId) {
|
|
13677
14221
|
fetchPinnedMessages2(conversationId);
|
|
13678
14222
|
}
|
|
13679
14223
|
}, [state.isPinOpen, conversationId, fetchPinnedMessages2]);
|
|
13680
|
-
|
|
14224
|
+
React3.useEffect(() => {
|
|
13681
14225
|
if (state.isFavoriteOpen && conversationId) {
|
|
13682
14226
|
fetchStarredMessages2(conversationId);
|
|
13683
14227
|
}
|
|
13684
14228
|
}, [state.isFavoriteOpen, conversationId, fetchStarredMessages2]);
|
|
13685
|
-
|
|
14229
|
+
React3.useEffect(() => {
|
|
13686
14230
|
if (state.isAttachmentsOpen && conversationId) {
|
|
13687
14231
|
const meta = exports.useChatStore.getState().messagesMetadata[conversationId];
|
|
13688
14232
|
if (!meta?.isFirstPage) {
|
|
@@ -14064,6 +14608,7 @@ var MessageReactions_default = MessageReactions;
|
|
|
14064
14608
|
var MessageToolbar = ({
|
|
14065
14609
|
isSender,
|
|
14066
14610
|
isRecent,
|
|
14611
|
+
isWithinDeleteWindow = isRecent,
|
|
14067
14612
|
isPinned,
|
|
14068
14613
|
isStarred,
|
|
14069
14614
|
isPinPending,
|
|
@@ -14087,7 +14632,7 @@ var MessageToolbar = ({
|
|
|
14087
14632
|
}) => {
|
|
14088
14633
|
const { isDark, scopeClassName, themeStyles } = useChatTheme();
|
|
14089
14634
|
const showDeleteMenu = isSender || hasAttachments || attachmentDeleteMode;
|
|
14090
|
-
const showDeleteForEveryone = isSender &&
|
|
14635
|
+
const showDeleteForEveryone = isSender && isWithinDeleteWindow;
|
|
14091
14636
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14092
14637
|
"div",
|
|
14093
14638
|
{
|
|
@@ -14242,8 +14787,8 @@ function SentAttachmentCaptionModal({
|
|
|
14242
14787
|
canEdit = false,
|
|
14243
14788
|
onSave
|
|
14244
14789
|
}) {
|
|
14245
|
-
const [draft, setDraft] =
|
|
14246
|
-
|
|
14790
|
+
const [draft, setDraft] = React3.useState("");
|
|
14791
|
+
React3.useEffect(() => {
|
|
14247
14792
|
if (open && attachment) {
|
|
14248
14793
|
setDraft(attachment.caption || "");
|
|
14249
14794
|
}
|
|
@@ -14409,16 +14954,59 @@ function resolveForwardItems(selectedKeys, messages) {
|
|
|
14409
14954
|
}
|
|
14410
14955
|
|
|
14411
14956
|
// src/chat/lib/chat-edit-window.ts
|
|
14412
|
-
|
|
14413
|
-
|
|
14414
|
-
|
|
14957
|
+
init_settings_types();
|
|
14958
|
+
|
|
14959
|
+
// src/lib/effective-settings.helpers.ts
|
|
14960
|
+
function minutesToMs(minutes) {
|
|
14961
|
+
return Math.max(0, minutes) * 60 * 1e3;
|
|
14962
|
+
}
|
|
14963
|
+
function getEditWindowMs(timers, isGroup) {
|
|
14964
|
+
return minutesToMs(isGroup ? timers.groupEditMinutes : timers.dmEditMinutes);
|
|
14415
14965
|
}
|
|
14416
|
-
function
|
|
14966
|
+
function getDeleteWindowMs(timers, isGroup) {
|
|
14967
|
+
return minutesToMs(
|
|
14968
|
+
isGroup ? timers.groupDeleteMinutes : timers.dmDeleteMinutes
|
|
14969
|
+
);
|
|
14970
|
+
}
|
|
14971
|
+
function isWithinWindow(createdAt, windowMs) {
|
|
14417
14972
|
if (!createdAt) return false;
|
|
14418
14973
|
const date = new Date(createdAt);
|
|
14419
14974
|
if (isNaN(date.getTime())) return false;
|
|
14420
14975
|
const diff = Date.now() - date.getTime();
|
|
14421
|
-
return diff >= 0 && diff <
|
|
14976
|
+
return diff >= 0 && diff < windowMs;
|
|
14977
|
+
}
|
|
14978
|
+
function isWithinMessageEditWindow(createdAt, timers, isGroup) {
|
|
14979
|
+
return isWithinWindow(createdAt, getEditWindowMs(timers, isGroup));
|
|
14980
|
+
}
|
|
14981
|
+
function isWithinMessageDeleteWindow(createdAt, timers, isGroup) {
|
|
14982
|
+
return isWithinWindow(createdAt, getDeleteWindowMs(timers, isGroup));
|
|
14983
|
+
}
|
|
14984
|
+
function matchesAllowedMimeType(fileType, allowedMimeTypes) {
|
|
14985
|
+
const mime = (fileType || "application/octet-stream").toLowerCase();
|
|
14986
|
+
return allowedMimeTypes.some((pattern) => {
|
|
14987
|
+
const normalized = pattern.trim().toLowerCase();
|
|
14988
|
+
if (!normalized) return false;
|
|
14989
|
+
if (normalized.endsWith("/*")) {
|
|
14990
|
+
const prefix = normalized.slice(0, -1);
|
|
14991
|
+
return mime.startsWith(prefix);
|
|
14992
|
+
}
|
|
14993
|
+
return mime === normalized;
|
|
14994
|
+
});
|
|
14995
|
+
}
|
|
14996
|
+
function buildAcceptFromMimeTypes(allowedMimeTypes) {
|
|
14997
|
+
return allowedMimeTypes.map((type) => type.trim()).filter(Boolean).join(",");
|
|
14998
|
+
}
|
|
14999
|
+
function formatFileSizeMB(sizeBytes) {
|
|
15000
|
+
return `${(sizeBytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
15001
|
+
}
|
|
15002
|
+
|
|
15003
|
+
// src/chat/lib/chat-edit-window.ts
|
|
15004
|
+
var FALLBACK_TIMERS = exports.DEFAULT_EFFECTIVE_SETTINGS.messageTimers;
|
|
15005
|
+
function isWithinMessageEditWindow2(createdAt, isGroup, timers = FALLBACK_TIMERS) {
|
|
15006
|
+
return isWithinMessageEditWindow(createdAt, timers, isGroup);
|
|
15007
|
+
}
|
|
15008
|
+
function isWithinMessageDeleteWindow2(createdAt, isGroup, timers = FALLBACK_TIMERS) {
|
|
15009
|
+
return isWithinMessageDeleteWindow(createdAt, timers, isGroup);
|
|
14422
15010
|
}
|
|
14423
15011
|
|
|
14424
15012
|
// src/chat/message-item/useMessageItemActions.ts
|
|
@@ -14443,7 +15031,7 @@ function useMessageItemActions({
|
|
|
14443
15031
|
selectionMode = false,
|
|
14444
15032
|
selectedKeys
|
|
14445
15033
|
}) {
|
|
14446
|
-
const [state, setState] =
|
|
15034
|
+
const [state, setState] = React3.useState({
|
|
14447
15035
|
isHoverMessage: false,
|
|
14448
15036
|
isEditing: false,
|
|
14449
15037
|
editValue: String(message || ""),
|
|
@@ -14456,7 +15044,7 @@ function useMessageItemActions({
|
|
|
14456
15044
|
const updateState = (updates) => {
|
|
14457
15045
|
setState((prev) => ({ ...prev, ...updates }));
|
|
14458
15046
|
};
|
|
14459
|
-
|
|
15047
|
+
React3.useEffect(() => {
|
|
14460
15048
|
setState((prev) => ({ ...prev, editValue: String(message || "") }));
|
|
14461
15049
|
}, [message]);
|
|
14462
15050
|
const emitDmEdit = exports.useChatStore((s) => s.emitDmEdit);
|
|
@@ -14496,6 +15084,9 @@ function useMessageItemActions({
|
|
|
14496
15084
|
const canUnpin = !isPinned || isPinnedByMe;
|
|
14497
15085
|
const { userPermissions } = useGroupInfo(conversationId || null);
|
|
14498
15086
|
const { formatMessageTime } = useChatLocale();
|
|
15087
|
+
const { settings } = useEffectiveSettingsOptional();
|
|
15088
|
+
const messageTimers = settings.messageTimers;
|
|
15089
|
+
const maxPinnedMessages = settings.maxPinnedMessagesPerConversation;
|
|
14499
15090
|
const visibleAttachments = getVisibleAttachments(attachments);
|
|
14500
15091
|
const hasAttachments = visibleAttachments.length > 0;
|
|
14501
15092
|
const hasMultiAttachments = hasAttachments && messageUsesAttachmentSelection({ attachments: visibleAttachments });
|
|
@@ -14512,7 +15103,8 @@ function useMessageItemActions({
|
|
|
14512
15103
|
const hasText = Boolean(message?.trim());
|
|
14513
15104
|
const isSelected = !!mid && !!selectedKeys && isMessageWhollySelected(selectedKeys, mid) && !hasMultiAttachments;
|
|
14514
15105
|
const canEdit = (!isGroup || userPermissions.canEditMessage) && hasText;
|
|
14515
|
-
const isWithinEditWindow = () =>
|
|
15106
|
+
const isWithinEditWindow = () => isWithinMessageEditWindow2(createdAt, isGroup, messageTimers);
|
|
15107
|
+
const isWithinDeleteWindow = () => isWithinMessageDeleteWindow2(createdAt, isGroup, messageTimers);
|
|
14516
15108
|
const canEditAttachmentCaption = isSender && isWithinEditWindow() && (!isGroup || userPermissions.canEditMessage) && !isDeletedForEveryone && !!mid;
|
|
14517
15109
|
const handleAttachmentCaptionClick = (attachment) => {
|
|
14518
15110
|
if (!canEditAttachmentCaption) return;
|
|
@@ -14681,6 +15273,15 @@ function useMessageItemActions({
|
|
|
14681
15273
|
});
|
|
14682
15274
|
}
|
|
14683
15275
|
} else {
|
|
15276
|
+
if (conversationId) {
|
|
15277
|
+
const pinnedCount = (pinnedMessagesByConversation[conversationId] || []).length || exports.useChatStore.getState().liveConversationCounts[conversationId]?.pinnedCount || 0;
|
|
15278
|
+
if (pinnedCount >= maxPinnedMessages) {
|
|
15279
|
+
exports.useChatStore.getState().handleAppError(
|
|
15280
|
+
`You can pin up to ${maxPinnedMessages} messages in this conversation.`
|
|
15281
|
+
);
|
|
15282
|
+
return;
|
|
15283
|
+
}
|
|
15284
|
+
}
|
|
14684
15285
|
if (isGroup) {
|
|
14685
15286
|
if (!conversationId) return;
|
|
14686
15287
|
emitGroupPin({
|
|
@@ -14739,6 +15340,7 @@ function useMessageItemActions({
|
|
|
14739
15340
|
canUnpin,
|
|
14740
15341
|
canEdit,
|
|
14741
15342
|
isWithinEditWindow,
|
|
15343
|
+
isWithinDeleteWindow,
|
|
14742
15344
|
canEditAttachmentCaption,
|
|
14743
15345
|
visibleAttachments,
|
|
14744
15346
|
hasAttachments,
|
|
@@ -14770,7 +15372,7 @@ function useMessageItemActions({
|
|
|
14770
15372
|
}
|
|
14771
15373
|
|
|
14772
15374
|
// src/chat/lib/reply-preview.ts
|
|
14773
|
-
function
|
|
15375
|
+
function normalizeAttachments2(replyTo, loggedUserId) {
|
|
14774
15376
|
const raw = replyTo?.attachments;
|
|
14775
15377
|
if (!Array.isArray(raw) || raw.length === 0) return [];
|
|
14776
15378
|
return raw.map((att, index) => {
|
|
@@ -14783,7 +15385,7 @@ function resolveReplyToMessage(replyTo, messagesById, loggedUserId) {
|
|
|
14783
15385
|
if (typeof replyTo === "object" && (replyTo.content?.trim() || replyTo.attachments?.length)) {
|
|
14784
15386
|
return {
|
|
14785
15387
|
...replyTo,
|
|
14786
|
-
attachments:
|
|
15388
|
+
attachments: normalizeAttachments2(replyTo, loggedUserId)
|
|
14787
15389
|
};
|
|
14788
15390
|
}
|
|
14789
15391
|
const replyId = String(
|
|
@@ -15220,6 +15822,7 @@ function MessageItemView(props) {
|
|
|
15220
15822
|
canUnpin,
|
|
15221
15823
|
canEdit,
|
|
15222
15824
|
isWithinEditWindow,
|
|
15825
|
+
isWithinDeleteWindow,
|
|
15223
15826
|
canEditAttachmentCaption,
|
|
15224
15827
|
visibleAttachments,
|
|
15225
15828
|
hasAttachments,
|
|
@@ -15311,6 +15914,7 @@ function MessageItemView(props) {
|
|
|
15311
15914
|
{
|
|
15312
15915
|
isSender,
|
|
15313
15916
|
isRecent: isWithinEditWindow(),
|
|
15917
|
+
isWithinDeleteWindow: isWithinDeleteWindow(),
|
|
15314
15918
|
messageId: mid,
|
|
15315
15919
|
isPinned,
|
|
15316
15920
|
isStarred,
|
|
@@ -15500,7 +16104,7 @@ function MessageSelectionBar({
|
|
|
15500
16104
|
className
|
|
15501
16105
|
}) {
|
|
15502
16106
|
const { scopeClassName, themeStyles } = useChatTheme();
|
|
15503
|
-
const [isDeleteOpen, setIsDeleteOpen] =
|
|
16107
|
+
const [isDeleteOpen, setIsDeleteOpen] = React3.useState(false);
|
|
15504
16108
|
if (count === 0) return null;
|
|
15505
16109
|
const countLabel = selectionLabel === "files" ? count === 1 ? "file" : "files" : count === 1 ? "message" : "messages";
|
|
15506
16110
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -15605,6 +16209,7 @@ function MessageSelectionBar({
|
|
|
15605
16209
|
}
|
|
15606
16210
|
|
|
15607
16211
|
// src/chat/active-channel-messages/utils.ts
|
|
16212
|
+
init_settings_types();
|
|
15608
16213
|
var getMessageSenderId2 = (msg) => msg ? String(msg.senderId || msg.sender?._id || "") : "";
|
|
15609
16214
|
var isLikelyObjectId = (value) => /^[a-f\d]{24}$/i.test(value);
|
|
15610
16215
|
function resolveGroupSenderDisplay(message, allUsers = [], participants = []) {
|
|
@@ -15636,7 +16241,7 @@ var isSameMessageSide = (a, b, isGroupChat) => {
|
|
|
15636
16241
|
const bId = getMessageSenderId2(b);
|
|
15637
16242
|
return aId !== "" && aId === bId;
|
|
15638
16243
|
};
|
|
15639
|
-
function canDeleteSelectionForEveryone(selectedKeys, messages, isGroup) {
|
|
16244
|
+
function canDeleteSelectionForEveryone(selectedKeys, messages, isGroup, timers = exports.DEFAULT_EFFECTIVE_SETTINGS.messageTimers) {
|
|
15640
16245
|
if (selectedKeys.size === 0) return false;
|
|
15641
16246
|
const parsed = [...selectedKeys].map((key) => parseSelectionKey(key));
|
|
15642
16247
|
const messageIds = new Set(parsed.map((entry) => entry.messageId));
|
|
@@ -15644,7 +16249,7 @@ function canDeleteSelectionForEveryone(selectedKeys, messages, isGroup) {
|
|
|
15644
16249
|
const messageId2 = [...messageIds][0];
|
|
15645
16250
|
const message = messages.find((entry) => String(entry._id || entry.id) === messageId2);
|
|
15646
16251
|
if (!message?.isOwnMessage) return false;
|
|
15647
|
-
if (!
|
|
16252
|
+
if (!isWithinMessageDeleteWindow2(message.timestamp, isGroup, timers)) return false;
|
|
15648
16253
|
const hasAttachmentKey = parsed.some((entry) => entry.attachmentId);
|
|
15649
16254
|
if (!hasAttachmentKey) {
|
|
15650
16255
|
return selectedKeys.size === 1;
|
|
@@ -15808,22 +16413,24 @@ function useActiveChannelMessages({
|
|
|
15808
16413
|
onSelectionModeChange,
|
|
15809
16414
|
conversationInfo
|
|
15810
16415
|
}) {
|
|
15811
|
-
const [selectionMode, setSelectionMode] =
|
|
15812
|
-
const [selectedKeys, setSelectedKeys] =
|
|
16416
|
+
const [selectionMode, setSelectionMode] = React3.useState(false);
|
|
16417
|
+
const [selectedKeys, setSelectedKeys] = React3.useState(/* @__PURE__ */ new Set());
|
|
15813
16418
|
const emitDmDelete = exports.useChatStore((s) => s.emitDmDelete);
|
|
15814
16419
|
const emitGroupDelete = exports.useChatStore((s) => s.emitGroupDelete);
|
|
15815
16420
|
const loggedUserDetails = exports.useChatStore((s) => s.loggedUserDetails);
|
|
15816
|
-
const
|
|
15817
|
-
const
|
|
15818
|
-
const
|
|
15819
|
-
const
|
|
15820
|
-
const
|
|
15821
|
-
const
|
|
15822
|
-
const
|
|
15823
|
-
const
|
|
15824
|
-
const
|
|
15825
|
-
const
|
|
15826
|
-
const
|
|
16421
|
+
const { settings } = useEffectiveSettingsOptional();
|
|
16422
|
+
const messageTimers = settings.messageTimers;
|
|
16423
|
+
const scrollContainerRef = React3.useRef(null);
|
|
16424
|
+
const bottomRef = React3.useRef(null);
|
|
16425
|
+
const messageListInitializedRef = React3.useRef(false);
|
|
16426
|
+
const previousMessageCountRef = React3.useRef(0);
|
|
16427
|
+
const previousLastMessageIdRef = React3.useRef(null);
|
|
16428
|
+
const [enteringMessageIds, setEnteringMessageIds] = React3.useState(/* @__PURE__ */ new Set());
|
|
16429
|
+
const [showScrollToBottom, setShowScrollToBottom] = React3.useState(false);
|
|
16430
|
+
const stickToBottomRef = React3.useRef(true);
|
|
16431
|
+
const pendingJumpRef = React3.useRef(null);
|
|
16432
|
+
const jumpPagesRef = React3.useRef(0);
|
|
16433
|
+
const [jumpNonce, setJumpNonce] = React3.useState(0);
|
|
15827
16434
|
const { fetchMessages: fetchMessages2, messagesMetadata, deletedForMeIds, searchedMessageId, isSearchActive, setSearchActive, setSearchedMessageId, fetchSearchMessageContext } = exports.useChatStore();
|
|
15828
16435
|
const loggedUserImage = exports.useChatStore((s) => s.loggedUserDetails?.image);
|
|
15829
16436
|
const conversations = exports.useChatStore((s) => s.conversations);
|
|
@@ -15832,29 +16439,29 @@ function useActiveChannelMessages({
|
|
|
15832
16439
|
const mappedApiMessages = conversationMessages.map(
|
|
15833
16440
|
(m) => mapApiMessage(m, activeChannel, conversationId, loggedUserId, activeConversation)
|
|
15834
16441
|
);
|
|
15835
|
-
const displayMessages =
|
|
16442
|
+
const displayMessages = React3.useMemo(
|
|
15836
16443
|
() => mergeChatMessages(mappedApiMessages, localMessages, loggedUserId).filter((m) => !deletedForMeIds.includes(String(m._id || m.id)) && !m.isDeletedForMe).filter((m) => !conversationId || String(m.conversationId || "") === String(conversationId)).sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()),
|
|
15837
16444
|
[mappedApiMessages, localMessages, loggedUserId, deletedForMeIds, conversationId]
|
|
15838
16445
|
);
|
|
15839
|
-
const messagesById =
|
|
16446
|
+
const messagesById = React3.useMemo(
|
|
15840
16447
|
() => new Map(displayMessages.map((message) => [String(message._id || message.id), message])),
|
|
15841
16448
|
[displayMessages]
|
|
15842
16449
|
);
|
|
15843
|
-
const messagesWithResolvedReplies =
|
|
16450
|
+
const messagesWithResolvedReplies = React3.useMemo(
|
|
15844
16451
|
() => displayMessages.map((message) => ({
|
|
15845
16452
|
...message,
|
|
15846
16453
|
replyTo: resolveReplyToMessage(message.replyTo, messagesById, loggedUserId)
|
|
15847
16454
|
})),
|
|
15848
16455
|
[displayMessages, messagesById, loggedUserId]
|
|
15849
16456
|
);
|
|
15850
|
-
const jumpDateBounds =
|
|
16457
|
+
const jumpDateBounds = React3.useMemo(
|
|
15851
16458
|
() => resolveJumpDateBounds(
|
|
15852
16459
|
conversationInfo?.createdAt,
|
|
15853
16460
|
displayMessages[0]?.timestamp
|
|
15854
16461
|
),
|
|
15855
16462
|
[conversationInfo?.createdAt, displayMessages]
|
|
15856
16463
|
);
|
|
15857
|
-
|
|
16464
|
+
React3.useEffect(() => {
|
|
15858
16465
|
const messages = messagesWithResolvedReplies;
|
|
15859
16466
|
const lastMessage = messages[messages.length - 1];
|
|
15860
16467
|
const lastMessageId = lastMessage ? String(lastMessage._id || lastMessage.id) : null;
|
|
@@ -15881,11 +16488,11 @@ function useActiveChannelMessages({
|
|
|
15881
16488
|
}, [messagesWithResolvedReplies]);
|
|
15882
16489
|
const isInitialLoading = isLoading && currentMeta?.isFirstPage;
|
|
15883
16490
|
const isLoadingMore = isLoading && !currentMeta?.isFirstPage;
|
|
15884
|
-
const clearSelection =
|
|
16491
|
+
const clearSelection = React3.useCallback(() => {
|
|
15885
16492
|
setSelectionMode(false);
|
|
15886
16493
|
setSelectedKeys(/* @__PURE__ */ new Set());
|
|
15887
16494
|
}, []);
|
|
15888
|
-
|
|
16495
|
+
React3.useEffect(() => {
|
|
15889
16496
|
clearSelection();
|
|
15890
16497
|
messageListInitializedRef.current = false;
|
|
15891
16498
|
previousMessageCountRef.current = 0;
|
|
@@ -15896,14 +16503,14 @@ function useActiveChannelMessages({
|
|
|
15896
16503
|
stickToBottomRef.current = true;
|
|
15897
16504
|
setShowScrollToBottom(false);
|
|
15898
16505
|
}, [conversationId, clearSelection]);
|
|
15899
|
-
const onSelectionModeChangeRef =
|
|
15900
|
-
|
|
16506
|
+
const onSelectionModeChangeRef = React3.useRef(onSelectionModeChange);
|
|
16507
|
+
React3.useEffect(() => {
|
|
15901
16508
|
onSelectionModeChangeRef.current = onSelectionModeChange;
|
|
15902
16509
|
}, [onSelectionModeChange]);
|
|
15903
|
-
|
|
16510
|
+
React3.useEffect(() => {
|
|
15904
16511
|
onSelectionModeChangeRef.current?.(selectionMode);
|
|
15905
16512
|
}, [selectionMode]);
|
|
15906
|
-
const toggleSelection =
|
|
16513
|
+
const toggleSelection = React3.useCallback((message, attachmentId) => {
|
|
15907
16514
|
const messageId2 = String(message._id || message.id);
|
|
15908
16515
|
if (!messageId2) return;
|
|
15909
16516
|
const useAttachmentSelection = messageUsesAttachmentSelection(message);
|
|
@@ -15916,7 +16523,7 @@ function useActiveChannelMessages({
|
|
|
15916
16523
|
return next;
|
|
15917
16524
|
});
|
|
15918
16525
|
}, []);
|
|
15919
|
-
const enterSelectionMode =
|
|
16526
|
+
const enterSelectionMode = React3.useCallback((message, attachmentId) => {
|
|
15920
16527
|
const messageId2 = String(message._id || message.id);
|
|
15921
16528
|
if (!messageId2) return;
|
|
15922
16529
|
setSelectionMode(true);
|
|
@@ -15930,17 +16537,23 @@ function useActiveChannelMessages({
|
|
|
15930
16537
|
setSelectedKeys((prev) => new Set(prev).add(messageId2));
|
|
15931
16538
|
}, []);
|
|
15932
16539
|
const selectedForwardItems = resolveForwardItems(selectedKeys, displayMessages);
|
|
15933
|
-
const canDeleteForEveryone =
|
|
15934
|
-
() => canDeleteSelectionForEveryone(
|
|
15935
|
-
|
|
16540
|
+
const canDeleteForEveryone = React3.useMemo(
|
|
16541
|
+
() => canDeleteSelectionForEveryone(
|
|
16542
|
+
selectedKeys,
|
|
16543
|
+
displayMessages,
|
|
16544
|
+
!!activeChannel?.isGroup,
|
|
16545
|
+
messageTimers
|
|
16546
|
+
),
|
|
16547
|
+
[selectedKeys, displayMessages, activeChannel?.isGroup, messageTimers]
|
|
15936
16548
|
);
|
|
15937
|
-
const emitSelectionDelete =
|
|
16549
|
+
const emitSelectionDelete = React3.useCallback(
|
|
15938
16550
|
(deleteType) => {
|
|
15939
16551
|
if (!loggedUserDetails || selectedKeys.size === 0) return;
|
|
15940
16552
|
if (deleteType === "everyone" && !canDeleteSelectionForEveryone(
|
|
15941
16553
|
selectedKeys,
|
|
15942
16554
|
displayMessages,
|
|
15943
|
-
!!activeChannel?.isGroup
|
|
16555
|
+
!!activeChannel?.isGroup,
|
|
16556
|
+
messageTimers
|
|
15944
16557
|
)) {
|
|
15945
16558
|
return;
|
|
15946
16559
|
}
|
|
@@ -15981,13 +16594,14 @@ function useActiveChannelMessages({
|
|
|
15981
16594
|
conversationId,
|
|
15982
16595
|
emitGroupDelete,
|
|
15983
16596
|
emitDmDelete,
|
|
15984
|
-
clearSelection
|
|
16597
|
+
clearSelection,
|
|
16598
|
+
messageTimers
|
|
15985
16599
|
]
|
|
15986
16600
|
);
|
|
15987
|
-
const handleBatchDeleteForMe =
|
|
16601
|
+
const handleBatchDeleteForMe = React3.useCallback(() => {
|
|
15988
16602
|
emitSelectionDelete("me");
|
|
15989
16603
|
}, [emitSelectionDelete]);
|
|
15990
|
-
const handleBatchDeleteForEveryone =
|
|
16604
|
+
const handleBatchDeleteForEveryone = React3.useCallback(() => {
|
|
15991
16605
|
emitSelectionDelete("everyone");
|
|
15992
16606
|
}, [emitSelectionDelete]);
|
|
15993
16607
|
const handleBatchForward = () => {
|
|
@@ -16011,7 +16625,7 @@ function useActiveChannelMessages({
|
|
|
16011
16625
|
}
|
|
16012
16626
|
await fetchSearchMessageContext(messageId2, { searchMode: false });
|
|
16013
16627
|
};
|
|
16014
|
-
const handleJumpTo =
|
|
16628
|
+
const handleJumpTo = React3.useCallback((preset, specificDate) => {
|
|
16015
16629
|
stickToBottomRef.current = false;
|
|
16016
16630
|
if (preset === "beginning") {
|
|
16017
16631
|
pendingJumpRef.current = { kind: "beginning" };
|
|
@@ -16032,7 +16646,7 @@ function useActiveChannelMessages({
|
|
|
16032
16646
|
jumpPagesRef.current = 0;
|
|
16033
16647
|
setJumpNonce((n) => n + 1);
|
|
16034
16648
|
}, [jumpDateBounds.minDay, jumpDateBounds.maxDay]);
|
|
16035
|
-
|
|
16649
|
+
React3.useEffect(() => {
|
|
16036
16650
|
const pending = pendingJumpRef.current;
|
|
16037
16651
|
if (!pending || isLoading) return;
|
|
16038
16652
|
const step = resolveJumpStep(
|
|
@@ -16071,13 +16685,13 @@ function useActiveChannelMessages({
|
|
|
16071
16685
|
fetchMessages2,
|
|
16072
16686
|
setSearchedMessageId
|
|
16073
16687
|
]);
|
|
16074
|
-
const updateScrollToBottomVisibility =
|
|
16688
|
+
const updateScrollToBottomVisibility = React3.useCallback((el) => {
|
|
16075
16689
|
const distanceFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight;
|
|
16076
16690
|
const nearBottom = distanceFromBottom <= 96;
|
|
16077
16691
|
stickToBottomRef.current = nearBottom;
|
|
16078
16692
|
setShowScrollToBottom(!nearBottom);
|
|
16079
16693
|
}, []);
|
|
16080
|
-
const handleScrollToBottom =
|
|
16694
|
+
const handleScrollToBottom = React3.useCallback(() => {
|
|
16081
16695
|
stickToBottomRef.current = true;
|
|
16082
16696
|
if (isSearchActive) {
|
|
16083
16697
|
setSearchActive(false);
|
|
@@ -16104,12 +16718,12 @@ function useActiveChannelMessages({
|
|
|
16104
16718
|
});
|
|
16105
16719
|
}
|
|
16106
16720
|
};
|
|
16107
|
-
|
|
16721
|
+
React3.useLayoutEffect(() => {
|
|
16108
16722
|
if (!isInitialLoading && stickToBottomRef.current && !pendingJumpRef.current) {
|
|
16109
16723
|
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
16110
16724
|
}
|
|
16111
16725
|
}, [messagesWithResolvedReplies.length, isInitialLoading]);
|
|
16112
|
-
|
|
16726
|
+
React3.useEffect(() => {
|
|
16113
16727
|
if (searchedMessageId && !isLoading) {
|
|
16114
16728
|
stickToBottomRef.current = false;
|
|
16115
16729
|
const container = scrollContainerRef.current;
|
|
@@ -16319,8 +16933,8 @@ function CalendarDayButton({
|
|
|
16319
16933
|
...props
|
|
16320
16934
|
}) {
|
|
16321
16935
|
const defaultClassNames = reactDayPicker.getDefaultClassNames();
|
|
16322
|
-
const ref =
|
|
16323
|
-
|
|
16936
|
+
const ref = React3__namespace.useRef(null);
|
|
16937
|
+
React3__namespace.useEffect(() => {
|
|
16324
16938
|
if (modifiers.focused) ref.current?.focus();
|
|
16325
16939
|
}, [modifiers.focused]);
|
|
16326
16940
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -16352,12 +16966,12 @@ var PRESETS = [
|
|
|
16352
16966
|
];
|
|
16353
16967
|
function ChatDateJumpMenu({ label, minDay, maxDay, onJump }) {
|
|
16354
16968
|
const { scopeClassName } = useChatTheme();
|
|
16355
|
-
const [open, setOpen] =
|
|
16356
|
-
const [showCalendar, setShowCalendar] =
|
|
16357
|
-
const [calendarMonth, setCalendarMonth] =
|
|
16969
|
+
const [open, setOpen] = React3.useState(false);
|
|
16970
|
+
const [showCalendar, setShowCalendar] = React3.useState(false);
|
|
16971
|
+
const [calendarMonth, setCalendarMonth] = React3.useState(() => new Date(maxDay));
|
|
16358
16972
|
const minDate = new Date(minDay);
|
|
16359
16973
|
const maxDate = new Date(maxDay);
|
|
16360
|
-
|
|
16974
|
+
React3.useEffect(() => {
|
|
16361
16975
|
if (showCalendar) setCalendarMonth(new Date(maxDay));
|
|
16362
16976
|
}, [showCalendar, maxDay]);
|
|
16363
16977
|
const queueJump = (preset, specificDate) => {
|
|
@@ -16691,8 +17305,8 @@ function AttachmentCaptionModal({
|
|
|
16691
17305
|
attachment,
|
|
16692
17306
|
onSave
|
|
16693
17307
|
}) {
|
|
16694
|
-
const [draft, setDraft] =
|
|
16695
|
-
|
|
17308
|
+
const [draft, setDraft] = React3.useState("");
|
|
17309
|
+
React3.useEffect(() => {
|
|
16696
17310
|
if (open && attachment) {
|
|
16697
17311
|
setDraft(attachment.caption || "");
|
|
16698
17312
|
}
|
|
@@ -17069,9 +17683,9 @@ function ComposerAttachmentPreview({
|
|
|
17069
17683
|
embedded = false,
|
|
17070
17684
|
maxAttachments = COMPOSER_MAX_ATTACHMENTS
|
|
17071
17685
|
}) {
|
|
17072
|
-
const [captionTargetId, setCaptionTargetId] =
|
|
17073
|
-
const [lightboxState, setLightboxState] =
|
|
17074
|
-
const { media, files, imageMedia, lightboxImages } =
|
|
17686
|
+
const [captionTargetId, setCaptionTargetId] = React3.useState(null);
|
|
17687
|
+
const [lightboxState, setLightboxState] = React3.useState(null);
|
|
17688
|
+
const { media, files, imageMedia, lightboxImages } = React3.useMemo(() => {
|
|
17075
17689
|
const mediaItems = attachments.filter(
|
|
17076
17690
|
(item) => (item.type === "image" || item.type === "video") && item.previewUrl
|
|
17077
17691
|
);
|
|
@@ -17224,7 +17838,6 @@ var getAttachmentType = (file) => {
|
|
|
17224
17838
|
};
|
|
17225
17839
|
|
|
17226
17840
|
// src/chat/channel-message-box/useChannelMessageBox.ts
|
|
17227
|
-
var MAX_ATTACHMENTS = COMPOSER_MAX_ATTACHMENTS;
|
|
17228
17841
|
function useChannelMessageBox({
|
|
17229
17842
|
activeChannel,
|
|
17230
17843
|
conversationId,
|
|
@@ -17238,7 +17851,13 @@ function useChannelMessageBox({
|
|
|
17238
17851
|
conversationId,
|
|
17239
17852
|
onActiveChannelPatch
|
|
17240
17853
|
);
|
|
17241
|
-
const
|
|
17854
|
+
const { settings, getAttachmentsGate } = useEffectiveSettingsOptional();
|
|
17855
|
+
const attachmentsGate = getAttachmentsGate();
|
|
17856
|
+
const maxAttachments = settings.attachments.maxAttachmentsPerMessage;
|
|
17857
|
+
const maxFileSizeBytes = settings.attachments.maxFileSizeMB * 1024 * 1024;
|
|
17858
|
+
const allowedMimeTypes = settings.attachments.allowedMimeTypes;
|
|
17859
|
+
const acceptAttribute = buildAcceptFromMimeTypes(allowedMimeTypes);
|
|
17860
|
+
const [state, setState] = React3.useState({
|
|
17242
17861
|
messageInput: "",
|
|
17243
17862
|
attachments: [],
|
|
17244
17863
|
isFocused: false,
|
|
@@ -17248,8 +17867,8 @@ function useChannelMessageBox({
|
|
|
17248
17867
|
const updateState = (updates) => {
|
|
17249
17868
|
setState((prev) => ({ ...prev, ...updates }));
|
|
17250
17869
|
};
|
|
17251
|
-
const typingTimeoutRef =
|
|
17252
|
-
const conversationIdRef =
|
|
17870
|
+
const typingTimeoutRef = React3.useRef(null);
|
|
17871
|
+
const conversationIdRef = React3.useRef(conversationId);
|
|
17253
17872
|
conversationIdRef.current = conversationId;
|
|
17254
17873
|
const { syncComposerRef } = useConversationDraft(conversationId);
|
|
17255
17874
|
const emitTypingStart = exports.useChatStore((s) => s.emitTypingStart);
|
|
@@ -17260,12 +17879,12 @@ function useChannelMessageBox({
|
|
|
17260
17879
|
const allUsers = exports.useChatStore((s) => s.allUsers);
|
|
17261
17880
|
const composerDisabledByConversation = exports.useChatStore((s) => s.composerDisabledByConversation);
|
|
17262
17881
|
const composerDisabledReason = conversationId ? composerDisabledByConversation[conversationId] : void 0;
|
|
17263
|
-
const fileInputRef =
|
|
17264
|
-
const attachmentsCountRef =
|
|
17265
|
-
|
|
17882
|
+
const fileInputRef = React3.useRef(null);
|
|
17883
|
+
const attachmentsCountRef = React3.useRef(0);
|
|
17884
|
+
React3__namespace.default.useEffect(() => {
|
|
17266
17885
|
attachmentsCountRef.current = state.attachments.length;
|
|
17267
17886
|
}, [state.attachments.length]);
|
|
17268
|
-
|
|
17887
|
+
React3__namespace.default.useEffect(() => {
|
|
17269
17888
|
const draft = {
|
|
17270
17889
|
messageInput: state.messageInput,
|
|
17271
17890
|
attachments: state.attachments
|
|
@@ -17273,7 +17892,7 @@ function useChannelMessageBox({
|
|
|
17273
17892
|
syncComposerRef(draft);
|
|
17274
17893
|
updateConversationDraft(conversationIdRef.current, draft);
|
|
17275
17894
|
}, [state.messageInput, state.attachments, syncComposerRef]);
|
|
17276
|
-
|
|
17895
|
+
React3__namespace.default.useEffect(() => {
|
|
17277
17896
|
if (typingTimeoutRef.current) {
|
|
17278
17897
|
clearTimeout(typingTimeoutRef.current);
|
|
17279
17898
|
typingTimeoutRef.current = null;
|
|
@@ -17333,21 +17952,52 @@ function useChannelMessageBox({
|
|
|
17333
17952
|
const handleFileChange = (e) => {
|
|
17334
17953
|
const files = e.target.files ? Array.from(e.target.files) : [];
|
|
17335
17954
|
if (!files.length) return;
|
|
17955
|
+
if (!attachmentsGate.enabled) {
|
|
17956
|
+
updateState({
|
|
17957
|
+
attachmentError: attachmentsGate.disabledReason || "Attachments are disabled by your administrator."
|
|
17958
|
+
});
|
|
17959
|
+
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
17960
|
+
return;
|
|
17961
|
+
}
|
|
17336
17962
|
const currentCount = attachmentsCountRef.current;
|
|
17337
|
-
const remaining =
|
|
17963
|
+
const remaining = maxAttachments - currentCount;
|
|
17338
17964
|
if (remaining <= 0) {
|
|
17339
|
-
updateState({ attachmentError: `Maximum ${
|
|
17965
|
+
updateState({ attachmentError: `Maximum ${maxAttachments} files allowed` });
|
|
17966
|
+
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
17967
|
+
return;
|
|
17968
|
+
}
|
|
17969
|
+
const validFiles = [];
|
|
17970
|
+
const rejectionMessages = [];
|
|
17971
|
+
for (const file of files) {
|
|
17972
|
+
if (!matchesAllowedMimeType(file.type, allowedMimeTypes)) {
|
|
17973
|
+
rejectionMessages.push(`"${file.name}" type is not allowed`);
|
|
17974
|
+
continue;
|
|
17975
|
+
}
|
|
17976
|
+
if (file.size > maxFileSizeBytes) {
|
|
17977
|
+
rejectionMessages.push(
|
|
17978
|
+
`"${file.name}" exceeds ${settings.attachments.maxFileSizeMB} MB (got ${formatFileSizeMB(file.size)})`
|
|
17979
|
+
);
|
|
17980
|
+
continue;
|
|
17981
|
+
}
|
|
17982
|
+
validFiles.push(file);
|
|
17983
|
+
}
|
|
17984
|
+
if (validFiles.length === 0) {
|
|
17985
|
+
updateState({
|
|
17986
|
+
attachmentError: rejectionMessages[0] || "Selected files are not allowed"
|
|
17987
|
+
});
|
|
17340
17988
|
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
17341
17989
|
return;
|
|
17342
17990
|
}
|
|
17343
|
-
if (
|
|
17991
|
+
if (validFiles.length > remaining) {
|
|
17344
17992
|
updateState({
|
|
17345
17993
|
attachmentError: `You can upload only ${remaining} more file${remaining > 1 ? "s" : ""}`
|
|
17346
17994
|
});
|
|
17995
|
+
} else if (rejectionMessages.length > 0) {
|
|
17996
|
+
updateState({ attachmentError: rejectionMessages[0] });
|
|
17347
17997
|
} else {
|
|
17348
17998
|
updateState({ attachmentError: "" });
|
|
17349
17999
|
}
|
|
17350
|
-
const filesToAdd =
|
|
18000
|
+
const filesToAdd = validFiles.slice(0, remaining);
|
|
17351
18001
|
attachmentsCountRef.current = currentCount + filesToAdd.length;
|
|
17352
18002
|
const newAttachments = filesToAdd.map((file) => ({
|
|
17353
18003
|
id: `att-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
@@ -17404,7 +18054,7 @@ function useChannelMessageBox({
|
|
|
17404
18054
|
return {
|
|
17405
18055
|
...prev,
|
|
17406
18056
|
attachments: nextAttachments,
|
|
17407
|
-
attachmentError: nextAttachments.length <
|
|
18057
|
+
attachmentError: nextAttachments.length < maxAttachments ? "" : prev.attachmentError
|
|
17408
18058
|
};
|
|
17409
18059
|
});
|
|
17410
18060
|
};
|
|
@@ -17511,7 +18161,10 @@ function useChannelMessageBox({
|
|
|
17511
18161
|
onlyAdminCanSendMessage,
|
|
17512
18162
|
fileInputRef,
|
|
17513
18163
|
hasUploadingAttachments,
|
|
17514
|
-
maxAttachments
|
|
18164
|
+
maxAttachments,
|
|
18165
|
+
acceptAttribute,
|
|
18166
|
+
attachmentsEnabled: attachmentsGate.enabled,
|
|
18167
|
+
attachmentsDisabledReason: attachmentsGate.disabledReason,
|
|
17515
18168
|
handleInputChange,
|
|
17516
18169
|
handleFileChange,
|
|
17517
18170
|
handleRemoveAttachment,
|
|
@@ -17539,6 +18192,9 @@ var ChannelMessageBoxView = (props) => {
|
|
|
17539
18192
|
fileInputRef,
|
|
17540
18193
|
hasUploadingAttachments,
|
|
17541
18194
|
maxAttachments,
|
|
18195
|
+
acceptAttribute,
|
|
18196
|
+
attachmentsEnabled,
|
|
18197
|
+
attachmentsDisabledReason,
|
|
17542
18198
|
handleInputChange,
|
|
17543
18199
|
handleFileChange,
|
|
17544
18200
|
handleRemoveAttachment,
|
|
@@ -17636,16 +18292,23 @@ var ChannelMessageBoxView = (props) => {
|
|
|
17636
18292
|
),
|
|
17637
18293
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-end gap-1.5 p-1.5", children: [
|
|
17638
18294
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17639
|
-
|
|
18295
|
+
AdminPermissionTooltip,
|
|
17640
18296
|
{
|
|
17641
|
-
|
|
17642
|
-
|
|
17643
|
-
|
|
17644
|
-
|
|
17645
|
-
|
|
17646
|
-
|
|
17647
|
-
|
|
17648
|
-
|
|
18297
|
+
disabled: !attachmentsEnabled,
|
|
18298
|
+
message: attachmentsDisabledReason,
|
|
18299
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
18300
|
+
Button,
|
|
18301
|
+
{
|
|
18302
|
+
type: "button",
|
|
18303
|
+
variant: "ghost",
|
|
18304
|
+
size: "icon",
|
|
18305
|
+
className: "shrink-0 size-9 rounded-xl text-(--chat-muted) transition-all hover:bg-(--chat-hover) hover:text-(--chat-text) disabled:opacity-40",
|
|
18306
|
+
onClick: () => attachmentsEnabled && !hasUploadingAttachments && fileInputRef.current?.click(),
|
|
18307
|
+
disabled: !attachmentsEnabled || hasUploadingAttachments,
|
|
18308
|
+
"aria-label": "Attach files",
|
|
18309
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Paperclip, { size: 16 })
|
|
18310
|
+
}
|
|
18311
|
+
)
|
|
17649
18312
|
}
|
|
17650
18313
|
),
|
|
17651
18314
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -17655,8 +18318,9 @@ var ChannelMessageBoxView = (props) => {
|
|
|
17655
18318
|
ref: fileInputRef,
|
|
17656
18319
|
className: "hidden",
|
|
17657
18320
|
multiple: true,
|
|
17658
|
-
accept:
|
|
17659
|
-
onChange: handleFileChange
|
|
18321
|
+
accept: acceptAttribute || void 0,
|
|
18322
|
+
onChange: handleFileChange,
|
|
18323
|
+
disabled: !attachmentsEnabled
|
|
17660
18324
|
}
|
|
17661
18325
|
),
|
|
17662
18326
|
/* @__PURE__ */ jsxRuntime.jsxs(Popover, { children: [
|
|
@@ -17735,11 +18399,11 @@ var ChannelMessageBoxView_default = ChannelMessageBoxView;
|
|
|
17735
18399
|
// src/chat/forward-modal/useForwardModal.ts
|
|
17736
18400
|
init_useStore();
|
|
17737
18401
|
function useForwardModal({ isOpen, onClose, items, onForwardComplete }) {
|
|
17738
|
-
const [search, setSearch] =
|
|
17739
|
-
const [debouncedSearch, setDebouncedSearch] =
|
|
17740
|
-
const targetChannelRef =
|
|
17741
|
-
const wasForwardingRef =
|
|
17742
|
-
const completionHandledRef =
|
|
18402
|
+
const [search, setSearch] = React3.useState("");
|
|
18403
|
+
const [debouncedSearch, setDebouncedSearch] = React3.useState("");
|
|
18404
|
+
const targetChannelRef = React3.useRef(null);
|
|
18405
|
+
const wasForwardingRef = React3.useRef(false);
|
|
18406
|
+
const completionHandledRef = React3.useRef(false);
|
|
17743
18407
|
const emitDmForward = exports.useChatStore((s) => s.emitDmForward);
|
|
17744
18408
|
const emitGroupForward = exports.useChatStore((s) => s.emitGroupForward);
|
|
17745
18409
|
const loggedUserDetails = exports.useChatStore((s) => s.loggedUserDetails);
|
|
@@ -17747,23 +18411,23 @@ function useForwardModal({ isOpen, onClose, items, onForwardComplete }) {
|
|
|
17747
18411
|
const storeConversations = exports.useChatStore((s) => s.conversations);
|
|
17748
18412
|
const allUsers = exports.useChatStore((s) => s.allUsers);
|
|
17749
18413
|
const sourceMessage = items[0]?.message ?? null;
|
|
17750
|
-
const mids =
|
|
18414
|
+
const mids = React3.useMemo(
|
|
17751
18415
|
() => items.map((item) => String(item.message._id || item.message.id || "")).filter(Boolean),
|
|
17752
18416
|
[items]
|
|
17753
18417
|
);
|
|
17754
18418
|
const isForwarding = mids.some((id) => pendingActions[id]?.includes("forward"));
|
|
17755
|
-
const onCloseRef =
|
|
17756
|
-
const onForwardCompleteRef =
|
|
17757
|
-
|
|
18419
|
+
const onCloseRef = React3.useRef(onClose);
|
|
18420
|
+
const onForwardCompleteRef = React3.useRef(onForwardComplete);
|
|
18421
|
+
React3.useEffect(() => {
|
|
17758
18422
|
onCloseRef.current = onClose;
|
|
17759
18423
|
}, [onClose]);
|
|
17760
|
-
|
|
18424
|
+
React3.useEffect(() => {
|
|
17761
18425
|
onForwardCompleteRef.current = onForwardComplete;
|
|
17762
18426
|
}, [onForwardComplete]);
|
|
17763
|
-
const handleOpenChange =
|
|
18427
|
+
const handleOpenChange = React3.useCallback((open) => {
|
|
17764
18428
|
if (!open) onCloseRef.current();
|
|
17765
18429
|
}, []);
|
|
17766
|
-
|
|
18430
|
+
React3.useEffect(() => {
|
|
17767
18431
|
if (isForwarding) {
|
|
17768
18432
|
wasForwardingRef.current = true;
|
|
17769
18433
|
const timeout = setTimeout(() => {
|
|
@@ -17781,7 +18445,7 @@ function useForwardModal({ isOpen, onClose, items, onForwardComplete }) {
|
|
|
17781
18445
|
queueMicrotask(() => onForwardCompleteRef.current(target));
|
|
17782
18446
|
}
|
|
17783
18447
|
}, [isForwarding, mids]);
|
|
17784
|
-
|
|
18448
|
+
React3.useEffect(() => {
|
|
17785
18449
|
if (!isOpen) {
|
|
17786
18450
|
setSearch("");
|
|
17787
18451
|
setDebouncedSearch("");
|
|
@@ -17790,11 +18454,11 @@ function useForwardModal({ isOpen, onClose, items, onForwardComplete }) {
|
|
|
17790
18454
|
completionHandledRef.current = false;
|
|
17791
18455
|
}
|
|
17792
18456
|
}, [isOpen]);
|
|
17793
|
-
|
|
18457
|
+
React3.useEffect(() => {
|
|
17794
18458
|
const handler = setTimeout(() => setDebouncedSearch(search), 400);
|
|
17795
18459
|
return () => clearTimeout(handler);
|
|
17796
18460
|
}, [search]);
|
|
17797
|
-
const mappedChannels =
|
|
18461
|
+
const mappedChannels = React3.useMemo(() => {
|
|
17798
18462
|
const sourceConversationId = sourceMessage?.conversationId ? String(sourceMessage.conversationId) : null;
|
|
17799
18463
|
const query = debouncedSearch.trim().toLowerCase();
|
|
17800
18464
|
return storeConversations.filter((c) => !sourceConversationId || String(c._id) !== sourceConversationId).map((c) => {
|
|
@@ -17922,7 +18586,7 @@ function ForwardModalView(props) {
|
|
|
17922
18586
|
|
|
17923
18587
|
// src/chat/ChatPanelAlerts.tsx
|
|
17924
18588
|
init_useStore();
|
|
17925
|
-
var ChatAlertsContext =
|
|
18589
|
+
var ChatAlertsContext = React3.createContext({});
|
|
17926
18590
|
function ChatAlertsProvider({
|
|
17927
18591
|
children,
|
|
17928
18592
|
value
|
|
@@ -17930,7 +18594,7 @@ function ChatAlertsProvider({
|
|
|
17930
18594
|
return /* @__PURE__ */ jsxRuntime.jsx(ChatAlertsContext.Provider, { value, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-0 h-full w-full flex-1 flex-col overflow-hidden", children }) });
|
|
17931
18595
|
}
|
|
17932
18596
|
function useChatAlerts() {
|
|
17933
|
-
return
|
|
18597
|
+
return React3.useContext(ChatAlertsContext);
|
|
17934
18598
|
}
|
|
17935
18599
|
var normalizeMessage = (message) => message.trim().toLowerCase();
|
|
17936
18600
|
var alertStyles = {
|
|
@@ -17945,14 +18609,14 @@ var ChatPanelAlerts = () => {
|
|
|
17945
18609
|
const conversationErrors = exports.useChatStore((s) => s.conversationErrors);
|
|
17946
18610
|
const clearAppError = exports.useChatStore((s) => s.clearAppError);
|
|
17947
18611
|
const rateLimitResetAt2 = exports.useChatStore((s) => s.rateLimitResetAt);
|
|
17948
|
-
const [now, setNow] =
|
|
18612
|
+
const [now, setNow] = React3.useState(() => Date.now());
|
|
17949
18613
|
const conversationAppError = activeConversationId ? conversationErrors[activeConversationId] ?? null : null;
|
|
17950
|
-
|
|
18614
|
+
React3.useEffect(() => {
|
|
17951
18615
|
if (rateLimitResetAt2 <= Date.now()) return;
|
|
17952
18616
|
const id = window.setInterval(() => setNow(Date.now()), 1e3);
|
|
17953
18617
|
return () => window.clearInterval(id);
|
|
17954
18618
|
}, [rateLimitResetAt2]);
|
|
17955
|
-
const alerts =
|
|
18619
|
+
const alerts = React3.useMemo(() => {
|
|
17956
18620
|
const items = [];
|
|
17957
18621
|
const seen = /* @__PURE__ */ new Set();
|
|
17958
18622
|
const push = (item) => {
|
|
@@ -18376,9 +19040,9 @@ var emitToast = (payload, onPush) => {
|
|
|
18376
19040
|
};
|
|
18377
19041
|
var ForegroundPushBridge = ({ onPush }) => {
|
|
18378
19042
|
const lastDM = exports.useChatStore((s) => s.lastDM);
|
|
18379
|
-
const onPushRef =
|
|
19043
|
+
const onPushRef = React3.useRef(onPush);
|
|
18380
19044
|
onPushRef.current = onPush;
|
|
18381
|
-
|
|
19045
|
+
React3.useEffect(() => {
|
|
18382
19046
|
if (!lastDM) return;
|
|
18383
19047
|
if (typeof document !== "undefined" && document.visibilityState !== "visible") {
|
|
18384
19048
|
return;
|
|
@@ -18418,7 +19082,7 @@ var ForegroundPushBridge = ({ onPush }) => {
|
|
|
18418
19082
|
onPushRef.current
|
|
18419
19083
|
);
|
|
18420
19084
|
}, [lastDM]);
|
|
18421
|
-
|
|
19085
|
+
React3.useEffect(() => {
|
|
18422
19086
|
let unsubscribe = null;
|
|
18423
19087
|
let retryTimer = null;
|
|
18424
19088
|
let cancelled = false;
|
|
@@ -18494,7 +19158,7 @@ var ForegroundPushBridge = ({ onPush }) => {
|
|
|
18494
19158
|
window.removeEventListener(PUSH_CHANGED_EVENT, onPushChanged);
|
|
18495
19159
|
};
|
|
18496
19160
|
}, []);
|
|
18497
|
-
|
|
19161
|
+
React3.useEffect(() => {
|
|
18498
19162
|
const onOpen = (event) => {
|
|
18499
19163
|
const id = String(
|
|
18500
19164
|
event.detail?.conversationId || ""
|
|
@@ -18571,8 +19235,8 @@ var ChatMain = ({
|
|
|
18571
19235
|
viewportHeight = "full",
|
|
18572
19236
|
viewportClassName
|
|
18573
19237
|
}) => {
|
|
18574
|
-
const clientObj =
|
|
18575
|
-
const uiConfigObj =
|
|
19238
|
+
const clientObj = React3__namespace.default.useMemo(() => ({ id: clientId }), [clientId]);
|
|
19239
|
+
const uiConfigObj = React3__namespace.default.useMemo(
|
|
18576
19240
|
() => ({
|
|
18577
19241
|
...uiConfig || {},
|
|
18578
19242
|
components: { ...uiConfig?.components, ...components },
|
|
@@ -18943,6 +19607,8 @@ var packageDefaultComponents = {
|
|
|
18943
19607
|
};
|
|
18944
19608
|
|
|
18945
19609
|
// src/index.ts
|
|
19610
|
+
init_settings_types();
|
|
19611
|
+
init_api_service();
|
|
18946
19612
|
var index_default = ChatMain_default;
|
|
18947
19613
|
|
|
18948
19614
|
exports.Calendar = Calendar;
|
|
@@ -18956,6 +19622,7 @@ exports.ChatAlertsProvider = ChatAlertsProvider;
|
|
|
18956
19622
|
exports.ChatAvatar = ChatAvatar_default;
|
|
18957
19623
|
exports.ChatCustomizationProvider = ChatCustomizationProvider;
|
|
18958
19624
|
exports.ChatDateJumpMenu = ChatDateJumpMenu;
|
|
19625
|
+
exports.ChatEffectiveSettingsProvider = ChatEffectiveSettingsProvider;
|
|
18959
19626
|
exports.ChatLayout = ChatLayout_default;
|
|
18960
19627
|
exports.ChatLocaleProvider = ChatLocaleProvider;
|
|
18961
19628
|
exports.ChatMain = ChatMain_default;
|
|
@@ -19035,6 +19702,8 @@ exports.useChatFeatures = useChatFeatures;
|
|
|
19035
19702
|
exports.useChatFeaturesOptional = useChatFeaturesOptional;
|
|
19036
19703
|
exports.useChatLocale = useChatLocale;
|
|
19037
19704
|
exports.useChatTheme = useChatTheme;
|
|
19705
|
+
exports.useEffectiveSettings = useEffectiveSettings;
|
|
19706
|
+
exports.useEffectiveSettingsOptional = useEffectiveSettingsOptional;
|
|
19038
19707
|
exports.usePushNotifications = usePushNotifications;
|
|
19039
19708
|
//# sourceMappingURL=index.cjs.map
|
|
19040
19709
|
//# sourceMappingURL=index.cjs.map
|