Features
Online Presence & In-Room Presence
The template tracks two types of presence: global online/offline status for all users, and per-room presence to know who is currently viewing a specific room. Both use Firebase Realtime Database for fast, real-time updates.
Global Online Presence
How It Works
Each signed-in user has a presence node in Realtime Database that tracks their online/offline status:
presence/{uid} {
status: "online" | "offline";
updatedAt: ServerTimestamp;
}- When a user signs in,
setupPresence(uid)is called (viaPresenceSyncProvider) - Uses Firebase's
.info/connectedto detect connection state - When connected, sets status to
"online" - Uses
onDisconnecthook to automatically set status to"offline"when connection drops - When user signs out,
offlinePresenceis called explicitly
Subscribing to User Presence
To track other users' presence, use subscribeToUserPresence from presence.service.ts:
subscribeToUserPresence(uid, (presence) => {
console.log(presence.status); // "online" | "offline"
console.log(presence.updatedAt);
});The template uses usePresenceSync hook to automatically subscribe to presence for users you're interested in (e.g., participants in your active rooms). It manages subscriptions efficiently, adding new ones and removing unused ones.
In-Room Presence
How It Works
Room presence tracks which users are currently viewing a specific room. This is used to:
- Exclude active viewers from unread count increments
- Show who is currently in the room (optional UI feature)
- Optimize message delivery (future: only notify users not in room)
Stored in Realtime Database:
room_presence/{roomId}/{uid}: trueThe value is simply true when the user is in the room, and the node is removed when they leave.
Entering and Leaving Rooms
The useRoomPresence hook automatically manages room presence:
- On mount: Calls
enterRoom(uid, roomId)to add the user to room presence - On mount: Also calls
resetUnreadCount(uid, roomId)to mark messages as read - On unmount: Calls
leaveRoom(uid, roomId)to remove the user from room presence - Uses onDisconnect: If connection drops while in a room, the user is automatically removed from room presence
Subscribing to Room Presence
To see who is currently in a room, use subscribeToRoomPresence from room-presence.service.ts:
subscribeToRoomPresence(roomId, (participantIds) => {
console.log("Users in room:", participantIds);
// ["uid1", "uid2", "uid3"]
});The useRoomPresence hook returns { usersInRoom } which is an array of UIDs currently viewing the room.
Integration with Unread Counts
Room presence is used when sending messages to determine which users should have their unread count incremented:
- When a message is sent, the service checks room presence for that room
- Users currently in the room (via room presence) are excluded from unread count increments
- Only users not in the room and not the sender get their count incremented
This ensures users actively viewing a room don't get unread badges for messages they can already see.
Implementation Details
Key files for presence:
services/presence.service.ts– setupPresence, subscribeToUserPresence, offlinePresencefeatures/chat/services/room-presence.service.ts– enterRoom, leaveRoom, subscribeToRoomPresencehooks/use-presence-sync.ts– Hook that manages subscriptions to user presence for interested usersfeatures/chat/hooks/use-room-presence.ts– Hook that manages room presence for the active roomproviders/presence-sync-provider.tsx– Provider that sets up global presence on sign-in