Private
Public Access
Add unread message indicators for rooms (#38)
Shows a dot on rooms with unread messages in the sidebar, updated live over WebSocket. Reuses the same offline-member audience computation already used for push notifications: a member gets the real-time signal whenever they aren't currently connected to that room's channel, which correctly covers both "room not open" and "room open but tab backgrounded" (the client leaves a room's channel while hidden). Persisted server-side via a new room_memberships.last_read_at column so state survives reload and stays consistent across devices, advanced by an explicit mark-read call the frontend makes on room-open and on each live message received while the room is genuinely visible -- gated on a live visibility check, not a cached ref, so a backgrounded-but-open room keeps accumulating unread instead of auto-marking-read the instant a message arrives somewhere it can't be seen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -59,13 +59,18 @@ export function ChatShellPage() {
|
||||
|
||||
const socket = useChatSocketContext()
|
||||
|
||||
const setRoomUnread = useCallback((id: string, hasUnread: boolean) => {
|
||||
setRooms((prev) => prev.map((r) => (r.id === id ? { ...r, has_unread: hasUnread } : r)))
|
||||
}, [])
|
||||
|
||||
useEffect(
|
||||
() =>
|
||||
socket.subscribe((envelope) => {
|
||||
if (envelope.type === 'room_added') refreshRooms()
|
||||
else if (envelope.type === 'member_updated' && envelope.room_id === roomId) refreshMembers()
|
||||
else if (envelope.type === 'unread_update') setRoomUnread(envelope.room_id, true)
|
||||
}),
|
||||
[socket, refreshRooms, refreshMembers, roomId],
|
||||
[socket, refreshRooms, refreshMembers, roomId, setRoomUnread],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
@@ -110,6 +115,7 @@ export function ChatShellPage() {
|
||||
onToggleInfo={() => setInfoOpen((v) => !v)}
|
||||
infoOpen={infoOpen}
|
||||
socket={socket}
|
||||
onRoomRead={(id) => setRoomUnread(id, false)}
|
||||
/>
|
||||
) : (
|
||||
!isMobile && (
|
||||
|
||||
Reference in New Issue
Block a user