@realtimexsco/live-chat 1.3.4 → 1.4.1
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/firebase-messaging-sw.js +68 -0
- package/dist/index.cjs +1268 -292
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +155 -1
- package/dist/index.d.ts +155 -1
- package/dist/index.mjs +1231 -294
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +93 -59
- package/package.json +9 -2
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
|
|
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,
|
|
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
|
|
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,
|
|
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(
|
|
807
|
+
(m) => String(m._id || m.id) === String(messageId2)
|
|
806
808
|
)
|
|
807
809
|
);
|
|
808
810
|
};
|
|
809
|
-
applyMessageStatusToStore = (state,
|
|
810
|
-
const normalizedMessageId = String(
|
|
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(
|
|
@@ -935,9 +937,9 @@ var init_conversation_helpers = __esm({
|
|
|
935
937
|
if (!conversationId) return void 0;
|
|
936
938
|
return conversations.find((c) => String(c._id) === String(conversationId));
|
|
937
939
|
};
|
|
938
|
-
findConversationIdByLastMessageId = (conversations,
|
|
939
|
-
if (!
|
|
940
|
-
const normalizedMessageId = String(
|
|
940
|
+
findConversationIdByLastMessageId = (conversations, messageId2) => {
|
|
941
|
+
if (!messageId2) return null;
|
|
942
|
+
const normalizedMessageId = String(messageId2);
|
|
941
943
|
const match = conversations.find(
|
|
942
944
|
(conversation) => String(conversation?.lastMessage?._id || conversation?.lastMessage?.id || "") === normalizedMessageId
|
|
943
945
|
);
|
|
@@ -1356,7 +1358,7 @@ var init_api_constants = __esm({
|
|
|
1356
1358
|
ADD_REMOVE_MEMBERS: "/conversation/group/participants/add-remove",
|
|
1357
1359
|
ADD_REMOVE_ADMINS: "/conversation/group/admins/add-remove",
|
|
1358
1360
|
SEARCH_MESSAGES: "/message/search-messages",
|
|
1359
|
-
SEARCH_MESSAGES_CONTEXT: (
|
|
1361
|
+
SEARCH_MESSAGES_CONTEXT: (messageId2) => `/message/searched-message/context?messageId=${messageId2}`,
|
|
1360
1362
|
BLOCK_UNBLOCK_USER: "/user/block-unblock"
|
|
1361
1363
|
}
|
|
1362
1364
|
};
|
|
@@ -1500,9 +1502,9 @@ var init_messages_api = __esm({
|
|
|
1500
1502
|
throw error;
|
|
1501
1503
|
}
|
|
1502
1504
|
};
|
|
1503
|
-
searchMessagesContext = async (
|
|
1505
|
+
searchMessagesContext = async (messageId2) => {
|
|
1504
1506
|
try {
|
|
1505
|
-
const response = await apiClient.get(API_ENDPOINTS.GROUP.SEARCH_MESSAGES_CONTEXT(
|
|
1507
|
+
const response = await apiClient.get(API_ENDPOINTS.GROUP.SEARCH_MESSAGES_CONTEXT(messageId2));
|
|
1506
1508
|
return response.data;
|
|
1507
1509
|
} catch (error) {
|
|
1508
1510
|
console.error("Search messages context failed:", error);
|
|
@@ -1628,24 +1630,24 @@ var init_forwardPending_store = __esm({
|
|
|
1628
1630
|
"src/store/forwardPending.store.ts"() {
|
|
1629
1631
|
pendingForwards = /* @__PURE__ */ new Map();
|
|
1630
1632
|
lastPendingMessageId = null;
|
|
1631
|
-
setPendingForward = (
|
|
1632
|
-
if (!
|
|
1633
|
-
const key = String(
|
|
1633
|
+
setPendingForward = (messageId2, meta) => {
|
|
1634
|
+
if (!messageId2) return;
|
|
1635
|
+
const key = String(messageId2);
|
|
1634
1636
|
pendingForwards.set(key, meta);
|
|
1635
1637
|
lastPendingMessageId = key;
|
|
1636
1638
|
};
|
|
1637
|
-
peekPendingForward = (
|
|
1638
|
-
if (!
|
|
1639
|
-
return pendingForwards.get(String(
|
|
1639
|
+
peekPendingForward = (messageId2) => {
|
|
1640
|
+
if (!messageId2) return void 0;
|
|
1641
|
+
return pendingForwards.get(String(messageId2));
|
|
1640
1642
|
};
|
|
1641
1643
|
peekMostRecentPendingForward = () => {
|
|
1642
1644
|
if (!lastPendingMessageId) return void 0;
|
|
1643
1645
|
return pendingForwards.get(lastPendingMessageId);
|
|
1644
1646
|
};
|
|
1645
1647
|
getLastPendingForwardMessageId = () => lastPendingMessageId;
|
|
1646
|
-
clearPendingForward = (
|
|
1647
|
-
if (
|
|
1648
|
-
const key = String(
|
|
1648
|
+
clearPendingForward = (messageId2) => {
|
|
1649
|
+
if (messageId2) {
|
|
1650
|
+
const key = String(messageId2);
|
|
1649
1651
|
pendingForwards.delete(key);
|
|
1650
1652
|
if (lastPendingMessageId === key) lastPendingMessageId = null;
|
|
1651
1653
|
return;
|
|
@@ -2115,14 +2117,14 @@ var init_group_reaction_handlers = __esm({
|
|
|
2115
2117
|
return Array.from(map.values());
|
|
2116
2118
|
};
|
|
2117
2119
|
handleGroupReactionAddReceive = (set, get, payload) => {
|
|
2118
|
-
const
|
|
2120
|
+
const messageId2 = payload.messageId || payload._id;
|
|
2119
2121
|
const conversationId = payload.conversationId;
|
|
2120
|
-
if (!
|
|
2122
|
+
if (!messageId2) return;
|
|
2121
2123
|
set((state) => {
|
|
2122
|
-
const cid = conversationId || findConversationIdByMessageId(state.messagesByConversation,
|
|
2124
|
+
const cid = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId2);
|
|
2123
2125
|
if (!cid) return state;
|
|
2124
2126
|
const messages = state.messagesByConversation[cid] || [];
|
|
2125
|
-
const idx = messages.findIndex((m) => String(m._id || m.id) === String(
|
|
2127
|
+
const idx = messages.findIndex((m) => String(m._id || m.id) === String(messageId2));
|
|
2126
2128
|
if (idx === -1) return state;
|
|
2127
2129
|
const nextMessages = [...messages];
|
|
2128
2130
|
const currentMsg = { ...nextMessages[idx] };
|
|
@@ -2140,20 +2142,20 @@ var init_group_reaction_handlers = __esm({
|
|
|
2140
2142
|
}
|
|
2141
2143
|
nextMessages[idx] = currentMsg;
|
|
2142
2144
|
return {
|
|
2143
|
-
lastReactionUpdate: { ...payload, messageId, action: "add", _v: Date.now() },
|
|
2145
|
+
lastReactionUpdate: { ...payload, messageId: messageId2, action: "add", _v: Date.now() },
|
|
2144
2146
|
messagesByConversation: { ...state.messagesByConversation, [cid]: nextMessages }
|
|
2145
2147
|
};
|
|
2146
2148
|
});
|
|
2147
2149
|
};
|
|
2148
2150
|
handleGroupReactionRemoveReceive = (set, get, payload) => {
|
|
2149
|
-
const
|
|
2151
|
+
const messageId2 = payload.messageId || payload._id;
|
|
2150
2152
|
const conversationId = payload.conversationId;
|
|
2151
|
-
if (!
|
|
2153
|
+
if (!messageId2) return;
|
|
2152
2154
|
set((state) => {
|
|
2153
|
-
const cid = conversationId || findConversationIdByMessageId(state.messagesByConversation,
|
|
2155
|
+
const cid = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId2);
|
|
2154
2156
|
if (!cid) return state;
|
|
2155
2157
|
const messages = state.messagesByConversation[cid] || [];
|
|
2156
|
-
const idx = messages.findIndex((m) => String(m._id || m.id) === String(
|
|
2158
|
+
const idx = messages.findIndex((m) => String(m._id || m.id) === String(messageId2));
|
|
2157
2159
|
if (idx === -1) return state;
|
|
2158
2160
|
const nextMessages = [...messages];
|
|
2159
2161
|
const currentMsg = { ...nextMessages[idx] };
|
|
@@ -2170,7 +2172,7 @@ var init_group_reaction_handlers = __esm({
|
|
|
2170
2172
|
}
|
|
2171
2173
|
nextMessages[idx] = currentMsg;
|
|
2172
2174
|
return {
|
|
2173
|
-
lastReactionUpdate: { ...payload, messageId, action: "remove", _v: Date.now() },
|
|
2175
|
+
lastReactionUpdate: { ...payload, messageId: messageId2, action: "remove", _v: Date.now() },
|
|
2174
2176
|
messagesByConversation: { ...state.messagesByConversation, [cid]: nextMessages }
|
|
2175
2177
|
};
|
|
2176
2178
|
});
|
|
@@ -2200,14 +2202,14 @@ function removeMessageAttachment(message, attachmentId) {
|
|
|
2200
2202
|
if (attachments.length === message.attachments.length) return message;
|
|
2201
2203
|
return { ...message, attachments };
|
|
2202
2204
|
}
|
|
2203
|
-
function pinKey(
|
|
2204
|
-
return attachmentId ? `${
|
|
2205
|
+
function pinKey(messageId2, attachmentId) {
|
|
2206
|
+
return attachmentId ? `${messageId2}:${attachmentId}` : String(messageId2);
|
|
2205
2207
|
}
|
|
2206
|
-
function matchesPinEntry(entry,
|
|
2208
|
+
function matchesPinEntry(entry, messageId2, attachmentId) {
|
|
2207
2209
|
const entryMessageId = String(
|
|
2208
2210
|
entry?.messageId?._id || entry?.messageId || entry?._id || entry?.id || ""
|
|
2209
2211
|
);
|
|
2210
|
-
if (entryMessageId !== String(
|
|
2212
|
+
if (entryMessageId !== String(messageId2)) return false;
|
|
2211
2213
|
const entryAttachmentId = entry?.attachmentId ? String(entry.attachmentId) : null;
|
|
2212
2214
|
const targetAttachmentId = attachmentId ? String(attachmentId) : null;
|
|
2213
2215
|
return entryAttachmentId === targetAttachmentId;
|
|
@@ -2222,13 +2224,13 @@ function applyPinnedListToMessages(messages, pinnedMessage) {
|
|
|
2222
2224
|
)
|
|
2223
2225
|
);
|
|
2224
2226
|
return messages.map((message) => {
|
|
2225
|
-
const
|
|
2226
|
-
const hasWholeMessagePin = pinnedKeys.has(pinKey(
|
|
2227
|
+
const messageId2 = String(message._id || message.id);
|
|
2228
|
+
const hasWholeMessagePin = pinnedKeys.has(pinKey(messageId2, null));
|
|
2227
2229
|
const attachments = (message.attachments || []).map((att) => {
|
|
2228
2230
|
const attId = getAttachmentId(att);
|
|
2229
2231
|
return {
|
|
2230
2232
|
...att,
|
|
2231
|
-
isPinned: attId ? pinnedKeys.has(pinKey(
|
|
2233
|
+
isPinned: attId ? pinnedKeys.has(pinKey(messageId2, attId)) : !!att.isPinned
|
|
2232
2234
|
};
|
|
2233
2235
|
});
|
|
2234
2236
|
return {
|
|
@@ -2290,13 +2292,13 @@ var init_pin_handlers = __esm({
|
|
|
2290
2292
|
});
|
|
2291
2293
|
return;
|
|
2292
2294
|
}
|
|
2293
|
-
const { messageId, conversationId, isPinned, attachmentId } = extractMessageData(payload);
|
|
2294
|
-
if (!
|
|
2295
|
+
const { messageId: messageId2, conversationId, isPinned, attachmentId } = extractMessageData(payload);
|
|
2296
|
+
if (!messageId2 || !conversationId) return;
|
|
2295
2297
|
set((state) => {
|
|
2296
|
-
const sid = conversationId || findConversationIdByMessageId(state.messagesByConversation,
|
|
2298
|
+
const sid = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId2);
|
|
2297
2299
|
if (!sid) return state;
|
|
2298
2300
|
const messages = state.messagesByConversation[sid] || [];
|
|
2299
|
-
const index = messages.findIndex((m) => String(m._id || m.id) === String(
|
|
2301
|
+
const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId2));
|
|
2300
2302
|
let newMessagesByConversation = state.messagesByConversation;
|
|
2301
2303
|
const msg = index !== -1 ? messages[index] : null;
|
|
2302
2304
|
const wasPinned = attachmentId ? !!msg?.attachments?.some(
|
|
@@ -2318,9 +2320,9 @@ var init_pin_handlers = __esm({
|
|
|
2318
2320
|
const newPinnedByConv = { ...state.pinnedMessagesByConversation };
|
|
2319
2321
|
if (isPinned) {
|
|
2320
2322
|
const currentPinned = newPinnedByConv[sid] || [];
|
|
2321
|
-
if (!currentPinned.some((m) => matchesPinEntry(m,
|
|
2323
|
+
if (!currentPinned.some((m) => matchesPinEntry(m, messageId2, attachmentId || null))) {
|
|
2322
2324
|
const fullMsg = msg ? attachmentId ? {
|
|
2323
|
-
messageId,
|
|
2325
|
+
messageId: messageId2,
|
|
2324
2326
|
attachmentId,
|
|
2325
2327
|
attachment: msg.attachments?.find(
|
|
2326
2328
|
(att) => getAttachmentId(att) === String(attachmentId)
|
|
@@ -2332,7 +2334,7 @@ var init_pin_handlers = __esm({
|
|
|
2332
2334
|
}
|
|
2333
2335
|
} else {
|
|
2334
2336
|
newPinnedByConv[sid] = (newPinnedByConv[sid] || []).filter(
|
|
2335
|
-
(m) => !matchesPinEntry(m,
|
|
2337
|
+
(m) => !matchesPinEntry(m, messageId2, attachmentId || payload.unpinAttachmentId || null)
|
|
2336
2338
|
);
|
|
2337
2339
|
}
|
|
2338
2340
|
const conversation = get().conversations?.find((c) => String(c._id) === String(sid));
|
|
@@ -2347,8 +2349,8 @@ var init_pin_handlers = __esm({
|
|
|
2347
2349
|
pinnedCount = payload.totalCount;
|
|
2348
2350
|
}
|
|
2349
2351
|
const newPendingActions = { ...state.messagePendingActions };
|
|
2350
|
-
if (newPendingActions[
|
|
2351
|
-
delete newPendingActions[
|
|
2352
|
+
if (newPendingActions[messageId2]) {
|
|
2353
|
+
delete newPendingActions[messageId2];
|
|
2352
2354
|
}
|
|
2353
2355
|
return {
|
|
2354
2356
|
lastPinUpdate: payload,
|
|
@@ -2379,13 +2381,13 @@ var init_star_handlers = __esm({
|
|
|
2379
2381
|
init_attachment_helpers();
|
|
2380
2382
|
handleStarUpdate = (set, get, payload) => {
|
|
2381
2383
|
if (payload.starredBy && Array.isArray(payload.starredBy)) {
|
|
2382
|
-
const { messageId:
|
|
2384
|
+
const { messageId: messageId3, attachmentId } = extractMessageData(payload);
|
|
2383
2385
|
const { starredBy } = payload;
|
|
2384
|
-
if (!
|
|
2386
|
+
if (!messageId3) return;
|
|
2385
2387
|
set((state) => {
|
|
2386
|
-
const sid = payload.conversationId || findConversationIdByMessageId(state.messagesByConversation,
|
|
2388
|
+
const sid = payload.conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId3);
|
|
2387
2389
|
const newPendingActions = { ...state.messagePendingActions };
|
|
2388
|
-
const pendingKey = String(
|
|
2390
|
+
const pendingKey = String(messageId3);
|
|
2389
2391
|
if (newPendingActions[pendingKey]) {
|
|
2390
2392
|
delete newPendingActions[pendingKey];
|
|
2391
2393
|
}
|
|
@@ -2395,7 +2397,7 @@ var init_star_handlers = __esm({
|
|
|
2395
2397
|
const loggedUserId = String(get().loggedUserDetails?._id || state.loggedUserDetails?._id || "");
|
|
2396
2398
|
const isStarred2 = starredBy.some((id) => String(id?._id || id) === loggedUserId) || loggedUserId === "" && starredBy.length > 0;
|
|
2397
2399
|
const messages = state.messagesByConversation[sid] || [];
|
|
2398
|
-
const index = messages.findIndex((m) => String(m._id || m.id) === String(
|
|
2400
|
+
const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId3));
|
|
2399
2401
|
let newMessagesByConversation = state.messagesByConversation;
|
|
2400
2402
|
if (index !== -1) {
|
|
2401
2403
|
const newMessages = [...messages];
|
|
@@ -2422,9 +2424,9 @@ var init_star_handlers = __esm({
|
|
|
2422
2424
|
const newStarredByConv = { ...state.starredMessagesByConversation };
|
|
2423
2425
|
const currentStarred = newStarredByConv[sid] || [];
|
|
2424
2426
|
const exists = attachmentId ? currentStarred.some(
|
|
2425
|
-
(m) => m.isAttachment && String(m.messageId) === String(
|
|
2427
|
+
(m) => m.isAttachment && String(m.messageId) === String(messageId3) && String(m.attachmentId) === String(attachmentId)
|
|
2426
2428
|
) : currentStarred.some(
|
|
2427
|
-
(m) => !m.isAttachment && String(m.messageId?._id || m.messageId || m._id || m.id) === String(
|
|
2429
|
+
(m) => !m.isAttachment && String(m.messageId?._id || m.messageId || m._id || m.id) === String(messageId3)
|
|
2428
2430
|
);
|
|
2429
2431
|
const conversation = get().conversations?.find((c) => String(c._id) === String(sid));
|
|
2430
2432
|
const existingCount = state.liveConversationCounts[sid]?.starredCount ?? conversation?.starredCount ?? 0;
|
|
@@ -2432,21 +2434,21 @@ var init_star_handlers = __esm({
|
|
|
2432
2434
|
if (isStarred2 && !exists) {
|
|
2433
2435
|
const fullMessage = attachmentId ? {
|
|
2434
2436
|
_id: attachmentId,
|
|
2435
|
-
messageId:
|
|
2437
|
+
messageId: messageId3,
|
|
2436
2438
|
attachmentId,
|
|
2437
2439
|
isAttachment: true,
|
|
2438
2440
|
attachment: index !== -1 ? newMessagesByConversation[sid][index]?.attachments?.find(
|
|
2439
2441
|
(att) => getAttachmentId(att) === String(attachmentId)
|
|
2440
2442
|
) : payload.attachment,
|
|
2441
2443
|
createdAt: payload.createdAt || (/* @__PURE__ */ new Date()).toISOString()
|
|
2442
|
-
} : index !== -1 ? newMessagesByConversation[sid][index] : { ...payload, _id:
|
|
2444
|
+
} : index !== -1 ? newMessagesByConversation[sid][index] : { ...payload, _id: messageId3 };
|
|
2443
2445
|
newStarredByConv[sid] = [...currentStarred, fullMessage];
|
|
2444
2446
|
starredCount = existingCount + 1;
|
|
2445
2447
|
} else if (!isStarred2 && exists) {
|
|
2446
2448
|
newStarredByConv[sid] = attachmentId ? currentStarred.filter(
|
|
2447
|
-
(m) => !(m.isAttachment && String(m.messageId) === String(
|
|
2449
|
+
(m) => !(m.isAttachment && String(m.messageId) === String(messageId3) && String(m.attachmentId) === String(attachmentId))
|
|
2448
2450
|
) : currentStarred.filter(
|
|
2449
|
-
(m) => String(m.messageId?._id || m.messageId || m._id || m.id) !== String(
|
|
2451
|
+
(m) => String(m.messageId?._id || m.messageId || m._id || m.id) !== String(messageId3)
|
|
2450
2452
|
);
|
|
2451
2453
|
starredCount = Math.max(0, existingCount - 1);
|
|
2452
2454
|
}
|
|
@@ -2472,13 +2474,13 @@ var init_star_handlers = __esm({
|
|
|
2472
2474
|
});
|
|
2473
2475
|
return;
|
|
2474
2476
|
}
|
|
2475
|
-
const { messageId, isStarred, conversationId } = extractMessageData(payload);
|
|
2476
|
-
if (!
|
|
2477
|
+
const { messageId: messageId2, isStarred, conversationId } = extractMessageData(payload);
|
|
2478
|
+
if (!messageId2) return;
|
|
2477
2479
|
set((state) => {
|
|
2478
|
-
const sid = conversationId || findConversationIdByMessageId(state.messagesByConversation,
|
|
2480
|
+
const sid = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId2);
|
|
2479
2481
|
if (!sid) return { lastStarUpdate: payload };
|
|
2480
2482
|
const messages = state.messagesByConversation[sid] || [];
|
|
2481
|
-
const index = messages.findIndex((m) => String(m._id || m.id) === String(
|
|
2483
|
+
const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId2));
|
|
2482
2484
|
let newMessagesByConversation = state.messagesByConversation;
|
|
2483
2485
|
const msg = index !== -1 ? messages[index] : null;
|
|
2484
2486
|
const wasStarred = msg ? !!msg.isStarred : false;
|
|
@@ -2494,13 +2496,13 @@ var init_star_handlers = __esm({
|
|
|
2494
2496
|
const newStarredByConv = { ...state.starredMessagesByConversation };
|
|
2495
2497
|
if (isStarred) {
|
|
2496
2498
|
const currentStarred = newStarredByConv[sid] || [];
|
|
2497
|
-
if (!currentStarred.some((m) => String(m?._id || m?.id || m.messageId?._id || m.messageId?.id) === String(
|
|
2499
|
+
if (!currentStarred.some((m) => String(m?._id || m?.id || m.messageId?._id || m.messageId?.id) === String(messageId2))) {
|
|
2498
2500
|
const fullMsg = msg ? { ...msg, isStarred: true } : payload;
|
|
2499
2501
|
newStarredByConv[sid] = [...currentStarred, fullMsg];
|
|
2500
2502
|
}
|
|
2501
2503
|
} else {
|
|
2502
2504
|
newStarredByConv[sid] = (newStarredByConv[sid] || []).filter(
|
|
2503
|
-
(m) => String(m?._id || m?.id || m.messageId?._id || m.messageId?.id) !== String(
|
|
2505
|
+
(m) => String(m?._id || m?.id || m.messageId?._id || m.messageId?.id) !== String(messageId2)
|
|
2504
2506
|
);
|
|
2505
2507
|
}
|
|
2506
2508
|
const conversation = get().conversations?.find((c) => String(c._id) === String(sid));
|
|
@@ -2515,7 +2517,7 @@ var init_star_handlers = __esm({
|
|
|
2515
2517
|
starredCount = payload.totalCount;
|
|
2516
2518
|
}
|
|
2517
2519
|
const newPendingActions = { ...state.messagePendingActions };
|
|
2518
|
-
const pendingKey = String(
|
|
2520
|
+
const pendingKey = String(messageId2);
|
|
2519
2521
|
if (newPendingActions[pendingKey]) {
|
|
2520
2522
|
delete newPendingActions[pendingKey];
|
|
2521
2523
|
}
|
|
@@ -2636,15 +2638,15 @@ var init_emit_actions = __esm({
|
|
|
2636
2638
|
socket_service_default.emit("dm_unpin", p);
|
|
2637
2639
|
},
|
|
2638
2640
|
emitDmStar: (p) => {
|
|
2639
|
-
const
|
|
2640
|
-
handleStarUpdate(set, get, { ...p, messageId, isStarred: true });
|
|
2641
|
-
set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [
|
|
2641
|
+
const messageId2 = String(p.messageId);
|
|
2642
|
+
handleStarUpdate(set, get, { ...p, messageId: messageId2, isStarred: true });
|
|
2643
|
+
set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [messageId2]: ["star"] } }));
|
|
2642
2644
|
socket_service_default.emit("dm_star", p);
|
|
2643
2645
|
},
|
|
2644
2646
|
emitDmUnstar: (p) => {
|
|
2645
|
-
const
|
|
2646
|
-
handleStarUpdate(set, get, { ...p, messageId, isStarred: false });
|
|
2647
|
-
set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [
|
|
2647
|
+
const messageId2 = String(p.messageId);
|
|
2648
|
+
handleStarUpdate(set, get, { ...p, messageId: messageId2, isStarred: false });
|
|
2649
|
+
set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [messageId2]: ["unstar"] } }));
|
|
2648
2650
|
socket_service_default.emit("dm_unstar", p);
|
|
2649
2651
|
},
|
|
2650
2652
|
emitDmForward: (p) => {
|
|
@@ -2696,15 +2698,15 @@ var init_emit_actions = __esm({
|
|
|
2696
2698
|
socket_service_default.emitGroupUnpin(p);
|
|
2697
2699
|
},
|
|
2698
2700
|
emitGroupStar: (p) => {
|
|
2699
|
-
const
|
|
2700
|
-
handleStarUpdate(set, get, { ...p, messageId, isStarred: true });
|
|
2701
|
-
set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [
|
|
2701
|
+
const messageId2 = String(p.messageId);
|
|
2702
|
+
handleStarUpdate(set, get, { ...p, messageId: messageId2, isStarred: true });
|
|
2703
|
+
set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [messageId2]: ["star"] } }));
|
|
2702
2704
|
socket_service_default.emitGroupStar(p);
|
|
2703
2705
|
},
|
|
2704
2706
|
emitGroupUnstar: (p) => {
|
|
2705
|
-
const
|
|
2706
|
-
handleStarUpdate(set, get, { ...p, messageId, isStarred: false });
|
|
2707
|
-
set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [
|
|
2707
|
+
const messageId2 = String(p.messageId);
|
|
2708
|
+
handleStarUpdate(set, get, { ...p, messageId: messageId2, isStarred: false });
|
|
2709
|
+
set((state) => ({ messagePendingActions: { ...state.messagePendingActions, [messageId2]: ["unstar"] } }));
|
|
2708
2710
|
socket_service_default.emitGroupUnstar(p);
|
|
2709
2711
|
},
|
|
2710
2712
|
emitGroupForward: (p) => {
|
|
@@ -2723,8 +2725,8 @@ var init_emit_actions = __esm({
|
|
|
2723
2725
|
...p.attachmentId ? { attachmentId: String(p.attachmentId) } : {}
|
|
2724
2726
|
});
|
|
2725
2727
|
},
|
|
2726
|
-
clearForwardPending: (
|
|
2727
|
-
clearForwardPendingActions(set,
|
|
2728
|
+
clearForwardPending: (messageId2) => {
|
|
2729
|
+
clearForwardPendingActions(set, messageId2);
|
|
2728
2730
|
},
|
|
2729
2731
|
emitConversationUpdate: (p) => socket_service_default.emitConversationUpdate(p),
|
|
2730
2732
|
emitGroupLeave: (p) => socket_service_default.emitGroupLeave(p),
|
|
@@ -2749,7 +2751,7 @@ var init_message_handlers = __esm({
|
|
|
2749
2751
|
get().conversations,
|
|
2750
2752
|
loggedUserId
|
|
2751
2753
|
);
|
|
2752
|
-
const { messageId } = extractMessageData(lastDM);
|
|
2754
|
+
const { messageId: messageId2 } = extractMessageData(lastDM);
|
|
2753
2755
|
const tempId = lastDM.tempId;
|
|
2754
2756
|
const isFromSelf = loggedUserDetails && String(lastDM.sender?._id || lastDM.sender) === String(loggedUserDetails._id);
|
|
2755
2757
|
const activeConversationId = get().activeConversationId;
|
|
@@ -2759,14 +2761,14 @@ var init_message_handlers = __esm({
|
|
|
2759
2761
|
const newPendingActions = { ...state.messagePendingActions };
|
|
2760
2762
|
if (conversationId) {
|
|
2761
2763
|
const current = nextMessagesByConversation[conversationId] || [];
|
|
2762
|
-
let matchedId =
|
|
2764
|
+
let matchedId = messageId2;
|
|
2763
2765
|
if (tempId && state.messagePendingActions[tempId]) {
|
|
2764
2766
|
matchedId = tempId;
|
|
2765
2767
|
}
|
|
2766
|
-
const exists = current.some((m) => String(m._id || m.id) === String(
|
|
2768
|
+
const exists = current.some((m) => String(m._id || m.id) === String(messageId2));
|
|
2767
2769
|
if (matchedId && matchedId === tempId) {
|
|
2768
2770
|
nextMessagesByConversation[conversationId] = current.map(
|
|
2769
|
-
(m) => String(m.id || m._id) === String(matchedId) ? { ...m, _id:
|
|
2771
|
+
(m) => String(m.id || m._id) === String(matchedId) ? { ...m, _id: messageId2, id: messageId2, status: messageWithStatus.status } : m
|
|
2770
2772
|
);
|
|
2771
2773
|
delete newPendingActions[matchedId];
|
|
2772
2774
|
} else if (!exists) {
|
|
@@ -2821,27 +2823,27 @@ var init_message_handlers = __esm({
|
|
|
2821
2823
|
}
|
|
2822
2824
|
};
|
|
2823
2825
|
handleEditDM = (set, get, payload) => {
|
|
2824
|
-
const { messageId, content, conversationId, attachmentId, caption } = extractMessageData(payload);
|
|
2825
|
-
if (!
|
|
2826
|
+
const { messageId: messageId2, content, conversationId, attachmentId, caption } = extractMessageData(payload);
|
|
2827
|
+
if (!messageId2) return;
|
|
2826
2828
|
const captionText = caption ?? content ?? "";
|
|
2827
2829
|
set((state) => {
|
|
2828
2830
|
let searchConversationId = conversationId;
|
|
2829
2831
|
if (!searchConversationId) {
|
|
2830
|
-
searchConversationId = findConversationIdByMessageId(state.messagesByConversation,
|
|
2832
|
+
searchConversationId = findConversationIdByMessageId(state.messagesByConversation, messageId2);
|
|
2831
2833
|
}
|
|
2832
2834
|
if (!searchConversationId) {
|
|
2833
2835
|
searchConversationId = state.conversations.find(
|
|
2834
|
-
(c) => String(c.lastMessage?._id || c.lastMessage?.id) === String(
|
|
2836
|
+
(c) => String(c.lastMessage?._id || c.lastMessage?.id) === String(messageId2)
|
|
2835
2837
|
)?._id;
|
|
2836
2838
|
}
|
|
2837
|
-
const normalizedEditPayload = { ...payload, messageId, content, conversationId: searchConversationId, _v: Date.now() };
|
|
2839
|
+
const normalizedEditPayload = { ...payload, messageId: messageId2, content, conversationId: searchConversationId, _v: Date.now() };
|
|
2838
2840
|
const newPendingActions = { ...state.messagePendingActions };
|
|
2839
|
-
if (newPendingActions[
|
|
2840
|
-
delete newPendingActions[
|
|
2841
|
+
if (newPendingActions[messageId2]) {
|
|
2842
|
+
delete newPendingActions[messageId2];
|
|
2841
2843
|
}
|
|
2842
2844
|
if (searchConversationId) {
|
|
2843
2845
|
const messages = state.messagesByConversation[searchConversationId] || [];
|
|
2844
|
-
const index = messages.findIndex((m) => String(m._id || m.id) === String(
|
|
2846
|
+
const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId2));
|
|
2845
2847
|
if (index !== -1) {
|
|
2846
2848
|
const newMessages = [...messages];
|
|
2847
2849
|
if (attachmentId) {
|
|
@@ -2867,15 +2869,15 @@ var init_message_handlers = __esm({
|
|
|
2867
2869
|
});
|
|
2868
2870
|
};
|
|
2869
2871
|
handleDeleteDM = (set, get, payload, type) => {
|
|
2870
|
-
const { messageId, conversationId, attachmentId } = extractMessageData(payload);
|
|
2871
|
-
if (!
|
|
2872
|
+
const { messageId: messageId2, conversationId, attachmentId } = extractMessageData(payload);
|
|
2873
|
+
if (!messageId2) return;
|
|
2872
2874
|
set((state) => {
|
|
2873
|
-
const searchConversationId = conversationId || findConversationIdByMessageId(state.messagesByConversation,
|
|
2875
|
+
const searchConversationId = conversationId || findConversationIdByMessageId(state.messagesByConversation, messageId2);
|
|
2874
2876
|
const messageTombstoned = payload.messageTombstoned === true;
|
|
2875
2877
|
let updatedConversations = state.conversations;
|
|
2876
2878
|
if (searchConversationId && !attachmentId) {
|
|
2877
2879
|
updatedConversations = state.conversations.map((c) => {
|
|
2878
|
-
if (String(c._id) === String(searchConversationId) && String(c.lastMessage?._id || c.lastMessage?.id) === String(
|
|
2880
|
+
if (String(c._id) === String(searchConversationId) && String(c.lastMessage?._id || c.lastMessage?.id) === String(messageId2)) {
|
|
2879
2881
|
return { ...c, lastMessage: type === "me" ? { ...c.lastMessage, content: "" } : { ...c.lastMessage, isDeletedForEveryone: true, content: "This message has been deleted" } };
|
|
2880
2882
|
}
|
|
2881
2883
|
return c;
|
|
@@ -2886,7 +2888,7 @@ var init_message_handlers = __esm({
|
|
|
2886
2888
|
if (searchConversationId) {
|
|
2887
2889
|
if (attachmentId) {
|
|
2888
2890
|
const updatedMessages = messages.map((m) => {
|
|
2889
|
-
if (String(m._id || m.id) !== String(
|
|
2891
|
+
if (String(m._id || m.id) !== String(messageId2)) return m;
|
|
2890
2892
|
if (messageTombstoned || type === "everyone" && payload.content) {
|
|
2891
2893
|
return {
|
|
2892
2894
|
...m,
|
|
@@ -2925,22 +2927,22 @@ var init_message_handlers = __esm({
|
|
|
2925
2927
|
[searchConversationId]: updatedMessages
|
|
2926
2928
|
};
|
|
2927
2929
|
} else if (type === "me") {
|
|
2928
|
-
nextMessagesByConversation = { ...state.messagesByConversation, [searchConversationId]: messages.filter((m) => String(m._id || m.id) !== String(
|
|
2930
|
+
nextMessagesByConversation = { ...state.messagesByConversation, [searchConversationId]: messages.filter((m) => String(m._id || m.id) !== String(messageId2)) };
|
|
2929
2931
|
} else {
|
|
2930
2932
|
nextMessagesByConversation = {
|
|
2931
2933
|
...state.messagesByConversation,
|
|
2932
|
-
[searchConversationId]: messages.map((m) => String(m._id || m.id) === String(
|
|
2934
|
+
[searchConversationId]: messages.map((m) => String(m._id || m.id) === String(messageId2) ? { ...m, isDeletedForEveryone: true, content: "" } : m)
|
|
2933
2935
|
};
|
|
2934
2936
|
}
|
|
2935
2937
|
}
|
|
2936
2938
|
const newPendingActions = { ...state.messagePendingActions };
|
|
2937
|
-
if (newPendingActions[
|
|
2938
|
-
delete newPendingActions[
|
|
2939
|
+
if (newPendingActions[messageId2]) {
|
|
2940
|
+
delete newPendingActions[messageId2];
|
|
2939
2941
|
}
|
|
2940
|
-
const shouldMarkWholeMessageDeleted = type === "me" && !attachmentId && !state.deletedForMeIds.includes(
|
|
2942
|
+
const shouldMarkWholeMessageDeleted = type === "me" && !attachmentId && !state.deletedForMeIds.includes(messageId2);
|
|
2941
2943
|
return {
|
|
2942
2944
|
lastDeleteDM: { ...payload, deleteType: type },
|
|
2943
|
-
deletedForMeIds: shouldMarkWholeMessageDeleted ? [...state.deletedForMeIds,
|
|
2945
|
+
deletedForMeIds: shouldMarkWholeMessageDeleted ? [...state.deletedForMeIds, messageId2] : state.deletedForMeIds,
|
|
2944
2946
|
messagesByConversation: nextMessagesByConversation,
|
|
2945
2947
|
conversations: updatedConversations,
|
|
2946
2948
|
messagePendingActions: newPendingActions
|
|
@@ -3014,15 +3016,15 @@ var init_dm_actions = __esm({
|
|
|
3014
3016
|
},
|
|
3015
3017
|
receivedStatusUpdate: (payload) => {
|
|
3016
3018
|
const data = extractMessageData(payload);
|
|
3017
|
-
const { messageId, status } = data;
|
|
3019
|
+
const { messageId: messageId2, status } = data;
|
|
3018
3020
|
let { conversationId } = data;
|
|
3019
|
-
if (!
|
|
3021
|
+
if (!messageId2 || !status) return;
|
|
3020
3022
|
set({ lastStatusUpdate: payload });
|
|
3021
3023
|
if (!conversationId) {
|
|
3022
|
-
conversationId = findConversationIdByMessageId(get().messagesByConversation,
|
|
3024
|
+
conversationId = findConversationIdByMessageId(get().messagesByConversation, messageId2) || findConversationIdByLastMessageId(get().conversations, messageId2) || void 0;
|
|
3023
3025
|
}
|
|
3024
3026
|
set((state) => ({
|
|
3025
|
-
...applyMessageStatusToStore(state, String(
|
|
3027
|
+
...applyMessageStatusToStore(state, String(messageId2), status, conversationId)
|
|
3026
3028
|
}));
|
|
3027
3029
|
},
|
|
3028
3030
|
receivedDMMarkRead: (payload) => {
|
|
@@ -3079,7 +3081,7 @@ var init_group_handlers = __esm({
|
|
|
3079
3081
|
get().conversations,
|
|
3080
3082
|
loggedUserId
|
|
3081
3083
|
);
|
|
3082
|
-
const { messageId } = extractMessageData(lastDM);
|
|
3084
|
+
const { messageId: messageId2 } = extractMessageData(lastDM);
|
|
3083
3085
|
const tempId = lastDM.tempId;
|
|
3084
3086
|
const activeConversationId = get().activeConversationId;
|
|
3085
3087
|
const isOpenConversation = conversationId && String(conversationId) === String(activeConversationId);
|
|
@@ -3116,23 +3118,23 @@ var init_group_handlers = __esm({
|
|
|
3116
3118
|
);
|
|
3117
3119
|
if (optimisticMsg) matchedTempId = optimisticMsg.id;
|
|
3118
3120
|
}
|
|
3119
|
-
const messageExists = current.some((m) => String(m._id || m.id) === String(
|
|
3121
|
+
const messageExists = current.some((m) => String(m._id || m.id) === String(messageId2));
|
|
3120
3122
|
if (!messageExists) {
|
|
3121
3123
|
nextMessagesByConversation[conversationId] = [...current, {
|
|
3122
3124
|
...lastDM,
|
|
3123
|
-
_id:
|
|
3124
|
-
id:
|
|
3125
|
+
_id: messageId2,
|
|
3126
|
+
id: messageId2,
|
|
3125
3127
|
status: lastDM.status || "sent"
|
|
3126
3128
|
}];
|
|
3127
3129
|
} else {
|
|
3128
3130
|
nextMessagesByConversation[conversationId] = current.map(
|
|
3129
|
-
(m) => String(m._id || m.id) === String(
|
|
3131
|
+
(m) => String(m._id || m.id) === String(messageId2) ? { ...m, status: lastDM.status || "sent" } : m
|
|
3130
3132
|
);
|
|
3131
3133
|
}
|
|
3132
3134
|
if (matchedTempId) {
|
|
3133
3135
|
delete newPendingActions[matchedTempId];
|
|
3134
3136
|
nextMessagesByConversation[conversationId] = nextMessagesByConversation[conversationId].map(
|
|
3135
|
-
(m) => String(m.id || m._id) === String(matchedTempId) ? { ...m, _id:
|
|
3137
|
+
(m) => String(m.id || m._id) === String(matchedTempId) ? { ...m, _id: messageId2, id: messageId2, status: lastDM.status || "sent" } : m
|
|
3136
3138
|
);
|
|
3137
3139
|
}
|
|
3138
3140
|
}
|
|
@@ -3205,10 +3207,10 @@ var init_group_handlers = __esm({
|
|
|
3205
3207
|
(c) => String(c._id) === String(conversationId)
|
|
3206
3208
|
);
|
|
3207
3209
|
const isGroupChat = isGroupConversation(targetConv);
|
|
3208
|
-
if (loggedUserDetails?._id &&
|
|
3210
|
+
if (loggedUserDetails?._id && messageId2 && isGroupChat) {
|
|
3209
3211
|
get().emitGroupMessageDelivered({
|
|
3210
3212
|
conversationId,
|
|
3211
|
-
messageId,
|
|
3213
|
+
messageId: messageId2,
|
|
3212
3214
|
userId: loggedUserDetails._id
|
|
3213
3215
|
});
|
|
3214
3216
|
}
|
|
@@ -3286,15 +3288,15 @@ var init_group_actions2 = __esm({
|
|
|
3286
3288
|
receivedGroupStatusUpdate: (payload) => {
|
|
3287
3289
|
const data = extractMessageData(payload);
|
|
3288
3290
|
let { conversationId } = data;
|
|
3289
|
-
const { messageId, status } = data;
|
|
3291
|
+
const { messageId: messageId2, status } = data;
|
|
3290
3292
|
set({ lastStatusUpdate: payload });
|
|
3291
3293
|
if (!status) return;
|
|
3292
|
-
if (
|
|
3294
|
+
if (messageId2) {
|
|
3293
3295
|
if (!conversationId) {
|
|
3294
|
-
conversationId = findConversationIdByMessageId(get().messagesByConversation,
|
|
3296
|
+
conversationId = findConversationIdByMessageId(get().messagesByConversation, messageId2) || findConversationIdByLastMessageId(get().conversations, messageId2) || void 0;
|
|
3295
3297
|
}
|
|
3296
3298
|
set((state) => ({
|
|
3297
|
-
...applyMessageStatusToStore(state, String(
|
|
3299
|
+
...applyMessageStatusToStore(state, String(messageId2), status, conversationId)
|
|
3298
3300
|
}));
|
|
3299
3301
|
return;
|
|
3300
3302
|
}
|
|
@@ -3510,7 +3512,7 @@ var init_receive = __esm({
|
|
|
3510
3512
|
};
|
|
3511
3513
|
});
|
|
3512
3514
|
},
|
|
3513
|
-
markDeletedForMe: (
|
|
3515
|
+
markDeletedForMe: (messageId2) => set((state) => ({ deletedForMeIds: [...state.deletedForMeIds, messageId2] }))
|
|
3514
3516
|
});
|
|
3515
3517
|
createReceiveActions = (set, get) => ({
|
|
3516
3518
|
...createDmReceiveActions(set, get),
|
|
@@ -3535,13 +3537,13 @@ var init_search_actions = __esm({
|
|
|
3535
3537
|
init_api_service();
|
|
3536
3538
|
init_store_helpers();
|
|
3537
3539
|
createSearchActions = (set, _get) => ({
|
|
3538
|
-
fetchSearchMessageContext: async (
|
|
3540
|
+
fetchSearchMessageContext: async (messageId2, options) => {
|
|
3539
3541
|
const searchMode = options?.searchMode !== false;
|
|
3540
|
-
set({ isSearchActive: searchMode, searchedMessageId:
|
|
3542
|
+
set({ isSearchActive: searchMode, searchedMessageId: messageId2, isFetchingMessages: true });
|
|
3541
3543
|
try {
|
|
3542
|
-
const response = await searchMessagesContext(
|
|
3544
|
+
const response = await searchMessagesContext(messageId2);
|
|
3543
3545
|
const data = response.data?.list || response.data?.messages || response.messages || response.data || [];
|
|
3544
|
-
const highlightId = response.data?.highlightMessageId ||
|
|
3546
|
+
const highlightId = response.data?.highlightMessageId || messageId2;
|
|
3545
3547
|
if (data.length > 0) {
|
|
3546
3548
|
const conversationId = data[0].conversationId;
|
|
3547
3549
|
if (conversationId) {
|
|
@@ -3570,7 +3572,7 @@ var init_search_actions = __esm({
|
|
|
3570
3572
|
}
|
|
3571
3573
|
},
|
|
3572
3574
|
setSearchActive: (active) => set({ isSearchActive: active }),
|
|
3573
|
-
setSearchedMessageId: (
|
|
3575
|
+
setSearchedMessageId: (messageId2) => set({ searchedMessageId: messageId2 })
|
|
3574
3576
|
});
|
|
3575
3577
|
}
|
|
3576
3578
|
});
|
|
@@ -3937,6 +3939,7 @@ var buildIncomingMessageFromDM = (lastDM, loggedUserId, conversations) => {
|
|
|
3937
3939
|
content: lastDM.content || lastDM.message?.content || "",
|
|
3938
3940
|
sender: lastDM.sender?.name || lastDM.fromUserId || (isMe ? "Me" : "User"),
|
|
3939
3941
|
senderId: String(lastDM.sender?._id || lastDM.sender || lastDM.fromUserId || ""),
|
|
3942
|
+
senderImage: lastDM.sender?.image,
|
|
3940
3943
|
timestamp: lastDM.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
|
|
3941
3944
|
isOwnMessage: isMe,
|
|
3942
3945
|
channelId,
|
|
@@ -4094,9 +4097,9 @@ var syncLocalMessagesOnPinUpdate = (prev, lastPinUpdate) => {
|
|
|
4094
4097
|
return next;
|
|
4095
4098
|
};
|
|
4096
4099
|
var syncLocalMessagesOnStarUpdate = (prev, lastStarUpdate, loggedUserId) => {
|
|
4097
|
-
const
|
|
4098
|
-
if (!
|
|
4099
|
-
const mid = String(
|
|
4100
|
+
const messageId2 = lastStarUpdate.messageId || lastStarUpdate._id;
|
|
4101
|
+
if (!messageId2) return null;
|
|
4102
|
+
const mid = String(messageId2);
|
|
4100
4103
|
let isStarred;
|
|
4101
4104
|
if (typeof lastStarUpdate.isStarred === "boolean") {
|
|
4102
4105
|
isStarred = lastStarUpdate.isStarred;
|
|
@@ -4115,9 +4118,9 @@ var syncLocalMessagesOnStarUpdate = (prev, lastStarUpdate, loggedUserId) => {
|
|
|
4115
4118
|
return next;
|
|
4116
4119
|
};
|
|
4117
4120
|
var syncLocalMessagesOnReactionUpdate = (prev, lastReactionUpdate, messagesByConversation) => {
|
|
4118
|
-
const
|
|
4119
|
-
if (!
|
|
4120
|
-
const mid = String(
|
|
4121
|
+
const messageId2 = lastReactionUpdate.messageId || lastReactionUpdate._id;
|
|
4122
|
+
if (!messageId2) return prev;
|
|
4123
|
+
const mid = String(messageId2);
|
|
4121
4124
|
let storeReactions;
|
|
4122
4125
|
for (const msgs of Object.values(messagesByConversation)) {
|
|
4123
4126
|
const found = msgs.find((m) => String(m._id || m.id) === mid);
|
|
@@ -4168,7 +4171,7 @@ var syncLocalMessagesOnReactionUpdate = (prev, lastReactionUpdate, messagesByCon
|
|
|
4168
4171
|
return changed ? next : prev;
|
|
4169
4172
|
};
|
|
4170
4173
|
var syncLocalMessagesOnDelete = (prev, lastDeleteDM) => {
|
|
4171
|
-
const
|
|
4174
|
+
const messageId2 = lastDeleteDM.messageId || lastDeleteDM._id;
|
|
4172
4175
|
const deleteType = lastDeleteDM.deleteType || "everyone";
|
|
4173
4176
|
const attachmentId = lastDeleteDM.attachmentId ? String(lastDeleteDM.attachmentId) : null;
|
|
4174
4177
|
const messageTombstoned = lastDeleteDM.messageTombstoned === true;
|
|
@@ -4176,7 +4179,7 @@ var syncLocalMessagesOnDelete = (prev, lastDeleteDM) => {
|
|
|
4176
4179
|
Object.keys(next).forEach((channelId) => {
|
|
4177
4180
|
if (attachmentId) {
|
|
4178
4181
|
next[channelId] = next[channelId].map((message) => {
|
|
4179
|
-
if (String(message._id || message.id) !== String(
|
|
4182
|
+
if (String(message._id || message.id) !== String(messageId2)) {
|
|
4180
4183
|
return message;
|
|
4181
4184
|
}
|
|
4182
4185
|
return applyLocalAttachmentDelete(
|
|
@@ -4190,26 +4193,26 @@ var syncLocalMessagesOnDelete = (prev, lastDeleteDM) => {
|
|
|
4190
4193
|
}
|
|
4191
4194
|
if (deleteType === "me") {
|
|
4192
4195
|
next[channelId] = next[channelId].filter(
|
|
4193
|
-
(m) => String(m._id || m.id) !== String(
|
|
4196
|
+
(m) => String(m._id || m.id) !== String(messageId2)
|
|
4194
4197
|
);
|
|
4195
4198
|
} else {
|
|
4196
4199
|
next[channelId] = next[channelId].map(
|
|
4197
|
-
(m) => String(m._id || m.id) === String(
|
|
4200
|
+
(m) => String(m._id || m.id) === String(messageId2) ? { ...m, isDeletedForEveryone: true } : m
|
|
4198
4201
|
);
|
|
4199
4202
|
}
|
|
4200
4203
|
});
|
|
4201
4204
|
return next;
|
|
4202
4205
|
};
|
|
4203
4206
|
var syncLocalMessagesOnEdit = (prev, lastEditDM) => {
|
|
4204
|
-
const
|
|
4207
|
+
const messageId2 = lastEditDM.messageId || lastEditDM._id;
|
|
4205
4208
|
const content = lastEditDM.content;
|
|
4206
4209
|
const attachmentId = lastEditDM.attachmentId ? String(lastEditDM.attachmentId) : null;
|
|
4207
4210
|
const caption = lastEditDM.caption ?? content;
|
|
4208
|
-
if (!
|
|
4211
|
+
if (!messageId2) return null;
|
|
4209
4212
|
const next = { ...prev };
|
|
4210
4213
|
Object.keys(next).forEach((channelId) => {
|
|
4211
4214
|
const messages = next[channelId];
|
|
4212
|
-
const index = messages.findIndex((m) => String(m._id || m.id) === String(
|
|
4215
|
+
const index = messages.findIndex((m) => String(m._id || m.id) === String(messageId2));
|
|
4213
4216
|
if (index !== -1) {
|
|
4214
4217
|
const updated = [...messages];
|
|
4215
4218
|
const current = updated[index];
|
|
@@ -4479,7 +4482,7 @@ var Chat = ({
|
|
|
4479
4482
|
const status = useStore((s) => s.status);
|
|
4480
4483
|
const error = useStore((s) => s.error);
|
|
4481
4484
|
useChatSync();
|
|
4482
|
-
|
|
4485
|
+
React2__default.useEffect(() => {
|
|
4483
4486
|
const clientId = client?.id;
|
|
4484
4487
|
const initializeChat = async () => {
|
|
4485
4488
|
if (!clientId || !loggedUserDetails) return;
|
|
@@ -4568,28 +4571,28 @@ var Chat = ({
|
|
|
4568
4571
|
queryParamApis: queryParamApis ?? ["get"],
|
|
4569
4572
|
queryParamsByApi: queryParamsByApi ?? {}
|
|
4570
4573
|
});
|
|
4571
|
-
|
|
4574
|
+
React2__default.useEffect(() => {
|
|
4572
4575
|
setChatQueryParams(queryParams);
|
|
4573
4576
|
setChatQueryParamApis(queryParamApis);
|
|
4574
4577
|
setChatQueryParamsByApi(queryParamsByApi);
|
|
4575
4578
|
}, [queryConfigKey]);
|
|
4576
|
-
|
|
4579
|
+
React2__default.useEffect(() => {
|
|
4577
4580
|
if (lastDM && onMessageReceived) {
|
|
4578
4581
|
onMessageReceived(lastDM);
|
|
4579
4582
|
}
|
|
4580
4583
|
}, [lastDM, onMessageReceived]);
|
|
4581
|
-
|
|
4584
|
+
React2__default.useEffect(() => {
|
|
4582
4585
|
if (status === "connected" && onSocketConnected) {
|
|
4583
4586
|
const socketId = useStore.getState().socketId;
|
|
4584
4587
|
if (socketId) onSocketConnected(socketId);
|
|
4585
4588
|
}
|
|
4586
4589
|
}, [status, onSocketConnected]);
|
|
4587
|
-
|
|
4590
|
+
React2__default.useEffect(() => {
|
|
4588
4591
|
if (status === "error" && error && onSocketError) {
|
|
4589
4592
|
onSocketError(error);
|
|
4590
4593
|
}
|
|
4591
4594
|
}, [status, error, onSocketError]);
|
|
4592
|
-
const contextValue =
|
|
4595
|
+
const contextValue = React2__default.useMemo(
|
|
4593
4596
|
() => ({
|
|
4594
4597
|
onSendMessage,
|
|
4595
4598
|
client,
|
|
@@ -4609,7 +4612,7 @@ var Chat = ({
|
|
|
4609
4612
|
messagesData
|
|
4610
4613
|
]
|
|
4611
4614
|
);
|
|
4612
|
-
const customization =
|
|
4615
|
+
const customization = React2__default.useMemo(
|
|
4613
4616
|
() => ({
|
|
4614
4617
|
components: uiConfig.components,
|
|
4615
4618
|
classNames: uiConfig.classNames,
|
|
@@ -6704,20 +6707,35 @@ init_chat_constants();
|
|
|
6704
6707
|
// src/chat/lib/last-message-preview.ts
|
|
6705
6708
|
init_store_helpers();
|
|
6706
6709
|
|
|
6707
|
-
// src/chat/lib/
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
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";
|
|
6716
6725
|
}
|
|
6717
|
-
|
|
6718
|
-
|
|
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`;
|
|
6719
6738
|
}
|
|
6720
|
-
return name.trim() || trimmed;
|
|
6721
6739
|
}
|
|
6722
6740
|
|
|
6723
6741
|
// src/chat/lib/last-message-preview.ts
|
|
@@ -6725,21 +6743,30 @@ function getAttachmentOnlyPreviewText(attachments) {
|
|
|
6725
6743
|
const images = attachments.filter((att2) => att2.type === "image" && att2.url);
|
|
6726
6744
|
const videos = attachments.filter((att2) => att2.type === "video" && att2.url);
|
|
6727
6745
|
const audios = attachments.filter((att2) => att2.type === "audio" && att2.url);
|
|
6728
|
-
|
|
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);
|
|
6729
6750
|
if (images.length === 1) {
|
|
6730
|
-
return images[0].caption?.trim() || "
|
|
6751
|
+
return images[0].caption?.trim() || getAttachmentTypePreviewLabel("image");
|
|
6731
6752
|
}
|
|
6732
|
-
if (videos.length > 1) return
|
|
6753
|
+
if (videos.length > 1) return getAttachmentCountPreviewLabel("video", videos.length);
|
|
6733
6754
|
if (videos.length === 1) {
|
|
6734
|
-
return videos[0].caption?.trim() || "
|
|
6755
|
+
return videos[0].caption?.trim() || getAttachmentTypePreviewLabel("video");
|
|
6735
6756
|
}
|
|
6736
|
-
if (audios.length > 1) return
|
|
6757
|
+
if (audios.length > 1) return getAttachmentCountPreviewLabel("audio", audios.length);
|
|
6737
6758
|
if (audios.length === 1) {
|
|
6738
|
-
return audios[0].caption?.trim() || "
|
|
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);
|
|
6739
6767
|
}
|
|
6740
|
-
if (attachments.length > 1) return `${attachments.length} files`;
|
|
6741
6768
|
const att = attachments[0];
|
|
6742
|
-
return att
|
|
6769
|
+
return att?.caption?.trim() || getAttachmentTypePreviewLabel(att?.type);
|
|
6743
6770
|
}
|
|
6744
6771
|
function getLastMessageSidebarPreview(message) {
|
|
6745
6772
|
const content = String(message?.content || "").trim();
|
|
@@ -6753,6 +6780,10 @@ function getLastMessageSidebarPreview(message) {
|
|
|
6753
6780
|
if (attachments.length > 0) {
|
|
6754
6781
|
return getAttachmentOnlyPreviewText(attachments);
|
|
6755
6782
|
}
|
|
6783
|
+
const messageType = String(message?.type || "").toLowerCase();
|
|
6784
|
+
if (messageType && messageType !== "text") {
|
|
6785
|
+
return getAttachmentTypePreviewLabel(messageType);
|
|
6786
|
+
}
|
|
6756
6787
|
return "No messages yet";
|
|
6757
6788
|
}
|
|
6758
6789
|
function getMessagePreviewText(message, fallback = "Message") {
|
|
@@ -6764,6 +6795,10 @@ function getMessagePreviewText(message, fallback = "Message") {
|
|
|
6764
6795
|
if (attachments.length > 0) {
|
|
6765
6796
|
return getAttachmentOnlyPreviewText(attachments);
|
|
6766
6797
|
}
|
|
6798
|
+
const messageType = String(message?.type || "").toLowerCase();
|
|
6799
|
+
if (messageType && messageType !== "text") {
|
|
6800
|
+
return getAttachmentTypePreviewLabel(messageType);
|
|
6801
|
+
}
|
|
6767
6802
|
return fallback;
|
|
6768
6803
|
}
|
|
6769
6804
|
|
|
@@ -7405,7 +7440,7 @@ function highlightSearchMatch(text, query) {
|
|
|
7405
7440
|
children: part
|
|
7406
7441
|
},
|
|
7407
7442
|
`${part}-${index}`
|
|
7408
|
-
) : /* @__PURE__ */ jsx(
|
|
7443
|
+
) : /* @__PURE__ */ jsx(React2__default.Fragment, { children: part }, `${part}-${index}`)
|
|
7409
7444
|
);
|
|
7410
7445
|
}
|
|
7411
7446
|
function getMessagePreview(message) {
|
|
@@ -7820,11 +7855,11 @@ function buildAttachmentSummary(attachments) {
|
|
|
7820
7855
|
else fileCount += 1;
|
|
7821
7856
|
}
|
|
7822
7857
|
const parts = [];
|
|
7823
|
-
if (imageCount) parts.push(
|
|
7824
|
-
if (videoCount) parts.push(
|
|
7825
|
-
if (audioCount) parts.push(
|
|
7826
|
-
if (fileCount) parts.push(
|
|
7827
|
-
return parts.join(", ") || "
|
|
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");
|
|
7828
7863
|
}
|
|
7829
7864
|
function mapSavedMessageAttachments(msg, messageObj, ctx) {
|
|
7830
7865
|
const loggedUserId = String(ctx.loggedUserDetails?._id || "");
|
|
@@ -7886,11 +7921,19 @@ function resolveSavedMessageContent(messageObj, msg) {
|
|
|
7886
7921
|
}
|
|
7887
7922
|
return { content: filename, messageType: "file", previewUrl: void 0 };
|
|
7888
7923
|
}
|
|
7889
|
-
if (messageType === "image")
|
|
7890
|
-
|
|
7891
|
-
|
|
7892
|
-
if (messageType === "
|
|
7893
|
-
|
|
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 };
|
|
7894
7937
|
}
|
|
7895
7938
|
function getMessageId(msg) {
|
|
7896
7939
|
if (msg?.messageId && typeof msg.messageId === "object") {
|
|
@@ -7924,7 +7967,7 @@ function readSenderFromRecord(record) {
|
|
|
7924
7967
|
}
|
|
7925
7968
|
function resolveSenderName(msg, ctx) {
|
|
7926
7969
|
const messageObj = getMessageObject(msg);
|
|
7927
|
-
const
|
|
7970
|
+
const messageId2 = getMessageId(msg);
|
|
7928
7971
|
const loggedId = String(ctx.loggedUserDetails?._id || "");
|
|
7929
7972
|
const tryRecord = (record) => {
|
|
7930
7973
|
const parsed = readSenderFromRecord(record);
|
|
@@ -7941,9 +7984,9 @@ function resolveSenderName(msg, ctx) {
|
|
|
7941
7984
|
const hit = tryRecord(record);
|
|
7942
7985
|
if (hit) return hit;
|
|
7943
7986
|
}
|
|
7944
|
-
if (
|
|
7987
|
+
if (messageId2 && ctx.conversationMessages?.length) {
|
|
7945
7988
|
const found = ctx.conversationMessages.find(
|
|
7946
|
-
(m) => String(m._id || m.id) === String(
|
|
7989
|
+
(m) => String(m._id || m.id) === String(messageId2)
|
|
7947
7990
|
);
|
|
7948
7991
|
if (found) {
|
|
7949
7992
|
const hit = tryRecord(found);
|
|
@@ -7994,7 +8037,7 @@ function parseSavedMessage(msg, ctx = {}) {
|
|
|
7994
8037
|
const mode = ctx.mode || "pinned";
|
|
7995
8038
|
const prefs = ctx.dateTimePrefs ?? {};
|
|
7996
8039
|
if (msg?.isAttachment) {
|
|
7997
|
-
const
|
|
8040
|
+
const messageId3 = String(msg.messageId || "");
|
|
7998
8041
|
const attachmentId2 = String(msg.attachmentId || msg._id || "");
|
|
7999
8042
|
const attachments2 = mapSavedMessageAttachments(msg, null, ctx);
|
|
8000
8043
|
const { content: content2, previewUrl: previewUrl2, messageType: messageType2 } = resolveSavedMessageContent(null, msg);
|
|
@@ -8002,8 +8045,8 @@ function parseSavedMessage(msg, ctx = {}) {
|
|
|
8002
8045
|
const actionAt2 = msg?.createdAt || msg?.updatedAt || "";
|
|
8003
8046
|
const bodyText2 = String(msg.attachment?.caption || "").trim() || void 0;
|
|
8004
8047
|
return {
|
|
8005
|
-
id: attachmentId2 ||
|
|
8006
|
-
messageId:
|
|
8048
|
+
id: attachmentId2 || messageId3,
|
|
8049
|
+
messageId: messageId3,
|
|
8007
8050
|
attachmentId: attachmentId2 || void 0,
|
|
8008
8051
|
content: content2,
|
|
8009
8052
|
bodyText: bodyText2,
|
|
@@ -8022,7 +8065,7 @@ function parseSavedMessage(msg, ctx = {}) {
|
|
|
8022
8065
|
}
|
|
8023
8066
|
const messageObj = getMessageObject(msg);
|
|
8024
8067
|
const id = getMessageId(msg);
|
|
8025
|
-
const
|
|
8068
|
+
const messageId2 = id;
|
|
8026
8069
|
const attachmentId = msg?.attachmentId ? String(msg.attachmentId) : void 0;
|
|
8027
8070
|
const attachments = mapSavedMessageAttachments(msg, messageObj, ctx);
|
|
8028
8071
|
const rawContent = messageObj?.content ?? msg?.content ?? msg?.messageId?.content ?? "";
|
|
@@ -8044,8 +8087,8 @@ function parseSavedMessage(msg, ctx = {}) {
|
|
|
8044
8087
|
metaLabel = "Starred by you";
|
|
8045
8088
|
}
|
|
8046
8089
|
return {
|
|
8047
|
-
id: attachmentId ? `${
|
|
8048
|
-
messageId,
|
|
8090
|
+
id: attachmentId ? `${messageId2}:${attachmentId}` : id,
|
|
8091
|
+
messageId: messageId2,
|
|
8049
8092
|
attachmentId,
|
|
8050
8093
|
content: displayContent,
|
|
8051
8094
|
bodyText,
|
|
@@ -8075,6 +8118,22 @@ function groupSavedMessages(items) {
|
|
|
8075
8118
|
}));
|
|
8076
8119
|
}
|
|
8077
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
|
+
|
|
8078
8137
|
// src/chat/header/saved-message/saved-message-utils.ts
|
|
8079
8138
|
var AVATAR_PALETTES = [
|
|
8080
8139
|
"bg-violet-500/15 text-violet-600 dark:text-violet-300",
|
|
@@ -8496,6 +8555,18 @@ var MessageStatus = ({ status, isPending, className }) => {
|
|
|
8496
8555
|
) });
|
|
8497
8556
|
};
|
|
8498
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
|
+
}
|
|
8499
8570
|
function ForwardDoubleIcon({ className }) {
|
|
8500
8571
|
return /* @__PURE__ */ jsxs(
|
|
8501
8572
|
"svg",
|
|
@@ -8533,22 +8604,10 @@ function MessageForwardedLabel({ isSender, className, overlay }) {
|
|
|
8533
8604
|
}
|
|
8534
8605
|
);
|
|
8535
8606
|
}
|
|
8536
|
-
function GroupSenderName({ name, className }) {
|
|
8537
|
-
return /* @__PURE__ */ jsx(
|
|
8538
|
-
"span",
|
|
8539
|
-
{
|
|
8540
|
-
className: cn(
|
|
8541
|
-
"block max-w-full truncate text-[13px] font-semibold leading-[1.15] tracking-tight text-(--chat-incoming-text)",
|
|
8542
|
-
className
|
|
8543
|
-
),
|
|
8544
|
-
children: name
|
|
8545
|
-
}
|
|
8546
|
-
);
|
|
8547
|
-
}
|
|
8548
8607
|
|
|
8549
8608
|
// src/chat/lib/chat-message-bubble.ts
|
|
8550
|
-
function getBubbleCornerClasses() {
|
|
8551
|
-
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";
|
|
8552
8611
|
}
|
|
8553
8612
|
function getChatBubbleClasses({
|
|
8554
8613
|
isSender = false,
|
|
@@ -8559,7 +8618,7 @@ function getChatBubbleClasses({
|
|
|
8559
8618
|
const isNeutral = resolvedSurface === "neutral";
|
|
8560
8619
|
return cn(
|
|
8561
8620
|
"relative",
|
|
8562
|
-
getBubbleCornerClasses(),
|
|
8621
|
+
getBubbleCornerClasses(isSender),
|
|
8563
8622
|
resolvedSurface === "sent" && "chat-bubble-sent bg-(--chat-theme) text-white",
|
|
8564
8623
|
resolvedSurface === "received" && "chat-bubble-received border border-(--chat-border)/60 bg-(--chat-incoming-bubble) text-(--chat-incoming-text)",
|
|
8565
8624
|
isNeutral && "chat-bubble-received border border-(--chat-border)/60 bg-(--chat-incoming-bubble) text-(--chat-incoming-text)",
|
|
@@ -10349,7 +10408,8 @@ function MessageAttachmentsView({
|
|
|
10349
10408
|
isGroupedWithPrev = false,
|
|
10350
10409
|
isGroupedWithNext = false,
|
|
10351
10410
|
showSenderLabel = false,
|
|
10352
|
-
senderName
|
|
10411
|
+
senderName,
|
|
10412
|
+
senderId
|
|
10353
10413
|
}) {
|
|
10354
10414
|
const [documentPreview, setDocumentPreview] = useState(null);
|
|
10355
10415
|
const visibleAttachments = getVisibleAttachments(attachments);
|
|
@@ -10406,7 +10466,13 @@ function MessageAttachmentsView({
|
|
|
10406
10466
|
isImageOnlyBubble ? "px-2.5 pt-1.5 pb-1" : "px-0.5 pb-0.5"
|
|
10407
10467
|
),
|
|
10408
10468
|
children: [
|
|
10409
|
-
canShowSenderName ? /* @__PURE__ */ jsx(
|
|
10469
|
+
canShowSenderName ? /* @__PURE__ */ jsx(
|
|
10470
|
+
GroupSenderName,
|
|
10471
|
+
{
|
|
10472
|
+
name: senderName,
|
|
10473
|
+
colorSeed: senderId || senderName
|
|
10474
|
+
}
|
|
10475
|
+
) : null,
|
|
10410
10476
|
showForwardedInHeader ? /* @__PURE__ */ jsx(
|
|
10411
10477
|
MessageForwardedLabel,
|
|
10412
10478
|
{
|
|
@@ -10950,7 +11016,7 @@ function collectConversationAttachments(messages) {
|
|
|
10950
11016
|
const items = [];
|
|
10951
11017
|
for (const message of messages) {
|
|
10952
11018
|
if (message?.isDeletedForEveryone) continue;
|
|
10953
|
-
const
|
|
11019
|
+
const messageId2 = String(message._id || message.id || "");
|
|
10954
11020
|
const createdAt = message.createdAt || message.timestamp;
|
|
10955
11021
|
const messageType = message.type || "text";
|
|
10956
11022
|
for (const attachment of message.attachments || []) {
|
|
@@ -10968,13 +11034,35 @@ function collectConversationAttachments(messages) {
|
|
|
10968
11034
|
url,
|
|
10969
11035
|
name,
|
|
10970
11036
|
type: resolveFileCategory(name, fileType, resolvedType),
|
|
10971
|
-
messageId,
|
|
11037
|
+
messageId: messageId2,
|
|
10972
11038
|
createdAt,
|
|
10973
11039
|
size: typeof attachment.size === "number" ? attachment.size : void 0,
|
|
10974
11040
|
duration: typeof attachment.duration === "number" ? attachment.duration : void 0,
|
|
10975
11041
|
fileType
|
|
10976
11042
|
});
|
|
10977
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
|
+
}
|
|
10978
11066
|
}
|
|
10979
11067
|
return items.sort(
|
|
10980
11068
|
(a, b) => new Date(b.createdAt || 0).getTime() - new Date(a.createdAt || 0).getTime()
|
|
@@ -11185,9 +11273,13 @@ function AttachmentSection({
|
|
|
11185
11273
|
}
|
|
11186
11274
|
var AttachmentsDrawer = ({ isOpen, onOpenChange, conversationId }) => {
|
|
11187
11275
|
const messagesByConversation = useStore((s) => s.messagesByConversation);
|
|
11276
|
+
const messagesMetadata = useStore((s) => s.messagesMetadata);
|
|
11277
|
+
const fetchMessages2 = useStore((s) => s.fetchMessages);
|
|
11188
11278
|
const [sectionVisibleCount, setSectionVisibleCount] = useState({});
|
|
11189
11279
|
const [documentPreview, setDocumentPreview] = useState(null);
|
|
11190
11280
|
const [imageLightboxIndex, setImageLightboxIndex] = useState(null);
|
|
11281
|
+
const hasLoadedMessages = conversationId ? Boolean(messagesMetadata[conversationId]?.isFirstPage) : false;
|
|
11282
|
+
const isLoading = isOpen && !!conversationId && !hasLoadedMessages;
|
|
11191
11283
|
useEffect(() => {
|
|
11192
11284
|
if (!isOpen) {
|
|
11193
11285
|
setSectionVisibleCount({});
|
|
@@ -11198,6 +11290,10 @@ var AttachmentsDrawer = ({ isOpen, onOpenChange, conversationId }) => {
|
|
|
11198
11290
|
useEffect(() => {
|
|
11199
11291
|
setSectionVisibleCount({});
|
|
11200
11292
|
}, [conversationId]);
|
|
11293
|
+
useEffect(() => {
|
|
11294
|
+
if (!isOpen || !conversationId || hasLoadedMessages) return;
|
|
11295
|
+
fetchMessages2(conversationId);
|
|
11296
|
+
}, [isOpen, conversationId, hasLoadedMessages, fetchMessages2]);
|
|
11201
11297
|
const attachments = useMemo(() => {
|
|
11202
11298
|
if (!conversationId) return [];
|
|
11203
11299
|
const messages = messagesByConversation[conversationId] || [];
|
|
@@ -11249,7 +11345,11 @@ var AttachmentsDrawer = ({ isOpen, onOpenChange, conversationId }) => {
|
|
|
11249
11345
|
] }),
|
|
11250
11346
|
/* @__PURE__ */ jsx("p", { className: "mt-1 text-[11px] text-(--chat-muted)", children: "Shared media and files" })
|
|
11251
11347
|
] }) }),
|
|
11252
|
-
/* @__PURE__ */ jsx("div", { className: "chat-message-scroll flex-1 overflow-y-auto bg-(--chat-main-bg) px-2.5 py-2", 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: [
|
|
11253
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)") }) }) }),
|
|
11254
11354
|
/* @__PURE__ */ jsx("p", { className: "text-[14px] font-semibold text-(--chat-text)", children: "No attachments" }),
|
|
11255
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." })
|
|
@@ -11632,7 +11732,7 @@ var ChannelDetailsDrawer = (props) => {
|
|
|
11632
11732
|
{
|
|
11633
11733
|
type: "button",
|
|
11634
11734
|
onClick: () => fileInputRef.current?.click(),
|
|
11635
|
-
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-
|
|
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)",
|
|
11636
11736
|
title: "Change group avatar",
|
|
11637
11737
|
children: /* @__PURE__ */ jsx(Camera, { size: 12 })
|
|
11638
11738
|
}
|
|
@@ -11671,7 +11771,7 @@ var ChannelDetailsDrawer = (props) => {
|
|
|
11671
11771
|
{
|
|
11672
11772
|
variant: "outline",
|
|
11673
11773
|
size: "sm",
|
|
11674
|
-
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)",
|
|
11675
11775
|
onClick: () => setIsEditing(false),
|
|
11676
11776
|
children: [
|
|
11677
11777
|
/* @__PURE__ */ jsx(X, { className: "mr-1 size-3" }),
|
|
@@ -11683,7 +11783,7 @@ var ChannelDetailsDrawer = (props) => {
|
|
|
11683
11783
|
Button,
|
|
11684
11784
|
{
|
|
11685
11785
|
size: "sm",
|
|
11686
|
-
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",
|
|
11687
11787
|
onClick: handleSave,
|
|
11688
11788
|
disabled: isSaving || imageUploadStatus === "uploading",
|
|
11689
11789
|
children: isSaving ? /* @__PURE__ */ jsx(Loader2, { className: "size-3 animate-spin" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -11701,7 +11801,7 @@ var ChannelDetailsDrawer = (props) => {
|
|
|
11701
11801
|
{
|
|
11702
11802
|
variant: "ghost",
|
|
11703
11803
|
size: "sm",
|
|
11704
|
-
className: "mt-2 h-7 gap-1 px-2 text-[11px] text-(--chat-
|
|
11804
|
+
className: "mt-2 h-7 gap-1 px-2 text-[11px] text-(--chat-theme) hover:bg-(--chat-theme-10) hover:text-(--chat-theme)",
|
|
11705
11805
|
onClick: () => setIsEditing(true),
|
|
11706
11806
|
children: [
|
|
11707
11807
|
/* @__PURE__ */ jsx(Pencil, { className: "size-3" }),
|
|
@@ -12559,8 +12659,8 @@ function useChannelHeader({
|
|
|
12559
12659
|
}
|
|
12560
12660
|
}
|
|
12561
12661
|
};
|
|
12562
|
-
const handleSelectSearchResult = async (
|
|
12563
|
-
await fetchSearchMessageContext(
|
|
12662
|
+
const handleSelectSearchResult = async (messageId2) => {
|
|
12663
|
+
await fetchSearchMessageContext(messageId2);
|
|
12564
12664
|
handleCloseSearch();
|
|
12565
12665
|
};
|
|
12566
12666
|
const handleSearchOpenChange = (open) => {
|
|
@@ -12596,6 +12696,14 @@ function useChannelHeader({
|
|
|
12596
12696
|
fetchStarredMessages2(conversationId);
|
|
12597
12697
|
}
|
|
12598
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]);
|
|
12599
12707
|
const pinnedCount = liveCounts?.pinnedCount ?? activeChannel?.pinnedCount ?? 0;
|
|
12600
12708
|
const starredCount = liveCounts?.starredCount ?? activeChannel?.starredCount ?? 0;
|
|
12601
12709
|
const handleClearChat = () => {
|
|
@@ -12641,14 +12749,14 @@ function useChannelHeader({
|
|
|
12641
12749
|
updateState({ isBlockAlertOpen: false });
|
|
12642
12750
|
}
|
|
12643
12751
|
};
|
|
12644
|
-
const handleUnpin = (
|
|
12752
|
+
const handleUnpin = (messageId2, attachmentId) => {
|
|
12645
12753
|
if (!loggedUserDetails?._id || !conversationId || !activeChannel) return;
|
|
12646
|
-
const loadingKey = attachmentId ? `${
|
|
12754
|
+
const loadingKey = attachmentId ? `${messageId2}:${attachmentId}` : messageId2;
|
|
12647
12755
|
updateState({ loadingIds: new Set(state.loadingIds).add(loadingKey) });
|
|
12648
12756
|
const basePayload = {
|
|
12649
12757
|
conversationId,
|
|
12650
12758
|
sender: loggedUserDetails._id,
|
|
12651
|
-
messageId,
|
|
12759
|
+
messageId: messageId2,
|
|
12652
12760
|
receiver: activeChannel.id,
|
|
12653
12761
|
...attachmentId ? { attachmentId } : {}
|
|
12654
12762
|
};
|
|
@@ -12668,12 +12776,12 @@ function useChannelHeader({
|
|
|
12668
12776
|
if (!dateStr) return "";
|
|
12669
12777
|
return formatLongDate(dateStr);
|
|
12670
12778
|
};
|
|
12671
|
-
const handleUnstar = (
|
|
12779
|
+
const handleUnstar = (messageId2, attachmentId) => {
|
|
12672
12780
|
if (!loggedUserDetails?._id || !conversationId || !activeChannel) return;
|
|
12673
|
-
const loadingKey = attachmentId ? `${
|
|
12781
|
+
const loadingKey = attachmentId ? `${messageId2}:${attachmentId}` : messageId2;
|
|
12674
12782
|
updateState({ loadingIds: new Set(state.loadingIds).add(loadingKey) });
|
|
12675
12783
|
const basePayload = {
|
|
12676
|
-
messageId,
|
|
12784
|
+
messageId: messageId2,
|
|
12677
12785
|
sender: loggedUserDetails._id,
|
|
12678
12786
|
conversationId,
|
|
12679
12787
|
receiver: activeChannel.id,
|
|
@@ -12943,7 +13051,7 @@ var MessageReactions = ({
|
|
|
12943
13051
|
{
|
|
12944
13052
|
onClick: () => onReactionClick(emoji),
|
|
12945
13053
|
className: cn(
|
|
12946
|
-
"flex items-center gap-
|
|
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",
|
|
12947
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)"
|
|
12948
13056
|
),
|
|
12949
13057
|
children: [
|
|
@@ -12997,7 +13105,7 @@ var MessageToolbar = ({
|
|
|
12997
13105
|
"div",
|
|
12998
13106
|
{
|
|
12999
13107
|
className: cn(
|
|
13000
|
-
"absolute -top-8 z-
|
|
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",
|
|
13001
13109
|
"bg-(--chat-toolbar-bg) text-(--chat-text)",
|
|
13002
13110
|
isSender ? "right-0" : "left-0"
|
|
13003
13111
|
),
|
|
@@ -13273,8 +13381,8 @@ init_useStore();
|
|
|
13273
13381
|
|
|
13274
13382
|
// src/chat/lib/chat-selection.ts
|
|
13275
13383
|
init_attachment_helpers();
|
|
13276
|
-
function buildSelectionKey(
|
|
13277
|
-
return pinKey(
|
|
13384
|
+
function buildSelectionKey(messageId2, attachmentId) {
|
|
13385
|
+
return pinKey(messageId2, attachmentId || null);
|
|
13278
13386
|
}
|
|
13279
13387
|
function parseSelectionKey(key) {
|
|
13280
13388
|
const colonIndex = key.indexOf(":");
|
|
@@ -13289,8 +13397,8 @@ function parseSelectionKey(key) {
|
|
|
13289
13397
|
function messageUsesAttachmentSelection(message) {
|
|
13290
13398
|
return getVisibleAttachments(message.attachments).length > 1;
|
|
13291
13399
|
}
|
|
13292
|
-
function getSelectedAttachmentIdsForMessage(selectedKeys,
|
|
13293
|
-
const prefix = `${
|
|
13400
|
+
function getSelectedAttachmentIdsForMessage(selectedKeys, messageId2) {
|
|
13401
|
+
const prefix = `${messageId2}:`;
|
|
13294
13402
|
const ids = /* @__PURE__ */ new Set();
|
|
13295
13403
|
selectedKeys.forEach((key) => {
|
|
13296
13404
|
if (key.startsWith(prefix)) {
|
|
@@ -13299,14 +13407,14 @@ function getSelectedAttachmentIdsForMessage(selectedKeys, messageId) {
|
|
|
13299
13407
|
});
|
|
13300
13408
|
return ids;
|
|
13301
13409
|
}
|
|
13302
|
-
function isMessageWhollySelected(selectedKeys,
|
|
13303
|
-
return selectedKeys.has(
|
|
13410
|
+
function isMessageWhollySelected(selectedKeys, messageId2) {
|
|
13411
|
+
return selectedKeys.has(messageId2);
|
|
13304
13412
|
}
|
|
13305
13413
|
function resolveForwardItems(selectedKeys, messages) {
|
|
13306
13414
|
const items = [];
|
|
13307
13415
|
selectedKeys.forEach((key) => {
|
|
13308
|
-
const { messageId, attachmentId } = parseSelectionKey(key);
|
|
13309
|
-
const message = messages.find((entry) => String(entry._id || entry.id) ===
|
|
13416
|
+
const { messageId: messageId2, attachmentId } = parseSelectionKey(key);
|
|
13417
|
+
const message = messages.find((entry) => String(entry._id || entry.id) === messageId2);
|
|
13310
13418
|
if (!message) return;
|
|
13311
13419
|
items.push({ message, attachmentId });
|
|
13312
13420
|
});
|
|
@@ -13332,7 +13440,7 @@ function useMessageItemActions({
|
|
|
13332
13440
|
message,
|
|
13333
13441
|
createdAt,
|
|
13334
13442
|
attachments,
|
|
13335
|
-
messageId,
|
|
13443
|
+
messageId: messageId2,
|
|
13336
13444
|
receiver,
|
|
13337
13445
|
isDeletedForEveryone,
|
|
13338
13446
|
reactions,
|
|
@@ -13384,10 +13492,10 @@ function useMessageItemActions({
|
|
|
13384
13492
|
const allUsers = useStore((s) => s.allUsers);
|
|
13385
13493
|
const loggedUserDetails = useStore((s) => s.loggedUserDetails);
|
|
13386
13494
|
const pinnedMessagesByConversation = useStore((s) => s.pinnedMessagesByConversation);
|
|
13387
|
-
const mid = String(
|
|
13495
|
+
const mid = String(messageId2 || "");
|
|
13388
13496
|
const pendingActions = mid ? messagePendingActions[mid] || [] : [];
|
|
13389
13497
|
const isPending = Boolean(
|
|
13390
|
-
isSender && (String(
|
|
13498
|
+
isSender && (String(messageId2 || "").startsWith("temp-") || mid && (messagePendingActions[mid] || []).includes("send"))
|
|
13391
13499
|
);
|
|
13392
13500
|
const isEditPending = pendingActions.includes("edit");
|
|
13393
13501
|
const isDeletePending = pendingActions.includes("delete");
|
|
@@ -13425,13 +13533,13 @@ function useMessageItemActions({
|
|
|
13425
13533
|
};
|
|
13426
13534
|
const handleSaveAttachmentCaption = (caption, attachment) => {
|
|
13427
13535
|
const target = attachment ?? state.captionModalAttachment;
|
|
13428
|
-
if (!
|
|
13536
|
+
if (!messageId2 || !loggedUserDetails || !target) return;
|
|
13429
13537
|
const attachmentId = target.id;
|
|
13430
13538
|
if (isGroup) {
|
|
13431
13539
|
if (!conversationId) return;
|
|
13432
13540
|
emitGroupEdit({
|
|
13433
13541
|
content: caption,
|
|
13434
|
-
messageId,
|
|
13542
|
+
messageId: messageId2,
|
|
13435
13543
|
sender: loggedUserDetails._id,
|
|
13436
13544
|
conversationId,
|
|
13437
13545
|
attachmentId
|
|
@@ -13440,7 +13548,7 @@ function useMessageItemActions({
|
|
|
13440
13548
|
if (!receiver) return;
|
|
13441
13549
|
emitDmEdit({
|
|
13442
13550
|
content: caption,
|
|
13443
|
-
messageId,
|
|
13551
|
+
messageId: messageId2,
|
|
13444
13552
|
sender: loggedUserDetails._id,
|
|
13445
13553
|
receiver,
|
|
13446
13554
|
attachmentId
|
|
@@ -13457,12 +13565,12 @@ function useMessageItemActions({
|
|
|
13457
13565
|
onEnterSelectionMode?.();
|
|
13458
13566
|
};
|
|
13459
13567
|
const handleSaveEdit = () => {
|
|
13460
|
-
if (!
|
|
13568
|
+
if (!messageId2 || !loggedUserDetails) return;
|
|
13461
13569
|
if (isGroup) {
|
|
13462
13570
|
if (!conversationId) return;
|
|
13463
13571
|
emitGroupEdit({
|
|
13464
13572
|
content: state.editValue.trim(),
|
|
13465
|
-
messageId,
|
|
13573
|
+
messageId: messageId2,
|
|
13466
13574
|
sender: loggedUserDetails._id,
|
|
13467
13575
|
conversationId
|
|
13468
13576
|
});
|
|
@@ -13470,7 +13578,7 @@ function useMessageItemActions({
|
|
|
13470
13578
|
if (!receiver) return;
|
|
13471
13579
|
emitDmEdit({
|
|
13472
13580
|
content: state.editValue.trim(),
|
|
13473
|
-
messageId,
|
|
13581
|
+
messageId: messageId2,
|
|
13474
13582
|
sender: loggedUserDetails._id,
|
|
13475
13583
|
receiver
|
|
13476
13584
|
});
|
|
@@ -13481,7 +13589,7 @@ function useMessageItemActions({
|
|
|
13481
13589
|
updateState({ isEditing: false, editValue: message });
|
|
13482
13590
|
};
|
|
13483
13591
|
const handleDeleteMessage = (deleteType) => {
|
|
13484
|
-
if (!
|
|
13592
|
+
if (!messageId2 || !loggedUserDetails) return;
|
|
13485
13593
|
if (deleteType === "everyone" && !isSender) return;
|
|
13486
13594
|
if (deleteType === "everyone" && !isWithinEditWindow()) return;
|
|
13487
13595
|
const attachmentIds = hasAttachments ? deleteAttachmentIds : [];
|
|
@@ -13489,7 +13597,7 @@ function useMessageItemActions({
|
|
|
13489
13597
|
if (isGroup) {
|
|
13490
13598
|
if (!conversationId) return;
|
|
13491
13599
|
emitGroupDelete({
|
|
13492
|
-
messageId,
|
|
13600
|
+
messageId: messageId2,
|
|
13493
13601
|
sender: loggedUserDetails._id,
|
|
13494
13602
|
deleteType,
|
|
13495
13603
|
conversationId,
|
|
@@ -13498,7 +13606,7 @@ function useMessageItemActions({
|
|
|
13498
13606
|
} else {
|
|
13499
13607
|
if (!receiver) return;
|
|
13500
13608
|
emitDmDelete({
|
|
13501
|
-
messageId,
|
|
13609
|
+
messageId: messageId2,
|
|
13502
13610
|
sender: loggedUserDetails._id,
|
|
13503
13611
|
receiver,
|
|
13504
13612
|
deleteType,
|
|
@@ -13520,7 +13628,7 @@ function useMessageItemActions({
|
|
|
13520
13628
|
onForward?.();
|
|
13521
13629
|
};
|
|
13522
13630
|
const handleReactionClick = (emojiObject) => {
|
|
13523
|
-
if (!
|
|
13631
|
+
if (!messageId2 || !loggedUserDetails) return;
|
|
13524
13632
|
const reaction = typeof emojiObject === "string" ? emojiObject : emojiObject.emoji || emojiObject.native;
|
|
13525
13633
|
const hasReacted = reactions?.some(
|
|
13526
13634
|
(r) => r.reaction === reaction && String(r.addedBy?._id || r.addedBy || r.sender?._id || r.sender) === String(loggedUserDetails._id)
|
|
@@ -13529,7 +13637,7 @@ function useMessageItemActions({
|
|
|
13529
13637
|
if (isGroup) {
|
|
13530
13638
|
if (!conversationId) return;
|
|
13531
13639
|
emitGroupReactionRemove({
|
|
13532
|
-
messageId,
|
|
13640
|
+
messageId: messageId2,
|
|
13533
13641
|
sender: loggedUserDetails._id,
|
|
13534
13642
|
reaction,
|
|
13535
13643
|
conversationId
|
|
@@ -13537,7 +13645,7 @@ function useMessageItemActions({
|
|
|
13537
13645
|
} else {
|
|
13538
13646
|
if (!receiver) return;
|
|
13539
13647
|
emitDmReactionRemove({
|
|
13540
|
-
messageId,
|
|
13648
|
+
messageId: messageId2,
|
|
13541
13649
|
sender: loggedUserDetails._id,
|
|
13542
13650
|
receiver,
|
|
13543
13651
|
reaction,
|
|
@@ -13548,7 +13656,7 @@ function useMessageItemActions({
|
|
|
13548
13656
|
if (isGroup) {
|
|
13549
13657
|
if (!conversationId) return;
|
|
13550
13658
|
emitGroupReactionAdd({
|
|
13551
|
-
messageId,
|
|
13659
|
+
messageId: messageId2,
|
|
13552
13660
|
sender: loggedUserDetails._id,
|
|
13553
13661
|
reaction,
|
|
13554
13662
|
conversationId
|
|
@@ -13556,7 +13664,7 @@ function useMessageItemActions({
|
|
|
13556
13664
|
} else {
|
|
13557
13665
|
if (!receiver) return;
|
|
13558
13666
|
emitDmReactionAdd({
|
|
13559
|
-
messageId,
|
|
13667
|
+
messageId: messageId2,
|
|
13560
13668
|
sender: loggedUserDetails._id,
|
|
13561
13669
|
receiver,
|
|
13562
13670
|
reaction,
|
|
@@ -13566,7 +13674,7 @@ function useMessageItemActions({
|
|
|
13566
13674
|
}
|
|
13567
13675
|
};
|
|
13568
13676
|
const handlePinClick = () => {
|
|
13569
|
-
if (!
|
|
13677
|
+
if (!messageId2 || !loggedUserDetails) return;
|
|
13570
13678
|
if (isPinned) {
|
|
13571
13679
|
if (!isPinnedByMe) return;
|
|
13572
13680
|
if (isGroup) {
|
|
@@ -13574,14 +13682,14 @@ function useMessageItemActions({
|
|
|
13574
13682
|
emitGroupUnpin({
|
|
13575
13683
|
conversationId,
|
|
13576
13684
|
sender: loggedUserDetails._id,
|
|
13577
|
-
messageId,
|
|
13685
|
+
messageId: messageId2,
|
|
13578
13686
|
receiver: ""
|
|
13579
13687
|
});
|
|
13580
13688
|
} else {
|
|
13581
13689
|
emitDmUnpin({
|
|
13582
13690
|
conversationId,
|
|
13583
13691
|
sender: loggedUserDetails._id,
|
|
13584
|
-
messageId,
|
|
13692
|
+
messageId: messageId2,
|
|
13585
13693
|
receiver: receiver || ""
|
|
13586
13694
|
});
|
|
13587
13695
|
}
|
|
@@ -13591,32 +13699,32 @@ function useMessageItemActions({
|
|
|
13591
13699
|
emitGroupPin({
|
|
13592
13700
|
conversationId,
|
|
13593
13701
|
sender: loggedUserDetails._id,
|
|
13594
|
-
messageId,
|
|
13702
|
+
messageId: messageId2,
|
|
13595
13703
|
receiver: ""
|
|
13596
13704
|
});
|
|
13597
13705
|
} else {
|
|
13598
13706
|
emitDmPin({
|
|
13599
13707
|
conversationId,
|
|
13600
13708
|
sender: loggedUserDetails._id,
|
|
13601
|
-
messageId,
|
|
13709
|
+
messageId: messageId2,
|
|
13602
13710
|
receiver: receiver || ""
|
|
13603
13711
|
});
|
|
13604
13712
|
}
|
|
13605
13713
|
}
|
|
13606
13714
|
};
|
|
13607
13715
|
const handleStarClick = () => {
|
|
13608
|
-
if (!
|
|
13716
|
+
if (!messageId2 || !loggedUserDetails || !conversationId) return;
|
|
13609
13717
|
if (isStarred) {
|
|
13610
13718
|
if (isGroup) {
|
|
13611
|
-
emitGroupUnstar({ messageId, sender: loggedUserDetails._id, conversationId });
|
|
13719
|
+
emitGroupUnstar({ messageId: messageId2, sender: loggedUserDetails._id, conversationId });
|
|
13612
13720
|
} else {
|
|
13613
|
-
emitDmUnstar({ messageId, sender: loggedUserDetails._id, conversationId });
|
|
13721
|
+
emitDmUnstar({ messageId: messageId2, sender: loggedUserDetails._id, conversationId });
|
|
13614
13722
|
}
|
|
13615
13723
|
} else {
|
|
13616
13724
|
if (isGroup) {
|
|
13617
|
-
emitGroupStar({ messageId, sender: loggedUserDetails._id, conversationId });
|
|
13725
|
+
emitGroupStar({ messageId: messageId2, sender: loggedUserDetails._id, conversationId });
|
|
13618
13726
|
} else {
|
|
13619
|
-
emitDmStar({ messageId, sender: loggedUserDetails._id, conversationId });
|
|
13727
|
+
emitDmStar({ messageId: messageId2, sender: loggedUserDetails._id, conversationId });
|
|
13620
13728
|
}
|
|
13621
13729
|
}
|
|
13622
13730
|
};
|
|
@@ -13838,6 +13946,7 @@ function MessageItemTextBubble({
|
|
|
13838
13946
|
isForwarded,
|
|
13839
13947
|
showSenderLabel,
|
|
13840
13948
|
senderName,
|
|
13949
|
+
senderId,
|
|
13841
13950
|
replyTo,
|
|
13842
13951
|
loggedUserDetails,
|
|
13843
13952
|
allUsers,
|
|
@@ -13876,7 +13985,13 @@ function MessageItemTextBubble({
|
|
|
13876
13985
|
),
|
|
13877
13986
|
children: [
|
|
13878
13987
|
(canShowSenderName || isForwarded) && /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [
|
|
13879
|
-
canShowSenderName ? /* @__PURE__ */ jsx(
|
|
13988
|
+
canShowSenderName ? /* @__PURE__ */ jsx(
|
|
13989
|
+
GroupSenderName,
|
|
13990
|
+
{
|
|
13991
|
+
name: senderName,
|
|
13992
|
+
colorSeed: senderId || senderName
|
|
13993
|
+
}
|
|
13994
|
+
) : null,
|
|
13880
13995
|
isForwarded ? /* @__PURE__ */ jsx(MessageForwardedLabel, { isSender, className: "px-0 pt-0 pb-0" }) : null
|
|
13881
13996
|
] }),
|
|
13882
13997
|
/* @__PURE__ */ jsx(
|
|
@@ -13927,7 +14042,7 @@ function MessageItemTextBubble({
|
|
|
13927
14042
|
}
|
|
13928
14043
|
)
|
|
13929
14044
|
] })
|
|
13930
|
-
] }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-
|
|
14045
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
13931
14046
|
hasText && /* @__PURE__ */ jsxs("p", { className: "whitespace-pre-wrap break-words leading-snug", children: [
|
|
13932
14047
|
message,
|
|
13933
14048
|
isEdited && /* @__PURE__ */ jsx(
|
|
@@ -13985,6 +14100,7 @@ function MessageItemAttachmentBubble({
|
|
|
13985
14100
|
isGroupedWithNext,
|
|
13986
14101
|
showSenderLabel,
|
|
13987
14102
|
senderName,
|
|
14103
|
+
senderId,
|
|
13988
14104
|
formattedTime,
|
|
13989
14105
|
status,
|
|
13990
14106
|
isPending,
|
|
@@ -14033,6 +14149,7 @@ function MessageItemAttachmentBubble({
|
|
|
14033
14149
|
isGroupedWithNext,
|
|
14034
14150
|
showSenderLabel,
|
|
14035
14151
|
senderName,
|
|
14152
|
+
senderId,
|
|
14036
14153
|
formattedTime,
|
|
14037
14154
|
status,
|
|
14038
14155
|
isPending,
|
|
@@ -14092,6 +14209,7 @@ function MessageItemView(props) {
|
|
|
14092
14209
|
isGroup,
|
|
14093
14210
|
isHighlighted,
|
|
14094
14211
|
senderName,
|
|
14212
|
+
senderId,
|
|
14095
14213
|
senderImage,
|
|
14096
14214
|
showSenderLabel,
|
|
14097
14215
|
senderAvatarImage,
|
|
@@ -14268,6 +14386,7 @@ function MessageItemView(props) {
|
|
|
14268
14386
|
isGroupedWithNext,
|
|
14269
14387
|
showSenderLabel,
|
|
14270
14388
|
senderName,
|
|
14389
|
+
senderId,
|
|
14271
14390
|
formattedTime,
|
|
14272
14391
|
status,
|
|
14273
14392
|
isPending,
|
|
@@ -14309,6 +14428,7 @@ function MessageItemView(props) {
|
|
|
14309
14428
|
isForwarded,
|
|
14310
14429
|
showSenderLabel,
|
|
14311
14430
|
senderName,
|
|
14431
|
+
senderId,
|
|
14312
14432
|
replyTo,
|
|
14313
14433
|
loggedUserDetails,
|
|
14314
14434
|
allUsers,
|
|
@@ -14499,6 +14619,28 @@ function MessageSelectionBar({
|
|
|
14499
14619
|
|
|
14500
14620
|
// src/chat/active-channel-messages/utils.ts
|
|
14501
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
|
+
}
|
|
14502
14644
|
var isSameMessageSide = (a, b, isGroupChat) => {
|
|
14503
14645
|
if (!!a.isOwnMessage !== !!b.isOwnMessage) return false;
|
|
14504
14646
|
if (a.isOwnMessage) return true;
|
|
@@ -14512,8 +14654,8 @@ function canDeleteSelectionForEveryone(selectedKeys, messages, isGroup) {
|
|
|
14512
14654
|
const parsed = [...selectedKeys].map((key) => parseSelectionKey(key));
|
|
14513
14655
|
const messageIds = new Set(parsed.map((entry) => entry.messageId));
|
|
14514
14656
|
if (messageIds.size !== 1) return false;
|
|
14515
|
-
const
|
|
14516
|
-
const message = messages.find((entry) => String(entry._id || entry.id) ===
|
|
14657
|
+
const messageId2 = [...messageIds][0];
|
|
14658
|
+
const message = messages.find((entry) => String(entry._id || entry.id) === messageId2);
|
|
14517
14659
|
if (!message?.isOwnMessage) return false;
|
|
14518
14660
|
if (!isWithinMessageEditWindow(message.timestamp, isGroup)) return false;
|
|
14519
14661
|
const hasAttachmentKey = parsed.some((entry) => entry.attachmentId);
|
|
@@ -14527,6 +14669,9 @@ function canDeleteSelectionForEveryone(selectedKeys, messages, isGroup) {
|
|
|
14527
14669
|
});
|
|
14528
14670
|
}
|
|
14529
14671
|
|
|
14672
|
+
// src/chat/active-channel-messages/ActiveChannelMessagesView.tsx
|
|
14673
|
+
init_useStore();
|
|
14674
|
+
|
|
14530
14675
|
// src/chat/active-channel-messages/useActiveChannelMessages.ts
|
|
14531
14676
|
init_useStore();
|
|
14532
14677
|
init_store_helpers();
|
|
@@ -14542,6 +14687,7 @@ function mapApiMessage(m, activeChannel, conversationId, loggedUserId, activeCon
|
|
|
14542
14687
|
content: m.content,
|
|
14543
14688
|
sender: m.sender?.name || "User",
|
|
14544
14689
|
senderId: String(m.sender?._id || m.sender || ""),
|
|
14690
|
+
senderImage: m.sender?.image,
|
|
14545
14691
|
receiver: activeChannel?.id,
|
|
14546
14692
|
timestamp: m.createdAt,
|
|
14547
14693
|
isOwnMessage: isOwn,
|
|
@@ -14569,7 +14715,101 @@ function mapApiMessage(m, activeChannel, conversationId, loggedUserId, activeCon
|
|
|
14569
14715
|
};
|
|
14570
14716
|
}
|
|
14571
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
|
+
|
|
14572
14811
|
// src/chat/active-channel-messages/useActiveChannelMessages.ts
|
|
14812
|
+
var MAX_JUMP_OLDER_PAGES = 40;
|
|
14573
14813
|
function useActiveChannelMessages({
|
|
14574
14814
|
activeChannel,
|
|
14575
14815
|
loggedUserId,
|
|
@@ -14592,6 +14832,11 @@ function useActiveChannelMessages({
|
|
|
14592
14832
|
const previousMessageCountRef = useRef(0);
|
|
14593
14833
|
const previousLastMessageIdRef = useRef(null);
|
|
14594
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);
|
|
14595
14840
|
const { fetchMessages: fetchMessages2, messagesMetadata, deletedForMeIds, searchedMessageId, isSearchActive, setSearchActive, setSearchedMessageId, fetchSearchMessageContext } = useStore();
|
|
14596
14841
|
const loggedUserImage = useStore((s) => s.loggedUserDetails?.image);
|
|
14597
14842
|
const conversations = useStore((s) => s.conversations);
|
|
@@ -14615,6 +14860,13 @@ function useActiveChannelMessages({
|
|
|
14615
14860
|
})),
|
|
14616
14861
|
[displayMessages, messagesById, loggedUserId]
|
|
14617
14862
|
);
|
|
14863
|
+
const jumpDateBounds = useMemo(
|
|
14864
|
+
() => resolveJumpDateBounds(
|
|
14865
|
+
conversationInfo?.createdAt,
|
|
14866
|
+
displayMessages[0]?.timestamp
|
|
14867
|
+
),
|
|
14868
|
+
[conversationInfo?.createdAt, displayMessages]
|
|
14869
|
+
);
|
|
14618
14870
|
useEffect(() => {
|
|
14619
14871
|
const messages = messagesWithResolvedReplies;
|
|
14620
14872
|
const lastMessage = messages[messages.length - 1];
|
|
@@ -14652,6 +14904,10 @@ function useActiveChannelMessages({
|
|
|
14652
14904
|
previousMessageCountRef.current = 0;
|
|
14653
14905
|
previousLastMessageIdRef.current = null;
|
|
14654
14906
|
setEnteringMessageIds(/* @__PURE__ */ new Set());
|
|
14907
|
+
pendingJumpRef.current = null;
|
|
14908
|
+
jumpPagesRef.current = 0;
|
|
14909
|
+
stickToBottomRef.current = true;
|
|
14910
|
+
setShowScrollToBottom(false);
|
|
14655
14911
|
}, [conversationId, clearSelection]);
|
|
14656
14912
|
const onSelectionModeChangeRef = useRef(onSelectionModeChange);
|
|
14657
14913
|
useEffect(() => {
|
|
@@ -14661,10 +14917,10 @@ function useActiveChannelMessages({
|
|
|
14661
14917
|
onSelectionModeChangeRef.current?.(selectionMode);
|
|
14662
14918
|
}, [selectionMode]);
|
|
14663
14919
|
const toggleSelection = useCallback((message, attachmentId) => {
|
|
14664
|
-
const
|
|
14665
|
-
if (!
|
|
14920
|
+
const messageId2 = String(message._id || message.id);
|
|
14921
|
+
if (!messageId2) return;
|
|
14666
14922
|
const useAttachmentSelection = messageUsesAttachmentSelection(message);
|
|
14667
|
-
const key = useAttachmentSelection && attachmentId ? buildSelectionKey(
|
|
14923
|
+
const key = useAttachmentSelection && attachmentId ? buildSelectionKey(messageId2, attachmentId) : messageId2;
|
|
14668
14924
|
setSelectedKeys((prev) => {
|
|
14669
14925
|
const next = new Set(prev);
|
|
14670
14926
|
if (next.has(key)) next.delete(key);
|
|
@@ -14674,17 +14930,17 @@ function useActiveChannelMessages({
|
|
|
14674
14930
|
});
|
|
14675
14931
|
}, []);
|
|
14676
14932
|
const enterSelectionMode = useCallback((message, attachmentId) => {
|
|
14677
|
-
const
|
|
14678
|
-
if (!
|
|
14933
|
+
const messageId2 = String(message._id || message.id);
|
|
14934
|
+
if (!messageId2) return;
|
|
14679
14935
|
setSelectionMode(true);
|
|
14680
14936
|
const useAttachmentSelection = messageUsesAttachmentSelection(message);
|
|
14681
14937
|
if (useAttachmentSelection) {
|
|
14682
14938
|
if (attachmentId) {
|
|
14683
|
-
setSelectedKeys((prev) => new Set(prev).add(buildSelectionKey(
|
|
14939
|
+
setSelectedKeys((prev) => new Set(prev).add(buildSelectionKey(messageId2, attachmentId)));
|
|
14684
14940
|
}
|
|
14685
14941
|
return;
|
|
14686
14942
|
}
|
|
14687
|
-
setSelectedKeys((prev) => new Set(prev).add(
|
|
14943
|
+
setSelectedKeys((prev) => new Set(prev).add(messageId2));
|
|
14688
14944
|
}, []);
|
|
14689
14945
|
const selectedForwardItems = resolveForwardItems(selectedKeys, displayMessages);
|
|
14690
14946
|
const canDeleteForEveryone = useMemo(
|
|
@@ -14703,14 +14959,14 @@ function useActiveChannelMessages({
|
|
|
14703
14959
|
}
|
|
14704
14960
|
const isGroupChat = !!activeChannel?.isGroup;
|
|
14705
14961
|
selectedKeys.forEach((key) => {
|
|
14706
|
-
const { messageId, attachmentId } = parseSelectionKey(key);
|
|
14707
|
-
if (!
|
|
14708
|
-
const message = displayMessages.find((entry) => String(entry._id || entry.id) ===
|
|
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);
|
|
14709
14965
|
if (isGroupChat) {
|
|
14710
14966
|
const convId = String(message?.conversationId || conversationId || "");
|
|
14711
14967
|
if (!convId) return;
|
|
14712
14968
|
emitGroupDelete({
|
|
14713
|
-
messageId,
|
|
14969
|
+
messageId: messageId2,
|
|
14714
14970
|
sender: loggedUserDetails._id,
|
|
14715
14971
|
deleteType,
|
|
14716
14972
|
conversationId: convId,
|
|
@@ -14720,7 +14976,7 @@ function useActiveChannelMessages({
|
|
|
14720
14976
|
const receiver = message?.receiver || activeChannel?.id;
|
|
14721
14977
|
if (!receiver) return;
|
|
14722
14978
|
emitDmDelete({
|
|
14723
|
-
messageId,
|
|
14979
|
+
messageId: messageId2,
|
|
14724
14980
|
sender: loggedUserDetails._id,
|
|
14725
14981
|
receiver: String(receiver),
|
|
14726
14982
|
deleteType,
|
|
@@ -14759,43 +15015,138 @@ function useActiveChannelMessages({
|
|
|
14759
15015
|
fetchMessages2(conversationId);
|
|
14760
15016
|
}
|
|
14761
15017
|
};
|
|
14762
|
-
const handleReplyTargetClick = async (
|
|
14763
|
-
if (!
|
|
14764
|
-
|
|
14765
|
-
|
|
15018
|
+
const handleReplyTargetClick = async (messageId2) => {
|
|
15019
|
+
if (!messageId2) return;
|
|
15020
|
+
stickToBottomRef.current = false;
|
|
15021
|
+
if (messagesById.has(messageId2)) {
|
|
15022
|
+
setSearchedMessageId(messageId2);
|
|
14766
15023
|
return;
|
|
14767
15024
|
}
|
|
14768
|
-
await fetchSearchMessageContext(
|
|
15025
|
+
await fetchSearchMessageContext(messageId2, { searchMode: false });
|
|
14769
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]);
|
|
14770
15105
|
const handleScroll = (e) => {
|
|
14771
15106
|
const target = e.currentTarget;
|
|
15107
|
+
updateScrollToBottomVisibility(target);
|
|
15108
|
+
if (pendingJumpRef.current) return;
|
|
14772
15109
|
if (target.scrollTop === 0 && currentMeta?.hasMore && !isLoading && conversationId && currentMeta.nextCursor) {
|
|
14773
15110
|
const prevScrollHeight = target.scrollHeight;
|
|
14774
15111
|
fetchMessages2(conversationId, DEFAULT_MESSAGES_LIMIT, currentMeta.nextCursor).then(() => {
|
|
14775
15112
|
if (scrollContainerRef.current) {
|
|
14776
15113
|
const newScrollHeight = scrollContainerRef.current.scrollHeight;
|
|
14777
15114
|
scrollContainerRef.current.scrollTop = newScrollHeight - prevScrollHeight;
|
|
15115
|
+
updateScrollToBottomVisibility(scrollContainerRef.current);
|
|
14778
15116
|
}
|
|
14779
15117
|
});
|
|
14780
15118
|
}
|
|
14781
15119
|
};
|
|
14782
15120
|
useLayoutEffect(() => {
|
|
14783
|
-
if (!isInitialLoading &&
|
|
15121
|
+
if (!isInitialLoading && stickToBottomRef.current && !pendingJumpRef.current) {
|
|
14784
15122
|
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
14785
15123
|
}
|
|
14786
|
-
}, [messagesWithResolvedReplies.length, isInitialLoading
|
|
15124
|
+
}, [messagesWithResolvedReplies.length, isInitialLoading]);
|
|
14787
15125
|
useEffect(() => {
|
|
14788
15126
|
if (searchedMessageId && !isLoading) {
|
|
15127
|
+
stickToBottomRef.current = false;
|
|
15128
|
+
const container = scrollContainerRef.current;
|
|
14789
15129
|
const element = document.getElementById(`message-${searchedMessageId}`);
|
|
14790
|
-
if (element) {
|
|
14791
|
-
|
|
15130
|
+
if (container && element) {
|
|
15131
|
+
requestAnimationFrame(() => {
|
|
15132
|
+
requestAnimationFrame(() => {
|
|
15133
|
+
smoothScrollToMessage(container, element);
|
|
15134
|
+
updateScrollToBottomVisibility(container);
|
|
15135
|
+
});
|
|
15136
|
+
});
|
|
14792
15137
|
}
|
|
14793
15138
|
if (!isSearchActive) {
|
|
14794
15139
|
const timer = window.setTimeout(() => setSearchedMessageId(null), 2500);
|
|
14795
15140
|
return () => window.clearTimeout(timer);
|
|
14796
15141
|
}
|
|
14797
15142
|
}
|
|
14798
|
-
}, [
|
|
15143
|
+
}, [
|
|
15144
|
+
searchedMessageId,
|
|
15145
|
+
isLoading,
|
|
15146
|
+
isSearchActive,
|
|
15147
|
+
setSearchedMessageId,
|
|
15148
|
+
updateScrollToBottomVisibility
|
|
15149
|
+
]);
|
|
14799
15150
|
return {
|
|
14800
15151
|
activeChannel,
|
|
14801
15152
|
conversationId,
|
|
@@ -14821,11 +15172,297 @@ function useActiveChannelMessages({
|
|
|
14821
15172
|
canDeleteForEveryone,
|
|
14822
15173
|
handleResetToNormal,
|
|
14823
15174
|
handleReplyTargetClick,
|
|
15175
|
+
handleJumpTo,
|
|
15176
|
+
jumpDateBounds,
|
|
15177
|
+
showScrollToBottom,
|
|
15178
|
+
handleScrollToBottom,
|
|
14824
15179
|
handleScroll
|
|
14825
15180
|
};
|
|
14826
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
|
+
}
|
|
14827
15463
|
var ActiveChannelMessagesView = (props) => {
|
|
14828
15464
|
const { formatDateDivider } = useChatLocale();
|
|
15465
|
+
const allUsers = useStore((s) => s.allUsers);
|
|
14829
15466
|
const {
|
|
14830
15467
|
activeChannel,
|
|
14831
15468
|
conversationId,
|
|
@@ -14851,6 +15488,10 @@ var ActiveChannelMessagesView = (props) => {
|
|
|
14851
15488
|
canDeleteForEveryone,
|
|
14852
15489
|
handleResetToNormal,
|
|
14853
15490
|
handleReplyTargetClick,
|
|
15491
|
+
handleJumpTo,
|
|
15492
|
+
jumpDateBounds,
|
|
15493
|
+
showScrollToBottom,
|
|
15494
|
+
handleScrollToBottom,
|
|
14854
15495
|
handleScroll
|
|
14855
15496
|
} = useActiveChannelMessages(props);
|
|
14856
15497
|
const { onReply, onForward } = props;
|
|
@@ -14863,7 +15504,7 @@ var ActiveChannelMessagesView = (props) => {
|
|
|
14863
15504
|
] })
|
|
14864
15505
|
] });
|
|
14865
15506
|
}
|
|
14866
|
-
return /* @__PURE__ */ jsxs("div", { className: "chat-message-canvas relative flex h-full
|
|
15507
|
+
return /* @__PURE__ */ jsxs("div", { className: "chat-message-canvas relative flex h-full flex-col", children: [
|
|
14867
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: [
|
|
14868
15509
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 bg-(--chat-theme) px-4 py-2.5", children: [
|
|
14869
15510
|
/* @__PURE__ */ jsx(History, { className: "size-3.5 animate-pulse text-white" }),
|
|
@@ -14900,11 +15541,20 @@ var ActiveChannelMessagesView = (props) => {
|
|
|
14900
15541
|
return groups;
|
|
14901
15542
|
}, {})
|
|
14902
15543
|
).map(([date, messages]) => /* @__PURE__ */ jsxs("div", { className: "mb-2 flex flex-col", children: [
|
|
14903
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
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
|
+
) }),
|
|
14904
15553
|
messages.map((m, msgIndex) => {
|
|
14905
|
-
const senderLabel = typeof m.sender === "string" ? m.sender : "User";
|
|
14906
|
-
const senderImage = !m.isOwnMessage ? activeChannel?.isGroup ? void 0 : activeChannel?.image : void 0;
|
|
14907
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;
|
|
14908
15558
|
const prevMessage = msgIndex > 0 ? messages[msgIndex - 1] : null;
|
|
14909
15559
|
const nextMessage = msgIndex < messages.length - 1 ? messages[msgIndex + 1] : null;
|
|
14910
15560
|
const isGroupedWithPrev = !!prevMessage && isSameMessageSide(prevMessage, m, isGroupChat);
|
|
@@ -14951,6 +15601,7 @@ var ActiveChannelMessagesView = (props) => {
|
|
|
14951
15601
|
conversationInfo,
|
|
14952
15602
|
isHighlighted: String(m._id || m.id) === String(searchedMessageId),
|
|
14953
15603
|
senderName: senderLabel,
|
|
15604
|
+
senderId: getMessageSenderId2(m),
|
|
14954
15605
|
senderImage,
|
|
14955
15606
|
showSenderName,
|
|
14956
15607
|
showSenderLabel,
|
|
@@ -14991,6 +15642,16 @@ var ActiveChannelMessagesView = (props) => {
|
|
|
14991
15642
|
onForward: handleBatchForward
|
|
14992
15643
|
}
|
|
14993
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
|
+
),
|
|
14994
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: [
|
|
14995
15656
|
/* @__PURE__ */ jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin text-(--chat-theme)" }),
|
|
14996
15657
|
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-bold uppercase tracking-[0.15em] text-(--chat-muted)", children: "Loading messages..." })
|
|
@@ -15614,10 +16275,10 @@ function useChannelMessageBox({
|
|
|
15614
16275
|
const composerDisabledReason = conversationId ? composerDisabledByConversation[conversationId] : void 0;
|
|
15615
16276
|
const fileInputRef = useRef(null);
|
|
15616
16277
|
const attachmentsCountRef = useRef(0);
|
|
15617
|
-
|
|
16278
|
+
React2__default.useEffect(() => {
|
|
15618
16279
|
attachmentsCountRef.current = state.attachments.length;
|
|
15619
16280
|
}, [state.attachments.length]);
|
|
15620
|
-
|
|
16281
|
+
React2__default.useEffect(() => {
|
|
15621
16282
|
const draft = {
|
|
15622
16283
|
messageInput: state.messageInput,
|
|
15623
16284
|
attachments: state.attachments
|
|
@@ -15625,7 +16286,7 @@ function useChannelMessageBox({
|
|
|
15625
16286
|
syncComposerRef(draft);
|
|
15626
16287
|
updateConversationDraft(conversationIdRef.current, draft);
|
|
15627
16288
|
}, [state.messageInput, state.attachments, syncComposerRef]);
|
|
15628
|
-
|
|
16289
|
+
React2__default.useEffect(() => {
|
|
15629
16290
|
if (typingTimeoutRef.current) {
|
|
15630
16291
|
clearTimeout(typingTimeoutRef.current);
|
|
15631
16292
|
typingTimeoutRef.current = null;
|
|
@@ -16176,10 +16837,10 @@ function useForwardModal({ isOpen, onClose, items, onForwardComplete }) {
|
|
|
16176
16837
|
targetChannelRef.current = channel;
|
|
16177
16838
|
const targetConversationIds = [String(channel.conversationId)];
|
|
16178
16839
|
items.forEach((item) => {
|
|
16179
|
-
const
|
|
16180
|
-
if (!
|
|
16840
|
+
const messageId2 = String(item.message._id || item.message.id || "");
|
|
16841
|
+
if (!messageId2) return;
|
|
16181
16842
|
const payload = {
|
|
16182
|
-
messageId,
|
|
16843
|
+
messageId: messageId2,
|
|
16183
16844
|
sender: String(loggedUserDetails._id),
|
|
16184
16845
|
sourceConversationId: item.message.conversationId ? String(item.message.conversationId) : void 0,
|
|
16185
16846
|
targetConversationIds,
|
|
@@ -16656,8 +17317,8 @@ var ChatMain = ({
|
|
|
16656
17317
|
viewportHeight = "full",
|
|
16657
17318
|
viewportClassName
|
|
16658
17319
|
}) => {
|
|
16659
|
-
const clientObj =
|
|
16660
|
-
const uiConfigObj =
|
|
17320
|
+
const clientObj = React2__default.useMemo(() => ({ id: clientId }), [clientId]);
|
|
17321
|
+
const uiConfigObj = React2__default.useMemo(
|
|
16661
17322
|
() => ({
|
|
16662
17323
|
...uiConfig || {},
|
|
16663
17324
|
components: { ...uiConfig?.components, ...components },
|
|
@@ -17089,9 +17750,285 @@ var packageDefaultComponents = {
|
|
|
17089
17750
|
ChatSocketStatus: ChatSocketStatus_default
|
|
17090
17751
|
};
|
|
17091
17752
|
|
|
17753
|
+
// src/notifications/push.service.ts
|
|
17754
|
+
init_client();
|
|
17755
|
+
var PUSH_TOKEN_STORAGE_KEY = "realtimex-push-token";
|
|
17756
|
+
var SERVICE_WORKER_PATH = "/firebase-messaging-sw.js";
|
|
17757
|
+
var v2Url = (path) => {
|
|
17758
|
+
const base = (getChatBaseUrl() || String(apiClient.defaults.baseURL || "")).replace(/\/$/, "").replace(/\/v1$/, "/v2");
|
|
17759
|
+
return `${base}${path}`;
|
|
17760
|
+
};
|
|
17761
|
+
var apiGetPushConfig = async () => {
|
|
17762
|
+
const { data } = await apiClient.get(v2Url("/notifications/push/config"));
|
|
17763
|
+
return data?.data;
|
|
17764
|
+
};
|
|
17765
|
+
var apiRegisterPushToken = async (token, deviceLabel) => {
|
|
17766
|
+
const { data } = await apiClient.post(v2Url("/notifications/push/token"), {
|
|
17767
|
+
token,
|
|
17768
|
+
deviceLabel
|
|
17769
|
+
});
|
|
17770
|
+
return data?.data;
|
|
17771
|
+
};
|
|
17772
|
+
var apiRemovePushToken = async (token) => {
|
|
17773
|
+
const { data } = await apiClient.delete(v2Url("/notifications/push/token"), {
|
|
17774
|
+
data: { token }
|
|
17775
|
+
});
|
|
17776
|
+
return data;
|
|
17777
|
+
};
|
|
17778
|
+
var apiGetPushPreference = async () => {
|
|
17779
|
+
const { data } = await apiClient.get(
|
|
17780
|
+
v2Url("/notifications/push/preference")
|
|
17781
|
+
);
|
|
17782
|
+
return data?.data;
|
|
17783
|
+
};
|
|
17784
|
+
var apiUpdatePushPreference = async (enabled) => {
|
|
17785
|
+
const { data } = await apiClient.patch(
|
|
17786
|
+
v2Url("/notifications/push/preference"),
|
|
17787
|
+
{ enabled }
|
|
17788
|
+
);
|
|
17789
|
+
return data?.data;
|
|
17790
|
+
};
|
|
17791
|
+
var isPushSupported = () => typeof window !== "undefined" && "Notification" in window && "serviceWorker" in navigator && "PushManager" in window;
|
|
17792
|
+
var getStoredPushToken = () => {
|
|
17793
|
+
try {
|
|
17794
|
+
return localStorage.getItem(PUSH_TOKEN_STORAGE_KEY);
|
|
17795
|
+
} catch {
|
|
17796
|
+
return null;
|
|
17797
|
+
}
|
|
17798
|
+
};
|
|
17799
|
+
var storePushToken = (token) => {
|
|
17800
|
+
try {
|
|
17801
|
+
if (token) localStorage.setItem(PUSH_TOKEN_STORAGE_KEY, token);
|
|
17802
|
+
else localStorage.removeItem(PUSH_TOKEN_STORAGE_KEY);
|
|
17803
|
+
} catch {
|
|
17804
|
+
}
|
|
17805
|
+
};
|
|
17806
|
+
var defaultDeviceLabel = () => {
|
|
17807
|
+
const ua = navigator.userAgent;
|
|
17808
|
+
const browser = /edg\//i.test(ua) ? "Edge" : /chrome/i.test(ua) ? "Chrome" : /safari/i.test(ua) ? "Safari" : /firefox/i.test(ua) ? "Firefox" : "Browser";
|
|
17809
|
+
const os = /mac/i.test(ua) ? "macOS" : /windows/i.test(ua) ? "Windows" : /android/i.test(ua) ? "Android" : /iphone|ipad/i.test(ua) ? "iOS" : /linux/i.test(ua) ? "Linux" : "Unknown OS";
|
|
17810
|
+
return `${browser} on ${os}`;
|
|
17811
|
+
};
|
|
17812
|
+
var loadFirebaseMessaging = async () => {
|
|
17813
|
+
try {
|
|
17814
|
+
const [{ initializeApp, getApps }, messagingModule] = await Promise.all([
|
|
17815
|
+
import('firebase/app'),
|
|
17816
|
+
import('firebase/messaging')
|
|
17817
|
+
]);
|
|
17818
|
+
return { initializeApp, getApps, ...messagingModule };
|
|
17819
|
+
} catch {
|
|
17820
|
+
throw new Error(
|
|
17821
|
+
'Push notifications need the "firebase" package \u2014 run: npm install firebase'
|
|
17822
|
+
);
|
|
17823
|
+
}
|
|
17824
|
+
};
|
|
17825
|
+
var getFirebaseMessaging = async (firebaseConfig) => {
|
|
17826
|
+
const fb = await loadFirebaseMessaging();
|
|
17827
|
+
const app = fb.getApps().length ? fb.getApps()[0] : fb.initializeApp(firebaseConfig);
|
|
17828
|
+
return { fb, messaging: fb.getMessaging(app) };
|
|
17829
|
+
};
|
|
17830
|
+
var enablePushOnThisDevice = async () => {
|
|
17831
|
+
if (!isPushSupported()) {
|
|
17832
|
+
throw new Error("Push notifications are not supported in this browser");
|
|
17833
|
+
}
|
|
17834
|
+
const config = await apiGetPushConfig();
|
|
17835
|
+
if (!config?.enabled) {
|
|
17836
|
+
throw new Error("Push notifications are disabled for this workspace");
|
|
17837
|
+
}
|
|
17838
|
+
if (!config.configured || !config.firebaseConfig || !config.vapidKey) {
|
|
17839
|
+
throw new Error(
|
|
17840
|
+
"Push notifications are not configured on the server yet"
|
|
17841
|
+
);
|
|
17842
|
+
}
|
|
17843
|
+
const permission = await Notification.requestPermission();
|
|
17844
|
+
if (permission !== "granted") {
|
|
17845
|
+
throw new Error("Notification permission was not granted");
|
|
17846
|
+
}
|
|
17847
|
+
let registration;
|
|
17848
|
+
try {
|
|
17849
|
+
registration = await navigator.serviceWorker.register(
|
|
17850
|
+
`${SERVICE_WORKER_PATH}?config=${encodeURIComponent(
|
|
17851
|
+
JSON.stringify(config.firebaseConfig)
|
|
17852
|
+
)}`
|
|
17853
|
+
);
|
|
17854
|
+
} catch {
|
|
17855
|
+
throw new Error(
|
|
17856
|
+
`Could not register ${SERVICE_WORKER_PATH} \u2014 copy it from node_modules/@realtimexsco/live-chat/dist/firebase-messaging-sw.js into your app's public folder`
|
|
17857
|
+
);
|
|
17858
|
+
}
|
|
17859
|
+
const { fb, messaging } = await getFirebaseMessaging(config.firebaseConfig);
|
|
17860
|
+
const token = await fb.getToken(messaging, {
|
|
17861
|
+
vapidKey: config.vapidKey,
|
|
17862
|
+
serviceWorkerRegistration: registration
|
|
17863
|
+
});
|
|
17864
|
+
if (!token) {
|
|
17865
|
+
throw new Error("Could not obtain a push token from Firebase");
|
|
17866
|
+
}
|
|
17867
|
+
await apiRegisterPushToken(token, defaultDeviceLabel());
|
|
17868
|
+
storePushToken(token);
|
|
17869
|
+
return token;
|
|
17870
|
+
};
|
|
17871
|
+
var disablePushOnThisDevice = async () => {
|
|
17872
|
+
const token = getStoredPushToken();
|
|
17873
|
+
if (!token) return;
|
|
17874
|
+
try {
|
|
17875
|
+
const config = await apiGetPushConfig();
|
|
17876
|
+
if (config?.firebaseConfig) {
|
|
17877
|
+
const { fb, messaging } = await getFirebaseMessaging(
|
|
17878
|
+
config.firebaseConfig
|
|
17879
|
+
);
|
|
17880
|
+
await fb.deleteToken(messaging).catch(() => void 0);
|
|
17881
|
+
}
|
|
17882
|
+
} catch {
|
|
17883
|
+
}
|
|
17884
|
+
await apiRemovePushToken(token).catch(() => void 0);
|
|
17885
|
+
storePushToken(null);
|
|
17886
|
+
};
|
|
17887
|
+
var onForegroundPush = async (callback) => {
|
|
17888
|
+
const config = await apiGetPushConfig();
|
|
17889
|
+
if (!config?.configured || !config.firebaseConfig) return () => void 0;
|
|
17890
|
+
const { fb, messaging } = await getFirebaseMessaging(config.firebaseConfig);
|
|
17891
|
+
return fb.onMessage(messaging, (payload) => {
|
|
17892
|
+
callback({
|
|
17893
|
+
title: payload?.notification?.title,
|
|
17894
|
+
body: payload?.notification?.body,
|
|
17895
|
+
data: payload?.data
|
|
17896
|
+
});
|
|
17897
|
+
});
|
|
17898
|
+
};
|
|
17899
|
+
var usePushNotifications = () => {
|
|
17900
|
+
const [state, setState] = useState({
|
|
17901
|
+
supported: false,
|
|
17902
|
+
allowedByWorkspace: false,
|
|
17903
|
+
configured: false,
|
|
17904
|
+
permission: "unsupported",
|
|
17905
|
+
userEnabled: true,
|
|
17906
|
+
deviceEnabled: false,
|
|
17907
|
+
loading: true,
|
|
17908
|
+
error: null
|
|
17909
|
+
});
|
|
17910
|
+
const refresh = useCallback(async () => {
|
|
17911
|
+
if (!isPushSupported()) {
|
|
17912
|
+
setState((prev) => ({
|
|
17913
|
+
...prev,
|
|
17914
|
+
supported: false,
|
|
17915
|
+
loading: false
|
|
17916
|
+
}));
|
|
17917
|
+
return;
|
|
17918
|
+
}
|
|
17919
|
+
try {
|
|
17920
|
+
const [config, preference] = await Promise.all([
|
|
17921
|
+
apiGetPushConfig(),
|
|
17922
|
+
apiGetPushPreference().catch(() => null)
|
|
17923
|
+
]);
|
|
17924
|
+
setState({
|
|
17925
|
+
supported: true,
|
|
17926
|
+
allowedByWorkspace: Boolean(config?.enabled),
|
|
17927
|
+
configured: Boolean(config?.configured),
|
|
17928
|
+
permission: Notification.permission,
|
|
17929
|
+
userEnabled: preference?.enabled ?? true,
|
|
17930
|
+
deviceEnabled: Notification.permission === "granted" && Boolean(getStoredPushToken()),
|
|
17931
|
+
loading: false,
|
|
17932
|
+
error: null
|
|
17933
|
+
});
|
|
17934
|
+
} catch (error) {
|
|
17935
|
+
setState((prev) => ({
|
|
17936
|
+
...prev,
|
|
17937
|
+
supported: true,
|
|
17938
|
+
loading: false,
|
|
17939
|
+
error: error instanceof Error ? error.message : "Could not load push settings"
|
|
17940
|
+
}));
|
|
17941
|
+
}
|
|
17942
|
+
}, []);
|
|
17943
|
+
useEffect(() => {
|
|
17944
|
+
void refresh();
|
|
17945
|
+
}, [refresh]);
|
|
17946
|
+
const enable = useCallback(async () => {
|
|
17947
|
+
setState((prev) => ({ ...prev, loading: true, error: null }));
|
|
17948
|
+
try {
|
|
17949
|
+
await enablePushOnThisDevice();
|
|
17950
|
+
await refresh();
|
|
17951
|
+
return true;
|
|
17952
|
+
} catch (error) {
|
|
17953
|
+
setState((prev) => ({
|
|
17954
|
+
...prev,
|
|
17955
|
+
loading: false,
|
|
17956
|
+
permission: isPushSupported() ? Notification.permission : "unsupported",
|
|
17957
|
+
error: error instanceof Error ? error.message : "Could not enable push notifications"
|
|
17958
|
+
}));
|
|
17959
|
+
return false;
|
|
17960
|
+
}
|
|
17961
|
+
}, [refresh]);
|
|
17962
|
+
const disable = useCallback(async () => {
|
|
17963
|
+
setState((prev) => ({ ...prev, loading: true, error: null }));
|
|
17964
|
+
try {
|
|
17965
|
+
await disablePushOnThisDevice();
|
|
17966
|
+
} finally {
|
|
17967
|
+
await refresh();
|
|
17968
|
+
}
|
|
17969
|
+
}, [refresh]);
|
|
17970
|
+
const setUserEnabled = useCallback(
|
|
17971
|
+
async (enabled) => {
|
|
17972
|
+
setState((prev) => ({ ...prev, userEnabled: enabled }));
|
|
17973
|
+
try {
|
|
17974
|
+
await apiUpdatePushPreference(enabled);
|
|
17975
|
+
} catch (error) {
|
|
17976
|
+
setState((prev) => ({
|
|
17977
|
+
...prev,
|
|
17978
|
+
userEnabled: !enabled,
|
|
17979
|
+
error: error instanceof Error ? error.message : "Could not update push preference"
|
|
17980
|
+
}));
|
|
17981
|
+
}
|
|
17982
|
+
},
|
|
17983
|
+
[]
|
|
17984
|
+
);
|
|
17985
|
+
return { ...state, enable, disable, setUserEnabled, refresh };
|
|
17986
|
+
};
|
|
17987
|
+
var PushNotificationToggle = ({
|
|
17988
|
+
className,
|
|
17989
|
+
label = "Push notifications",
|
|
17990
|
+
description = "Get notified about new messages on this device"
|
|
17991
|
+
}) => {
|
|
17992
|
+
const push = usePushNotifications();
|
|
17993
|
+
if (!push.supported || !push.allowedByWorkspace || !push.configured) {
|
|
17994
|
+
return null;
|
|
17995
|
+
}
|
|
17996
|
+
const isOn = push.deviceEnabled && push.userEnabled;
|
|
17997
|
+
const permissionBlocked = push.permission === "denied";
|
|
17998
|
+
const handleChange = async (checked) => {
|
|
17999
|
+
if (checked) {
|
|
18000
|
+
if (!push.userEnabled) await push.setUserEnabled(true);
|
|
18001
|
+
if (!push.deviceEnabled) await push.enable();
|
|
18002
|
+
} else {
|
|
18003
|
+
await push.disable();
|
|
18004
|
+
}
|
|
18005
|
+
};
|
|
18006
|
+
return /* @__PURE__ */ jsxs(
|
|
18007
|
+
"div",
|
|
18008
|
+
{
|
|
18009
|
+
className: className ?? "flex items-center justify-between gap-4 rounded-xl border border-border bg-background px-4 py-3",
|
|
18010
|
+
children: [
|
|
18011
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-0.5", children: [
|
|
18012
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: label }),
|
|
18013
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: permissionBlocked ? "Notifications are blocked in your browser settings" : push.error ?? description })
|
|
18014
|
+
] }),
|
|
18015
|
+
/* @__PURE__ */ jsx(
|
|
18016
|
+
Switch,
|
|
18017
|
+
{
|
|
18018
|
+
checked: isOn,
|
|
18019
|
+
disabled: push.loading || permissionBlocked,
|
|
18020
|
+
onCheckedChange: (checked) => void handleChange(checked),
|
|
18021
|
+
"aria-label": `Toggle ${label}`
|
|
18022
|
+
}
|
|
18023
|
+
)
|
|
18024
|
+
]
|
|
18025
|
+
}
|
|
18026
|
+
);
|
|
18027
|
+
};
|
|
18028
|
+
|
|
17092
18029
|
// src/index.ts
|
|
17093
18030
|
var index_default = ChatMain_default;
|
|
17094
18031
|
|
|
17095
|
-
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 };
|
|
18032
|
+
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, PushNotificationToggle, apiGetPushConfig, apiGetPushPreference, apiRegisterPushToken, apiRemovePushToken, apiUpdatePushPreference, capitalizeFirst, clampJumpDate, index_default as default, defaultChatClassNames, defaultChatComponents, defaultChatFeatures, defaultChatLayoutConfig, disablePushOnThisDevice, downloadFile, enablePushOnThisDevice, getChatBaseUrl, getChatQueryParamApis, getChatQueryParams, getChatQueryParamsByApi, getChatSocketUrl, getFirstAndLastNameOneCharacter, getResponsiveWidth, getSocketConfig, getStoredPushToken, isEmpty, isPushSupported, mergeChatCustomization, mergeChatLayoutConfig, onForegroundPush, 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, usePushNotifications };
|
|
17096
18033
|
//# sourceMappingURL=index.mjs.map
|
|
17097
18034
|
//# sourceMappingURL=index.mjs.map
|