fix(chat): real-time active users list updates
Fixed issue where active users list in event chat did not update in real-time when new users joined. Users had to refresh the page to see newly joined participants. Root Cause: - getAllDisplayUsers() used checkedInUsers (loaded once from API) as base list, with activeUsers (Socket.IO real-time) only for isOnline flag - When new user joined chat, they appeared in activeUsers but not in checkedInUsers, so they were not displayed Solution: - Rewrote getAllDisplayUsers() to prioritize activeUsers (real-time data) - Merges activeUsers (online) with checkedInUsers (offline checked-in users) - Uses Socket.IO data as source of truth for online users - Enriches with database data when available (firstName, lastName, etc) - Sorts online users first, offline second Changes: - EventChatPage.jsx: Rewrote getAllDisplayUsers() to merge activeUsers with checkedInUsers, prioritizing real-time Socket.IO data - useEventChat.js: Added debug logging for active_users events - socket/index.js: Added debug logging for active_users emissions Testing: - User A in chat sees User B appear immediately when B joins - No page refresh required - Online/offline status updates in real-time
This commit is contained in:
@@ -225,6 +225,7 @@ function initializeSocket(httpServer) {
|
|||||||
|
|
||||||
// Broadcast updated active users list
|
// Broadcast updated active users list
|
||||||
const users = Array.from(activeUsers.get(eventId)).map(u => JSON.parse(u));
|
const users = Array.from(activeUsers.get(eventId)).map(u => JSON.parse(u));
|
||||||
|
console.log(`📡 Emitting active_users to room ${roomName}:`, users.length, 'users');
|
||||||
io.to(roomName).emit('active_users', users);
|
io.to(roomName).emit('active_users', users);
|
||||||
|
|
||||||
// Notify room about new user
|
// Notify room about new user
|
||||||
@@ -276,6 +277,7 @@ function initializeSocket(httpServer) {
|
|||||||
|
|
||||||
// Broadcast updated list
|
// Broadcast updated list
|
||||||
const updatedUsers = Array.from(users).map(u => JSON.parse(u));
|
const updatedUsers = Array.from(users).map(u => JSON.parse(u));
|
||||||
|
console.log(`📡 Emitting active_users (after leave) to room ${roomName}:`, updatedUsers.length, 'users');
|
||||||
io.to(roomName).emit('active_users', updatedUsers);
|
io.to(roomName).emit('active_users', updatedUsers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,6 +601,7 @@ function initializeSocket(httpServer) {
|
|||||||
|
|
||||||
// Broadcast updated list
|
// Broadcast updated list
|
||||||
const updatedUsers = Array.from(users).map(u => JSON.parse(u));
|
const updatedUsers = Array.from(users).map(u => JSON.parse(u));
|
||||||
|
console.log(`📡 Emitting active_users (after disconnect) to room ${socket.currentEventRoom}:`, updatedUsers.length, 'users');
|
||||||
io.to(socket.currentEventRoom).emit('active_users', updatedUsers);
|
io.to(socket.currentEventRoom).emit('active_users', updatedUsers);
|
||||||
|
|
||||||
// Notify about user leaving
|
// Notify about user leaving
|
||||||
|
|||||||
@@ -143,12 +143,14 @@ const useEventChat = (slug, userId, event, messagesContainerRef) => {
|
|||||||
|
|
||||||
// Receive active users list
|
// Receive active users list
|
||||||
socket.on('active_users', (users) => {
|
socket.on('active_users', (users) => {
|
||||||
|
console.log('📡 Received active_users event:', users);
|
||||||
// Filter out duplicates and current user
|
// Filter out duplicates and current user
|
||||||
const uniqueUsers = users
|
const uniqueUsers = users
|
||||||
.filter((u, index, self) =>
|
.filter((u, index, self) =>
|
||||||
index === self.findIndex((t) => t.userId === u.userId)
|
index === self.findIndex((t) => t.userId === u.userId)
|
||||||
)
|
)
|
||||||
.filter((u) => u.userId !== userId);
|
.filter((u) => u.userId !== userId);
|
||||||
|
console.log('👥 Updating active users:', uniqueUsers);
|
||||||
setActiveUsers(uniqueUsers);
|
setActiveUsers(uniqueUsers);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -246,16 +246,38 @@ const EventChatPage = () => {
|
|||||||
|
|
||||||
// Combine checked-in users with online status
|
// Combine checked-in users with online status
|
||||||
const getAllDisplayUsers = () => {
|
const getAllDisplayUsers = () => {
|
||||||
const activeUserIds = new Set(activeUsers.map(u => u.userId));
|
// Create map of userId -> user data from activeUsers (real-time socket data)
|
||||||
|
const activeUsersMap = new Map(activeUsers.map(u => [u.userId, { ...u, isOnline: true }]));
|
||||||
|
|
||||||
// Merge checked-in users with online status
|
// Create map of userId -> user data from checkedInUsers (database data)
|
||||||
const allUsers = checkedInUsers.map(user => ({
|
const checkedInUsersMap = new Map(checkedInUsers.map(u => [u.userId, { ...u, isOnline: false }]));
|
||||||
...user,
|
|
||||||
isOnline: activeUserIds.has(user.userId),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Sort: online first, then offline
|
// Merge: prioritize activeUsers data (it's real-time), add offline users from checkedInUsers
|
||||||
return allUsers.sort((a, b) => {
|
const mergedMap = new Map();
|
||||||
|
|
||||||
|
// Add all active users (online)
|
||||||
|
activeUsers.forEach(u => {
|
||||||
|
const checkedInData = checkedInUsersMap.get(u.userId);
|
||||||
|
mergedMap.set(u.userId, {
|
||||||
|
userId: u.userId,
|
||||||
|
username: u.username,
|
||||||
|
avatar: u.avatar,
|
||||||
|
// Use additional data from checkedInUsers if available
|
||||||
|
...checkedInData,
|
||||||
|
// Override with socket data
|
||||||
|
isOnline: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add offline checked-in users (not in activeUsers)
|
||||||
|
checkedInUsers.forEach(u => {
|
||||||
|
if (!mergedMap.has(u.userId)) {
|
||||||
|
mergedMap.set(u.userId, { ...u, isOnline: false });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Convert to array and sort: online first, then offline
|
||||||
|
return Array.from(mergedMap.values()).sort((a, b) => {
|
||||||
if (a.isOnline === b.isOnline) return 0;
|
if (a.isOnline === b.isOnline) return 0;
|
||||||
return a.isOnline ? -1 : 1;
|
return a.isOnline ? -1 : 1;
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user