@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.mjs CHANGED
@@ -2,15 +2,17 @@ import { io } from 'socket.io-client';
2
2
  import axios from 'axios';
3
3
  import { create } from 'zustand';
4
4
  import { persist } from 'zustand/middleware';
5
- import React2, { createContext, useMemo, useContext, useState, useCallback, useRef, useEffect, useLayoutEffect, useSyncExternalStore } from 'react';
5
+ import * as React2 from 'react';
6
+ import React2__default, { createContext, useMemo, useContext, useState, useCallback, useRef, useEffect, useLayoutEffect, useSyncExternalStore } from 'react';
6
7
  import { Tooltip as Tooltip$1, Slot, Avatar as Avatar$1, ScrollArea as ScrollArea$1, Popover as Popover$1, DropdownMenu as DropdownMenu$1, Dialog as Dialog$1, Switch as Switch$1, AlertDialog as AlertDialog$1 } from 'radix-ui';
7
8
  import { clsx } from 'clsx';
8
9
  import { twMerge } from 'tailwind-merge';
9
10
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
10
11
  import { flushSync } from 'react-dom';
11
- import { Sun, Moon, Search, X, Loader2, UserPlus, ChevronDown, ArrowLeft, Users, WifiOff, Wifi, Sparkles, MessageSquareText, ChevronRight, Pin, Star, Phone, Video, MoreVertical, Info, UserKey, ShieldUser, Paperclip, Clock, MessageSquareX, Trash2, LogOut, Ban, CheckCheck, Check, Camera, Save, Pencil, Mail, CornerUpLeft, CheckSquare, Smile, MessageCircleMore, History, Shield, Send, AlertCircle, ShieldCheck, UserMinus, MessageCircle, ChevronRightIcon, ExternalLink, Download, ChevronLeft, ZoomOut, ZoomIn, RotateCcw, Music, ArrowRight, MoreHorizontal, PinOff, StarOff, XIcon, ImageIcon, Film, Play, Pause, FileText, FileSpreadsheet, FileIcon, Eye, Captions } from 'lucide-react';
12
+ import { Sun, Moon, Search, X, Loader2, UserPlus, ChevronDown, ArrowLeft, Users, WifiOff, Wifi, Sparkles, MessageSquareText, ChevronRight, Pin, Star, Phone, Video, MoreVertical, Info, UserKey, ShieldUser, Paperclip, Clock, MessageSquareX, Trash2, LogOut, Ban, CheckCheck, Check, Camera, Save, Pencil, Mail, CornerUpLeft, CheckSquare, Smile, ChevronLeftIcon, ChevronRightIcon, ChevronDownIcon, MessageCircleMore, History, Shield, Send, AlertCircle, ShieldCheck, UserMinus, MessageCircle, ExternalLink, Download, ChevronLeft, ZoomOut, ZoomIn, RotateCcw, Music, ArrowRight, MoreHorizontal, PinOff, StarOff, XIcon, ImageIcon, Film, Play, Pause, FileText, FileSpreadsheet, FileIcon, Eye, Captions } from 'lucide-react';
12
13
  import { cva } from 'class-variance-authority';
13
14
  import EmojiPicker, { Theme } from 'emoji-picker-react';
15
+ import { getDefaultClassNames, DayPicker } from 'react-day-picker';
14
16
  import { toast } from 'react-hot-toast';
15
17
 
16
18
  var __defProp = Object.defineProperty;
@@ -560,7 +562,7 @@ var init_message_helpers = __esm({
560
562
  "src/store/helpers/message.helpers.ts"() {
561
563
  getMessageSenderId = (message) => String(message?.sender?._id || message?.sender?.id || message?.senderId || message?.fromUserId || message?.sender || "");
562
564
  extractMessageData = (payload) => {
563
- const messageId = payload.messageId || payload._id || payload.message?._id || payload.message?.id;
565
+ const messageId2 = payload.messageId || payload._id || payload.message?._id || payload.message?.id;
564
566
  const content = payload.content || payload.message?.content;
565
567
  const conversationId = payload.conversationId || payload.conversation_id || payload.message?.conversationId || payload.message?.conversation_id;
566
568
  const status = payload.status || payload.message?.status;
@@ -568,7 +570,7 @@ var init_message_helpers = __esm({
568
570
  const isStarred = payload.isStarred ?? payload.message?.isStarred;
569
571
  const attachmentId = payload.attachmentId || payload.unpinAttachmentId || null;
570
572
  const caption = payload.caption ?? payload.message?.caption ?? null;
571
- return { messageId, content, conversationId, status, isPinned, isStarred, attachmentId, caption };
573
+ return { messageId: messageId2, content, conversationId, status, isPinned, isStarred, attachmentId, caption };
572
574
  };
573
575
  statusRank = { sent: 0, delivered: 1, read: 2 };
574
576
  preferHigherStatus = (base, incoming) => {
@@ -799,15 +801,15 @@ var init_conversation_helpers = __esm({
799
801
  init_message_helpers();
800
802
  init_participant_helpers();
801
803
  init_unread_helpers();
802
- findConversationIdByMessageId = (messagesByConversation, messageId) => {
804
+ findConversationIdByMessageId = (messagesByConversation, messageId2) => {
803
805
  return Object.keys(messagesByConversation).find(
804
806
  (cid) => messagesByConversation[cid].some(
805
- (m) => String(m._id || m.id) === String(messageId)
807
+ (m) => String(m._id || m.id) === String(messageId2)
806
808
  )
807
809
  );
808
810
  };
809
- applyMessageStatusToStore = (state, messageId, status, conversationId) => {
810
- const normalizedMessageId = String(messageId);
811
+ applyMessageStatusToStore = (state, messageId2, status, conversationId) => {
812
+ const normalizedMessageId = String(messageId2);
811
813
  const resolvedConversationId = conversationId ? String(conversationId) : findConversationIdByMessageId(state.messagesByConversation, normalizedMessageId) || findConversationIdByLastMessageId(state.conversations, normalizedMessageId) || null;
812
814
  const nextConversations = state.conversations.map((conversation) => {
813
815
  const lastMessageId = String(
@@ -850,6 +852,9 @@ var init_conversation_helpers = __esm({
850
852
  const mergedParticipants = conversation.participants !== void 0 ? mergeConversationParticipants(existing?.participants, conversation.participants) : existing?.participants ?? conversation.participants;
851
853
  const isGroup = isGroupConversation(conversation) || isGroupConversation(existing);
852
854
  const resolvedGroupImage = resolveGroupImage(conversation) || resolveGroupImage(existing);
855
+ const incomingGroupName = typeof conversation.groupName === "string" && conversation.groupName.trim() || typeof conversation.name === "string" && conversation.name.trim() || "";
856
+ const existingGroupName = typeof existing?.groupName === "string" && existing.groupName.trim() || typeof existing?.name === "string" && existing.name.trim() || "";
857
+ const resolvedGroupName = incomingGroupName || existingGroupName || void 0;
853
858
  return {
854
859
  ...existing,
855
860
  ...conversation,
@@ -857,7 +862,10 @@ var init_conversation_helpers = __esm({
857
862
  isGroup,
858
863
  isBlocked: resolvedBlocked,
859
864
  lastMessage: mergeLastMessage(existing?.lastMessage, conversation.lastMessage),
860
- ...isGroup && resolvedGroupImage ? { image: resolvedGroupImage, groupImage: resolvedGroupImage } : {}
865
+ ...isGroup ? {
866
+ ...resolvedGroupName ? { groupName: resolvedGroupName, name: resolvedGroupName } : {},
867
+ ...resolvedGroupImage ? { image: resolvedGroupImage, groupImage: resolvedGroupImage } : {}
868
+ } : {}
861
869
  };
862
870
  };
863
871
  resolveConversationLastMessage = (conversation, messagesByConversation) => {
@@ -929,9 +937,9 @@ var init_conversation_helpers = __esm({
929
937
  if (!conversationId) return void 0;
930
938
  return conversations.find((c) => String(c._id) === String(conversationId));
931
939
  };
932
- findConversationIdByLastMessageId = (conversations, messageId) => {
933
- if (!messageId) return null;
934
- const normalizedMessageId = String(messageId);
940
+ findConversationIdByLastMessageId = (conversations, messageId2) => {
941
+ if (!messageId2) return null;
942
+ const normalizedMessageId = String(messageId2);
935
943
  const match = conversations.find(
936
944
  (conversation) => String(conversation?.lastMessage?._id || conversation?.lastMessage?.id || "") === normalizedMessageId
937
945
  );
@@ -1350,7 +1358,7 @@ var init_api_constants = __esm({
1350
1358
  ADD_REMOVE_MEMBERS: "/conversation/group/participants/add-remove",
1351
1359
  ADD_REMOVE_ADMINS: "/conversation/group/admins/add-remove",
1352
1360
  SEARCH_MESSAGES: "/message/search-messages",
1353
- SEARCH_MESSAGES_CONTEXT: (messageId) => `/message/searched-message/context?messageId=${messageId}`,
1361
+ SEARCH_MESSAGES_CONTEXT: (messageId2) => `/message/searched-message/context?messageId=${messageId2}`,
1354
1362
  BLOCK_UNBLOCK_USER: "/user/block-unblock"
1355
1363
  }
1356
1364
  };
@@ -1494,9 +1502,9 @@ var init_messages_api = __esm({
1494
1502
  throw error;
1495
1503
  }
1496
1504
  };
1497
- searchMessagesContext = async (messageId) => {
1505
+ searchMessagesContext = async (messageId2) => {
1498
1506
  try {
1499
- const response = await apiClient.get(API_ENDPOINTS.GROUP.SEARCH_MESSAGES_CONTEXT(messageId));
1507
+ const response = await apiClient.get(API_ENDPOINTS.GROUP.SEARCH_MESSAGES_CONTEXT(messageId2));
1500
1508
  return response.data;
1501
1509
  } catch (error) {
1502
1510
  console.error("Search messages context failed:", error);
@@ -1622,24 +1630,24 @@ var init_forwardPending_store = __esm({
1622
1630
  "src/store/forwardPending.store.ts"() {
1623
1631
  pendingForwards = /* @__PURE__ */ new Map();
1624
1632
  lastPendingMessageId = null;
1625
- setPendingForward = (messageId, meta) => {
1626
- if (!messageId) return;
1627
- const key = String(messageId);
1633
+ setPendingForward = (messageId2, meta) => {
1634
+ if (!messageId2) return;
1635
+ const key = String(messageId2);
1628
1636
  pendingForwards.set(key, meta);
1629
1637
  lastPendingMessageId = key;
1630
1638
  };
1631
- peekPendingForward = (messageId) => {
1632
- if (!messageId) return void 0;
1633
- return pendingForwards.get(String(messageId));
1639
+ peekPendingForward = (messageId2) => {
1640
+ if (!messageId2) return void 0;
1641
+ return pendingForwards.get(String(messageId2));
1634
1642
  };
1635
1643
  peekMostRecentPendingForward = () => {
1636
1644
  if (!lastPendingMessageId) return void 0;
1637
1645
  return pendingForwards.get(lastPendingMessageId);
1638
1646
  };
1639
1647
  getLastPendingForwardMessageId = () => lastPendingMessageId;
1640
- clearPendingForward = (messageId) => {
1641
- if (messageId) {
1642
- const key = String(messageId);
1648
+ clearPendingForward = (messageId2) => {
1649
+ if (messageId2) {
1650
+ const key = String(messageId2);
1643
1651
  pendingForwards.delete(key);
1644
1652
  if (lastPendingMessageId === key) lastPendingMessageId = null;
1645
1653
  return;
@@ -2109,14 +2117,14 @@ var init_group_reaction_handlers = __esm({
2109
2117
  return Array.from(map.values());
2110
2118
  };
2111
2119
  handleGroupReactionAddReceive = (set, get, payload) => {
2112
- const messageId = payload.messageId || payload._id;
2120
+ const messageId2 = payload.messageId || payload._id;
2113
2121
  const conversationId = payload.conversationId;
2114
- if (!messageId) return;
2122
+ if (!messageId2) return;
2115
2123
  set((state) => {
2116
- const cid = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId);
2124
+ const cid = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId2);
2117
2125
  if (!cid) return state;
2118
2126
  const messages = state.messagesByConversation[cid] || [];
2119
- const idx = messages.findIndex((m) => String(m._id || m.id) === String(messageId));
2127
+ const idx = messages.findIndex((m) => String(m._id || m.id) === String(messageId2));
2120
2128
  if (idx === -1) return state;
2121
2129
  const nextMessages = [...messages];
2122
2130
  const currentMsg = { ...nextMessages[idx] };
@@ -2134,20 +2142,20 @@ var init_group_reaction_handlers = __esm({
2134
2142
  }
2135
2143
  nextMessages[idx] = currentMsg;
2136
2144
  return {
2137
- lastReactionUpdate: { ...payload, messageId, action: "add", _v: Date.now() },
2145
+ lastReactionUpdate: { ...payload, messageId: messageId2, action: "add", _v: Date.now() },
2138
2146
  messagesByConversation: { ...state.messagesByConversation, [cid]: nextMessages }
2139
2147
  };
2140
2148
  });
2141
2149
  };
2142
2150
  handleGroupReactionRemoveReceive = (set, get, payload) => {
2143
- const messageId = payload.messageId || payload._id;
2151
+ const messageId2 = payload.messageId || payload._id;
2144
2152
  const conversationId = payload.conversationId;
2145
- if (!messageId) return;
2153
+ if (!messageId2) return;
2146
2154
  set((state) => {
2147
- const cid = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId);
2155
+ const cid = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId2);
2148
2156
  if (!cid) return state;
2149
2157
  const messages = state.messagesByConversation[cid] || [];
2150
- const idx = messages.findIndex((m) => String(m._id || m.id) === String(messageId));
2158
+ const idx = messages.findIndex((m) => String(m._id || m.id) === String(messageId2));
2151
2159
  if (idx === -1) return state;
2152
2160
  const nextMessages = [...messages];
2153
2161
  const currentMsg = { ...nextMessages[idx] };
@@ -2164,7 +2172,7 @@ var init_group_reaction_handlers = __esm({
2164
2172
  }
2165
2173
  nextMessages[idx] = currentMsg;
2166
2174
  return {
2167
- lastReactionUpdate: { ...payload, messageId, action: "remove", _v: Date.now() },
2175
+ lastReactionUpdate: { ...payload, messageId: messageId2, action: "remove", _v: Date.now() },
2168
2176
  messagesByConversation: { ...state.messagesByConversation, [cid]: nextMessages }
2169
2177
  };
2170
2178
  });
@@ -2194,14 +2202,14 @@ function removeMessageAttachment(message, attachmentId) {
2194
2202
  if (attachments.length === message.attachments.length) return message;
2195
2203
  return { ...message, attachments };
2196
2204
  }
2197
- function pinKey(messageId, attachmentId) {
2198
- return attachmentId ? `${messageId}:${attachmentId}` : String(messageId);
2205
+ function pinKey(messageId2, attachmentId) {
2206
+ return attachmentId ? `${messageId2}:${attachmentId}` : String(messageId2);
2199
2207
  }
2200
- function matchesPinEntry(entry, messageId, attachmentId) {
2208
+ function matchesPinEntry(entry, messageId2, attachmentId) {
2201
2209
  const entryMessageId = String(
2202
2210
  entry?.messageId?._id || entry?.messageId || entry?._id || entry?.id || ""
2203
2211
  );
2204
- if (entryMessageId !== String(messageId)) return false;
2212
+ if (entryMessageId !== String(messageId2)) return false;
2205
2213
  const entryAttachmentId = entry?.attachmentId ? String(entry.attachmentId) : null;
2206
2214
  const targetAttachmentId = attachmentId ? String(attachmentId) : null;
2207
2215
  return entryAttachmentId === targetAttachmentId;
@@ -2216,13 +2224,13 @@ function applyPinnedListToMessages(messages, pinnedMessage) {
2216
2224
  )
2217
2225
  );
2218
2226
  return messages.map((message) => {
2219
- const messageId = String(message._id || message.id);
2220
- const hasWholeMessagePin = pinnedKeys.has(pinKey(messageId, null));
2227
+ const messageId2 = String(message._id || message.id);
2228
+ const hasWholeMessagePin = pinnedKeys.has(pinKey(messageId2, null));
2221
2229
  const attachments = (message.attachments || []).map((att) => {
2222
2230
  const attId = getAttachmentId(att);
2223
2231
  return {
2224
2232
  ...att,
2225
- isPinned: attId ? pinnedKeys.has(pinKey(messageId, attId)) : !!att.isPinned
2233
+ isPinned: attId ? pinnedKeys.has(pinKey(messageId2, attId)) : !!att.isPinned
2226
2234
  };
2227
2235
  });
2228
2236
  return {
@@ -2284,13 +2292,13 @@ var init_pin_handlers = __esm({
2284
2292
  });
2285
2293
  return;
2286
2294
  }
2287
- const { messageId, conversationId, isPinned, attachmentId } = extractMessageData(payload);
2288
- if (!messageId || !conversationId) return;
2295
+ const { messageId: messageId2, conversationId, isPinned, attachmentId } = extractMessageData(payload);
2296
+ if (!messageId2 || !conversationId) return;
2289
2297
  set((state) => {
2290
- const sid = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId);
2298
+ const sid = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId2);
2291
2299
  if (!sid) return state;
2292
2300
  const messages = state.messagesByConversation[sid] || [];
2293
- const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId));
2301
+ const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId2));
2294
2302
  let newMessagesByConversation = state.messagesByConversation;
2295
2303
  const msg = index !== -1 ? messages[index] : null;
2296
2304
  const wasPinned = attachmentId ? !!msg?.attachments?.some(
@@ -2312,9 +2320,9 @@ var init_pin_handlers = __esm({
2312
2320
  const newPinnedByConv = { ...state.pinnedMessagesByConversation };
2313
2321
  if (isPinned) {
2314
2322
  const currentPinned = newPinnedByConv[sid] || [];
2315
- if (!currentPinned.some((m) => matchesPinEntry(m, messageId, attachmentId || null))) {
2323
+ if (!currentPinned.some((m) => matchesPinEntry(m, messageId2, attachmentId || null))) {
2316
2324
  const fullMsg = msg ? attachmentId ? {
2317
- messageId,
2325
+ messageId: messageId2,
2318
2326
  attachmentId,
2319
2327
  attachment: msg.attachments?.find(
2320
2328
  (att) => getAttachmentId(att) === String(attachmentId)
@@ -2326,7 +2334,7 @@ var init_pin_handlers = __esm({
2326
2334
  }
2327
2335
  } else {
2328
2336
  newPinnedByConv[sid] = (newPinnedByConv[sid] || []).filter(
2329
- (m) => !matchesPinEntry(m, messageId, attachmentId || payload.unpinAttachmentId || null)
2337
+ (m) => !matchesPinEntry(m, messageId2, attachmentId || payload.unpinAttachmentId || null)
2330
2338
  );
2331
2339
  }
2332
2340
  const conversation = get().conversations?.find((c) => String(c._id) === String(sid));
@@ -2341,8 +2349,8 @@ var init_pin_handlers = __esm({
2341
2349
  pinnedCount = payload.totalCount;
2342
2350
  }
2343
2351
  const newPendingActions = { ...state.messagePendingActions };
2344
- if (newPendingActions[messageId]) {
2345
- delete newPendingActions[messageId];
2352
+ if (newPendingActions[messageId2]) {
2353
+ delete newPendingActions[messageId2];
2346
2354
  }
2347
2355
  return {
2348
2356
  lastPinUpdate: payload,
@@ -2373,13 +2381,13 @@ var init_star_handlers = __esm({
2373
2381
  init_attachment_helpers();
2374
2382
  handleStarUpdate = (set, get, payload) => {
2375
2383
  if (payload.starredBy && Array.isArray(payload.starredBy)) {
2376
- const { messageId: messageId2, attachmentId } = extractMessageData(payload);
2384
+ const { messageId: messageId3, attachmentId } = extractMessageData(payload);
2377
2385
  const { starredBy } = payload;
2378
- if (!messageId2) return;
2386
+ if (!messageId3) return;
2379
2387
  set((state) => {
2380
- const sid = payload.conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId2);
2388
+ const sid = payload.conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId3);
2381
2389
  const newPendingActions = { ...state.messagePendingActions };
2382
- const pendingKey = String(messageId2);
2390
+ const pendingKey = String(messageId3);
2383
2391
  if (newPendingActions[pendingKey]) {
2384
2392
  delete newPendingActions[pendingKey];
2385
2393
  }
@@ -2389,7 +2397,7 @@ var init_star_handlers = __esm({
2389
2397
  const loggedUserId = String(get().loggedUserDetails?._id || state.loggedUserDetails?._id || "");
2390
2398
  const isStarred2 = starredBy.some((id) => String(id?._id || id) === loggedUserId) || loggedUserId === "" && starredBy.length > 0;
2391
2399
  const messages = state.messagesByConversation[sid] || [];
2392
- const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId2));
2400
+ const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId3));
2393
2401
  let newMessagesByConversation = state.messagesByConversation;
2394
2402
  if (index !== -1) {
2395
2403
  const newMessages = [...messages];
@@ -2416,9 +2424,9 @@ var init_star_handlers = __esm({
2416
2424
  const newStarredByConv = { ...state.starredMessagesByConversation };
2417
2425
  const currentStarred = newStarredByConv[sid] || [];
2418
2426
  const exists = attachmentId ? currentStarred.some(
2419
- (m) => m.isAttachment && String(m.messageId) === String(messageId2) && String(m.attachmentId) === String(attachmentId)
2427
+ (m) => m.isAttachment && String(m.messageId) === String(messageId3) && String(m.attachmentId) === String(attachmentId)
2420
2428
  ) : currentStarred.some(
2421
- (m) => !m.isAttachment && String(m.messageId?._id || m.messageId || m._id || m.id) === String(messageId2)
2429
+ (m) => !m.isAttachment && String(m.messageId?._id || m.messageId || m._id || m.id) === String(messageId3)
2422
2430
  );
2423
2431
  const conversation = get().conversations?.find((c) => String(c._id) === String(sid));
2424
2432
  const existingCount = state.liveConversationCounts[sid]?.starredCount ?? conversation?.starredCount ?? 0;
@@ -2426,21 +2434,21 @@ var init_star_handlers = __esm({
2426
2434
  if (isStarred2 && !exists) {
2427
2435
  const fullMessage = attachmentId ? {
2428
2436
  _id: attachmentId,
2429
- messageId: messageId2,
2437
+ messageId: messageId3,
2430
2438
  attachmentId,
2431
2439
  isAttachment: true,
2432
2440
  attachment: index !== -1 ? newMessagesByConversation[sid][index]?.attachments?.find(
2433
2441
  (att) => getAttachmentId(att) === String(attachmentId)
2434
2442
  ) : payload.attachment,
2435
2443
  createdAt: payload.createdAt || (/* @__PURE__ */ new Date()).toISOString()
2436
- } : index !== -1 ? newMessagesByConversation[sid][index] : { ...payload, _id: messageId2 };
2444
+ } : index !== -1 ? newMessagesByConversation[sid][index] : { ...payload, _id: messageId3 };
2437
2445
  newStarredByConv[sid] = [...currentStarred, fullMessage];
2438
2446
  starredCount = existingCount + 1;
2439
2447
  } else if (!isStarred2 && exists) {
2440
2448
  newStarredByConv[sid] = attachmentId ? currentStarred.filter(
2441
- (m) => !(m.isAttachment && String(m.messageId) === String(messageId2) && String(m.attachmentId) === String(attachmentId))
2449
+ (m) => !(m.isAttachment && String(m.messageId) === String(messageId3) && String(m.attachmentId) === String(attachmentId))
2442
2450
  ) : currentStarred.filter(
2443
- (m) => String(m.messageId?._id || m.messageId || m._id || m.id) !== String(messageId2)
2451
+ (m) => String(m.messageId?._id || m.messageId || m._id || m.id) !== String(messageId3)
2444
2452
  );
2445
2453
  starredCount = Math.max(0, existingCount - 1);
2446
2454
  }
@@ -2466,13 +2474,13 @@ var init_star_handlers = __esm({
2466
2474
  });
2467
2475
  return;
2468
2476
  }
2469
- const { messageId, isStarred, conversationId } = extractMessageData(payload);
2470
- if (!messageId) return;
2477
+ const { messageId: messageId2, isStarred, conversationId } = extractMessageData(payload);
2478
+ if (!messageId2) return;
2471
2479
  set((state) => {
2472
- const sid = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId);
2480
+ const sid = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId2);
2473
2481
  if (!sid) return { lastStarUpdate: payload };
2474
2482
  const messages = state.messagesByConversation[sid] || [];
2475
- const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId));
2483
+ const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId2));
2476
2484
  let newMessagesByConversation = state.messagesByConversation;
2477
2485
  const msg = index !== -1 ? messages[index] : null;
2478
2486
  const wasStarred = msg ? !!msg.isStarred : false;
@@ -2488,13 +2496,13 @@ var init_star_handlers = __esm({
2488
2496
  const newStarredByConv = { ...state.starredMessagesByConversation };
2489
2497
  if (isStarred) {
2490
2498
  const currentStarred = newStarredByConv[sid] || [];
2491
- if (!currentStarred.some((m) => String(m?._id || m?.id || m.messageId?._id || m.messageId?.id) === String(messageId))) {
2499
+ if (!currentStarred.some((m) => String(m?._id || m?.id || m.messageId?._id || m.messageId?.id) === String(messageId2))) {
2492
2500
  const fullMsg = msg ? { ...msg, isStarred: true } : payload;
2493
2501
  newStarredByConv[sid] = [...currentStarred, fullMsg];
2494
2502
  }
2495
2503
  } else {
2496
2504
  newStarredByConv[sid] = (newStarredByConv[sid] || []).filter(
2497
- (m) => String(m?._id || m?.id || m.messageId?._id || m.messageId?.id) !== String(messageId)
2505
+ (m) => String(m?._id || m?.id || m.messageId?._id || m.messageId?.id) !== String(messageId2)
2498
2506
  );
2499
2507
  }
2500
2508
  const conversation = get().conversations?.find((c) => String(c._id) === String(sid));
@@ -2509,7 +2517,7 @@ var init_star_handlers = __esm({
2509
2517
  starredCount = payload.totalCount;
2510
2518
  }
2511
2519
  const newPendingActions = { ...state.messagePendingActions };
2512
- const pendingKey = String(messageId);
2520
+ const pendingKey = String(messageId2);
2513
2521
  if (newPendingActions[pendingKey]) {
2514
2522
  delete newPendingActions[pendingKey];
2515
2523
  }
@@ -2630,15 +2638,15 @@ var init_emit_actions = __esm({
2630
2638
  socket_service_default.emit("dm_unpin", p);
2631
2639
  },
2632
2640
  emitDmStar: (p) => {
2633
- const messageId = String(p.messageId);
2634
- handleStarUpdate(set, get, { ...p, messageId, isStarred: true });
2635
- set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [messageId]: ["star"] } }));
2641
+ const messageId2 = String(p.messageId);
2642
+ handleStarUpdate(set, get, { ...p, messageId: messageId2, isStarred: true });
2643
+ set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [messageId2]: ["star"] } }));
2636
2644
  socket_service_default.emit("dm_star", p);
2637
2645
  },
2638
2646
  emitDmUnstar: (p) => {
2639
- const messageId = String(p.messageId);
2640
- handleStarUpdate(set, get, { ...p, messageId, isStarred: false });
2641
- set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [messageId]: ["unstar"] } }));
2647
+ const messageId2 = String(p.messageId);
2648
+ handleStarUpdate(set, get, { ...p, messageId: messageId2, isStarred: false });
2649
+ set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [messageId2]: ["unstar"] } }));
2642
2650
  socket_service_default.emit("dm_unstar", p);
2643
2651
  },
2644
2652
  emitDmForward: (p) => {
@@ -2690,15 +2698,15 @@ var init_emit_actions = __esm({
2690
2698
  socket_service_default.emitGroupUnpin(p);
2691
2699
  },
2692
2700
  emitGroupStar: (p) => {
2693
- const messageId = String(p.messageId);
2694
- handleStarUpdate(set, get, { ...p, messageId, isStarred: true });
2695
- set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [messageId]: ["star"] } }));
2701
+ const messageId2 = String(p.messageId);
2702
+ handleStarUpdate(set, get, { ...p, messageId: messageId2, isStarred: true });
2703
+ set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [messageId2]: ["star"] } }));
2696
2704
  socket_service_default.emitGroupStar(p);
2697
2705
  },
2698
2706
  emitGroupUnstar: (p) => {
2699
- const messageId = String(p.messageId);
2700
- handleStarUpdate(set, get, { ...p, messageId, isStarred: false });
2701
- set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [messageId]: ["unstar"] } }));
2707
+ const messageId2 = String(p.messageId);
2708
+ handleStarUpdate(set, get, { ...p, messageId: messageId2, isStarred: false });
2709
+ set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [messageId2]: ["unstar"] } }));
2702
2710
  socket_service_default.emitGroupUnstar(p);
2703
2711
  },
2704
2712
  emitGroupForward: (p) => {
@@ -2717,8 +2725,8 @@ var init_emit_actions = __esm({
2717
2725
  ...p.attachmentId ? { attachmentId: String(p.attachmentId) } : {}
2718
2726
  });
2719
2727
  },
2720
- clearForwardPending: (messageId) => {
2721
- clearForwardPendingActions(set, messageId);
2728
+ clearForwardPending: (messageId2) => {
2729
+ clearForwardPendingActions(set, messageId2);
2722
2730
  },
2723
2731
  emitConversationUpdate: (p) => socket_service_default.emitConversationUpdate(p),
2724
2732
  emitGroupLeave: (p) => socket_service_default.emitGroupLeave(p),
@@ -2743,7 +2751,7 @@ var init_message_handlers = __esm({
2743
2751
  get().conversations,
2744
2752
  loggedUserId
2745
2753
  );
2746
- const { messageId } = extractMessageData(lastDM);
2754
+ const { messageId: messageId2 } = extractMessageData(lastDM);
2747
2755
  const tempId = lastDM.tempId;
2748
2756
  const isFromSelf = loggedUserDetails && String(lastDM.sender?._id || lastDM.sender) === String(loggedUserDetails._id);
2749
2757
  const activeConversationId = get().activeConversationId;
@@ -2753,14 +2761,14 @@ var init_message_handlers = __esm({
2753
2761
  const newPendingActions = { ...state.messagePendingActions };
2754
2762
  if (conversationId) {
2755
2763
  const current = nextMessagesByConversation[conversationId] || [];
2756
- let matchedId = messageId;
2764
+ let matchedId = messageId2;
2757
2765
  if (tempId && state.messagePendingActions[tempId]) {
2758
2766
  matchedId = tempId;
2759
2767
  }
2760
- const exists = current.some((m) => String(m._id || m.id) === String(messageId));
2768
+ const exists = current.some((m) => String(m._id || m.id) === String(messageId2));
2761
2769
  if (matchedId && matchedId === tempId) {
2762
2770
  nextMessagesByConversation[conversationId] = current.map(
2763
- (m) => String(m.id || m._id) === String(matchedId) ? { ...m, _id: messageId, id: messageId, status: messageWithStatus.status } : m
2771
+ (m) => String(m.id || m._id) === String(matchedId) ? { ...m, _id: messageId2, id: messageId2, status: messageWithStatus.status } : m
2764
2772
  );
2765
2773
  delete newPendingActions[matchedId];
2766
2774
  } else if (!exists) {
@@ -2793,8 +2801,7 @@ var init_message_handlers = __esm({
2793
2801
  conversationType: lastDM.conversationType || "individual",
2794
2802
  isGroup: false,
2795
2803
  ...shouldIncludeParticipants ? { participants: participantSeed } : {},
2796
- groupName: lastDM.groupName,
2797
- name: lastDM.groupName,
2804
+ ...lastDM.groupName ? { groupName: lastDM.groupName, name: lastDM.groupName } : {},
2798
2805
  owner: existingConv?.owner ?? lastDM.owner
2799
2806
  },
2800
2807
  {
@@ -2816,27 +2823,27 @@ var init_message_handlers = __esm({
2816
2823
  }
2817
2824
  };
2818
2825
  handleEditDM = (set, get, payload) => {
2819
- const { messageId, content, conversationId, attachmentId, caption } = extractMessageData(payload);
2820
- if (!messageId) return;
2826
+ const { messageId: messageId2, content, conversationId, attachmentId, caption } = extractMessageData(payload);
2827
+ if (!messageId2) return;
2821
2828
  const captionText = caption ?? content ?? "";
2822
2829
  set((state) => {
2823
2830
  let searchConversationId = conversationId;
2824
2831
  if (!searchConversationId) {
2825
- searchConversationId = findConversationIdByMessageId(state.messagesByConversation, messageId);
2832
+ searchConversationId = findConversationIdByMessageId(state.messagesByConversation, messageId2);
2826
2833
  }
2827
2834
  if (!searchConversationId) {
2828
2835
  searchConversationId = state.conversations.find(
2829
- (c) => String(c.lastMessage?._id || c.lastMessage?.id) === String(messageId)
2836
+ (c) => String(c.lastMessage?._id || c.lastMessage?.id) === String(messageId2)
2830
2837
  )?._id;
2831
2838
  }
2832
- const normalizedEditPayload = { ...payload, messageId, content, conversationId: searchConversationId, _v: Date.now() };
2839
+ const normalizedEditPayload = { ...payload, messageId: messageId2, content, conversationId: searchConversationId, _v: Date.now() };
2833
2840
  const newPendingActions = { ...state.messagePendingActions };
2834
- if (newPendingActions[messageId]) {
2835
- delete newPendingActions[messageId];
2841
+ if (newPendingActions[messageId2]) {
2842
+ delete newPendingActions[messageId2];
2836
2843
  }
2837
2844
  if (searchConversationId) {
2838
2845
  const messages = state.messagesByConversation[searchConversationId] || [];
2839
- const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId));
2846
+ const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId2));
2840
2847
  if (index !== -1) {
2841
2848
  const newMessages = [...messages];
2842
2849
  if (attachmentId) {
@@ -2862,15 +2869,15 @@ var init_message_handlers = __esm({
2862
2869
  });
2863
2870
  };
2864
2871
  handleDeleteDM = (set, get, payload, type) => {
2865
- const { messageId, conversationId, attachmentId } = extractMessageData(payload);
2866
- if (!messageId) return;
2872
+ const { messageId: messageId2, conversationId, attachmentId } = extractMessageData(payload);
2873
+ if (!messageId2) return;
2867
2874
  set((state) => {
2868
- const searchConversationId = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId);
2875
+ const searchConversationId = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId2);
2869
2876
  const messageTombstoned = payload.messageTombstoned === true;
2870
2877
  let updatedConversations = state.conversations;
2871
2878
  if (searchConversationId && !attachmentId) {
2872
2879
  updatedConversations = state.conversations.map((c) => {
2873
- if (String(c._id) === String(searchConversationId) && String(c.lastMessage?._id || c.lastMessage?.id) === String(messageId)) {
2880
+ if (String(c._id) === String(searchConversationId) && String(c.lastMessage?._id || c.lastMessage?.id) === String(messageId2)) {
2874
2881
  return { ...c, lastMessage: type === "me" ? { ...c.lastMessage, content: "" } : { ...c.lastMessage, isDeletedForEveryone: true, content: "This message has been deleted" } };
2875
2882
  }
2876
2883
  return c;
@@ -2881,7 +2888,7 @@ var init_message_handlers = __esm({
2881
2888
  if (searchConversationId) {
2882
2889
  if (attachmentId) {
2883
2890
  const updatedMessages = messages.map((m) => {
2884
- if (String(m._id || m.id) !== String(messageId)) return m;
2891
+ if (String(m._id || m.id) !== String(messageId2)) return m;
2885
2892
  if (messageTombstoned || type === "everyone" && payload.content) {
2886
2893
  return {
2887
2894
  ...m,
@@ -2920,22 +2927,22 @@ var init_message_handlers = __esm({
2920
2927
  [searchConversationId]: updatedMessages
2921
2928
  };
2922
2929
  } else if (type === "me") {
2923
- nextMessagesByConversation = { ...state.messagesByConversation, [searchConversationId]: messages.filter((m) => String(m._id || m.id) !== String(messageId)) };
2930
+ nextMessagesByConversation = { ...state.messagesByConversation, [searchConversationId]: messages.filter((m) => String(m._id || m.id) !== String(messageId2)) };
2924
2931
  } else {
2925
2932
  nextMessagesByConversation = {
2926
2933
  ...state.messagesByConversation,
2927
- [searchConversationId]: messages.map((m) => String(m._id || m.id) === String(messageId) ? { ...m, isDeletedForEveryone: true, content: "" } : m)
2934
+ [searchConversationId]: messages.map((m) => String(m._id || m.id) === String(messageId2) ? { ...m, isDeletedForEveryone: true, content: "" } : m)
2928
2935
  };
2929
2936
  }
2930
2937
  }
2931
2938
  const newPendingActions = { ...state.messagePendingActions };
2932
- if (newPendingActions[messageId]) {
2933
- delete newPendingActions[messageId];
2939
+ if (newPendingActions[messageId2]) {
2940
+ delete newPendingActions[messageId2];
2934
2941
  }
2935
- const shouldMarkWholeMessageDeleted = type === "me" && !attachmentId && !state.deletedForMeIds.includes(messageId);
2942
+ const shouldMarkWholeMessageDeleted = type === "me" && !attachmentId && !state.deletedForMeIds.includes(messageId2);
2936
2943
  return {
2937
2944
  lastDeleteDM: { ...payload, deleteType: type },
2938
- deletedForMeIds: shouldMarkWholeMessageDeleted ? [...state.deletedForMeIds, messageId] : state.deletedForMeIds,
2945
+ deletedForMeIds: shouldMarkWholeMessageDeleted ? [...state.deletedForMeIds, messageId2] : state.deletedForMeIds,
2939
2946
  messagesByConversation: nextMessagesByConversation,
2940
2947
  conversations: updatedConversations,
2941
2948
  messagePendingActions: newPendingActions
@@ -3009,15 +3016,15 @@ var init_dm_actions = __esm({
3009
3016
  },
3010
3017
  receivedStatusUpdate: (payload) => {
3011
3018
  const data = extractMessageData(payload);
3012
- const { messageId, status } = data;
3019
+ const { messageId: messageId2, status } = data;
3013
3020
  let { conversationId } = data;
3014
- if (!messageId || !status) return;
3021
+ if (!messageId2 || !status) return;
3015
3022
  set({ lastStatusUpdate: payload });
3016
3023
  if (!conversationId) {
3017
- conversationId = findConversationIdByMessageId(get().messagesByConversation, messageId) || findConversationIdByLastMessageId(get().conversations, messageId) || void 0;
3024
+ conversationId = findConversationIdByMessageId(get().messagesByConversation, messageId2) || findConversationIdByLastMessageId(get().conversations, messageId2) || void 0;
3018
3025
  }
3019
3026
  set((state) => ({
3020
- ...applyMessageStatusToStore(state, String(messageId), status, conversationId)
3027
+ ...applyMessageStatusToStore(state, String(messageId2), status, conversationId)
3021
3028
  }));
3022
3029
  },
3023
3030
  receivedDMMarkRead: (payload) => {
@@ -3074,7 +3081,7 @@ var init_group_handlers = __esm({
3074
3081
  get().conversations,
3075
3082
  loggedUserId
3076
3083
  );
3077
- const { messageId } = extractMessageData(lastDM);
3084
+ const { messageId: messageId2 } = extractMessageData(lastDM);
3078
3085
  const tempId = lastDM.tempId;
3079
3086
  const activeConversationId = get().activeConversationId;
3080
3087
  const isOpenConversation = conversationId && String(conversationId) === String(activeConversationId);
@@ -3111,23 +3118,23 @@ var init_group_handlers = __esm({
3111
3118
  );
3112
3119
  if (optimisticMsg) matchedTempId = optimisticMsg.id;
3113
3120
  }
3114
- const messageExists = current.some((m) => String(m._id || m.id) === String(messageId));
3121
+ const messageExists = current.some((m) => String(m._id || m.id) === String(messageId2));
3115
3122
  if (!messageExists) {
3116
3123
  nextMessagesByConversation[conversationId] = [...current, {
3117
3124
  ...lastDM,
3118
- _id: messageId,
3119
- id: messageId,
3125
+ _id: messageId2,
3126
+ id: messageId2,
3120
3127
  status: lastDM.status || "sent"
3121
3128
  }];
3122
3129
  } else {
3123
3130
  nextMessagesByConversation[conversationId] = current.map(
3124
- (m) => String(m._id || m.id) === String(messageId) ? { ...m, status: lastDM.status || "sent" } : m
3131
+ (m) => String(m._id || m.id) === String(messageId2) ? { ...m, status: lastDM.status || "sent" } : m
3125
3132
  );
3126
3133
  }
3127
3134
  if (matchedTempId) {
3128
3135
  delete newPendingActions[matchedTempId];
3129
3136
  nextMessagesByConversation[conversationId] = nextMessagesByConversation[conversationId].map(
3130
- (m) => String(m.id || m._id) === String(matchedTempId) ? { ...m, _id: messageId, id: messageId, status: lastDM.status || "sent" } : m
3137
+ (m) => String(m.id || m._id) === String(matchedTempId) ? { ...m, _id: messageId2, id: messageId2, status: lastDM.status || "sent" } : m
3131
3138
  );
3132
3139
  }
3133
3140
  }
@@ -3137,8 +3144,10 @@ var init_group_handlers = __esm({
3137
3144
  _id: conversationId,
3138
3145
  conversationType: "group",
3139
3146
  isGroup: true,
3140
- groupName: lastDM.groupName,
3141
- name: lastDM.groupName,
3147
+ ...lastDM.groupName || lastDM.name ? {
3148
+ groupName: lastDM.groupName || lastDM.name,
3149
+ name: lastDM.groupName || lastDM.name
3150
+ } : {},
3142
3151
  participants: buildParticipantsFromMessagePayload(lastDM, loggedUserId)
3143
3152
  },
3144
3153
  {
@@ -3176,8 +3185,10 @@ var init_group_handlers = __esm({
3176
3185
  _id: conversationId,
3177
3186
  conversationType: "group",
3178
3187
  isGroup: true,
3179
- groupName: lastDM.groupName,
3180
- name: lastDM.groupName,
3188
+ ...lastDM.groupName || lastDM.name ? {
3189
+ groupName: lastDM.groupName || lastDM.name,
3190
+ name: lastDM.groupName || lastDM.name
3191
+ } : {},
3181
3192
  participants: buildParticipantsFromMessagePayload(lastDM, loggedUserId)
3182
3193
  },
3183
3194
  {
@@ -3196,10 +3207,10 @@ var init_group_handlers = __esm({
3196
3207
  (c) => String(c._id) === String(conversationId)
3197
3208
  );
3198
3209
  const isGroupChat = isGroupConversation(targetConv);
3199
- if (loggedUserDetails?._id && messageId && isGroupChat) {
3210
+ if (loggedUserDetails?._id && messageId2 && isGroupChat) {
3200
3211
  get().emitGroupMessageDelivered({
3201
3212
  conversationId,
3202
- messageId,
3213
+ messageId: messageId2,
3203
3214
  userId: loggedUserDetails._id
3204
3215
  });
3205
3216
  }
@@ -3277,15 +3288,15 @@ var init_group_actions2 = __esm({
3277
3288
  receivedGroupStatusUpdate: (payload) => {
3278
3289
  const data = extractMessageData(payload);
3279
3290
  let { conversationId } = data;
3280
- const { messageId, status } = data;
3291
+ const { messageId: messageId2, status } = data;
3281
3292
  set({ lastStatusUpdate: payload });
3282
3293
  if (!status) return;
3283
- if (messageId) {
3294
+ if (messageId2) {
3284
3295
  if (!conversationId) {
3285
- conversationId = findConversationIdByMessageId(get().messagesByConversation, messageId) || findConversationIdByLastMessageId(get().conversations, messageId) || void 0;
3296
+ conversationId = findConversationIdByMessageId(get().messagesByConversation, messageId2) || findConversationIdByLastMessageId(get().conversations, messageId2) || void 0;
3286
3297
  }
3287
3298
  set((state) => ({
3288
- ...applyMessageStatusToStore(state, String(messageId), status, conversationId)
3299
+ ...applyMessageStatusToStore(state, String(messageId2), status, conversationId)
3289
3300
  }));
3290
3301
  return;
3291
3302
  }
@@ -3501,7 +3512,7 @@ var init_receive = __esm({
3501
3512
  };
3502
3513
  });
3503
3514
  },
3504
- markDeletedForMe: (messageId) => set((state) => ({ deletedForMeIds: [...state.deletedForMeIds, messageId] }))
3515
+ markDeletedForMe: (messageId2) => set((state) => ({ deletedForMeIds: [...state.deletedForMeIds, messageId2] }))
3505
3516
  });
3506
3517
  createReceiveActions = (set, get) => ({
3507
3518
  ...createDmReceiveActions(set, get),
@@ -3526,13 +3537,13 @@ var init_search_actions = __esm({
3526
3537
  init_api_service();
3527
3538
  init_store_helpers();
3528
3539
  createSearchActions = (set, _get) => ({
3529
- fetchSearchMessageContext: async (messageId, options) => {
3540
+ fetchSearchMessageContext: async (messageId2, options) => {
3530
3541
  const searchMode = options?.searchMode !== false;
3531
- set({ isSearchActive: searchMode, searchedMessageId: messageId, isFetchingMessages: true });
3542
+ set({ isSearchActive: searchMode, searchedMessageId: messageId2, isFetchingMessages: true });
3532
3543
  try {
3533
- const response = await searchMessagesContext(messageId);
3544
+ const response = await searchMessagesContext(messageId2);
3534
3545
  const data = response.data?.list || response.data?.messages || response.messages || response.data || [];
3535
- const highlightId = response.data?.highlightMessageId || messageId;
3546
+ const highlightId = response.data?.highlightMessageId || messageId2;
3536
3547
  if (data.length > 0) {
3537
3548
  const conversationId = data[0].conversationId;
3538
3549
  if (conversationId) {
@@ -3561,7 +3572,7 @@ var init_search_actions = __esm({
3561
3572
  }
3562
3573
  },
3563
3574
  setSearchActive: (active) => set({ isSearchActive: active }),
3564
- setSearchedMessageId: (messageId) => set({ searchedMessageId: messageId })
3575
+ setSearchedMessageId: (messageId2) => set({ searchedMessageId: messageId2 })
3565
3576
  });
3566
3577
  }
3567
3578
  });
@@ -3928,6 +3939,7 @@ var buildIncomingMessageFromDM = (lastDM, loggedUserId, conversations) => {
3928
3939
  content: lastDM.content || lastDM.message?.content || "",
3929
3940
  sender: lastDM.sender?.name || lastDM.fromUserId || (isMe ? "Me" : "User"),
3930
3941
  senderId: String(lastDM.sender?._id || lastDM.sender || lastDM.fromUserId || ""),
3942
+ senderImage: lastDM.sender?.image,
3931
3943
  timestamp: lastDM.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
3932
3944
  isOwnMessage: isMe,
3933
3945
  channelId,
@@ -4085,9 +4097,9 @@ var syncLocalMessagesOnPinUpdate = (prev, lastPinUpdate) => {
4085
4097
  return next;
4086
4098
  };
4087
4099
  var syncLocalMessagesOnStarUpdate = (prev, lastStarUpdate, loggedUserId) => {
4088
- const messageId = lastStarUpdate.messageId || lastStarUpdate._id;
4089
- if (!messageId) return null;
4090
- const mid = String(messageId);
4100
+ const messageId2 = lastStarUpdate.messageId || lastStarUpdate._id;
4101
+ if (!messageId2) return null;
4102
+ const mid = String(messageId2);
4091
4103
  let isStarred;
4092
4104
  if (typeof lastStarUpdate.isStarred === "boolean") {
4093
4105
  isStarred = lastStarUpdate.isStarred;
@@ -4106,9 +4118,9 @@ var syncLocalMessagesOnStarUpdate = (prev, lastStarUpdate, loggedUserId) => {
4106
4118
  return next;
4107
4119
  };
4108
4120
  var syncLocalMessagesOnReactionUpdate = (prev, lastReactionUpdate, messagesByConversation) => {
4109
- const messageId = lastReactionUpdate.messageId || lastReactionUpdate._id;
4110
- if (!messageId) return prev;
4111
- const mid = String(messageId);
4121
+ const messageId2 = lastReactionUpdate.messageId || lastReactionUpdate._id;
4122
+ if (!messageId2) return prev;
4123
+ const mid = String(messageId2);
4112
4124
  let storeReactions;
4113
4125
  for (const msgs of Object.values(messagesByConversation)) {
4114
4126
  const found = msgs.find((m) => String(m._id || m.id) === mid);
@@ -4159,7 +4171,7 @@ var syncLocalMessagesOnReactionUpdate = (prev, lastReactionUpdate, messagesByCon
4159
4171
  return changed ? next : prev;
4160
4172
  };
4161
4173
  var syncLocalMessagesOnDelete = (prev, lastDeleteDM) => {
4162
- const messageId = lastDeleteDM.messageId || lastDeleteDM._id;
4174
+ const messageId2 = lastDeleteDM.messageId || lastDeleteDM._id;
4163
4175
  const deleteType = lastDeleteDM.deleteType || "everyone";
4164
4176
  const attachmentId = lastDeleteDM.attachmentId ? String(lastDeleteDM.attachmentId) : null;
4165
4177
  const messageTombstoned = lastDeleteDM.messageTombstoned === true;
@@ -4167,7 +4179,7 @@ var syncLocalMessagesOnDelete = (prev, lastDeleteDM) => {
4167
4179
  Object.keys(next).forEach((channelId) => {
4168
4180
  if (attachmentId) {
4169
4181
  next[channelId] = next[channelId].map((message) => {
4170
- if (String(message._id || message.id) !== String(messageId)) {
4182
+ if (String(message._id || message.id) !== String(messageId2)) {
4171
4183
  return message;
4172
4184
  }
4173
4185
  return applyLocalAttachmentDelete(
@@ -4181,26 +4193,26 @@ var syncLocalMessagesOnDelete = (prev, lastDeleteDM) => {
4181
4193
  }
4182
4194
  if (deleteType === "me") {
4183
4195
  next[channelId] = next[channelId].filter(
4184
- (m) => String(m._id || m.id) !== String(messageId)
4196
+ (m) => String(m._id || m.id) !== String(messageId2)
4185
4197
  );
4186
4198
  } else {
4187
4199
  next[channelId] = next[channelId].map(
4188
- (m) => String(m._id || m.id) === String(messageId) ? { ...m, isDeletedForEveryone: true } : m
4200
+ (m) => String(m._id || m.id) === String(messageId2) ? { ...m, isDeletedForEveryone: true } : m
4189
4201
  );
4190
4202
  }
4191
4203
  });
4192
4204
  return next;
4193
4205
  };
4194
4206
  var syncLocalMessagesOnEdit = (prev, lastEditDM) => {
4195
- const messageId = lastEditDM.messageId || lastEditDM._id;
4207
+ const messageId2 = lastEditDM.messageId || lastEditDM._id;
4196
4208
  const content = lastEditDM.content;
4197
4209
  const attachmentId = lastEditDM.attachmentId ? String(lastEditDM.attachmentId) : null;
4198
4210
  const caption = lastEditDM.caption ?? content;
4199
- if (!messageId) return null;
4211
+ if (!messageId2) return null;
4200
4212
  const next = { ...prev };
4201
4213
  Object.keys(next).forEach((channelId) => {
4202
4214
  const messages = next[channelId];
4203
- const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId));
4215
+ const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId2));
4204
4216
  if (index !== -1) {
4205
4217
  const updated = [...messages];
4206
4218
  const current = updated[index];
@@ -4470,7 +4482,7 @@ var Chat = ({
4470
4482
  const status = useStore((s) => s.status);
4471
4483
  const error = useStore((s) => s.error);
4472
4484
  useChatSync();
4473
- React2.useEffect(() => {
4485
+ React2__default.useEffect(() => {
4474
4486
  const clientId = client?.id;
4475
4487
  const initializeChat = async () => {
4476
4488
  if (!clientId || !loggedUserDetails) return;
@@ -4559,28 +4571,28 @@ var Chat = ({
4559
4571
  queryParamApis: queryParamApis ?? ["get"],
4560
4572
  queryParamsByApi: queryParamsByApi ?? {}
4561
4573
  });
4562
- React2.useEffect(() => {
4574
+ React2__default.useEffect(() => {
4563
4575
  setChatQueryParams(queryParams);
4564
4576
  setChatQueryParamApis(queryParamApis);
4565
4577
  setChatQueryParamsByApi(queryParamsByApi);
4566
4578
  }, [queryConfigKey]);
4567
- React2.useEffect(() => {
4579
+ React2__default.useEffect(() => {
4568
4580
  if (lastDM && onMessageReceived) {
4569
4581
  onMessageReceived(lastDM);
4570
4582
  }
4571
4583
  }, [lastDM, onMessageReceived]);
4572
- React2.useEffect(() => {
4584
+ React2__default.useEffect(() => {
4573
4585
  if (status === "connected" && onSocketConnected) {
4574
4586
  const socketId = useStore.getState().socketId;
4575
4587
  if (socketId) onSocketConnected(socketId);
4576
4588
  }
4577
4589
  }, [status, onSocketConnected]);
4578
- React2.useEffect(() => {
4590
+ React2__default.useEffect(() => {
4579
4591
  if (status === "error" && error && onSocketError) {
4580
4592
  onSocketError(error);
4581
4593
  }
4582
4594
  }, [status, error, onSocketError]);
4583
- const contextValue = React2.useMemo(
4595
+ const contextValue = React2__default.useMemo(
4584
4596
  () => ({
4585
4597
  onSendMessage,
4586
4598
  client,
@@ -4600,7 +4612,7 @@ var Chat = ({
4600
4612
  messagesData
4601
4613
  ]
4602
4614
  );
4603
- const customization = React2.useMemo(
4615
+ const customization = React2__default.useMemo(
4604
4616
  () => ({
4605
4617
  components: uiConfig.components,
4606
4618
  classNames: uiConfig.classNames,
@@ -6695,20 +6707,35 @@ init_chat_constants();
6695
6707
  // src/chat/lib/last-message-preview.ts
6696
6708
  init_store_helpers();
6697
6709
 
6698
- // src/chat/lib/chat-attachment-display.ts
6699
- init_chat_constants();
6700
- function cleanAttachmentDisplayName(filename, fallback = "Attachment") {
6701
- const trimmed = filename.trim();
6702
- if (!trimmed) return fallback;
6703
- let name = trimmed;
6704
- const prefixPattern = new RegExp(`^\\d{${ATTACHMENT_FILENAME_TIMESTAMP_LENGTH}}_`);
6705
- while (prefixPattern.test(name)) {
6706
- name = name.slice(ATTACHMENT_FILENAME_TIMESTAMP_LENGTH + 1);
6710
+ // src/chat/lib/attachment-preview-labels.ts
6711
+ function getAttachmentTypePreviewLabel(type) {
6712
+ switch (String(type || "").toLowerCase()) {
6713
+ case "image":
6714
+ return "Photo";
6715
+ case "video":
6716
+ return "Video";
6717
+ case "audio":
6718
+ return "Audio";
6719
+ case "file":
6720
+ case "document":
6721
+ case "spreadsheet":
6722
+ return "Attachment";
6723
+ default:
6724
+ return "Attachment";
6707
6725
  }
6708
- if (name.length > ATTACHMENT_FILENAME_TIMESTAMP_LENGTH && /^\d+$/.test(name.slice(0, ATTACHMENT_FILENAME_TIMESTAMP_LENGTH)) && name[ATTACHMENT_FILENAME_TIMESTAMP_LENGTH] !== "_") {
6709
- name = name.slice(ATTACHMENT_FILENAME_TIMESTAMP_LENGTH);
6726
+ }
6727
+ function getAttachmentCountPreviewLabel(type, count) {
6728
+ if (count <= 1) return getAttachmentTypePreviewLabel(type);
6729
+ switch (String(type).toLowerCase()) {
6730
+ case "image":
6731
+ return `${count} photos`;
6732
+ case "video":
6733
+ return `${count} videos`;
6734
+ case "audio":
6735
+ return `${count} audio files`;
6736
+ default:
6737
+ return `${count} attachments`;
6710
6738
  }
6711
- return name.trim() || trimmed;
6712
6739
  }
6713
6740
 
6714
6741
  // src/chat/lib/last-message-preview.ts
@@ -6716,21 +6743,30 @@ function getAttachmentOnlyPreviewText(attachments) {
6716
6743
  const images = attachments.filter((att2) => att2.type === "image" && att2.url);
6717
6744
  const videos = attachments.filter((att2) => att2.type === "video" && att2.url);
6718
6745
  const audios = attachments.filter((att2) => att2.type === "audio" && att2.url);
6719
- if (images.length > 1) return `${images.length} photos`;
6746
+ const files = attachments.filter(
6747
+ (att2) => att2.url && !["image", "video", "audio"].includes(att2.type)
6748
+ );
6749
+ if (images.length > 1) return getAttachmentCountPreviewLabel("image", images.length);
6720
6750
  if (images.length === 1) {
6721
- return images[0].caption?.trim() || "Photo";
6751
+ return images[0].caption?.trim() || getAttachmentTypePreviewLabel("image");
6722
6752
  }
6723
- if (videos.length > 1) return `${videos.length} videos`;
6753
+ if (videos.length > 1) return getAttachmentCountPreviewLabel("video", videos.length);
6724
6754
  if (videos.length === 1) {
6725
- return videos[0].caption?.trim() || "Video";
6755
+ return videos[0].caption?.trim() || getAttachmentTypePreviewLabel("video");
6726
6756
  }
6727
- if (audios.length > 1) return `${audios.length} audio files`;
6757
+ if (audios.length > 1) return getAttachmentCountPreviewLabel("audio", audios.length);
6728
6758
  if (audios.length === 1) {
6729
- return audios[0].caption?.trim() || "Audio";
6759
+ return audios[0].caption?.trim() || getAttachmentTypePreviewLabel("audio");
6760
+ }
6761
+ if (files.length > 1) return getAttachmentCountPreviewLabel("file", files.length);
6762
+ if (files.length === 1) {
6763
+ return files[0].caption?.trim() || getAttachmentTypePreviewLabel(files[0].type);
6764
+ }
6765
+ if (attachments.length > 1) {
6766
+ return getAttachmentCountPreviewLabel("file", attachments.length);
6730
6767
  }
6731
- if (attachments.length > 1) return `${attachments.length} files`;
6732
6768
  const att = attachments[0];
6733
- return att.caption?.trim() || cleanAttachmentDisplayName(att.name || "", "Attachment");
6769
+ return att?.caption?.trim() || getAttachmentTypePreviewLabel(att?.type);
6734
6770
  }
6735
6771
  function getLastMessageSidebarPreview(message) {
6736
6772
  const content = String(message?.content || "").trim();
@@ -6744,6 +6780,10 @@ function getLastMessageSidebarPreview(message) {
6744
6780
  if (attachments.length > 0) {
6745
6781
  return getAttachmentOnlyPreviewText(attachments);
6746
6782
  }
6783
+ const messageType = String(message?.type || "").toLowerCase();
6784
+ if (messageType && messageType !== "text") {
6785
+ return getAttachmentTypePreviewLabel(messageType);
6786
+ }
6747
6787
  return "No messages yet";
6748
6788
  }
6749
6789
  function getMessagePreviewText(message, fallback = "Message") {
@@ -6755,6 +6795,10 @@ function getMessagePreviewText(message, fallback = "Message") {
6755
6795
  if (attachments.length > 0) {
6756
6796
  return getAttachmentOnlyPreviewText(attachments);
6757
6797
  }
6798
+ const messageType = String(message?.type || "").toLowerCase();
6799
+ if (messageType && messageType !== "text") {
6800
+ return getAttachmentTypePreviewLabel(messageType);
6801
+ }
6758
6802
  return fallback;
6759
6803
  }
6760
6804
 
@@ -7396,7 +7440,7 @@ function highlightSearchMatch(text, query) {
7396
7440
  children: part
7397
7441
  },
7398
7442
  `${part}-${index}`
7399
- ) : /* @__PURE__ */ jsx(React2.Fragment, { children: part }, `${part}-${index}`)
7443
+ ) : /* @__PURE__ */ jsx(React2__default.Fragment, { children: part }, `${part}-${index}`)
7400
7444
  );
7401
7445
  }
7402
7446
  function getMessagePreview(message) {
@@ -7811,11 +7855,11 @@ function buildAttachmentSummary(attachments) {
7811
7855
  else fileCount += 1;
7812
7856
  }
7813
7857
  const parts = [];
7814
- if (imageCount) parts.push(`${imageCount} photo${imageCount > 1 ? "s" : ""}`);
7815
- if (videoCount) parts.push(`${videoCount} video${videoCount > 1 ? "s" : ""}`);
7816
- if (audioCount) parts.push(`${audioCount} audio file${audioCount > 1 ? "s" : ""}`);
7817
- if (fileCount) parts.push(`${fileCount} file${fileCount > 1 ? "s" : ""}`);
7818
- return parts.join(", ") || "Attachment";
7858
+ if (imageCount) parts.push(getAttachmentCountPreviewLabel("image", imageCount));
7859
+ if (videoCount) parts.push(getAttachmentCountPreviewLabel("video", videoCount));
7860
+ if (audioCount) parts.push(getAttachmentCountPreviewLabel("audio", audioCount));
7861
+ if (fileCount) parts.push(getAttachmentCountPreviewLabel("file", fileCount));
7862
+ return parts.join(", ") || getAttachmentTypePreviewLabel("file");
7819
7863
  }
7820
7864
  function mapSavedMessageAttachments(msg, messageObj, ctx) {
7821
7865
  const loggedUserId = String(ctx.loggedUserDetails?._id || "");
@@ -7877,11 +7921,19 @@ function resolveSavedMessageContent(messageObj, msg) {
7877
7921
  }
7878
7922
  return { content: filename, messageType: "file", previewUrl: void 0 };
7879
7923
  }
7880
- if (messageType === "image") return { content: "Photo", messageType, previewUrl: void 0 };
7881
- if (messageType === "video") return { content: "Video", messageType, previewUrl: void 0 };
7882
- if (messageType === "audio") return { content: "Audio", messageType, previewUrl: void 0 };
7883
- if (messageType === "file") return { content: "File", messageType, previewUrl: void 0 };
7884
- return { content: "Attachment", messageType, previewUrl: void 0 };
7924
+ if (messageType === "image") {
7925
+ return { content: getAttachmentTypePreviewLabel("image"), messageType, previewUrl: void 0 };
7926
+ }
7927
+ if (messageType === "video") {
7928
+ return { content: getAttachmentTypePreviewLabel("video"), messageType, previewUrl: void 0 };
7929
+ }
7930
+ if (messageType === "audio") {
7931
+ return { content: getAttachmentTypePreviewLabel("audio"), messageType, previewUrl: void 0 };
7932
+ }
7933
+ if (messageType === "file") {
7934
+ return { content: getAttachmentTypePreviewLabel("file"), messageType, previewUrl: void 0 };
7935
+ }
7936
+ return { content: getAttachmentTypePreviewLabel("file"), messageType, previewUrl: void 0 };
7885
7937
  }
7886
7938
  function getMessageId(msg) {
7887
7939
  if (msg?.messageId && typeof msg.messageId === "object") {
@@ -7915,7 +7967,7 @@ function readSenderFromRecord(record) {
7915
7967
  }
7916
7968
  function resolveSenderName(msg, ctx) {
7917
7969
  const messageObj = getMessageObject(msg);
7918
- const messageId = getMessageId(msg);
7970
+ const messageId2 = getMessageId(msg);
7919
7971
  const loggedId = String(ctx.loggedUserDetails?._id || "");
7920
7972
  const tryRecord = (record) => {
7921
7973
  const parsed = readSenderFromRecord(record);
@@ -7932,9 +7984,9 @@ function resolveSenderName(msg, ctx) {
7932
7984
  const hit = tryRecord(record);
7933
7985
  if (hit) return hit;
7934
7986
  }
7935
- if (messageId && ctx.conversationMessages?.length) {
7987
+ if (messageId2 && ctx.conversationMessages?.length) {
7936
7988
  const found = ctx.conversationMessages.find(
7937
- (m) => String(m._id || m.id) === String(messageId)
7989
+ (m) => String(m._id || m.id) === String(messageId2)
7938
7990
  );
7939
7991
  if (found) {
7940
7992
  const hit = tryRecord(found);
@@ -7985,7 +8037,7 @@ function parseSavedMessage(msg, ctx = {}) {
7985
8037
  const mode = ctx.mode || "pinned";
7986
8038
  const prefs = ctx.dateTimePrefs ?? {};
7987
8039
  if (msg?.isAttachment) {
7988
- const messageId2 = String(msg.messageId || "");
8040
+ const messageId3 = String(msg.messageId || "");
7989
8041
  const attachmentId2 = String(msg.attachmentId || msg._id || "");
7990
8042
  const attachments2 = mapSavedMessageAttachments(msg, null, ctx);
7991
8043
  const { content: content2, previewUrl: previewUrl2, messageType: messageType2 } = resolveSavedMessageContent(null, msg);
@@ -7993,8 +8045,8 @@ function parseSavedMessage(msg, ctx = {}) {
7993
8045
  const actionAt2 = msg?.createdAt || msg?.updatedAt || "";
7994
8046
  const bodyText2 = String(msg.attachment?.caption || "").trim() || void 0;
7995
8047
  return {
7996
- id: attachmentId2 || messageId2,
7997
- messageId: messageId2,
8048
+ id: attachmentId2 || messageId3,
8049
+ messageId: messageId3,
7998
8050
  attachmentId: attachmentId2 || void 0,
7999
8051
  content: content2,
8000
8052
  bodyText: bodyText2,
@@ -8013,7 +8065,7 @@ function parseSavedMessage(msg, ctx = {}) {
8013
8065
  }
8014
8066
  const messageObj = getMessageObject(msg);
8015
8067
  const id = getMessageId(msg);
8016
- const messageId = id;
8068
+ const messageId2 = id;
8017
8069
  const attachmentId = msg?.attachmentId ? String(msg.attachmentId) : void 0;
8018
8070
  const attachments = mapSavedMessageAttachments(msg, messageObj, ctx);
8019
8071
  const rawContent = messageObj?.content ?? msg?.content ?? msg?.messageId?.content ?? "";
@@ -8035,8 +8087,8 @@ function parseSavedMessage(msg, ctx = {}) {
8035
8087
  metaLabel = "Starred by you";
8036
8088
  }
8037
8089
  return {
8038
- id: attachmentId ? `${messageId}:${attachmentId}` : id,
8039
- messageId,
8090
+ id: attachmentId ? `${messageId2}:${attachmentId}` : id,
8091
+ messageId: messageId2,
8040
8092
  attachmentId,
8041
8093
  content: displayContent,
8042
8094
  bodyText,
@@ -8066,6 +8118,22 @@ function groupSavedMessages(items) {
8066
8118
  }));
8067
8119
  }
8068
8120
 
8121
+ // src/chat/lib/chat-attachment-display.ts
8122
+ init_chat_constants();
8123
+ function cleanAttachmentDisplayName(filename, fallback = "Attachment") {
8124
+ const trimmed = filename.trim();
8125
+ if (!trimmed) return fallback;
8126
+ let name = trimmed;
8127
+ const prefixPattern = new RegExp(`^\\d{${ATTACHMENT_FILENAME_TIMESTAMP_LENGTH}}_`);
8128
+ while (prefixPattern.test(name)) {
8129
+ name = name.slice(ATTACHMENT_FILENAME_TIMESTAMP_LENGTH + 1);
8130
+ }
8131
+ if (name.length > ATTACHMENT_FILENAME_TIMESTAMP_LENGTH && /^\d+$/.test(name.slice(0, ATTACHMENT_FILENAME_TIMESTAMP_LENGTH)) && name[ATTACHMENT_FILENAME_TIMESTAMP_LENGTH] !== "_") {
8132
+ name = name.slice(ATTACHMENT_FILENAME_TIMESTAMP_LENGTH);
8133
+ }
8134
+ return name.trim() || trimmed;
8135
+ }
8136
+
8069
8137
  // src/chat/header/saved-message/saved-message-utils.ts
8070
8138
  var AVATAR_PALETTES = [
8071
8139
  "bg-violet-500/15 text-violet-600 dark:text-violet-300",
@@ -8487,6 +8555,18 @@ var MessageStatus = ({ status, isPending, className }) => {
8487
8555
  ) });
8488
8556
  };
8489
8557
  var MessageStatus_default = MessageStatus;
8558
+ function GroupSenderName({ name, className }) {
8559
+ return /* @__PURE__ */ jsx(
8560
+ "span",
8561
+ {
8562
+ className: cn(
8563
+ "block max-w-full truncate text-[13px] font-semibold leading-[1.15] tracking-tight text-(--chat-incoming-text)",
8564
+ className
8565
+ ),
8566
+ children: name
8567
+ }
8568
+ );
8569
+ }
8490
8570
  function ForwardDoubleIcon({ className }) {
8491
8571
  return /* @__PURE__ */ jsxs(
8492
8572
  "svg",
@@ -8524,22 +8604,10 @@ function MessageForwardedLabel({ isSender, className, overlay }) {
8524
8604
  }
8525
8605
  );
8526
8606
  }
8527
- function GroupSenderName({ name, className }) {
8528
- return /* @__PURE__ */ jsx(
8529
- "span",
8530
- {
8531
- className: cn(
8532
- "block max-w-full truncate text-[13px] font-semibold leading-[1.15] tracking-tight text-(--chat-incoming-text)",
8533
- className
8534
- ),
8535
- children: name
8536
- }
8537
- );
8538
- }
8539
8607
 
8540
8608
  // src/chat/lib/chat-message-bubble.ts
8541
- function getBubbleCornerClasses() {
8542
- return "rounded-tl-[18px] rounded-tr-[18px] rounded-br-[18px] rounded-bl-none";
8609
+ function getBubbleCornerClasses(isSender) {
8610
+ 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";
8543
8611
  }
8544
8612
  function getChatBubbleClasses({
8545
8613
  isSender = false,
@@ -8550,7 +8618,7 @@ function getChatBubbleClasses({
8550
8618
  const isNeutral = resolvedSurface === "neutral";
8551
8619
  return cn(
8552
8620
  "relative",
8553
- getBubbleCornerClasses(),
8621
+ getBubbleCornerClasses(isSender),
8554
8622
  resolvedSurface === "sent" && "chat-bubble-sent bg-(--chat-theme) text-white",
8555
8623
  resolvedSurface === "received" && "chat-bubble-received border border-(--chat-border)/60 bg-(--chat-incoming-bubble) text-(--chat-incoming-text)",
8556
8624
  isNeutral && "chat-bubble-received border border-(--chat-border)/60 bg-(--chat-incoming-bubble) text-(--chat-incoming-text)",
@@ -8848,7 +8916,7 @@ function MessageAttachmentsCaptionBar({
8848
8916
  onCancelEdit
8849
8917
  }) {
8850
8918
  if (isStandaloneMetaOnly) {
8851
- return /* @__PURE__ */ jsx("div", { className: "flex justify-end pt-0.5", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5", children: [
8919
+ return /* @__PURE__ */ jsx("div", { className: "flex justify-end pt-1.5 pb-0.5", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5", children: [
8852
8920
  /* @__PURE__ */ jsx(
8853
8921
  MessageCornerBadges,
8854
8922
  {
@@ -10059,6 +10127,8 @@ function FileAttachmentRow({
10059
10127
  }
10060
10128
  window.open(fileUrl, "_blank", "noopener,noreferrer");
10061
10129
  };
10130
+ const onThemeBubble = inBubble && isSender;
10131
+ const onIncomingBubble = inBubble && !isSender;
10062
10132
  return /* @__PURE__ */ jsxs(
10063
10133
  "div",
10064
10134
  {
@@ -10066,8 +10136,11 @@ function FileAttachmentRow({
10066
10136
  "group w-full transition-opacity",
10067
10137
  !stacked && "flex min-w-[220px] items-center gap-2",
10068
10138
  stacked && "py-1.5",
10069
- stacked && showDivider && (inBubble && isSender ? "border-t border-white/15" : "border-t border-(--chat-border)/35"),
10070
- !stacked && !inBubble && "rounded-2xl border border-(--chat-border) bg-(--chat-surface) p-2 shadow-sm",
10139
+ stacked && showDivider && (onThemeBubble ? "border-t border-white/15" : "border-t border-(--chat-border)/35"),
10140
+ !stacked && "rounded-xl border p-2.5",
10141
+ !stacked && onThemeBubble && "border-white/20 bg-white/12 text-white shadow-[inset_0_1px_0_rgba(255,255,255,0.08)] backdrop-blur-[2px]",
10142
+ !stacked && onIncomingBubble && "border-(--chat-border)/70 bg-(--chat-elevated) text-(--chat-text) shadow-sm [.dark_&]:bg-(--chat-surface)",
10143
+ !stacked && !inBubble && "border-(--chat-border) bg-(--chat-surface) shadow-sm",
10071
10144
  !fileUrl && "pointer-events-none opacity-60",
10072
10145
  isCaptionActive && "opacity-90"
10073
10146
  ),
@@ -10079,36 +10152,31 @@ function FileAttachmentRow({
10079
10152
  type: "button",
10080
10153
  onClick: handleFileOpen,
10081
10154
  disabled: !fileUrl || selectionMode,
10082
- className: "flex min-w-0 flex-1 items-center gap-2 text-left disabled:cursor-default",
10155
+ className: "flex min-w-0 flex-1 items-center gap-2.5 text-left disabled:cursor-default",
10083
10156
  children: [
10084
10157
  /* @__PURE__ */ jsx("div", { className: cn(
10085
- "flex shrink-0 items-center justify-center rounded-lg text-white",
10086
- stacked ? "size-9" : "size-10 rounded-xl shadow-sm",
10158
+ "flex size-10 shrink-0 items-center justify-center rounded-lg text-white shadow-sm",
10087
10159
  getAttachmentIconBoxClass(rawName)
10088
- ), children: getAttachmentIcon(rawName, "file", "text-white", stacked ? 18 : 20) }),
10160
+ ), children: getAttachmentIcon(rawName, "file", "text-white", 18) }),
10089
10161
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
10090
10162
  /* @__PURE__ */ jsx("span", { className: cn(
10091
- "block truncate text-xs font-medium leading-tight",
10092
- inBubble && isSender ? "text-white" : "text-(--chat-text)"
10163
+ "block truncate text-[12px] font-semibold leading-tight",
10164
+ onThemeBubble ? "text-white" : "text-(--chat-text)"
10093
10165
  ), children: displayName }),
10094
10166
  /* @__PURE__ */ jsx("span", { className: cn(
10095
- "mt-0.5 block truncate text-[10px] leading-tight uppercase",
10096
- inBubble && isSender ? "text-white/60" : "text-(--chat-muted)"
10167
+ "mt-0.5 block truncate text-[10px] font-medium leading-tight uppercase tracking-wide",
10168
+ onThemeBubble ? "text-white/70" : "text-(--chat-muted)"
10097
10169
  ), children: subtitle })
10098
10170
  ] }),
10099
10171
  /* @__PURE__ */ jsx(
10100
10172
  "span",
10101
10173
  {
10102
10174
  className: cn(
10103
- "flex shrink-0 items-center justify-center transition-colors",
10104
- stacked ? "size-6 text-(--chat-muted) group-hover:text-(--chat-theme)" : cn(
10105
- "size-7 rounded-lg border",
10106
- 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)"
10107
- ),
10108
- stacked && inBubble && isSender && "text-white/70 group-hover:text-white"
10175
+ "flex size-8 shrink-0 items-center justify-center rounded-full transition-colors",
10176
+ 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)"
10109
10177
  ),
10110
10178
  "aria-hidden": true,
10111
- children: /* @__PURE__ */ jsx(Eye, { size: stacked ? 13 : 14 })
10179
+ children: /* @__PURE__ */ jsx(Eye, { size: 14 })
10112
10180
  }
10113
10181
  )
10114
10182
  ]
@@ -10119,13 +10187,13 @@ function FileAttachmentRow({
10119
10187
  {
10120
10188
  onClick: onEditCaption,
10121
10189
  label: `${attachmentCaption ? "Edit" : "Add"} caption for ${displayName}`,
10122
- className: inBubble && isSender ? "text-white/60 hover:text-white" : void 0
10190
+ className: onThemeBubble ? "text-white/60 hover:text-white" : void 0
10123
10191
  }
10124
10192
  )
10125
10193
  ] }),
10126
10194
  stacked && attachmentCaption ? /* @__PURE__ */ jsx("p", { className: cn(
10127
- "mt-1 whitespace-pre-wrap break-words pl-11 pr-7 text-[11px] leading-snug",
10128
- inBubble && isSender ? "text-white/85" : "text-(--chat-text-secondary)"
10195
+ "mt-1 whitespace-pre-wrap break-words pl-12 pr-8 text-[11px] leading-snug",
10196
+ onThemeBubble ? "text-white/85" : "text-(--chat-text-secondary)"
10129
10197
  ), children: attachmentCaption }) : null
10130
10198
  ]
10131
10199
  }
@@ -10244,17 +10312,30 @@ function MessageAttachmentsNonImageSection({
10244
10312
  att.id
10245
10313
  );
10246
10314
  };
10247
- return /* @__PURE__ */ jsx(Fragment, { children: nonImageGroups.map((group) => {
10315
+ return /* @__PURE__ */ jsx("div", { className: "flex w-full flex-col gap-1.5", children: nonImageGroups.map((group) => {
10248
10316
  if (group.kind === "file-run") {
10249
10317
  if (group.items.length === 1) {
10250
10318
  return renderFileAttachmentFrame(group.items[0]);
10251
10319
  }
10252
- return /* @__PURE__ */ jsx("div", { className: "w-full min-w-[220px]", children: group.items.map(
10253
- (att2, index) => renderFileAttachmentFrame(att2, {
10254
- stacked: true,
10255
- showDivider: index > 0
10256
- })
10257
- ) }, `file-run-${group.items.map((item) => item.id).join("-")}`);
10320
+ return /* @__PURE__ */ jsx(
10321
+ "div",
10322
+ {
10323
+ className: cn(
10324
+ "w-full min-w-[220px]",
10325
+ isBubbleLayout && "rounded-xl border p-2",
10326
+ isBubbleLayout && isSender && "border-white/20 bg-white/12 shadow-[inset_0_1px_0_rgba(255,255,255,0.08)] backdrop-blur-[2px]",
10327
+ isBubbleLayout && !isSender && "border-(--chat-border)/70 bg-(--chat-elevated) shadow-sm [.dark_&]:bg-(--chat-surface)",
10328
+ !isBubbleLayout && "rounded-xl border border-(--chat-border) bg-(--chat-surface) p-2 shadow-sm"
10329
+ ),
10330
+ children: group.items.map(
10331
+ (att2, index) => renderFileAttachmentFrame(att2, {
10332
+ stacked: true,
10333
+ showDivider: index > 0
10334
+ })
10335
+ )
10336
+ },
10337
+ `file-run-${group.items.map((item) => item.id).join("-")}`
10338
+ );
10258
10339
  }
10259
10340
  const att = group.item;
10260
10341
  const type = resolveAttachmentType(att);
@@ -10327,7 +10408,8 @@ function MessageAttachmentsView({
10327
10408
  isGroupedWithPrev = false,
10328
10409
  isGroupedWithNext = false,
10329
10410
  showSenderLabel = false,
10330
- senderName
10411
+ senderName,
10412
+ senderId
10331
10413
  }) {
10332
10414
  const [documentPreview, setDocumentPreview] = useState(null);
10333
10415
  const visibleAttachments = getVisibleAttachments(attachments);
@@ -10368,7 +10450,10 @@ function MessageAttachmentsView({
10368
10450
  isSender,
10369
10451
  surface: bubbleSurface,
10370
10452
  className: cn(
10371
- isImageOnlyBubble ? "overflow-hidden p-0" : isForwarded || canShowSenderName ? "px-2 py-0.5" : "px-2.5 py-1"
10453
+ isImageOnlyBubble ? "overflow-hidden p-0" : isForwarded || canShowSenderName ? "px-2 py-1" : cn(
10454
+ "px-2.5",
10455
+ nonImages.length > 1 || images.length > 0 && nonImages.length > 0 ? "py-1.5" : "py-1"
10456
+ )
10372
10457
  )
10373
10458
  })
10374
10459
  ),
@@ -10381,7 +10466,13 @@ function MessageAttachmentsView({
10381
10466
  isImageOnlyBubble ? "px-2.5 pt-1.5 pb-1" : "px-0.5 pb-0.5"
10382
10467
  ),
10383
10468
  children: [
10384
- canShowSenderName ? /* @__PURE__ */ jsx(GroupSenderName, { name: senderName }) : null,
10469
+ canShowSenderName ? /* @__PURE__ */ jsx(
10470
+ GroupSenderName,
10471
+ {
10472
+ name: senderName,
10473
+ colorSeed: senderId || senderName
10474
+ }
10475
+ ) : null,
10385
10476
  showForwardedInHeader ? /* @__PURE__ */ jsx(
10386
10477
  MessageForwardedLabel,
10387
10478
  {
@@ -10395,7 +10486,7 @@ function MessageAttachmentsView({
10395
10486
  isBubbleLayout && replySnippet ? /* @__PURE__ */ jsx("div", { className: "px-2 pb-1", children: replySnippet }) : null,
10396
10487
  /* @__PURE__ */ jsxs("div", { className: cn(
10397
10488
  "flex w-full flex-col",
10398
- !isImageOnlyBubble && "gap-0",
10489
+ !isImageOnlyBubble && (images.length > 0 && nonImages.length > 0 ? "gap-1.5" : "gap-0"),
10399
10490
  isImageOnlyBubble && "relative overflow-hidden"
10400
10491
  ), children: [
10401
10492
  /* @__PURE__ */ jsx(
@@ -10925,7 +11016,7 @@ function collectConversationAttachments(messages) {
10925
11016
  const items = [];
10926
11017
  for (const message of messages) {
10927
11018
  if (message?.isDeletedForEveryone) continue;
10928
- const messageId = String(message._id || message.id || "");
11019
+ const messageId2 = String(message._id || message.id || "");
10929
11020
  const createdAt = message.createdAt || message.timestamp;
10930
11021
  const messageType = message.type || "text";
10931
11022
  for (const attachment of message.attachments || []) {
@@ -10943,13 +11034,35 @@ function collectConversationAttachments(messages) {
10943
11034
  url,
10944
11035
  name,
10945
11036
  type: resolveFileCategory(name, fileType, resolvedType),
10946
- messageId,
11037
+ messageId: messageId2,
10947
11038
  createdAt,
10948
11039
  size: typeof attachment.size === "number" ? attachment.size : void 0,
10949
11040
  duration: typeof attachment.duration === "number" ? attachment.duration : void 0,
10950
11041
  fileType
10951
11042
  });
10952
11043
  }
11044
+ if ((message.attachments || []).length === 0) {
11045
+ const rootUrl = message.url || message.fileUrl || message.attachmentUrl || message.public_link || message.publicLink || "";
11046
+ if (!rootUrl) continue;
11047
+ const name = message.filename || message.fileName || message.name || "Attachment";
11048
+ const fileType = message.fileType || message.mimeType || "";
11049
+ const dedupeKey = `${rootUrl}|${name}`;
11050
+ if (seen.has(dedupeKey)) continue;
11051
+ seen.add(dedupeKey);
11052
+ const baseType = inferAttachmentType(fileType, name);
11053
+ const resolvedType = messageType === "image" && baseType === "file" ? "image" : baseType;
11054
+ items.push({
11055
+ id: String(message.attachmentId || message.fileId || dedupeKey),
11056
+ url: rootUrl,
11057
+ name,
11058
+ type: resolveFileCategory(name, fileType, resolvedType),
11059
+ messageId: messageId2,
11060
+ createdAt,
11061
+ size: typeof message.size === "number" ? message.size : void 0,
11062
+ duration: typeof message.duration === "number" ? message.duration : void 0,
11063
+ fileType
11064
+ });
11065
+ }
10953
11066
  }
10954
11067
  return items.sort(
10955
11068
  (a, b) => new Date(b.createdAt || 0).getTime() - new Date(a.createdAt || 0).getTime()
@@ -11160,9 +11273,13 @@ function AttachmentSection({
11160
11273
  }
11161
11274
  var AttachmentsDrawer = ({ isOpen, onOpenChange, conversationId }) => {
11162
11275
  const messagesByConversation = useStore((s) => s.messagesByConversation);
11276
+ const messagesMetadata = useStore((s) => s.messagesMetadata);
11277
+ const fetchMessages2 = useStore((s) => s.fetchMessages);
11163
11278
  const [sectionVisibleCount, setSectionVisibleCount] = useState({});
11164
11279
  const [documentPreview, setDocumentPreview] = useState(null);
11165
11280
  const [imageLightboxIndex, setImageLightboxIndex] = useState(null);
11281
+ const hasLoadedMessages = conversationId ? Boolean(messagesMetadata[conversationId]?.isFirstPage) : false;
11282
+ const isLoading = isOpen && !!conversationId && !hasLoadedMessages;
11166
11283
  useEffect(() => {
11167
11284
  if (!isOpen) {
11168
11285
  setSectionVisibleCount({});
@@ -11173,6 +11290,10 @@ var AttachmentsDrawer = ({ isOpen, onOpenChange, conversationId }) => {
11173
11290
  useEffect(() => {
11174
11291
  setSectionVisibleCount({});
11175
11292
  }, [conversationId]);
11293
+ useEffect(() => {
11294
+ if (!isOpen || !conversationId || hasLoadedMessages) return;
11295
+ fetchMessages2(conversationId);
11296
+ }, [isOpen, conversationId, hasLoadedMessages, fetchMessages2]);
11176
11297
  const attachments = useMemo(() => {
11177
11298
  if (!conversationId) return [];
11178
11299
  const messages = messagesByConversation[conversationId] || [];
@@ -11224,7 +11345,11 @@ var AttachmentsDrawer = ({ isOpen, onOpenChange, conversationId }) => {
11224
11345
  ] }),
11225
11346
  /* @__PURE__ */ jsx("p", { className: "mt-1 text-[11px] text-(--chat-muted)", children: "Shared media and files" })
11226
11347
  ] }) }),
11227
- /* @__PURE__ */ 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__ */ jsxs("div", { className: "chat-saved-empty flex min-h-[220px] flex-col items-center justify-center px-4 text-center", children: [
11348
+ /* @__PURE__ */ jsx("div", { className: "chat-message-scroll flex-1 overflow-y-auto bg-(--chat-main-bg) px-2.5 py-2", children: isLoading ? /* @__PURE__ */ jsxs("div", { className: "flex min-h-[220px] flex-col items-center justify-center px-4 text-center", children: [
11349
+ /* @__PURE__ */ jsx(Loader2, { className: "mb-3 size-8 animate-spin text-(--chat-theme)" }),
11350
+ /* @__PURE__ */ jsx("p", { className: "text-[13px] font-medium text-(--chat-text)", children: "Loading attachments..." }),
11351
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-[11px] text-(--chat-muted)", children: "Fetching shared files for this chat" })
11352
+ ] }) : attachments.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "chat-saved-empty flex min-h-[220px] flex-col items-center justify-center px-4 text-center", children: [
11228
11353
  /* @__PURE__ */ jsx("div", { className: "mb-3", children: /* @__PURE__ */ jsx("div", { className: "chat-saved-empty-icon-wrap", children: /* @__PURE__ */ jsx(Paperclip, { size: 22, className: cn("chat-saved-empty-icon !text-(--chat-theme)") }) }) }),
11229
11354
  /* @__PURE__ */ jsx("p", { className: "text-[14px] font-semibold text-(--chat-text)", children: "No attachments" }),
11230
11355
  /* @__PURE__ */ jsx("p", { className: "mt-1.5 max-w-[240px] text-[12px] leading-relaxed text-(--chat-muted)", children: "Shared files will show up here." })
@@ -11607,7 +11732,7 @@ var ChannelDetailsDrawer = (props) => {
11607
11732
  {
11608
11733
  type: "button",
11609
11734
  onClick: () => fileInputRef.current?.click(),
11610
- 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)",
11735
+ 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)",
11611
11736
  title: "Change group avatar",
11612
11737
  children: /* @__PURE__ */ jsx(Camera, { size: 12 })
11613
11738
  }
@@ -11646,7 +11771,7 @@ var ChannelDetailsDrawer = (props) => {
11646
11771
  {
11647
11772
  variant: "outline",
11648
11773
  size: "sm",
11649
- className: "h-8 flex-1 text-[12px]",
11774
+ className: "h-8 flex-1 border-(--chat-border) bg-(--chat-surface) text-[12px] text-(--chat-text) hover:bg-(--chat-hover)",
11650
11775
  onClick: () => setIsEditing(false),
11651
11776
  children: [
11652
11777
  /* @__PURE__ */ jsx(X, { className: "mr-1 size-3" }),
@@ -11658,7 +11783,7 @@ var ChannelDetailsDrawer = (props) => {
11658
11783
  Button,
11659
11784
  {
11660
11785
  size: "sm",
11661
- className: "h-8 flex-1 text-[12px]",
11786
+ className: "h-8 flex-1 border border-(--chat-theme) bg-(--chat-theme) text-[12px] text-white hover:opacity-90 disabled:opacity-50",
11662
11787
  onClick: handleSave,
11663
11788
  disabled: isSaving || imageUploadStatus === "uploading",
11664
11789
  children: isSaving ? /* @__PURE__ */ jsx(Loader2, { className: "size-3 animate-spin" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -11676,7 +11801,7 @@ var ChannelDetailsDrawer = (props) => {
11676
11801
  {
11677
11802
  variant: "ghost",
11678
11803
  size: "sm",
11679
- className: "mt-2 h-7 gap-1 px-2 text-[11px] text-(--chat-muted) hover:text-(--chat-text)",
11804
+ className: "mt-2 h-7 gap-1 px-2 text-[11px] text-(--chat-theme) hover:bg-(--chat-theme-10) hover:text-(--chat-theme)",
11680
11805
  onClick: () => setIsEditing(true),
11681
11806
  children: [
11682
11807
  /* @__PURE__ */ jsx(Pencil, { className: "size-3" }),
@@ -12534,8 +12659,8 @@ function useChannelHeader({
12534
12659
  }
12535
12660
  }
12536
12661
  };
12537
- const handleSelectSearchResult = async (messageId) => {
12538
- await fetchSearchMessageContext(messageId);
12662
+ const handleSelectSearchResult = async (messageId2) => {
12663
+ await fetchSearchMessageContext(messageId2);
12539
12664
  handleCloseSearch();
12540
12665
  };
12541
12666
  const handleSearchOpenChange = (open) => {
@@ -12571,6 +12696,14 @@ function useChannelHeader({
12571
12696
  fetchStarredMessages2(conversationId);
12572
12697
  }
12573
12698
  }, [state.isFavoriteOpen, conversationId, fetchStarredMessages2]);
12699
+ useEffect(() => {
12700
+ if (state.isAttachmentsOpen && conversationId) {
12701
+ const meta = useStore.getState().messagesMetadata[conversationId];
12702
+ if (!meta?.isFirstPage) {
12703
+ fetchMessagesStore(conversationId);
12704
+ }
12705
+ }
12706
+ }, [state.isAttachmentsOpen, conversationId, fetchMessagesStore]);
12574
12707
  const pinnedCount = liveCounts?.pinnedCount ?? activeChannel?.pinnedCount ?? 0;
12575
12708
  const starredCount = liveCounts?.starredCount ?? activeChannel?.starredCount ?? 0;
12576
12709
  const handleClearChat = () => {
@@ -12616,14 +12749,14 @@ function useChannelHeader({
12616
12749
  updateState({ isBlockAlertOpen: false });
12617
12750
  }
12618
12751
  };
12619
- const handleUnpin = (messageId, attachmentId) => {
12752
+ const handleUnpin = (messageId2, attachmentId) => {
12620
12753
  if (!loggedUserDetails?._id || !conversationId || !activeChannel) return;
12621
- const loadingKey = attachmentId ? `${messageId}:${attachmentId}` : messageId;
12754
+ const loadingKey = attachmentId ? `${messageId2}:${attachmentId}` : messageId2;
12622
12755
  updateState({ loadingIds: new Set(state.loadingIds).add(loadingKey) });
12623
12756
  const basePayload = {
12624
12757
  conversationId,
12625
12758
  sender: loggedUserDetails._id,
12626
- messageId,
12759
+ messageId: messageId2,
12627
12760
  receiver: activeChannel.id,
12628
12761
  ...attachmentId ? { attachmentId } : {}
12629
12762
  };
@@ -12643,12 +12776,12 @@ function useChannelHeader({
12643
12776
  if (!dateStr) return "";
12644
12777
  return formatLongDate(dateStr);
12645
12778
  };
12646
- const handleUnstar = (messageId, attachmentId) => {
12779
+ const handleUnstar = (messageId2, attachmentId) => {
12647
12780
  if (!loggedUserDetails?._id || !conversationId || !activeChannel) return;
12648
- const loadingKey = attachmentId ? `${messageId}:${attachmentId}` : messageId;
12781
+ const loadingKey = attachmentId ? `${messageId2}:${attachmentId}` : messageId2;
12649
12782
  updateState({ loadingIds: new Set(state.loadingIds).add(loadingKey) });
12650
12783
  const basePayload = {
12651
- messageId,
12784
+ messageId: messageId2,
12652
12785
  sender: loggedUserDetails._id,
12653
12786
  conversationId,
12654
12787
  receiver: activeChannel.id,
@@ -12918,7 +13051,7 @@ var MessageReactions = ({
12918
13051
  {
12919
13052
  onClick: () => onReactionClick(emoji),
12920
13053
  className: cn(
12921
- "flex items-center gap-1 px-2 py-0.5 rounded-full text-xs border shadow-sm transition-all shadow-black/5 outline-none",
13054
+ "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",
12922
13055
  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)"
12923
13056
  ),
12924
13057
  children: [
@@ -12972,7 +13105,7 @@ var MessageToolbar = ({
12972
13105
  "div",
12973
13106
  {
12974
13107
  className: cn(
12975
- "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",
13108
+ "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",
12976
13109
  "bg-(--chat-toolbar-bg) text-(--chat-text)",
12977
13110
  isSender ? "right-0" : "left-0"
12978
13111
  ),
@@ -13248,8 +13381,8 @@ init_useStore();
13248
13381
 
13249
13382
  // src/chat/lib/chat-selection.ts
13250
13383
  init_attachment_helpers();
13251
- function buildSelectionKey(messageId, attachmentId) {
13252
- return pinKey(messageId, attachmentId || null);
13384
+ function buildSelectionKey(messageId2, attachmentId) {
13385
+ return pinKey(messageId2, attachmentId || null);
13253
13386
  }
13254
13387
  function parseSelectionKey(key) {
13255
13388
  const colonIndex = key.indexOf(":");
@@ -13264,8 +13397,8 @@ function parseSelectionKey(key) {
13264
13397
  function messageUsesAttachmentSelection(message) {
13265
13398
  return getVisibleAttachments(message.attachments).length > 1;
13266
13399
  }
13267
- function getSelectedAttachmentIdsForMessage(selectedKeys, messageId) {
13268
- const prefix = `${messageId}:`;
13400
+ function getSelectedAttachmentIdsForMessage(selectedKeys, messageId2) {
13401
+ const prefix = `${messageId2}:`;
13269
13402
  const ids = /* @__PURE__ */ new Set();
13270
13403
  selectedKeys.forEach((key) => {
13271
13404
  if (key.startsWith(prefix)) {
@@ -13274,14 +13407,14 @@ function getSelectedAttachmentIdsForMessage(selectedKeys, messageId) {
13274
13407
  });
13275
13408
  return ids;
13276
13409
  }
13277
- function isMessageWhollySelected(selectedKeys, messageId) {
13278
- return selectedKeys.has(messageId);
13410
+ function isMessageWhollySelected(selectedKeys, messageId2) {
13411
+ return selectedKeys.has(messageId2);
13279
13412
  }
13280
13413
  function resolveForwardItems(selectedKeys, messages) {
13281
13414
  const items = [];
13282
13415
  selectedKeys.forEach((key) => {
13283
- const { messageId, attachmentId } = parseSelectionKey(key);
13284
- const message = messages.find((entry) => String(entry._id || entry.id) === messageId);
13416
+ const { messageId: messageId2, attachmentId } = parseSelectionKey(key);
13417
+ const message = messages.find((entry) => String(entry._id || entry.id) === messageId2);
13285
13418
  if (!message) return;
13286
13419
  items.push({ message, attachmentId });
13287
13420
  });
@@ -13307,7 +13440,7 @@ function useMessageItemActions({
13307
13440
  message,
13308
13441
  createdAt,
13309
13442
  attachments,
13310
- messageId,
13443
+ messageId: messageId2,
13311
13444
  receiver,
13312
13445
  isDeletedForEveryone,
13313
13446
  reactions,
@@ -13359,10 +13492,10 @@ function useMessageItemActions({
13359
13492
  const allUsers = useStore((s) => s.allUsers);
13360
13493
  const loggedUserDetails = useStore((s) => s.loggedUserDetails);
13361
13494
  const pinnedMessagesByConversation = useStore((s) => s.pinnedMessagesByConversation);
13362
- const mid = String(messageId || "");
13495
+ const mid = String(messageId2 || "");
13363
13496
  const pendingActions = mid ? messagePendingActions[mid] || [] : [];
13364
13497
  const isPending = Boolean(
13365
- isSender && (String(messageId || "").startsWith("temp-") || mid && (messagePendingActions[mid] || []).includes("send"))
13498
+ isSender && (String(messageId2 || "").startsWith("temp-") || mid && (messagePendingActions[mid] || []).includes("send"))
13366
13499
  );
13367
13500
  const isEditPending = pendingActions.includes("edit");
13368
13501
  const isDeletePending = pendingActions.includes("delete");
@@ -13400,13 +13533,13 @@ function useMessageItemActions({
13400
13533
  };
13401
13534
  const handleSaveAttachmentCaption = (caption, attachment) => {
13402
13535
  const target = attachment ?? state.captionModalAttachment;
13403
- if (!messageId || !loggedUserDetails || !target) return;
13536
+ if (!messageId2 || !loggedUserDetails || !target) return;
13404
13537
  const attachmentId = target.id;
13405
13538
  if (isGroup) {
13406
13539
  if (!conversationId) return;
13407
13540
  emitGroupEdit({
13408
13541
  content: caption,
13409
- messageId,
13542
+ messageId: messageId2,
13410
13543
  sender: loggedUserDetails._id,
13411
13544
  conversationId,
13412
13545
  attachmentId
@@ -13415,7 +13548,7 @@ function useMessageItemActions({
13415
13548
  if (!receiver) return;
13416
13549
  emitDmEdit({
13417
13550
  content: caption,
13418
- messageId,
13551
+ messageId: messageId2,
13419
13552
  sender: loggedUserDetails._id,
13420
13553
  receiver,
13421
13554
  attachmentId
@@ -13432,12 +13565,12 @@ function useMessageItemActions({
13432
13565
  onEnterSelectionMode?.();
13433
13566
  };
13434
13567
  const handleSaveEdit = () => {
13435
- if (!messageId || !loggedUserDetails) return;
13568
+ if (!messageId2 || !loggedUserDetails) return;
13436
13569
  if (isGroup) {
13437
13570
  if (!conversationId) return;
13438
13571
  emitGroupEdit({
13439
13572
  content: state.editValue.trim(),
13440
- messageId,
13573
+ messageId: messageId2,
13441
13574
  sender: loggedUserDetails._id,
13442
13575
  conversationId
13443
13576
  });
@@ -13445,7 +13578,7 @@ function useMessageItemActions({
13445
13578
  if (!receiver) return;
13446
13579
  emitDmEdit({
13447
13580
  content: state.editValue.trim(),
13448
- messageId,
13581
+ messageId: messageId2,
13449
13582
  sender: loggedUserDetails._id,
13450
13583
  receiver
13451
13584
  });
@@ -13456,7 +13589,7 @@ function useMessageItemActions({
13456
13589
  updateState({ isEditing: false, editValue: message });
13457
13590
  };
13458
13591
  const handleDeleteMessage = (deleteType) => {
13459
- if (!messageId || !loggedUserDetails) return;
13592
+ if (!messageId2 || !loggedUserDetails) return;
13460
13593
  if (deleteType === "everyone" && !isSender) return;
13461
13594
  if (deleteType === "everyone" && !isWithinEditWindow()) return;
13462
13595
  const attachmentIds = hasAttachments ? deleteAttachmentIds : [];
@@ -13464,7 +13597,7 @@ function useMessageItemActions({
13464
13597
  if (isGroup) {
13465
13598
  if (!conversationId) return;
13466
13599
  emitGroupDelete({
13467
- messageId,
13600
+ messageId: messageId2,
13468
13601
  sender: loggedUserDetails._id,
13469
13602
  deleteType,
13470
13603
  conversationId,
@@ -13473,7 +13606,7 @@ function useMessageItemActions({
13473
13606
  } else {
13474
13607
  if (!receiver) return;
13475
13608
  emitDmDelete({
13476
- messageId,
13609
+ messageId: messageId2,
13477
13610
  sender: loggedUserDetails._id,
13478
13611
  receiver,
13479
13612
  deleteType,
@@ -13495,7 +13628,7 @@ function useMessageItemActions({
13495
13628
  onForward?.();
13496
13629
  };
13497
13630
  const handleReactionClick = (emojiObject) => {
13498
- if (!messageId || !loggedUserDetails) return;
13631
+ if (!messageId2 || !loggedUserDetails) return;
13499
13632
  const reaction = typeof emojiObject === "string" ? emojiObject : emojiObject.emoji || emojiObject.native;
13500
13633
  const hasReacted = reactions?.some(
13501
13634
  (r) => r.reaction === reaction && String(r.addedBy?._id || r.addedBy || r.sender?._id || r.sender) === String(loggedUserDetails._id)
@@ -13504,7 +13637,7 @@ function useMessageItemActions({
13504
13637
  if (isGroup) {
13505
13638
  if (!conversationId) return;
13506
13639
  emitGroupReactionRemove({
13507
- messageId,
13640
+ messageId: messageId2,
13508
13641
  sender: loggedUserDetails._id,
13509
13642
  reaction,
13510
13643
  conversationId
@@ -13512,7 +13645,7 @@ function useMessageItemActions({
13512
13645
  } else {
13513
13646
  if (!receiver) return;
13514
13647
  emitDmReactionRemove({
13515
- messageId,
13648
+ messageId: messageId2,
13516
13649
  sender: loggedUserDetails._id,
13517
13650
  receiver,
13518
13651
  reaction,
@@ -13523,7 +13656,7 @@ function useMessageItemActions({
13523
13656
  if (isGroup) {
13524
13657
  if (!conversationId) return;
13525
13658
  emitGroupReactionAdd({
13526
- messageId,
13659
+ messageId: messageId2,
13527
13660
  sender: loggedUserDetails._id,
13528
13661
  reaction,
13529
13662
  conversationId
@@ -13531,7 +13664,7 @@ function useMessageItemActions({
13531
13664
  } else {
13532
13665
  if (!receiver) return;
13533
13666
  emitDmReactionAdd({
13534
- messageId,
13667
+ messageId: messageId2,
13535
13668
  sender: loggedUserDetails._id,
13536
13669
  receiver,
13537
13670
  reaction,
@@ -13541,7 +13674,7 @@ function useMessageItemActions({
13541
13674
  }
13542
13675
  };
13543
13676
  const handlePinClick = () => {
13544
- if (!messageId || !loggedUserDetails) return;
13677
+ if (!messageId2 || !loggedUserDetails) return;
13545
13678
  if (isPinned) {
13546
13679
  if (!isPinnedByMe) return;
13547
13680
  if (isGroup) {
@@ -13549,14 +13682,14 @@ function useMessageItemActions({
13549
13682
  emitGroupUnpin({
13550
13683
  conversationId,
13551
13684
  sender: loggedUserDetails._id,
13552
- messageId,
13685
+ messageId: messageId2,
13553
13686
  receiver: ""
13554
13687
  });
13555
13688
  } else {
13556
13689
  emitDmUnpin({
13557
13690
  conversationId,
13558
13691
  sender: loggedUserDetails._id,
13559
- messageId,
13692
+ messageId: messageId2,
13560
13693
  receiver: receiver || ""
13561
13694
  });
13562
13695
  }
@@ -13566,32 +13699,32 @@ function useMessageItemActions({
13566
13699
  emitGroupPin({
13567
13700
  conversationId,
13568
13701
  sender: loggedUserDetails._id,
13569
- messageId,
13702
+ messageId: messageId2,
13570
13703
  receiver: ""
13571
13704
  });
13572
13705
  } else {
13573
13706
  emitDmPin({
13574
13707
  conversationId,
13575
13708
  sender: loggedUserDetails._id,
13576
- messageId,
13709
+ messageId: messageId2,
13577
13710
  receiver: receiver || ""
13578
13711
  });
13579
13712
  }
13580
13713
  }
13581
13714
  };
13582
13715
  const handleStarClick = () => {
13583
- if (!messageId || !loggedUserDetails || !conversationId) return;
13716
+ if (!messageId2 || !loggedUserDetails || !conversationId) return;
13584
13717
  if (isStarred) {
13585
13718
  if (isGroup) {
13586
- emitGroupUnstar({ messageId, sender: loggedUserDetails._id, conversationId });
13719
+ emitGroupUnstar({ messageId: messageId2, sender: loggedUserDetails._id, conversationId });
13587
13720
  } else {
13588
- emitDmUnstar({ messageId, sender: loggedUserDetails._id, conversationId });
13721
+ emitDmUnstar({ messageId: messageId2, sender: loggedUserDetails._id, conversationId });
13589
13722
  }
13590
13723
  } else {
13591
13724
  if (isGroup) {
13592
- emitGroupStar({ messageId, sender: loggedUserDetails._id, conversationId });
13725
+ emitGroupStar({ messageId: messageId2, sender: loggedUserDetails._id, conversationId });
13593
13726
  } else {
13594
- emitDmStar({ messageId, sender: loggedUserDetails._id, conversationId });
13727
+ emitDmStar({ messageId: messageId2, sender: loggedUserDetails._id, conversationId });
13595
13728
  }
13596
13729
  }
13597
13730
  };
@@ -13813,6 +13946,7 @@ function MessageItemTextBubble({
13813
13946
  isForwarded,
13814
13947
  showSenderLabel,
13815
13948
  senderName,
13949
+ senderId,
13816
13950
  replyTo,
13817
13951
  loggedUserDetails,
13818
13952
  allUsers,
@@ -13851,7 +13985,13 @@ function MessageItemTextBubble({
13851
13985
  ),
13852
13986
  children: [
13853
13987
  (canShowSenderName || isForwarded) && /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [
13854
- canShowSenderName ? /* @__PURE__ */ jsx(GroupSenderName, { name: senderName }) : null,
13988
+ canShowSenderName ? /* @__PURE__ */ jsx(
13989
+ GroupSenderName,
13990
+ {
13991
+ name: senderName,
13992
+ colorSeed: senderId || senderName
13993
+ }
13994
+ ) : null,
13855
13995
  isForwarded ? /* @__PURE__ */ jsx(MessageForwardedLabel, { isSender, className: "px-0 pt-0 pb-0" }) : null
13856
13996
  ] }),
13857
13997
  /* @__PURE__ */ jsx(
@@ -13902,7 +14042,7 @@ function MessageItemTextBubble({
13902
14042
  }
13903
14043
  )
13904
14044
  ] })
13905
- ] }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
14045
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
13906
14046
  hasText && /* @__PURE__ */ jsxs("p", { className: "whitespace-pre-wrap break-words leading-snug", children: [
13907
14047
  message,
13908
14048
  isEdited && /* @__PURE__ */ jsx(
@@ -13960,6 +14100,7 @@ function MessageItemAttachmentBubble({
13960
14100
  isGroupedWithNext,
13961
14101
  showSenderLabel,
13962
14102
  senderName,
14103
+ senderId,
13963
14104
  formattedTime,
13964
14105
  status,
13965
14106
  isPending,
@@ -14008,6 +14149,7 @@ function MessageItemAttachmentBubble({
14008
14149
  isGroupedWithNext,
14009
14150
  showSenderLabel,
14010
14151
  senderName,
14152
+ senderId,
14011
14153
  formattedTime,
14012
14154
  status,
14013
14155
  isPending,
@@ -14067,6 +14209,7 @@ function MessageItemView(props) {
14067
14209
  isGroup,
14068
14210
  isHighlighted,
14069
14211
  senderName,
14212
+ senderId,
14070
14213
  senderImage,
14071
14214
  showSenderLabel,
14072
14215
  senderAvatarImage,
@@ -14243,6 +14386,7 @@ function MessageItemView(props) {
14243
14386
  isGroupedWithNext,
14244
14387
  showSenderLabel,
14245
14388
  senderName,
14389
+ senderId,
14246
14390
  formattedTime,
14247
14391
  status,
14248
14392
  isPending,
@@ -14284,6 +14428,7 @@ function MessageItemView(props) {
14284
14428
  isForwarded,
14285
14429
  showSenderLabel,
14286
14430
  senderName,
14431
+ senderId,
14287
14432
  replyTo,
14288
14433
  loggedUserDetails,
14289
14434
  allUsers,
@@ -14474,6 +14619,28 @@ function MessageSelectionBar({
14474
14619
 
14475
14620
  // src/chat/active-channel-messages/utils.ts
14476
14621
  var getMessageSenderId2 = (msg) => msg ? String(msg.senderId || msg.sender?._id || "") : "";
14622
+ var isLikelyObjectId = (value) => /^[a-f\d]{24}$/i.test(value);
14623
+ function resolveGroupSenderDisplay(message, allUsers = [], participants = []) {
14624
+ const senderId = getMessageSenderId2(message);
14625
+ if (senderId) {
14626
+ const fromUsers = allUsers.find((user) => String(user._id) === senderId);
14627
+ if (fromUsers?.name?.trim()) {
14628
+ return { name: fromUsers.name.trim(), image: fromUsers.image };
14629
+ }
14630
+ const fromParticipants = participants.find((participant) => {
14631
+ const id = typeof participant === "string" ? participant : participant?._id;
14632
+ return String(id) === senderId;
14633
+ });
14634
+ if (fromParticipants && typeof fromParticipants === "object" && fromParticipants.name?.trim()) {
14635
+ return { name: fromParticipants.name.trim(), image: fromParticipants.image };
14636
+ }
14637
+ }
14638
+ const sender = message.sender;
14639
+ if (typeof sender === "string" && sender.trim() && !isLikelyObjectId(sender.trim())) {
14640
+ return { name: sender.trim(), image: message.senderImage };
14641
+ }
14642
+ return { name: "User", image: void 0 };
14643
+ }
14477
14644
  var isSameMessageSide = (a, b, isGroupChat) => {
14478
14645
  if (!!a.isOwnMessage !== !!b.isOwnMessage) return false;
14479
14646
  if (a.isOwnMessage) return true;
@@ -14487,8 +14654,8 @@ function canDeleteSelectionForEveryone(selectedKeys, messages, isGroup) {
14487
14654
  const parsed = [...selectedKeys].map((key) => parseSelectionKey(key));
14488
14655
  const messageIds = new Set(parsed.map((entry) => entry.messageId));
14489
14656
  if (messageIds.size !== 1) return false;
14490
- const messageId = [...messageIds][0];
14491
- const message = messages.find((entry) => String(entry._id || entry.id) === messageId);
14657
+ const messageId2 = [...messageIds][0];
14658
+ const message = messages.find((entry) => String(entry._id || entry.id) === messageId2);
14492
14659
  if (!message?.isOwnMessage) return false;
14493
14660
  if (!isWithinMessageEditWindow(message.timestamp, isGroup)) return false;
14494
14661
  const hasAttachmentKey = parsed.some((entry) => entry.attachmentId);
@@ -14502,6 +14669,9 @@ function canDeleteSelectionForEveryone(selectedKeys, messages, isGroup) {
14502
14669
  });
14503
14670
  }
14504
14671
 
14672
+ // src/chat/active-channel-messages/ActiveChannelMessagesView.tsx
14673
+ init_useStore();
14674
+
14505
14675
  // src/chat/active-channel-messages/useActiveChannelMessages.ts
14506
14676
  init_useStore();
14507
14677
  init_store_helpers();
@@ -14517,6 +14687,7 @@ function mapApiMessage(m, activeChannel, conversationId, loggedUserId, activeCon
14517
14687
  content: m.content,
14518
14688
  sender: m.sender?.name || "User",
14519
14689
  senderId: String(m.sender?._id || m.sender || ""),
14690
+ senderImage: m.sender?.image,
14520
14691
  receiver: activeChannel?.id,
14521
14692
  timestamp: m.createdAt,
14522
14693
  isOwnMessage: isOwn,
@@ -14544,7 +14715,101 @@ function mapApiMessage(m, activeChannel, conversationId, loggedUserId, activeCon
14544
14715
  };
14545
14716
  }
14546
14717
 
14718
+ // src/chat/active-channel-messages/jump-to-date.ts
14719
+ function startOfLocalDay(date) {
14720
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();
14721
+ }
14722
+ function toDateInputValue(date) {
14723
+ const y = date.getFullYear();
14724
+ const m = String(date.getMonth() + 1).padStart(2, "0");
14725
+ const d = String(date.getDate()).padStart(2, "0");
14726
+ return `${y}-${m}-${d}`;
14727
+ }
14728
+ function clampJumpDate(picked, minDay, maxDay) {
14729
+ if (!Number.isFinite(minDay) || !Number.isFinite(maxDay) || minDay > maxDay) return null;
14730
+ const at = startOfLocalDay(picked);
14731
+ const clamped = Math.min(Math.max(at, minDay), maxDay);
14732
+ return new Date(clamped);
14733
+ }
14734
+ function resolveJumpDateBounds(createdAt, oldestMessageTimestamp, now = /* @__PURE__ */ new Date()) {
14735
+ const today = startOfLocalDay(now);
14736
+ const createdDay = createdAt ? startOfLocalDay(new Date(createdAt)) : null;
14737
+ const oldestDay = oldestMessageTimestamp ? startOfLocalDay(new Date(oldestMessageTimestamp)) : null;
14738
+ let minDay = today;
14739
+ if (createdDay != null && oldestDay != null) {
14740
+ minDay = Math.max(createdDay, oldestDay);
14741
+ } else if (oldestDay != null) {
14742
+ minDay = oldestDay;
14743
+ } else if (createdDay != null) {
14744
+ minDay = createdDay;
14745
+ }
14746
+ return { minDay: Math.min(minDay, today), maxDay: today };
14747
+ }
14748
+ function resolveJumpPreset(preset, now = /* @__PURE__ */ new Date()) {
14749
+ const day = new Date(now.getFullYear(), now.getMonth(), now.getDate());
14750
+ if (preset === "today") return day.getTime();
14751
+ if (preset === "yesterday") {
14752
+ day.setDate(day.getDate() - 1);
14753
+ return day.getTime();
14754
+ }
14755
+ if (preset === "lastWeek") {
14756
+ day.setDate(day.getDate() - 7);
14757
+ return day.getTime();
14758
+ }
14759
+ day.setMonth(day.getMonth() - 1);
14760
+ return day.getTime();
14761
+ }
14762
+ function messageId(m) {
14763
+ return String(m._id || m.id);
14764
+ }
14765
+ function findNearestMessageByDay(messages, targetDay) {
14766
+ let best = messages[0];
14767
+ let bestDist = Infinity;
14768
+ let bestDay = startOfLocalDay(new Date(best.timestamp));
14769
+ for (const m of messages) {
14770
+ const day = startOfLocalDay(new Date(m.timestamp));
14771
+ const dist = Math.abs(day - targetDay);
14772
+ if (dist < bestDist || dist === bestDist && day < bestDay) {
14773
+ best = m;
14774
+ bestDist = dist;
14775
+ bestDay = day;
14776
+ }
14777
+ }
14778
+ return best;
14779
+ }
14780
+ function resolveJumpStep(messages, pending, hasMore) {
14781
+ if (messages.length === 0) {
14782
+ return hasMore ? { action: "loadOlder" } : { action: "done" };
14783
+ }
14784
+ if (pending.kind === "beginning") {
14785
+ if (hasMore) return { action: "loadOlder" };
14786
+ return { action: "scroll", messageId: messageId(messages[0]) };
14787
+ }
14788
+ const oldestDay = startOfLocalDay(new Date(messages[0].timestamp));
14789
+ if (hasMore && oldestDay > pending.at) {
14790
+ return { action: "loadOlder" };
14791
+ }
14792
+ const onDay = messages.find(
14793
+ (m) => startOfLocalDay(new Date(m.timestamp)) === pending.at
14794
+ );
14795
+ if (onDay) {
14796
+ return { action: "scroll", messageId: messageId(onDay) };
14797
+ }
14798
+ const nearest = findNearestMessageByDay(messages, pending.at);
14799
+ return { action: "scroll", messageId: messageId(nearest) };
14800
+ }
14801
+ function smoothScrollToMessage(container, messageEl) {
14802
+ const containerRect = container.getBoundingClientRect();
14803
+ const messageRect = messageEl.getBoundingClientRect();
14804
+ const delta = messageRect.top - containerRect.top - Math.min(120, container.clientHeight * 0.25);
14805
+ container.scrollTo({
14806
+ top: Math.max(0, container.scrollTop + delta),
14807
+ behavior: "smooth"
14808
+ });
14809
+ }
14810
+
14547
14811
  // src/chat/active-channel-messages/useActiveChannelMessages.ts
14812
+ var MAX_JUMP_OLDER_PAGES = 40;
14548
14813
  function useActiveChannelMessages({
14549
14814
  activeChannel,
14550
14815
  loggedUserId,
@@ -14567,6 +14832,11 @@ function useActiveChannelMessages({
14567
14832
  const previousMessageCountRef = useRef(0);
14568
14833
  const previousLastMessageIdRef = useRef(null);
14569
14834
  const [enteringMessageIds, setEnteringMessageIds] = useState(/* @__PURE__ */ new Set());
14835
+ const [showScrollToBottom, setShowScrollToBottom] = useState(false);
14836
+ const stickToBottomRef = useRef(true);
14837
+ const pendingJumpRef = useRef(null);
14838
+ const jumpPagesRef = useRef(0);
14839
+ const [jumpNonce, setJumpNonce] = useState(0);
14570
14840
  const { fetchMessages: fetchMessages2, messagesMetadata, deletedForMeIds, searchedMessageId, isSearchActive, setSearchActive, setSearchedMessageId, fetchSearchMessageContext } = useStore();
14571
14841
  const loggedUserImage = useStore((s) => s.loggedUserDetails?.image);
14572
14842
  const conversations = useStore((s) => s.conversations);
@@ -14590,6 +14860,13 @@ function useActiveChannelMessages({
14590
14860
  })),
14591
14861
  [displayMessages, messagesById, loggedUserId]
14592
14862
  );
14863
+ const jumpDateBounds = useMemo(
14864
+ () => resolveJumpDateBounds(
14865
+ conversationInfo?.createdAt,
14866
+ displayMessages[0]?.timestamp
14867
+ ),
14868
+ [conversationInfo?.createdAt, displayMessages]
14869
+ );
14593
14870
  useEffect(() => {
14594
14871
  const messages = messagesWithResolvedReplies;
14595
14872
  const lastMessage = messages[messages.length - 1];
@@ -14627,6 +14904,10 @@ function useActiveChannelMessages({
14627
14904
  previousMessageCountRef.current = 0;
14628
14905
  previousLastMessageIdRef.current = null;
14629
14906
  setEnteringMessageIds(/* @__PURE__ */ new Set());
14907
+ pendingJumpRef.current = null;
14908
+ jumpPagesRef.current = 0;
14909
+ stickToBottomRef.current = true;
14910
+ setShowScrollToBottom(false);
14630
14911
  }, [conversationId, clearSelection]);
14631
14912
  const onSelectionModeChangeRef = useRef(onSelectionModeChange);
14632
14913
  useEffect(() => {
@@ -14636,10 +14917,10 @@ function useActiveChannelMessages({
14636
14917
  onSelectionModeChangeRef.current?.(selectionMode);
14637
14918
  }, [selectionMode]);
14638
14919
  const toggleSelection = useCallback((message, attachmentId) => {
14639
- const messageId = String(message._id || message.id);
14640
- if (!messageId) return;
14920
+ const messageId2 = String(message._id || message.id);
14921
+ if (!messageId2) return;
14641
14922
  const useAttachmentSelection = messageUsesAttachmentSelection(message);
14642
- const key = useAttachmentSelection && attachmentId ? buildSelectionKey(messageId, attachmentId) : messageId;
14923
+ const key = useAttachmentSelection && attachmentId ? buildSelectionKey(messageId2, attachmentId) : messageId2;
14643
14924
  setSelectedKeys((prev) => {
14644
14925
  const next = new Set(prev);
14645
14926
  if (next.has(key)) next.delete(key);
@@ -14649,17 +14930,17 @@ function useActiveChannelMessages({
14649
14930
  });
14650
14931
  }, []);
14651
14932
  const enterSelectionMode = useCallback((message, attachmentId) => {
14652
- const messageId = String(message._id || message.id);
14653
- if (!messageId) return;
14933
+ const messageId2 = String(message._id || message.id);
14934
+ if (!messageId2) return;
14654
14935
  setSelectionMode(true);
14655
14936
  const useAttachmentSelection = messageUsesAttachmentSelection(message);
14656
14937
  if (useAttachmentSelection) {
14657
14938
  if (attachmentId) {
14658
- setSelectedKeys((prev) => new Set(prev).add(buildSelectionKey(messageId, attachmentId)));
14939
+ setSelectedKeys((prev) => new Set(prev).add(buildSelectionKey(messageId2, attachmentId)));
14659
14940
  }
14660
14941
  return;
14661
14942
  }
14662
- setSelectedKeys((prev) => new Set(prev).add(messageId));
14943
+ setSelectedKeys((prev) => new Set(prev).add(messageId2));
14663
14944
  }, []);
14664
14945
  const selectedForwardItems = resolveForwardItems(selectedKeys, displayMessages);
14665
14946
  const canDeleteForEveryone = useMemo(
@@ -14678,14 +14959,14 @@ function useActiveChannelMessages({
14678
14959
  }
14679
14960
  const isGroupChat = !!activeChannel?.isGroup;
14680
14961
  selectedKeys.forEach((key) => {
14681
- const { messageId, attachmentId } = parseSelectionKey(key);
14682
- if (!messageId || messageId.startsWith("temp-")) return;
14683
- const message = displayMessages.find((entry) => String(entry._id || entry.id) === messageId);
14962
+ const { messageId: messageId2, attachmentId } = parseSelectionKey(key);
14963
+ if (!messageId2 || messageId2.startsWith("temp-")) return;
14964
+ const message = displayMessages.find((entry) => String(entry._id || entry.id) === messageId2);
14684
14965
  if (isGroupChat) {
14685
14966
  const convId = String(message?.conversationId || conversationId || "");
14686
14967
  if (!convId) return;
14687
14968
  emitGroupDelete({
14688
- messageId,
14969
+ messageId: messageId2,
14689
14970
  sender: loggedUserDetails._id,
14690
14971
  deleteType,
14691
14972
  conversationId: convId,
@@ -14695,7 +14976,7 @@ function useActiveChannelMessages({
14695
14976
  const receiver = message?.receiver || activeChannel?.id;
14696
14977
  if (!receiver) return;
14697
14978
  emitDmDelete({
14698
- messageId,
14979
+ messageId: messageId2,
14699
14980
  sender: loggedUserDetails._id,
14700
14981
  receiver: String(receiver),
14701
14982
  deleteType,
@@ -14734,43 +15015,138 @@ function useActiveChannelMessages({
14734
15015
  fetchMessages2(conversationId);
14735
15016
  }
14736
15017
  };
14737
- const handleReplyTargetClick = async (messageId) => {
14738
- if (!messageId) return;
14739
- if (messagesById.has(messageId)) {
14740
- setSearchedMessageId(messageId);
15018
+ const handleReplyTargetClick = async (messageId2) => {
15019
+ if (!messageId2) return;
15020
+ stickToBottomRef.current = false;
15021
+ if (messagesById.has(messageId2)) {
15022
+ setSearchedMessageId(messageId2);
14741
15023
  return;
14742
15024
  }
14743
- await fetchSearchMessageContext(messageId, { searchMode: false });
15025
+ await fetchSearchMessageContext(messageId2, { searchMode: false });
14744
15026
  };
15027
+ const handleJumpTo = useCallback((preset, specificDate) => {
15028
+ stickToBottomRef.current = false;
15029
+ if (preset === "beginning") {
15030
+ pendingJumpRef.current = { kind: "beginning" };
15031
+ } else if (preset === "specific") {
15032
+ if (!specificDate) return;
15033
+ const clamped = clampJumpDate(
15034
+ specificDate,
15035
+ jumpDateBounds.minDay,
15036
+ jumpDateBounds.maxDay
15037
+ );
15038
+ if (!clamped) return;
15039
+ pendingJumpRef.current = { kind: "date", at: startOfLocalDay(clamped) };
15040
+ } else {
15041
+ const raw = resolveJumpPreset(preset);
15042
+ const at = Math.min(Math.max(raw, jumpDateBounds.minDay), jumpDateBounds.maxDay);
15043
+ pendingJumpRef.current = { kind: "date", at };
15044
+ }
15045
+ jumpPagesRef.current = 0;
15046
+ setJumpNonce((n) => n + 1);
15047
+ }, [jumpDateBounds.minDay, jumpDateBounds.maxDay]);
15048
+ useEffect(() => {
15049
+ const pending = pendingJumpRef.current;
15050
+ if (!pending || isLoading) return;
15051
+ const step = resolveJumpStep(
15052
+ messagesWithResolvedReplies,
15053
+ pending,
15054
+ !!currentMeta?.hasMore
15055
+ );
15056
+ if (step.action === "loadOlder") {
15057
+ if (!conversationId || !currentMeta?.nextCursor || jumpPagesRef.current >= MAX_JUMP_OLDER_PAGES) {
15058
+ pendingJumpRef.current = null;
15059
+ const fallback = messagesWithResolvedReplies[0];
15060
+ if (fallback) setSearchedMessageId(String(fallback._id || fallback.id));
15061
+ return;
15062
+ }
15063
+ jumpPagesRef.current += 1;
15064
+ const prevScrollHeight = scrollContainerRef.current?.scrollHeight ?? 0;
15065
+ fetchMessages2(conversationId, DEFAULT_MESSAGES_LIMIT, currentMeta.nextCursor).then(() => {
15066
+ if (scrollContainerRef.current && prevScrollHeight) {
15067
+ scrollContainerRef.current.scrollTop = scrollContainerRef.current.scrollHeight - prevScrollHeight;
15068
+ }
15069
+ });
15070
+ return;
15071
+ }
15072
+ pendingJumpRef.current = null;
15073
+ if (step.action === "scroll") {
15074
+ setSearchedMessageId(null);
15075
+ requestAnimationFrame(() => setSearchedMessageId(step.messageId));
15076
+ }
15077
+ }, [
15078
+ jumpNonce,
15079
+ isLoading,
15080
+ messagesWithResolvedReplies,
15081
+ currentMeta?.hasMore,
15082
+ currentMeta?.nextCursor,
15083
+ conversationId,
15084
+ fetchMessages2,
15085
+ setSearchedMessageId
15086
+ ]);
15087
+ const updateScrollToBottomVisibility = useCallback((el) => {
15088
+ const distanceFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight;
15089
+ const nearBottom = distanceFromBottom <= 96;
15090
+ stickToBottomRef.current = nearBottom;
15091
+ setShowScrollToBottom(!nearBottom);
15092
+ }, []);
15093
+ const handleScrollToBottom = useCallback(() => {
15094
+ stickToBottomRef.current = true;
15095
+ if (isSearchActive) {
15096
+ setSearchActive(false);
15097
+ setSearchedMessageId(null);
15098
+ if (conversationId) fetchMessages2(conversationId);
15099
+ setShowScrollToBottom(false);
15100
+ return;
15101
+ }
15102
+ bottomRef.current?.scrollIntoView({ behavior: "smooth" });
15103
+ setShowScrollToBottom(false);
15104
+ }, [isSearchActive, conversationId, setSearchActive, setSearchedMessageId, fetchMessages2]);
14745
15105
  const handleScroll = (e) => {
14746
15106
  const target = e.currentTarget;
15107
+ updateScrollToBottomVisibility(target);
15108
+ if (pendingJumpRef.current) return;
14747
15109
  if (target.scrollTop === 0 && currentMeta?.hasMore && !isLoading && conversationId && currentMeta.nextCursor) {
14748
15110
  const prevScrollHeight = target.scrollHeight;
14749
15111
  fetchMessages2(conversationId, DEFAULT_MESSAGES_LIMIT, currentMeta.nextCursor).then(() => {
14750
15112
  if (scrollContainerRef.current) {
14751
15113
  const newScrollHeight = scrollContainerRef.current.scrollHeight;
14752
15114
  scrollContainerRef.current.scrollTop = newScrollHeight - prevScrollHeight;
15115
+ updateScrollToBottomVisibility(scrollContainerRef.current);
14753
15116
  }
14754
15117
  });
14755
15118
  }
14756
15119
  };
14757
15120
  useLayoutEffect(() => {
14758
- if (!isInitialLoading && currentMeta?.isFirstPage && !searchedMessageId) {
15121
+ if (!isInitialLoading && stickToBottomRef.current && !pendingJumpRef.current) {
14759
15122
  bottomRef.current?.scrollIntoView({ behavior: "smooth" });
14760
15123
  }
14761
- }, [messagesWithResolvedReplies.length, isInitialLoading, currentMeta?.isFirstPage, searchedMessageId]);
15124
+ }, [messagesWithResolvedReplies.length, isInitialLoading]);
14762
15125
  useEffect(() => {
14763
15126
  if (searchedMessageId && !isLoading) {
15127
+ stickToBottomRef.current = false;
15128
+ const container = scrollContainerRef.current;
14764
15129
  const element = document.getElementById(`message-${searchedMessageId}`);
14765
- if (element) {
14766
- element.scrollIntoView({ behavior: "smooth", block: "center" });
15130
+ if (container && element) {
15131
+ requestAnimationFrame(() => {
15132
+ requestAnimationFrame(() => {
15133
+ smoothScrollToMessage(container, element);
15134
+ updateScrollToBottomVisibility(container);
15135
+ });
15136
+ });
14767
15137
  }
14768
15138
  if (!isSearchActive) {
14769
15139
  const timer = window.setTimeout(() => setSearchedMessageId(null), 2500);
14770
15140
  return () => window.clearTimeout(timer);
14771
15141
  }
14772
15142
  }
14773
- }, [searchedMessageId, isLoading, messagesWithResolvedReplies.length, isSearchActive, setSearchedMessageId]);
15143
+ }, [
15144
+ searchedMessageId,
15145
+ isLoading,
15146
+ isSearchActive,
15147
+ setSearchedMessageId,
15148
+ updateScrollToBottomVisibility
15149
+ ]);
14774
15150
  return {
14775
15151
  activeChannel,
14776
15152
  conversationId,
@@ -14796,11 +15172,297 @@ function useActiveChannelMessages({
14796
15172
  canDeleteForEveryone,
14797
15173
  handleResetToNormal,
14798
15174
  handleReplyTargetClick,
15175
+ handleJumpTo,
15176
+ jumpDateBounds,
15177
+ showScrollToBottom,
15178
+ handleScrollToBottom,
14799
15179
  handleScroll
14800
15180
  };
14801
15181
  }
15182
+ function Calendar({
15183
+ className,
15184
+ classNames,
15185
+ showOutsideDays = true,
15186
+ captionLayout = "label",
15187
+ buttonVariant = "ghost",
15188
+ formatters,
15189
+ components,
15190
+ ...props
15191
+ }) {
15192
+ const defaultClassNames = getDefaultClassNames();
15193
+ return /* @__PURE__ */ jsx(
15194
+ DayPicker,
15195
+ {
15196
+ showOutsideDays,
15197
+ className: cn(
15198
+ "group/calendar bg-background p-3 [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
15199
+ String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
15200
+ String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
15201
+ className
15202
+ ),
15203
+ captionLayout,
15204
+ formatters: {
15205
+ formatMonthDropdown: (date) => date.toLocaleString("default", { month: "short" }),
15206
+ ...formatters
15207
+ },
15208
+ classNames: {
15209
+ root: cn("w-fit", defaultClassNames.root),
15210
+ months: cn(
15211
+ "relative flex flex-col gap-4 md:flex-row",
15212
+ defaultClassNames.months
15213
+ ),
15214
+ month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
15215
+ nav: cn(
15216
+ "absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1",
15217
+ defaultClassNames.nav
15218
+ ),
15219
+ button_previous: cn(
15220
+ buttonVariants({ variant: buttonVariant }),
15221
+ "size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
15222
+ defaultClassNames.button_previous
15223
+ ),
15224
+ button_next: cn(
15225
+ buttonVariants({ variant: buttonVariant }),
15226
+ "size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
15227
+ defaultClassNames.button_next
15228
+ ),
15229
+ month_caption: cn(
15230
+ "flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)",
15231
+ defaultClassNames.month_caption
15232
+ ),
15233
+ dropdowns: cn(
15234
+ "flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium",
15235
+ defaultClassNames.dropdowns
15236
+ ),
15237
+ dropdown_root: cn(
15238
+ "relative rounded-md border border-input shadow-xs has-focus:border-ring has-focus:ring-[3px] has-focus:ring-ring/50",
15239
+ defaultClassNames.dropdown_root
15240
+ ),
15241
+ dropdown: cn(
15242
+ "absolute inset-0 bg-popover opacity-0",
15243
+ defaultClassNames.dropdown
15244
+ ),
15245
+ caption_label: cn(
15246
+ "font-medium select-none",
15247
+ 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",
15248
+ defaultClassNames.caption_label
15249
+ ),
15250
+ month_grid: cn("w-full border-collapse", defaultClassNames.month_grid),
15251
+ weekdays: cn("flex", defaultClassNames.weekdays),
15252
+ weekday: cn(
15253
+ "flex-1 rounded-md text-[0.8rem] font-normal text-muted-foreground select-none",
15254
+ defaultClassNames.weekday
15255
+ ),
15256
+ week: cn("mt-2 flex w-full", defaultClassNames.week),
15257
+ week_number_header: cn(
15258
+ "w-(--cell-size) select-none",
15259
+ defaultClassNames.week_number_header
15260
+ ),
15261
+ week_number: cn(
15262
+ "text-[0.8rem] text-muted-foreground select-none",
15263
+ defaultClassNames.week_number
15264
+ ),
15265
+ day: cn(
15266
+ "group/day relative aspect-square h-full w-full p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-r-md",
15267
+ props.showWeekNumber ? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-md" : "[&:first-child[data-selected=true]_button]:rounded-l-md",
15268
+ defaultClassNames.day
15269
+ ),
15270
+ range_start: cn(
15271
+ "rounded-l-md bg-accent",
15272
+ defaultClassNames.range_start
15273
+ ),
15274
+ range_middle: cn("rounded-none", defaultClassNames.range_middle),
15275
+ range_end: cn("rounded-r-md bg-accent", defaultClassNames.range_end),
15276
+ today: cn(
15277
+ "rounded-md bg-accent text-accent-foreground data-[selected=true]:rounded-none",
15278
+ defaultClassNames.today
15279
+ ),
15280
+ outside: cn(
15281
+ "text-muted-foreground aria-selected:text-muted-foreground",
15282
+ defaultClassNames.outside
15283
+ ),
15284
+ disabled: cn(
15285
+ "text-muted-foreground opacity-50",
15286
+ defaultClassNames.disabled
15287
+ ),
15288
+ hidden: cn("invisible", defaultClassNames.hidden),
15289
+ ...classNames
15290
+ },
15291
+ components: {
15292
+ Root: ({ className: className2, rootRef, ...props2 }) => {
15293
+ return /* @__PURE__ */ jsx(
15294
+ "div",
15295
+ {
15296
+ "data-slot": "calendar",
15297
+ ref: rootRef,
15298
+ className: cn(className2),
15299
+ ...props2
15300
+ }
15301
+ );
15302
+ },
15303
+ Chevron: ({ className: className2, orientation, ...props2 }) => {
15304
+ if (orientation === "left") {
15305
+ return /* @__PURE__ */ jsx(ChevronLeftIcon, { className: cn("size-4", className2), ...props2 });
15306
+ }
15307
+ if (orientation === "right") {
15308
+ return /* @__PURE__ */ jsx(
15309
+ ChevronRightIcon,
15310
+ {
15311
+ className: cn("size-4", className2),
15312
+ ...props2
15313
+ }
15314
+ );
15315
+ }
15316
+ return /* @__PURE__ */ jsx(ChevronDownIcon, { className: cn("size-4", className2), ...props2 });
15317
+ },
15318
+ DayButton: CalendarDayButton,
15319
+ WeekNumber: ({ children, ...props2 }) => {
15320
+ return /* @__PURE__ */ jsx("td", { ...props2, children: /* @__PURE__ */ jsx("div", { className: "flex size-(--cell-size) items-center justify-center text-center", children }) });
15321
+ },
15322
+ ...components
15323
+ },
15324
+ ...props
15325
+ }
15326
+ );
15327
+ }
15328
+ function CalendarDayButton({
15329
+ className,
15330
+ day,
15331
+ modifiers,
15332
+ ...props
15333
+ }) {
15334
+ const defaultClassNames = getDefaultClassNames();
15335
+ const ref = React2.useRef(null);
15336
+ React2.useEffect(() => {
15337
+ if (modifiers.focused) ref.current?.focus();
15338
+ }, [modifiers.focused]);
15339
+ return /* @__PURE__ */ jsx(
15340
+ Button,
15341
+ {
15342
+ ref,
15343
+ variant: "ghost",
15344
+ size: "icon",
15345
+ "data-day": day.date.toLocaleDateString(),
15346
+ "data-selected-single": modifiers.selected && !modifiers.range_start && !modifiers.range_end && !modifiers.range_middle,
15347
+ "data-range-start": modifiers.range_start,
15348
+ "data-range-end": modifiers.range_end,
15349
+ "data-range-middle": modifiers.range_middle,
15350
+ className: cn(
15351
+ "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",
15352
+ defaultClassNames.day,
15353
+ className
15354
+ ),
15355
+ ...props
15356
+ }
15357
+ );
15358
+ }
15359
+ var PRESETS = [
15360
+ { preset: "today", label: "Today" },
15361
+ { preset: "yesterday", label: "Yesterday" },
15362
+ { preset: "lastWeek", label: "Last week" },
15363
+ { preset: "lastMonth", label: "Last month" },
15364
+ { preset: "beginning", label: "The very beginning" }
15365
+ ];
15366
+ function ChatDateJumpMenu({ label, minDay, maxDay, onJump }) {
15367
+ const { scopeClassName } = useChatTheme();
15368
+ const [open, setOpen] = useState(false);
15369
+ const [showCalendar, setShowCalendar] = useState(false);
15370
+ const [calendarMonth, setCalendarMonth] = useState(() => new Date(maxDay));
15371
+ const minDate = new Date(minDay);
15372
+ const maxDate = new Date(maxDay);
15373
+ useEffect(() => {
15374
+ if (showCalendar) setCalendarMonth(new Date(maxDay));
15375
+ }, [showCalendar, maxDay]);
15376
+ const queueJump = (preset, specificDate) => {
15377
+ window.setTimeout(() => onJump(preset, specificDate), 0);
15378
+ };
15379
+ const handleOpenChange = (next) => {
15380
+ setOpen(next);
15381
+ if (!next) setShowCalendar(false);
15382
+ };
15383
+ const handlePreset = (preset) => {
15384
+ setOpen(false);
15385
+ setShowCalendar(false);
15386
+ queueJump(preset);
15387
+ };
15388
+ const handleDateSelect = (date) => {
15389
+ if (!date) return;
15390
+ const clamped = clampJumpDate(date, minDay, maxDay);
15391
+ if (!clamped) return;
15392
+ setOpen(false);
15393
+ setShowCalendar(false);
15394
+ queueJump("specific", clamped);
15395
+ };
15396
+ return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: handleOpenChange, children: [
15397
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
15398
+ "button",
15399
+ {
15400
+ type: "button",
15401
+ className: "chat-date-divider-pill chat-date-divider-pill--interactive",
15402
+ "aria-label": `Jump to date, currently ${label}`,
15403
+ children: [
15404
+ /* @__PURE__ */ jsx("span", { children: label }),
15405
+ /* @__PURE__ */ jsx(ChevronDown, { className: "chat-date-divider-chevron", "aria-hidden": true })
15406
+ ]
15407
+ }
15408
+ ) }),
15409
+ /* @__PURE__ */ jsx(
15410
+ PopoverContent,
15411
+ {
15412
+ align: "center",
15413
+ sideOffset: 8,
15414
+ className: cn(
15415
+ scopeClassName,
15416
+ chatPopoverContentClass,
15417
+ "w-auto overflow-hidden rounded-2xl p-0",
15418
+ showCalendar ? "min-w-[300px]" : "min-w-[220px]"
15419
+ ),
15420
+ onCloseAutoFocus: (event) => event.preventDefault(),
15421
+ children: showCalendar ? /* @__PURE__ */ jsx("div", { className: "p-2", children: /* @__PURE__ */ jsx(
15422
+ Calendar,
15423
+ {
15424
+ mode: "single",
15425
+ month: calendarMonth,
15426
+ onMonthChange: setCalendarMonth,
15427
+ startMonth: minDate,
15428
+ endMonth: maxDate,
15429
+ showOutsideDays: false,
15430
+ disabled: { before: minDate, after: maxDate },
15431
+ onSelect: handleDateSelect,
15432
+ className: "chat-jump-calendar rounded-xl bg-transparent p-1 [--cell-size:2.125rem]"
15433
+ }
15434
+ ) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
15435
+ /* @__PURE__ */ jsxs("div", { className: "px-3 pt-3 pb-2", children: [
15436
+ /* @__PURE__ */ jsx("p", { className: chatOptionsMenuLabelClass, children: "Jump to\u2026" }),
15437
+ /* @__PURE__ */ jsx("div", { className: "mt-1 flex flex-col", children: PRESETS.map(({ preset, label: itemLabel }) => /* @__PURE__ */ jsx(
15438
+ "button",
15439
+ {
15440
+ type: "button",
15441
+ className: cn(chatOptionsMenuItemClass, "w-full border-0 bg-transparent text-left"),
15442
+ onClick: () => handlePreset(preset),
15443
+ children: itemLabel
15444
+ },
15445
+ preset
15446
+ )) })
15447
+ ] }),
15448
+ /* @__PURE__ */ jsx("div", { className: cn(chatOptionsMenuSeparatorClass, "mx-3") }),
15449
+ /* @__PURE__ */ jsx("div", { className: "px-1 pb-2", children: /* @__PURE__ */ jsx(
15450
+ "button",
15451
+ {
15452
+ type: "button",
15453
+ className: cn(chatOptionsMenuItemClass, "w-full border-0 bg-transparent text-left"),
15454
+ onClick: () => setShowCalendar(true),
15455
+ children: "Jump to a specific date"
15456
+ }
15457
+ ) })
15458
+ ] })
15459
+ }
15460
+ )
15461
+ ] });
15462
+ }
14802
15463
  var ActiveChannelMessagesView = (props) => {
14803
15464
  const { formatDateDivider } = useChatLocale();
15465
+ const allUsers = useStore((s) => s.allUsers);
14804
15466
  const {
14805
15467
  activeChannel,
14806
15468
  conversationId,
@@ -14826,6 +15488,10 @@ var ActiveChannelMessagesView = (props) => {
14826
15488
  canDeleteForEveryone,
14827
15489
  handleResetToNormal,
14828
15490
  handleReplyTargetClick,
15491
+ handleJumpTo,
15492
+ jumpDateBounds,
15493
+ showScrollToBottom,
15494
+ handleScrollToBottom,
14829
15495
  handleScroll
14830
15496
  } = useActiveChannelMessages(props);
14831
15497
  const { onReply, onForward } = props;
@@ -14838,7 +15504,7 @@ var ActiveChannelMessagesView = (props) => {
14838
15504
  ] })
14839
15505
  ] });
14840
15506
  }
14841
- return /* @__PURE__ */ jsxs("div", { className: "chat-message-canvas relative flex h-full min-h-0 flex-col overflow-hidden", children: [
15507
+ return /* @__PURE__ */ jsxs("div", { className: "chat-message-canvas relative flex h-full flex-col", children: [
14842
15508
  isSearchActive && /* @__PURE__ */ 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__ */ 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: [
14843
15509
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 bg-(--chat-theme) px-4 py-2.5", children: [
14844
15510
  /* @__PURE__ */ jsx(History, { className: "size-3.5 animate-pulse text-white" }),
@@ -14875,11 +15541,20 @@ var ActiveChannelMessagesView = (props) => {
14875
15541
  return groups;
14876
15542
  }, {})
14877
15543
  ).map(([date, messages]) => /* @__PURE__ */ jsxs("div", { className: "mb-2 flex flex-col", children: [
14878
- /* @__PURE__ */ jsx("div", { className: "chat-date-divider", children: /* @__PURE__ */ jsx("span", { className: "chat-date-divider-pill", children: date }) }),
15544
+ /* @__PURE__ */ jsx("div", { className: "sticky top-1.5 z-20 mb-2 flex justify-center py-1", children: /* @__PURE__ */ jsx(
15545
+ ChatDateJumpMenu,
15546
+ {
15547
+ label: date,
15548
+ minDay: jumpDateBounds.minDay,
15549
+ maxDay: jumpDateBounds.maxDay,
15550
+ onJump: handleJumpTo
15551
+ }
15552
+ ) }),
14879
15553
  messages.map((m, msgIndex) => {
14880
- const senderLabel = typeof m.sender === "string" ? m.sender : "User";
14881
- const senderImage = !m.isOwnMessage ? activeChannel?.isGroup ? void 0 : activeChannel?.image : void 0;
14882
15554
  const isGroupChat = !!activeChannel?.isGroup;
15555
+ const participants = conversationInfo?.participants ?? [];
15556
+ const { name: senderLabel, image: groupSenderImage } = isGroupChat && !m.isOwnMessage ? resolveGroupSenderDisplay(m, allUsers, participants) : { name: typeof m.sender === "string" ? m.sender : "User", image: void 0 };
15557
+ const senderImage = !m.isOwnMessage ? isGroupChat ? groupSenderImage : activeChannel?.image : void 0;
14883
15558
  const prevMessage = msgIndex > 0 ? messages[msgIndex - 1] : null;
14884
15559
  const nextMessage = msgIndex < messages.length - 1 ? messages[msgIndex + 1] : null;
14885
15560
  const isGroupedWithPrev = !!prevMessage && isSameMessageSide(prevMessage, m, isGroupChat);
@@ -14926,6 +15601,7 @@ var ActiveChannelMessagesView = (props) => {
14926
15601
  conversationInfo,
14927
15602
  isHighlighted: String(m._id || m.id) === String(searchedMessageId),
14928
15603
  senderName: senderLabel,
15604
+ senderId: getMessageSenderId2(m),
14929
15605
  senderImage,
14930
15606
  showSenderName,
14931
15607
  showSenderLabel,
@@ -14966,6 +15642,16 @@ var ActiveChannelMessagesView = (props) => {
14966
15642
  onForward: handleBatchForward
14967
15643
  }
14968
15644
  ),
15645
+ showScrollToBottom && !selectionMode && /* @__PURE__ */ jsx(
15646
+ "button",
15647
+ {
15648
+ type: "button",
15649
+ onClick: handleScrollToBottom,
15650
+ className: "chat-scroll-to-bottom",
15651
+ "aria-label": "Scroll to latest messages",
15652
+ children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-5", strokeWidth: 2.25 })
15653
+ }
15654
+ ),
14969
15655
  isInitialLoading && /* @__PURE__ */ 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: [
14970
15656
  /* @__PURE__ */ jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin text-(--chat-theme)" }),
14971
15657
  /* @__PURE__ */ jsx("span", { className: "text-[10px] font-bold uppercase tracking-[0.15em] text-(--chat-muted)", children: "Loading messages..." })
@@ -15589,10 +16275,10 @@ function useChannelMessageBox({
15589
16275
  const composerDisabledReason = conversationId ? composerDisabledByConversation[conversationId] : void 0;
15590
16276
  const fileInputRef = useRef(null);
15591
16277
  const attachmentsCountRef = useRef(0);
15592
- React2.useEffect(() => {
16278
+ React2__default.useEffect(() => {
15593
16279
  attachmentsCountRef.current = state.attachments.length;
15594
16280
  }, [state.attachments.length]);
15595
- React2.useEffect(() => {
16281
+ React2__default.useEffect(() => {
15596
16282
  const draft = {
15597
16283
  messageInput: state.messageInput,
15598
16284
  attachments: state.attachments
@@ -15600,7 +16286,7 @@ function useChannelMessageBox({
15600
16286
  syncComposerRef(draft);
15601
16287
  updateConversationDraft(conversationIdRef.current, draft);
15602
16288
  }, [state.messageInput, state.attachments, syncComposerRef]);
15603
- React2.useEffect(() => {
16289
+ React2__default.useEffect(() => {
15604
16290
  if (typingTimeoutRef.current) {
15605
16291
  clearTimeout(typingTimeoutRef.current);
15606
16292
  typingTimeoutRef.current = null;
@@ -16151,10 +16837,10 @@ function useForwardModal({ isOpen, onClose, items, onForwardComplete }) {
16151
16837
  targetChannelRef.current = channel;
16152
16838
  const targetConversationIds = [String(channel.conversationId)];
16153
16839
  items.forEach((item) => {
16154
- const messageId = String(item.message._id || item.message.id || "");
16155
- if (!messageId) return;
16840
+ const messageId2 = String(item.message._id || item.message.id || "");
16841
+ if (!messageId2) return;
16156
16842
  const payload = {
16157
- messageId,
16843
+ messageId: messageId2,
16158
16844
  sender: String(loggedUserDetails._id),
16159
16845
  sourceConversationId: item.message.conversationId ? String(item.message.conversationId) : void 0,
16160
16846
  targetConversationIds,
@@ -16631,8 +17317,8 @@ var ChatMain = ({
16631
17317
  viewportHeight = "full",
16632
17318
  viewportClassName
16633
17319
  }) => {
16634
- const clientObj = React2.useMemo(() => ({ id: clientId }), [clientId]);
16635
- const uiConfigObj = React2.useMemo(
17320
+ const clientObj = React2__default.useMemo(() => ({ id: clientId }), [clientId]);
17321
+ const uiConfigObj = React2__default.useMemo(
16636
17322
  () => ({
16637
17323
  ...uiConfig || {},
16638
17324
  components: { ...uiConfig?.components, ...components },
@@ -17067,6 +17753,6 @@ var packageDefaultComponents = {
17067
17753
  // src/index.ts
17068
17754
  var index_default = ChatMain_default;
17069
17755
 
17070
- export { CHAT_API_KEYS, CHAT_GET_API_KEYS, Channel, ChannelHeaderView_default as ChannelHeader, ChannelListView_default as ChannelList, ChannelListItem_default as ChannelListItem, Chat, ChatAlertsProvider, ChatAvatar_default as ChatAvatar, ChatCustomizationProvider, ChatLayout_default as ChatLayout, ChatLocaleProvider, ChatMain_default as ChatMain, ChatThemeProvider, ChatViewport, DefaultChannelListItem, DefaultChatAvatar, DefaultChatLayout_default as DefaultChatLayout, ForwardModalView as ForwardModal, HeaderCallActions_default as HeaderCallActions, LoggedUserDetails_default as LoggedUserDetails, ChannelMessageBoxView_default as MessageInput, MessageItemView as MessageItem, ActiveChannelMessagesView_default as MessageList, capitalizeFirst, index_default as default, defaultChatClassNames, defaultChatComponents, defaultChatFeatures, defaultChatLayoutConfig, downloadFile, getChatBaseUrl, getChatQueryParamApis, getChatQueryParams, getChatQueryParamsByApi, getChatSocketUrl, getFirstAndLastNameOneCharacter, getResponsiveWidth, getSocketConfig, isEmpty, mergeChatCustomization, mergeChatLayoutConfig, packageDefaultComponents, resolveApiUrl, resolveChatApiKey, resolveSocketUrl, setChatAccessToken, setChatBaseURL, setChatClientId, setChatQueryParamApis, setChatQueryParams, setChatQueryParamsByApi, setChatSocketUrl, showNotification, socket_service_default as socketService, uniqueList, useChatAlerts, useChatContext, useChatController, useChatCustomization, useChatCustomizationOptional, useChatFeatures, useChatFeaturesOptional, useChatLocale, useStore as useChatStore, useChatTheme };
17756
+ export { CHAT_API_KEYS, CHAT_GET_API_KEYS, Calendar, CalendarDayButton, Channel, ChannelHeaderView_default as ChannelHeader, ChannelListView_default as ChannelList, ChannelListItem_default as ChannelListItem, Chat, ChatAlertsProvider, ChatAvatar_default as ChatAvatar, ChatCustomizationProvider, ChatDateJumpMenu, ChatLayout_default as ChatLayout, ChatLocaleProvider, ChatMain_default as ChatMain, ChatThemeProvider, ChatViewport, DefaultChannelListItem, DefaultChatAvatar, DefaultChatLayout_default as DefaultChatLayout, ForwardModalView as ForwardModal, HeaderCallActions_default as HeaderCallActions, LoggedUserDetails_default as LoggedUserDetails, ChannelMessageBoxView_default as MessageInput, MessageItemView as MessageItem, ActiveChannelMessagesView_default as MessageList, capitalizeFirst, clampJumpDate, index_default as default, defaultChatClassNames, defaultChatComponents, defaultChatFeatures, defaultChatLayoutConfig, downloadFile, getChatBaseUrl, getChatQueryParamApis, getChatQueryParams, getChatQueryParamsByApi, getChatSocketUrl, getFirstAndLastNameOneCharacter, getResponsiveWidth, getSocketConfig, isEmpty, mergeChatCustomization, mergeChatLayoutConfig, packageDefaultComponents, resolveApiUrl, resolveChatApiKey, resolveJumpDateBounds, resolveJumpPreset, resolveJumpStep, resolveSocketUrl, setChatAccessToken, setChatBaseURL, setChatClientId, setChatQueryParamApis, setChatQueryParams, setChatQueryParamsByApi, setChatSocketUrl, showNotification, smoothScrollToMessage, socket_service_default as socketService, startOfLocalDay, toDateInputValue, uniqueList, useChatAlerts, useChatContext, useChatController, useChatCustomization, useChatCustomizationOptional, useChatFeatures, useChatFeaturesOptional, useChatLocale, useStore as useChatStore, useChatTheme };
17071
17757
  //# sourceMappingURL=index.mjs.map
17072
17758
  //# sourceMappingURL=index.mjs.map