fix(chat): авто-сброс unread badge при открытом активном чате и синхронизация с сообщением

This commit is contained in:
2026-07-09 10:19:29 +03:00
parent d70827b39e
commit 7ed89f7f97

View File

@@ -1029,7 +1029,7 @@ export default function ChatPage() {
markReadMutation.mutate(activeConvId); markReadMutation.mutate(activeConvId);
}, [activeConvId]); }, [activeConvId]);
// Auto-mark read when user returns to the tab with an open conversation // Auto-mark read when user returns to the tab/window with an open conversation
useEffect(() => { useEffect(() => {
if (!activeConvId) return; if (!activeConvId) return;
const handleVisibility = () => { const handleVisibility = () => {
@@ -1037,8 +1037,15 @@ export default function ChatPage() {
markReadMutation.mutate(activeConvId); markReadMutation.mutate(activeConvId);
} }
}; };
const handleFocus = () => {
markReadMutation.mutate(activeConvId);
};
document.addEventListener('visibilitychange', handleVisibility); document.addEventListener('visibilitychange', handleVisibility);
return () => document.removeEventListener('visibilitychange', handleVisibility); window.addEventListener('focus', handleFocus);
return () => {
document.removeEventListener('visibilitychange', handleVisibility);
window.removeEventListener('focus', handleFocus);
};
}, [activeConvId]); }, [activeConvId]);
const activeConv = conversations.find(c => c.id === activeConvId) ?? null; const activeConv = conversations.find(c => c.id === activeConvId) ?? null;
@@ -1292,7 +1299,12 @@ export default function ChatPage() {
useEvents({ useEvents({
onConvMessageCreated: useCallback((data: { conversationId: number; message: ConvMessage }) => { onConvMessageCreated: useCallback((data: { conversationId: number; message: ConvMessage }) => {
const { conversationId, message } = data; const { conversationId, message } = data;
const isActiveConv = conversationId === activeConvId;
const isMine = message.author?.id === user?.id;
const isVisible = typeof document !== 'undefined' && document.visibilityState === 'visible';
// 1. Сначала добавляем сообщение в кэш активного чата, чтобы оно появилось
// одновременно со значком, а не после него.
queryClient.setQueryData( queryClient.setQueryData(
['/api/messenger/conversations', conversationId, 'messages'], ['/api/messenger/conversations', conversationId, 'messages'],
(old: any) => { (old: any) => {
@@ -1303,18 +1315,8 @@ export default function ChatPage() {
} }
); );
const isActiveConv = conversationId === activeConvId; // 2. Обновляем список чатов: bump наверх, lastMessage, unreadCount.
const isMine = message.author?.id === user?.id; // Для активного и видимого чата сразу сбрасываем unreadCount в 0.
// Auto-mark read when message arrives in the currently open conversation
if (isActiveConv && !isMine) {
apiRequest('POST', `/api/messenger/conversations/${conversationId}/read`).catch(() => {});
// Also invalidate sidebar unread badge
queryClient.invalidateQueries({ queryKey: ['/api/messenger/unread-count'] });
}
// Update conv list (bump to top, update lastMessage, inc unread if not active)
// Also upsert missing conversation if not yet in cache
queryClient.setQueryData( queryClient.setQueryData(
['/api/messenger/conversations'], ['/api/messenger/conversations'],
(old: any) => { (old: any) => {
@@ -1333,7 +1335,7 @@ export default function ChatPage() {
...c, ...c,
lastMessage: message, lastMessage: message,
updatedAt: message.createdAt, updatedAt: message.createdAt,
unreadCount: isActiveConv || isMine ? 0 : c.unreadCount + 1, unreadCount: (isActiveConv && isVisible) || isMine ? 0 : c.unreadCount + 1,
}; };
}); });
// Bump updated conversation to top (sort by updatedAt desc) // Bump updated conversation to top (sort by updatedAt desc)
@@ -1343,6 +1345,12 @@ export default function ChatPage() {
return { ...old, conversations: sorted }; return { ...old, conversations: sorted };
} }
); );
// 3. Автоотметка прочтения только для активного, видимого чата и чужих сообщений.
// Используем mutation, чтобы onSuccess обновил кэш и сбросил бейджи.
if (isActiveConv && !isMine && isVisible) {
markReadMutation.mutate(conversationId);
}
}, [activeConvId, user]), }, [activeConvId, user]),
onConvMessageUpdated: useCallback((data: { conversationId: number; message: ConvMessage }) => { onConvMessageUpdated: useCallback((data: { conversationId: number; message: ConvMessage }) => {
@@ -1484,6 +1492,7 @@ export default function ChatPage() {
), ),
}; };
}); });
queryClient.invalidateQueries({ queryKey: ['/api/messenger/unread-count'] });
}, },
}); });