mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-22 19:30:15 +01:00
⚡️ refactor: Optimize Rendering Performance for Icons, Conversations (#5234)
* refactor: HoverButtons and Fork components to use explicit props * refactor: improve typing for Fork Component * fix: memoize SpecIcon to avoid unnecessary re-renders * feat: introduce URLIcon component and update SpecIcon for improved icon handling * WIP: optimizing icons * refactor: simplify modelLabel assignment in Message components * refactor: memoize ConvoOptions component to optimize rendering performance
This commit is contained in:
parent
687ab32bd3
commit
0f95604a67
19 changed files with 206 additions and 171 deletions
|
|
@ -1,10 +1,11 @@
|
|||
import React, { memo } from 'react';
|
||||
import { memo, useMemo } from 'react';
|
||||
import type { IconMapProps } from '~/common';
|
||||
import { icons } from '~/components/Chat/Menus/Endpoints/Icons';
|
||||
import { URLIcon } from '~/components/Endpoints/URLIcon';
|
||||
|
||||
interface ConvoIconURLProps {
|
||||
iconURL?: string;
|
||||
modelLabel?: string;
|
||||
modelLabel?: string | null;
|
||||
endpointIconURL?: string;
|
||||
assistantName?: string;
|
||||
agentName?: string;
|
||||
|
|
@ -38,33 +39,26 @@ const ConvoIconURL: React.FC<ConvoIconURLProps> = ({
|
|||
agentName,
|
||||
context,
|
||||
}) => {
|
||||
let Icon: (
|
||||
const Icon: (
|
||||
props: IconMapProps & {
|
||||
context?: string;
|
||||
iconURL?: string;
|
||||
},
|
||||
) => React.JSX.Element;
|
||||
|
||||
const isURL = !!(iconURL && (iconURL.includes('http') || iconURL.startsWith('/images/')));
|
||||
|
||||
if (!isURL) {
|
||||
Icon = icons[iconURL] ?? icons.unknown;
|
||||
} else {
|
||||
Icon = () => (
|
||||
<div
|
||||
) => React.JSX.Element = useMemo(() => icons[iconURL] ?? icons.unknown, [iconURL]);
|
||||
const isURL = useMemo(
|
||||
() => !!(iconURL && (iconURL.includes('http') || iconURL.startsWith('/images/'))),
|
||||
[iconURL],
|
||||
);
|
||||
if (isURL) {
|
||||
return (
|
||||
<URLIcon
|
||||
iconURL={iconURL}
|
||||
altName={modelLabel}
|
||||
className={classMap[context ?? 'default'] ?? classMap.default}
|
||||
style={styleMap[context ?? 'default'] ?? styleMap.default}
|
||||
>
|
||||
<img
|
||||
src={iconURL}
|
||||
alt={modelLabel}
|
||||
style={styleImageMap[context ?? 'default'] ?? styleImageMap.default}
|
||||
className="object-cover"
|
||||
/>
|
||||
</div>
|
||||
containerStyle={styleMap[context ?? 'default'] ?? styleMap.default}
|
||||
imageStyle={styleImageMap[context ?? 'default'] ?? styleImageMap.default}
|
||||
/>
|
||||
);
|
||||
|
||||
return <Icon context={context} />;
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { EModelEndpoint, isAssistantsEndpoint, alternateName } from 'librechat-data-provider';
|
||||
import UnknownIcon from '~/components/Chat/Menus/Endpoints/UnknownIcon';
|
||||
import { memo } from 'react';
|
||||
import { Feather } from 'lucide-react';
|
||||
import { EModelEndpoint, isAssistantsEndpoint, alternateName } from 'librechat-data-provider';
|
||||
import {
|
||||
Plugin,
|
||||
GPTIcon,
|
||||
|
|
@ -13,10 +13,16 @@ import {
|
|||
AzureMinimalIcon,
|
||||
CustomMinimalIcon,
|
||||
} from '~/components/svg';
|
||||
|
||||
import UnknownIcon from '~/components/Chat/Menus/Endpoints/UnknownIcon';
|
||||
import { IconProps } from '~/common';
|
||||
import { cn } from '~/utils';
|
||||
|
||||
type EndpointIcon = {
|
||||
icon: React.ReactNode | React.JSX.Element;
|
||||
bg?: string;
|
||||
name?: string | null;
|
||||
};
|
||||
|
||||
function getOpenAIColor(_model: string | null | undefined) {
|
||||
const model = _model?.toLowerCase() ?? '';
|
||||
if (model && /\bo1\b/i.test(model)) {
|
||||
|
|
@ -116,7 +122,9 @@ const MessageEndpointIcon: React.FC<IconProps> = (props) => {
|
|||
name: endpoint,
|
||||
};
|
||||
|
||||
const endpointIcons = {
|
||||
const endpointIcons: {
|
||||
[key: string]: EndpointIcon | undefined;
|
||||
} = {
|
||||
[EModelEndpoint.assistants]: assistantsIcon,
|
||||
[EModelEndpoint.agents]: agentsIcon,
|
||||
[EModelEndpoint.azureAssistants]: assistantsIcon,
|
||||
|
|
@ -189,7 +197,9 @@ const MessageEndpointIcon: React.FC<IconProps> = (props) => {
|
|||
};
|
||||
|
||||
let { icon, bg, name } =
|
||||
endpoint && endpointIcons[endpoint] ? endpointIcons[endpoint] : endpointIcons.default;
|
||||
endpoint != null && endpoint && endpointIcons[endpoint]
|
||||
? endpointIcons[endpoint] ?? {}
|
||||
: (endpointIcons.default as EndpointIcon);
|
||||
|
||||
if (iconURL && endpointIcons[iconURL]) {
|
||||
({ icon, bg, name } = endpointIcons[iconURL]);
|
||||
|
|
@ -201,9 +211,9 @@ const MessageEndpointIcon: React.FC<IconProps> = (props) => {
|
|||
|
||||
return (
|
||||
<div
|
||||
title={name}
|
||||
title={name ?? ''}
|
||||
style={{
|
||||
background: bg || 'transparent',
|
||||
background: bg != null ? bg || 'transparent' : 'transparent',
|
||||
width: size,
|
||||
height: size,
|
||||
}}
|
||||
|
|
@ -222,4 +232,4 @@ const MessageEndpointIcon: React.FC<IconProps> = (props) => {
|
|||
);
|
||||
};
|
||||
|
||||
export default MessageEndpointIcon;
|
||||
export default memo(MessageEndpointIcon);
|
||||
|
|
|
|||
21
client/src/components/Endpoints/URLIcon.tsx
Normal file
21
client/src/components/Endpoints/URLIcon.tsx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import React, { memo } from 'react';
|
||||
|
||||
export const URLIcon = memo(
|
||||
({
|
||||
iconURL,
|
||||
altName,
|
||||
containerStyle = { width: '20', height: '20' },
|
||||
imageStyle = { width: '100%', height: '100%' },
|
||||
className = 'icon-xl mr-1 shrink-0 overflow-hidden rounded-full',
|
||||
}: {
|
||||
iconURL: string;
|
||||
altName?: string | null;
|
||||
className?: string;
|
||||
containerStyle?: React.CSSProperties;
|
||||
imageStyle?: React.CSSProperties;
|
||||
}) => (
|
||||
<div className={className} style={containerStyle}>
|
||||
<img src={iconURL} alt={altName ?? ''} style={imageStyle} className="object-cover" />
|
||||
</div>
|
||||
),
|
||||
);
|
||||
Loading…
Add table
Add a link
Reference in a new issue