Private
Public Access
Fix presence showing offline on non-chat pages, and a room-join bug it exposed
The WebSocket connection lived entirely inside ChatShellPage, so navigating to /admin (which never opens its own connection) unmounted it -- the server correctly marked the user offline since the connection genuinely closed, even though they were still logged in and using the app. New ChatSocketContext.tsx hoists the connection to App.tsx, shared across every authenticated route via a single provider (keyed by user id, so a logout/login as a different account gets a clean reconnect rather than an old connection lingering under a new identity) instead of living inside whichever page happens to be mounted. Verifying that fix surfaced a second, independent bug: #31's visibility handling had gated the *explicit* joinRoom/leaveRoom calls (fired when a room actually mounts/unmounts in the UI) on the same isVisibleRef check meant for automatic background/foreground transitions. That's wrong -- a room can only be opened by a real user interaction, which can't happen on a genuinely backgrounded tab, so gating it too meant a stale or momentarily-wrong visibility reading at mount time could silently skip the join with nothing to ever retry it. joinRoom/leaveRoom now always send immediately; only the automatic hide/show transitions and the reconnect replay stay gated on visibility, which is what #31 actually needed. Verified both end-to-end in the browser: navigating to /admin via real in-app navigation (not a reload) keeps the presence dot online, confirmed via direct Redis inspection and the /api/users/online endpoint; opening a room and sending a message works immediately afterward. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,9 +10,9 @@ import { RoomInfoPanel } from '../components/RoomInfoPanel'
|
||||
import { Sidebar } from '../components/Sidebar'
|
||||
import { TopBar } from '../components/TopBar'
|
||||
import { useAuth } from '../context/AuthContext'
|
||||
import { useChatSocketContext } from '../context/ChatSocketContext'
|
||||
import { MOBILE_BREAKPOINT, useWindowWidth } from '../hooks/useWindowWidth'
|
||||
import type { MyRoomItem, RoomMember } from '../types'
|
||||
import { useChatSocket } from '../ws/useChatSocket'
|
||||
import './ChatShellPage.css'
|
||||
|
||||
type ModalKind = 'new' | 'browse' | null
|
||||
@@ -57,8 +57,7 @@ export function ChatShellPage() {
|
||||
refreshRooms().catch(() => {})
|
||||
}, [refreshRooms])
|
||||
|
||||
const onSocketUnauthenticated = useCallback(() => navigate('/login'), [navigate])
|
||||
const socket = useChatSocket({ onUnauthenticated: onSocketUnauthenticated })
|
||||
const socket = useChatSocketContext()
|
||||
|
||||
useEffect(
|
||||
() =>
|
||||
|
||||
Reference in New Issue
Block a user