fix(chat): авто-сброс unread badge при открытом активном чате и синхронизация с сообщением
This commit is contained in:
@@ -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'] });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user