Files
ChatApp/apps/desktop/src/components/Avatar.tsx
T
byGalax 6d0e4fb1f0 perf(P6A.T5): pre-warm Supabase + avatar loading hints
Fire a no-await profiles query in AuthContext on session establish to absorb
cold-connection latency before the first user-triggered request. Add
loading='lazy' default to the central Avatar component so all off-screen
avatars (chat list, friends list, popovers, message senders) skip eager
Supabase Storage fetches; set loading='eager' on ConversationHeader (active
conv header) and CallParticipantTile inline imgs (both AudioContent and
VideoStub) which are always above-the-fold when visible.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 23:43:04 +02:00

56 lines
1.6 KiB
TypeScript

// Reusable avatar that prefers an uploaded image and falls back to a coloured
// letter circle. Use this everywhere the app needs to render a profile.
import { useCachedAvatarUrl } from '../lib/avatarCache';
interface Props {
url?: string | null | undefined;
displayName?: string | null | undefined;
className?: string;
// Background gradient classes used when no image is set. Defaults to a
// brand-tinted fallback; callers can override (e.g. to colour-by-id).
fallbackClass?: string;
alt?: string;
// Browser loading hint. Use 'eager' for above-the-fold avatars (e.g. the
// active conversation header, call tiles). Defaults to 'lazy' so off-screen
// avatars (chat list rows, friends list, popovers) don't hammer Supabase
// Storage on initial render.
loading?: 'eager' | 'lazy';
}
export function Avatar({
url,
displayName,
className = 'h-10 w-10',
fallbackClass = 'bg-accent/20 text-accent',
alt,
loading = 'lazy',
}: Props) {
const effectiveUrl = useCachedAvatarUrl(url);
if (effectiveUrl) {
return (
<img
src={effectiveUrl}
alt={alt ?? displayName ?? ''}
className={'shrink-0 rounded-full object-cover ' + className}
draggable={false}
loading={loading}
/>
);
}
const letter = (displayName ?? '?').trim().charAt(0).toUpperCase() || '?';
return (
<div
aria-hidden={alt ? undefined : 'true'}
className={
'flex shrink-0 items-center justify-center rounded-full font-semibold ' +
fallbackClass +
' ' +
className
}
>
{letter}
</div>
);
}