@realtimexsco/live-chat 1.3.3 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -15,12 +15,31 @@ var reactDom = require('react-dom');
15
15
  var lucideReact = require('lucide-react');
16
16
  var classVarianceAuthority = require('class-variance-authority');
17
17
  var EmojiPicker = require('emoji-picker-react');
18
+ var reactDayPicker = require('react-day-picker');
18
19
  var reactHotToast = require('react-hot-toast');
19
20
 
20
21
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
21
22
 
23
+ function _interopNamespace(e) {
24
+ if (e && e.__esModule) return e;
25
+ var n = Object.create(null);
26
+ if (e) {
27
+ Object.keys(e).forEach(function (k) {
28
+ if (k !== 'default') {
29
+ var d = Object.getOwnPropertyDescriptor(e, k);
30
+ Object.defineProperty(n, k, d.get ? d : {
31
+ enumerable: true,
32
+ get: function () { return e[k]; }
33
+ });
34
+ }
35
+ });
36
+ }
37
+ n.default = e;
38
+ return Object.freeze(n);
39
+ }
40
+
22
41
  var axios__default = /*#__PURE__*/_interopDefault(axios);
23
- var React2__default = /*#__PURE__*/_interopDefault(React2);
42
+ var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
24
43
  var EmojiPicker__default = /*#__PURE__*/_interopDefault(EmojiPicker);
25
44
 
26
45
  var __defProp = Object.defineProperty;
@@ -570,7 +589,7 @@ var init_message_helpers = __esm({
570
589
  "src/store/helpers/message.helpers.ts"() {
571
590
  getMessageSenderId = (message) => String(message?.sender?._id || message?.sender?.id || message?.senderId || message?.fromUserId || message?.sender || "");
572
591
  extractMessageData = (payload) => {
573
- const messageId = payload.messageId || payload._id || payload.message?._id || payload.message?.id;
592
+ const messageId2 = payload.messageId || payload._id || payload.message?._id || payload.message?.id;
574
593
  const content = payload.content || payload.message?.content;
575
594
  const conversationId = payload.conversationId || payload.conversation_id || payload.message?.conversationId || payload.message?.conversation_id;
576
595
  const status = payload.status || payload.message?.status;
@@ -578,7 +597,7 @@ var init_message_helpers = __esm({
578
597
  const isStarred = payload.isStarred ?? payload.message?.isStarred;
579
598
  const attachmentId = payload.attachmentId || payload.unpinAttachmentId || null;
580
599
  const caption = payload.caption ?? payload.message?.caption ?? null;
581
- return { messageId, content, conversationId, status, isPinned, isStarred, attachmentId, caption };
600
+ return { messageId: messageId2, content, conversationId, status, isPinned, isStarred, attachmentId, caption };
582
601
  };
583
602
  statusRank = { sent: 0, delivered: 1, read: 2 };
584
603
  preferHigherStatus = (base, incoming) => {
@@ -809,15 +828,15 @@ var init_conversation_helpers = __esm({
809
828
  init_message_helpers();
810
829
  init_participant_helpers();
811
830
  init_unread_helpers();
812
- findConversationIdByMessageId = (messagesByConversation, messageId) => {
831
+ findConversationIdByMessageId = (messagesByConversation, messageId2) => {
813
832
  return Object.keys(messagesByConversation).find(
814
833
  (cid) => messagesByConversation[cid].some(
815
- (m) => String(m._id || m.id) === String(messageId)
834
+ (m) => String(m._id || m.id) === String(messageId2)
816
835
  )
817
836
  );
818
837
  };
819
- applyMessageStatusToStore = (state, messageId, status, conversationId) => {
820
- const normalizedMessageId = String(messageId);
838
+ applyMessageStatusToStore = (state, messageId2, status, conversationId) => {
839
+ const normalizedMessageId = String(messageId2);
821
840
  const resolvedConversationId = conversationId ? String(conversationId) : findConversationIdByMessageId(state.messagesByConversation, normalizedMessageId) || findConversationIdByLastMessageId(state.conversations, normalizedMessageId) || null;
822
841
  const nextConversations = state.conversations.map((conversation) => {
823
842
  const lastMessageId = String(
@@ -860,6 +879,9 @@ var init_conversation_helpers = __esm({
860
879
  const mergedParticipants = conversation.participants !== void 0 ? mergeConversationParticipants(existing?.participants, conversation.participants) : existing?.participants ?? conversation.participants;
861
880
  const isGroup = isGroupConversation(conversation) || isGroupConversation(existing);
862
881
  const resolvedGroupImage = resolveGroupImage(conversation) || resolveGroupImage(existing);
882
+ const incomingGroupName = typeof conversation.groupName === "string" && conversation.groupName.trim() || typeof conversation.name === "string" && conversation.name.trim() || "";
883
+ const existingGroupName = typeof existing?.groupName === "string" && existing.groupName.trim() || typeof existing?.name === "string" && existing.name.trim() || "";
884
+ const resolvedGroupName = incomingGroupName || existingGroupName || void 0;
863
885
  return {
864
886
  ...existing,
865
887
  ...conversation,
@@ -867,7 +889,10 @@ var init_conversation_helpers = __esm({
867
889
  isGroup,
868
890
  isBlocked: resolvedBlocked,
869
891
  lastMessage: mergeLastMessage(existing?.lastMessage, conversation.lastMessage),
870
- ...isGroup && resolvedGroupImage ? { image: resolvedGroupImage, groupImage: resolvedGroupImage } : {}
892
+ ...isGroup ? {
893
+ ...resolvedGroupName ? { groupName: resolvedGroupName, name: resolvedGroupName } : {},
894
+ ...resolvedGroupImage ? { image: resolvedGroupImage, groupImage: resolvedGroupImage } : {}
895
+ } : {}
871
896
  };
872
897
  };
873
898
  resolveConversationLastMessage = (conversation, messagesByConversation) => {
@@ -939,9 +964,9 @@ var init_conversation_helpers = __esm({
939
964
  if (!conversationId) return void 0;
940
965
  return conversations.find((c) => String(c._id) === String(conversationId));
941
966
  };
942
- findConversationIdByLastMessageId = (conversations, messageId) => {
943
- if (!messageId) return null;
944
- const normalizedMessageId = String(messageId);
967
+ findConversationIdByLastMessageId = (conversations, messageId2) => {
968
+ if (!messageId2) return null;
969
+ const normalizedMessageId = String(messageId2);
945
970
  const match = conversations.find(
946
971
  (conversation) => String(conversation?.lastMessage?._id || conversation?.lastMessage?.id || "") === normalizedMessageId
947
972
  );
@@ -1360,7 +1385,7 @@ var init_api_constants = __esm({
1360
1385
  ADD_REMOVE_MEMBERS: "/conversation/group/participants/add-remove",
1361
1386
  ADD_REMOVE_ADMINS: "/conversation/group/admins/add-remove",
1362
1387
  SEARCH_MESSAGES: "/message/search-messages",
1363
- SEARCH_MESSAGES_CONTEXT: (messageId) => `/message/searched-message/context?messageId=${messageId}`,
1388
+ SEARCH_MESSAGES_CONTEXT: (messageId2) => `/message/searched-message/context?messageId=${messageId2}`,
1364
1389
  BLOCK_UNBLOCK_USER: "/user/block-unblock"
1365
1390
  }
1366
1391
  };
@@ -1504,9 +1529,9 @@ var init_messages_api = __esm({
1504
1529
  throw error;
1505
1530
  }
1506
1531
  };
1507
- searchMessagesContext = async (messageId) => {
1532
+ searchMessagesContext = async (messageId2) => {
1508
1533
  try {
1509
- const response = await apiClient.get(API_ENDPOINTS.GROUP.SEARCH_MESSAGES_CONTEXT(messageId));
1534
+ const response = await apiClient.get(API_ENDPOINTS.GROUP.SEARCH_MESSAGES_CONTEXT(messageId2));
1510
1535
  return response.data;
1511
1536
  } catch (error) {
1512
1537
  console.error("Search messages context failed:", error);
@@ -1632,24 +1657,24 @@ var init_forwardPending_store = __esm({
1632
1657
  "src/store/forwardPending.store.ts"() {
1633
1658
  pendingForwards = /* @__PURE__ */ new Map();
1634
1659
  lastPendingMessageId = null;
1635
- setPendingForward = (messageId, meta) => {
1636
- if (!messageId) return;
1637
- const key = String(messageId);
1660
+ setPendingForward = (messageId2, meta) => {
1661
+ if (!messageId2) return;
1662
+ const key = String(messageId2);
1638
1663
  pendingForwards.set(key, meta);
1639
1664
  lastPendingMessageId = key;
1640
1665
  };
1641
- peekPendingForward = (messageId) => {
1642
- if (!messageId) return void 0;
1643
- return pendingForwards.get(String(messageId));
1666
+ peekPendingForward = (messageId2) => {
1667
+ if (!messageId2) return void 0;
1668
+ return pendingForwards.get(String(messageId2));
1644
1669
  };
1645
1670
  peekMostRecentPendingForward = () => {
1646
1671
  if (!lastPendingMessageId) return void 0;
1647
1672
  return pendingForwards.get(lastPendingMessageId);
1648
1673
  };
1649
1674
  getLastPendingForwardMessageId = () => lastPendingMessageId;
1650
- clearPendingForward = (messageId) => {
1651
- if (messageId) {
1652
- const key = String(messageId);
1675
+ clearPendingForward = (messageId2) => {
1676
+ if (messageId2) {
1677
+ const key = String(messageId2);
1653
1678
  pendingForwards.delete(key);
1654
1679
  if (lastPendingMessageId === key) lastPendingMessageId = null;
1655
1680
  return;
@@ -2119,14 +2144,14 @@ var init_group_reaction_handlers = __esm({
2119
2144
  return Array.from(map.values());
2120
2145
  };
2121
2146
  handleGroupReactionAddReceive = (set, get, payload) => {
2122
- const messageId = payload.messageId || payload._id;
2147
+ const messageId2 = payload.messageId || payload._id;
2123
2148
  const conversationId = payload.conversationId;
2124
- if (!messageId) return;
2149
+ if (!messageId2) return;
2125
2150
  set((state) => {
2126
- const cid = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId);
2151
+ const cid = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId2);
2127
2152
  if (!cid) return state;
2128
2153
  const messages = state.messagesByConversation[cid] || [];
2129
- const idx = messages.findIndex((m) => String(m._id || m.id) === String(messageId));
2154
+ const idx = messages.findIndex((m) => String(m._id || m.id) === String(messageId2));
2130
2155
  if (idx === -1) return state;
2131
2156
  const nextMessages = [...messages];
2132
2157
  const currentMsg = { ...nextMessages[idx] };
@@ -2144,20 +2169,20 @@ var init_group_reaction_handlers = __esm({
2144
2169
  }
2145
2170
  nextMessages[idx] = currentMsg;
2146
2171
  return {
2147
- lastReactionUpdate: { ...payload, messageId, action: "add", _v: Date.now() },
2172
+ lastReactionUpdate: { ...payload, messageId: messageId2, action: "add", _v: Date.now() },
2148
2173
  messagesByConversation: { ...state.messagesByConversation, [cid]: nextMessages }
2149
2174
  };
2150
2175
  });
2151
2176
  };
2152
2177
  handleGroupReactionRemoveReceive = (set, get, payload) => {
2153
- const messageId = payload.messageId || payload._id;
2178
+ const messageId2 = payload.messageId || payload._id;
2154
2179
  const conversationId = payload.conversationId;
2155
- if (!messageId) return;
2180
+ if (!messageId2) return;
2156
2181
  set((state) => {
2157
- const cid = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId);
2182
+ const cid = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId2);
2158
2183
  if (!cid) return state;
2159
2184
  const messages = state.messagesByConversation[cid] || [];
2160
- const idx = messages.findIndex((m) => String(m._id || m.id) === String(messageId));
2185
+ const idx = messages.findIndex((m) => String(m._id || m.id) === String(messageId2));
2161
2186
  if (idx === -1) return state;
2162
2187
  const nextMessages = [...messages];
2163
2188
  const currentMsg = { ...nextMessages[idx] };
@@ -2174,7 +2199,7 @@ var init_group_reaction_handlers = __esm({
2174
2199
  }
2175
2200
  nextMessages[idx] = currentMsg;
2176
2201
  return {
2177
- lastReactionUpdate: { ...payload, messageId, action: "remove", _v: Date.now() },
2202
+ lastReactionUpdate: { ...payload, messageId: messageId2, action: "remove", _v: Date.now() },
2178
2203
  messagesByConversation: { ...state.messagesByConversation, [cid]: nextMessages }
2179
2204
  };
2180
2205
  });
@@ -2204,14 +2229,14 @@ function removeMessageAttachment(message, attachmentId) {
2204
2229
  if (attachments.length === message.attachments.length) return message;
2205
2230
  return { ...message, attachments };
2206
2231
  }
2207
- function pinKey(messageId, attachmentId) {
2208
- return attachmentId ? `${messageId}:${attachmentId}` : String(messageId);
2232
+ function pinKey(messageId2, attachmentId) {
2233
+ return attachmentId ? `${messageId2}:${attachmentId}` : String(messageId2);
2209
2234
  }
2210
- function matchesPinEntry(entry, messageId, attachmentId) {
2235
+ function matchesPinEntry(entry, messageId2, attachmentId) {
2211
2236
  const entryMessageId = String(
2212
2237
  entry?.messageId?._id || entry?.messageId || entry?._id || entry?.id || ""
2213
2238
  );
2214
- if (entryMessageId !== String(messageId)) return false;
2239
+ if (entryMessageId !== String(messageId2)) return false;
2215
2240
  const entryAttachmentId = entry?.attachmentId ? String(entry.attachmentId) : null;
2216
2241
  const targetAttachmentId = attachmentId ? String(attachmentId) : null;
2217
2242
  return entryAttachmentId === targetAttachmentId;
@@ -2226,13 +2251,13 @@ function applyPinnedListToMessages(messages, pinnedMessage) {
2226
2251
  )
2227
2252
  );
2228
2253
  return messages.map((message) => {
2229
- const messageId = String(message._id || message.id);
2230
- const hasWholeMessagePin = pinnedKeys.has(pinKey(messageId, null));
2254
+ const messageId2 = String(message._id || message.id);
2255
+ const hasWholeMessagePin = pinnedKeys.has(pinKey(messageId2, null));
2231
2256
  const attachments = (message.attachments || []).map((att) => {
2232
2257
  const attId = getAttachmentId(att);
2233
2258
  return {
2234
2259
  ...att,
2235
- isPinned: attId ? pinnedKeys.has(pinKey(messageId, attId)) : !!att.isPinned
2260
+ isPinned: attId ? pinnedKeys.has(pinKey(messageId2, attId)) : !!att.isPinned
2236
2261
  };
2237
2262
  });
2238
2263
  return {
@@ -2294,13 +2319,13 @@ var init_pin_handlers = __esm({
2294
2319
  });
2295
2320
  return;
2296
2321
  }
2297
- const { messageId, conversationId, isPinned, attachmentId } = extractMessageData(payload);
2298
- if (!messageId || !conversationId) return;
2322
+ const { messageId: messageId2, conversationId, isPinned, attachmentId } = extractMessageData(payload);
2323
+ if (!messageId2 || !conversationId) return;
2299
2324
  set((state) => {
2300
- const sid = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId);
2325
+ const sid = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId2);
2301
2326
  if (!sid) return state;
2302
2327
  const messages = state.messagesByConversation[sid] || [];
2303
- const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId));
2328
+ const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId2));
2304
2329
  let newMessagesByConversation = state.messagesByConversation;
2305
2330
  const msg = index !== -1 ? messages[index] : null;
2306
2331
  const wasPinned = attachmentId ? !!msg?.attachments?.some(
@@ -2322,9 +2347,9 @@ var init_pin_handlers = __esm({
2322
2347
  const newPinnedByConv = { ...state.pinnedMessagesByConversation };
2323
2348
  if (isPinned) {
2324
2349
  const currentPinned = newPinnedByConv[sid] || [];
2325
- if (!currentPinned.some((m) => matchesPinEntry(m, messageId, attachmentId || null))) {
2350
+ if (!currentPinned.some((m) => matchesPinEntry(m, messageId2, attachmentId || null))) {
2326
2351
  const fullMsg = msg ? attachmentId ? {
2327
- messageId,
2352
+ messageId: messageId2,
2328
2353
  attachmentId,
2329
2354
  attachment: msg.attachments?.find(
2330
2355
  (att) => getAttachmentId(att) === String(attachmentId)
@@ -2336,7 +2361,7 @@ var init_pin_handlers = __esm({
2336
2361
  }
2337
2362
  } else {
2338
2363
  newPinnedByConv[sid] = (newPinnedByConv[sid] || []).filter(
2339
- (m) => !matchesPinEntry(m, messageId, attachmentId || payload.unpinAttachmentId || null)
2364
+ (m) => !matchesPinEntry(m, messageId2, attachmentId || payload.unpinAttachmentId || null)
2340
2365
  );
2341
2366
  }
2342
2367
  const conversation = get().conversations?.find((c) => String(c._id) === String(sid));
@@ -2351,8 +2376,8 @@ var init_pin_handlers = __esm({
2351
2376
  pinnedCount = payload.totalCount;
2352
2377
  }
2353
2378
  const newPendingActions = { ...state.messagePendingActions };
2354
- if (newPendingActions[messageId]) {
2355
- delete newPendingActions[messageId];
2379
+ if (newPendingActions[messageId2]) {
2380
+ delete newPendingActions[messageId2];
2356
2381
  }
2357
2382
  return {
2358
2383
  lastPinUpdate: payload,
@@ -2383,13 +2408,13 @@ var init_star_handlers = __esm({
2383
2408
  init_attachment_helpers();
2384
2409
  handleStarUpdate = (set, get, payload) => {
2385
2410
  if (payload.starredBy && Array.isArray(payload.starredBy)) {
2386
- const { messageId: messageId2, attachmentId } = extractMessageData(payload);
2411
+ const { messageId: messageId3, attachmentId } = extractMessageData(payload);
2387
2412
  const { starredBy } = payload;
2388
- if (!messageId2) return;
2413
+ if (!messageId3) return;
2389
2414
  set((state) => {
2390
- const sid = payload.conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId2);
2415
+ const sid = payload.conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId3);
2391
2416
  const newPendingActions = { ...state.messagePendingActions };
2392
- const pendingKey = String(messageId2);
2417
+ const pendingKey = String(messageId3);
2393
2418
  if (newPendingActions[pendingKey]) {
2394
2419
  delete newPendingActions[pendingKey];
2395
2420
  }
@@ -2399,7 +2424,7 @@ var init_star_handlers = __esm({
2399
2424
  const loggedUserId = String(get().loggedUserDetails?._id || state.loggedUserDetails?._id || "");
2400
2425
  const isStarred2 = starredBy.some((id) => String(id?._id || id) === loggedUserId) || loggedUserId === "" && starredBy.length > 0;
2401
2426
  const messages = state.messagesByConversation[sid] || [];
2402
- const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId2));
2427
+ const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId3));
2403
2428
  let newMessagesByConversation = state.messagesByConversation;
2404
2429
  if (index !== -1) {
2405
2430
  const newMessages = [...messages];
@@ -2426,9 +2451,9 @@ var init_star_handlers = __esm({
2426
2451
  const newStarredByConv = { ...state.starredMessagesByConversation };
2427
2452
  const currentStarred = newStarredByConv[sid] || [];
2428
2453
  const exists = attachmentId ? currentStarred.some(
2429
- (m) => m.isAttachment && String(m.messageId) === String(messageId2) && String(m.attachmentId) === String(attachmentId)
2454
+ (m) => m.isAttachment && String(m.messageId) === String(messageId3) && String(m.attachmentId) === String(attachmentId)
2430
2455
  ) : currentStarred.some(
2431
- (m) => !m.isAttachment && String(m.messageId?._id || m.messageId || m._id || m.id) === String(messageId2)
2456
+ (m) => !m.isAttachment && String(m.messageId?._id || m.messageId || m._id || m.id) === String(messageId3)
2432
2457
  );
2433
2458
  const conversation = get().conversations?.find((c) => String(c._id) === String(sid));
2434
2459
  const existingCount = state.liveConversationCounts[sid]?.starredCount ?? conversation?.starredCount ?? 0;
@@ -2436,21 +2461,21 @@ var init_star_handlers = __esm({
2436
2461
  if (isStarred2 && !exists) {
2437
2462
  const fullMessage = attachmentId ? {
2438
2463
  _id: attachmentId,
2439
- messageId: messageId2,
2464
+ messageId: messageId3,
2440
2465
  attachmentId,
2441
2466
  isAttachment: true,
2442
2467
  attachment: index !== -1 ? newMessagesByConversation[sid][index]?.attachments?.find(
2443
2468
  (att) => getAttachmentId(att) === String(attachmentId)
2444
2469
  ) : payload.attachment,
2445
2470
  createdAt: payload.createdAt || (/* @__PURE__ */ new Date()).toISOString()
2446
- } : index !== -1 ? newMessagesByConversation[sid][index] : { ...payload, _id: messageId2 };
2471
+ } : index !== -1 ? newMessagesByConversation[sid][index] : { ...payload, _id: messageId3 };
2447
2472
  newStarredByConv[sid] = [...currentStarred, fullMessage];
2448
2473
  starredCount = existingCount + 1;
2449
2474
  } else if (!isStarred2 && exists) {
2450
2475
  newStarredByConv[sid] = attachmentId ? currentStarred.filter(
2451
- (m) => !(m.isAttachment && String(m.messageId) === String(messageId2) && String(m.attachmentId) === String(attachmentId))
2476
+ (m) => !(m.isAttachment && String(m.messageId) === String(messageId3) && String(m.attachmentId) === String(attachmentId))
2452
2477
  ) : currentStarred.filter(
2453
- (m) => String(m.messageId?._id || m.messageId || m._id || m.id) !== String(messageId2)
2478
+ (m) => String(m.messageId?._id || m.messageId || m._id || m.id) !== String(messageId3)
2454
2479
  );
2455
2480
  starredCount = Math.max(0, existingCount - 1);
2456
2481
  }
@@ -2476,13 +2501,13 @@ var init_star_handlers = __esm({
2476
2501
  });
2477
2502
  return;
2478
2503
  }
2479
- const { messageId, isStarred, conversationId } = extractMessageData(payload);
2480
- if (!messageId) return;
2504
+ const { messageId: messageId2, isStarred, conversationId } = extractMessageData(payload);
2505
+ if (!messageId2) return;
2481
2506
  set((state) => {
2482
- const sid = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId);
2507
+ const sid = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId2);
2483
2508
  if (!sid) return { lastStarUpdate: payload };
2484
2509
  const messages = state.messagesByConversation[sid] || [];
2485
- const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId));
2510
+ const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId2));
2486
2511
  let newMessagesByConversation = state.messagesByConversation;
2487
2512
  const msg = index !== -1 ? messages[index] : null;
2488
2513
  const wasStarred = msg ? !!msg.isStarred : false;
@@ -2498,13 +2523,13 @@ var init_star_handlers = __esm({
2498
2523
  const newStarredByConv = { ...state.starredMessagesByConversation };
2499
2524
  if (isStarred) {
2500
2525
  const currentStarred = newStarredByConv[sid] || [];
2501
- if (!currentStarred.some((m) => String(m?._id || m?.id || m.messageId?._id || m.messageId?.id) === String(messageId))) {
2526
+ if (!currentStarred.some((m) => String(m?._id || m?.id || m.messageId?._id || m.messageId?.id) === String(messageId2))) {
2502
2527
  const fullMsg = msg ? { ...msg, isStarred: true } : payload;
2503
2528
  newStarredByConv[sid] = [...currentStarred, fullMsg];
2504
2529
  }
2505
2530
  } else {
2506
2531
  newStarredByConv[sid] = (newStarredByConv[sid] || []).filter(
2507
- (m) => String(m?._id || m?.id || m.messageId?._id || m.messageId?.id) !== String(messageId)
2532
+ (m) => String(m?._id || m?.id || m.messageId?._id || m.messageId?.id) !== String(messageId2)
2508
2533
  );
2509
2534
  }
2510
2535
  const conversation = get().conversations?.find((c) => String(c._id) === String(sid));
@@ -2519,7 +2544,7 @@ var init_star_handlers = __esm({
2519
2544
  starredCount = payload.totalCount;
2520
2545
  }
2521
2546
  const newPendingActions = { ...state.messagePendingActions };
2522
- const pendingKey = String(messageId);
2547
+ const pendingKey = String(messageId2);
2523
2548
  if (newPendingActions[pendingKey]) {
2524
2549
  delete newPendingActions[pendingKey];
2525
2550
  }
@@ -2640,15 +2665,15 @@ var init_emit_actions = __esm({
2640
2665
  exports.socketService.emit("dm_unpin", p);
2641
2666
  },
2642
2667
  emitDmStar: (p) => {
2643
- const messageId = String(p.messageId);
2644
- handleStarUpdate(set, get, { ...p, messageId, isStarred: true });
2645
- set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [messageId]: ["star"] } }));
2668
+ const messageId2 = String(p.messageId);
2669
+ handleStarUpdate(set, get, { ...p, messageId: messageId2, isStarred: true });
2670
+ set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [messageId2]: ["star"] } }));
2646
2671
  exports.socketService.emit("dm_star", p);
2647
2672
  },
2648
2673
  emitDmUnstar: (p) => {
2649
- const messageId = String(p.messageId);
2650
- handleStarUpdate(set, get, { ...p, messageId, isStarred: false });
2651
- set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [messageId]: ["unstar"] } }));
2674
+ const messageId2 = String(p.messageId);
2675
+ handleStarUpdate(set, get, { ...p, messageId: messageId2, isStarred: false });
2676
+ set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [messageId2]: ["unstar"] } }));
2652
2677
  exports.socketService.emit("dm_unstar", p);
2653
2678
  },
2654
2679
  emitDmForward: (p) => {
@@ -2700,15 +2725,15 @@ var init_emit_actions = __esm({
2700
2725
  exports.socketService.emitGroupUnpin(p);
2701
2726
  },
2702
2727
  emitGroupStar: (p) => {
2703
- const messageId = String(p.messageId);
2704
- handleStarUpdate(set, get, { ...p, messageId, isStarred: true });
2705
- set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [messageId]: ["star"] } }));
2728
+ const messageId2 = String(p.messageId);
2729
+ handleStarUpdate(set, get, { ...p, messageId: messageId2, isStarred: true });
2730
+ set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [messageId2]: ["star"] } }));
2706
2731
  exports.socketService.emitGroupStar(p);
2707
2732
  },
2708
2733
  emitGroupUnstar: (p) => {
2709
- const messageId = String(p.messageId);
2710
- handleStarUpdate(set, get, { ...p, messageId, isStarred: false });
2711
- set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [messageId]: ["unstar"] } }));
2734
+ const messageId2 = String(p.messageId);
2735
+ handleStarUpdate(set, get, { ...p, messageId: messageId2, isStarred: false });
2736
+ set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [messageId2]: ["unstar"] } }));
2712
2737
  exports.socketService.emitGroupUnstar(p);
2713
2738
  },
2714
2739
  emitGroupForward: (p) => {
@@ -2727,8 +2752,8 @@ var init_emit_actions = __esm({
2727
2752
  ...p.attachmentId ? { attachmentId: String(p.attachmentId) } : {}
2728
2753
  });
2729
2754
  },
2730
- clearForwardPending: (messageId) => {
2731
- clearForwardPendingActions(set, messageId);
2755
+ clearForwardPending: (messageId2) => {
2756
+ clearForwardPendingActions(set, messageId2);
2732
2757
  },
2733
2758
  emitConversationUpdate: (p) => exports.socketService.emitConversationUpdate(p),
2734
2759
  emitGroupLeave: (p) => exports.socketService.emitGroupLeave(p),
@@ -2753,7 +2778,7 @@ var init_message_handlers = __esm({
2753
2778
  get().conversations,
2754
2779
  loggedUserId
2755
2780
  );
2756
- const { messageId } = extractMessageData(lastDM);
2781
+ const { messageId: messageId2 } = extractMessageData(lastDM);
2757
2782
  const tempId = lastDM.tempId;
2758
2783
  const isFromSelf = loggedUserDetails && String(lastDM.sender?._id || lastDM.sender) === String(loggedUserDetails._id);
2759
2784
  const activeConversationId = get().activeConversationId;
@@ -2763,14 +2788,14 @@ var init_message_handlers = __esm({
2763
2788
  const newPendingActions = { ...state.messagePendingActions };
2764
2789
  if (conversationId) {
2765
2790
  const current = nextMessagesByConversation[conversationId] || [];
2766
- let matchedId = messageId;
2791
+ let matchedId = messageId2;
2767
2792
  if (tempId && state.messagePendingActions[tempId]) {
2768
2793
  matchedId = tempId;
2769
2794
  }
2770
- const exists = current.some((m) => String(m._id || m.id) === String(messageId));
2795
+ const exists = current.some((m) => String(m._id || m.id) === String(messageId2));
2771
2796
  if (matchedId && matchedId === tempId) {
2772
2797
  nextMessagesByConversation[conversationId] = current.map(
2773
- (m) => String(m.id || m._id) === String(matchedId) ? { ...m, _id: messageId, id: messageId, status: messageWithStatus.status } : m
2798
+ (m) => String(m.id || m._id) === String(matchedId) ? { ...m, _id: messageId2, id: messageId2, status: messageWithStatus.status } : m
2774
2799
  );
2775
2800
  delete newPendingActions[matchedId];
2776
2801
  } else if (!exists) {
@@ -2803,8 +2828,7 @@ var init_message_handlers = __esm({
2803
2828
  conversationType: lastDM.conversationType || "individual",
2804
2829
  isGroup: false,
2805
2830
  ...shouldIncludeParticipants ? { participants: participantSeed } : {},
2806
- groupName: lastDM.groupName,
2807
- name: lastDM.groupName,
2831
+ ...lastDM.groupName ? { groupName: lastDM.groupName, name: lastDM.groupName } : {},
2808
2832
  owner: existingConv?.owner ?? lastDM.owner
2809
2833
  },
2810
2834
  {
@@ -2826,27 +2850,27 @@ var init_message_handlers = __esm({
2826
2850
  }
2827
2851
  };
2828
2852
  handleEditDM = (set, get, payload) => {
2829
- const { messageId, content, conversationId, attachmentId, caption } = extractMessageData(payload);
2830
- if (!messageId) return;
2853
+ const { messageId: messageId2, content, conversationId, attachmentId, caption } = extractMessageData(payload);
2854
+ if (!messageId2) return;
2831
2855
  const captionText = caption ?? content ?? "";
2832
2856
  set((state) => {
2833
2857
  let searchConversationId = conversationId;
2834
2858
  if (!searchConversationId) {
2835
- searchConversationId = findConversationIdByMessageId(state.messagesByConversation, messageId);
2859
+ searchConversationId = findConversationIdByMessageId(state.messagesByConversation, messageId2);
2836
2860
  }
2837
2861
  if (!searchConversationId) {
2838
2862
  searchConversationId = state.conversations.find(
2839
- (c) => String(c.lastMessage?._id || c.lastMessage?.id) === String(messageId)
2863
+ (c) => String(c.lastMessage?._id || c.lastMessage?.id) === String(messageId2)
2840
2864
  )?._id;
2841
2865
  }
2842
- const normalizedEditPayload = { ...payload, messageId, content, conversationId: searchConversationId, _v: Date.now() };
2866
+ const normalizedEditPayload = { ...payload, messageId: messageId2, content, conversationId: searchConversationId, _v: Date.now() };
2843
2867
  const newPendingActions = { ...state.messagePendingActions };
2844
- if (newPendingActions[messageId]) {
2845
- delete newPendingActions[messageId];
2868
+ if (newPendingActions[messageId2]) {
2869
+ delete newPendingActions[messageId2];
2846
2870
  }
2847
2871
  if (searchConversationId) {
2848
2872
  const messages = state.messagesByConversation[searchConversationId] || [];
2849
- const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId));
2873
+ const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId2));
2850
2874
  if (index !== -1) {
2851
2875
  const newMessages = [...messages];
2852
2876
  if (attachmentId) {
@@ -2872,15 +2896,15 @@ var init_message_handlers = __esm({
2872
2896
  });
2873
2897
  };
2874
2898
  handleDeleteDM = (set, get, payload, type) => {
2875
- const { messageId, conversationId, attachmentId } = extractMessageData(payload);
2876
- if (!messageId) return;
2899
+ const { messageId: messageId2, conversationId, attachmentId } = extractMessageData(payload);
2900
+ if (!messageId2) return;
2877
2901
  set((state) => {
2878
- const searchConversationId = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId);
2902
+ const searchConversationId = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId2);
2879
2903
  const messageTombstoned = payload.messageTombstoned === true;
2880
2904
  let updatedConversations = state.conversations;
2881
2905
  if (searchConversationId && !attachmentId) {
2882
2906
  updatedConversations = state.conversations.map((c) => {
2883
- if (String(c._id) === String(searchConversationId) && String(c.lastMessage?._id || c.lastMessage?.id) === String(messageId)) {
2907
+ if (String(c._id) === String(searchConversationId) && String(c.lastMessage?._id || c.lastMessage?.id) === String(messageId2)) {
2884
2908
  return { ...c, lastMessage: type === "me" ? { ...c.lastMessage, content: "" } : { ...c.lastMessage, isDeletedForEveryone: true, content: "This message has been deleted" } };
2885
2909
  }
2886
2910
  return c;
@@ -2891,7 +2915,7 @@ var init_message_handlers = __esm({
2891
2915
  if (searchConversationId) {
2892
2916
  if (attachmentId) {
2893
2917
  const updatedMessages = messages.map((m) => {
2894
- if (String(m._id || m.id) !== String(messageId)) return m;
2918
+ if (String(m._id || m.id) !== String(messageId2)) return m;
2895
2919
  if (messageTombstoned || type === "everyone" && payload.content) {
2896
2920
  return {
2897
2921
  ...m,
@@ -2930,22 +2954,22 @@ var init_message_handlers = __esm({
2930
2954
  [searchConversationId]: updatedMessages
2931
2955
  };
2932
2956
  } else if (type === "me") {
2933
- nextMessagesByConversation = { ...state.messagesByConversation, [searchConversationId]: messages.filter((m) => String(m._id || m.id) !== String(messageId)) };
2957
+ nextMessagesByConversation = { ...state.messagesByConversation, [searchConversationId]: messages.filter((m) => String(m._id || m.id) !== String(messageId2)) };
2934
2958
  } else {
2935
2959
  nextMessagesByConversation = {
2936
2960
  ...state.messagesByConversation,
2937
- [searchConversationId]: messages.map((m) => String(m._id || m.id) === String(messageId) ? { ...m, isDeletedForEveryone: true, content: "" } : m)
2961
+ [searchConversationId]: messages.map((m) => String(m._id || m.id) === String(messageId2) ? { ...m, isDeletedForEveryone: true, content: "" } : m)
2938
2962
  };
2939
2963
  }
2940
2964
  }
2941
2965
  const newPendingActions = { ...state.messagePendingActions };
2942
- if (newPendingActions[messageId]) {
2943
- delete newPendingActions[messageId];
2966
+ if (newPendingActions[messageId2]) {
2967
+ delete newPendingActions[messageId2];
2944
2968
  }
2945
- const shouldMarkWholeMessageDeleted = type === "me" && !attachmentId && !state.deletedForMeIds.includes(messageId);
2969
+ const shouldMarkWholeMessageDeleted = type === "me" && !attachmentId && !state.deletedForMeIds.includes(messageId2);
2946
2970
  return {
2947
2971
  lastDeleteDM: { ...payload, deleteType: type },
2948
- deletedForMeIds: shouldMarkWholeMessageDeleted ? [...state.deletedForMeIds, messageId] : state.deletedForMeIds,
2972
+ deletedForMeIds: shouldMarkWholeMessageDeleted ? [...state.deletedForMeIds, messageId2] : state.deletedForMeIds,
2949
2973
  messagesByConversation: nextMessagesByConversation,
2950
2974
  conversations: updatedConversations,
2951
2975
  messagePendingActions: newPendingActions
@@ -3019,15 +3043,15 @@ var init_dm_actions = __esm({
3019
3043
  },
3020
3044
  receivedStatusUpdate: (payload) => {
3021
3045
  const data = extractMessageData(payload);
3022
- const { messageId, status } = data;
3046
+ const { messageId: messageId2, status } = data;
3023
3047
  let { conversationId } = data;
3024
- if (!messageId || !status) return;
3048
+ if (!messageId2 || !status) return;
3025
3049
  set({ lastStatusUpdate: payload });
3026
3050
  if (!conversationId) {
3027
- conversationId = findConversationIdByMessageId(get().messagesByConversation, messageId) || findConversationIdByLastMessageId(get().conversations, messageId) || void 0;
3051
+ conversationId = findConversationIdByMessageId(get().messagesByConversation, messageId2) || findConversationIdByLastMessageId(get().conversations, messageId2) || void 0;
3028
3052
  }
3029
3053
  set((state) => ({
3030
- ...applyMessageStatusToStore(state, String(messageId), status, conversationId)
3054
+ ...applyMessageStatusToStore(state, String(messageId2), status, conversationId)
3031
3055
  }));
3032
3056
  },
3033
3057
  receivedDMMarkRead: (payload) => {
@@ -3084,7 +3108,7 @@ var init_group_handlers = __esm({
3084
3108
  get().conversations,
3085
3109
  loggedUserId
3086
3110
  );
3087
- const { messageId } = extractMessageData(lastDM);
3111
+ const { messageId: messageId2 } = extractMessageData(lastDM);
3088
3112
  const tempId = lastDM.tempId;
3089
3113
  const activeConversationId = get().activeConversationId;
3090
3114
  const isOpenConversation = conversationId && String(conversationId) === String(activeConversationId);
@@ -3121,23 +3145,23 @@ var init_group_handlers = __esm({
3121
3145
  );
3122
3146
  if (optimisticMsg) matchedTempId = optimisticMsg.id;
3123
3147
  }
3124
- const messageExists = current.some((m) => String(m._id || m.id) === String(messageId));
3148
+ const messageExists = current.some((m) => String(m._id || m.id) === String(messageId2));
3125
3149
  if (!messageExists) {
3126
3150
  nextMessagesByConversation[conversationId] = [...current, {
3127
3151
  ...lastDM,
3128
- _id: messageId,
3129
- id: messageId,
3152
+ _id: messageId2,
3153
+ id: messageId2,
3130
3154
  status: lastDM.status || "sent"
3131
3155
  }];
3132
3156
  } else {
3133
3157
  nextMessagesByConversation[conversationId] = current.map(
3134
- (m) => String(m._id || m.id) === String(messageId) ? { ...m, status: lastDM.status || "sent" } : m
3158
+ (m) => String(m._id || m.id) === String(messageId2) ? { ...m, status: lastDM.status || "sent" } : m
3135
3159
  );
3136
3160
  }
3137
3161
  if (matchedTempId) {
3138
3162
  delete newPendingActions[matchedTempId];
3139
3163
  nextMessagesByConversation[conversationId] = nextMessagesByConversation[conversationId].map(
3140
- (m) => String(m.id || m._id) === String(matchedTempId) ? { ...m, _id: messageId, id: messageId, status: lastDM.status || "sent" } : m
3164
+ (m) => String(m.id || m._id) === String(matchedTempId) ? { ...m, _id: messageId2, id: messageId2, status: lastDM.status || "sent" } : m
3141
3165
  );
3142
3166
  }
3143
3167
  }
@@ -3147,8 +3171,10 @@ var init_group_handlers = __esm({
3147
3171
  _id: conversationId,
3148
3172
  conversationType: "group",
3149
3173
  isGroup: true,
3150
- groupName: lastDM.groupName,
3151
- name: lastDM.groupName,
3174
+ ...lastDM.groupName || lastDM.name ? {
3175
+ groupName: lastDM.groupName || lastDM.name,
3176
+ name: lastDM.groupName || lastDM.name
3177
+ } : {},
3152
3178
  participants: buildParticipantsFromMessagePayload(lastDM, loggedUserId)
3153
3179
  },
3154
3180
  {
@@ -3186,8 +3212,10 @@ var init_group_handlers = __esm({
3186
3212
  _id: conversationId,
3187
3213
  conversationType: "group",
3188
3214
  isGroup: true,
3189
- groupName: lastDM.groupName,
3190
- name: lastDM.groupName,
3215
+ ...lastDM.groupName || lastDM.name ? {
3216
+ groupName: lastDM.groupName || lastDM.name,
3217
+ name: lastDM.groupName || lastDM.name
3218
+ } : {},
3191
3219
  participants: buildParticipantsFromMessagePayload(lastDM, loggedUserId)
3192
3220
  },
3193
3221
  {
@@ -3206,10 +3234,10 @@ var init_group_handlers = __esm({
3206
3234
  (c) => String(c._id) === String(conversationId)
3207
3235
  );
3208
3236
  const isGroupChat = isGroupConversation(targetConv);
3209
- if (loggedUserDetails?._id && messageId && isGroupChat) {
3237
+ if (loggedUserDetails?._id && messageId2 && isGroupChat) {
3210
3238
  get().emitGroupMessageDelivered({
3211
3239
  conversationId,
3212
- messageId,
3240
+ messageId: messageId2,
3213
3241
  userId: loggedUserDetails._id
3214
3242
  });
3215
3243
  }
@@ -3287,15 +3315,15 @@ var init_group_actions2 = __esm({
3287
3315
  receivedGroupStatusUpdate: (payload) => {
3288
3316
  const data = extractMessageData(payload);
3289
3317
  let { conversationId } = data;
3290
- const { messageId, status } = data;
3318
+ const { messageId: messageId2, status } = data;
3291
3319
  set({ lastStatusUpdate: payload });
3292
3320
  if (!status) return;
3293
- if (messageId) {
3321
+ if (messageId2) {
3294
3322
  if (!conversationId) {
3295
- conversationId = findConversationIdByMessageId(get().messagesByConversation, messageId) || findConversationIdByLastMessageId(get().conversations, messageId) || void 0;
3323
+ conversationId = findConversationIdByMessageId(get().messagesByConversation, messageId2) || findConversationIdByLastMessageId(get().conversations, messageId2) || void 0;
3296
3324
  }
3297
3325
  set((state) => ({
3298
- ...applyMessageStatusToStore(state, String(messageId), status, conversationId)
3326
+ ...applyMessageStatusToStore(state, String(messageId2), status, conversationId)
3299
3327
  }));
3300
3328
  return;
3301
3329
  }
@@ -3511,7 +3539,7 @@ var init_receive = __esm({
3511
3539
  };
3512
3540
  });
3513
3541
  },
3514
- markDeletedForMe: (messageId) => set((state) => ({ deletedForMeIds: [...state.deletedForMeIds, messageId] }))
3542
+ markDeletedForMe: (messageId2) => set((state) => ({ deletedForMeIds: [...state.deletedForMeIds, messageId2] }))
3515
3543
  });
3516
3544
  createReceiveActions = (set, get) => ({
3517
3545
  ...createDmReceiveActions(set, get),
@@ -3536,13 +3564,13 @@ var init_search_actions = __esm({
3536
3564
  init_api_service();
3537
3565
  init_store_helpers();
3538
3566
  createSearchActions = (set, _get) => ({
3539
- fetchSearchMessageContext: async (messageId, options) => {
3567
+ fetchSearchMessageContext: async (messageId2, options) => {
3540
3568
  const searchMode = options?.searchMode !== false;
3541
- set({ isSearchActive: searchMode, searchedMessageId: messageId, isFetchingMessages: true });
3569
+ set({ isSearchActive: searchMode, searchedMessageId: messageId2, isFetchingMessages: true });
3542
3570
  try {
3543
- const response = await searchMessagesContext(messageId);
3571
+ const response = await searchMessagesContext(messageId2);
3544
3572
  const data = response.data?.list || response.data?.messages || response.messages || response.data || [];
3545
- const highlightId = response.data?.highlightMessageId || messageId;
3573
+ const highlightId = response.data?.highlightMessageId || messageId2;
3546
3574
  if (data.length > 0) {
3547
3575
  const conversationId = data[0].conversationId;
3548
3576
  if (conversationId) {
@@ -3571,7 +3599,7 @@ var init_search_actions = __esm({
3571
3599
  }
3572
3600
  },
3573
3601
  setSearchActive: (active) => set({ isSearchActive: active }),
3574
- setSearchedMessageId: (messageId) => set({ searchedMessageId: messageId })
3602
+ setSearchedMessageId: (messageId2) => set({ searchedMessageId: messageId2 })
3575
3603
  });
3576
3604
  }
3577
3605
  });
@@ -3938,6 +3966,7 @@ var buildIncomingMessageFromDM = (lastDM, loggedUserId, conversations) => {
3938
3966
  content: lastDM.content || lastDM.message?.content || "",
3939
3967
  sender: lastDM.sender?.name || lastDM.fromUserId || (isMe ? "Me" : "User"),
3940
3968
  senderId: String(lastDM.sender?._id || lastDM.sender || lastDM.fromUserId || ""),
3969
+ senderImage: lastDM.sender?.image,
3941
3970
  timestamp: lastDM.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
3942
3971
  isOwnMessage: isMe,
3943
3972
  channelId,
@@ -4095,9 +4124,9 @@ var syncLocalMessagesOnPinUpdate = (prev, lastPinUpdate) => {
4095
4124
  return next;
4096
4125
  };
4097
4126
  var syncLocalMessagesOnStarUpdate = (prev, lastStarUpdate, loggedUserId) => {
4098
- const messageId = lastStarUpdate.messageId || lastStarUpdate._id;
4099
- if (!messageId) return null;
4100
- const mid = String(messageId);
4127
+ const messageId2 = lastStarUpdate.messageId || lastStarUpdate._id;
4128
+ if (!messageId2) return null;
4129
+ const mid = String(messageId2);
4101
4130
  let isStarred;
4102
4131
  if (typeof lastStarUpdate.isStarred === "boolean") {
4103
4132
  isStarred = lastStarUpdate.isStarred;
@@ -4116,9 +4145,9 @@ var syncLocalMessagesOnStarUpdate = (prev, lastStarUpdate, loggedUserId) => {
4116
4145
  return next;
4117
4146
  };
4118
4147
  var syncLocalMessagesOnReactionUpdate = (prev, lastReactionUpdate, messagesByConversation) => {
4119
- const messageId = lastReactionUpdate.messageId || lastReactionUpdate._id;
4120
- if (!messageId) return prev;
4121
- const mid = String(messageId);
4148
+ const messageId2 = lastReactionUpdate.messageId || lastReactionUpdate._id;
4149
+ if (!messageId2) return prev;
4150
+ const mid = String(messageId2);
4122
4151
  let storeReactions;
4123
4152
  for (const msgs of Object.values(messagesByConversation)) {
4124
4153
  const found = msgs.find((m) => String(m._id || m.id) === mid);
@@ -4169,7 +4198,7 @@ var syncLocalMessagesOnReactionUpdate = (prev, lastReactionUpdate, messagesByCon
4169
4198
  return changed ? next : prev;
4170
4199
  };
4171
4200
  var syncLocalMessagesOnDelete = (prev, lastDeleteDM) => {
4172
- const messageId = lastDeleteDM.messageId || lastDeleteDM._id;
4201
+ const messageId2 = lastDeleteDM.messageId || lastDeleteDM._id;
4173
4202
  const deleteType = lastDeleteDM.deleteType || "everyone";
4174
4203
  const attachmentId = lastDeleteDM.attachmentId ? String(lastDeleteDM.attachmentId) : null;
4175
4204
  const messageTombstoned = lastDeleteDM.messageTombstoned === true;
@@ -4177,7 +4206,7 @@ var syncLocalMessagesOnDelete = (prev, lastDeleteDM) => {
4177
4206
  Object.keys(next).forEach((channelId) => {
4178
4207
  if (attachmentId) {
4179
4208
  next[channelId] = next[channelId].map((message) => {
4180
- if (String(message._id || message.id) !== String(messageId)) {
4209
+ if (String(message._id || message.id) !== String(messageId2)) {
4181
4210
  return message;
4182
4211
  }
4183
4212
  return applyLocalAttachmentDelete(
@@ -4191,26 +4220,26 @@ var syncLocalMessagesOnDelete = (prev, lastDeleteDM) => {
4191
4220
  }
4192
4221
  if (deleteType === "me") {
4193
4222
  next[channelId] = next[channelId].filter(
4194
- (m) => String(m._id || m.id) !== String(messageId)
4223
+ (m) => String(m._id || m.id) !== String(messageId2)
4195
4224
  );
4196
4225
  } else {
4197
4226
  next[channelId] = next[channelId].map(
4198
- (m) => String(m._id || m.id) === String(messageId) ? { ...m, isDeletedForEveryone: true } : m
4227
+ (m) => String(m._id || m.id) === String(messageId2) ? { ...m, isDeletedForEveryone: true } : m
4199
4228
  );
4200
4229
  }
4201
4230
  });
4202
4231
  return next;
4203
4232
  };
4204
4233
  var syncLocalMessagesOnEdit = (prev, lastEditDM) => {
4205
- const messageId = lastEditDM.messageId || lastEditDM._id;
4234
+ const messageId2 = lastEditDM.messageId || lastEditDM._id;
4206
4235
  const content = lastEditDM.content;
4207
4236
  const attachmentId = lastEditDM.attachmentId ? String(lastEditDM.attachmentId) : null;
4208
4237
  const caption = lastEditDM.caption ?? content;
4209
- if (!messageId) return null;
4238
+ if (!messageId2) return null;
4210
4239
  const next = { ...prev };
4211
4240
  Object.keys(next).forEach((channelId) => {
4212
4241
  const messages = next[channelId];
4213
- const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId));
4242
+ const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId2));
4214
4243
  if (index !== -1) {
4215
4244
  const updated = [...messages];
4216
4245
  const current = updated[index];
@@ -4480,7 +4509,7 @@ var Chat = ({
4480
4509
  const status = exports.useChatStore((s) => s.status);
4481
4510
  const error = exports.useChatStore((s) => s.error);
4482
4511
  useChatSync();
4483
- React2__default.default.useEffect(() => {
4512
+ React2__namespace.default.useEffect(() => {
4484
4513
  const clientId = client?.id;
4485
4514
  const initializeChat = async () => {
4486
4515
  if (!clientId || !loggedUserDetails) return;
@@ -4569,28 +4598,28 @@ var Chat = ({
4569
4598
  queryParamApis: queryParamApis ?? ["get"],
4570
4599
  queryParamsByApi: queryParamsByApi ?? {}
4571
4600
  });
4572
- React2__default.default.useEffect(() => {
4601
+ React2__namespace.default.useEffect(() => {
4573
4602
  exports.setChatQueryParams(queryParams);
4574
4603
  exports.setChatQueryParamApis(queryParamApis);
4575
4604
  exports.setChatQueryParamsByApi(queryParamsByApi);
4576
4605
  }, [queryConfigKey]);
4577
- React2__default.default.useEffect(() => {
4606
+ React2__namespace.default.useEffect(() => {
4578
4607
  if (lastDM && onMessageReceived) {
4579
4608
  onMessageReceived(lastDM);
4580
4609
  }
4581
4610
  }, [lastDM, onMessageReceived]);
4582
- React2__default.default.useEffect(() => {
4611
+ React2__namespace.default.useEffect(() => {
4583
4612
  if (status === "connected" && onSocketConnected) {
4584
4613
  const socketId = exports.useChatStore.getState().socketId;
4585
4614
  if (socketId) onSocketConnected(socketId);
4586
4615
  }
4587
4616
  }, [status, onSocketConnected]);
4588
- React2__default.default.useEffect(() => {
4617
+ React2__namespace.default.useEffect(() => {
4589
4618
  if (status === "error" && error && onSocketError) {
4590
4619
  onSocketError(error);
4591
4620
  }
4592
4621
  }, [status, error, onSocketError]);
4593
- const contextValue = React2__default.default.useMemo(
4622
+ const contextValue = React2__namespace.default.useMemo(
4594
4623
  () => ({
4595
4624
  onSendMessage,
4596
4625
  client,
@@ -4610,7 +4639,7 @@ var Chat = ({
4610
4639
  messagesData
4611
4640
  ]
4612
4641
  );
4613
- const customization = React2__default.default.useMemo(
4642
+ const customization = React2__namespace.default.useMemo(
4614
4643
  () => ({
4615
4644
  components: uiConfig.components,
4616
4645
  classNames: uiConfig.classNames,
@@ -6705,20 +6734,35 @@ init_chat_constants();
6705
6734
  // src/chat/lib/last-message-preview.ts
6706
6735
  init_store_helpers();
6707
6736
 
6708
- // src/chat/lib/chat-attachment-display.ts
6709
- init_chat_constants();
6710
- function cleanAttachmentDisplayName(filename, fallback = "Attachment") {
6711
- const trimmed = filename.trim();
6712
- if (!trimmed) return fallback;
6713
- let name = trimmed;
6714
- const prefixPattern = new RegExp(`^\\d{${ATTACHMENT_FILENAME_TIMESTAMP_LENGTH}}_`);
6715
- while (prefixPattern.test(name)) {
6716
- name = name.slice(ATTACHMENT_FILENAME_TIMESTAMP_LENGTH + 1);
6737
+ // src/chat/lib/attachment-preview-labels.ts
6738
+ function getAttachmentTypePreviewLabel(type) {
6739
+ switch (String(type || "").toLowerCase()) {
6740
+ case "image":
6741
+ return "Photo";
6742
+ case "video":
6743
+ return "Video";
6744
+ case "audio":
6745
+ return "Audio";
6746
+ case "file":
6747
+ case "document":
6748
+ case "spreadsheet":
6749
+ return "Attachment";
6750
+ default:
6751
+ return "Attachment";
6717
6752
  }
6718
- if (name.length > ATTACHMENT_FILENAME_TIMESTAMP_LENGTH && /^\d+$/.test(name.slice(0, ATTACHMENT_FILENAME_TIMESTAMP_LENGTH)) && name[ATTACHMENT_FILENAME_TIMESTAMP_LENGTH] !== "_") {
6719
- name = name.slice(ATTACHMENT_FILENAME_TIMESTAMP_LENGTH);
6753
+ }
6754
+ function getAttachmentCountPreviewLabel(type, count) {
6755
+ if (count <= 1) return getAttachmentTypePreviewLabel(type);
6756
+ switch (String(type).toLowerCase()) {
6757
+ case "image":
6758
+ return `${count} photos`;
6759
+ case "video":
6760
+ return `${count} videos`;
6761
+ case "audio":
6762
+ return `${count} audio files`;
6763
+ default:
6764
+ return `${count} attachments`;
6720
6765
  }
6721
- return name.trim() || trimmed;
6722
6766
  }
6723
6767
 
6724
6768
  // src/chat/lib/last-message-preview.ts
@@ -6726,21 +6770,30 @@ function getAttachmentOnlyPreviewText(attachments) {
6726
6770
  const images = attachments.filter((att2) => att2.type === "image" && att2.url);
6727
6771
  const videos = attachments.filter((att2) => att2.type === "video" && att2.url);
6728
6772
  const audios = attachments.filter((att2) => att2.type === "audio" && att2.url);
6729
- if (images.length > 1) return `${images.length} photos`;
6773
+ const files = attachments.filter(
6774
+ (att2) => att2.url && !["image", "video", "audio"].includes(att2.type)
6775
+ );
6776
+ if (images.length > 1) return getAttachmentCountPreviewLabel("image", images.length);
6730
6777
  if (images.length === 1) {
6731
- return images[0].caption?.trim() || "Photo";
6778
+ return images[0].caption?.trim() || getAttachmentTypePreviewLabel("image");
6732
6779
  }
6733
- if (videos.length > 1) return `${videos.length} videos`;
6780
+ if (videos.length > 1) return getAttachmentCountPreviewLabel("video", videos.length);
6734
6781
  if (videos.length === 1) {
6735
- return videos[0].caption?.trim() || "Video";
6782
+ return videos[0].caption?.trim() || getAttachmentTypePreviewLabel("video");
6736
6783
  }
6737
- if (audios.length > 1) return `${audios.length} audio files`;
6784
+ if (audios.length > 1) return getAttachmentCountPreviewLabel("audio", audios.length);
6738
6785
  if (audios.length === 1) {
6739
- return audios[0].caption?.trim() || "Audio";
6786
+ return audios[0].caption?.trim() || getAttachmentTypePreviewLabel("audio");
6787
+ }
6788
+ if (files.length > 1) return getAttachmentCountPreviewLabel("file", files.length);
6789
+ if (files.length === 1) {
6790
+ return files[0].caption?.trim() || getAttachmentTypePreviewLabel(files[0].type);
6791
+ }
6792
+ if (attachments.length > 1) {
6793
+ return getAttachmentCountPreviewLabel("file", attachments.length);
6740
6794
  }
6741
- if (attachments.length > 1) return `${attachments.length} files`;
6742
6795
  const att = attachments[0];
6743
- return att.caption?.trim() || cleanAttachmentDisplayName(att.name || "", "Attachment");
6796
+ return att?.caption?.trim() || getAttachmentTypePreviewLabel(att?.type);
6744
6797
  }
6745
6798
  function getLastMessageSidebarPreview(message) {
6746
6799
  const content = String(message?.content || "").trim();
@@ -6754,6 +6807,10 @@ function getLastMessageSidebarPreview(message) {
6754
6807
  if (attachments.length > 0) {
6755
6808
  return getAttachmentOnlyPreviewText(attachments);
6756
6809
  }
6810
+ const messageType = String(message?.type || "").toLowerCase();
6811
+ if (messageType && messageType !== "text") {
6812
+ return getAttachmentTypePreviewLabel(messageType);
6813
+ }
6757
6814
  return "No messages yet";
6758
6815
  }
6759
6816
  function getMessagePreviewText(message, fallback = "Message") {
@@ -6765,6 +6822,10 @@ function getMessagePreviewText(message, fallback = "Message") {
6765
6822
  if (attachments.length > 0) {
6766
6823
  return getAttachmentOnlyPreviewText(attachments);
6767
6824
  }
6825
+ const messageType = String(message?.type || "").toLowerCase();
6826
+ if (messageType && messageType !== "text") {
6827
+ return getAttachmentTypePreviewLabel(messageType);
6828
+ }
6768
6829
  return fallback;
6769
6830
  }
6770
6831
 
@@ -7406,7 +7467,7 @@ function highlightSearchMatch(text, query) {
7406
7467
  children: part
7407
7468
  },
7408
7469
  `${part}-${index}`
7409
- ) : /* @__PURE__ */ jsxRuntime.jsx(React2__default.default.Fragment, { children: part }, `${part}-${index}`)
7470
+ ) : /* @__PURE__ */ jsxRuntime.jsx(React2__namespace.default.Fragment, { children: part }, `${part}-${index}`)
7410
7471
  );
7411
7472
  }
7412
7473
  function getMessagePreview(message) {
@@ -7821,11 +7882,11 @@ function buildAttachmentSummary(attachments) {
7821
7882
  else fileCount += 1;
7822
7883
  }
7823
7884
  const parts = [];
7824
- if (imageCount) parts.push(`${imageCount} photo${imageCount > 1 ? "s" : ""}`);
7825
- if (videoCount) parts.push(`${videoCount} video${videoCount > 1 ? "s" : ""}`);
7826
- if (audioCount) parts.push(`${audioCount} audio file${audioCount > 1 ? "s" : ""}`);
7827
- if (fileCount) parts.push(`${fileCount} file${fileCount > 1 ? "s" : ""}`);
7828
- return parts.join(", ") || "Attachment";
7885
+ if (imageCount) parts.push(getAttachmentCountPreviewLabel("image", imageCount));
7886
+ if (videoCount) parts.push(getAttachmentCountPreviewLabel("video", videoCount));
7887
+ if (audioCount) parts.push(getAttachmentCountPreviewLabel("audio", audioCount));
7888
+ if (fileCount) parts.push(getAttachmentCountPreviewLabel("file", fileCount));
7889
+ return parts.join(", ") || getAttachmentTypePreviewLabel("file");
7829
7890
  }
7830
7891
  function mapSavedMessageAttachments(msg, messageObj, ctx) {
7831
7892
  const loggedUserId = String(ctx.loggedUserDetails?._id || "");
@@ -7887,11 +7948,19 @@ function resolveSavedMessageContent(messageObj, msg) {
7887
7948
  }
7888
7949
  return { content: filename, messageType: "file", previewUrl: void 0 };
7889
7950
  }
7890
- if (messageType === "image") return { content: "Photo", messageType, previewUrl: void 0 };
7891
- if (messageType === "video") return { content: "Video", messageType, previewUrl: void 0 };
7892
- if (messageType === "audio") return { content: "Audio", messageType, previewUrl: void 0 };
7893
- if (messageType === "file") return { content: "File", messageType, previewUrl: void 0 };
7894
- return { content: "Attachment", messageType, previewUrl: void 0 };
7951
+ if (messageType === "image") {
7952
+ return { content: getAttachmentTypePreviewLabel("image"), messageType, previewUrl: void 0 };
7953
+ }
7954
+ if (messageType === "video") {
7955
+ return { content: getAttachmentTypePreviewLabel("video"), messageType, previewUrl: void 0 };
7956
+ }
7957
+ if (messageType === "audio") {
7958
+ return { content: getAttachmentTypePreviewLabel("audio"), messageType, previewUrl: void 0 };
7959
+ }
7960
+ if (messageType === "file") {
7961
+ return { content: getAttachmentTypePreviewLabel("file"), messageType, previewUrl: void 0 };
7962
+ }
7963
+ return { content: getAttachmentTypePreviewLabel("file"), messageType, previewUrl: void 0 };
7895
7964
  }
7896
7965
  function getMessageId(msg) {
7897
7966
  if (msg?.messageId && typeof msg.messageId === "object") {
@@ -7925,7 +7994,7 @@ function readSenderFromRecord(record) {
7925
7994
  }
7926
7995
  function resolveSenderName(msg, ctx) {
7927
7996
  const messageObj = getMessageObject(msg);
7928
- const messageId = getMessageId(msg);
7997
+ const messageId2 = getMessageId(msg);
7929
7998
  const loggedId = String(ctx.loggedUserDetails?._id || "");
7930
7999
  const tryRecord = (record) => {
7931
8000
  const parsed = readSenderFromRecord(record);
@@ -7942,9 +8011,9 @@ function resolveSenderName(msg, ctx) {
7942
8011
  const hit = tryRecord(record);
7943
8012
  if (hit) return hit;
7944
8013
  }
7945
- if (messageId && ctx.conversationMessages?.length) {
8014
+ if (messageId2 && ctx.conversationMessages?.length) {
7946
8015
  const found = ctx.conversationMessages.find(
7947
- (m) => String(m._id || m.id) === String(messageId)
8016
+ (m) => String(m._id || m.id) === String(messageId2)
7948
8017
  );
7949
8018
  if (found) {
7950
8019
  const hit = tryRecord(found);
@@ -7995,7 +8064,7 @@ function parseSavedMessage(msg, ctx = {}) {
7995
8064
  const mode = ctx.mode || "pinned";
7996
8065
  const prefs = ctx.dateTimePrefs ?? {};
7997
8066
  if (msg?.isAttachment) {
7998
- const messageId2 = String(msg.messageId || "");
8067
+ const messageId3 = String(msg.messageId || "");
7999
8068
  const attachmentId2 = String(msg.attachmentId || msg._id || "");
8000
8069
  const attachments2 = mapSavedMessageAttachments(msg, null, ctx);
8001
8070
  const { content: content2, previewUrl: previewUrl2, messageType: messageType2 } = resolveSavedMessageContent(null, msg);
@@ -8003,8 +8072,8 @@ function parseSavedMessage(msg, ctx = {}) {
8003
8072
  const actionAt2 = msg?.createdAt || msg?.updatedAt || "";
8004
8073
  const bodyText2 = String(msg.attachment?.caption || "").trim() || void 0;
8005
8074
  return {
8006
- id: attachmentId2 || messageId2,
8007
- messageId: messageId2,
8075
+ id: attachmentId2 || messageId3,
8076
+ messageId: messageId3,
8008
8077
  attachmentId: attachmentId2 || void 0,
8009
8078
  content: content2,
8010
8079
  bodyText: bodyText2,
@@ -8023,7 +8092,7 @@ function parseSavedMessage(msg, ctx = {}) {
8023
8092
  }
8024
8093
  const messageObj = getMessageObject(msg);
8025
8094
  const id = getMessageId(msg);
8026
- const messageId = id;
8095
+ const messageId2 = id;
8027
8096
  const attachmentId = msg?.attachmentId ? String(msg.attachmentId) : void 0;
8028
8097
  const attachments = mapSavedMessageAttachments(msg, messageObj, ctx);
8029
8098
  const rawContent = messageObj?.content ?? msg?.content ?? msg?.messageId?.content ?? "";
@@ -8045,8 +8114,8 @@ function parseSavedMessage(msg, ctx = {}) {
8045
8114
  metaLabel = "Starred by you";
8046
8115
  }
8047
8116
  return {
8048
- id: attachmentId ? `${messageId}:${attachmentId}` : id,
8049
- messageId,
8117
+ id: attachmentId ? `${messageId2}:${attachmentId}` : id,
8118
+ messageId: messageId2,
8050
8119
  attachmentId,
8051
8120
  content: displayContent,
8052
8121
  bodyText,
@@ -8076,6 +8145,22 @@ function groupSavedMessages(items) {
8076
8145
  }));
8077
8146
  }
8078
8147
 
8148
+ // src/chat/lib/chat-attachment-display.ts
8149
+ init_chat_constants();
8150
+ function cleanAttachmentDisplayName(filename, fallback = "Attachment") {
8151
+ const trimmed = filename.trim();
8152
+ if (!trimmed) return fallback;
8153
+ let name = trimmed;
8154
+ const prefixPattern = new RegExp(`^\\d{${ATTACHMENT_FILENAME_TIMESTAMP_LENGTH}}_`);
8155
+ while (prefixPattern.test(name)) {
8156
+ name = name.slice(ATTACHMENT_FILENAME_TIMESTAMP_LENGTH + 1);
8157
+ }
8158
+ if (name.length > ATTACHMENT_FILENAME_TIMESTAMP_LENGTH && /^\d+$/.test(name.slice(0, ATTACHMENT_FILENAME_TIMESTAMP_LENGTH)) && name[ATTACHMENT_FILENAME_TIMESTAMP_LENGTH] !== "_") {
8159
+ name = name.slice(ATTACHMENT_FILENAME_TIMESTAMP_LENGTH);
8160
+ }
8161
+ return name.trim() || trimmed;
8162
+ }
8163
+
8079
8164
  // src/chat/header/saved-message/saved-message-utils.ts
8080
8165
  var AVATAR_PALETTES = [
8081
8166
  "bg-violet-500/15 text-violet-600 dark:text-violet-300",
@@ -8497,6 +8582,18 @@ var MessageStatus = ({ status, isPending, className }) => {
8497
8582
  ) });
8498
8583
  };
8499
8584
  var MessageStatus_default = MessageStatus;
8585
+ function GroupSenderName({ name, className }) {
8586
+ return /* @__PURE__ */ jsxRuntime.jsx(
8587
+ "span",
8588
+ {
8589
+ className: cn(
8590
+ "block max-w-full truncate text-[13px] font-semibold leading-[1.15] tracking-tight text-(--chat-incoming-text)",
8591
+ className
8592
+ ),
8593
+ children: name
8594
+ }
8595
+ );
8596
+ }
8500
8597
  function ForwardDoubleIcon({ className }) {
8501
8598
  return /* @__PURE__ */ jsxRuntime.jsxs(
8502
8599
  "svg",
@@ -8534,22 +8631,10 @@ function MessageForwardedLabel({ isSender, className, overlay }) {
8534
8631
  }
8535
8632
  );
8536
8633
  }
8537
- function GroupSenderName({ name, className }) {
8538
- return /* @__PURE__ */ jsxRuntime.jsx(
8539
- "span",
8540
- {
8541
- className: cn(
8542
- "block max-w-full truncate text-[13px] font-semibold leading-[1.15] tracking-tight text-(--chat-incoming-text)",
8543
- className
8544
- ),
8545
- children: name
8546
- }
8547
- );
8548
- }
8549
8634
 
8550
8635
  // src/chat/lib/chat-message-bubble.ts
8551
- function getBubbleCornerClasses() {
8552
- return "rounded-tl-[18px] rounded-tr-[18px] rounded-br-[18px] rounded-bl-none";
8636
+ function getBubbleCornerClasses(isSender) {
8637
+ return isSender ? "rounded-tl-[18px] rounded-tr-[18px] rounded-bl-[18px] rounded-br-none" : "rounded-tl-[18px] rounded-tr-[18px] rounded-br-[18px] rounded-bl-none";
8553
8638
  }
8554
8639
  function getChatBubbleClasses({
8555
8640
  isSender = false,
@@ -8560,7 +8645,7 @@ function getChatBubbleClasses({
8560
8645
  const isNeutral = resolvedSurface === "neutral";
8561
8646
  return cn(
8562
8647
  "relative",
8563
- getBubbleCornerClasses(),
8648
+ getBubbleCornerClasses(isSender),
8564
8649
  resolvedSurface === "sent" && "chat-bubble-sent bg-(--chat-theme) text-white",
8565
8650
  resolvedSurface === "received" && "chat-bubble-received border border-(--chat-border)/60 bg-(--chat-incoming-bubble) text-(--chat-incoming-text)",
8566
8651
  isNeutral && "chat-bubble-received border border-(--chat-border)/60 bg-(--chat-incoming-bubble) text-(--chat-incoming-text)",
@@ -8858,7 +8943,7 @@ function MessageAttachmentsCaptionBar({
8858
8943
  onCancelEdit
8859
8944
  }) {
8860
8945
  if (isStandaloneMetaOnly) {
8861
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-end pt-0.5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5", children: [
8946
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-end pt-1.5 pb-0.5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5", children: [
8862
8947
  /* @__PURE__ */ jsxRuntime.jsx(
8863
8948
  MessageCornerBadges,
8864
8949
  {
@@ -10069,6 +10154,8 @@ function FileAttachmentRow({
10069
10154
  }
10070
10155
  window.open(fileUrl, "_blank", "noopener,noreferrer");
10071
10156
  };
10157
+ const onThemeBubble = inBubble && isSender;
10158
+ const onIncomingBubble = inBubble && !isSender;
10072
10159
  return /* @__PURE__ */ jsxRuntime.jsxs(
10073
10160
  "div",
10074
10161
  {
@@ -10076,8 +10163,11 @@ function FileAttachmentRow({
10076
10163
  "group w-full transition-opacity",
10077
10164
  !stacked && "flex min-w-[220px] items-center gap-2",
10078
10165
  stacked && "py-1.5",
10079
- stacked && showDivider && (inBubble && isSender ? "border-t border-white/15" : "border-t border-(--chat-border)/35"),
10080
- !stacked && !inBubble && "rounded-2xl border border-(--chat-border) bg-(--chat-surface) p-2 shadow-sm",
10166
+ stacked && showDivider && (onThemeBubble ? "border-t border-white/15" : "border-t border-(--chat-border)/35"),
10167
+ !stacked && "rounded-xl border p-2.5",
10168
+ !stacked && onThemeBubble && "border-white/20 bg-white/12 text-white shadow-[inset_0_1px_0_rgba(255,255,255,0.08)] backdrop-blur-[2px]",
10169
+ !stacked && onIncomingBubble && "border-(--chat-border)/70 bg-(--chat-elevated) text-(--chat-text) shadow-sm [.dark_&]:bg-(--chat-surface)",
10170
+ !stacked && !inBubble && "border-(--chat-border) bg-(--chat-surface) shadow-sm",
10081
10171
  !fileUrl && "pointer-events-none opacity-60",
10082
10172
  isCaptionActive && "opacity-90"
10083
10173
  ),
@@ -10089,36 +10179,31 @@ function FileAttachmentRow({
10089
10179
  type: "button",
10090
10180
  onClick: handleFileOpen,
10091
10181
  disabled: !fileUrl || selectionMode,
10092
- className: "flex min-w-0 flex-1 items-center gap-2 text-left disabled:cursor-default",
10182
+ className: "flex min-w-0 flex-1 items-center gap-2.5 text-left disabled:cursor-default",
10093
10183
  children: [
10094
10184
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(
10095
- "flex shrink-0 items-center justify-center rounded-lg text-white",
10096
- stacked ? "size-9" : "size-10 rounded-xl shadow-sm",
10185
+ "flex size-10 shrink-0 items-center justify-center rounded-lg text-white shadow-sm",
10097
10186
  getAttachmentIconBoxClass(rawName)
10098
- ), children: getAttachmentIcon(rawName, "file", "text-white", stacked ? 18 : 20) }),
10187
+ ), children: getAttachmentIcon(rawName, "file", "text-white", 18) }),
10099
10188
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
10100
10189
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
10101
- "block truncate text-xs font-medium leading-tight",
10102
- inBubble && isSender ? "text-white" : "text-(--chat-text)"
10190
+ "block truncate text-[12px] font-semibold leading-tight",
10191
+ onThemeBubble ? "text-white" : "text-(--chat-text)"
10103
10192
  ), children: displayName }),
10104
10193
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
10105
- "mt-0.5 block truncate text-[10px] leading-tight uppercase",
10106
- inBubble && isSender ? "text-white/60" : "text-(--chat-muted)"
10194
+ "mt-0.5 block truncate text-[10px] font-medium leading-tight uppercase tracking-wide",
10195
+ onThemeBubble ? "text-white/70" : "text-(--chat-muted)"
10107
10196
  ), children: subtitle })
10108
10197
  ] }),
10109
10198
  /* @__PURE__ */ jsxRuntime.jsx(
10110
10199
  "span",
10111
10200
  {
10112
10201
  className: cn(
10113
- "flex shrink-0 items-center justify-center transition-colors",
10114
- stacked ? "size-6 text-(--chat-muted) group-hover:text-(--chat-theme)" : cn(
10115
- "size-7 rounded-lg border",
10116
- inBubble && isSender ? "border-white/15 bg-white/10 text-white/80 group-hover:bg-white/15 group-hover:text-white" : "border-(--chat-border) bg-(--chat-elevated) text-(--chat-muted) group-hover:text-(--chat-theme)"
10117
- ),
10118
- stacked && inBubble && isSender && "text-white/70 group-hover:text-white"
10202
+ "flex size-8 shrink-0 items-center justify-center rounded-full transition-colors",
10203
+ onThemeBubble ? "text-white/80 group-hover:bg-white/10 group-hover:text-white" : "text-(--chat-muted) group-hover:bg-(--chat-hover) group-hover:text-(--chat-theme)"
10119
10204
  ),
10120
10205
  "aria-hidden": true,
10121
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { size: stacked ? 13 : 14 })
10206
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { size: 14 })
10122
10207
  }
10123
10208
  )
10124
10209
  ]
@@ -10129,13 +10214,13 @@ function FileAttachmentRow({
10129
10214
  {
10130
10215
  onClick: onEditCaption,
10131
10216
  label: `${attachmentCaption ? "Edit" : "Add"} caption for ${displayName}`,
10132
- className: inBubble && isSender ? "text-white/60 hover:text-white" : void 0
10217
+ className: onThemeBubble ? "text-white/60 hover:text-white" : void 0
10133
10218
  }
10134
10219
  )
10135
10220
  ] }),
10136
10221
  stacked && attachmentCaption ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn(
10137
- "mt-1 whitespace-pre-wrap break-words pl-11 pr-7 text-[11px] leading-snug",
10138
- inBubble && isSender ? "text-white/85" : "text-(--chat-text-secondary)"
10222
+ "mt-1 whitespace-pre-wrap break-words pl-12 pr-8 text-[11px] leading-snug",
10223
+ onThemeBubble ? "text-white/85" : "text-(--chat-text-secondary)"
10139
10224
  ), children: attachmentCaption }) : null
10140
10225
  ]
10141
10226
  }
@@ -10254,17 +10339,30 @@ function MessageAttachmentsNonImageSection({
10254
10339
  att.id
10255
10340
  );
10256
10341
  };
10257
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: nonImageGroups.map((group) => {
10342
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex w-full flex-col gap-1.5", children: nonImageGroups.map((group) => {
10258
10343
  if (group.kind === "file-run") {
10259
10344
  if (group.items.length === 1) {
10260
10345
  return renderFileAttachmentFrame(group.items[0]);
10261
10346
  }
10262
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full min-w-[220px]", children: group.items.map(
10263
- (att2, index) => renderFileAttachmentFrame(att2, {
10264
- stacked: true,
10265
- showDivider: index > 0
10266
- })
10267
- ) }, `file-run-${group.items.map((item) => item.id).join("-")}`);
10347
+ return /* @__PURE__ */ jsxRuntime.jsx(
10348
+ "div",
10349
+ {
10350
+ className: cn(
10351
+ "w-full min-w-[220px]",
10352
+ isBubbleLayout && "rounded-xl border p-2",
10353
+ isBubbleLayout && isSender && "border-white/20 bg-white/12 shadow-[inset_0_1px_0_rgba(255,255,255,0.08)] backdrop-blur-[2px]",
10354
+ isBubbleLayout && !isSender && "border-(--chat-border)/70 bg-(--chat-elevated) shadow-sm [.dark_&]:bg-(--chat-surface)",
10355
+ !isBubbleLayout && "rounded-xl border border-(--chat-border) bg-(--chat-surface) p-2 shadow-sm"
10356
+ ),
10357
+ children: group.items.map(
10358
+ (att2, index) => renderFileAttachmentFrame(att2, {
10359
+ stacked: true,
10360
+ showDivider: index > 0
10361
+ })
10362
+ )
10363
+ },
10364
+ `file-run-${group.items.map((item) => item.id).join("-")}`
10365
+ );
10268
10366
  }
10269
10367
  const att = group.item;
10270
10368
  const type = resolveAttachmentType(att);
@@ -10337,7 +10435,8 @@ function MessageAttachmentsView({
10337
10435
  isGroupedWithPrev = false,
10338
10436
  isGroupedWithNext = false,
10339
10437
  showSenderLabel = false,
10340
- senderName
10438
+ senderName,
10439
+ senderId
10341
10440
  }) {
10342
10441
  const [documentPreview, setDocumentPreview] = React2.useState(null);
10343
10442
  const visibleAttachments = getVisibleAttachments(attachments);
@@ -10378,7 +10477,10 @@ function MessageAttachmentsView({
10378
10477
  isSender,
10379
10478
  surface: bubbleSurface,
10380
10479
  className: cn(
10381
- isImageOnlyBubble ? "overflow-hidden p-0" : isForwarded || canShowSenderName ? "px-2 py-0.5" : "px-2.5 py-1"
10480
+ isImageOnlyBubble ? "overflow-hidden p-0" : isForwarded || canShowSenderName ? "px-2 py-1" : cn(
10481
+ "px-2.5",
10482
+ nonImages.length > 1 || images.length > 0 && nonImages.length > 0 ? "py-1.5" : "py-1"
10483
+ )
10382
10484
  )
10383
10485
  })
10384
10486
  ),
@@ -10391,7 +10493,13 @@ function MessageAttachmentsView({
10391
10493
  isImageOnlyBubble ? "px-2.5 pt-1.5 pb-1" : "px-0.5 pb-0.5"
10392
10494
  ),
10393
10495
  children: [
10394
- canShowSenderName ? /* @__PURE__ */ jsxRuntime.jsx(GroupSenderName, { name: senderName }) : null,
10496
+ canShowSenderName ? /* @__PURE__ */ jsxRuntime.jsx(
10497
+ GroupSenderName,
10498
+ {
10499
+ name: senderName,
10500
+ colorSeed: senderId || senderName
10501
+ }
10502
+ ) : null,
10395
10503
  showForwardedInHeader ? /* @__PURE__ */ jsxRuntime.jsx(
10396
10504
  MessageForwardedLabel,
10397
10505
  {
@@ -10405,7 +10513,7 @@ function MessageAttachmentsView({
10405
10513
  isBubbleLayout && replySnippet ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 pb-1", children: replySnippet }) : null,
10406
10514
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(
10407
10515
  "flex w-full flex-col",
10408
- !isImageOnlyBubble && "gap-0",
10516
+ !isImageOnlyBubble && (images.length > 0 && nonImages.length > 0 ? "gap-1.5" : "gap-0"),
10409
10517
  isImageOnlyBubble && "relative overflow-hidden"
10410
10518
  ), children: [
10411
10519
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -10935,7 +11043,7 @@ function collectConversationAttachments(messages) {
10935
11043
  const items = [];
10936
11044
  for (const message of messages) {
10937
11045
  if (message?.isDeletedForEveryone) continue;
10938
- const messageId = String(message._id || message.id || "");
11046
+ const messageId2 = String(message._id || message.id || "");
10939
11047
  const createdAt = message.createdAt || message.timestamp;
10940
11048
  const messageType = message.type || "text";
10941
11049
  for (const attachment of message.attachments || []) {
@@ -10953,13 +11061,35 @@ function collectConversationAttachments(messages) {
10953
11061
  url,
10954
11062
  name,
10955
11063
  type: resolveFileCategory(name, fileType, resolvedType),
10956
- messageId,
11064
+ messageId: messageId2,
10957
11065
  createdAt,
10958
11066
  size: typeof attachment.size === "number" ? attachment.size : void 0,
10959
11067
  duration: typeof attachment.duration === "number" ? attachment.duration : void 0,
10960
11068
  fileType
10961
11069
  });
10962
11070
  }
11071
+ if ((message.attachments || []).length === 0) {
11072
+ const rootUrl = message.url || message.fileUrl || message.attachmentUrl || message.public_link || message.publicLink || "";
11073
+ if (!rootUrl) continue;
11074
+ const name = message.filename || message.fileName || message.name || "Attachment";
11075
+ const fileType = message.fileType || message.mimeType || "";
11076
+ const dedupeKey = `${rootUrl}|${name}`;
11077
+ if (seen.has(dedupeKey)) continue;
11078
+ seen.add(dedupeKey);
11079
+ const baseType = inferAttachmentType(fileType, name);
11080
+ const resolvedType = messageType === "image" && baseType === "file" ? "image" : baseType;
11081
+ items.push({
11082
+ id: String(message.attachmentId || message.fileId || dedupeKey),
11083
+ url: rootUrl,
11084
+ name,
11085
+ type: resolveFileCategory(name, fileType, resolvedType),
11086
+ messageId: messageId2,
11087
+ createdAt,
11088
+ size: typeof message.size === "number" ? message.size : void 0,
11089
+ duration: typeof message.duration === "number" ? message.duration : void 0,
11090
+ fileType
11091
+ });
11092
+ }
10963
11093
  }
10964
11094
  return items.sort(
10965
11095
  (a, b) => new Date(b.createdAt || 0).getTime() - new Date(a.createdAt || 0).getTime()
@@ -11170,9 +11300,13 @@ function AttachmentSection({
11170
11300
  }
11171
11301
  var AttachmentsDrawer = ({ isOpen, onOpenChange, conversationId }) => {
11172
11302
  const messagesByConversation = exports.useChatStore((s) => s.messagesByConversation);
11303
+ const messagesMetadata = exports.useChatStore((s) => s.messagesMetadata);
11304
+ const fetchMessages2 = exports.useChatStore((s) => s.fetchMessages);
11173
11305
  const [sectionVisibleCount, setSectionVisibleCount] = React2.useState({});
11174
11306
  const [documentPreview, setDocumentPreview] = React2.useState(null);
11175
11307
  const [imageLightboxIndex, setImageLightboxIndex] = React2.useState(null);
11308
+ const hasLoadedMessages = conversationId ? Boolean(messagesMetadata[conversationId]?.isFirstPage) : false;
11309
+ const isLoading = isOpen && !!conversationId && !hasLoadedMessages;
11176
11310
  React2.useEffect(() => {
11177
11311
  if (!isOpen) {
11178
11312
  setSectionVisibleCount({});
@@ -11183,6 +11317,10 @@ var AttachmentsDrawer = ({ isOpen, onOpenChange, conversationId }) => {
11183
11317
  React2.useEffect(() => {
11184
11318
  setSectionVisibleCount({});
11185
11319
  }, [conversationId]);
11320
+ React2.useEffect(() => {
11321
+ if (!isOpen || !conversationId || hasLoadedMessages) return;
11322
+ fetchMessages2(conversationId);
11323
+ }, [isOpen, conversationId, hasLoadedMessages, fetchMessages2]);
11186
11324
  const attachments = React2.useMemo(() => {
11187
11325
  if (!conversationId) return [];
11188
11326
  const messages = messagesByConversation[conversationId] || [];
@@ -11234,7 +11372,11 @@ var AttachmentsDrawer = ({ isOpen, onOpenChange, conversationId }) => {
11234
11372
  ] }),
11235
11373
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-[11px] text-(--chat-muted)", children: "Shared media and files" })
11236
11374
  ] }) }),
11237
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "chat-message-scroll flex-1 overflow-y-auto bg-(--chat-main-bg) px-2.5 py-2", children: attachments.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "chat-saved-empty flex min-h-[220px] flex-col items-center justify-center px-4 text-center", children: [
11375
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "chat-message-scroll flex-1 overflow-y-auto bg-(--chat-main-bg) px-2.5 py-2", children: isLoading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-[220px] flex-col items-center justify-center px-4 text-center", children: [
11376
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mb-3 size-8 animate-spin text-(--chat-theme)" }),
11377
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[13px] font-medium text-(--chat-text)", children: "Loading attachments..." }),
11378
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-[11px] text-(--chat-muted)", children: "Fetching shared files for this chat" })
11379
+ ] }) : attachments.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "chat-saved-empty flex min-h-[220px] flex-col items-center justify-center px-4 text-center", children: [
11238
11380
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-3", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "chat-saved-empty-icon-wrap", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Paperclip, { size: 22, className: cn("chat-saved-empty-icon !text-(--chat-theme)") }) }) }),
11239
11381
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[14px] font-semibold text-(--chat-text)", children: "No attachments" }),
11240
11382
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1.5 max-w-[240px] text-[12px] leading-relaxed text-(--chat-muted)", children: "Shared files will show up here." })
@@ -11617,7 +11759,7 @@ var ChannelDetailsDrawer = (props) => {
11617
11759
  {
11618
11760
  type: "button",
11619
11761
  onClick: () => fileInputRef.current?.click(),
11620
- className: "absolute -bottom-0.5 -right-0.5 flex size-6 items-center justify-center rounded-full border border-(--chat-border) bg-(--chat-surface) text-(--chat-muted) shadow-sm hover:text-(--chat-text)",
11762
+ className: "absolute -bottom-0.5 -right-0.5 flex size-6 items-center justify-center rounded-full border border-(--chat-border) bg-(--chat-surface) text-(--chat-theme) shadow-sm hover:bg-(--chat-theme-10)",
11621
11763
  title: "Change group avatar",
11622
11764
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Camera, { size: 12 })
11623
11765
  }
@@ -11656,7 +11798,7 @@ var ChannelDetailsDrawer = (props) => {
11656
11798
  {
11657
11799
  variant: "outline",
11658
11800
  size: "sm",
11659
- className: "h-8 flex-1 text-[12px]",
11801
+ className: "h-8 flex-1 border-(--chat-border) bg-(--chat-surface) text-[12px] text-(--chat-text) hover:bg-(--chat-hover)",
11660
11802
  onClick: () => setIsEditing(false),
11661
11803
  children: [
11662
11804
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "mr-1 size-3" }),
@@ -11668,7 +11810,7 @@ var ChannelDetailsDrawer = (props) => {
11668
11810
  Button,
11669
11811
  {
11670
11812
  size: "sm",
11671
- className: "h-8 flex-1 text-[12px]",
11813
+ className: "h-8 flex-1 border border-(--chat-theme) bg-(--chat-theme) text-[12px] text-white hover:opacity-90 disabled:opacity-50",
11672
11814
  onClick: handleSave,
11673
11815
  disabled: isSaving || imageUploadStatus === "uploading",
11674
11816
  children: isSaving ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-3 animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -11686,7 +11828,7 @@ var ChannelDetailsDrawer = (props) => {
11686
11828
  {
11687
11829
  variant: "ghost",
11688
11830
  size: "sm",
11689
- className: "mt-2 h-7 gap-1 px-2 text-[11px] text-(--chat-muted) hover:text-(--chat-text)",
11831
+ className: "mt-2 h-7 gap-1 px-2 text-[11px] text-(--chat-theme) hover:bg-(--chat-theme-10) hover:text-(--chat-theme)",
11690
11832
  onClick: () => setIsEditing(true),
11691
11833
  children: [
11692
11834
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "size-3" }),
@@ -12544,8 +12686,8 @@ function useChannelHeader({
12544
12686
  }
12545
12687
  }
12546
12688
  };
12547
- const handleSelectSearchResult = async (messageId) => {
12548
- await fetchSearchMessageContext(messageId);
12689
+ const handleSelectSearchResult = async (messageId2) => {
12690
+ await fetchSearchMessageContext(messageId2);
12549
12691
  handleCloseSearch();
12550
12692
  };
12551
12693
  const handleSearchOpenChange = (open) => {
@@ -12581,6 +12723,14 @@ function useChannelHeader({
12581
12723
  fetchStarredMessages2(conversationId);
12582
12724
  }
12583
12725
  }, [state.isFavoriteOpen, conversationId, fetchStarredMessages2]);
12726
+ React2.useEffect(() => {
12727
+ if (state.isAttachmentsOpen && conversationId) {
12728
+ const meta = exports.useChatStore.getState().messagesMetadata[conversationId];
12729
+ if (!meta?.isFirstPage) {
12730
+ fetchMessagesStore(conversationId);
12731
+ }
12732
+ }
12733
+ }, [state.isAttachmentsOpen, conversationId, fetchMessagesStore]);
12584
12734
  const pinnedCount = liveCounts?.pinnedCount ?? activeChannel?.pinnedCount ?? 0;
12585
12735
  const starredCount = liveCounts?.starredCount ?? activeChannel?.starredCount ?? 0;
12586
12736
  const handleClearChat = () => {
@@ -12626,14 +12776,14 @@ function useChannelHeader({
12626
12776
  updateState({ isBlockAlertOpen: false });
12627
12777
  }
12628
12778
  };
12629
- const handleUnpin = (messageId, attachmentId) => {
12779
+ const handleUnpin = (messageId2, attachmentId) => {
12630
12780
  if (!loggedUserDetails?._id || !conversationId || !activeChannel) return;
12631
- const loadingKey = attachmentId ? `${messageId}:${attachmentId}` : messageId;
12781
+ const loadingKey = attachmentId ? `${messageId2}:${attachmentId}` : messageId2;
12632
12782
  updateState({ loadingIds: new Set(state.loadingIds).add(loadingKey) });
12633
12783
  const basePayload = {
12634
12784
  conversationId,
12635
12785
  sender: loggedUserDetails._id,
12636
- messageId,
12786
+ messageId: messageId2,
12637
12787
  receiver: activeChannel.id,
12638
12788
  ...attachmentId ? { attachmentId } : {}
12639
12789
  };
@@ -12653,12 +12803,12 @@ function useChannelHeader({
12653
12803
  if (!dateStr) return "";
12654
12804
  return formatLongDate(dateStr);
12655
12805
  };
12656
- const handleUnstar = (messageId, attachmentId) => {
12806
+ const handleUnstar = (messageId2, attachmentId) => {
12657
12807
  if (!loggedUserDetails?._id || !conversationId || !activeChannel) return;
12658
- const loadingKey = attachmentId ? `${messageId}:${attachmentId}` : messageId;
12808
+ const loadingKey = attachmentId ? `${messageId2}:${attachmentId}` : messageId2;
12659
12809
  updateState({ loadingIds: new Set(state.loadingIds).add(loadingKey) });
12660
12810
  const basePayload = {
12661
- messageId,
12811
+ messageId: messageId2,
12662
12812
  sender: loggedUserDetails._id,
12663
12813
  conversationId,
12664
12814
  receiver: activeChannel.id,
@@ -12928,7 +13078,7 @@ var MessageReactions = ({
12928
13078
  {
12929
13079
  onClick: () => onReactionClick(emoji),
12930
13080
  className: cn(
12931
- "flex items-center gap-1 px-2 py-0.5 rounded-full text-xs border shadow-sm transition-all shadow-black/5 outline-none",
13081
+ "flex items-center gap-0.5 px-1.5 py-0.5 rounded-full text-[11px] border shadow-[0_1px_3px_rgba(15,23,42,0.08)] transition-all outline-none",
12932
13082
  isReactedByMe ? "bg-(--chat-theme-10) border-(--chat-theme-20) text-(--chat-theme)" : "bg-(--chat-surface) border-(--chat-border) text-(--chat-text) hover:bg-(--chat-hover)"
12933
13083
  ),
12934
13084
  children: [
@@ -12982,7 +13132,7 @@ var MessageToolbar = ({
12982
13132
  "div",
12983
13133
  {
12984
13134
  className: cn(
12985
- "absolute -top-8 z-40 flex items-center gap-0.5 rounded-full border border-(--chat-border) p-0.5 shadow-md backdrop-blur-sm",
13135
+ "absolute -top-8 z-50 flex items-center gap-0.5 rounded-full border border-(--chat-border) p-0.5 shadow-md backdrop-blur-sm",
12986
13136
  "bg-(--chat-toolbar-bg) text-(--chat-text)",
12987
13137
  isSender ? "right-0" : "left-0"
12988
13138
  ),
@@ -13258,8 +13408,8 @@ init_useStore();
13258
13408
 
13259
13409
  // src/chat/lib/chat-selection.ts
13260
13410
  init_attachment_helpers();
13261
- function buildSelectionKey(messageId, attachmentId) {
13262
- return pinKey(messageId, attachmentId || null);
13411
+ function buildSelectionKey(messageId2, attachmentId) {
13412
+ return pinKey(messageId2, attachmentId || null);
13263
13413
  }
13264
13414
  function parseSelectionKey(key) {
13265
13415
  const colonIndex = key.indexOf(":");
@@ -13274,8 +13424,8 @@ function parseSelectionKey(key) {
13274
13424
  function messageUsesAttachmentSelection(message) {
13275
13425
  return getVisibleAttachments(message.attachments).length > 1;
13276
13426
  }
13277
- function getSelectedAttachmentIdsForMessage(selectedKeys, messageId) {
13278
- const prefix = `${messageId}:`;
13427
+ function getSelectedAttachmentIdsForMessage(selectedKeys, messageId2) {
13428
+ const prefix = `${messageId2}:`;
13279
13429
  const ids = /* @__PURE__ */ new Set();
13280
13430
  selectedKeys.forEach((key) => {
13281
13431
  if (key.startsWith(prefix)) {
@@ -13284,14 +13434,14 @@ function getSelectedAttachmentIdsForMessage(selectedKeys, messageId) {
13284
13434
  });
13285
13435
  return ids;
13286
13436
  }
13287
- function isMessageWhollySelected(selectedKeys, messageId) {
13288
- return selectedKeys.has(messageId);
13437
+ function isMessageWhollySelected(selectedKeys, messageId2) {
13438
+ return selectedKeys.has(messageId2);
13289
13439
  }
13290
13440
  function resolveForwardItems(selectedKeys, messages) {
13291
13441
  const items = [];
13292
13442
  selectedKeys.forEach((key) => {
13293
- const { messageId, attachmentId } = parseSelectionKey(key);
13294
- const message = messages.find((entry) => String(entry._id || entry.id) === messageId);
13443
+ const { messageId: messageId2, attachmentId } = parseSelectionKey(key);
13444
+ const message = messages.find((entry) => String(entry._id || entry.id) === messageId2);
13295
13445
  if (!message) return;
13296
13446
  items.push({ message, attachmentId });
13297
13447
  });
@@ -13317,7 +13467,7 @@ function useMessageItemActions({
13317
13467
  message,
13318
13468
  createdAt,
13319
13469
  attachments,
13320
- messageId,
13470
+ messageId: messageId2,
13321
13471
  receiver,
13322
13472
  isDeletedForEveryone,
13323
13473
  reactions,
@@ -13369,10 +13519,10 @@ function useMessageItemActions({
13369
13519
  const allUsers = exports.useChatStore((s) => s.allUsers);
13370
13520
  const loggedUserDetails = exports.useChatStore((s) => s.loggedUserDetails);
13371
13521
  const pinnedMessagesByConversation = exports.useChatStore((s) => s.pinnedMessagesByConversation);
13372
- const mid = String(messageId || "");
13522
+ const mid = String(messageId2 || "");
13373
13523
  const pendingActions = mid ? messagePendingActions[mid] || [] : [];
13374
13524
  const isPending = Boolean(
13375
- isSender && (String(messageId || "").startsWith("temp-") || mid && (messagePendingActions[mid] || []).includes("send"))
13525
+ isSender && (String(messageId2 || "").startsWith("temp-") || mid && (messagePendingActions[mid] || []).includes("send"))
13376
13526
  );
13377
13527
  const isEditPending = pendingActions.includes("edit");
13378
13528
  const isDeletePending = pendingActions.includes("delete");
@@ -13410,13 +13560,13 @@ function useMessageItemActions({
13410
13560
  };
13411
13561
  const handleSaveAttachmentCaption = (caption, attachment) => {
13412
13562
  const target = attachment ?? state.captionModalAttachment;
13413
- if (!messageId || !loggedUserDetails || !target) return;
13563
+ if (!messageId2 || !loggedUserDetails || !target) return;
13414
13564
  const attachmentId = target.id;
13415
13565
  if (isGroup) {
13416
13566
  if (!conversationId) return;
13417
13567
  emitGroupEdit({
13418
13568
  content: caption,
13419
- messageId,
13569
+ messageId: messageId2,
13420
13570
  sender: loggedUserDetails._id,
13421
13571
  conversationId,
13422
13572
  attachmentId
@@ -13425,7 +13575,7 @@ function useMessageItemActions({
13425
13575
  if (!receiver) return;
13426
13576
  emitDmEdit({
13427
13577
  content: caption,
13428
- messageId,
13578
+ messageId: messageId2,
13429
13579
  sender: loggedUserDetails._id,
13430
13580
  receiver,
13431
13581
  attachmentId
@@ -13442,12 +13592,12 @@ function useMessageItemActions({
13442
13592
  onEnterSelectionMode?.();
13443
13593
  };
13444
13594
  const handleSaveEdit = () => {
13445
- if (!messageId || !loggedUserDetails) return;
13595
+ if (!messageId2 || !loggedUserDetails) return;
13446
13596
  if (isGroup) {
13447
13597
  if (!conversationId) return;
13448
13598
  emitGroupEdit({
13449
13599
  content: state.editValue.trim(),
13450
- messageId,
13600
+ messageId: messageId2,
13451
13601
  sender: loggedUserDetails._id,
13452
13602
  conversationId
13453
13603
  });
@@ -13455,7 +13605,7 @@ function useMessageItemActions({
13455
13605
  if (!receiver) return;
13456
13606
  emitDmEdit({
13457
13607
  content: state.editValue.trim(),
13458
- messageId,
13608
+ messageId: messageId2,
13459
13609
  sender: loggedUserDetails._id,
13460
13610
  receiver
13461
13611
  });
@@ -13466,7 +13616,7 @@ function useMessageItemActions({
13466
13616
  updateState({ isEditing: false, editValue: message });
13467
13617
  };
13468
13618
  const handleDeleteMessage = (deleteType) => {
13469
- if (!messageId || !loggedUserDetails) return;
13619
+ if (!messageId2 || !loggedUserDetails) return;
13470
13620
  if (deleteType === "everyone" && !isSender) return;
13471
13621
  if (deleteType === "everyone" && !isWithinEditWindow()) return;
13472
13622
  const attachmentIds = hasAttachments ? deleteAttachmentIds : [];
@@ -13474,7 +13624,7 @@ function useMessageItemActions({
13474
13624
  if (isGroup) {
13475
13625
  if (!conversationId) return;
13476
13626
  emitGroupDelete({
13477
- messageId,
13627
+ messageId: messageId2,
13478
13628
  sender: loggedUserDetails._id,
13479
13629
  deleteType,
13480
13630
  conversationId,
@@ -13483,7 +13633,7 @@ function useMessageItemActions({
13483
13633
  } else {
13484
13634
  if (!receiver) return;
13485
13635
  emitDmDelete({
13486
- messageId,
13636
+ messageId: messageId2,
13487
13637
  sender: loggedUserDetails._id,
13488
13638
  receiver,
13489
13639
  deleteType,
@@ -13505,7 +13655,7 @@ function useMessageItemActions({
13505
13655
  onForward?.();
13506
13656
  };
13507
13657
  const handleReactionClick = (emojiObject) => {
13508
- if (!messageId || !loggedUserDetails) return;
13658
+ if (!messageId2 || !loggedUserDetails) return;
13509
13659
  const reaction = typeof emojiObject === "string" ? emojiObject : emojiObject.emoji || emojiObject.native;
13510
13660
  const hasReacted = reactions?.some(
13511
13661
  (r) => r.reaction === reaction && String(r.addedBy?._id || r.addedBy || r.sender?._id || r.sender) === String(loggedUserDetails._id)
@@ -13514,7 +13664,7 @@ function useMessageItemActions({
13514
13664
  if (isGroup) {
13515
13665
  if (!conversationId) return;
13516
13666
  emitGroupReactionRemove({
13517
- messageId,
13667
+ messageId: messageId2,
13518
13668
  sender: loggedUserDetails._id,
13519
13669
  reaction,
13520
13670
  conversationId
@@ -13522,7 +13672,7 @@ function useMessageItemActions({
13522
13672
  } else {
13523
13673
  if (!receiver) return;
13524
13674
  emitDmReactionRemove({
13525
- messageId,
13675
+ messageId: messageId2,
13526
13676
  sender: loggedUserDetails._id,
13527
13677
  receiver,
13528
13678
  reaction,
@@ -13533,7 +13683,7 @@ function useMessageItemActions({
13533
13683
  if (isGroup) {
13534
13684
  if (!conversationId) return;
13535
13685
  emitGroupReactionAdd({
13536
- messageId,
13686
+ messageId: messageId2,
13537
13687
  sender: loggedUserDetails._id,
13538
13688
  reaction,
13539
13689
  conversationId
@@ -13541,7 +13691,7 @@ function useMessageItemActions({
13541
13691
  } else {
13542
13692
  if (!receiver) return;
13543
13693
  emitDmReactionAdd({
13544
- messageId,
13694
+ messageId: messageId2,
13545
13695
  sender: loggedUserDetails._id,
13546
13696
  receiver,
13547
13697
  reaction,
@@ -13551,7 +13701,7 @@ function useMessageItemActions({
13551
13701
  }
13552
13702
  };
13553
13703
  const handlePinClick = () => {
13554
- if (!messageId || !loggedUserDetails) return;
13704
+ if (!messageId2 || !loggedUserDetails) return;
13555
13705
  if (isPinned) {
13556
13706
  if (!isPinnedByMe) return;
13557
13707
  if (isGroup) {
@@ -13559,14 +13709,14 @@ function useMessageItemActions({
13559
13709
  emitGroupUnpin({
13560
13710
  conversationId,
13561
13711
  sender: loggedUserDetails._id,
13562
- messageId,
13712
+ messageId: messageId2,
13563
13713
  receiver: ""
13564
13714
  });
13565
13715
  } else {
13566
13716
  emitDmUnpin({
13567
13717
  conversationId,
13568
13718
  sender: loggedUserDetails._id,
13569
- messageId,
13719
+ messageId: messageId2,
13570
13720
  receiver: receiver || ""
13571
13721
  });
13572
13722
  }
@@ -13576,32 +13726,32 @@ function useMessageItemActions({
13576
13726
  emitGroupPin({
13577
13727
  conversationId,
13578
13728
  sender: loggedUserDetails._id,
13579
- messageId,
13729
+ messageId: messageId2,
13580
13730
  receiver: ""
13581
13731
  });
13582
13732
  } else {
13583
13733
  emitDmPin({
13584
13734
  conversationId,
13585
13735
  sender: loggedUserDetails._id,
13586
- messageId,
13736
+ messageId: messageId2,
13587
13737
  receiver: receiver || ""
13588
13738
  });
13589
13739
  }
13590
13740
  }
13591
13741
  };
13592
13742
  const handleStarClick = () => {
13593
- if (!messageId || !loggedUserDetails || !conversationId) return;
13743
+ if (!messageId2 || !loggedUserDetails || !conversationId) return;
13594
13744
  if (isStarred) {
13595
13745
  if (isGroup) {
13596
- emitGroupUnstar({ messageId, sender: loggedUserDetails._id, conversationId });
13746
+ emitGroupUnstar({ messageId: messageId2, sender: loggedUserDetails._id, conversationId });
13597
13747
  } else {
13598
- emitDmUnstar({ messageId, sender: loggedUserDetails._id, conversationId });
13748
+ emitDmUnstar({ messageId: messageId2, sender: loggedUserDetails._id, conversationId });
13599
13749
  }
13600
13750
  } else {
13601
13751
  if (isGroup) {
13602
- emitGroupStar({ messageId, sender: loggedUserDetails._id, conversationId });
13752
+ emitGroupStar({ messageId: messageId2, sender: loggedUserDetails._id, conversationId });
13603
13753
  } else {
13604
- emitDmStar({ messageId, sender: loggedUserDetails._id, conversationId });
13754
+ emitDmStar({ messageId: messageId2, sender: loggedUserDetails._id, conversationId });
13605
13755
  }
13606
13756
  }
13607
13757
  };
@@ -13823,6 +13973,7 @@ function MessageItemTextBubble({
13823
13973
  isForwarded,
13824
13974
  showSenderLabel,
13825
13975
  senderName,
13976
+ senderId,
13826
13977
  replyTo,
13827
13978
  loggedUserDetails,
13828
13979
  allUsers,
@@ -13861,7 +14012,13 @@ function MessageItemTextBubble({
13861
14012
  ),
13862
14013
  children: [
13863
14014
  (canShowSenderName || isForwarded) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [
13864
- canShowSenderName ? /* @__PURE__ */ jsxRuntime.jsx(GroupSenderName, { name: senderName }) : null,
14015
+ canShowSenderName ? /* @__PURE__ */ jsxRuntime.jsx(
14016
+ GroupSenderName,
14017
+ {
14018
+ name: senderName,
14019
+ colorSeed: senderId || senderName
14020
+ }
14021
+ ) : null,
13865
14022
  isForwarded ? /* @__PURE__ */ jsxRuntime.jsx(MessageForwardedLabel, { isSender, className: "px-0 pt-0 pb-0" }) : null
13866
14023
  ] }),
13867
14024
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -13912,7 +14069,7 @@ function MessageItemTextBubble({
13912
14069
  }
13913
14070
  )
13914
14071
  ] })
13915
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5", children: [
14072
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
13916
14073
  hasText && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "whitespace-pre-wrap break-words leading-snug", children: [
13917
14074
  message,
13918
14075
  isEdited && /* @__PURE__ */ jsxRuntime.jsx(
@@ -13970,6 +14127,7 @@ function MessageItemAttachmentBubble({
13970
14127
  isGroupedWithNext,
13971
14128
  showSenderLabel,
13972
14129
  senderName,
14130
+ senderId,
13973
14131
  formattedTime,
13974
14132
  status,
13975
14133
  isPending,
@@ -14018,6 +14176,7 @@ function MessageItemAttachmentBubble({
14018
14176
  isGroupedWithNext,
14019
14177
  showSenderLabel,
14020
14178
  senderName,
14179
+ senderId,
14021
14180
  formattedTime,
14022
14181
  status,
14023
14182
  isPending,
@@ -14077,6 +14236,7 @@ function MessageItemView(props) {
14077
14236
  isGroup,
14078
14237
  isHighlighted,
14079
14238
  senderName,
14239
+ senderId,
14080
14240
  senderImage,
14081
14241
  showSenderLabel,
14082
14242
  senderAvatarImage,
@@ -14253,6 +14413,7 @@ function MessageItemView(props) {
14253
14413
  isGroupedWithNext,
14254
14414
  showSenderLabel,
14255
14415
  senderName,
14416
+ senderId,
14256
14417
  formattedTime,
14257
14418
  status,
14258
14419
  isPending,
@@ -14294,6 +14455,7 @@ function MessageItemView(props) {
14294
14455
  isForwarded,
14295
14456
  showSenderLabel,
14296
14457
  senderName,
14458
+ senderId,
14297
14459
  replyTo,
14298
14460
  loggedUserDetails,
14299
14461
  allUsers,
@@ -14484,6 +14646,28 @@ function MessageSelectionBar({
14484
14646
 
14485
14647
  // src/chat/active-channel-messages/utils.ts
14486
14648
  var getMessageSenderId2 = (msg) => msg ? String(msg.senderId || msg.sender?._id || "") : "";
14649
+ var isLikelyObjectId = (value) => /^[a-f\d]{24}$/i.test(value);
14650
+ function resolveGroupSenderDisplay(message, allUsers = [], participants = []) {
14651
+ const senderId = getMessageSenderId2(message);
14652
+ if (senderId) {
14653
+ const fromUsers = allUsers.find((user) => String(user._id) === senderId);
14654
+ if (fromUsers?.name?.trim()) {
14655
+ return { name: fromUsers.name.trim(), image: fromUsers.image };
14656
+ }
14657
+ const fromParticipants = participants.find((participant) => {
14658
+ const id = typeof participant === "string" ? participant : participant?._id;
14659
+ return String(id) === senderId;
14660
+ });
14661
+ if (fromParticipants && typeof fromParticipants === "object" && fromParticipants.name?.trim()) {
14662
+ return { name: fromParticipants.name.trim(), image: fromParticipants.image };
14663
+ }
14664
+ }
14665
+ const sender = message.sender;
14666
+ if (typeof sender === "string" && sender.trim() && !isLikelyObjectId(sender.trim())) {
14667
+ return { name: sender.trim(), image: message.senderImage };
14668
+ }
14669
+ return { name: "User", image: void 0 };
14670
+ }
14487
14671
  var isSameMessageSide = (a, b, isGroupChat) => {
14488
14672
  if (!!a.isOwnMessage !== !!b.isOwnMessage) return false;
14489
14673
  if (a.isOwnMessage) return true;
@@ -14497,8 +14681,8 @@ function canDeleteSelectionForEveryone(selectedKeys, messages, isGroup) {
14497
14681
  const parsed = [...selectedKeys].map((key) => parseSelectionKey(key));
14498
14682
  const messageIds = new Set(parsed.map((entry) => entry.messageId));
14499
14683
  if (messageIds.size !== 1) return false;
14500
- const messageId = [...messageIds][0];
14501
- const message = messages.find((entry) => String(entry._id || entry.id) === messageId);
14684
+ const messageId2 = [...messageIds][0];
14685
+ const message = messages.find((entry) => String(entry._id || entry.id) === messageId2);
14502
14686
  if (!message?.isOwnMessage) return false;
14503
14687
  if (!isWithinMessageEditWindow(message.timestamp, isGroup)) return false;
14504
14688
  const hasAttachmentKey = parsed.some((entry) => entry.attachmentId);
@@ -14512,6 +14696,9 @@ function canDeleteSelectionForEveryone(selectedKeys, messages, isGroup) {
14512
14696
  });
14513
14697
  }
14514
14698
 
14699
+ // src/chat/active-channel-messages/ActiveChannelMessagesView.tsx
14700
+ init_useStore();
14701
+
14515
14702
  // src/chat/active-channel-messages/useActiveChannelMessages.ts
14516
14703
  init_useStore();
14517
14704
  init_store_helpers();
@@ -14527,6 +14714,7 @@ function mapApiMessage(m, activeChannel, conversationId, loggedUserId, activeCon
14527
14714
  content: m.content,
14528
14715
  sender: m.sender?.name || "User",
14529
14716
  senderId: String(m.sender?._id || m.sender || ""),
14717
+ senderImage: m.sender?.image,
14530
14718
  receiver: activeChannel?.id,
14531
14719
  timestamp: m.createdAt,
14532
14720
  isOwnMessage: isOwn,
@@ -14554,7 +14742,101 @@ function mapApiMessage(m, activeChannel, conversationId, loggedUserId, activeCon
14554
14742
  };
14555
14743
  }
14556
14744
 
14745
+ // src/chat/active-channel-messages/jump-to-date.ts
14746
+ function startOfLocalDay(date) {
14747
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();
14748
+ }
14749
+ function toDateInputValue(date) {
14750
+ const y = date.getFullYear();
14751
+ const m = String(date.getMonth() + 1).padStart(2, "0");
14752
+ const d = String(date.getDate()).padStart(2, "0");
14753
+ return `${y}-${m}-${d}`;
14754
+ }
14755
+ function clampJumpDate(picked, minDay, maxDay) {
14756
+ if (!Number.isFinite(minDay) || !Number.isFinite(maxDay) || minDay > maxDay) return null;
14757
+ const at = startOfLocalDay(picked);
14758
+ const clamped = Math.min(Math.max(at, minDay), maxDay);
14759
+ return new Date(clamped);
14760
+ }
14761
+ function resolveJumpDateBounds(createdAt, oldestMessageTimestamp, now = /* @__PURE__ */ new Date()) {
14762
+ const today = startOfLocalDay(now);
14763
+ const createdDay = createdAt ? startOfLocalDay(new Date(createdAt)) : null;
14764
+ const oldestDay = oldestMessageTimestamp ? startOfLocalDay(new Date(oldestMessageTimestamp)) : null;
14765
+ let minDay = today;
14766
+ if (createdDay != null && oldestDay != null) {
14767
+ minDay = Math.max(createdDay, oldestDay);
14768
+ } else if (oldestDay != null) {
14769
+ minDay = oldestDay;
14770
+ } else if (createdDay != null) {
14771
+ minDay = createdDay;
14772
+ }
14773
+ return { minDay: Math.min(minDay, today), maxDay: today };
14774
+ }
14775
+ function resolveJumpPreset(preset, now = /* @__PURE__ */ new Date()) {
14776
+ const day = new Date(now.getFullYear(), now.getMonth(), now.getDate());
14777
+ if (preset === "today") return day.getTime();
14778
+ if (preset === "yesterday") {
14779
+ day.setDate(day.getDate() - 1);
14780
+ return day.getTime();
14781
+ }
14782
+ if (preset === "lastWeek") {
14783
+ day.setDate(day.getDate() - 7);
14784
+ return day.getTime();
14785
+ }
14786
+ day.setMonth(day.getMonth() - 1);
14787
+ return day.getTime();
14788
+ }
14789
+ function messageId(m) {
14790
+ return String(m._id || m.id);
14791
+ }
14792
+ function findNearestMessageByDay(messages, targetDay) {
14793
+ let best = messages[0];
14794
+ let bestDist = Infinity;
14795
+ let bestDay = startOfLocalDay(new Date(best.timestamp));
14796
+ for (const m of messages) {
14797
+ const day = startOfLocalDay(new Date(m.timestamp));
14798
+ const dist = Math.abs(day - targetDay);
14799
+ if (dist < bestDist || dist === bestDist && day < bestDay) {
14800
+ best = m;
14801
+ bestDist = dist;
14802
+ bestDay = day;
14803
+ }
14804
+ }
14805
+ return best;
14806
+ }
14807
+ function resolveJumpStep(messages, pending, hasMore) {
14808
+ if (messages.length === 0) {
14809
+ return hasMore ? { action: "loadOlder" } : { action: "done" };
14810
+ }
14811
+ if (pending.kind === "beginning") {
14812
+ if (hasMore) return { action: "loadOlder" };
14813
+ return { action: "scroll", messageId: messageId(messages[0]) };
14814
+ }
14815
+ const oldestDay = startOfLocalDay(new Date(messages[0].timestamp));
14816
+ if (hasMore && oldestDay > pending.at) {
14817
+ return { action: "loadOlder" };
14818
+ }
14819
+ const onDay = messages.find(
14820
+ (m) => startOfLocalDay(new Date(m.timestamp)) === pending.at
14821
+ );
14822
+ if (onDay) {
14823
+ return { action: "scroll", messageId: messageId(onDay) };
14824
+ }
14825
+ const nearest = findNearestMessageByDay(messages, pending.at);
14826
+ return { action: "scroll", messageId: messageId(nearest) };
14827
+ }
14828
+ function smoothScrollToMessage(container, messageEl) {
14829
+ const containerRect = container.getBoundingClientRect();
14830
+ const messageRect = messageEl.getBoundingClientRect();
14831
+ const delta = messageRect.top - containerRect.top - Math.min(120, container.clientHeight * 0.25);
14832
+ container.scrollTo({
14833
+ top: Math.max(0, container.scrollTop + delta),
14834
+ behavior: "smooth"
14835
+ });
14836
+ }
14837
+
14557
14838
  // src/chat/active-channel-messages/useActiveChannelMessages.ts
14839
+ var MAX_JUMP_OLDER_PAGES = 40;
14558
14840
  function useActiveChannelMessages({
14559
14841
  activeChannel,
14560
14842
  loggedUserId,
@@ -14577,6 +14859,11 @@ function useActiveChannelMessages({
14577
14859
  const previousMessageCountRef = React2.useRef(0);
14578
14860
  const previousLastMessageIdRef = React2.useRef(null);
14579
14861
  const [enteringMessageIds, setEnteringMessageIds] = React2.useState(/* @__PURE__ */ new Set());
14862
+ const [showScrollToBottom, setShowScrollToBottom] = React2.useState(false);
14863
+ const stickToBottomRef = React2.useRef(true);
14864
+ const pendingJumpRef = React2.useRef(null);
14865
+ const jumpPagesRef = React2.useRef(0);
14866
+ const [jumpNonce, setJumpNonce] = React2.useState(0);
14580
14867
  const { fetchMessages: fetchMessages2, messagesMetadata, deletedForMeIds, searchedMessageId, isSearchActive, setSearchActive, setSearchedMessageId, fetchSearchMessageContext } = exports.useChatStore();
14581
14868
  const loggedUserImage = exports.useChatStore((s) => s.loggedUserDetails?.image);
14582
14869
  const conversations = exports.useChatStore((s) => s.conversations);
@@ -14600,6 +14887,13 @@ function useActiveChannelMessages({
14600
14887
  })),
14601
14888
  [displayMessages, messagesById, loggedUserId]
14602
14889
  );
14890
+ const jumpDateBounds = React2.useMemo(
14891
+ () => resolveJumpDateBounds(
14892
+ conversationInfo?.createdAt,
14893
+ displayMessages[0]?.timestamp
14894
+ ),
14895
+ [conversationInfo?.createdAt, displayMessages]
14896
+ );
14603
14897
  React2.useEffect(() => {
14604
14898
  const messages = messagesWithResolvedReplies;
14605
14899
  const lastMessage = messages[messages.length - 1];
@@ -14637,6 +14931,10 @@ function useActiveChannelMessages({
14637
14931
  previousMessageCountRef.current = 0;
14638
14932
  previousLastMessageIdRef.current = null;
14639
14933
  setEnteringMessageIds(/* @__PURE__ */ new Set());
14934
+ pendingJumpRef.current = null;
14935
+ jumpPagesRef.current = 0;
14936
+ stickToBottomRef.current = true;
14937
+ setShowScrollToBottom(false);
14640
14938
  }, [conversationId, clearSelection]);
14641
14939
  const onSelectionModeChangeRef = React2.useRef(onSelectionModeChange);
14642
14940
  React2.useEffect(() => {
@@ -14646,10 +14944,10 @@ function useActiveChannelMessages({
14646
14944
  onSelectionModeChangeRef.current?.(selectionMode);
14647
14945
  }, [selectionMode]);
14648
14946
  const toggleSelection = React2.useCallback((message, attachmentId) => {
14649
- const messageId = String(message._id || message.id);
14650
- if (!messageId) return;
14947
+ const messageId2 = String(message._id || message.id);
14948
+ if (!messageId2) return;
14651
14949
  const useAttachmentSelection = messageUsesAttachmentSelection(message);
14652
- const key = useAttachmentSelection && attachmentId ? buildSelectionKey(messageId, attachmentId) : messageId;
14950
+ const key = useAttachmentSelection && attachmentId ? buildSelectionKey(messageId2, attachmentId) : messageId2;
14653
14951
  setSelectedKeys((prev) => {
14654
14952
  const next = new Set(prev);
14655
14953
  if (next.has(key)) next.delete(key);
@@ -14659,17 +14957,17 @@ function useActiveChannelMessages({
14659
14957
  });
14660
14958
  }, []);
14661
14959
  const enterSelectionMode = React2.useCallback((message, attachmentId) => {
14662
- const messageId = String(message._id || message.id);
14663
- if (!messageId) return;
14960
+ const messageId2 = String(message._id || message.id);
14961
+ if (!messageId2) return;
14664
14962
  setSelectionMode(true);
14665
14963
  const useAttachmentSelection = messageUsesAttachmentSelection(message);
14666
14964
  if (useAttachmentSelection) {
14667
14965
  if (attachmentId) {
14668
- setSelectedKeys((prev) => new Set(prev).add(buildSelectionKey(messageId, attachmentId)));
14966
+ setSelectedKeys((prev) => new Set(prev).add(buildSelectionKey(messageId2, attachmentId)));
14669
14967
  }
14670
14968
  return;
14671
14969
  }
14672
- setSelectedKeys((prev) => new Set(prev).add(messageId));
14970
+ setSelectedKeys((prev) => new Set(prev).add(messageId2));
14673
14971
  }, []);
14674
14972
  const selectedForwardItems = resolveForwardItems(selectedKeys, displayMessages);
14675
14973
  const canDeleteForEveryone = React2.useMemo(
@@ -14688,14 +14986,14 @@ function useActiveChannelMessages({
14688
14986
  }
14689
14987
  const isGroupChat = !!activeChannel?.isGroup;
14690
14988
  selectedKeys.forEach((key) => {
14691
- const { messageId, attachmentId } = parseSelectionKey(key);
14692
- if (!messageId || messageId.startsWith("temp-")) return;
14693
- const message = displayMessages.find((entry) => String(entry._id || entry.id) === messageId);
14989
+ const { messageId: messageId2, attachmentId } = parseSelectionKey(key);
14990
+ if (!messageId2 || messageId2.startsWith("temp-")) return;
14991
+ const message = displayMessages.find((entry) => String(entry._id || entry.id) === messageId2);
14694
14992
  if (isGroupChat) {
14695
14993
  const convId = String(message?.conversationId || conversationId || "");
14696
14994
  if (!convId) return;
14697
14995
  emitGroupDelete({
14698
- messageId,
14996
+ messageId: messageId2,
14699
14997
  sender: loggedUserDetails._id,
14700
14998
  deleteType,
14701
14999
  conversationId: convId,
@@ -14705,7 +15003,7 @@ function useActiveChannelMessages({
14705
15003
  const receiver = message?.receiver || activeChannel?.id;
14706
15004
  if (!receiver) return;
14707
15005
  emitDmDelete({
14708
- messageId,
15006
+ messageId: messageId2,
14709
15007
  sender: loggedUserDetails._id,
14710
15008
  receiver: String(receiver),
14711
15009
  deleteType,
@@ -14744,43 +15042,138 @@ function useActiveChannelMessages({
14744
15042
  fetchMessages2(conversationId);
14745
15043
  }
14746
15044
  };
14747
- const handleReplyTargetClick = async (messageId) => {
14748
- if (!messageId) return;
14749
- if (messagesById.has(messageId)) {
14750
- setSearchedMessageId(messageId);
15045
+ const handleReplyTargetClick = async (messageId2) => {
15046
+ if (!messageId2) return;
15047
+ stickToBottomRef.current = false;
15048
+ if (messagesById.has(messageId2)) {
15049
+ setSearchedMessageId(messageId2);
14751
15050
  return;
14752
15051
  }
14753
- await fetchSearchMessageContext(messageId, { searchMode: false });
15052
+ await fetchSearchMessageContext(messageId2, { searchMode: false });
14754
15053
  };
15054
+ const handleJumpTo = React2.useCallback((preset, specificDate) => {
15055
+ stickToBottomRef.current = false;
15056
+ if (preset === "beginning") {
15057
+ pendingJumpRef.current = { kind: "beginning" };
15058
+ } else if (preset === "specific") {
15059
+ if (!specificDate) return;
15060
+ const clamped = clampJumpDate(
15061
+ specificDate,
15062
+ jumpDateBounds.minDay,
15063
+ jumpDateBounds.maxDay
15064
+ );
15065
+ if (!clamped) return;
15066
+ pendingJumpRef.current = { kind: "date", at: startOfLocalDay(clamped) };
15067
+ } else {
15068
+ const raw = resolveJumpPreset(preset);
15069
+ const at = Math.min(Math.max(raw, jumpDateBounds.minDay), jumpDateBounds.maxDay);
15070
+ pendingJumpRef.current = { kind: "date", at };
15071
+ }
15072
+ jumpPagesRef.current = 0;
15073
+ setJumpNonce((n) => n + 1);
15074
+ }, [jumpDateBounds.minDay, jumpDateBounds.maxDay]);
15075
+ React2.useEffect(() => {
15076
+ const pending = pendingJumpRef.current;
15077
+ if (!pending || isLoading) return;
15078
+ const step = resolveJumpStep(
15079
+ messagesWithResolvedReplies,
15080
+ pending,
15081
+ !!currentMeta?.hasMore
15082
+ );
15083
+ if (step.action === "loadOlder") {
15084
+ if (!conversationId || !currentMeta?.nextCursor || jumpPagesRef.current >= MAX_JUMP_OLDER_PAGES) {
15085
+ pendingJumpRef.current = null;
15086
+ const fallback = messagesWithResolvedReplies[0];
15087
+ if (fallback) setSearchedMessageId(String(fallback._id || fallback.id));
15088
+ return;
15089
+ }
15090
+ jumpPagesRef.current += 1;
15091
+ const prevScrollHeight = scrollContainerRef.current?.scrollHeight ?? 0;
15092
+ fetchMessages2(conversationId, DEFAULT_MESSAGES_LIMIT, currentMeta.nextCursor).then(() => {
15093
+ if (scrollContainerRef.current && prevScrollHeight) {
15094
+ scrollContainerRef.current.scrollTop = scrollContainerRef.current.scrollHeight - prevScrollHeight;
15095
+ }
15096
+ });
15097
+ return;
15098
+ }
15099
+ pendingJumpRef.current = null;
15100
+ if (step.action === "scroll") {
15101
+ setSearchedMessageId(null);
15102
+ requestAnimationFrame(() => setSearchedMessageId(step.messageId));
15103
+ }
15104
+ }, [
15105
+ jumpNonce,
15106
+ isLoading,
15107
+ messagesWithResolvedReplies,
15108
+ currentMeta?.hasMore,
15109
+ currentMeta?.nextCursor,
15110
+ conversationId,
15111
+ fetchMessages2,
15112
+ setSearchedMessageId
15113
+ ]);
15114
+ const updateScrollToBottomVisibility = React2.useCallback((el) => {
15115
+ const distanceFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight;
15116
+ const nearBottom = distanceFromBottom <= 96;
15117
+ stickToBottomRef.current = nearBottom;
15118
+ setShowScrollToBottom(!nearBottom);
15119
+ }, []);
15120
+ const handleScrollToBottom = React2.useCallback(() => {
15121
+ stickToBottomRef.current = true;
15122
+ if (isSearchActive) {
15123
+ setSearchActive(false);
15124
+ setSearchedMessageId(null);
15125
+ if (conversationId) fetchMessages2(conversationId);
15126
+ setShowScrollToBottom(false);
15127
+ return;
15128
+ }
15129
+ bottomRef.current?.scrollIntoView({ behavior: "smooth" });
15130
+ setShowScrollToBottom(false);
15131
+ }, [isSearchActive, conversationId, setSearchActive, setSearchedMessageId, fetchMessages2]);
14755
15132
  const handleScroll = (e) => {
14756
15133
  const target = e.currentTarget;
15134
+ updateScrollToBottomVisibility(target);
15135
+ if (pendingJumpRef.current) return;
14757
15136
  if (target.scrollTop === 0 && currentMeta?.hasMore && !isLoading && conversationId && currentMeta.nextCursor) {
14758
15137
  const prevScrollHeight = target.scrollHeight;
14759
15138
  fetchMessages2(conversationId, DEFAULT_MESSAGES_LIMIT, currentMeta.nextCursor).then(() => {
14760
15139
  if (scrollContainerRef.current) {
14761
15140
  const newScrollHeight = scrollContainerRef.current.scrollHeight;
14762
15141
  scrollContainerRef.current.scrollTop = newScrollHeight - prevScrollHeight;
15142
+ updateScrollToBottomVisibility(scrollContainerRef.current);
14763
15143
  }
14764
15144
  });
14765
15145
  }
14766
15146
  };
14767
15147
  React2.useLayoutEffect(() => {
14768
- if (!isInitialLoading && currentMeta?.isFirstPage && !searchedMessageId) {
15148
+ if (!isInitialLoading && stickToBottomRef.current && !pendingJumpRef.current) {
14769
15149
  bottomRef.current?.scrollIntoView({ behavior: "smooth" });
14770
15150
  }
14771
- }, [messagesWithResolvedReplies.length, isInitialLoading, currentMeta?.isFirstPage, searchedMessageId]);
15151
+ }, [messagesWithResolvedReplies.length, isInitialLoading]);
14772
15152
  React2.useEffect(() => {
14773
15153
  if (searchedMessageId && !isLoading) {
15154
+ stickToBottomRef.current = false;
15155
+ const container = scrollContainerRef.current;
14774
15156
  const element = document.getElementById(`message-${searchedMessageId}`);
14775
- if (element) {
14776
- element.scrollIntoView({ behavior: "smooth", block: "center" });
15157
+ if (container && element) {
15158
+ requestAnimationFrame(() => {
15159
+ requestAnimationFrame(() => {
15160
+ smoothScrollToMessage(container, element);
15161
+ updateScrollToBottomVisibility(container);
15162
+ });
15163
+ });
14777
15164
  }
14778
15165
  if (!isSearchActive) {
14779
15166
  const timer = window.setTimeout(() => setSearchedMessageId(null), 2500);
14780
15167
  return () => window.clearTimeout(timer);
14781
15168
  }
14782
15169
  }
14783
- }, [searchedMessageId, isLoading, messagesWithResolvedReplies.length, isSearchActive, setSearchedMessageId]);
15170
+ }, [
15171
+ searchedMessageId,
15172
+ isLoading,
15173
+ isSearchActive,
15174
+ setSearchedMessageId,
15175
+ updateScrollToBottomVisibility
15176
+ ]);
14784
15177
  return {
14785
15178
  activeChannel,
14786
15179
  conversationId,
@@ -14806,11 +15199,297 @@ function useActiveChannelMessages({
14806
15199
  canDeleteForEveryone,
14807
15200
  handleResetToNormal,
14808
15201
  handleReplyTargetClick,
15202
+ handleJumpTo,
15203
+ jumpDateBounds,
15204
+ showScrollToBottom,
15205
+ handleScrollToBottom,
14809
15206
  handleScroll
14810
15207
  };
14811
15208
  }
15209
+ function Calendar({
15210
+ className,
15211
+ classNames,
15212
+ showOutsideDays = true,
15213
+ captionLayout = "label",
15214
+ buttonVariant = "ghost",
15215
+ formatters,
15216
+ components,
15217
+ ...props
15218
+ }) {
15219
+ const defaultClassNames = reactDayPicker.getDefaultClassNames();
15220
+ return /* @__PURE__ */ jsxRuntime.jsx(
15221
+ reactDayPicker.DayPicker,
15222
+ {
15223
+ showOutsideDays,
15224
+ className: cn(
15225
+ "group/calendar bg-background p-3 [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
15226
+ String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
15227
+ String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
15228
+ className
15229
+ ),
15230
+ captionLayout,
15231
+ formatters: {
15232
+ formatMonthDropdown: (date) => date.toLocaleString("default", { month: "short" }),
15233
+ ...formatters
15234
+ },
15235
+ classNames: {
15236
+ root: cn("w-fit", defaultClassNames.root),
15237
+ months: cn(
15238
+ "relative flex flex-col gap-4 md:flex-row",
15239
+ defaultClassNames.months
15240
+ ),
15241
+ month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
15242
+ nav: cn(
15243
+ "absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1",
15244
+ defaultClassNames.nav
15245
+ ),
15246
+ button_previous: cn(
15247
+ buttonVariants({ variant: buttonVariant }),
15248
+ "size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
15249
+ defaultClassNames.button_previous
15250
+ ),
15251
+ button_next: cn(
15252
+ buttonVariants({ variant: buttonVariant }),
15253
+ "size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
15254
+ defaultClassNames.button_next
15255
+ ),
15256
+ month_caption: cn(
15257
+ "flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)",
15258
+ defaultClassNames.month_caption
15259
+ ),
15260
+ dropdowns: cn(
15261
+ "flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium",
15262
+ defaultClassNames.dropdowns
15263
+ ),
15264
+ dropdown_root: cn(
15265
+ "relative rounded-md border border-input shadow-xs has-focus:border-ring has-focus:ring-[3px] has-focus:ring-ring/50",
15266
+ defaultClassNames.dropdown_root
15267
+ ),
15268
+ dropdown: cn(
15269
+ "absolute inset-0 bg-popover opacity-0",
15270
+ defaultClassNames.dropdown
15271
+ ),
15272
+ caption_label: cn(
15273
+ "font-medium select-none",
15274
+ captionLayout === "label" ? "text-sm" : "flex h-8 items-center gap-1 rounded-md pr-1 pl-2 text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground",
15275
+ defaultClassNames.caption_label
15276
+ ),
15277
+ month_grid: cn("w-full border-collapse", defaultClassNames.month_grid),
15278
+ weekdays: cn("flex", defaultClassNames.weekdays),
15279
+ weekday: cn(
15280
+ "flex-1 rounded-md text-[0.8rem] font-normal text-muted-foreground select-none",
15281
+ defaultClassNames.weekday
15282
+ ),
15283
+ week: cn("mt-2 flex w-full", defaultClassNames.week),
15284
+ week_number_header: cn(
15285
+ "w-(--cell-size) select-none",
15286
+ defaultClassNames.week_number_header
15287
+ ),
15288
+ week_number: cn(
15289
+ "text-[0.8rem] text-muted-foreground select-none",
15290
+ defaultClassNames.week_number
15291
+ ),
15292
+ day: cn(
15293
+ "group/day relative aspect-square h-full w-full p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-r-md",
15294
+ props.showWeekNumber ? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-md" : "[&:first-child[data-selected=true]_button]:rounded-l-md",
15295
+ defaultClassNames.day
15296
+ ),
15297
+ range_start: cn(
15298
+ "rounded-l-md bg-accent",
15299
+ defaultClassNames.range_start
15300
+ ),
15301
+ range_middle: cn("rounded-none", defaultClassNames.range_middle),
15302
+ range_end: cn("rounded-r-md bg-accent", defaultClassNames.range_end),
15303
+ today: cn(
15304
+ "rounded-md bg-accent text-accent-foreground data-[selected=true]:rounded-none",
15305
+ defaultClassNames.today
15306
+ ),
15307
+ outside: cn(
15308
+ "text-muted-foreground aria-selected:text-muted-foreground",
15309
+ defaultClassNames.outside
15310
+ ),
15311
+ disabled: cn(
15312
+ "text-muted-foreground opacity-50",
15313
+ defaultClassNames.disabled
15314
+ ),
15315
+ hidden: cn("invisible", defaultClassNames.hidden),
15316
+ ...classNames
15317
+ },
15318
+ components: {
15319
+ Root: ({ className: className2, rootRef, ...props2 }) => {
15320
+ return /* @__PURE__ */ jsxRuntime.jsx(
15321
+ "div",
15322
+ {
15323
+ "data-slot": "calendar",
15324
+ ref: rootRef,
15325
+ className: cn(className2),
15326
+ ...props2
15327
+ }
15328
+ );
15329
+ },
15330
+ Chevron: ({ className: className2, orientation, ...props2 }) => {
15331
+ if (orientation === "left") {
15332
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeftIcon, { className: cn("size-4", className2), ...props2 });
15333
+ }
15334
+ if (orientation === "right") {
15335
+ return /* @__PURE__ */ jsxRuntime.jsx(
15336
+ lucideReact.ChevronRightIcon,
15337
+ {
15338
+ className: cn("size-4", className2),
15339
+ ...props2
15340
+ }
15341
+ );
15342
+ }
15343
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDownIcon, { className: cn("size-4", className2), ...props2 });
15344
+ },
15345
+ DayButton: CalendarDayButton,
15346
+ WeekNumber: ({ children, ...props2 }) => {
15347
+ return /* @__PURE__ */ jsxRuntime.jsx("td", { ...props2, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex size-(--cell-size) items-center justify-center text-center", children }) });
15348
+ },
15349
+ ...components
15350
+ },
15351
+ ...props
15352
+ }
15353
+ );
15354
+ }
15355
+ function CalendarDayButton({
15356
+ className,
15357
+ day,
15358
+ modifiers,
15359
+ ...props
15360
+ }) {
15361
+ const defaultClassNames = reactDayPicker.getDefaultClassNames();
15362
+ const ref = React2__namespace.useRef(null);
15363
+ React2__namespace.useEffect(() => {
15364
+ if (modifiers.focused) ref.current?.focus();
15365
+ }, [modifiers.focused]);
15366
+ return /* @__PURE__ */ jsxRuntime.jsx(
15367
+ Button,
15368
+ {
15369
+ ref,
15370
+ variant: "ghost",
15371
+ size: "icon",
15372
+ "data-day": day.date.toLocaleDateString(),
15373
+ "data-selected-single": modifiers.selected && !modifiers.range_start && !modifiers.range_end && !modifiers.range_middle,
15374
+ "data-range-start": modifiers.range_start,
15375
+ "data-range-end": modifiers.range_end,
15376
+ "data-range-middle": modifiers.range_middle,
15377
+ className: cn(
15378
+ "flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-[3px] group-data-[focused=true]/day:ring-ring/50 data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground data-[range-middle=true]:rounded-none data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground dark:hover:text-accent-foreground [&>span]:text-xs [&>span]:opacity-70",
15379
+ defaultClassNames.day,
15380
+ className
15381
+ ),
15382
+ ...props
15383
+ }
15384
+ );
15385
+ }
15386
+ var PRESETS = [
15387
+ { preset: "today", label: "Today" },
15388
+ { preset: "yesterday", label: "Yesterday" },
15389
+ { preset: "lastWeek", label: "Last week" },
15390
+ { preset: "lastMonth", label: "Last month" },
15391
+ { preset: "beginning", label: "The very beginning" }
15392
+ ];
15393
+ function ChatDateJumpMenu({ label, minDay, maxDay, onJump }) {
15394
+ const { scopeClassName } = useChatTheme();
15395
+ const [open, setOpen] = React2.useState(false);
15396
+ const [showCalendar, setShowCalendar] = React2.useState(false);
15397
+ const [calendarMonth, setCalendarMonth] = React2.useState(() => new Date(maxDay));
15398
+ const minDate = new Date(minDay);
15399
+ const maxDate = new Date(maxDay);
15400
+ React2.useEffect(() => {
15401
+ if (showCalendar) setCalendarMonth(new Date(maxDay));
15402
+ }, [showCalendar, maxDay]);
15403
+ const queueJump = (preset, specificDate) => {
15404
+ window.setTimeout(() => onJump(preset, specificDate), 0);
15405
+ };
15406
+ const handleOpenChange = (next) => {
15407
+ setOpen(next);
15408
+ if (!next) setShowCalendar(false);
15409
+ };
15410
+ const handlePreset = (preset) => {
15411
+ setOpen(false);
15412
+ setShowCalendar(false);
15413
+ queueJump(preset);
15414
+ };
15415
+ const handleDateSelect = (date) => {
15416
+ if (!date) return;
15417
+ const clamped = clampJumpDate(date, minDay, maxDay);
15418
+ if (!clamped) return;
15419
+ setOpen(false);
15420
+ setShowCalendar(false);
15421
+ queueJump("specific", clamped);
15422
+ };
15423
+ return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: handleOpenChange, children: [
15424
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
15425
+ "button",
15426
+ {
15427
+ type: "button",
15428
+ className: "chat-date-divider-pill chat-date-divider-pill--interactive",
15429
+ "aria-label": `Jump to date, currently ${label}`,
15430
+ children: [
15431
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: label }),
15432
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "chat-date-divider-chevron", "aria-hidden": true })
15433
+ ]
15434
+ }
15435
+ ) }),
15436
+ /* @__PURE__ */ jsxRuntime.jsx(
15437
+ PopoverContent,
15438
+ {
15439
+ align: "center",
15440
+ sideOffset: 8,
15441
+ className: cn(
15442
+ scopeClassName,
15443
+ chatPopoverContentClass,
15444
+ "w-auto overflow-hidden rounded-2xl p-0",
15445
+ showCalendar ? "min-w-[300px]" : "min-w-[220px]"
15446
+ ),
15447
+ onCloseAutoFocus: (event) => event.preventDefault(),
15448
+ children: showCalendar ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2", children: /* @__PURE__ */ jsxRuntime.jsx(
15449
+ Calendar,
15450
+ {
15451
+ mode: "single",
15452
+ month: calendarMonth,
15453
+ onMonthChange: setCalendarMonth,
15454
+ startMonth: minDate,
15455
+ endMonth: maxDate,
15456
+ showOutsideDays: false,
15457
+ disabled: { before: minDate, after: maxDate },
15458
+ onSelect: handleDateSelect,
15459
+ className: "chat-jump-calendar rounded-xl bg-transparent p-1 [--cell-size:2.125rem]"
15460
+ }
15461
+ ) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
15462
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 pt-3 pb-2", children: [
15463
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: chatOptionsMenuLabelClass, children: "Jump to\u2026" }),
15464
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 flex flex-col", children: PRESETS.map(({ preset, label: itemLabel }) => /* @__PURE__ */ jsxRuntime.jsx(
15465
+ "button",
15466
+ {
15467
+ type: "button",
15468
+ className: cn(chatOptionsMenuItemClass, "w-full border-0 bg-transparent text-left"),
15469
+ onClick: () => handlePreset(preset),
15470
+ children: itemLabel
15471
+ },
15472
+ preset
15473
+ )) })
15474
+ ] }),
15475
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(chatOptionsMenuSeparatorClass, "mx-3") }),
15476
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-1 pb-2", children: /* @__PURE__ */ jsxRuntime.jsx(
15477
+ "button",
15478
+ {
15479
+ type: "button",
15480
+ className: cn(chatOptionsMenuItemClass, "w-full border-0 bg-transparent text-left"),
15481
+ onClick: () => setShowCalendar(true),
15482
+ children: "Jump to a specific date"
15483
+ }
15484
+ ) })
15485
+ ] })
15486
+ }
15487
+ )
15488
+ ] });
15489
+ }
14812
15490
  var ActiveChannelMessagesView = (props) => {
14813
15491
  const { formatDateDivider } = useChatLocale();
15492
+ const allUsers = exports.useChatStore((s) => s.allUsers);
14814
15493
  const {
14815
15494
  activeChannel,
14816
15495
  conversationId,
@@ -14836,6 +15515,10 @@ var ActiveChannelMessagesView = (props) => {
14836
15515
  canDeleteForEveryone,
14837
15516
  handleResetToNormal,
14838
15517
  handleReplyTargetClick,
15518
+ handleJumpTo,
15519
+ jumpDateBounds,
15520
+ showScrollToBottom,
15521
+ handleScrollToBottom,
14839
15522
  handleScroll
14840
15523
  } = useActiveChannelMessages(props);
14841
15524
  const { onReply, onForward } = props;
@@ -14848,7 +15531,7 @@ var ActiveChannelMessagesView = (props) => {
14848
15531
  ] })
14849
15532
  ] });
14850
15533
  }
14851
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "chat-message-canvas relative flex h-full min-h-0 flex-col overflow-hidden", children: [
15534
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "chat-message-canvas relative flex h-full flex-col", children: [
14852
15535
  isSearchActive && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-6 left-1/2 -translate-x-1/2 z-40 animate-in slide-in-from-top-4 duration-500", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center overflow-hidden rounded-2xl border border-(--chat-border) bg-(--chat-surface) shadow-lg ring-4 ring-(--chat-surface)", children: [
14853
15536
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 bg-(--chat-theme) px-4 py-2.5", children: [
14854
15537
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "size-3.5 animate-pulse text-white" }),
@@ -14885,11 +15568,20 @@ var ActiveChannelMessagesView = (props) => {
14885
15568
  return groups;
14886
15569
  }, {})
14887
15570
  ).map(([date, messages]) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-2 flex flex-col", children: [
14888
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "chat-date-divider", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "chat-date-divider-pill", children: date }) }),
15571
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-1.5 z-20 mb-2 flex justify-center py-1", children: /* @__PURE__ */ jsxRuntime.jsx(
15572
+ ChatDateJumpMenu,
15573
+ {
15574
+ label: date,
15575
+ minDay: jumpDateBounds.minDay,
15576
+ maxDay: jumpDateBounds.maxDay,
15577
+ onJump: handleJumpTo
15578
+ }
15579
+ ) }),
14889
15580
  messages.map((m, msgIndex) => {
14890
- const senderLabel = typeof m.sender === "string" ? m.sender : "User";
14891
- const senderImage = !m.isOwnMessage ? activeChannel?.isGroup ? void 0 : activeChannel?.image : void 0;
14892
15581
  const isGroupChat = !!activeChannel?.isGroup;
15582
+ const participants = conversationInfo?.participants ?? [];
15583
+ const { name: senderLabel, image: groupSenderImage } = isGroupChat && !m.isOwnMessage ? resolveGroupSenderDisplay(m, allUsers, participants) : { name: typeof m.sender === "string" ? m.sender : "User", image: void 0 };
15584
+ const senderImage = !m.isOwnMessage ? isGroupChat ? groupSenderImage : activeChannel?.image : void 0;
14893
15585
  const prevMessage = msgIndex > 0 ? messages[msgIndex - 1] : null;
14894
15586
  const nextMessage = msgIndex < messages.length - 1 ? messages[msgIndex + 1] : null;
14895
15587
  const isGroupedWithPrev = !!prevMessage && isSameMessageSide(prevMessage, m, isGroupChat);
@@ -14936,6 +15628,7 @@ var ActiveChannelMessagesView = (props) => {
14936
15628
  conversationInfo,
14937
15629
  isHighlighted: String(m._id || m.id) === String(searchedMessageId),
14938
15630
  senderName: senderLabel,
15631
+ senderId: getMessageSenderId2(m),
14939
15632
  senderImage,
14940
15633
  showSenderName,
14941
15634
  showSenderLabel,
@@ -14976,6 +15669,16 @@ var ActiveChannelMessagesView = (props) => {
14976
15669
  onForward: handleBatchForward
14977
15670
  }
14978
15671
  ),
15672
+ showScrollToBottom && !selectionMode && /* @__PURE__ */ jsxRuntime.jsx(
15673
+ "button",
15674
+ {
15675
+ type: "button",
15676
+ onClick: handleScrollToBottom,
15677
+ className: "chat-scroll-to-bottom",
15678
+ "aria-label": "Scroll to latest messages",
15679
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "size-5", strokeWidth: 2.25 })
15680
+ }
15681
+ ),
14979
15682
  isInitialLoading && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pointer-events-none absolute bottom-6 left-1/2 z-30 flex -translate-x-1/2 animate-in items-center gap-3 rounded-2xl border border-(--chat-border) bg-(--chat-surface)/80 px-5 py-2.5 shadow-xl backdrop-blur-md duration-400 fade-in slide-in-from-bottom-2", children: [
14980
15683
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-3.5 w-3.5 animate-spin text-(--chat-theme)" }),
14981
15684
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-bold uppercase tracking-[0.15em] text-(--chat-muted)", children: "Loading messages..." })
@@ -15599,10 +16302,10 @@ function useChannelMessageBox({
15599
16302
  const composerDisabledReason = conversationId ? composerDisabledByConversation[conversationId] : void 0;
15600
16303
  const fileInputRef = React2.useRef(null);
15601
16304
  const attachmentsCountRef = React2.useRef(0);
15602
- React2__default.default.useEffect(() => {
16305
+ React2__namespace.default.useEffect(() => {
15603
16306
  attachmentsCountRef.current = state.attachments.length;
15604
16307
  }, [state.attachments.length]);
15605
- React2__default.default.useEffect(() => {
16308
+ React2__namespace.default.useEffect(() => {
15606
16309
  const draft = {
15607
16310
  messageInput: state.messageInput,
15608
16311
  attachments: state.attachments
@@ -15610,7 +16313,7 @@ function useChannelMessageBox({
15610
16313
  syncComposerRef(draft);
15611
16314
  updateConversationDraft(conversationIdRef.current, draft);
15612
16315
  }, [state.messageInput, state.attachments, syncComposerRef]);
15613
- React2__default.default.useEffect(() => {
16316
+ React2__namespace.default.useEffect(() => {
15614
16317
  if (typingTimeoutRef.current) {
15615
16318
  clearTimeout(typingTimeoutRef.current);
15616
16319
  typingTimeoutRef.current = null;
@@ -16161,10 +16864,10 @@ function useForwardModal({ isOpen, onClose, items, onForwardComplete }) {
16161
16864
  targetChannelRef.current = channel;
16162
16865
  const targetConversationIds = [String(channel.conversationId)];
16163
16866
  items.forEach((item) => {
16164
- const messageId = String(item.message._id || item.message.id || "");
16165
- if (!messageId) return;
16867
+ const messageId2 = String(item.message._id || item.message.id || "");
16868
+ if (!messageId2) return;
16166
16869
  const payload = {
16167
- messageId,
16870
+ messageId: messageId2,
16168
16871
  sender: String(loggedUserDetails._id),
16169
16872
  sourceConversationId: item.message.conversationId ? String(item.message.conversationId) : void 0,
16170
16873
  targetConversationIds,
@@ -16641,8 +17344,8 @@ var ChatMain = ({
16641
17344
  viewportHeight = "full",
16642
17345
  viewportClassName
16643
17346
  }) => {
16644
- const clientObj = React2__default.default.useMemo(() => ({ id: clientId }), [clientId]);
16645
- const uiConfigObj = React2__default.default.useMemo(
17347
+ const clientObj = React2__namespace.default.useMemo(() => ({ id: clientId }), [clientId]);
17348
+ const uiConfigObj = React2__namespace.default.useMemo(
16646
17349
  () => ({
16647
17350
  ...uiConfig || {},
16648
17351
  components: { ...uiConfig?.components, ...components },
@@ -17077,6 +17780,8 @@ var packageDefaultComponents = {
17077
17780
  // src/index.ts
17078
17781
  var index_default = ChatMain_default;
17079
17782
 
17783
+ exports.Calendar = Calendar;
17784
+ exports.CalendarDayButton = CalendarDayButton;
17080
17785
  exports.Channel = Channel;
17081
17786
  exports.ChannelHeader = ChannelHeaderView_default;
17082
17787
  exports.ChannelList = ChannelListView_default;
@@ -17085,6 +17790,7 @@ exports.Chat = Chat;
17085
17790
  exports.ChatAlertsProvider = ChatAlertsProvider;
17086
17791
  exports.ChatAvatar = ChatAvatar_default;
17087
17792
  exports.ChatCustomizationProvider = ChatCustomizationProvider;
17793
+ exports.ChatDateJumpMenu = ChatDateJumpMenu;
17088
17794
  exports.ChatLayout = ChatLayout_default;
17089
17795
  exports.ChatLocaleProvider = ChatLocaleProvider;
17090
17796
  exports.ChatMain = ChatMain_default;
@@ -17100,6 +17806,7 @@ exports.MessageInput = ChannelMessageBoxView_default;
17100
17806
  exports.MessageItem = MessageItemView;
17101
17807
  exports.MessageList = ActiveChannelMessagesView_default;
17102
17808
  exports.capitalizeFirst = capitalizeFirst;
17809
+ exports.clampJumpDate = clampJumpDate;
17103
17810
  exports.default = index_default;
17104
17811
  exports.defaultChatClassNames = defaultChatClassNames;
17105
17812
  exports.defaultChatComponents = defaultChatComponents;
@@ -17115,8 +17822,14 @@ exports.mergeChatLayoutConfig = mergeChatLayoutConfig;
17115
17822
  exports.packageDefaultComponents = packageDefaultComponents;
17116
17823
  exports.resolveApiUrl = resolveApiUrl;
17117
17824
  exports.resolveChatApiKey = resolveChatApiKey;
17825
+ exports.resolveJumpDateBounds = resolveJumpDateBounds;
17826
+ exports.resolveJumpPreset = resolveJumpPreset;
17827
+ exports.resolveJumpStep = resolveJumpStep;
17118
17828
  exports.resolveSocketUrl = resolveSocketUrl;
17119
17829
  exports.showNotification = showNotification;
17830
+ exports.smoothScrollToMessage = smoothScrollToMessage;
17831
+ exports.startOfLocalDay = startOfLocalDay;
17832
+ exports.toDateInputValue = toDateInputValue;
17120
17833
  exports.uniqueList = uniqueList;
17121
17834
  exports.useChatAlerts = useChatAlerts;
17122
17835
  exports.useChatContext = useChatContext;