mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-03-11 10:32:37 +01:00
refactor: optimize image loading and error handling in UserAvatar component
This commit is contained in:
parent
9b4c4cafb6
commit
41380d9cb9
1 changed files with 23 additions and 7 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { memo, useState } from 'react';
|
import React, { memo, useState, useMemo } from 'react';
|
||||||
import { UserIcon, useAvatar } from '@librechat/client';
|
import { UserIcon, useAvatar } from '@librechat/client';
|
||||||
import type { TUser } from 'librechat-data-provider';
|
import type { TUser } from 'librechat-data-provider';
|
||||||
import type { IconProps } from '~/common';
|
import type { IconProps } from '~/common';
|
||||||
|
|
@ -17,9 +17,15 @@ type UserAvatarProps = {
|
||||||
|
|
||||||
const UserAvatar = memo(({ size, user, avatarSrc, username, className }: UserAvatarProps) => {
|
const UserAvatar = memo(({ size, user, avatarSrc, username, className }: UserAvatarProps) => {
|
||||||
const [imageError, setImageError] = useState(false);
|
const [imageError, setImageError] = useState(false);
|
||||||
|
const [imageLoaded, setImageLoaded] = useState(false);
|
||||||
|
|
||||||
const handleImageError = () => {
|
const handleImageError = () => {
|
||||||
setImageError(true);
|
setImageError(true);
|
||||||
|
setImageLoaded(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleImageLoad = () => {
|
||||||
|
setImageLoaded(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderDefaultAvatar = () => (
|
const renderDefaultAvatar = () => (
|
||||||
|
|
@ -36,6 +42,10 @@ const UserAvatar = memo(({ size, user, avatarSrc, username, className }: UserAva
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const hasAvatar = useMemo(() => (user?.avatar ?? '') || avatarSrc, [user?.avatar, avatarSrc]);
|
||||||
|
const showImage = useMemo(() => hasAvatar && !imageError, [hasAvatar, imageError]);
|
||||||
|
const imageSrc = useMemo(() => (user?.avatar ?? '') || avatarSrc, [user?.avatar, avatarSrc]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
title={username}
|
title={username}
|
||||||
|
|
@ -45,14 +55,16 @@ const UserAvatar = memo(({ size, user, avatarSrc, username, className }: UserAva
|
||||||
}}
|
}}
|
||||||
className={cn('relative flex items-center justify-center', className ?? '')}
|
className={cn('relative flex items-center justify-center', className ?? '')}
|
||||||
>
|
>
|
||||||
{(!(user?.avatar ?? '') && (!(user?.username ?? '') || user?.username.trim() === '')) ||
|
{!showImage || !imageLoaded ? renderDefaultAvatar() : null}
|
||||||
imageError ? (
|
{showImage && (
|
||||||
renderDefaultAvatar()
|
|
||||||
) : (
|
|
||||||
<img
|
<img
|
||||||
|
style={{
|
||||||
|
display: imageLoaded ? 'block' : 'none',
|
||||||
|
}}
|
||||||
className="rounded-full"
|
className="rounded-full"
|
||||||
src={(user?.avatar ?? '') || avatarSrc}
|
src={imageSrc}
|
||||||
alt="avatar"
|
alt="avatar"
|
||||||
|
onLoad={handleImageLoad}
|
||||||
onError={handleImageError}
|
onError={handleImageError}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
@ -69,8 +81,12 @@ const Icon: React.FC<IconProps> = memo((props) => {
|
||||||
const avatarSrc = useAvatar(user);
|
const avatarSrc = useAvatar(user);
|
||||||
const localize = useLocalize();
|
const localize = useLocalize();
|
||||||
|
|
||||||
|
const username = useMemo(
|
||||||
|
() => user?.name ?? user?.username ?? localize('com_nav_user'),
|
||||||
|
[user?.name, user?.username, localize],
|
||||||
|
);
|
||||||
|
|
||||||
if (isCreatedByUser) {
|
if (isCreatedByUser) {
|
||||||
const username = user?.name ?? user?.username ?? localize('com_nav_user');
|
|
||||||
return (
|
return (
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
size={size}
|
size={size}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue