chat
This commit is contained in:
@@ -9,6 +9,13 @@ function matchesPendingServer(server: ChatMessage, pending: ChatMessage): boolea
|
||||
return Boolean(pending.fileType && server.fileType === pending.fileType);
|
||||
}
|
||||
|
||||
export function findPendingMatchForServer(
|
||||
server: ChatMessage,
|
||||
pending: ChatMessage[]
|
||||
): ChatMessage | undefined {
|
||||
return pending.find((p) => matchesPendingServer(server, p));
|
||||
}
|
||||
|
||||
export function filterResolvedPendingMessages(
|
||||
server: ChatMessage[],
|
||||
pending: ChatMessage[]
|
||||
|
||||
53
src/lib/chat/socketClient.ts
Normal file
53
src/lib/chat/socketClient.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { io, Socket } from "socket.io-client";
|
||||
import { SOCKET_URL } from "@/components/main/BaseUrl";
|
||||
|
||||
let sharedSocket: Socket | null = null;
|
||||
let refCount = 0;
|
||||
|
||||
export function acquireChatSocket(): Socket {
|
||||
if (!sharedSocket) {
|
||||
sharedSocket = io(SOCKET_URL, {
|
||||
transports: ["websocket", "polling"],
|
||||
reconnection: true,
|
||||
reconnectionAttempts: Infinity,
|
||||
reconnectionDelay: 800,
|
||||
reconnectionDelayMax: 5000,
|
||||
timeout: 20000,
|
||||
withCredentials: true,
|
||||
autoConnect: true,
|
||||
});
|
||||
}
|
||||
refCount += 1;
|
||||
return sharedSocket;
|
||||
}
|
||||
|
||||
/** Use after acquire — does not change ref count */
|
||||
export function getChatSocket(): Socket | null {
|
||||
return sharedSocket;
|
||||
}
|
||||
|
||||
export function releaseChatSocket(): void {
|
||||
refCount = Math.max(0, refCount - 1);
|
||||
if (refCount === 0 && sharedSocket) {
|
||||
sharedSocket.removeAllListeners();
|
||||
sharedSocket.disconnect();
|
||||
sharedSocket = null;
|
||||
}
|
||||
}
|
||||
|
||||
export function joinUserRoom(userId: string): void {
|
||||
const id = String(userId).trim();
|
||||
if (!id || !sharedSocket) return;
|
||||
sharedSocket.emit("joinUser", { userId: id });
|
||||
}
|
||||
|
||||
export function joinChatRoom(userId: string, receiverId: string): void {
|
||||
const uid = String(userId).trim();
|
||||
const rid = String(receiverId).trim();
|
||||
if (!uid || !rid || !sharedSocket) return;
|
||||
sharedSocket.emit("joinChat", { userId: uid, receiverId: rid });
|
||||
}
|
||||
|
||||
export function isChatSocketConnected(): boolean {
|
||||
return Boolean(sharedSocket?.connected);
|
||||
}
|
||||
@@ -34,3 +34,33 @@ export function appendMessageToThreadCache(
|
||||
|
||||
return { ...oldData, pages: newPages };
|
||||
}
|
||||
|
||||
/** Add or update — avoids duplicate / flicker when optimistic + socket + HTTP overlap */
|
||||
export function upsertMessageInThreadCache(
|
||||
oldData: ChatThreadData | undefined,
|
||||
message: ChatMessage
|
||||
): ChatThreadData {
|
||||
if (!oldData?.pages?.length) {
|
||||
return appendMessageToThreadCache(oldData, message);
|
||||
}
|
||||
|
||||
const messageId = String(message._id);
|
||||
let found = false;
|
||||
|
||||
const newPages = oldData.pages.map((page) => ({
|
||||
...page,
|
||||
messages: page.messages.map((m) => {
|
||||
if (String(m._id) === messageId) {
|
||||
found = true;
|
||||
return { ...m, ...message };
|
||||
}
|
||||
return m;
|
||||
}),
|
||||
}));
|
||||
|
||||
if (found) {
|
||||
return { ...oldData, pages: newPages };
|
||||
}
|
||||
|
||||
return appendMessageToThreadCache(oldData, message);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user