@realtimexsco/live-chat 1.4.10 → 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 +1374 -504
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +206 -47
- package/dist/index.d.ts +206 -47
- package/dist/index.mjs +1105 -242
- 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",
|
|
@@ -1251,6 +1253,64 @@ var init_query_params = __esm({
|
|
|
1251
1253
|
];
|
|
1252
1254
|
}
|
|
1253
1255
|
});
|
|
1256
|
+
|
|
1257
|
+
// src/services/api/api-version.ts
|
|
1258
|
+
var DEFAULT_VERSIONS, apiVersions, normalizeApiVersion; exports.resolveApiRoot = void 0; exports.buildVersionedApiUrl = void 0; exports.setChatApiVersions = void 0; exports.getChatApiVersions = void 0; exports.setChatPushApiVersion = void 0; var syncDefaultApiVersionFromBaseUrl;
|
|
1259
|
+
var init_api_version = __esm({
|
|
1260
|
+
"src/services/api/api-version.ts"() {
|
|
1261
|
+
init_client();
|
|
1262
|
+
DEFAULT_VERSIONS = {
|
|
1263
|
+
v1: "v1",
|
|
1264
|
+
v2: "v2"
|
|
1265
|
+
};
|
|
1266
|
+
apiVersions = { ...DEFAULT_VERSIONS };
|
|
1267
|
+
normalizeApiVersion = (version) => {
|
|
1268
|
+
const raw = String(version || "v1").trim().replace(/^\/+|\/+$/g, "");
|
|
1269
|
+
if (!raw) return "v1";
|
|
1270
|
+
return /^v\d+$/i.test(raw) ? raw.toLowerCase() : `v${raw}`;
|
|
1271
|
+
};
|
|
1272
|
+
exports.resolveApiRoot = (baseUrl) => {
|
|
1273
|
+
const raw = String(
|
|
1274
|
+
baseUrl || exports.getChatBaseUrl() || apiClient.defaults.baseURL || ""
|
|
1275
|
+
).trim().replace(/\/$/, "");
|
|
1276
|
+
if (!raw) return "";
|
|
1277
|
+
const withoutVersion = raw.replace(/\/v\d+$/i, "");
|
|
1278
|
+
return withoutVersion || raw;
|
|
1279
|
+
};
|
|
1280
|
+
exports.buildVersionedApiUrl = (path, options) => {
|
|
1281
|
+
const root = exports.resolveApiRoot(options?.baseUrl);
|
|
1282
|
+
const version = normalizeApiVersion(
|
|
1283
|
+
options?.version ?? (options?.service ? apiVersions[options.service] : apiVersions.v1)
|
|
1284
|
+
);
|
|
1285
|
+
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
1286
|
+
if (!root) {
|
|
1287
|
+
return `/${version}${normalizedPath}`;
|
|
1288
|
+
}
|
|
1289
|
+
return `${root}/${version}${normalizedPath}`;
|
|
1290
|
+
};
|
|
1291
|
+
exports.setChatApiVersions = (config) => {
|
|
1292
|
+
if (!config) return;
|
|
1293
|
+
if (config.v1) {
|
|
1294
|
+
apiVersions.v1 = normalizeApiVersion(config.v1);
|
|
1295
|
+
}
|
|
1296
|
+
if (config.v2) {
|
|
1297
|
+
apiVersions.v2 = normalizeApiVersion(config.v2);
|
|
1298
|
+
}
|
|
1299
|
+
};
|
|
1300
|
+
exports.getChatApiVersions = () => ({
|
|
1301
|
+
...apiVersions
|
|
1302
|
+
});
|
|
1303
|
+
exports.setChatPushApiVersion = (version) => {
|
|
1304
|
+
apiVersions.v2 = normalizeApiVersion(version);
|
|
1305
|
+
};
|
|
1306
|
+
syncDefaultApiVersionFromBaseUrl = (baseUrl) => {
|
|
1307
|
+
const match = String(baseUrl || "").trim().match(/\/(v\d+)\/?$/i);
|
|
1308
|
+
if (match?.[1]) {
|
|
1309
|
+
apiVersions.v1 = normalizeApiVersion(match[1]);
|
|
1310
|
+
}
|
|
1311
|
+
};
|
|
1312
|
+
}
|
|
1313
|
+
});
|
|
1254
1314
|
function resolveParamsForRequest(url, method) {
|
|
1255
1315
|
const apiKey = resolveChatApiKey(url);
|
|
1256
1316
|
const httpMethod = (method || "get").toLowerCase();
|
|
@@ -1267,7 +1327,9 @@ var chatClientId, chatAccessToken, chatBaseUrl, chatSocketUrl, chatQueryParams,
|
|
|
1267
1327
|
var init_client = __esm({
|
|
1268
1328
|
"src/services/api/client.ts"() {
|
|
1269
1329
|
init_query_params();
|
|
1330
|
+
init_api_version();
|
|
1270
1331
|
init_query_params();
|
|
1332
|
+
init_api_version();
|
|
1271
1333
|
chatClientId = "";
|
|
1272
1334
|
chatAccessToken = "";
|
|
1273
1335
|
chatBaseUrl = "";
|
|
@@ -1285,6 +1347,7 @@ var init_client = __esm({
|
|
|
1285
1347
|
exports.setChatBaseURL = (url) => {
|
|
1286
1348
|
chatBaseUrl = url.trim();
|
|
1287
1349
|
apiClient.defaults.baseURL = chatBaseUrl;
|
|
1350
|
+
syncDefaultApiVersionFromBaseUrl(chatBaseUrl);
|
|
1288
1351
|
};
|
|
1289
1352
|
exports.getChatBaseUrl = () => chatBaseUrl;
|
|
1290
1353
|
exports.setChatSocketUrl = (url) => {
|
|
@@ -1388,6 +1451,9 @@ var init_api_constants = __esm({
|
|
|
1388
1451
|
SEARCH_MESSAGES: "/message/search-messages",
|
|
1389
1452
|
SEARCH_MESSAGES_CONTEXT: (messageId2) => `/message/searched-message/context?messageId=${messageId2}`,
|
|
1390
1453
|
BLOCK_UNBLOCK_USER: "/user/block-unblock"
|
|
1454
|
+
},
|
|
1455
|
+
SETTINGS: {
|
|
1456
|
+
PERMISSIONS: "/settings/effective"
|
|
1391
1457
|
}
|
|
1392
1458
|
};
|
|
1393
1459
|
}
|
|
@@ -1424,13 +1490,11 @@ var init_auth_api = __esm({
|
|
|
1424
1490
|
});
|
|
1425
1491
|
|
|
1426
1492
|
// src/constants/chat.constants.ts
|
|
1427
|
-
var DEFAULT_MESSAGES_LIMIT, DEFAULT_CONVERSATIONS_LIMIT,
|
|
1493
|
+
var DEFAULT_MESSAGES_LIMIT, DEFAULT_CONVERSATIONS_LIMIT, MAX_ATTACHMENT_CAPTION_LENGTH, ATTACHMENT_FILENAME_TIMESTAMP_LENGTH;
|
|
1428
1494
|
var init_chat_constants = __esm({
|
|
1429
1495
|
"src/constants/chat.constants.ts"() {
|
|
1430
1496
|
DEFAULT_MESSAGES_LIMIT = 20;
|
|
1431
1497
|
DEFAULT_CONVERSATIONS_LIMIT = 20;
|
|
1432
|
-
DM_EDIT_WINDOW_MS = 5 * 60 * 1e3;
|
|
1433
|
-
GROUP_EDIT_WINDOW_MS = 10 * 60 * 1e3;
|
|
1434
1498
|
MAX_ATTACHMENT_CAPTION_LENGTH = 100;
|
|
1435
1499
|
ATTACHMENT_FILENAME_TIMESTAMP_LENGTH = 13;
|
|
1436
1500
|
}
|
|
@@ -1633,6 +1697,206 @@ var init_uploads_api = __esm({
|
|
|
1633
1697
|
}
|
|
1634
1698
|
});
|
|
1635
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
|
+
|
|
1636
1900
|
// src/services/api/index.ts
|
|
1637
1901
|
var init_api = __esm({
|
|
1638
1902
|
"src/services/api/index.ts"() {
|
|
@@ -1641,6 +1905,7 @@ var init_api = __esm({
|
|
|
1641
1905
|
init_messages_api();
|
|
1642
1906
|
init_groups_api();
|
|
1643
1907
|
init_uploads_api();
|
|
1908
|
+
init_settings_api();
|
|
1644
1909
|
}
|
|
1645
1910
|
});
|
|
1646
1911
|
|
|
@@ -3750,7 +4015,7 @@ function resolveApiUrl(apiUrl) {
|
|
|
3750
4015
|
function resolveSocketUrl(socketUrl, apiUrl) {
|
|
3751
4016
|
const explicit = (socketUrl ?? "").trim();
|
|
3752
4017
|
if (explicit) return explicit;
|
|
3753
|
-
return resolveApiUrl(apiUrl).replace(/\/api\/
|
|
4018
|
+
return resolveApiUrl(apiUrl).replace(/\/api\/v\d+\/?$/i, "");
|
|
3754
4019
|
}
|
|
3755
4020
|
|
|
3756
4021
|
// src/hooks/chat-sync/useChatSync.ts
|
|
@@ -4324,7 +4589,7 @@ var syncLocalMessagesOnDmMarkRead = (prev, lastDMMarkRead, conversations, logged
|
|
|
4324
4589
|
|
|
4325
4590
|
// src/hooks/chat-sync/useChatSync.ts
|
|
4326
4591
|
var useChatSync = () => {
|
|
4327
|
-
const [localMessages, setLocalMessages] =
|
|
4592
|
+
const [localMessages, setLocalMessages] = React3.useState({});
|
|
4328
4593
|
const lastDM = useSocketStore((s) => s.lastDM);
|
|
4329
4594
|
const lastEditDM = useSocketStore((s) => s.lastEditDM);
|
|
4330
4595
|
const lastDeleteDM = useSocketStore((s) => s.lastDeleteDM);
|
|
@@ -4337,17 +4602,17 @@ var useChatSync = () => {
|
|
|
4337
4602
|
const messagesByConversation = useSocketStore((s) => s.messagesByConversation);
|
|
4338
4603
|
const messagesMetadata = useSocketStore((s) => s.messagesMetadata);
|
|
4339
4604
|
const loggedUserDetails = useAuthStore((s) => s.loggedUserDetails);
|
|
4340
|
-
|
|
4605
|
+
React3.useEffect(() => {
|
|
4341
4606
|
setLocalMessages(
|
|
4342
4607
|
(prev) => syncLocalMessagesOnStoreClear(prev, messagesByConversation, messagesMetadata)
|
|
4343
4608
|
);
|
|
4344
4609
|
}, [messagesByConversation, messagesMetadata]);
|
|
4345
|
-
|
|
4610
|
+
React3.useEffect(() => {
|
|
4346
4611
|
if (lastPinUpdate) {
|
|
4347
4612
|
setLocalMessages((prev) => syncLocalMessagesOnPinUpdate(prev, lastPinUpdate));
|
|
4348
4613
|
}
|
|
4349
4614
|
}, [lastPinUpdate]);
|
|
4350
|
-
|
|
4615
|
+
React3.useEffect(() => {
|
|
4351
4616
|
if (lastStarUpdate) {
|
|
4352
4617
|
setLocalMessages((prev) => {
|
|
4353
4618
|
const next = syncLocalMessagesOnStarUpdate(
|
|
@@ -4359,18 +4624,18 @@ var useChatSync = () => {
|
|
|
4359
4624
|
});
|
|
4360
4625
|
}
|
|
4361
4626
|
}, [lastStarUpdate, loggedUserDetails?._id]);
|
|
4362
|
-
|
|
4627
|
+
React3.useEffect(() => {
|
|
4363
4628
|
if (!lastReactionUpdate) return;
|
|
4364
4629
|
setLocalMessages(
|
|
4365
4630
|
(prev) => syncLocalMessagesOnReactionUpdate(prev, lastReactionUpdate, messagesByConversation)
|
|
4366
4631
|
);
|
|
4367
4632
|
}, [lastReactionUpdate, messagesByConversation]);
|
|
4368
|
-
|
|
4633
|
+
React3.useEffect(() => {
|
|
4369
4634
|
if (lastDeleteDM) {
|
|
4370
4635
|
setLocalMessages((prev) => syncLocalMessagesOnDelete(prev, lastDeleteDM));
|
|
4371
4636
|
}
|
|
4372
4637
|
}, [lastDeleteDM]);
|
|
4373
|
-
|
|
4638
|
+
React3.useEffect(() => {
|
|
4374
4639
|
if (lastEditDM) {
|
|
4375
4640
|
setLocalMessages((prev) => {
|
|
4376
4641
|
const next = syncLocalMessagesOnEdit(prev, lastEditDM);
|
|
@@ -4378,7 +4643,7 @@ var useChatSync = () => {
|
|
|
4378
4643
|
});
|
|
4379
4644
|
}
|
|
4380
4645
|
}, [lastEditDM]);
|
|
4381
|
-
|
|
4646
|
+
React3.useEffect(() => {
|
|
4382
4647
|
if (!lastDM) return;
|
|
4383
4648
|
const result = buildIncomingMessageFromDM(
|
|
4384
4649
|
lastDM,
|
|
@@ -4390,14 +4655,14 @@ var useChatSync = () => {
|
|
|
4390
4655
|
(prev) => applyMessageUpdate(prev, result.storageKey, result.incomingMsg, result.isMe)
|
|
4391
4656
|
);
|
|
4392
4657
|
}, [lastDM, loggedUserDetails, conversations]);
|
|
4393
|
-
|
|
4658
|
+
React3.useEffect(() => {
|
|
4394
4659
|
if (lastStatusUpdate) {
|
|
4395
4660
|
setLocalMessages(
|
|
4396
4661
|
(prev) => syncLocalMessagesOnStatusUpdate(prev, lastStatusUpdate, loggedUserDetails)
|
|
4397
4662
|
);
|
|
4398
4663
|
}
|
|
4399
4664
|
}, [lastStatusUpdate, loggedUserDetails]);
|
|
4400
|
-
|
|
4665
|
+
React3.useEffect(() => {
|
|
4401
4666
|
if (lastDMMarkRead) {
|
|
4402
4667
|
setLocalMessages((prev) => {
|
|
4403
4668
|
const next = syncLocalMessagesOnDmMarkRead(
|
|
@@ -4427,16 +4692,16 @@ var mergeChatCustomization = (config) => ({
|
|
|
4427
4692
|
classNames: { ...defaultChatClassNames, ...config?.classNames ?? {} },
|
|
4428
4693
|
features: { ...defaultChatFeatures, ...config?.features ?? {} }
|
|
4429
4694
|
});
|
|
4430
|
-
var ChatCustomizationContext =
|
|
4695
|
+
var ChatCustomizationContext = React3.createContext(void 0);
|
|
4431
4696
|
var ChatCustomizationProvider = ({
|
|
4432
4697
|
children,
|
|
4433
4698
|
customization
|
|
4434
4699
|
}) => {
|
|
4435
|
-
const merged =
|
|
4700
|
+
const merged = React3.useMemo(
|
|
4436
4701
|
() => mergeChatCustomization(customization),
|
|
4437
4702
|
[customization]
|
|
4438
4703
|
);
|
|
4439
|
-
const value =
|
|
4704
|
+
const value = React3.useMemo(
|
|
4440
4705
|
() => ({
|
|
4441
4706
|
components: merged.components,
|
|
4442
4707
|
classNames: merged.classNames,
|
|
@@ -4452,7 +4717,7 @@ var ChatCustomizationProvider = ({
|
|
|
4452
4717
|
return /* @__PURE__ */ jsxRuntime.jsx(ChatCustomizationContext.Provider, { value, children });
|
|
4453
4718
|
};
|
|
4454
4719
|
var useChatCustomization = () => {
|
|
4455
|
-
const context =
|
|
4720
|
+
const context = React3.useContext(ChatCustomizationContext);
|
|
4456
4721
|
if (!context) {
|
|
4457
4722
|
throw new Error(
|
|
4458
4723
|
"useChatCustomization must be used within ChatCustomizationProvider"
|
|
@@ -4461,7 +4726,7 @@ var useChatCustomization = () => {
|
|
|
4461
4726
|
return context;
|
|
4462
4727
|
};
|
|
4463
4728
|
var useChatCustomizationOptional = () => {
|
|
4464
|
-
const context =
|
|
4729
|
+
const context = React3.useContext(ChatCustomizationContext);
|
|
4465
4730
|
return context ?? {
|
|
4466
4731
|
components: {},
|
|
4467
4732
|
classNames: {},
|
|
@@ -4472,9 +4737,146 @@ var useChatCustomizationOptional = () => {
|
|
|
4472
4737
|
};
|
|
4473
4738
|
var useChatFeatures = () => useChatCustomization().features;
|
|
4474
4739
|
var useChatFeaturesOptional = () => useChatCustomizationOptional().features;
|
|
4475
|
-
|
|
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);
|
|
4476
4878
|
var useChatContext = () => {
|
|
4477
|
-
const context =
|
|
4879
|
+
const context = React3.useContext(ChatContext);
|
|
4478
4880
|
if (!context) {
|
|
4479
4881
|
throw new Error("useChatContext must be used within a Chat provider");
|
|
4480
4882
|
}
|
|
@@ -4497,6 +4899,7 @@ var Chat = ({
|
|
|
4497
4899
|
queryParams,
|
|
4498
4900
|
queryParamApis,
|
|
4499
4901
|
queryParamsByApi,
|
|
4902
|
+
apiVersions: apiVersions2,
|
|
4500
4903
|
channelsData,
|
|
4501
4904
|
messagesData,
|
|
4502
4905
|
onMessageReceived,
|
|
@@ -4510,7 +4913,7 @@ var Chat = ({
|
|
|
4510
4913
|
const status = exports.useChatStore((s) => s.status);
|
|
4511
4914
|
const error = exports.useChatStore((s) => s.error);
|
|
4512
4915
|
useChatSync();
|
|
4513
|
-
|
|
4916
|
+
React3__namespace.default.useEffect(() => {
|
|
4514
4917
|
const clientId = client?.id;
|
|
4515
4918
|
const initializeChat = async () => {
|
|
4516
4919
|
if (!clientId || !loggedUserDetails) return;
|
|
@@ -4522,6 +4925,7 @@ var Chat = ({
|
|
|
4522
4925
|
const resolvedApiUrl = resolveApiUrl(apiUrl);
|
|
4523
4926
|
const resolvedSocketUrl = resolveSocketUrl(socketUrl, resolvedApiUrl);
|
|
4524
4927
|
if (resolvedApiUrl) exports.setChatBaseURL(resolvedApiUrl);
|
|
4928
|
+
exports.setChatApiVersions(apiVersions2);
|
|
4525
4929
|
if (resolvedSocketUrl) exports.setChatSocketUrl(resolvedSocketUrl);
|
|
4526
4930
|
let currentToken = accessToken || "";
|
|
4527
4931
|
let sessionUser = resolveUserFromAccessToken(currentToken, loggedUserDetails);
|
|
@@ -4599,28 +5003,28 @@ var Chat = ({
|
|
|
4599
5003
|
queryParamApis: queryParamApis ?? ["get"],
|
|
4600
5004
|
queryParamsByApi: queryParamsByApi ?? {}
|
|
4601
5005
|
});
|
|
4602
|
-
|
|
5006
|
+
React3__namespace.default.useEffect(() => {
|
|
4603
5007
|
exports.setChatQueryParams(queryParams);
|
|
4604
5008
|
exports.setChatQueryParamApis(queryParamApis);
|
|
4605
5009
|
exports.setChatQueryParamsByApi(queryParamsByApi);
|
|
4606
5010
|
}, [queryConfigKey]);
|
|
4607
|
-
|
|
5011
|
+
React3__namespace.default.useEffect(() => {
|
|
4608
5012
|
if (lastDM && onMessageReceived) {
|
|
4609
5013
|
onMessageReceived(lastDM);
|
|
4610
5014
|
}
|
|
4611
5015
|
}, [lastDM, onMessageReceived]);
|
|
4612
|
-
|
|
5016
|
+
React3__namespace.default.useEffect(() => {
|
|
4613
5017
|
if (status === "connected" && onSocketConnected) {
|
|
4614
5018
|
const socketId = exports.useChatStore.getState().socketId;
|
|
4615
5019
|
if (socketId) onSocketConnected(socketId);
|
|
4616
5020
|
}
|
|
4617
5021
|
}, [status, onSocketConnected]);
|
|
4618
|
-
|
|
5022
|
+
React3__namespace.default.useEffect(() => {
|
|
4619
5023
|
if (status === "error" && error && onSocketError) {
|
|
4620
5024
|
onSocketError(error);
|
|
4621
5025
|
}
|
|
4622
5026
|
}, [status, error, onSocketError]);
|
|
4623
|
-
const contextValue =
|
|
5027
|
+
const contextValue = React3__namespace.default.useMemo(
|
|
4624
5028
|
() => ({
|
|
4625
5029
|
onSendMessage,
|
|
4626
5030
|
client,
|
|
@@ -4640,7 +5044,7 @@ var Chat = ({
|
|
|
4640
5044
|
messagesData
|
|
4641
5045
|
]
|
|
4642
5046
|
);
|
|
4643
|
-
const customization =
|
|
5047
|
+
const customization = React3__namespace.default.useMemo(
|
|
4644
5048
|
() => ({
|
|
4645
5049
|
components: uiConfig.components,
|
|
4646
5050
|
classNames: uiConfig.classNames,
|
|
@@ -4648,7 +5052,7 @@ var Chat = ({
|
|
|
4648
5052
|
}),
|
|
4649
5053
|
[uiConfig.components, uiConfig.classNames, uiConfig.features]
|
|
4650
5054
|
);
|
|
4651
|
-
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..." }) }) }) }) });
|
|
4652
5056
|
};
|
|
4653
5057
|
|
|
4654
5058
|
// src/hooks/useChatController.ts
|
|
@@ -4946,7 +5350,7 @@ function toDisplayAttachments(attachments) {
|
|
|
4946
5350
|
}));
|
|
4947
5351
|
}
|
|
4948
5352
|
var useChatController = () => {
|
|
4949
|
-
const [state, setState] =
|
|
5353
|
+
const [state, setState] = React3.useState({
|
|
4950
5354
|
activeChannel: null,
|
|
4951
5355
|
activeConversationId: null,
|
|
4952
5356
|
replyToMessage: null,
|
|
@@ -4956,15 +5360,15 @@ var useChatController = () => {
|
|
|
4956
5360
|
debouncedSearch: "",
|
|
4957
5361
|
isCreateModalOpen: false
|
|
4958
5362
|
});
|
|
4959
|
-
const updateState =
|
|
5363
|
+
const updateState = React3.useCallback((updates) => {
|
|
4960
5364
|
setState((prev) => ({ ...prev, ...updates }));
|
|
4961
5365
|
}, []);
|
|
4962
|
-
const handleSelectionModeChange =
|
|
5366
|
+
const handleSelectionModeChange = React3.useCallback((active) => {
|
|
4963
5367
|
setState(
|
|
4964
5368
|
(prev) => prev.isMessageSelectionMode === active ? prev : { ...prev, isMessageSelectionMode: active }
|
|
4965
5369
|
);
|
|
4966
5370
|
}, []);
|
|
4967
|
-
const handleActiveChannelPatch =
|
|
5371
|
+
const handleActiveChannelPatch = React3.useCallback((patch) => {
|
|
4968
5372
|
setState(
|
|
4969
5373
|
(prev) => prev.activeChannel ? { ...prev, activeChannel: { ...prev.activeChannel, ...patch } } : prev
|
|
4970
5374
|
);
|
|
@@ -4988,11 +5392,11 @@ var useChatController = () => {
|
|
|
4988
5392
|
const allUsers = exports.useChatStore((s) => s.allUsers);
|
|
4989
5393
|
const isFetchingConversations = exports.useChatStore((s) => s.isFetchingConversations);
|
|
4990
5394
|
const conversations = exports.useChatStore((s) => s.conversations);
|
|
4991
|
-
const [pendingOpenRequest, setPendingOpenRequest] =
|
|
5395
|
+
const [pendingOpenRequest, setPendingOpenRequest] = React3.useState(() => peekPendingOpenRequest());
|
|
4992
5396
|
const conversationsLength = exports.useChatStore(
|
|
4993
5397
|
(s) => state.activeChannel?.conversationId ? 0 : s.conversations.length
|
|
4994
5398
|
);
|
|
4995
|
-
const lastConversationActionsRef =
|
|
5399
|
+
const lastConversationActionsRef = React3.useRef(null);
|
|
4996
5400
|
const activeChannelId = state.activeChannel?.id;
|
|
4997
5401
|
const activeChannelConvId = state.activeChannel?.conversationId;
|
|
4998
5402
|
const activeChannelIsGroup = !!state.activeChannel?.isGroup;
|
|
@@ -5017,7 +5421,7 @@ var useChatController = () => {
|
|
|
5017
5421
|
isGroupConversation(latestInfo)
|
|
5018
5422
|
].join("|");
|
|
5019
5423
|
});
|
|
5020
|
-
|
|
5424
|
+
React3.useEffect(() => {
|
|
5021
5425
|
const onOpen = (event) => {
|
|
5022
5426
|
const detail = event.detail;
|
|
5023
5427
|
if (detail?.conversationId) {
|
|
@@ -5034,7 +5438,7 @@ var useChatController = () => {
|
|
|
5034
5438
|
window.addEventListener(OPEN_CONVERSATION_EVENT, onOpen);
|
|
5035
5439
|
return () => window.removeEventListener(OPEN_CONVERSATION_EVENT, onOpen);
|
|
5036
5440
|
}, []);
|
|
5037
|
-
|
|
5441
|
+
React3.useEffect(() => {
|
|
5038
5442
|
if (!pendingOpenRequest?.conversationId || !loggedUserDetails) return;
|
|
5039
5443
|
let cancelled = false;
|
|
5040
5444
|
const openPending = async () => {
|
|
@@ -5100,13 +5504,13 @@ var useChatController = () => {
|
|
|
5100
5504
|
allUsers,
|
|
5101
5505
|
fetchConversationInfo2
|
|
5102
5506
|
]);
|
|
5103
|
-
|
|
5507
|
+
React3.useEffect(() => {
|
|
5104
5508
|
const handler = setTimeout(() => {
|
|
5105
5509
|
updateState({ debouncedSearch: state.searchQuery });
|
|
5106
5510
|
}, 400);
|
|
5107
5511
|
return () => clearTimeout(handler);
|
|
5108
5512
|
}, [state.searchQuery, updateState]);
|
|
5109
|
-
|
|
5513
|
+
React3.useEffect(() => {
|
|
5110
5514
|
if (!state.activeChannel || !loggedUserDetails) {
|
|
5111
5515
|
setState(
|
|
5112
5516
|
(prev) => prev.activeConversationId === null ? prev : { ...prev, activeConversationId: null }
|
|
@@ -5122,7 +5526,7 @@ var useChatController = () => {
|
|
|
5122
5526
|
(prev) => prev.activeConversationId === nextId ? prev : { ...prev, activeConversationId: nextId }
|
|
5123
5527
|
);
|
|
5124
5528
|
}, [state.activeChannel, loggedUserDetails, conversationsLength]);
|
|
5125
|
-
|
|
5529
|
+
React3.useEffect(() => {
|
|
5126
5530
|
if (!lastDM?.conversationId || !loggedUserDetails) return;
|
|
5127
5531
|
const convId = String(lastDM.conversationId);
|
|
5128
5532
|
const senderId = String(lastDM.sender?._id || lastDM.sender || "");
|
|
@@ -5155,7 +5559,7 @@ var useChatController = () => {
|
|
|
5155
5559
|
};
|
|
5156
5560
|
});
|
|
5157
5561
|
}, [lastDM, loggedUserDetails]);
|
|
5158
|
-
const resolvedLocalMessages =
|
|
5562
|
+
const resolvedLocalMessages = React3.useMemo(
|
|
5159
5563
|
() => resolveLocalMessagesForChannel(
|
|
5160
5564
|
localMessages,
|
|
5161
5565
|
state.activeConversationId,
|
|
@@ -5163,7 +5567,7 @@ var useChatController = () => {
|
|
|
5163
5567
|
),
|
|
5164
5568
|
[localMessages, state.activeConversationId, state.activeChannel?.id]
|
|
5165
5569
|
);
|
|
5166
|
-
const resolvedConversationMessages =
|
|
5570
|
+
const resolvedConversationMessages = React3.useMemo(() => {
|
|
5167
5571
|
if (state.activeConversationId) {
|
|
5168
5572
|
return messagesByConversation[state.activeConversationId] || [];
|
|
5169
5573
|
}
|
|
@@ -5171,7 +5575,7 @@ var useChatController = () => {
|
|
|
5171
5575
|
const groupConversationId = String(state.activeChannel.id);
|
|
5172
5576
|
return messagesByConversation[groupConversationId] || [];
|
|
5173
5577
|
}, [messagesByConversation, state.activeConversationId, state.activeChannel]);
|
|
5174
|
-
|
|
5578
|
+
React3.useEffect(() => {
|
|
5175
5579
|
if (!activeChannelSyncKey || !state.activeChannel) return;
|
|
5176
5580
|
const [convId, pinned, starred, isLeft, isBlocked, isGroup] = activeChannelSyncKey.split("|");
|
|
5177
5581
|
setState((prev) => {
|
|
@@ -5194,10 +5598,10 @@ var useChatController = () => {
|
|
|
5194
5598
|
};
|
|
5195
5599
|
});
|
|
5196
5600
|
}, [activeChannelSyncKey, state.activeChannel]);
|
|
5197
|
-
|
|
5601
|
+
React3.useEffect(() => {
|
|
5198
5602
|
setActiveConversationId(state.activeConversationId);
|
|
5199
5603
|
}, [state.activeConversationId, setActiveConversationId]);
|
|
5200
|
-
|
|
5604
|
+
React3.useEffect(() => {
|
|
5201
5605
|
if (!state.activeConversationId || !state.activeChannel || !loggedUserDetails) {
|
|
5202
5606
|
lastConversationActionsRef.current = null;
|
|
5203
5607
|
return;
|
|
@@ -5244,7 +5648,7 @@ var useChatController = () => {
|
|
|
5244
5648
|
emitGroupMarkRead,
|
|
5245
5649
|
emitMarkAsRead
|
|
5246
5650
|
]);
|
|
5247
|
-
|
|
5651
|
+
React3.useEffect(() => {
|
|
5248
5652
|
if (globalAppError?.type === "participant" && state.activeChannel) {
|
|
5249
5653
|
updateState({ activeChannel: null, activeConversationId: null });
|
|
5250
5654
|
}
|
|
@@ -5421,7 +5825,7 @@ function withThemeTransition(apply) {
|
|
|
5421
5825
|
}
|
|
5422
5826
|
reactDom.flushSync(apply);
|
|
5423
5827
|
}
|
|
5424
|
-
var ChatThemeContext =
|
|
5828
|
+
var ChatThemeContext = React3.createContext(null);
|
|
5425
5829
|
var ChatThemeProvider = ({
|
|
5426
5830
|
children,
|
|
5427
5831
|
themeColor,
|
|
@@ -5431,10 +5835,10 @@ var ChatThemeProvider = ({
|
|
|
5431
5835
|
showColorModeToggle = true
|
|
5432
5836
|
}) => {
|
|
5433
5837
|
const isControlled = colorMode !== void 0;
|
|
5434
|
-
const [internalMode, setInternalMode] =
|
|
5435
|
-
const [isThemeTransitionReady, setIsThemeTransitionReady] =
|
|
5436
|
-
const skipThemeTransitionRef =
|
|
5437
|
-
|
|
5838
|
+
const [internalMode, setInternalMode] = React3.useState(defaultColorMode);
|
|
5839
|
+
const [isThemeTransitionReady, setIsThemeTransitionReady] = React3.useState(false);
|
|
5840
|
+
const skipThemeTransitionRef = React3.useRef(true);
|
|
5841
|
+
React3.useLayoutEffect(() => {
|
|
5438
5842
|
if (!isControlled) {
|
|
5439
5843
|
const stored = loadChatColorMode();
|
|
5440
5844
|
if (stored) {
|
|
@@ -5449,7 +5853,7 @@ var ChatThemeProvider = ({
|
|
|
5449
5853
|
}, [isControlled]);
|
|
5450
5854
|
const resolvedMode = isControlled ? colorMode : internalMode;
|
|
5451
5855
|
const isDark = resolvedMode === "dark";
|
|
5452
|
-
const setColorMode =
|
|
5856
|
+
const setColorMode = React3.useCallback(
|
|
5453
5857
|
(mode) => {
|
|
5454
5858
|
const apply = () => {
|
|
5455
5859
|
if (!isControlled) {
|
|
@@ -5466,10 +5870,10 @@ var ChatThemeProvider = ({
|
|
|
5466
5870
|
},
|
|
5467
5871
|
[isControlled, onColorModeChange]
|
|
5468
5872
|
);
|
|
5469
|
-
const toggleColorMode =
|
|
5873
|
+
const toggleColorMode = React3.useCallback(() => {
|
|
5470
5874
|
setColorMode(resolvedMode === "dark" ? "light" : "dark");
|
|
5471
5875
|
}, [resolvedMode, setColorMode]);
|
|
5472
|
-
const value =
|
|
5876
|
+
const value = React3.useMemo(
|
|
5473
5877
|
() => ({
|
|
5474
5878
|
colorMode: resolvedMode,
|
|
5475
5879
|
isDark,
|
|
@@ -5497,7 +5901,7 @@ var ChatThemeProvider = ({
|
|
|
5497
5901
|
return /* @__PURE__ */ jsxRuntime.jsx(ChatThemeContext.Provider, { value, children });
|
|
5498
5902
|
};
|
|
5499
5903
|
var useChatTheme = () => {
|
|
5500
|
-
const context =
|
|
5904
|
+
const context = React3.useContext(ChatThemeContext);
|
|
5501
5905
|
if (!context) {
|
|
5502
5906
|
throw new Error("useChatTheme must be used within ChatThemeProvider");
|
|
5503
5907
|
}
|
|
@@ -5639,6 +6043,18 @@ function formatMemberName(name) {
|
|
|
5639
6043
|
function formatLoggedUserName(name) {
|
|
5640
6044
|
return name ? name.charAt(0).toUpperCase() + name.slice(1) : "User";
|
|
5641
6045
|
}
|
|
6046
|
+
|
|
6047
|
+
// src/chat/sidebar/build-logged-user-profile.ts
|
|
6048
|
+
var buildLoggedUserProfile = (loggedUserDetails) => ({
|
|
6049
|
+
_id: loggedUserDetails?._id || "1",
|
|
6050
|
+
name: formatLoggedUserName(loggedUserDetails?.name),
|
|
6051
|
+
email: loggedUserDetails?.email || "user@example.com",
|
|
6052
|
+
role: loggedUserDetails?.role || "user",
|
|
6053
|
+
isActive: loggedUserDetails?.isActive ?? true,
|
|
6054
|
+
createdAt: loggedUserDetails?.createdAt ? new Date(loggedUserDetails.createdAt) : /* @__PURE__ */ new Date(),
|
|
6055
|
+
updatedAt: loggedUserDetails?.updatedAt ? new Date(loggedUserDetails.updatedAt) : /* @__PURE__ */ new Date(),
|
|
6056
|
+
image: loggedUserDetails?.image || void 0
|
|
6057
|
+
});
|
|
5642
6058
|
function Dialog({
|
|
5643
6059
|
...props
|
|
5644
6060
|
}) {
|
|
@@ -6030,7 +6446,7 @@ function useCreateChatDialog({
|
|
|
6030
6446
|
onUserSelect,
|
|
6031
6447
|
setIsCreateModalOpen
|
|
6032
6448
|
}) {
|
|
6033
|
-
const [state, setState] =
|
|
6449
|
+
const [state, setState] = React3.useState(initialState);
|
|
6034
6450
|
const updateState = (updates) => {
|
|
6035
6451
|
setState((prev) => ({ ...prev, ...updates }));
|
|
6036
6452
|
};
|
|
@@ -6039,8 +6455,10 @@ function useCreateChatDialog({
|
|
|
6039
6455
|
const fetchAllUsers = exports.useChatStore((storeState) => storeState.fetchAllUsers);
|
|
6040
6456
|
const accessToken = exports.useChatStore((storeState) => storeState.accessToken);
|
|
6041
6457
|
const fetchConversations2 = exports.useChatStore((storeState) => storeState.fetchConversations);
|
|
6042
|
-
const
|
|
6043
|
-
|
|
6458
|
+
const { settings } = useEffectiveSettingsOptional();
|
|
6459
|
+
const maxParticipants = settings.maxParticipantsPerGroup;
|
|
6460
|
+
const fileInputRef = React3.useRef(null);
|
|
6461
|
+
React3.useEffect(() => {
|
|
6044
6462
|
if (accessToken) {
|
|
6045
6463
|
fetchAllUsers();
|
|
6046
6464
|
}
|
|
@@ -6052,9 +6470,18 @@ function useCreateChatDialog({
|
|
|
6052
6470
|
setState((prev) => {
|
|
6053
6471
|
const memberId = String(member._id);
|
|
6054
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
|
+
}
|
|
6055
6482
|
return {
|
|
6056
6483
|
...prev,
|
|
6057
|
-
selectedMembers:
|
|
6484
|
+
selectedMembers: [...prev.selectedMembers, member]
|
|
6058
6485
|
};
|
|
6059
6486
|
});
|
|
6060
6487
|
};
|
|
@@ -6438,8 +6865,25 @@ function GroupCreateTab({
|
|
|
6438
6865
|
) })
|
|
6439
6866
|
] });
|
|
6440
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
|
+
}
|
|
6441
6883
|
var CreateChatDialog = (props) => {
|
|
6442
6884
|
const { isCreateModalOpen = false, setIsCreateModalOpen } = props;
|
|
6885
|
+
const { getGroupCreationGate } = useEffectiveSettingsOptional();
|
|
6886
|
+
const groupCreationGate = getGroupCreationGate();
|
|
6443
6887
|
const {
|
|
6444
6888
|
state,
|
|
6445
6889
|
updateState,
|
|
@@ -6493,24 +6937,39 @@ var CreateChatDialog = (props) => {
|
|
|
6493
6937
|
) })
|
|
6494
6938
|
] }),
|
|
6495
6939
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid shrink-0 grid-cols-2 gap-2 px-5", children: [
|
|
6496
|
-
{ id: "dm", label: "Message", icon: lucideReact.MessageCircle },
|
|
6497
|
-
{ id: "group", label: "New group", icon: lucideReact.Users }
|
|
6498
|
-
].map(({ id, label, icon: Icon }) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6499
|
-
"button",
|
|
6940
|
+
{ id: "dm", label: "Message", icon: lucideReact.MessageCircle, disabled: false, reason: null },
|
|
6500
6941
|
{
|
|
6501
|
-
|
|
6502
|
-
|
|
6503
|
-
|
|
6504
|
-
|
|
6505
|
-
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
|
|
6509
|
-
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
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
|
+
}) }),
|
|
6514
6973
|
state.activeTab === "dm" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6515
6974
|
DmContactsTab,
|
|
6516
6975
|
{
|
|
@@ -6521,7 +6980,7 @@ var CreateChatDialog = (props) => {
|
|
|
6521
6980
|
onStartDM: handleStartDM
|
|
6522
6981
|
}
|
|
6523
6982
|
),
|
|
6524
|
-
state.activeTab === "group" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6983
|
+
state.activeTab === "group" && groupCreationGate.enabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6525
6984
|
GroupCreateTab,
|
|
6526
6985
|
{
|
|
6527
6986
|
state,
|
|
@@ -6573,6 +7032,7 @@ function Switch({
|
|
|
6573
7032
|
|
|
6574
7033
|
// src/notifications/push.service.ts
|
|
6575
7034
|
init_client();
|
|
7035
|
+
init_api_version();
|
|
6576
7036
|
var PUSH_TOKEN_STORAGE_KEY = "realtimex-push-token";
|
|
6577
7037
|
var SERVICE_WORKER_PATH = "/firebase-messaging-sw.js";
|
|
6578
7038
|
var PUSH_CHANGED_EVENT = "realtimex:push-changed";
|
|
@@ -6584,33 +7044,33 @@ var emitPushChanged = (enabled) => {
|
|
|
6584
7044
|
} catch {
|
|
6585
7045
|
}
|
|
6586
7046
|
};
|
|
6587
|
-
var
|
|
7047
|
+
var pushApiUrl = (path) => exports.buildVersionedApiUrl(path, { service: "v2" });
|
|
6588
7048
|
var apiGetPushConfig = async () => {
|
|
6589
|
-
const { data } = await apiClient.get(
|
|
7049
|
+
const { data } = await apiClient.get(pushApiUrl("/notifications/push/config"));
|
|
6590
7050
|
return data?.data;
|
|
6591
7051
|
};
|
|
6592
7052
|
var apiRegisterPushToken = async (token, deviceLabel) => {
|
|
6593
|
-
const { data } = await apiClient.post(
|
|
7053
|
+
const { data } = await apiClient.post(pushApiUrl("/notifications/push/token"), {
|
|
6594
7054
|
token,
|
|
6595
7055
|
deviceLabel
|
|
6596
7056
|
});
|
|
6597
7057
|
return data?.data;
|
|
6598
7058
|
};
|
|
6599
7059
|
var apiRemovePushToken = async (token) => {
|
|
6600
|
-
const { data } = await apiClient.delete(
|
|
7060
|
+
const { data } = await apiClient.delete(pushApiUrl("/notifications/push/token"), {
|
|
6601
7061
|
data: { token }
|
|
6602
7062
|
});
|
|
6603
7063
|
return data;
|
|
6604
7064
|
};
|
|
6605
7065
|
var apiGetPushPreference = async () => {
|
|
6606
7066
|
const { data } = await apiClient.get(
|
|
6607
|
-
|
|
7067
|
+
pushApiUrl("/notifications/push/preference")
|
|
6608
7068
|
);
|
|
6609
7069
|
return data?.data;
|
|
6610
7070
|
};
|
|
6611
7071
|
var apiUpdatePushPreference = async (enabled) => {
|
|
6612
7072
|
const { data } = await apiClient.patch(
|
|
6613
|
-
|
|
7073
|
+
pushApiUrl("/notifications/push/preference"),
|
|
6614
7074
|
{ enabled }
|
|
6615
7075
|
);
|
|
6616
7076
|
return data?.data;
|
|
@@ -6733,7 +7193,7 @@ var onForegroundPush = async (callback) => {
|
|
|
6733
7193
|
|
|
6734
7194
|
// src/notifications/usePushNotifications.ts
|
|
6735
7195
|
var usePushNotifications = () => {
|
|
6736
|
-
const [state, setState] =
|
|
7196
|
+
const [state, setState] = React3.useState({
|
|
6737
7197
|
supported: false,
|
|
6738
7198
|
allowedByWorkspace: false,
|
|
6739
7199
|
configured: false,
|
|
@@ -6743,7 +7203,7 @@ var usePushNotifications = () => {
|
|
|
6743
7203
|
loading: true,
|
|
6744
7204
|
error: null
|
|
6745
7205
|
});
|
|
6746
|
-
const refresh =
|
|
7206
|
+
const refresh = React3.useCallback(async () => {
|
|
6747
7207
|
if (!isPushSupported()) {
|
|
6748
7208
|
setState((prev) => ({
|
|
6749
7209
|
...prev,
|
|
@@ -6776,10 +7236,10 @@ var usePushNotifications = () => {
|
|
|
6776
7236
|
}));
|
|
6777
7237
|
}
|
|
6778
7238
|
}, []);
|
|
6779
|
-
|
|
7239
|
+
React3.useEffect(() => {
|
|
6780
7240
|
void refresh();
|
|
6781
7241
|
}, [refresh]);
|
|
6782
|
-
const enable =
|
|
7242
|
+
const enable = React3.useCallback(async () => {
|
|
6783
7243
|
setState((prev) => ({ ...prev, loading: true, error: null }));
|
|
6784
7244
|
try {
|
|
6785
7245
|
await enablePushOnThisDevice();
|
|
@@ -6795,7 +7255,7 @@ var usePushNotifications = () => {
|
|
|
6795
7255
|
return false;
|
|
6796
7256
|
}
|
|
6797
7257
|
}, [refresh]);
|
|
6798
|
-
const disable =
|
|
7258
|
+
const disable = React3.useCallback(async () => {
|
|
6799
7259
|
setState((prev) => ({ ...prev, loading: true, error: null }));
|
|
6800
7260
|
try {
|
|
6801
7261
|
await disablePushOnThisDevice();
|
|
@@ -6803,15 +7263,17 @@ var usePushNotifications = () => {
|
|
|
6803
7263
|
await refresh();
|
|
6804
7264
|
}
|
|
6805
7265
|
}, [refresh]);
|
|
6806
|
-
const setUserEnabled =
|
|
7266
|
+
const setUserEnabled = React3.useCallback(
|
|
6807
7267
|
async (enabled) => {
|
|
6808
|
-
setState((prev) => ({ ...prev,
|
|
7268
|
+
setState((prev) => ({ ...prev, loading: true, error: null }));
|
|
6809
7269
|
try {
|
|
6810
7270
|
await apiUpdatePushPreference(enabled);
|
|
7271
|
+
setState((prev) => ({ ...prev, userEnabled: enabled, loading: false }));
|
|
6811
7272
|
} catch (error) {
|
|
6812
7273
|
setState((prev) => ({
|
|
6813
7274
|
...prev,
|
|
6814
7275
|
userEnabled: !enabled,
|
|
7276
|
+
loading: false,
|
|
6815
7277
|
error: error instanceof Error ? error.message : "Could not update push preference"
|
|
6816
7278
|
}));
|
|
6817
7279
|
}
|
|
@@ -6823,95 +7285,229 @@ var usePushNotifications = () => {
|
|
|
6823
7285
|
var PushNotificationToggle = ({
|
|
6824
7286
|
className,
|
|
6825
7287
|
label = "Push notifications",
|
|
6826
|
-
description = "Get notified about new messages on this device"
|
|
7288
|
+
description = "Get notified about new messages on this device",
|
|
7289
|
+
children
|
|
6827
7290
|
}) => {
|
|
6828
7291
|
const push = usePushNotifications();
|
|
6829
|
-
|
|
7292
|
+
const { getPushNotificationGate } = useEffectiveSettingsOptional();
|
|
7293
|
+
const adminGate = getPushNotificationGate();
|
|
7294
|
+
const [isToggling, setIsToggling] = React3.useState(false);
|
|
7295
|
+
if (!push.supported) {
|
|
6830
7296
|
return null;
|
|
6831
7297
|
}
|
|
6832
7298
|
const isOn = push.deviceEnabled && push.userEnabled;
|
|
6833
7299
|
const permissionBlocked = push.permission === "denied";
|
|
7300
|
+
const adminBlocked = !adminGate.enabled;
|
|
7301
|
+
const notConfigured = !push.configured;
|
|
7302
|
+
const showLoader = isToggling;
|
|
7303
|
+
const isDisabled = showLoader || permissionBlocked || push.loading || adminBlocked || notConfigured;
|
|
6834
7304
|
const handleChange = async (checked) => {
|
|
6835
|
-
if (
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
7305
|
+
if (adminBlocked || notConfigured) return;
|
|
7306
|
+
setIsToggling(true);
|
|
7307
|
+
try {
|
|
7308
|
+
if (checked) {
|
|
7309
|
+
if (!push.userEnabled) await push.setUserEnabled(true);
|
|
7310
|
+
if (!push.deviceEnabled) await push.enable();
|
|
7311
|
+
} else {
|
|
7312
|
+
await push.disable();
|
|
7313
|
+
}
|
|
7314
|
+
} finally {
|
|
7315
|
+
setIsToggling(false);
|
|
6840
7316
|
}
|
|
6841
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;
|
|
7319
|
+
const renderProps = {
|
|
7320
|
+
label,
|
|
7321
|
+
description: descriptionText,
|
|
7322
|
+
checked: adminBlocked || notConfigured ? false : isOn,
|
|
7323
|
+
disabled: isDisabled,
|
|
7324
|
+
loading: showLoader || push.loading,
|
|
7325
|
+
permissionBlocked,
|
|
7326
|
+
error: push.error,
|
|
7327
|
+
onCheckedChange: (checked) => void handleChange(checked)
|
|
7328
|
+
};
|
|
7329
|
+
if (children) {
|
|
7330
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children(renderProps) });
|
|
7331
|
+
}
|
|
6842
7332
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6843
7333
|
"div",
|
|
6844
7334
|
{
|
|
6845
|
-
className:
|
|
7335
|
+
className: cn(
|
|
7336
|
+
"flex items-center justify-between gap-4 rounded-xl border border-(--chat-border) bg-(--chat-surface) px-4 py-3",
|
|
7337
|
+
className
|
|
7338
|
+
),
|
|
6846
7339
|
children: [
|
|
6847
7340
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
|
|
6848
7341
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-(--chat-text)", children: label }),
|
|
6849
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-(--chat-muted)", children:
|
|
7342
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-(--chat-muted)", children: renderProps.description })
|
|
6850
7343
|
] }),
|
|
6851
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6852
|
-
|
|
7344
|
+
showLoader ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
7345
|
+
lucideReact.Loader2,
|
|
6853
7346
|
{
|
|
6854
|
-
|
|
6855
|
-
|
|
6856
|
-
|
|
6857
|
-
|
|
7347
|
+
className: "size-5 shrink-0 animate-spin text-(--chat-theme)",
|
|
7348
|
+
"aria-label": "Updating push notifications"
|
|
7349
|
+
}
|
|
7350
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
7351
|
+
AdminPermissionTooltip,
|
|
7352
|
+
{
|
|
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
|
+
)
|
|
6858
7364
|
}
|
|
6859
7365
|
)
|
|
6860
7366
|
]
|
|
6861
7367
|
}
|
|
6862
7368
|
);
|
|
6863
7369
|
};
|
|
6864
|
-
var
|
|
6865
|
-
|
|
7370
|
+
var LoggedUserSettingsContent = ({
|
|
7371
|
+
user,
|
|
7372
|
+
title = "Account settings",
|
|
7373
|
+
showProfile = true,
|
|
7374
|
+
showPushToggle = true,
|
|
7375
|
+
className
|
|
6866
7376
|
}) => {
|
|
6867
|
-
const
|
|
6868
|
-
const
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
"
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
7377
|
+
const { resolveComponent, slotClassName } = useChatCustomization();
|
|
7378
|
+
const PushToggleSlot = resolveComponent(
|
|
7379
|
+
"PushNotificationToggle",
|
|
7380
|
+
PushNotificationToggle
|
|
7381
|
+
);
|
|
7382
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7383
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7384
|
+
"div",
|
|
7385
|
+
{
|
|
7386
|
+
className: cn(
|
|
7387
|
+
"border-b border-(--chat-border) px-5 py-4",
|
|
7388
|
+
slotClassName("loggedUserSettingsHeader")
|
|
7389
|
+
),
|
|
7390
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { className: "text-left text-base font-semibold text-(--chat-text)", children: title })
|
|
7391
|
+
}
|
|
7392
|
+
),
|
|
7393
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7394
|
+
"div",
|
|
7395
|
+
{
|
|
7396
|
+
className: cn(
|
|
7397
|
+
"space-y-5 px-5 py-5",
|
|
7398
|
+
slotClassName("loggedUserSettingsContent", className)
|
|
7399
|
+
),
|
|
7400
|
+
children: [
|
|
7401
|
+
showProfile ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center text-center", children: [
|
|
7402
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
7403
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7404
|
+
Avatar,
|
|
7405
|
+
{
|
|
7406
|
+
className: cn(
|
|
7407
|
+
"size-16 ring-2 ring-(--chat-theme-20)",
|
|
7408
|
+
slotClassName("loggedUserSettingsAvatar")
|
|
7409
|
+
),
|
|
7410
|
+
children: [
|
|
7411
|
+
user.image ? /* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: user.image, alt: user.name }) : null,
|
|
7412
|
+
/* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { className: "bg-(--chat-theme-10) text-lg font-medium text-(--chat-theme)", children: (user.name || "?").charAt(0).toUpperCase() })
|
|
7413
|
+
]
|
|
7414
|
+
}
|
|
7415
|
+
),
|
|
7416
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute bottom-0.5 right-0.5 size-3 rounded-full border-2 border-(--chat-surface) bg-(--chat-online)" })
|
|
6902
7417
|
] }),
|
|
6903
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
|
|
6910
|
-
|
|
6911
|
-
|
|
6912
|
-
|
|
6913
|
-
|
|
6914
|
-
|
|
7418
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mt-3 text-base font-semibold text-(--chat-text)", children: user.name }),
|
|
7419
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 text-sm text-(--chat-muted)", children: user.email }),
|
|
7420
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-2 inline-flex items-center gap-1.5 rounded-full bg-(--chat-theme-10) px-2.5 py-0.5 text-xs font-medium text-(--chat-theme)", children: [
|
|
7421
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "size-1.5 rounded-full bg-(--chat-online)" }),
|
|
7422
|
+
"Online"
|
|
7423
|
+
] })
|
|
7424
|
+
] }) : null,
|
|
7425
|
+
showPushToggle ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-(--chat-border) pt-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7426
|
+
PushToggleSlot,
|
|
7427
|
+
{
|
|
7428
|
+
className: cn(
|
|
7429
|
+
"flex items-center justify-between gap-4 rounded-xl border border-(--chat-border) bg-(--chat-theme-10) px-4 py-3",
|
|
7430
|
+
slotClassName("pushNotificationToggle")
|
|
7431
|
+
)
|
|
7432
|
+
}
|
|
7433
|
+
) }) : null
|
|
7434
|
+
]
|
|
7435
|
+
}
|
|
7436
|
+
)
|
|
7437
|
+
] });
|
|
7438
|
+
};
|
|
7439
|
+
var LoggedUserSettingsContent_default = LoggedUserSettingsContent;
|
|
7440
|
+
var LoggedUserSettingsTrigger = ({
|
|
7441
|
+
onClick,
|
|
7442
|
+
className,
|
|
7443
|
+
tooltip = "Settings",
|
|
7444
|
+
ariaLabel = "Account settings"
|
|
7445
|
+
}) => {
|
|
7446
|
+
const { slotClassName } = useChatCustomization();
|
|
7447
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
|
|
7448
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7449
|
+
Button,
|
|
7450
|
+
{
|
|
7451
|
+
type: "button",
|
|
7452
|
+
variant: "ghost",
|
|
7453
|
+
size: "icon",
|
|
7454
|
+
className: cn(
|
|
7455
|
+
sidebarActionBtnClass,
|
|
7456
|
+
slotClassName("loggedUserSettingsTrigger", className)
|
|
7457
|
+
),
|
|
7458
|
+
"aria-label": ariaLabel,
|
|
7459
|
+
onClick,
|
|
7460
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings, { className: "size-3.5", strokeWidth: 2 })
|
|
7461
|
+
}
|
|
7462
|
+
) }),
|
|
7463
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "bottom", children: tooltip })
|
|
7464
|
+
] });
|
|
7465
|
+
};
|
|
7466
|
+
var LoggedUserSettingsTrigger_default = LoggedUserSettingsTrigger;
|
|
7467
|
+
var LoggedUserSettingsDialog = ({
|
|
7468
|
+
loggedUserDetails,
|
|
7469
|
+
open: controlledOpen,
|
|
7470
|
+
onOpenChange: controlledOnOpenChange,
|
|
7471
|
+
title,
|
|
7472
|
+
showProfile = true,
|
|
7473
|
+
showPushToggle = true,
|
|
7474
|
+
className
|
|
7475
|
+
}) => {
|
|
7476
|
+
const { resolveComponent, slotClassName } = useChatCustomization();
|
|
7477
|
+
const [internalOpen, setInternalOpen] = React3.useState(false);
|
|
7478
|
+
const open = controlledOpen ?? internalOpen;
|
|
7479
|
+
const onOpenChange = controlledOnOpenChange ?? setInternalOpen;
|
|
7480
|
+
const TriggerSlot = resolveComponent(
|
|
7481
|
+
"LoggedUserSettingsTrigger",
|
|
7482
|
+
LoggedUserSettingsTrigger_default
|
|
7483
|
+
);
|
|
7484
|
+
const ContentSlot = resolveComponent(
|
|
7485
|
+
"LoggedUserSettingsContent",
|
|
7486
|
+
LoggedUserSettingsContent_default
|
|
7487
|
+
);
|
|
7488
|
+
const user = buildLoggedUserProfile(loggedUserDetails);
|
|
7489
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Dialog, { open, onOpenChange, children: [
|
|
7490
|
+
/* @__PURE__ */ jsxRuntime.jsx(TriggerSlot, { onClick: () => onOpenChange(true) }),
|
|
7491
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7492
|
+
ChatDialogContent,
|
|
7493
|
+
{
|
|
7494
|
+
className: cn(
|
|
7495
|
+
"gap-0 overflow-hidden p-0 sm:max-w-[380px]",
|
|
7496
|
+
slotClassName("loggedUserSettingsDialog", className)
|
|
7497
|
+
),
|
|
7498
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7499
|
+
ContentSlot,
|
|
7500
|
+
{
|
|
7501
|
+
loggedUserDetails,
|
|
7502
|
+
user,
|
|
7503
|
+
onClose: () => onOpenChange(false),
|
|
7504
|
+
title,
|
|
7505
|
+
showProfile,
|
|
7506
|
+
showPushToggle
|
|
7507
|
+
}
|
|
7508
|
+
)
|
|
7509
|
+
}
|
|
7510
|
+
)
|
|
6915
7511
|
] });
|
|
6916
7512
|
};
|
|
6917
7513
|
var LoggedUserSettingsDialog_default = LoggedUserSettingsDialog;
|
|
@@ -6924,16 +7520,12 @@ var LoggedUserDetails = ({
|
|
|
6924
7520
|
setSearchQuery
|
|
6925
7521
|
}) => {
|
|
6926
7522
|
const { showColorModeToggle } = useChatTheme();
|
|
6927
|
-
const
|
|
6928
|
-
|
|
6929
|
-
|
|
6930
|
-
|
|
6931
|
-
|
|
6932
|
-
|
|
6933
|
-
createdAt: loggedUserDetails?.createdAt ? new Date(loggedUserDetails.createdAt) : /* @__PURE__ */ new Date(),
|
|
6934
|
-
updatedAt: loggedUserDetails?.updatedAt ? new Date(loggedUserDetails.updatedAt) : /* @__PURE__ */ new Date(),
|
|
6935
|
-
image: loggedUserDetails?.image || void 0
|
|
6936
|
-
};
|
|
7523
|
+
const { resolveComponent } = useChatCustomization();
|
|
7524
|
+
const SettingsDialogSlot = resolveComponent(
|
|
7525
|
+
"LoggedUserSettingsDialog",
|
|
7526
|
+
LoggedUserSettingsDialog_default
|
|
7527
|
+
);
|
|
7528
|
+
const user = buildLoggedUserProfile(loggedUserDetails);
|
|
6937
7529
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 border-b border-(--chat-border) bg-(--chat-surface) px-3 pb-3 pt-3", children: [
|
|
6938
7530
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-center gap-2.5", children: [
|
|
6939
7531
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative shrink-0", children: [
|
|
@@ -6944,14 +7536,11 @@ var LoggedUserDetails = ({
|
|
|
6944
7536
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -bottom-0.5 -right-0.5 size-2 rounded-full border-2 border-(--chat-surface) bg-(--chat-online)" })
|
|
6945
7537
|
] }),
|
|
6946
7538
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
6947
|
-
/* @__PURE__ */ jsxRuntime.
|
|
6948
|
-
user.name,
|
|
6949
|
-
"123"
|
|
6950
|
-
] }),
|
|
7539
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "truncate text-xs font-medium leading-tight text-(--chat-text)", children: user.name }),
|
|
6951
7540
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-[10px] text-(--chat-muted)", children: user.email })
|
|
6952
7541
|
] }),
|
|
6953
7542
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-0.5", children: [
|
|
6954
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7543
|
+
/* @__PURE__ */ jsxRuntime.jsx(SettingsDialogSlot, { loggedUserDetails }),
|
|
6955
7544
|
showColorModeToggle ? /* @__PURE__ */ jsxRuntime.jsx(ChatThemeToggle_default, {}) : null
|
|
6956
7545
|
] })
|
|
6957
7546
|
] }),
|
|
@@ -7073,7 +7662,7 @@ function getDraftRevision() {
|
|
|
7073
7662
|
return draftRevision;
|
|
7074
7663
|
}
|
|
7075
7664
|
function useDraftRevision() {
|
|
7076
|
-
return
|
|
7665
|
+
return React3.useSyncExternalStore(subscribeToDrafts, getDraftRevision, getDraftRevision);
|
|
7077
7666
|
}
|
|
7078
7667
|
function getConversationDraft(conversationId) {
|
|
7079
7668
|
if (!conversationId) return emptyDraft();
|
|
@@ -7111,11 +7700,11 @@ function getConversationDraftPreview(conversationId) {
|
|
|
7111
7700
|
return null;
|
|
7112
7701
|
}
|
|
7113
7702
|
function useConversationDraft(conversationId) {
|
|
7114
|
-
const composerRef =
|
|
7115
|
-
const syncComposerRef =
|
|
7703
|
+
const composerRef = React3.useRef(emptyDraft());
|
|
7704
|
+
const syncComposerRef = React3.useCallback((draft) => {
|
|
7116
7705
|
composerRef.current = draft;
|
|
7117
7706
|
}, []);
|
|
7118
|
-
|
|
7707
|
+
React3.useEffect(() => {
|
|
7119
7708
|
const id = conversationId;
|
|
7120
7709
|
return () => {
|
|
7121
7710
|
if (!id) return;
|
|
@@ -7334,7 +7923,7 @@ var saveChatDateTimePreferences = (prefs) => {
|
|
|
7334
7923
|
} catch {
|
|
7335
7924
|
}
|
|
7336
7925
|
};
|
|
7337
|
-
var ChatLocaleContext =
|
|
7926
|
+
var ChatLocaleContext = React3.createContext(null);
|
|
7338
7927
|
var resolveInitialPrefs = (defaults) => {
|
|
7339
7928
|
const stored = loadChatDateTimePreferences();
|
|
7340
7929
|
const fallback = resolveStoredPrefs(defaults);
|
|
@@ -7361,7 +7950,7 @@ var ChatLocaleProvider = ({
|
|
|
7361
7950
|
const localeControlled = controlledLocale !== void 0;
|
|
7362
7951
|
const timeZoneControlled = controlledTimeZone !== void 0;
|
|
7363
7952
|
const hour12Controlled = controlledHour12 !== void 0;
|
|
7364
|
-
const [internalPrefs, setInternalPrefs] =
|
|
7953
|
+
const [internalPrefs, setInternalPrefs] = React3.useState(
|
|
7365
7954
|
() => resolveInitialPrefs({
|
|
7366
7955
|
locale: defaultLocale,
|
|
7367
7956
|
timeZone: defaultTimeZone,
|
|
@@ -7371,7 +7960,7 @@ var ChatLocaleProvider = ({
|
|
|
7371
7960
|
const resolvedLocale = localeControlled ? controlledLocale : internalPrefs.locale;
|
|
7372
7961
|
const resolvedTimeZone = timeZoneControlled ? controlledTimeZone : internalPrefs.timeZone;
|
|
7373
7962
|
const resolvedHour12 = hour12Controlled ? controlledHour12 ?? getDefaultHour12() : internalPrefs.hour12 ?? getDefaultHour12();
|
|
7374
|
-
const updatePrefs =
|
|
7963
|
+
const updatePrefs = React3.useCallback(
|
|
7375
7964
|
(updates) => {
|
|
7376
7965
|
const next = {
|
|
7377
7966
|
locale: updates.locale !== void 0 ? updates.locale : resolvedLocale,
|
|
@@ -7400,19 +7989,19 @@ var ChatLocaleProvider = ({
|
|
|
7400
7989
|
onDateTimePreferencesChange
|
|
7401
7990
|
]
|
|
7402
7991
|
);
|
|
7403
|
-
const setLocale =
|
|
7992
|
+
const setLocale = React3.useCallback(
|
|
7404
7993
|
(locale) => updatePrefs({ locale }),
|
|
7405
7994
|
[updatePrefs]
|
|
7406
7995
|
);
|
|
7407
|
-
const setTimeZone =
|
|
7996
|
+
const setTimeZone = React3.useCallback(
|
|
7408
7997
|
(timeZone) => updatePrefs({ timeZone }),
|
|
7409
7998
|
[updatePrefs]
|
|
7410
7999
|
);
|
|
7411
|
-
const setHour12 =
|
|
8000
|
+
const setHour12 = React3.useCallback(
|
|
7412
8001
|
(hour12) => updatePrefs({ hour12 }),
|
|
7413
8002
|
[updatePrefs]
|
|
7414
8003
|
);
|
|
7415
|
-
const prefs =
|
|
8004
|
+
const prefs = React3.useMemo(
|
|
7416
8005
|
() => ({
|
|
7417
8006
|
locale: resolvedLocale,
|
|
7418
8007
|
timeZone: resolvedTimeZone,
|
|
@@ -7420,8 +8009,8 @@ var ChatLocaleProvider = ({
|
|
|
7420
8009
|
}),
|
|
7421
8010
|
[resolvedLocale, resolvedTimeZone, resolvedHour12]
|
|
7422
8011
|
);
|
|
7423
|
-
const formatters =
|
|
7424
|
-
const value =
|
|
8012
|
+
const formatters = React3.useMemo(() => createChatDateTimeFormatters(prefs), [prefs]);
|
|
8013
|
+
const value = React3.useMemo(
|
|
7425
8014
|
() => ({
|
|
7426
8015
|
...formatters,
|
|
7427
8016
|
locale: resolvedLocale,
|
|
@@ -7446,7 +8035,7 @@ var ChatLocaleProvider = ({
|
|
|
7446
8035
|
return /* @__PURE__ */ jsxRuntime.jsx(ChatLocaleContext.Provider, { value, children });
|
|
7447
8036
|
};
|
|
7448
8037
|
var useChatLocale = () => {
|
|
7449
|
-
const context =
|
|
8038
|
+
const context = React3.useContext(ChatLocaleContext);
|
|
7450
8039
|
if (!context) {
|
|
7451
8040
|
throw new Error("useChatLocale must be used within ChatLocaleProvider");
|
|
7452
8041
|
}
|
|
@@ -7568,15 +8157,15 @@ function useChannelList({ debouncedSearch = "" }) {
|
|
|
7568
8157
|
const conversationsPage = exports.useChatStore((s) => s.conversationsPage);
|
|
7569
8158
|
const accessToken = exports.useChatStore((s) => s.accessToken);
|
|
7570
8159
|
const loggedUserDetails = exports.useChatStore((s) => s.loggedUserDetails);
|
|
7571
|
-
const lastFetchKeyRef =
|
|
8160
|
+
const lastFetchKeyRef = React3.useRef(null);
|
|
7572
8161
|
useDraftRevision();
|
|
7573
8162
|
const { formatSidebarTime } = useChatLocale();
|
|
7574
|
-
|
|
8163
|
+
React3.useEffect(() => {
|
|
7575
8164
|
if (accessToken) {
|
|
7576
8165
|
exports.useChatStore.getState().fetchAllUsers();
|
|
7577
8166
|
}
|
|
7578
8167
|
}, [accessToken]);
|
|
7579
|
-
|
|
8168
|
+
React3.useEffect(() => {
|
|
7580
8169
|
if (!accessToken) return;
|
|
7581
8170
|
const fetchKey = debouncedSearch;
|
|
7582
8171
|
if (lastFetchKeyRef.current === fetchKey) return;
|
|
@@ -7588,7 +8177,7 @@ function useChannelList({ debouncedSearch = "" }) {
|
|
|
7588
8177
|
}
|
|
7589
8178
|
fetchConversations2(DEFAULT_CONVERSATIONS_LIMIT, 1, debouncedSearch, true);
|
|
7590
8179
|
}, [accessToken, debouncedSearch]);
|
|
7591
|
-
const mappedChannels =
|
|
8180
|
+
const mappedChannels = React3.useMemo(() => {
|
|
7592
8181
|
const safeConversations = Array.isArray(conversations) ? conversations : [];
|
|
7593
8182
|
const seenConversationIds = /* @__PURE__ */ new Set();
|
|
7594
8183
|
return safeConversations.map((c) => {
|
|
@@ -8192,7 +8781,7 @@ function highlightSearchMatch(text, query) {
|
|
|
8192
8781
|
children: part
|
|
8193
8782
|
},
|
|
8194
8783
|
`${part}-${index}`
|
|
8195
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
8784
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(React3__namespace.default.Fragment, { children: part }, `${part}-${index}`)
|
|
8196
8785
|
);
|
|
8197
8786
|
}
|
|
8198
8787
|
function getMessagePreview(message) {
|
|
@@ -8239,14 +8828,14 @@ var HeaderSearchPopover = ({
|
|
|
8239
8828
|
}) => {
|
|
8240
8829
|
const { scopeClassName, themeStyles } = useChatTheme();
|
|
8241
8830
|
const { formatMessageTime, formatShortDate } = useChatLocale();
|
|
8242
|
-
const inputRef =
|
|
8243
|
-
|
|
8831
|
+
const inputRef = React3.useRef(null);
|
|
8832
|
+
React3.useEffect(() => {
|
|
8244
8833
|
if (!open) return;
|
|
8245
8834
|
const timer = window.setTimeout(() => inputRef.current?.focus(), 0);
|
|
8246
8835
|
return () => window.clearTimeout(timer);
|
|
8247
8836
|
}, [open]);
|
|
8248
8837
|
const showResults = searchQuery.trim().length > 0;
|
|
8249
|
-
const resultCountLabel =
|
|
8838
|
+
const resultCountLabel = React3.useMemo(() => {
|
|
8250
8839
|
if (!searchResults.length) return "0 results";
|
|
8251
8840
|
return `${searchResults.length}${hasMore ? "+" : ""} result${searchResults.length === 1 ? "" : "s"}`;
|
|
8252
8841
|
}, [hasMore, searchResults.length]);
|
|
@@ -8372,7 +8961,7 @@ var HeaderSearchPopover = ({
|
|
|
8372
8961
|
] });
|
|
8373
8962
|
};
|
|
8374
8963
|
var HeaderSearchPopover_default = HeaderSearchPopover;
|
|
8375
|
-
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";
|
|
8376
8965
|
var DefaultHeaderCallActions = ({
|
|
8377
8966
|
activeChannel,
|
|
8378
8967
|
conversationId,
|
|
@@ -8383,48 +8972,91 @@ var DefaultHeaderCallActions = ({
|
|
|
8383
8972
|
className
|
|
8384
8973
|
}) => {
|
|
8385
8974
|
const { components, slotClassName, features } = useChatCustomizationOptional();
|
|
8975
|
+
const { getAudioCallGate, getVideoCallGate } = useEffectiveSettingsOptional();
|
|
8386
8976
|
const PhoneSlot = components.PhoneCallButton;
|
|
8387
8977
|
const VideoSlot = components.VideoCallButton;
|
|
8388
8978
|
const hideInGroups = features.hideCallActionsInGroupChats ?? false;
|
|
8979
|
+
const audioGate = getAudioCallGate();
|
|
8980
|
+
const videoGate = getVideoCallGate();
|
|
8389
8981
|
if (hideInGroups && activeChannel.isGroup) return null;
|
|
8390
8982
|
if (!showPhoneCall && !showVideoCall) return null;
|
|
8983
|
+
const phoneEnabled = showPhoneCall && audioGate.enabled;
|
|
8984
|
+
const videoEnabled = showVideoCall && videoGate.enabled;
|
|
8391
8985
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8392
8986
|
showPhoneCall && (PhoneSlot ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8393
|
-
|
|
8987
|
+
AdminPermissionTooltip,
|
|
8394
8988
|
{
|
|
8395
|
-
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
|
|
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
|
+
) })
|
|
8399
9004
|
}
|
|
8400
9005
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
8401
|
-
|
|
9006
|
+
AdminPermissionTooltip,
|
|
8402
9007
|
{
|
|
8403
|
-
|
|
8404
|
-
|
|
8405
|
-
|
|
8406
|
-
|
|
8407
|
-
|
|
8408
|
-
|
|
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
|
+
)
|
|
8409
9022
|
}
|
|
8410
9023
|
)),
|
|
8411
9024
|
showVideoCall && (VideoSlot ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8412
|
-
|
|
9025
|
+
AdminPermissionTooltip,
|
|
8413
9026
|
{
|
|
8414
|
-
|
|
8415
|
-
|
|
8416
|
-
|
|
8417
|
-
|
|
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
|
+
) })
|
|
8418
9042
|
}
|
|
8419
9043
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
8420
|
-
|
|
9044
|
+
AdminPermissionTooltip,
|
|
8421
9045
|
{
|
|
8422
|
-
|
|
8423
|
-
|
|
8424
|
-
|
|
8425
|
-
|
|
8426
|
-
|
|
8427
|
-
|
|
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
|
+
)
|
|
8428
9060
|
}
|
|
8429
9061
|
))
|
|
8430
9062
|
] });
|
|
@@ -8446,19 +9078,38 @@ function OptionsMenuItem({
|
|
|
8446
9078
|
icon: Icon,
|
|
8447
9079
|
label,
|
|
8448
9080
|
onSelect,
|
|
8449
|
-
destructive = false
|
|
9081
|
+
destructive = false,
|
|
9082
|
+
disabled = false,
|
|
9083
|
+
disabledReason
|
|
8450
9084
|
}) {
|
|
8451
|
-
|
|
9085
|
+
const item = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8452
9086
|
DropdownMenuItem,
|
|
8453
9087
|
{
|
|
8454
|
-
className:
|
|
8455
|
-
|
|
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
|
+
},
|
|
8456
9100
|
children: [
|
|
8457
9101
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { strokeWidth: 1.75 }),
|
|
8458
9102
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: label })
|
|
8459
9103
|
]
|
|
8460
9104
|
}
|
|
8461
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
|
+
] });
|
|
8462
9113
|
}
|
|
8463
9114
|
var HeaderRightSide = ({
|
|
8464
9115
|
activeChannel,
|
|
@@ -8493,6 +9144,8 @@ var HeaderRightSide = ({
|
|
|
8493
9144
|
const { scopeClassName, themeStyles, showColorModeToggle } = useChatTheme();
|
|
8494
9145
|
const { showDateTimeSettings } = useChatLocale();
|
|
8495
9146
|
const features = useChatFeaturesOptional();
|
|
9147
|
+
const { getBlockUsersGate } = useEffectiveSettingsOptional();
|
|
9148
|
+
const blockUsersGate = getBlockUsersGate();
|
|
8496
9149
|
const showPhoneCall = features.showPhoneCall ?? defaultChatFeatures.showPhoneCall;
|
|
8497
9150
|
const showVideoCall = features.showVideoCall ?? defaultChatFeatures.showVideoCall;
|
|
8498
9151
|
const handlePhoneCall = () => {
|
|
@@ -8641,7 +9294,9 @@ var HeaderRightSide = ({
|
|
|
8641
9294
|
icon: lucideReact.Ban,
|
|
8642
9295
|
label: isBlocked ? "Unblock User" : "Block User",
|
|
8643
9296
|
onSelect: onToggleBlock,
|
|
8644
|
-
destructive: true
|
|
9297
|
+
destructive: true,
|
|
9298
|
+
disabled: !blockUsersGate.enabled,
|
|
9299
|
+
disabledReason: blockUsersGate.disabledReason
|
|
8645
9300
|
}
|
|
8646
9301
|
)
|
|
8647
9302
|
]
|
|
@@ -9012,13 +9667,13 @@ function AudioAttachmentPlayer({
|
|
|
9012
9667
|
showDownload = true,
|
|
9013
9668
|
downloadName
|
|
9014
9669
|
}) {
|
|
9015
|
-
const audioRef =
|
|
9016
|
-
const [isPlaying, setIsPlaying] =
|
|
9017
|
-
const [currentTime, setCurrentTime] =
|
|
9018
|
-
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);
|
|
9019
9674
|
const resolvedDuration = duration > 0 ? duration : 0;
|
|
9020
9675
|
const progressPercent = resolvedDuration > 0 ? Math.min(100, currentTime / resolvedDuration * 100) : 0;
|
|
9021
|
-
const togglePlay =
|
|
9676
|
+
const togglePlay = React3.useCallback(async () => {
|
|
9022
9677
|
const audio = audioRef.current;
|
|
9023
9678
|
if (!audio || !url) return;
|
|
9024
9679
|
if (audio.paused) {
|
|
@@ -9040,7 +9695,7 @@ function AudioAttachmentPlayer({
|
|
|
9040
9695
|
audio.currentTime = next;
|
|
9041
9696
|
setCurrentTime(next);
|
|
9042
9697
|
};
|
|
9043
|
-
|
|
9698
|
+
React3.useEffect(() => {
|
|
9044
9699
|
const audio = audioRef.current;
|
|
9045
9700
|
if (!audio) return;
|
|
9046
9701
|
const onTimeUpdate = () => setCurrentTime(audio.currentTime);
|
|
@@ -9068,7 +9723,7 @@ function AudioAttachmentPlayer({
|
|
|
9068
9723
|
audio.removeEventListener("play", onPlay);
|
|
9069
9724
|
};
|
|
9070
9725
|
}, [url]);
|
|
9071
|
-
|
|
9726
|
+
React3.useEffect(() => {
|
|
9072
9727
|
if (durationProp && durationProp > 0) {
|
|
9073
9728
|
setDuration(durationProp);
|
|
9074
9729
|
}
|
|
@@ -9190,12 +9845,12 @@ function VideoAttachmentPlayer({
|
|
|
9190
9845
|
downloadName,
|
|
9191
9846
|
onOpenPreview
|
|
9192
9847
|
}) {
|
|
9193
|
-
const videoRef =
|
|
9194
|
-
const [isPlaying, setIsPlaying] =
|
|
9195
|
-
const [duration, setDuration] =
|
|
9848
|
+
const videoRef = React3.useRef(null);
|
|
9849
|
+
const [isPlaying, setIsPlaying] = React3.useState(false);
|
|
9850
|
+
const [duration, setDuration] = React3.useState(durationProp ?? 0);
|
|
9196
9851
|
const onThemeBubble = inBubble && isSender;
|
|
9197
9852
|
const resolvedDuration = duration > 0 ? duration : 0;
|
|
9198
|
-
const togglePlay =
|
|
9853
|
+
const togglePlay = React3.useCallback(async () => {
|
|
9199
9854
|
const video = videoRef.current;
|
|
9200
9855
|
if (!video || !url) return;
|
|
9201
9856
|
if (video.paused) {
|
|
@@ -9210,7 +9865,7 @@ function VideoAttachmentPlayer({
|
|
|
9210
9865
|
setIsPlaying(false);
|
|
9211
9866
|
}
|
|
9212
9867
|
}, [url]);
|
|
9213
|
-
|
|
9868
|
+
React3.useEffect(() => {
|
|
9214
9869
|
if (durationProp && durationProp > 0) {
|
|
9215
9870
|
setDuration(durationProp);
|
|
9216
9871
|
}
|
|
@@ -9488,10 +10143,10 @@ async function fetchAuthenticatedBlob(url) {
|
|
|
9488
10143
|
return response.blob();
|
|
9489
10144
|
}
|
|
9490
10145
|
function PdfPreviewPanel({ url, name }) {
|
|
9491
|
-
const [blobUrl, setBlobUrl] =
|
|
9492
|
-
const [fallbackUrl, setFallbackUrl] =
|
|
9493
|
-
const [loading, setLoading] =
|
|
9494
|
-
|
|
10146
|
+
const [blobUrl, setBlobUrl] = React3.useState(null);
|
|
10147
|
+
const [fallbackUrl, setFallbackUrl] = React3.useState(null);
|
|
10148
|
+
const [loading, setLoading] = React3.useState(true);
|
|
10149
|
+
React3.useEffect(() => {
|
|
9495
10150
|
let active = true;
|
|
9496
10151
|
let objectUrl = null;
|
|
9497
10152
|
const loadPdf = async () => {
|
|
@@ -9995,60 +10650,60 @@ function AttachmentImageLightbox({
|
|
|
9995
10650
|
onSaveCaption,
|
|
9996
10651
|
initialCaptionEditing = false
|
|
9997
10652
|
}) {
|
|
9998
|
-
const [index, setIndex] =
|
|
9999
|
-
const [zoom, setZoom] =
|
|
10000
|
-
const [pan, setPan] =
|
|
10001
|
-
const [imageVersion, setImageVersion] =
|
|
10002
|
-
const [localCaptions, setLocalCaptions] =
|
|
10003
|
-
const [captionDraft, setCaptionDraft] =
|
|
10004
|
-
const [isCaptionEditing, setIsCaptionEditing] =
|
|
10005
|
-
const thumbRefs =
|
|
10006
|
-
const captionInputRef =
|
|
10007
|
-
const touchStartX =
|
|
10008
|
-
const isPanning =
|
|
10009
|
-
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 });
|
|
10010
10665
|
const canEdit = canEditCaption && !!onSaveCaption;
|
|
10011
|
-
|
|
10666
|
+
React3.useEffect(() => {
|
|
10012
10667
|
setIndex(initialIndex);
|
|
10013
10668
|
}, [initialIndex]);
|
|
10014
|
-
const resetView =
|
|
10669
|
+
const resetView = React3.useCallback(() => {
|
|
10015
10670
|
setZoom(1);
|
|
10016
10671
|
setPan({ x: 0, y: 0 });
|
|
10017
10672
|
}, []);
|
|
10018
|
-
const reloadImage =
|
|
10673
|
+
const reloadImage = React3.useCallback(() => {
|
|
10019
10674
|
resetView();
|
|
10020
10675
|
setImageVersion((version) => version + 1);
|
|
10021
10676
|
}, [resetView]);
|
|
10022
|
-
|
|
10677
|
+
React3.useEffect(() => {
|
|
10023
10678
|
resetView();
|
|
10024
10679
|
setIsCaptionEditing(false);
|
|
10025
10680
|
}, [index, resetView]);
|
|
10026
|
-
|
|
10681
|
+
React3.useEffect(() => {
|
|
10027
10682
|
if (!initialCaptionEditing || !canEdit) return;
|
|
10028
10683
|
setIsCaptionEditing(true);
|
|
10029
10684
|
}, [initialCaptionEditing, canEdit]);
|
|
10030
|
-
|
|
10685
|
+
React3.useEffect(() => {
|
|
10031
10686
|
if (!isCaptionEditing) return;
|
|
10032
10687
|
const id = window.setTimeout(() => captionInputRef.current?.focus(), 40);
|
|
10033
10688
|
return () => window.clearTimeout(id);
|
|
10034
10689
|
}, [isCaptionEditing]);
|
|
10035
|
-
const goPrev =
|
|
10690
|
+
const goPrev = React3.useCallback(() => {
|
|
10036
10691
|
setIndex((current2) => current2 > 0 ? current2 - 1 : images.length - 1);
|
|
10037
10692
|
}, [images.length]);
|
|
10038
|
-
const goNext =
|
|
10693
|
+
const goNext = React3.useCallback(() => {
|
|
10039
10694
|
setIndex((current2) => current2 < images.length - 1 ? current2 + 1 : 0);
|
|
10040
10695
|
}, [images.length]);
|
|
10041
|
-
const zoomIn =
|
|
10696
|
+
const zoomIn = React3.useCallback(() => {
|
|
10042
10697
|
setZoom((current2) => clampZoom(Number((current2 + ZOOM_STEP).toFixed(2))));
|
|
10043
10698
|
}, []);
|
|
10044
|
-
const zoomOut =
|
|
10699
|
+
const zoomOut = React3.useCallback(() => {
|
|
10045
10700
|
setZoom((current2) => {
|
|
10046
10701
|
const next = clampZoom(Number((current2 - ZOOM_STEP).toFixed(2)));
|
|
10047
10702
|
if (next <= MIN_ZOOM) setPan({ x: 0, y: 0 });
|
|
10048
10703
|
return next;
|
|
10049
10704
|
});
|
|
10050
10705
|
}, []);
|
|
10051
|
-
|
|
10706
|
+
React3.useEffect(() => {
|
|
10052
10707
|
const onKeyDown = (event) => {
|
|
10053
10708
|
const tag = event.target?.tagName;
|
|
10054
10709
|
const isTyping = tag === "INPUT" || tag === "TEXTAREA";
|
|
@@ -10062,14 +10717,14 @@ function AttachmentImageLightbox({
|
|
|
10062
10717
|
window.addEventListener("keydown", onKeyDown);
|
|
10063
10718
|
return () => window.removeEventListener("keydown", onKeyDown);
|
|
10064
10719
|
}, [goPrev, goNext, zoomIn, zoomOut, resetView]);
|
|
10065
|
-
|
|
10720
|
+
React3.useEffect(() => {
|
|
10066
10721
|
thumbRefs.current[index]?.scrollIntoView({
|
|
10067
10722
|
behavior: "smooth",
|
|
10068
10723
|
block: "nearest",
|
|
10069
10724
|
inline: "center"
|
|
10070
10725
|
});
|
|
10071
10726
|
}, [index]);
|
|
10072
|
-
|
|
10727
|
+
React3.useEffect(() => {
|
|
10073
10728
|
const attachment = images[index];
|
|
10074
10729
|
if (!attachment) return;
|
|
10075
10730
|
setCaptionDraft(getCaptionForAttachment(attachment, localCaptions));
|
|
@@ -10540,7 +11195,7 @@ function MessageAttachmentGrid({
|
|
|
10540
11195
|
onToggleAttachmentSelect,
|
|
10541
11196
|
onAttachmentHover
|
|
10542
11197
|
}) {
|
|
10543
|
-
const [lightboxIndex, setLightboxIndex] =
|
|
11198
|
+
const [lightboxIndex, setLightboxIndex] = React3.useState(null);
|
|
10544
11199
|
if (!images.length) return null;
|
|
10545
11200
|
const visible = images.slice(0, MAX_VISIBLE);
|
|
10546
11201
|
const overflow = images.length - MAX_VISIBLE;
|
|
@@ -10760,7 +11415,7 @@ function MessageAttachmentsImageSection({
|
|
|
10760
11415
|
hoveredAttachmentId,
|
|
10761
11416
|
onAttachmentHover
|
|
10762
11417
|
}) {
|
|
10763
|
-
const [lightboxIndex, setLightboxIndex] =
|
|
11418
|
+
const [lightboxIndex, setLightboxIndex] = React3.useState(null);
|
|
10764
11419
|
if (images.length === 0) return null;
|
|
10765
11420
|
const renderMediaMetaOverlay = () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
10766
11421
|
MediaMetaOverlay,
|
|
@@ -11235,7 +11890,7 @@ function MessageAttachmentsView({
|
|
|
11235
11890
|
senderName,
|
|
11236
11891
|
senderId
|
|
11237
11892
|
}) {
|
|
11238
|
-
const [documentPreview, setDocumentPreview] =
|
|
11893
|
+
const [documentPreview, setDocumentPreview] = React3.useState(null);
|
|
11239
11894
|
const visibleAttachments = getVisibleAttachments(attachments);
|
|
11240
11895
|
if (isDeletedForEveryone || visibleAttachments.length === 0) return null;
|
|
11241
11896
|
const messageCaption = caption?.trim() || "";
|
|
@@ -11620,8 +12275,8 @@ var SavedMessagesDrawer = ({
|
|
|
11620
12275
|
const conversationMessages = exports.useChatStore(
|
|
11621
12276
|
(s) => conversationId ? s.messagesByConversation[conversationId] ?? EMPTY_CONVERSATION_MESSAGES : EMPTY_CONVERSATION_MESSAGES
|
|
11622
12277
|
);
|
|
11623
|
-
const [searchQuery, setSearchQuery] =
|
|
11624
|
-
const parsedEntries =
|
|
12278
|
+
const [searchQuery, setSearchQuery] = React3.useState("");
|
|
12279
|
+
const parsedEntries = React3.useMemo(() => {
|
|
11625
12280
|
return messages.map((msg) => ({
|
|
11626
12281
|
msg,
|
|
11627
12282
|
item: parseSavedMessage(msg, {
|
|
@@ -11642,7 +12297,7 @@ var SavedMessagesDrawer = ({
|
|
|
11642
12297
|
variant,
|
|
11643
12298
|
prefs
|
|
11644
12299
|
]);
|
|
11645
|
-
const groupedEntries =
|
|
12300
|
+
const groupedEntries = React3.useMemo(() => {
|
|
11646
12301
|
const query = searchQuery.trim().toLowerCase();
|
|
11647
12302
|
const filtered = parsedEntries.filter(({ item, msg }) => {
|
|
11648
12303
|
if (!query) return true;
|
|
@@ -11915,15 +12570,15 @@ function SectionScrollArea({
|
|
|
11915
12570
|
onLoadMore,
|
|
11916
12571
|
dependencyKey
|
|
11917
12572
|
}) {
|
|
11918
|
-
const scrollRef =
|
|
11919
|
-
const [showArrow, setShowArrow] =
|
|
11920
|
-
const updateArrow =
|
|
12573
|
+
const scrollRef = React3.useRef(null);
|
|
12574
|
+
const [showArrow, setShowArrow] = React3.useState(false);
|
|
12575
|
+
const updateArrow = React3.useCallback(() => {
|
|
11921
12576
|
const el = scrollRef.current;
|
|
11922
12577
|
if (!el) return;
|
|
11923
12578
|
const canScrollDown = el.scrollHeight - el.scrollTop - el.clientHeight > 6;
|
|
11924
12579
|
setShowArrow(canScrollDown || hasMoreToLoad);
|
|
11925
12580
|
}, [hasMoreToLoad]);
|
|
11926
|
-
|
|
12581
|
+
React3.useEffect(() => {
|
|
11927
12582
|
updateArrow();
|
|
11928
12583
|
const el = scrollRef.current;
|
|
11929
12584
|
if (!el) return;
|
|
@@ -12099,31 +12754,31 @@ var AttachmentsDrawer = ({ isOpen, onOpenChange, conversationId }) => {
|
|
|
12099
12754
|
const messagesByConversation = exports.useChatStore((s) => s.messagesByConversation);
|
|
12100
12755
|
const messagesMetadata = exports.useChatStore((s) => s.messagesMetadata);
|
|
12101
12756
|
const fetchMessages2 = exports.useChatStore((s) => s.fetchMessages);
|
|
12102
|
-
const [sectionVisibleCount, setSectionVisibleCount] =
|
|
12103
|
-
const [documentPreview, setDocumentPreview] =
|
|
12104
|
-
const [imageLightboxIndex, setImageLightboxIndex] =
|
|
12757
|
+
const [sectionVisibleCount, setSectionVisibleCount] = React3.useState({});
|
|
12758
|
+
const [documentPreview, setDocumentPreview] = React3.useState(null);
|
|
12759
|
+
const [imageLightboxIndex, setImageLightboxIndex] = React3.useState(null);
|
|
12105
12760
|
const hasLoadedMessages = conversationId ? Boolean(messagesMetadata[conversationId]?.isFirstPage) : false;
|
|
12106
12761
|
const isLoading = isOpen && !!conversationId && !hasLoadedMessages;
|
|
12107
|
-
|
|
12762
|
+
React3.useEffect(() => {
|
|
12108
12763
|
if (!isOpen) {
|
|
12109
12764
|
setSectionVisibleCount({});
|
|
12110
12765
|
setDocumentPreview(null);
|
|
12111
12766
|
setImageLightboxIndex(null);
|
|
12112
12767
|
}
|
|
12113
12768
|
}, [isOpen]);
|
|
12114
|
-
|
|
12769
|
+
React3.useEffect(() => {
|
|
12115
12770
|
setSectionVisibleCount({});
|
|
12116
12771
|
}, [conversationId]);
|
|
12117
|
-
|
|
12772
|
+
React3.useEffect(() => {
|
|
12118
12773
|
if (!isOpen || !conversationId || hasLoadedMessages) return;
|
|
12119
12774
|
fetchMessages2(conversationId);
|
|
12120
12775
|
}, [isOpen, conversationId, hasLoadedMessages, fetchMessages2]);
|
|
12121
|
-
const attachments =
|
|
12776
|
+
const attachments = React3.useMemo(() => {
|
|
12122
12777
|
if (!conversationId) return [];
|
|
12123
12778
|
const messages = messagesByConversation[conversationId] || [];
|
|
12124
12779
|
return collectConversationAttachments(messages);
|
|
12125
12780
|
}, [conversationId, messagesByConversation]);
|
|
12126
|
-
const imageLightboxItems =
|
|
12781
|
+
const imageLightboxItems = React3.useMemo(
|
|
12127
12782
|
() => attachments.filter((item) => item.type === "image").map((item) => ({
|
|
12128
12783
|
id: item.id,
|
|
12129
12784
|
url: item.url,
|
|
@@ -12132,14 +12787,14 @@ var AttachmentsDrawer = ({ isOpen, onOpenChange, conversationId }) => {
|
|
|
12132
12787
|
})),
|
|
12133
12788
|
[attachments]
|
|
12134
12789
|
);
|
|
12135
|
-
const openImagePreview =
|
|
12790
|
+
const openImagePreview = React3.useCallback(
|
|
12136
12791
|
(item) => {
|
|
12137
12792
|
const index = imageLightboxItems.findIndex((entry) => entry.id === item.id);
|
|
12138
12793
|
if (index >= 0) setImageLightboxIndex(index);
|
|
12139
12794
|
},
|
|
12140
12795
|
[imageLightboxItems]
|
|
12141
12796
|
);
|
|
12142
|
-
const grouped =
|
|
12797
|
+
const grouped = React3.useMemo(() => {
|
|
12143
12798
|
const map = /* @__PURE__ */ new Map();
|
|
12144
12799
|
for (const item of attachments) {
|
|
12145
12800
|
const bucket = map.get(item.type) ?? [];
|
|
@@ -12239,13 +12894,13 @@ var useGroupInfo = (conversationId) => {
|
|
|
12239
12894
|
const conversationInfos = exports.useChatStore((s) => s.conversationInfos);
|
|
12240
12895
|
const loggedUserDetails = exports.useChatStore((s) => s.loggedUserDetails);
|
|
12241
12896
|
const info = conversationId ? conversationInfos[conversationId] : null;
|
|
12242
|
-
const isAdmin =
|
|
12897
|
+
const isAdmin = React3.useMemo(() => {
|
|
12243
12898
|
if (!info || !loggedUserDetails) return false;
|
|
12244
12899
|
return info.groupAdmins?.some(
|
|
12245
12900
|
(admin) => (typeof admin === "string" ? admin : admin._id) === String(loggedUserDetails._id)
|
|
12246
12901
|
) || false;
|
|
12247
12902
|
}, [info, loggedUserDetails]);
|
|
12248
|
-
const isOwner =
|
|
12903
|
+
const isOwner = React3.useMemo(() => {
|
|
12249
12904
|
if (!info || !loggedUserDetails) return false;
|
|
12250
12905
|
let ownerId = null;
|
|
12251
12906
|
if (info.owner) {
|
|
@@ -12254,7 +12909,7 @@ var useGroupInfo = (conversationId) => {
|
|
|
12254
12909
|
return String(ownerId) === String(loggedUserDetails._id);
|
|
12255
12910
|
}, [info, loggedUserDetails]);
|
|
12256
12911
|
const permissions = info?.groupPermissions || null;
|
|
12257
|
-
const userPermissions =
|
|
12912
|
+
const userPermissions = React3.useMemo(() => {
|
|
12258
12913
|
return {
|
|
12259
12914
|
canSendMessage: isOwner || isAdmin || !permissions?.onlyAdminCanSendMessage,
|
|
12260
12915
|
canEditInfo: isOwner || isAdmin || !permissions?.onlyAdminCanEditInfo,
|
|
@@ -12303,21 +12958,21 @@ function useChannelDetailsDrawer({
|
|
|
12303
12958
|
const conversationId = conversationInfo?._id || activeChannel?.conversationId || storeActiveConversationId || null;
|
|
12304
12959
|
const { userPermissions } = useGroupInfo(conversationId);
|
|
12305
12960
|
const { formatLongDate } = useChatLocale();
|
|
12306
|
-
const storeConversation =
|
|
12961
|
+
const storeConversation = React3.useMemo(
|
|
12307
12962
|
() => conversations.find((c) => conversationId && String(c._id) === String(conversationId)),
|
|
12308
12963
|
[conversations, conversationId]
|
|
12309
12964
|
);
|
|
12310
|
-
const isGroupChannel =
|
|
12965
|
+
const isGroupChannel = React3.useMemo(() => {
|
|
12311
12966
|
if (storeConversation) {
|
|
12312
12967
|
return storeConversation.conversationType === "group" || !!storeConversation.isGroup;
|
|
12313
12968
|
}
|
|
12314
12969
|
return !!activeChannel?.isGroup;
|
|
12315
12970
|
}, [storeConversation, activeChannel?.isGroup]);
|
|
12316
|
-
const participantsSource =
|
|
12971
|
+
const participantsSource = React3.useMemo(
|
|
12317
12972
|
() => conversationInfo?.participants || storeConversation?.participants || [],
|
|
12318
12973
|
[conversationInfo?.participants, storeConversation?.participants]
|
|
12319
12974
|
);
|
|
12320
|
-
const resolvedOtherParticipant =
|
|
12975
|
+
const resolvedOtherParticipant = React3.useMemo(() => {
|
|
12321
12976
|
if (isGroupChannel) return { id: "", user: null };
|
|
12322
12977
|
return resolveOtherParticipant(
|
|
12323
12978
|
{
|
|
@@ -12336,7 +12991,7 @@ function useChannelDetailsDrawer({
|
|
|
12336
12991
|
allUsers
|
|
12337
12992
|
]);
|
|
12338
12993
|
const otherUser = resolvedOtherParticipant.user;
|
|
12339
|
-
const otherUserEmail =
|
|
12994
|
+
const otherUserEmail = React3.useMemo(() => {
|
|
12340
12995
|
if (isGroupChannel) return null;
|
|
12341
12996
|
const fromResolved = resolvedOtherParticipant.user?.email?.trim();
|
|
12342
12997
|
if (fromResolved) return fromResolved;
|
|
@@ -12344,7 +12999,7 @@ function useChannelDetailsDrawer({
|
|
|
12344
12999
|
if (!otherId) return null;
|
|
12345
13000
|
return allUsers.find((user) => String(user._id) === String(otherId))?.email?.trim() || activeChannel?.email?.trim() || null;
|
|
12346
13001
|
}, [isGroupChannel, resolvedOtherParticipant.id, resolvedOtherParticipant.user?.email, allUsers, activeChannel?.email]);
|
|
12347
|
-
const resolvedCreatedAt =
|
|
13002
|
+
const resolvedCreatedAt = React3.useMemo(
|
|
12348
13003
|
() => pickDate(
|
|
12349
13004
|
conversationInfo?.createdAt,
|
|
12350
13005
|
conversationInfo?.updatedAt,
|
|
@@ -12357,9 +13012,9 @@ function useChannelDetailsDrawer({
|
|
|
12357
13012
|
),
|
|
12358
13013
|
[conversationInfo, storeConversation, otherUser, conversationId, messagesByConversation]
|
|
12359
13014
|
);
|
|
12360
|
-
const [detailsLoading, setDetailsLoading] =
|
|
12361
|
-
const fetchStartedRef =
|
|
12362
|
-
|
|
13015
|
+
const [detailsLoading, setDetailsLoading] = React3.useState(false);
|
|
13016
|
+
const fetchStartedRef = React3.useRef(null);
|
|
13017
|
+
React3.useEffect(() => {
|
|
12363
13018
|
if (!isOpen) {
|
|
12364
13019
|
fetchStartedRef.current = null;
|
|
12365
13020
|
setDetailsLoading(false);
|
|
@@ -12401,16 +13056,16 @@ function useChannelDetailsDrawer({
|
|
|
12401
13056
|
};
|
|
12402
13057
|
}, [isOpen, conversationId, isGroupChannel, fetchAllUsers]);
|
|
12403
13058
|
const canEditInfo = activeChannel ? userPermissions.canEditInfo : false;
|
|
12404
|
-
const [isEditing, setIsEditing] =
|
|
12405
|
-
const [name, setName] =
|
|
12406
|
-
const [description, setDescription] =
|
|
12407
|
-
const [image, setImage] =
|
|
12408
|
-
const [uploadedImageUrl, setUploadedImageUrl] =
|
|
12409
|
-
const [imageUploadStatus, setImageUploadStatus] =
|
|
12410
|
-
const [imageUploadError, setImageUploadError] =
|
|
12411
|
-
const [isSaving, setIsSaving] =
|
|
12412
|
-
const fileInputRef =
|
|
12413
|
-
|
|
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(() => {
|
|
12414
13069
|
if (conversationInfo) {
|
|
12415
13070
|
setName(conversationInfo.groupName || activeChannel?.name || "");
|
|
12416
13071
|
setDescription(conversationInfo.groupDescription || "");
|
|
@@ -12681,17 +13336,24 @@ var ChannelDetailsDrawer = (props) => {
|
|
|
12681
13336
|
};
|
|
12682
13337
|
var ChannelDetailsDrawer_default = ChannelDetailsDrawer;
|
|
12683
13338
|
init_useStore();
|
|
13339
|
+
init_settings_types();
|
|
12684
13340
|
var PermissionDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo }) => {
|
|
12685
13341
|
const updateGroupPermissions = exports.useChatStore((s) => s.updateGroupPermissions);
|
|
12686
|
-
const
|
|
12687
|
-
const [
|
|
12688
|
-
|
|
13342
|
+
const { settings, isGroupPermissionLocked } = useEffectiveSettingsOptional();
|
|
13343
|
+
const [permissions, setPermissions] = React3.useState(null);
|
|
13344
|
+
const [isSaving, setIsSaving] = React3.useState(false);
|
|
13345
|
+
React3.useEffect(() => {
|
|
12689
13346
|
if (conversationInfo?.groupPermissions) {
|
|
12690
13347
|
setPermissions(conversationInfo.groupPermissions);
|
|
13348
|
+
return;
|
|
13349
|
+
}
|
|
13350
|
+
if (isOpen) {
|
|
13351
|
+
setPermissions({ ...settings.groupPolicy.defaults });
|
|
12691
13352
|
}
|
|
12692
|
-
}, [conversationInfo]);
|
|
13353
|
+
}, [conversationInfo, isOpen, settings.groupPolicy.defaults]);
|
|
12693
13354
|
if (!conversationId || !permissions) return null;
|
|
12694
13355
|
const handleToggle = (key) => {
|
|
13356
|
+
if (isGroupPermissionLocked(key)) return;
|
|
12695
13357
|
setPermissions((prev) => prev ? { ...prev, [key]: !prev[key] } : null);
|
|
12696
13358
|
};
|
|
12697
13359
|
const handleSave = async () => {
|
|
@@ -12723,31 +13385,43 @@ var PermissionDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo
|
|
|
12723
13385
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(chatSheetBodyClass, "flex flex-col px-2.5 py-2"), children: [
|
|
12724
13386
|
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "mb-2.5 flex-1", children: [
|
|
12725
13387
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-1 px-0.5 text-[10px] font-semibold uppercase tracking-wide text-(--chat-muted)", children: "Permissions" }),
|
|
12726
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-(--chat-border) px-3", children: permissionItems.map((item, index) =>
|
|
12727
|
-
|
|
12728
|
-
|
|
12729
|
-
|
|
12730
|
-
|
|
12731
|
-
|
|
12732
|
-
|
|
12733
|
-
|
|
12734
|
-
|
|
12735
|
-
|
|
12736
|
-
/* @__PURE__ */ jsxRuntime.
|
|
12737
|
-
|
|
12738
|
-
|
|
12739
|
-
|
|
12740
|
-
|
|
12741
|
-
|
|
12742
|
-
|
|
12743
|
-
|
|
12744
|
-
|
|
12745
|
-
|
|
12746
|
-
|
|
12747
|
-
|
|
12748
|
-
|
|
12749
|
-
|
|
12750
|
-
|
|
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
|
+
}) })
|
|
12751
13425
|
] }),
|
|
12752
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(
|
|
12753
13427
|
Button,
|
|
@@ -12773,51 +13447,61 @@ var PermissionDrawer_default = PermissionDrawer;
|
|
|
12773
13447
|
// src/chat/header/admins-drawer/useAdminsDrawer.ts
|
|
12774
13448
|
init_useStore();
|
|
12775
13449
|
function useAdminsDrawer({ conversationId, conversationInfo }) {
|
|
12776
|
-
const [searchQuery, setSearchQuery] =
|
|
12777
|
-
const [isManaging, setIsManaging] =
|
|
13450
|
+
const [searchQuery, setSearchQuery] = React3.useState("");
|
|
13451
|
+
const [isManaging, setIsManaging] = React3.useState(null);
|
|
12778
13452
|
const manageGroupAdmins = exports.useChatStore((s) => s.manageGroupAdmins);
|
|
12779
13453
|
const { isOwner } = useGroupInfo(conversationId);
|
|
12780
|
-
const
|
|
13454
|
+
const { settings } = useEffectiveSettingsOptional();
|
|
13455
|
+
const maxAdmins = settings.maxAdminsPerGroup;
|
|
13456
|
+
const participants = React3.useMemo(
|
|
12781
13457
|
() => conversationInfo?.participants ?? [],
|
|
12782
13458
|
[conversationInfo?.participants]
|
|
12783
13459
|
);
|
|
12784
|
-
const admins =
|
|
13460
|
+
const admins = React3.useMemo(
|
|
12785
13461
|
() => conversationInfo?.groupAdmins ?? [],
|
|
12786
13462
|
[conversationInfo?.groupAdmins]
|
|
12787
13463
|
);
|
|
12788
|
-
const ownerId =
|
|
13464
|
+
const ownerId = React3.useMemo(() => {
|
|
12789
13465
|
if (!conversationInfo?.owner) return null;
|
|
12790
13466
|
return typeof conversationInfo.owner === "object" && conversationInfo.owner !== null ? conversationInfo.owner._id || conversationInfo.owner.id : conversationInfo.owner;
|
|
12791
13467
|
}, [conversationInfo?.owner]);
|
|
12792
|
-
const adminIds =
|
|
13468
|
+
const adminIds = React3.useMemo(
|
|
12793
13469
|
() => new Set(
|
|
12794
13470
|
admins.map((a) => typeof a === "string" ? a : a._id).filter((id) => Boolean(id))
|
|
12795
13471
|
),
|
|
12796
13472
|
[admins]
|
|
12797
13473
|
);
|
|
12798
|
-
const isAdmin =
|
|
12799
|
-
const filteredParticipants =
|
|
13474
|
+
const isAdmin = React3.useCallback((userId) => adminIds.has(userId), [adminIds]);
|
|
13475
|
+
const filteredParticipants = React3.useMemo(() => {
|
|
12800
13476
|
if (!searchQuery.trim()) return participants;
|
|
12801
13477
|
return participants.filter(
|
|
12802
13478
|
(p) => p.name?.toLowerCase().includes(searchQuery.toLowerCase()) || p.email?.toLowerCase().includes(searchQuery.toLowerCase())
|
|
12803
13479
|
);
|
|
12804
13480
|
}, [participants, searchQuery]);
|
|
12805
|
-
const adminParticipants =
|
|
13481
|
+
const adminParticipants = React3.useMemo(
|
|
12806
13482
|
() => filteredParticipants.filter((p) => {
|
|
12807
13483
|
const id = typeof p === "string" ? p : p._id;
|
|
12808
13484
|
return id && (adminIds.has(id) || id === ownerId);
|
|
12809
13485
|
}),
|
|
12810
13486
|
[filteredParticipants, adminIds, ownerId]
|
|
12811
13487
|
);
|
|
12812
|
-
const promotableParticipants =
|
|
13488
|
+
const promotableParticipants = React3.useMemo(
|
|
12813
13489
|
() => filteredParticipants.filter((p) => {
|
|
12814
13490
|
const id = typeof p === "string" ? p : p._id;
|
|
12815
13491
|
return id && id !== ownerId && !adminIds.has(id);
|
|
12816
13492
|
}),
|
|
12817
13493
|
[filteredParticipants, adminIds, ownerId]
|
|
12818
13494
|
);
|
|
13495
|
+
const adminCount = admins.length + (ownerId ? 1 : 0);
|
|
13496
|
+
const atAdminLimit = adminCount >= maxAdmins;
|
|
12819
13497
|
const handleManageAdmin = async (userId, type) => {
|
|
12820
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
|
+
}
|
|
12821
13505
|
setIsManaging(userId);
|
|
12822
13506
|
try {
|
|
12823
13507
|
await manageGroupAdmins({
|
|
@@ -12829,7 +13513,6 @@ function useAdminsDrawer({ conversationId, conversationInfo }) {
|
|
|
12829
13513
|
setIsManaging(null);
|
|
12830
13514
|
}
|
|
12831
13515
|
};
|
|
12832
|
-
const adminCount = admins.length + (ownerId ? 1 : 0);
|
|
12833
13516
|
return {
|
|
12834
13517
|
searchQuery,
|
|
12835
13518
|
setSearchQuery,
|
|
@@ -12841,6 +13524,8 @@ function useAdminsDrawer({ conversationId, conversationInfo }) {
|
|
|
12841
13524
|
promotableParticipants,
|
|
12842
13525
|
handleManageAdmin,
|
|
12843
13526
|
adminCount,
|
|
13527
|
+
maxAdmins,
|
|
13528
|
+
atAdminLimit,
|
|
12844
13529
|
hasRequiredData: Boolean(conversationId && conversationInfo)
|
|
12845
13530
|
};
|
|
12846
13531
|
}
|
|
@@ -12853,6 +13538,8 @@ function AdminParticipantRow({
|
|
|
12853
13538
|
isAdmin,
|
|
12854
13539
|
showPromote,
|
|
12855
13540
|
showDemote,
|
|
13541
|
+
promoteDisabled = false,
|
|
13542
|
+
promoteDisabledReason,
|
|
12856
13543
|
isOwnerViewer,
|
|
12857
13544
|
isManaging,
|
|
12858
13545
|
onManageAdmin
|
|
@@ -12893,14 +13580,24 @@ function AdminParticipantRow({
|
|
|
12893
13580
|
}
|
|
12894
13581
|
),
|
|
12895
13582
|
showPromote && isOwnerViewer && /* @__PURE__ */ jsxRuntime.jsx(
|
|
12896
|
-
|
|
13583
|
+
AdminPermissionTooltip,
|
|
12897
13584
|
{
|
|
12898
|
-
|
|
12899
|
-
|
|
12900
|
-
|
|
12901
|
-
|
|
12902
|
-
|
|
12903
|
-
|
|
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
|
+
)
|
|
12904
13601
|
}
|
|
12905
13602
|
)
|
|
12906
13603
|
] })
|
|
@@ -12924,7 +13621,9 @@ function AdminParticipantList({
|
|
|
12924
13621
|
isAdmin,
|
|
12925
13622
|
onManageAdmin,
|
|
12926
13623
|
showPromote,
|
|
12927
|
-
showDemoteForAdmins
|
|
13624
|
+
showDemoteForAdmins,
|
|
13625
|
+
promoteDisabled = false,
|
|
13626
|
+
promoteDisabledReason
|
|
12928
13627
|
}) {
|
|
12929
13628
|
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: members.map((member, index) => {
|
|
12930
13629
|
const { memberId, memberName, memberEmail, memberImage } = getMemberFields(member);
|
|
@@ -12942,6 +13641,8 @@ function AdminParticipantList({
|
|
|
12942
13641
|
isAdmin: userIsAdmin,
|
|
12943
13642
|
showPromote: showPromote && !userIsAdmin && !userIsOwner,
|
|
12944
13643
|
showDemote: showDemoteForAdmins ? userIsAdmin && !userIsOwner : false,
|
|
13644
|
+
promoteDisabled,
|
|
13645
|
+
promoteDisabledReason,
|
|
12945
13646
|
isOwnerViewer,
|
|
12946
13647
|
isManaging,
|
|
12947
13648
|
onManageAdmin
|
|
@@ -12961,6 +13662,8 @@ var AdminsDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
12961
13662
|
promotableParticipants,
|
|
12962
13663
|
handleManageAdmin,
|
|
12963
13664
|
adminCount,
|
|
13665
|
+
maxAdmins,
|
|
13666
|
+
atAdminLimit,
|
|
12964
13667
|
hasRequiredData
|
|
12965
13668
|
} = useAdminsDrawer({ conversationId, conversationInfo });
|
|
12966
13669
|
if (!hasRequiredData) return null;
|
|
@@ -12980,7 +13683,10 @@ var AdminsDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
12980
13683
|
/* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: chatSheetTitleClass, children: "Group Administrators" }),
|
|
12981
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 })
|
|
12982
13685
|
] }),
|
|
12983
|
-
/* @__PURE__ */ jsxRuntime.
|
|
13686
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: chatSheetSubtitleClass, children: [
|
|
13687
|
+
"Manage who can adjust group settings and members",
|
|
13688
|
+
maxAdmins ? ` (max ${maxAdmins}).` : "."
|
|
13689
|
+
] })
|
|
12984
13690
|
] }),
|
|
12985
13691
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(chatSheetBodyClass, "px-2.5 py-2"), children: [
|
|
12986
13692
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2.5 px-0.5", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -13023,7 +13729,9 @@ var AdminsDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13023
13729
|
ownerId,
|
|
13024
13730
|
isAdmin,
|
|
13025
13731
|
onManageAdmin: handleManageAdmin,
|
|
13026
|
-
showPromote: true
|
|
13732
|
+
showPromote: true,
|
|
13733
|
+
promoteDisabled: atAdminLimit,
|
|
13734
|
+
promoteDisabledReason: `Maximum ${maxAdmins} admins allowed in this group.`
|
|
13027
13735
|
}
|
|
13028
13736
|
) })
|
|
13029
13737
|
] }),
|
|
@@ -13040,7 +13748,9 @@ var AdminsDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13040
13748
|
isAdmin,
|
|
13041
13749
|
onManageAdmin: handleManageAdmin,
|
|
13042
13750
|
showPromote: true,
|
|
13043
|
-
showDemoteForAdmins: true
|
|
13751
|
+
showDemoteForAdmins: true,
|
|
13752
|
+
promoteDisabled: atAdminLimit,
|
|
13753
|
+
promoteDisabledReason: `Maximum ${maxAdmins} admins allowed in this group.`
|
|
13044
13754
|
}
|
|
13045
13755
|
) })
|
|
13046
13756
|
] }),
|
|
@@ -13056,21 +13766,24 @@ var AdminsDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13056
13766
|
var AdminsDrawer_default = AdminsDrawer;
|
|
13057
13767
|
init_useStore();
|
|
13058
13768
|
var MembersDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo }) => {
|
|
13059
|
-
const [searchQuery, setSearchQuery] =
|
|
13060
|
-
const [isManaging, setIsManaging] =
|
|
13769
|
+
const [searchQuery, setSearchQuery] = React3.useState("");
|
|
13770
|
+
const [isManaging, setIsManaging] = React3.useState(null);
|
|
13061
13771
|
const allUsers = exports.useChatStore((s) => s.allUsers);
|
|
13062
13772
|
const manageGroupMembers = exports.useChatStore((s) => s.manageGroupMembers);
|
|
13063
13773
|
const loggedUserDetails = exports.useChatStore((s) => s.loggedUserDetails);
|
|
13064
|
-
const filteredUsers =
|
|
13774
|
+
const filteredUsers = React3.useMemo(() => {
|
|
13065
13775
|
if (!searchQuery.trim()) return allUsers;
|
|
13066
13776
|
return allUsers.filter(
|
|
13067
13777
|
(u) => u.name?.toLowerCase().includes(searchQuery.toLowerCase()) || u.email?.toLowerCase().includes(searchQuery.toLowerCase())
|
|
13068
13778
|
);
|
|
13069
13779
|
}, [allUsers, searchQuery]);
|
|
13070
13780
|
const { userPermissions } = useGroupInfo(conversationId);
|
|
13781
|
+
const { settings } = useEffectiveSettingsOptional();
|
|
13782
|
+
const maxParticipants = settings.maxParticipantsPerGroup;
|
|
13071
13783
|
if (!conversationId || !conversationInfo) return null;
|
|
13072
13784
|
const participants = conversationInfo.participants || [];
|
|
13073
13785
|
const admins = conversationInfo.groupAdmins || [];
|
|
13786
|
+
const atParticipantLimit = participants.length >= maxParticipants;
|
|
13074
13787
|
let ownerId = null;
|
|
13075
13788
|
if (conversationInfo.owner) {
|
|
13076
13789
|
ownerId = typeof conversationInfo.owner === "object" && conversationInfo.owner !== null ? conversationInfo.owner._id || conversationInfo.owner.id : conversationInfo.owner;
|
|
@@ -13124,14 +13837,24 @@ var MembersDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13124
13837
|
}
|
|
13125
13838
|
),
|
|
13126
13839
|
options.showAdd && /* @__PURE__ */ jsxRuntime.jsx(
|
|
13127
|
-
|
|
13840
|
+
AdminPermissionTooltip,
|
|
13128
13841
|
{
|
|
13129
|
-
|
|
13130
|
-
|
|
13131
|
-
|
|
13132
|
-
|
|
13133
|
-
|
|
13134
|
-
|
|
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
|
+
)
|
|
13135
13858
|
}
|
|
13136
13859
|
)
|
|
13137
13860
|
] })
|
|
@@ -13153,7 +13876,11 @@ var MembersDrawer = ({ isOpen, onOpenChange, conversationId, conversationInfo })
|
|
|
13153
13876
|
/* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: chatSheetTitleClass, children: "Group Management" }),
|
|
13154
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 })
|
|
13155
13878
|
] }),
|
|
13156
|
-
/* @__PURE__ */ jsxRuntime.
|
|
13879
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: chatSheetSubtitleClass, children: [
|
|
13880
|
+
"Manage members and invite people (max ",
|
|
13881
|
+
maxParticipants,
|
|
13882
|
+
")."
|
|
13883
|
+
] })
|
|
13157
13884
|
] }),
|
|
13158
13885
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(chatSheetBodyClass, "px-2.5 py-2"), children: [
|
|
13159
13886
|
!searchQuery && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "mb-2.5", children: [
|
|
@@ -13274,8 +14001,8 @@ var ChatActionModal_default = ChatActionModal;
|
|
|
13274
14001
|
// src/chat/channel-header/useChannelHeader.ts
|
|
13275
14002
|
init_useStore();
|
|
13276
14003
|
function useDebounce(value, delay) {
|
|
13277
|
-
const [debouncedValue, setDebouncedValue] =
|
|
13278
|
-
|
|
14004
|
+
const [debouncedValue, setDebouncedValue] = React3.useState(value);
|
|
14005
|
+
React3.useEffect(() => {
|
|
13279
14006
|
const timer = setTimeout(() => setDebouncedValue(value), delay);
|
|
13280
14007
|
return () => {
|
|
13281
14008
|
clearTimeout(timer);
|
|
@@ -13295,7 +14022,9 @@ init_store_helpers();
|
|
|
13295
14022
|
function useBlockUser(activeChannel, conversationId, onActiveChannelPatch) {
|
|
13296
14023
|
const loggedUserDetails = exports.useChatStore((s) => s.loggedUserDetails);
|
|
13297
14024
|
const composerDisabledByConversation = exports.useChatStore((s) => s.composerDisabledByConversation);
|
|
13298
|
-
const
|
|
14025
|
+
const { getBlockUsersGate } = useEffectiveSettingsOptional();
|
|
14026
|
+
const blockUsersGate = getBlockUsersGate();
|
|
14027
|
+
const [isBlocking, setIsBlocking] = React3.useState(false);
|
|
13299
14028
|
const resolvedConversationId = conversationId ?? activeChannel?.conversationId ?? null;
|
|
13300
14029
|
const composerDisabledReason = resolvedConversationId ? composerDisabledByConversation[resolvedConversationId] : void 0;
|
|
13301
14030
|
const isBlockedFromConversation = exports.useChatStore((s) => {
|
|
@@ -13313,9 +14042,15 @@ function useBlockUser(activeChannel, conversationId, onActiveChannelPatch) {
|
|
|
13313
14042
|
return !!conv?.isBlocked || !!activeChannel.isBlocked;
|
|
13314
14043
|
});
|
|
13315
14044
|
const isBlocked = isBlockedFromConversation || !activeChannel?.isGroup && !!composerDisabledReason && /block/i.test(composerDisabledReason);
|
|
13316
|
-
const toggleBlock =
|
|
14045
|
+
const toggleBlock = React3.useCallback(async () => {
|
|
13317
14046
|
if (!activeChannel?.id || activeChannel.isGroup) return false;
|
|
13318
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
|
+
}
|
|
13319
14054
|
const type = nextBlocked ? "block" : "unblock";
|
|
13320
14055
|
try {
|
|
13321
14056
|
setIsBlocking(true);
|
|
@@ -13336,8 +14071,8 @@ function useBlockUser(activeChannel, conversationId, onActiveChannelPatch) {
|
|
|
13336
14071
|
} finally {
|
|
13337
14072
|
setIsBlocking(false);
|
|
13338
14073
|
}
|
|
13339
|
-
}, [activeChannel, isBlocked, onActiveChannelPatch, resolvedConversationId]);
|
|
13340
|
-
return { isBlocked, isBlocking, toggleBlock };
|
|
14074
|
+
}, [activeChannel, isBlocked, onActiveChannelPatch, resolvedConversationId, blockUsersGate]);
|
|
14075
|
+
return { isBlocked, isBlocking, toggleBlock, blockUsersGate };
|
|
13341
14076
|
}
|
|
13342
14077
|
|
|
13343
14078
|
// src/chat/channel-header/useChannelHeader.ts
|
|
@@ -13370,8 +14105,8 @@ function useChannelHeader({
|
|
|
13370
14105
|
onBack,
|
|
13371
14106
|
onActiveChannelPatch
|
|
13372
14107
|
}) {
|
|
13373
|
-
const [state, setState] =
|
|
13374
|
-
const updateState =
|
|
14108
|
+
const [state, setState] = React3.useState(initialState2);
|
|
14109
|
+
const updateState = React3.useCallback((updates) => {
|
|
13375
14110
|
setState((prev) => ({ ...prev, ...updates }));
|
|
13376
14111
|
}, []);
|
|
13377
14112
|
const { formatLongDate } = useChatLocale();
|
|
@@ -13411,7 +14146,7 @@ function useChannelHeader({
|
|
|
13411
14146
|
const setSearchedMessageId = exports.useChatStore((s) => s.setSearchedMessageId);
|
|
13412
14147
|
const isSearchActive = exports.useChatStore((s) => s.isSearchActive);
|
|
13413
14148
|
const debouncedSearch = useDebounce(state.searchQuery, 800);
|
|
13414
|
-
const handleSearch =
|
|
14149
|
+
const handleSearch = React3.useCallback(async (query, cursor) => {
|
|
13415
14150
|
if (!conversationId) return;
|
|
13416
14151
|
const isFirstPage = !cursor;
|
|
13417
14152
|
updateState({ isSearching: isFirstPage, isLoadingMoreSearch: !isFirstPage });
|
|
@@ -13432,7 +14167,7 @@ function useChannelHeader({
|
|
|
13432
14167
|
updateState({ isSearching: false, isLoadingMoreSearch: false });
|
|
13433
14168
|
}
|
|
13434
14169
|
}, [conversationId, updateState]);
|
|
13435
|
-
|
|
14170
|
+
React3.useEffect(() => {
|
|
13436
14171
|
if (debouncedSearch && conversationId) {
|
|
13437
14172
|
updateState({ searchCursor: null, searchHasMore: false });
|
|
13438
14173
|
handleSearch(debouncedSearch);
|
|
@@ -13466,32 +14201,32 @@ function useChannelHeader({
|
|
|
13466
14201
|
handleCloseSearch();
|
|
13467
14202
|
};
|
|
13468
14203
|
const canViewMembers = isAdmin || userPermissions.canAddMember || userPermissions.canRemoveMember;
|
|
13469
|
-
const prevIsClearingRef =
|
|
13470
|
-
|
|
14204
|
+
const prevIsClearingRef = React3.useRef(isClearingChat);
|
|
14205
|
+
React3.useEffect(() => {
|
|
13471
14206
|
if (prevIsClearingRef.current === true && !isClearingChat) {
|
|
13472
14207
|
updateState({ isClearChatAlertOpen: false });
|
|
13473
14208
|
}
|
|
13474
14209
|
prevIsClearingRef.current = isClearingChat;
|
|
13475
14210
|
}, [isClearingChat, updateState]);
|
|
13476
|
-
const prevIsDeletingRef =
|
|
13477
|
-
|
|
14211
|
+
const prevIsDeletingRef = React3.useRef(isDeletingConversation);
|
|
14212
|
+
React3.useEffect(() => {
|
|
13478
14213
|
if (prevIsDeletingRef.current === true && !isDeletingConversation) {
|
|
13479
14214
|
updateState({ isDeletingConversationAlertOpen: false });
|
|
13480
14215
|
onBack?.();
|
|
13481
14216
|
}
|
|
13482
14217
|
prevIsDeletingRef.current = isDeletingConversation;
|
|
13483
14218
|
}, [isDeletingConversation, onBack, updateState]);
|
|
13484
|
-
|
|
14219
|
+
React3.useEffect(() => {
|
|
13485
14220
|
if (state.isPinOpen && conversationId) {
|
|
13486
14221
|
fetchPinnedMessages2(conversationId);
|
|
13487
14222
|
}
|
|
13488
14223
|
}, [state.isPinOpen, conversationId, fetchPinnedMessages2]);
|
|
13489
|
-
|
|
14224
|
+
React3.useEffect(() => {
|
|
13490
14225
|
if (state.isFavoriteOpen && conversationId) {
|
|
13491
14226
|
fetchStarredMessages2(conversationId);
|
|
13492
14227
|
}
|
|
13493
14228
|
}, [state.isFavoriteOpen, conversationId, fetchStarredMessages2]);
|
|
13494
|
-
|
|
14229
|
+
React3.useEffect(() => {
|
|
13495
14230
|
if (state.isAttachmentsOpen && conversationId) {
|
|
13496
14231
|
const meta = exports.useChatStore.getState().messagesMetadata[conversationId];
|
|
13497
14232
|
if (!meta?.isFirstPage) {
|
|
@@ -13873,6 +14608,7 @@ var MessageReactions_default = MessageReactions;
|
|
|
13873
14608
|
var MessageToolbar = ({
|
|
13874
14609
|
isSender,
|
|
13875
14610
|
isRecent,
|
|
14611
|
+
isWithinDeleteWindow = isRecent,
|
|
13876
14612
|
isPinned,
|
|
13877
14613
|
isStarred,
|
|
13878
14614
|
isPinPending,
|
|
@@ -13896,7 +14632,7 @@ var MessageToolbar = ({
|
|
|
13896
14632
|
}) => {
|
|
13897
14633
|
const { isDark, scopeClassName, themeStyles } = useChatTheme();
|
|
13898
14634
|
const showDeleteMenu = isSender || hasAttachments || attachmentDeleteMode;
|
|
13899
|
-
const showDeleteForEveryone = isSender &&
|
|
14635
|
+
const showDeleteForEveryone = isSender && isWithinDeleteWindow;
|
|
13900
14636
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
13901
14637
|
"div",
|
|
13902
14638
|
{
|
|
@@ -14051,8 +14787,8 @@ function SentAttachmentCaptionModal({
|
|
|
14051
14787
|
canEdit = false,
|
|
14052
14788
|
onSave
|
|
14053
14789
|
}) {
|
|
14054
|
-
const [draft, setDraft] =
|
|
14055
|
-
|
|
14790
|
+
const [draft, setDraft] = React3.useState("");
|
|
14791
|
+
React3.useEffect(() => {
|
|
14056
14792
|
if (open && attachment) {
|
|
14057
14793
|
setDraft(attachment.caption || "");
|
|
14058
14794
|
}
|
|
@@ -14218,16 +14954,59 @@ function resolveForwardItems(selectedKeys, messages) {
|
|
|
14218
14954
|
}
|
|
14219
14955
|
|
|
14220
14956
|
// src/chat/lib/chat-edit-window.ts
|
|
14221
|
-
|
|
14222
|
-
|
|
14223
|
-
|
|
14957
|
+
init_settings_types();
|
|
14958
|
+
|
|
14959
|
+
// src/lib/effective-settings.helpers.ts
|
|
14960
|
+
function minutesToMs(minutes) {
|
|
14961
|
+
return Math.max(0, minutes) * 60 * 1e3;
|
|
14224
14962
|
}
|
|
14225
|
-
function
|
|
14963
|
+
function getEditWindowMs(timers, isGroup) {
|
|
14964
|
+
return minutesToMs(isGroup ? timers.groupEditMinutes : timers.dmEditMinutes);
|
|
14965
|
+
}
|
|
14966
|
+
function getDeleteWindowMs(timers, isGroup) {
|
|
14967
|
+
return minutesToMs(
|
|
14968
|
+
isGroup ? timers.groupDeleteMinutes : timers.dmDeleteMinutes
|
|
14969
|
+
);
|
|
14970
|
+
}
|
|
14971
|
+
function isWithinWindow(createdAt, windowMs) {
|
|
14226
14972
|
if (!createdAt) return false;
|
|
14227
14973
|
const date = new Date(createdAt);
|
|
14228
14974
|
if (isNaN(date.getTime())) return false;
|
|
14229
14975
|
const diff = Date.now() - date.getTime();
|
|
14230
|
-
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);
|
|
14231
15010
|
}
|
|
14232
15011
|
|
|
14233
15012
|
// src/chat/message-item/useMessageItemActions.ts
|
|
@@ -14252,7 +15031,7 @@ function useMessageItemActions({
|
|
|
14252
15031
|
selectionMode = false,
|
|
14253
15032
|
selectedKeys
|
|
14254
15033
|
}) {
|
|
14255
|
-
const [state, setState] =
|
|
15034
|
+
const [state, setState] = React3.useState({
|
|
14256
15035
|
isHoverMessage: false,
|
|
14257
15036
|
isEditing: false,
|
|
14258
15037
|
editValue: String(message || ""),
|
|
@@ -14265,7 +15044,7 @@ function useMessageItemActions({
|
|
|
14265
15044
|
const updateState = (updates) => {
|
|
14266
15045
|
setState((prev) => ({ ...prev, ...updates }));
|
|
14267
15046
|
};
|
|
14268
|
-
|
|
15047
|
+
React3.useEffect(() => {
|
|
14269
15048
|
setState((prev) => ({ ...prev, editValue: String(message || "") }));
|
|
14270
15049
|
}, [message]);
|
|
14271
15050
|
const emitDmEdit = exports.useChatStore((s) => s.emitDmEdit);
|
|
@@ -14305,6 +15084,9 @@ function useMessageItemActions({
|
|
|
14305
15084
|
const canUnpin = !isPinned || isPinnedByMe;
|
|
14306
15085
|
const { userPermissions } = useGroupInfo(conversationId || null);
|
|
14307
15086
|
const { formatMessageTime } = useChatLocale();
|
|
15087
|
+
const { settings } = useEffectiveSettingsOptional();
|
|
15088
|
+
const messageTimers = settings.messageTimers;
|
|
15089
|
+
const maxPinnedMessages = settings.maxPinnedMessagesPerConversation;
|
|
14308
15090
|
const visibleAttachments = getVisibleAttachments(attachments);
|
|
14309
15091
|
const hasAttachments = visibleAttachments.length > 0;
|
|
14310
15092
|
const hasMultiAttachments = hasAttachments && messageUsesAttachmentSelection({ attachments: visibleAttachments });
|
|
@@ -14321,7 +15103,8 @@ function useMessageItemActions({
|
|
|
14321
15103
|
const hasText = Boolean(message?.trim());
|
|
14322
15104
|
const isSelected = !!mid && !!selectedKeys && isMessageWhollySelected(selectedKeys, mid) && !hasMultiAttachments;
|
|
14323
15105
|
const canEdit = (!isGroup || userPermissions.canEditMessage) && hasText;
|
|
14324
|
-
const isWithinEditWindow = () =>
|
|
15106
|
+
const isWithinEditWindow = () => isWithinMessageEditWindow2(createdAt, isGroup, messageTimers);
|
|
15107
|
+
const isWithinDeleteWindow = () => isWithinMessageDeleteWindow2(createdAt, isGroup, messageTimers);
|
|
14325
15108
|
const canEditAttachmentCaption = isSender && isWithinEditWindow() && (!isGroup || userPermissions.canEditMessage) && !isDeletedForEveryone && !!mid;
|
|
14326
15109
|
const handleAttachmentCaptionClick = (attachment) => {
|
|
14327
15110
|
if (!canEditAttachmentCaption) return;
|
|
@@ -14490,6 +15273,15 @@ function useMessageItemActions({
|
|
|
14490
15273
|
});
|
|
14491
15274
|
}
|
|
14492
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
|
+
}
|
|
14493
15285
|
if (isGroup) {
|
|
14494
15286
|
if (!conversationId) return;
|
|
14495
15287
|
emitGroupPin({
|
|
@@ -14548,6 +15340,7 @@ function useMessageItemActions({
|
|
|
14548
15340
|
canUnpin,
|
|
14549
15341
|
canEdit,
|
|
14550
15342
|
isWithinEditWindow,
|
|
15343
|
+
isWithinDeleteWindow,
|
|
14551
15344
|
canEditAttachmentCaption,
|
|
14552
15345
|
visibleAttachments,
|
|
14553
15346
|
hasAttachments,
|
|
@@ -14579,7 +15372,7 @@ function useMessageItemActions({
|
|
|
14579
15372
|
}
|
|
14580
15373
|
|
|
14581
15374
|
// src/chat/lib/reply-preview.ts
|
|
14582
|
-
function
|
|
15375
|
+
function normalizeAttachments2(replyTo, loggedUserId) {
|
|
14583
15376
|
const raw = replyTo?.attachments;
|
|
14584
15377
|
if (!Array.isArray(raw) || raw.length === 0) return [];
|
|
14585
15378
|
return raw.map((att, index) => {
|
|
@@ -14592,7 +15385,7 @@ function resolveReplyToMessage(replyTo, messagesById, loggedUserId) {
|
|
|
14592
15385
|
if (typeof replyTo === "object" && (replyTo.content?.trim() || replyTo.attachments?.length)) {
|
|
14593
15386
|
return {
|
|
14594
15387
|
...replyTo,
|
|
14595
|
-
attachments:
|
|
15388
|
+
attachments: normalizeAttachments2(replyTo, loggedUserId)
|
|
14596
15389
|
};
|
|
14597
15390
|
}
|
|
14598
15391
|
const replyId = String(
|
|
@@ -15029,6 +15822,7 @@ function MessageItemView(props) {
|
|
|
15029
15822
|
canUnpin,
|
|
15030
15823
|
canEdit,
|
|
15031
15824
|
isWithinEditWindow,
|
|
15825
|
+
isWithinDeleteWindow,
|
|
15032
15826
|
canEditAttachmentCaption,
|
|
15033
15827
|
visibleAttachments,
|
|
15034
15828
|
hasAttachments,
|
|
@@ -15120,6 +15914,7 @@ function MessageItemView(props) {
|
|
|
15120
15914
|
{
|
|
15121
15915
|
isSender,
|
|
15122
15916
|
isRecent: isWithinEditWindow(),
|
|
15917
|
+
isWithinDeleteWindow: isWithinDeleteWindow(),
|
|
15123
15918
|
messageId: mid,
|
|
15124
15919
|
isPinned,
|
|
15125
15920
|
isStarred,
|
|
@@ -15309,7 +16104,7 @@ function MessageSelectionBar({
|
|
|
15309
16104
|
className
|
|
15310
16105
|
}) {
|
|
15311
16106
|
const { scopeClassName, themeStyles } = useChatTheme();
|
|
15312
|
-
const [isDeleteOpen, setIsDeleteOpen] =
|
|
16107
|
+
const [isDeleteOpen, setIsDeleteOpen] = React3.useState(false);
|
|
15313
16108
|
if (count === 0) return null;
|
|
15314
16109
|
const countLabel = selectionLabel === "files" ? count === 1 ? "file" : "files" : count === 1 ? "message" : "messages";
|
|
15315
16110
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -15414,6 +16209,7 @@ function MessageSelectionBar({
|
|
|
15414
16209
|
}
|
|
15415
16210
|
|
|
15416
16211
|
// src/chat/active-channel-messages/utils.ts
|
|
16212
|
+
init_settings_types();
|
|
15417
16213
|
var getMessageSenderId2 = (msg) => msg ? String(msg.senderId || msg.sender?._id || "") : "";
|
|
15418
16214
|
var isLikelyObjectId = (value) => /^[a-f\d]{24}$/i.test(value);
|
|
15419
16215
|
function resolveGroupSenderDisplay(message, allUsers = [], participants = []) {
|
|
@@ -15445,7 +16241,7 @@ var isSameMessageSide = (a, b, isGroupChat) => {
|
|
|
15445
16241
|
const bId = getMessageSenderId2(b);
|
|
15446
16242
|
return aId !== "" && aId === bId;
|
|
15447
16243
|
};
|
|
15448
|
-
function canDeleteSelectionForEveryone(selectedKeys, messages, isGroup) {
|
|
16244
|
+
function canDeleteSelectionForEveryone(selectedKeys, messages, isGroup, timers = exports.DEFAULT_EFFECTIVE_SETTINGS.messageTimers) {
|
|
15449
16245
|
if (selectedKeys.size === 0) return false;
|
|
15450
16246
|
const parsed = [...selectedKeys].map((key) => parseSelectionKey(key));
|
|
15451
16247
|
const messageIds = new Set(parsed.map((entry) => entry.messageId));
|
|
@@ -15453,7 +16249,7 @@ function canDeleteSelectionForEveryone(selectedKeys, messages, isGroup) {
|
|
|
15453
16249
|
const messageId2 = [...messageIds][0];
|
|
15454
16250
|
const message = messages.find((entry) => String(entry._id || entry.id) === messageId2);
|
|
15455
16251
|
if (!message?.isOwnMessage) return false;
|
|
15456
|
-
if (!
|
|
16252
|
+
if (!isWithinMessageDeleteWindow2(message.timestamp, isGroup, timers)) return false;
|
|
15457
16253
|
const hasAttachmentKey = parsed.some((entry) => entry.attachmentId);
|
|
15458
16254
|
if (!hasAttachmentKey) {
|
|
15459
16255
|
return selectedKeys.size === 1;
|
|
@@ -15617,22 +16413,24 @@ function useActiveChannelMessages({
|
|
|
15617
16413
|
onSelectionModeChange,
|
|
15618
16414
|
conversationInfo
|
|
15619
16415
|
}) {
|
|
15620
|
-
const [selectionMode, setSelectionMode] =
|
|
15621
|
-
const [selectedKeys, setSelectedKeys] =
|
|
16416
|
+
const [selectionMode, setSelectionMode] = React3.useState(false);
|
|
16417
|
+
const [selectedKeys, setSelectedKeys] = React3.useState(/* @__PURE__ */ new Set());
|
|
15622
16418
|
const emitDmDelete = exports.useChatStore((s) => s.emitDmDelete);
|
|
15623
16419
|
const emitGroupDelete = exports.useChatStore((s) => s.emitGroupDelete);
|
|
15624
16420
|
const loggedUserDetails = exports.useChatStore((s) => s.loggedUserDetails);
|
|
15625
|
-
const
|
|
15626
|
-
const
|
|
15627
|
-
const
|
|
15628
|
-
const
|
|
15629
|
-
const
|
|
15630
|
-
const
|
|
15631
|
-
const
|
|
15632
|
-
const
|
|
15633
|
-
const
|
|
15634
|
-
const
|
|
15635
|
-
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);
|
|
15636
16434
|
const { fetchMessages: fetchMessages2, messagesMetadata, deletedForMeIds, searchedMessageId, isSearchActive, setSearchActive, setSearchedMessageId, fetchSearchMessageContext } = exports.useChatStore();
|
|
15637
16435
|
const loggedUserImage = exports.useChatStore((s) => s.loggedUserDetails?.image);
|
|
15638
16436
|
const conversations = exports.useChatStore((s) => s.conversations);
|
|
@@ -15641,29 +16439,29 @@ function useActiveChannelMessages({
|
|
|
15641
16439
|
const mappedApiMessages = conversationMessages.map(
|
|
15642
16440
|
(m) => mapApiMessage(m, activeChannel, conversationId, loggedUserId, activeConversation)
|
|
15643
16441
|
);
|
|
15644
|
-
const displayMessages =
|
|
16442
|
+
const displayMessages = React3.useMemo(
|
|
15645
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()),
|
|
15646
16444
|
[mappedApiMessages, localMessages, loggedUserId, deletedForMeIds, conversationId]
|
|
15647
16445
|
);
|
|
15648
|
-
const messagesById =
|
|
16446
|
+
const messagesById = React3.useMemo(
|
|
15649
16447
|
() => new Map(displayMessages.map((message) => [String(message._id || message.id), message])),
|
|
15650
16448
|
[displayMessages]
|
|
15651
16449
|
);
|
|
15652
|
-
const messagesWithResolvedReplies =
|
|
16450
|
+
const messagesWithResolvedReplies = React3.useMemo(
|
|
15653
16451
|
() => displayMessages.map((message) => ({
|
|
15654
16452
|
...message,
|
|
15655
16453
|
replyTo: resolveReplyToMessage(message.replyTo, messagesById, loggedUserId)
|
|
15656
16454
|
})),
|
|
15657
16455
|
[displayMessages, messagesById, loggedUserId]
|
|
15658
16456
|
);
|
|
15659
|
-
const jumpDateBounds =
|
|
16457
|
+
const jumpDateBounds = React3.useMemo(
|
|
15660
16458
|
() => resolveJumpDateBounds(
|
|
15661
16459
|
conversationInfo?.createdAt,
|
|
15662
16460
|
displayMessages[0]?.timestamp
|
|
15663
16461
|
),
|
|
15664
16462
|
[conversationInfo?.createdAt, displayMessages]
|
|
15665
16463
|
);
|
|
15666
|
-
|
|
16464
|
+
React3.useEffect(() => {
|
|
15667
16465
|
const messages = messagesWithResolvedReplies;
|
|
15668
16466
|
const lastMessage = messages[messages.length - 1];
|
|
15669
16467
|
const lastMessageId = lastMessage ? String(lastMessage._id || lastMessage.id) : null;
|
|
@@ -15690,11 +16488,11 @@ function useActiveChannelMessages({
|
|
|
15690
16488
|
}, [messagesWithResolvedReplies]);
|
|
15691
16489
|
const isInitialLoading = isLoading && currentMeta?.isFirstPage;
|
|
15692
16490
|
const isLoadingMore = isLoading && !currentMeta?.isFirstPage;
|
|
15693
|
-
const clearSelection =
|
|
16491
|
+
const clearSelection = React3.useCallback(() => {
|
|
15694
16492
|
setSelectionMode(false);
|
|
15695
16493
|
setSelectedKeys(/* @__PURE__ */ new Set());
|
|
15696
16494
|
}, []);
|
|
15697
|
-
|
|
16495
|
+
React3.useEffect(() => {
|
|
15698
16496
|
clearSelection();
|
|
15699
16497
|
messageListInitializedRef.current = false;
|
|
15700
16498
|
previousMessageCountRef.current = 0;
|
|
@@ -15705,14 +16503,14 @@ function useActiveChannelMessages({
|
|
|
15705
16503
|
stickToBottomRef.current = true;
|
|
15706
16504
|
setShowScrollToBottom(false);
|
|
15707
16505
|
}, [conversationId, clearSelection]);
|
|
15708
|
-
const onSelectionModeChangeRef =
|
|
15709
|
-
|
|
16506
|
+
const onSelectionModeChangeRef = React3.useRef(onSelectionModeChange);
|
|
16507
|
+
React3.useEffect(() => {
|
|
15710
16508
|
onSelectionModeChangeRef.current = onSelectionModeChange;
|
|
15711
16509
|
}, [onSelectionModeChange]);
|
|
15712
|
-
|
|
16510
|
+
React3.useEffect(() => {
|
|
15713
16511
|
onSelectionModeChangeRef.current?.(selectionMode);
|
|
15714
16512
|
}, [selectionMode]);
|
|
15715
|
-
const toggleSelection =
|
|
16513
|
+
const toggleSelection = React3.useCallback((message, attachmentId) => {
|
|
15716
16514
|
const messageId2 = String(message._id || message.id);
|
|
15717
16515
|
if (!messageId2) return;
|
|
15718
16516
|
const useAttachmentSelection = messageUsesAttachmentSelection(message);
|
|
@@ -15725,7 +16523,7 @@ function useActiveChannelMessages({
|
|
|
15725
16523
|
return next;
|
|
15726
16524
|
});
|
|
15727
16525
|
}, []);
|
|
15728
|
-
const enterSelectionMode =
|
|
16526
|
+
const enterSelectionMode = React3.useCallback((message, attachmentId) => {
|
|
15729
16527
|
const messageId2 = String(message._id || message.id);
|
|
15730
16528
|
if (!messageId2) return;
|
|
15731
16529
|
setSelectionMode(true);
|
|
@@ -15739,17 +16537,23 @@ function useActiveChannelMessages({
|
|
|
15739
16537
|
setSelectedKeys((prev) => new Set(prev).add(messageId2));
|
|
15740
16538
|
}, []);
|
|
15741
16539
|
const selectedForwardItems = resolveForwardItems(selectedKeys, displayMessages);
|
|
15742
|
-
const canDeleteForEveryone =
|
|
15743
|
-
() => canDeleteSelectionForEveryone(
|
|
15744
|
-
|
|
16540
|
+
const canDeleteForEveryone = React3.useMemo(
|
|
16541
|
+
() => canDeleteSelectionForEveryone(
|
|
16542
|
+
selectedKeys,
|
|
16543
|
+
displayMessages,
|
|
16544
|
+
!!activeChannel?.isGroup,
|
|
16545
|
+
messageTimers
|
|
16546
|
+
),
|
|
16547
|
+
[selectedKeys, displayMessages, activeChannel?.isGroup, messageTimers]
|
|
15745
16548
|
);
|
|
15746
|
-
const emitSelectionDelete =
|
|
16549
|
+
const emitSelectionDelete = React3.useCallback(
|
|
15747
16550
|
(deleteType) => {
|
|
15748
16551
|
if (!loggedUserDetails || selectedKeys.size === 0) return;
|
|
15749
16552
|
if (deleteType === "everyone" && !canDeleteSelectionForEveryone(
|
|
15750
16553
|
selectedKeys,
|
|
15751
16554
|
displayMessages,
|
|
15752
|
-
!!activeChannel?.isGroup
|
|
16555
|
+
!!activeChannel?.isGroup,
|
|
16556
|
+
messageTimers
|
|
15753
16557
|
)) {
|
|
15754
16558
|
return;
|
|
15755
16559
|
}
|
|
@@ -15790,13 +16594,14 @@ function useActiveChannelMessages({
|
|
|
15790
16594
|
conversationId,
|
|
15791
16595
|
emitGroupDelete,
|
|
15792
16596
|
emitDmDelete,
|
|
15793
|
-
clearSelection
|
|
16597
|
+
clearSelection,
|
|
16598
|
+
messageTimers
|
|
15794
16599
|
]
|
|
15795
16600
|
);
|
|
15796
|
-
const handleBatchDeleteForMe =
|
|
16601
|
+
const handleBatchDeleteForMe = React3.useCallback(() => {
|
|
15797
16602
|
emitSelectionDelete("me");
|
|
15798
16603
|
}, [emitSelectionDelete]);
|
|
15799
|
-
const handleBatchDeleteForEveryone =
|
|
16604
|
+
const handleBatchDeleteForEveryone = React3.useCallback(() => {
|
|
15800
16605
|
emitSelectionDelete("everyone");
|
|
15801
16606
|
}, [emitSelectionDelete]);
|
|
15802
16607
|
const handleBatchForward = () => {
|
|
@@ -15820,7 +16625,7 @@ function useActiveChannelMessages({
|
|
|
15820
16625
|
}
|
|
15821
16626
|
await fetchSearchMessageContext(messageId2, { searchMode: false });
|
|
15822
16627
|
};
|
|
15823
|
-
const handleJumpTo =
|
|
16628
|
+
const handleJumpTo = React3.useCallback((preset, specificDate) => {
|
|
15824
16629
|
stickToBottomRef.current = false;
|
|
15825
16630
|
if (preset === "beginning") {
|
|
15826
16631
|
pendingJumpRef.current = { kind: "beginning" };
|
|
@@ -15841,7 +16646,7 @@ function useActiveChannelMessages({
|
|
|
15841
16646
|
jumpPagesRef.current = 0;
|
|
15842
16647
|
setJumpNonce((n) => n + 1);
|
|
15843
16648
|
}, [jumpDateBounds.minDay, jumpDateBounds.maxDay]);
|
|
15844
|
-
|
|
16649
|
+
React3.useEffect(() => {
|
|
15845
16650
|
const pending = pendingJumpRef.current;
|
|
15846
16651
|
if (!pending || isLoading) return;
|
|
15847
16652
|
const step = resolveJumpStep(
|
|
@@ -15880,13 +16685,13 @@ function useActiveChannelMessages({
|
|
|
15880
16685
|
fetchMessages2,
|
|
15881
16686
|
setSearchedMessageId
|
|
15882
16687
|
]);
|
|
15883
|
-
const updateScrollToBottomVisibility =
|
|
16688
|
+
const updateScrollToBottomVisibility = React3.useCallback((el) => {
|
|
15884
16689
|
const distanceFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight;
|
|
15885
16690
|
const nearBottom = distanceFromBottom <= 96;
|
|
15886
16691
|
stickToBottomRef.current = nearBottom;
|
|
15887
16692
|
setShowScrollToBottom(!nearBottom);
|
|
15888
16693
|
}, []);
|
|
15889
|
-
const handleScrollToBottom =
|
|
16694
|
+
const handleScrollToBottom = React3.useCallback(() => {
|
|
15890
16695
|
stickToBottomRef.current = true;
|
|
15891
16696
|
if (isSearchActive) {
|
|
15892
16697
|
setSearchActive(false);
|
|
@@ -15913,12 +16718,12 @@ function useActiveChannelMessages({
|
|
|
15913
16718
|
});
|
|
15914
16719
|
}
|
|
15915
16720
|
};
|
|
15916
|
-
|
|
16721
|
+
React3.useLayoutEffect(() => {
|
|
15917
16722
|
if (!isInitialLoading && stickToBottomRef.current && !pendingJumpRef.current) {
|
|
15918
16723
|
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
15919
16724
|
}
|
|
15920
16725
|
}, [messagesWithResolvedReplies.length, isInitialLoading]);
|
|
15921
|
-
|
|
16726
|
+
React3.useEffect(() => {
|
|
15922
16727
|
if (searchedMessageId && !isLoading) {
|
|
15923
16728
|
stickToBottomRef.current = false;
|
|
15924
16729
|
const container = scrollContainerRef.current;
|
|
@@ -16128,8 +16933,8 @@ function CalendarDayButton({
|
|
|
16128
16933
|
...props
|
|
16129
16934
|
}) {
|
|
16130
16935
|
const defaultClassNames = reactDayPicker.getDefaultClassNames();
|
|
16131
|
-
const ref =
|
|
16132
|
-
|
|
16936
|
+
const ref = React3__namespace.useRef(null);
|
|
16937
|
+
React3__namespace.useEffect(() => {
|
|
16133
16938
|
if (modifiers.focused) ref.current?.focus();
|
|
16134
16939
|
}, [modifiers.focused]);
|
|
16135
16940
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -16161,12 +16966,12 @@ var PRESETS = [
|
|
|
16161
16966
|
];
|
|
16162
16967
|
function ChatDateJumpMenu({ label, minDay, maxDay, onJump }) {
|
|
16163
16968
|
const { scopeClassName } = useChatTheme();
|
|
16164
|
-
const [open, setOpen] =
|
|
16165
|
-
const [showCalendar, setShowCalendar] =
|
|
16166
|
-
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));
|
|
16167
16972
|
const minDate = new Date(minDay);
|
|
16168
16973
|
const maxDate = new Date(maxDay);
|
|
16169
|
-
|
|
16974
|
+
React3.useEffect(() => {
|
|
16170
16975
|
if (showCalendar) setCalendarMonth(new Date(maxDay));
|
|
16171
16976
|
}, [showCalendar, maxDay]);
|
|
16172
16977
|
const queueJump = (preset, specificDate) => {
|
|
@@ -16500,8 +17305,8 @@ function AttachmentCaptionModal({
|
|
|
16500
17305
|
attachment,
|
|
16501
17306
|
onSave
|
|
16502
17307
|
}) {
|
|
16503
|
-
const [draft, setDraft] =
|
|
16504
|
-
|
|
17308
|
+
const [draft, setDraft] = React3.useState("");
|
|
17309
|
+
React3.useEffect(() => {
|
|
16505
17310
|
if (open && attachment) {
|
|
16506
17311
|
setDraft(attachment.caption || "");
|
|
16507
17312
|
}
|
|
@@ -16878,9 +17683,9 @@ function ComposerAttachmentPreview({
|
|
|
16878
17683
|
embedded = false,
|
|
16879
17684
|
maxAttachments = COMPOSER_MAX_ATTACHMENTS
|
|
16880
17685
|
}) {
|
|
16881
|
-
const [captionTargetId, setCaptionTargetId] =
|
|
16882
|
-
const [lightboxState, setLightboxState] =
|
|
16883
|
-
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(() => {
|
|
16884
17689
|
const mediaItems = attachments.filter(
|
|
16885
17690
|
(item) => (item.type === "image" || item.type === "video") && item.previewUrl
|
|
16886
17691
|
);
|
|
@@ -17033,7 +17838,6 @@ var getAttachmentType = (file) => {
|
|
|
17033
17838
|
};
|
|
17034
17839
|
|
|
17035
17840
|
// src/chat/channel-message-box/useChannelMessageBox.ts
|
|
17036
|
-
var MAX_ATTACHMENTS = COMPOSER_MAX_ATTACHMENTS;
|
|
17037
17841
|
function useChannelMessageBox({
|
|
17038
17842
|
activeChannel,
|
|
17039
17843
|
conversationId,
|
|
@@ -17047,7 +17851,13 @@ function useChannelMessageBox({
|
|
|
17047
17851
|
conversationId,
|
|
17048
17852
|
onActiveChannelPatch
|
|
17049
17853
|
);
|
|
17050
|
-
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({
|
|
17051
17861
|
messageInput: "",
|
|
17052
17862
|
attachments: [],
|
|
17053
17863
|
isFocused: false,
|
|
@@ -17057,8 +17867,8 @@ function useChannelMessageBox({
|
|
|
17057
17867
|
const updateState = (updates) => {
|
|
17058
17868
|
setState((prev) => ({ ...prev, ...updates }));
|
|
17059
17869
|
};
|
|
17060
|
-
const typingTimeoutRef =
|
|
17061
|
-
const conversationIdRef =
|
|
17870
|
+
const typingTimeoutRef = React3.useRef(null);
|
|
17871
|
+
const conversationIdRef = React3.useRef(conversationId);
|
|
17062
17872
|
conversationIdRef.current = conversationId;
|
|
17063
17873
|
const { syncComposerRef } = useConversationDraft(conversationId);
|
|
17064
17874
|
const emitTypingStart = exports.useChatStore((s) => s.emitTypingStart);
|
|
@@ -17069,12 +17879,12 @@ function useChannelMessageBox({
|
|
|
17069
17879
|
const allUsers = exports.useChatStore((s) => s.allUsers);
|
|
17070
17880
|
const composerDisabledByConversation = exports.useChatStore((s) => s.composerDisabledByConversation);
|
|
17071
17881
|
const composerDisabledReason = conversationId ? composerDisabledByConversation[conversationId] : void 0;
|
|
17072
|
-
const fileInputRef =
|
|
17073
|
-
const attachmentsCountRef =
|
|
17074
|
-
|
|
17882
|
+
const fileInputRef = React3.useRef(null);
|
|
17883
|
+
const attachmentsCountRef = React3.useRef(0);
|
|
17884
|
+
React3__namespace.default.useEffect(() => {
|
|
17075
17885
|
attachmentsCountRef.current = state.attachments.length;
|
|
17076
17886
|
}, [state.attachments.length]);
|
|
17077
|
-
|
|
17887
|
+
React3__namespace.default.useEffect(() => {
|
|
17078
17888
|
const draft = {
|
|
17079
17889
|
messageInput: state.messageInput,
|
|
17080
17890
|
attachments: state.attachments
|
|
@@ -17082,7 +17892,7 @@ function useChannelMessageBox({
|
|
|
17082
17892
|
syncComposerRef(draft);
|
|
17083
17893
|
updateConversationDraft(conversationIdRef.current, draft);
|
|
17084
17894
|
}, [state.messageInput, state.attachments, syncComposerRef]);
|
|
17085
|
-
|
|
17895
|
+
React3__namespace.default.useEffect(() => {
|
|
17086
17896
|
if (typingTimeoutRef.current) {
|
|
17087
17897
|
clearTimeout(typingTimeoutRef.current);
|
|
17088
17898
|
typingTimeoutRef.current = null;
|
|
@@ -17142,21 +17952,52 @@ function useChannelMessageBox({
|
|
|
17142
17952
|
const handleFileChange = (e) => {
|
|
17143
17953
|
const files = e.target.files ? Array.from(e.target.files) : [];
|
|
17144
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
|
+
}
|
|
17145
17962
|
const currentCount = attachmentsCountRef.current;
|
|
17146
|
-
const remaining =
|
|
17963
|
+
const remaining = maxAttachments - currentCount;
|
|
17147
17964
|
if (remaining <= 0) {
|
|
17148
|
-
updateState({ attachmentError: `Maximum ${
|
|
17965
|
+
updateState({ attachmentError: `Maximum ${maxAttachments} files allowed` });
|
|
17149
17966
|
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
17150
17967
|
return;
|
|
17151
17968
|
}
|
|
17152
|
-
|
|
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
|
+
});
|
|
17988
|
+
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
17989
|
+
return;
|
|
17990
|
+
}
|
|
17991
|
+
if (validFiles.length > remaining) {
|
|
17153
17992
|
updateState({
|
|
17154
17993
|
attachmentError: `You can upload only ${remaining} more file${remaining > 1 ? "s" : ""}`
|
|
17155
17994
|
});
|
|
17995
|
+
} else if (rejectionMessages.length > 0) {
|
|
17996
|
+
updateState({ attachmentError: rejectionMessages[0] });
|
|
17156
17997
|
} else {
|
|
17157
17998
|
updateState({ attachmentError: "" });
|
|
17158
17999
|
}
|
|
17159
|
-
const filesToAdd =
|
|
18000
|
+
const filesToAdd = validFiles.slice(0, remaining);
|
|
17160
18001
|
attachmentsCountRef.current = currentCount + filesToAdd.length;
|
|
17161
18002
|
const newAttachments = filesToAdd.map((file) => ({
|
|
17162
18003
|
id: `att-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
@@ -17213,7 +18054,7 @@ function useChannelMessageBox({
|
|
|
17213
18054
|
return {
|
|
17214
18055
|
...prev,
|
|
17215
18056
|
attachments: nextAttachments,
|
|
17216
|
-
attachmentError: nextAttachments.length <
|
|
18057
|
+
attachmentError: nextAttachments.length < maxAttachments ? "" : prev.attachmentError
|
|
17217
18058
|
};
|
|
17218
18059
|
});
|
|
17219
18060
|
};
|
|
@@ -17320,7 +18161,10 @@ function useChannelMessageBox({
|
|
|
17320
18161
|
onlyAdminCanSendMessage,
|
|
17321
18162
|
fileInputRef,
|
|
17322
18163
|
hasUploadingAttachments,
|
|
17323
|
-
maxAttachments
|
|
18164
|
+
maxAttachments,
|
|
18165
|
+
acceptAttribute,
|
|
18166
|
+
attachmentsEnabled: attachmentsGate.enabled,
|
|
18167
|
+
attachmentsDisabledReason: attachmentsGate.disabledReason,
|
|
17324
18168
|
handleInputChange,
|
|
17325
18169
|
handleFileChange,
|
|
17326
18170
|
handleRemoveAttachment,
|
|
@@ -17348,6 +18192,9 @@ var ChannelMessageBoxView = (props) => {
|
|
|
17348
18192
|
fileInputRef,
|
|
17349
18193
|
hasUploadingAttachments,
|
|
17350
18194
|
maxAttachments,
|
|
18195
|
+
acceptAttribute,
|
|
18196
|
+
attachmentsEnabled,
|
|
18197
|
+
attachmentsDisabledReason,
|
|
17351
18198
|
handleInputChange,
|
|
17352
18199
|
handleFileChange,
|
|
17353
18200
|
handleRemoveAttachment,
|
|
@@ -17445,16 +18292,23 @@ var ChannelMessageBoxView = (props) => {
|
|
|
17445
18292
|
),
|
|
17446
18293
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-end gap-1.5 p-1.5", children: [
|
|
17447
18294
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17448
|
-
|
|
18295
|
+
AdminPermissionTooltip,
|
|
17449
18296
|
{
|
|
17450
|
-
|
|
17451
|
-
|
|
17452
|
-
|
|
17453
|
-
|
|
17454
|
-
|
|
17455
|
-
|
|
17456
|
-
|
|
17457
|
-
|
|
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
|
+
)
|
|
17458
18312
|
}
|
|
17459
18313
|
),
|
|
17460
18314
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -17464,8 +18318,9 @@ var ChannelMessageBoxView = (props) => {
|
|
|
17464
18318
|
ref: fileInputRef,
|
|
17465
18319
|
className: "hidden",
|
|
17466
18320
|
multiple: true,
|
|
17467
|
-
accept:
|
|
17468
|
-
onChange: handleFileChange
|
|
18321
|
+
accept: acceptAttribute || void 0,
|
|
18322
|
+
onChange: handleFileChange,
|
|
18323
|
+
disabled: !attachmentsEnabled
|
|
17469
18324
|
}
|
|
17470
18325
|
),
|
|
17471
18326
|
/* @__PURE__ */ jsxRuntime.jsxs(Popover, { children: [
|
|
@@ -17544,11 +18399,11 @@ var ChannelMessageBoxView_default = ChannelMessageBoxView;
|
|
|
17544
18399
|
// src/chat/forward-modal/useForwardModal.ts
|
|
17545
18400
|
init_useStore();
|
|
17546
18401
|
function useForwardModal({ isOpen, onClose, items, onForwardComplete }) {
|
|
17547
|
-
const [search, setSearch] =
|
|
17548
|
-
const [debouncedSearch, setDebouncedSearch] =
|
|
17549
|
-
const targetChannelRef =
|
|
17550
|
-
const wasForwardingRef =
|
|
17551
|
-
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);
|
|
17552
18407
|
const emitDmForward = exports.useChatStore((s) => s.emitDmForward);
|
|
17553
18408
|
const emitGroupForward = exports.useChatStore((s) => s.emitGroupForward);
|
|
17554
18409
|
const loggedUserDetails = exports.useChatStore((s) => s.loggedUserDetails);
|
|
@@ -17556,23 +18411,23 @@ function useForwardModal({ isOpen, onClose, items, onForwardComplete }) {
|
|
|
17556
18411
|
const storeConversations = exports.useChatStore((s) => s.conversations);
|
|
17557
18412
|
const allUsers = exports.useChatStore((s) => s.allUsers);
|
|
17558
18413
|
const sourceMessage = items[0]?.message ?? null;
|
|
17559
|
-
const mids =
|
|
18414
|
+
const mids = React3.useMemo(
|
|
17560
18415
|
() => items.map((item) => String(item.message._id || item.message.id || "")).filter(Boolean),
|
|
17561
18416
|
[items]
|
|
17562
18417
|
);
|
|
17563
18418
|
const isForwarding = mids.some((id) => pendingActions[id]?.includes("forward"));
|
|
17564
|
-
const onCloseRef =
|
|
17565
|
-
const onForwardCompleteRef =
|
|
17566
|
-
|
|
18419
|
+
const onCloseRef = React3.useRef(onClose);
|
|
18420
|
+
const onForwardCompleteRef = React3.useRef(onForwardComplete);
|
|
18421
|
+
React3.useEffect(() => {
|
|
17567
18422
|
onCloseRef.current = onClose;
|
|
17568
18423
|
}, [onClose]);
|
|
17569
|
-
|
|
18424
|
+
React3.useEffect(() => {
|
|
17570
18425
|
onForwardCompleteRef.current = onForwardComplete;
|
|
17571
18426
|
}, [onForwardComplete]);
|
|
17572
|
-
const handleOpenChange =
|
|
18427
|
+
const handleOpenChange = React3.useCallback((open) => {
|
|
17573
18428
|
if (!open) onCloseRef.current();
|
|
17574
18429
|
}, []);
|
|
17575
|
-
|
|
18430
|
+
React3.useEffect(() => {
|
|
17576
18431
|
if (isForwarding) {
|
|
17577
18432
|
wasForwardingRef.current = true;
|
|
17578
18433
|
const timeout = setTimeout(() => {
|
|
@@ -17590,7 +18445,7 @@ function useForwardModal({ isOpen, onClose, items, onForwardComplete }) {
|
|
|
17590
18445
|
queueMicrotask(() => onForwardCompleteRef.current(target));
|
|
17591
18446
|
}
|
|
17592
18447
|
}, [isForwarding, mids]);
|
|
17593
|
-
|
|
18448
|
+
React3.useEffect(() => {
|
|
17594
18449
|
if (!isOpen) {
|
|
17595
18450
|
setSearch("");
|
|
17596
18451
|
setDebouncedSearch("");
|
|
@@ -17599,11 +18454,11 @@ function useForwardModal({ isOpen, onClose, items, onForwardComplete }) {
|
|
|
17599
18454
|
completionHandledRef.current = false;
|
|
17600
18455
|
}
|
|
17601
18456
|
}, [isOpen]);
|
|
17602
|
-
|
|
18457
|
+
React3.useEffect(() => {
|
|
17603
18458
|
const handler = setTimeout(() => setDebouncedSearch(search), 400);
|
|
17604
18459
|
return () => clearTimeout(handler);
|
|
17605
18460
|
}, [search]);
|
|
17606
|
-
const mappedChannels =
|
|
18461
|
+
const mappedChannels = React3.useMemo(() => {
|
|
17607
18462
|
const sourceConversationId = sourceMessage?.conversationId ? String(sourceMessage.conversationId) : null;
|
|
17608
18463
|
const query = debouncedSearch.trim().toLowerCase();
|
|
17609
18464
|
return storeConversations.filter((c) => !sourceConversationId || String(c._id) !== sourceConversationId).map((c) => {
|
|
@@ -17731,7 +18586,7 @@ function ForwardModalView(props) {
|
|
|
17731
18586
|
|
|
17732
18587
|
// src/chat/ChatPanelAlerts.tsx
|
|
17733
18588
|
init_useStore();
|
|
17734
|
-
var ChatAlertsContext =
|
|
18589
|
+
var ChatAlertsContext = React3.createContext({});
|
|
17735
18590
|
function ChatAlertsProvider({
|
|
17736
18591
|
children,
|
|
17737
18592
|
value
|
|
@@ -17739,7 +18594,7 @@ function ChatAlertsProvider({
|
|
|
17739
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 }) });
|
|
17740
18595
|
}
|
|
17741
18596
|
function useChatAlerts() {
|
|
17742
|
-
return
|
|
18597
|
+
return React3.useContext(ChatAlertsContext);
|
|
17743
18598
|
}
|
|
17744
18599
|
var normalizeMessage = (message) => message.trim().toLowerCase();
|
|
17745
18600
|
var alertStyles = {
|
|
@@ -17754,14 +18609,14 @@ var ChatPanelAlerts = () => {
|
|
|
17754
18609
|
const conversationErrors = exports.useChatStore((s) => s.conversationErrors);
|
|
17755
18610
|
const clearAppError = exports.useChatStore((s) => s.clearAppError);
|
|
17756
18611
|
const rateLimitResetAt2 = exports.useChatStore((s) => s.rateLimitResetAt);
|
|
17757
|
-
const [now, setNow] =
|
|
18612
|
+
const [now, setNow] = React3.useState(() => Date.now());
|
|
17758
18613
|
const conversationAppError = activeConversationId ? conversationErrors[activeConversationId] ?? null : null;
|
|
17759
|
-
|
|
18614
|
+
React3.useEffect(() => {
|
|
17760
18615
|
if (rateLimitResetAt2 <= Date.now()) return;
|
|
17761
18616
|
const id = window.setInterval(() => setNow(Date.now()), 1e3);
|
|
17762
18617
|
return () => window.clearInterval(id);
|
|
17763
18618
|
}, [rateLimitResetAt2]);
|
|
17764
|
-
const alerts =
|
|
18619
|
+
const alerts = React3.useMemo(() => {
|
|
17765
18620
|
const items = [];
|
|
17766
18621
|
const seen = /* @__PURE__ */ new Set();
|
|
17767
18622
|
const push = (item) => {
|
|
@@ -18185,9 +19040,9 @@ var emitToast = (payload, onPush) => {
|
|
|
18185
19040
|
};
|
|
18186
19041
|
var ForegroundPushBridge = ({ onPush }) => {
|
|
18187
19042
|
const lastDM = exports.useChatStore((s) => s.lastDM);
|
|
18188
|
-
const onPushRef =
|
|
19043
|
+
const onPushRef = React3.useRef(onPush);
|
|
18189
19044
|
onPushRef.current = onPush;
|
|
18190
|
-
|
|
19045
|
+
React3.useEffect(() => {
|
|
18191
19046
|
if (!lastDM) return;
|
|
18192
19047
|
if (typeof document !== "undefined" && document.visibilityState !== "visible") {
|
|
18193
19048
|
return;
|
|
@@ -18227,7 +19082,7 @@ var ForegroundPushBridge = ({ onPush }) => {
|
|
|
18227
19082
|
onPushRef.current
|
|
18228
19083
|
);
|
|
18229
19084
|
}, [lastDM]);
|
|
18230
|
-
|
|
19085
|
+
React3.useEffect(() => {
|
|
18231
19086
|
let unsubscribe = null;
|
|
18232
19087
|
let retryTimer = null;
|
|
18233
19088
|
let cancelled = false;
|
|
@@ -18303,7 +19158,7 @@ var ForegroundPushBridge = ({ onPush }) => {
|
|
|
18303
19158
|
window.removeEventListener(PUSH_CHANGED_EVENT, onPushChanged);
|
|
18304
19159
|
};
|
|
18305
19160
|
}, []);
|
|
18306
|
-
|
|
19161
|
+
React3.useEffect(() => {
|
|
18307
19162
|
const onOpen = (event) => {
|
|
18308
19163
|
const id = String(
|
|
18309
19164
|
event.detail?.conversationId || ""
|
|
@@ -18353,6 +19208,7 @@ var ChatMain = ({
|
|
|
18353
19208
|
queryParams,
|
|
18354
19209
|
queryParamApis,
|
|
18355
19210
|
queryParamsByApi,
|
|
19211
|
+
apiVersions: apiVersions2,
|
|
18356
19212
|
themeColor = "#7494ec",
|
|
18357
19213
|
theme,
|
|
18358
19214
|
uiConfig,
|
|
@@ -18379,8 +19235,8 @@ var ChatMain = ({
|
|
|
18379
19235
|
viewportHeight = "full",
|
|
18380
19236
|
viewportClassName
|
|
18381
19237
|
}) => {
|
|
18382
|
-
const clientObj =
|
|
18383
|
-
const uiConfigObj =
|
|
19238
|
+
const clientObj = React3__namespace.default.useMemo(() => ({ id: clientId }), [clientId]);
|
|
19239
|
+
const uiConfigObj = React3__namespace.default.useMemo(
|
|
18384
19240
|
() => ({
|
|
18385
19241
|
...uiConfig || {},
|
|
18386
19242
|
components: { ...uiConfig?.components, ...components },
|
|
@@ -18422,6 +19278,7 @@ var ChatMain = ({
|
|
|
18422
19278
|
queryParams,
|
|
18423
19279
|
queryParamApis,
|
|
18424
19280
|
queryParamsByApi,
|
|
19281
|
+
apiVersions: apiVersions2,
|
|
18425
19282
|
children: [
|
|
18426
19283
|
/* @__PURE__ */ jsxRuntime.jsx(ForegroundPushBridge, {}),
|
|
18427
19284
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -18714,6 +19571,10 @@ var ChannelListItem_default = ChannelListItem2;
|
|
|
18714
19571
|
var packageDefaultComponents = {
|
|
18715
19572
|
ChatLayout: DefaultChatLayout_default,
|
|
18716
19573
|
LoggedUserDetails: LoggedUserDetails_default,
|
|
19574
|
+
LoggedUserSettingsDialog: LoggedUserSettingsDialog_default,
|
|
19575
|
+
LoggedUserSettingsTrigger: LoggedUserSettingsTrigger_default,
|
|
19576
|
+
LoggedUserSettingsContent: LoggedUserSettingsContent_default,
|
|
19577
|
+
PushNotificationToggle,
|
|
18717
19578
|
ChannelList: ChannelListView_default,
|
|
18718
19579
|
ChannelListItem: DefaultChannelListItem,
|
|
18719
19580
|
ChannelHeader: ChannelHeaderView_default,
|
|
@@ -18746,6 +19607,8 @@ var packageDefaultComponents = {
|
|
|
18746
19607
|
};
|
|
18747
19608
|
|
|
18748
19609
|
// src/index.ts
|
|
19610
|
+
init_settings_types();
|
|
19611
|
+
init_api_service();
|
|
18749
19612
|
var index_default = ChatMain_default;
|
|
18750
19613
|
|
|
18751
19614
|
exports.Calendar = Calendar;
|
|
@@ -18759,6 +19622,7 @@ exports.ChatAlertsProvider = ChatAlertsProvider;
|
|
|
18759
19622
|
exports.ChatAvatar = ChatAvatar_default;
|
|
18760
19623
|
exports.ChatCustomizationProvider = ChatCustomizationProvider;
|
|
18761
19624
|
exports.ChatDateJumpMenu = ChatDateJumpMenu;
|
|
19625
|
+
exports.ChatEffectiveSettingsProvider = ChatEffectiveSettingsProvider;
|
|
18762
19626
|
exports.ChatLayout = ChatLayout_default;
|
|
18763
19627
|
exports.ChatLocaleProvider = ChatLocaleProvider;
|
|
18764
19628
|
exports.ChatMain = ChatMain_default;
|
|
@@ -18771,6 +19635,9 @@ exports.ForegroundPushBridge = ForegroundPushBridge;
|
|
|
18771
19635
|
exports.ForwardModal = ForwardModalView;
|
|
18772
19636
|
exports.HeaderCallActions = HeaderCallActions_default;
|
|
18773
19637
|
exports.LoggedUserDetails = LoggedUserDetails_default;
|
|
19638
|
+
exports.LoggedUserSettingsContent = LoggedUserSettingsContent_default;
|
|
19639
|
+
exports.LoggedUserSettingsDialog = LoggedUserSettingsDialog_default;
|
|
19640
|
+
exports.LoggedUserSettingsTrigger = LoggedUserSettingsTrigger_default;
|
|
18774
19641
|
exports.MessageInput = ChannelMessageBoxView_default;
|
|
18775
19642
|
exports.MessageItem = MessageItemView;
|
|
18776
19643
|
exports.MessageList = ActiveChannelMessagesView_default;
|
|
@@ -18786,6 +19653,7 @@ exports.apiRegisterPushToken = apiRegisterPushToken;
|
|
|
18786
19653
|
exports.apiRemovePushToken = apiRemovePushToken;
|
|
18787
19654
|
exports.apiUpdatePushPreference = apiUpdatePushPreference;
|
|
18788
19655
|
exports.buildChannelFromPushRequest = buildChannelFromPushRequest;
|
|
19656
|
+
exports.buildLoggedUserProfile = buildLoggedUserProfile;
|
|
18789
19657
|
exports.capitalizeFirst = capitalizeFirst;
|
|
18790
19658
|
exports.clampJumpDate = clampJumpDate;
|
|
18791
19659
|
exports.consumePendingOpenConversation = consumePendingOpenConversation;
|
|
@@ -18834,6 +19702,8 @@ exports.useChatFeatures = useChatFeatures;
|
|
|
18834
19702
|
exports.useChatFeaturesOptional = useChatFeaturesOptional;
|
|
18835
19703
|
exports.useChatLocale = useChatLocale;
|
|
18836
19704
|
exports.useChatTheme = useChatTheme;
|
|
19705
|
+
exports.useEffectiveSettings = useEffectiveSettings;
|
|
19706
|
+
exports.useEffectiveSettingsOptional = useEffectiveSettingsOptional;
|
|
18837
19707
|
exports.usePushNotifications = usePushNotifications;
|
|
18838
19708
|
//# sourceMappingURL=index.cjs.map
|
|
18839
19709
|
//# sourceMappingURL=index.cjs.map
|