diff --git a/web/src/app/AppShell.tsx b/web/src/app/AppShell.tsx index cf9863c3..4b767d6f 100644 --- a/web/src/app/AppShell.tsx +++ b/web/src/app/AppShell.tsx @@ -1,9 +1,11 @@ import { useEffect } from 'react'; +import { useQuery } from '@tanstack/react-query'; import { Outlet } from 'react-router-dom'; import { CallRoot } from '@/features/calls/CallRoot'; import { useBootstrap } from '@/lib/api/hooks'; +import { getMe } from '@/lib/api/profile'; import { useChatList } from '@/lib/tinode/hooks'; import { initCallSignaling } from '@/stores/calls'; @@ -19,6 +21,12 @@ import { NavRail } from './NavRail'; export function AppShell() { const contacts = useChatList(); const bootstrap = useBootstrap(); + // Same `['me']` query SettingsLayout already runs -- sharing the key means whichever mounts + // first fetches it and the other just reads the cache, not two redundant requests. This was + // never wired up here before, so the rail's self-tile (NavRail below) had no avatar/name data + // at all and fell back to a permanently-hardcoded "我" glyph regardless of who was logged in or + // what avatar they'd uploaded -- see Avatar.tsx's own comment for the wider version of this gap. + const meQuery = useQuery({ queryKey: ['me'], queryFn: getMe }); // Once per app session, regardless of which page is open -- an incoming call must surface even // while browsing contacts/settings/etc, not only while a conversation happens to be open. useEffect(() => { @@ -37,7 +45,12 @@ export function AppShell() { return (