mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-03-07 08:40:19 +01:00
* 🔄 refactor: Update Artifacts and Messages Contexts to Use Latest Message ID and Depth
- Modified ArtifactsContext to retrieve latestMessage using Recoil state management.
- Updated MessagesViewContext to replace latestMessage with latestMessageId and latestMessageDepth for improved clarity and consistency.
- Adjusted various components (HoverButtons, MessageParts, MessageRender, ContentRender) to utilize latestMessageId instead of the entire message object, enhancing performance and reducing unnecessary re-renders.
- Refactored useChatHelpers to extract latestMessageId and latestMessageDepth, streamlining message handling across the application.
* refactor: Introduce PartWithContext Component for Optimized Message Rendering
- Added a new PartWithContext component to encapsulate message part rendering logic, improving context management and reducing redundancy in the ContentParts component.
- Updated MessageRender to utilize the new PartWithContext, streamlining the context provider setup and enhancing code clarity.
- Refactored related logic to ensure proper context values are passed, improving maintainability and performance in message rendering.
* refactor: Update Components to Use Function Declarations and Improve Readability
- Refactored several components (MessageContainer, Markdown, MarkdownCode, MarkdownCodeNoExecution, MarkdownAnchor, MarkdownParagraph, MarkdownImage, TextPart, PlaceholderRow) to use function declarations instead of arrow functions, enhancing readability and consistency across the codebase.
- Added display names to memoized components for better debugging and profiling in React DevTools.
- Improved overall code clarity and maintainability by standardizing component definitions.
* refactor: Standardize MessageRender and ContentRender Components for Improved Clarity
- Refactored MessageRender and ContentRender components to use function declarations, enhancing readability and consistency.
- Streamlined props handling by removing unnecessary parameters and improving the use of hooks for state management.
- Updated memoization and rendering logic to optimize performance and reduce unnecessary re-renders.
- Enhanced overall code clarity and maintainability by standardizing component definitions and structure.
* refactor: Enhance Header Component with Memoization for Performance
- Refactored the Header component to utilize React's memoization by wrapping it with the memo function, improving rendering performance by preventing unnecessary re-renders.
- Changed the export to a memoized version of the Header component, ensuring better debugging with a display name.
- Maintained overall code clarity and consistency in component structure.
* refactor: Transition Components to Use Recoil for State Management
- Updated multiple components (AddMultiConvo, TemporaryChat, HeaderNewChat, PresetsMenu, ModelSelectorChatContext) to utilize Recoil for state management, enhancing consistency and performance.
- Replaced useChatContext with Recoil selectors and atoms, improving data flow and reducing unnecessary re-renders.
- Introduced new selectors for conversation ID and endpoint retrieval, streamlining component logic and enhancing maintainability.
- Improved overall code clarity by standardizing state management practices across components.
* refactor: Integrate getConversation Callback for Enhanced State Management
- Updated multiple components (Mention, ModelSelectorChatContext, ModelSelectorContext, FavoritesList) to utilize a getConversation callback instead of directly accessing conversation state, improving encapsulation and maintainability.
- Refactored useSelectMention hook to accept getConversation, streamlining conversation retrieval and enhancing code clarity.
- Introduced new Recoil selectors for conversation properties, ensuring consistent state management across components.
- Enhanced overall code structure by standardizing the approach to conversation handling, reducing redundancy and improving performance.
* refactor: Optimize LiveAnnouncer Context Value with useMemo
- Updated the LiveAnnouncer component to utilize useMemo for context value creation, enhancing performance by preventing unnecessary recalculations of the context object.
- Improved overall code clarity and maintainability by ensuring that context values are only recomputed when their dependencies change.
* refactor: Update AgentPanelSwitch to Use Recoil for Agent ID Management
- Refactored AgentPanelSwitch component to utilize Recoil for retrieving the current agent ID, replacing the previous use of chat context.
- Improved state management by ensuring the agent ID is derived from Recoil, enhancing code clarity and maintainability.
- Adjusted useEffect dependencies to reflect the new state management approach, streamlining the component's logic.
* refactor: Enhance useLocalize Hook with useCallback for Improved Performance
- Updated the useLocalize hook to utilize useCallback for the translation function, optimizing performance by preventing unnecessary re-creations of the function on each render.
- Improved code clarity by ensuring that the translation function is memoized, enhancing maintainability and efficiency in localization handling.
* refactor: Rename useCreateConversationAtom to useSetConversationAtom for Clarity
- Updated the hook name from useCreateConversationAtom to useSetConversationAtom to better reflect its functionality in managing conversation state.
- Introduced a new implementation for setting conversation state, enhancing clarity and maintainability in the codebase.
- Adjusted related references in the useNewConvo hook to align with the new naming convention.
* refactor: Enhance useKeyDialog Hook with useMemo and useCallback for Improved Performance
- Updated the useKeyDialog hook to utilize useMemo for returning the dialog state and handlers, optimizing performance by preventing unnecessary recalculations.
- Refactored the onOpenChange function to use useCallback, ensuring it only changes when its dependencies do, enhancing maintainability and clarity in the code.
- Improved overall code structure and readability by streamlining the hook's logic and dependencies.
* feat: Add useRenderChangeLog Hook for Debugging Render Changes
- Introduced a new hook, useRenderChangeLog, that logs changes in tracked values between renders when a debug flag is enabled.
- Utilizes useEffect and useRef to track previous values and identify changes, enhancing debugging capabilities for component renders.
- Provides detailed console output for initial renders and value changes, improving developer insights during the rendering process.
* refactor: Update useSelectAgent Hook for Improved State Management and Performance
- Refactored the useSelectAgent hook to utilize useRecoilCallback for fetching conversation data, enhancing state management and performance.
- Replaced the use of useChatContext with a more efficient approach, streamlining the logic for selecting agents and updating conversations.
- Improved error handling and ensured asynchronous operations are properly awaited, enhancing reliability in agent selection and data fetching processes.
* refactor: Optimize useDefaultConvo Hook with useCallback for Improved Performance
- Refactored the getDefaultConversation function within the useDefaultConvo hook to utilize useCallback, enhancing performance by memoizing the function and preventing unnecessary re-creations on re-renders.
- Streamlined the logic for cleaning input and output in the conversation object, improving code clarity and maintainability.
- Ensured that dependencies for useCallback are correctly set, enhancing the reliability of the hook's behavior.
* refactor: Optimize Agent Components with Memoization for Improved Performance
- Refactored multiple agent-related components (AgentAvatar, AgentCategorySelector, AgentSelect, DeleteButton, FileContext, FileSearch, Files) to utilize React.memo for memoization, enhancing rendering performance by preventing unnecessary re-renders.
- Updated the FileRow component to make setFilesLoading optional, improving flexibility in file handling.
- Streamlined component logic and improved maintainability by ensuring that props are compared efficiently in memoized components.
* refactor: Enhance File Handling and Agent Components for Improved Performance
- Refactored multiple components (DeleteButton, FileContext, FileSearch, Files) to utilize new file handling hooks that separate chat context from file operations, improving performance and maintainability.
- Introduced useFileHandlingNoChatContext and useSharePointFileHandlingNoChatContext hooks to streamline file handling logic, enhancing flexibility in managing file states.
- Updated DeleteButton to improve conversation state management and ensure proper handling of agent deletions, enhancing user experience.
- Optimized imports and component structure for better clarity and organization across the affected files.
* refactor: Enhance useRenderChangeLog Hook with Improved Type Safety and Documentation
- Updated the useRenderChangeLog hook to improve type safety by specifying the value types as string, number, boolean, null, or undefined.
- Enhanced documentation to clarify usage and enablement of the debug feature, ensuring better developer insights during rendering.
- Added a production check to prevent logging in production builds, optimizing performance and maintaining clean console output.
* chore: imports
* refactor: Replace useRecoilCallback with useGetConversation Hook for Improved Clarity and Performance
- Refactored multiple components (AddMultiConvo, ModelSelectorChatContext, FavoritesList, useSelectAgent, usePresets) to utilize the new useGetConversation hook, enhancing clarity and reducing complexity by eliminating the use of useRecoilCallback.
- Streamlined conversation retrieval logic across components, improving maintainability and performance.
- Updated imports and component structure for better organization and readability.
* refactor: Enhance Memoization in DeleteButton Component for Improved Performance
- Updated the memoization logic in the DeleteButton component to include a comparison for the setCurrentAgentId prop, ensuring more efficient re-renders.
- This change improves performance by preventing unnecessary updates when the agent ID and current agent ID remain unchanged.
* chore: fix test
* refactor: Improve Memoization Logic in AgentSelect Component
- Updated the memoization comparison in the AgentSelect component to directly compare agentQuery.data objects, enhancing performance by ensuring accurate re-renders.
- Refactored the useCreateConversationAtom function to streamline the logic for updating conversation keys, improving clarity and maintainability.
* refactor: Simplify State Management in DeleteButton Component
- Removed unnecessary setConversationOption function, streamlining the logic for updating conversation state after agent deletion.
- Updated the conversation state directly within the deleteAgent mutation, improving clarity and maintainability of the component.
- Refactored conversationByKeySelector to directly reference conversationByIndex, enhancing performance and reducing complexity in state retrieval.
* refactor: Remove Unused Conversation Prop from Mention Component
- Eliminated the conversation prop from the Mention component, simplifying its interface and reducing unnecessary dependencies.
- Updated the ChatForm component to reflect this change, enhancing clarity and maintainability of the codebase.
- Introduced useGetConversation hook for improved conversation retrieval logic, streamlining the component's functionality.
* refactor: Simplify File Handling State Management Across Components
- Removed the unused setFilesLoading function from FileContext, FileSearch, and Files components, streamlining the file handling state management.
- Updated the FileHandlingState type to make setFilesLoading optional, enhancing flexibility in file operations.
- Improved memoization logic by directly referencing necessary state properties, ensuring better performance and maintainability.
* refactor: Update ArtifactsContext for Improved State Management
- Replaced the useChatContext hook with direct Recoil state retrieval for isSubmitting, latestMessage, and conversationId, simplifying the context provider's logic.
- Enhanced memoization by ensuring relevant state properties are directly referenced, improving performance and maintainability.
- Streamlined the context value creation to reflect the updated state management approach.
* refactor: Adjust Memoization Logic in ArtifactsContext for Consistency
- Updated the memoization logic in the ArtifactsProvider to ensure the messageId is consistently referenced, improving clarity and maintainability.
- This change enhances the performance of the context provider by ensuring all relevant properties are included in the memoization dependencies.
218 lines
6.3 KiB
TypeScript
218 lines
6.3 KiB
TypeScript
import React, { memo, useMemo, useRef, useEffect } from 'react';
|
|
import { useRecoilValue } from 'recoil';
|
|
import { useToastContext } from '@librechat/client';
|
|
import { PermissionTypes, Permissions, apiBaseUrl } from 'librechat-data-provider';
|
|
import MermaidErrorBoundary from '~/components/Messages/Content/MermaidErrorBoundary';
|
|
import CodeBlock from '~/components/Messages/Content/CodeBlock';
|
|
import Mermaid from '~/components/Messages/Content/Mermaid';
|
|
import useHasAccess from '~/hooks/Roles/useHasAccess';
|
|
import { useFileDownload } from '~/data-provider';
|
|
import { useCodeBlockContext } from '~/Providers';
|
|
import { handleDoubleClick } from '~/utils';
|
|
import { useLocalize } from '~/hooks';
|
|
import store from '~/store';
|
|
|
|
type TCodeProps = {
|
|
inline?: boolean;
|
|
className?: string;
|
|
children: React.ReactNode;
|
|
};
|
|
|
|
export const code: React.ElementType = memo(function MarkdownCode({
|
|
className,
|
|
children,
|
|
}: TCodeProps) {
|
|
const canRunCode = useHasAccess({
|
|
permissionType: PermissionTypes.RUN_CODE,
|
|
permission: Permissions.USE,
|
|
});
|
|
const match = /language-(\w+)/.exec(className ?? '');
|
|
const lang = match && match[1];
|
|
const isMath = lang === 'math';
|
|
const isMermaid = lang === 'mermaid';
|
|
const isSingleLine = typeof children === 'string' && children.split('\n').length === 1;
|
|
|
|
const { getNextIndex, resetCounter } = useCodeBlockContext();
|
|
const blockIndex = useRef(getNextIndex(isMath || isMermaid || isSingleLine)).current;
|
|
|
|
useEffect(() => {
|
|
resetCounter();
|
|
}, [children, resetCounter]);
|
|
|
|
if (isMath) {
|
|
return <>{children}</>;
|
|
} else if (isMermaid) {
|
|
const content = typeof children === 'string' ? children : String(children);
|
|
return (
|
|
<MermaidErrorBoundary code={content}>
|
|
<Mermaid id={`mermaid-${blockIndex}`}>{content}</Mermaid>
|
|
</MermaidErrorBoundary>
|
|
);
|
|
} else if (isSingleLine) {
|
|
return (
|
|
<code onDoubleClick={handleDoubleClick} className={className}>
|
|
{children}
|
|
</code>
|
|
);
|
|
} else {
|
|
return (
|
|
<CodeBlock
|
|
lang={lang ?? 'text'}
|
|
codeChildren={children}
|
|
blockIndex={blockIndex}
|
|
allowExecution={canRunCode}
|
|
/>
|
|
);
|
|
}
|
|
});
|
|
code.displayName = 'MarkdownCode';
|
|
|
|
export const codeNoExecution: React.ElementType = memo(function MarkdownCodeNoExecution({
|
|
className,
|
|
children,
|
|
}: TCodeProps) {
|
|
const match = /language-(\w+)/.exec(className ?? '');
|
|
const lang = match && match[1];
|
|
|
|
if (lang === 'math') {
|
|
return children;
|
|
} else if (lang === 'mermaid') {
|
|
const content = typeof children === 'string' ? children : String(children);
|
|
return <Mermaid>{content}</Mermaid>;
|
|
} else if (typeof children === 'string' && children.split('\n').length === 1) {
|
|
return (
|
|
<code onDoubleClick={handleDoubleClick} className={className}>
|
|
{children}
|
|
</code>
|
|
);
|
|
} else {
|
|
return <CodeBlock lang={lang ?? 'text'} codeChildren={children} allowExecution={false} />;
|
|
}
|
|
});
|
|
codeNoExecution.displayName = 'MarkdownCodeNoExecution';
|
|
|
|
type TAnchorProps = {
|
|
href: string;
|
|
children: React.ReactNode;
|
|
};
|
|
|
|
export const a: React.ElementType = memo(function MarkdownAnchor({ href, children }: TAnchorProps) {
|
|
const user = useRecoilValue(store.user);
|
|
const { showToast } = useToastContext();
|
|
const localize = useLocalize();
|
|
|
|
const {
|
|
file_id = '',
|
|
filename = '',
|
|
filepath,
|
|
} = useMemo(() => {
|
|
const pattern = new RegExp(`(?:files|outputs)/${user?.id}/([^\\s]+)`);
|
|
const match = href.match(pattern);
|
|
if (match && match[0]) {
|
|
const path = match[0];
|
|
const parts = path.split('/');
|
|
const name = parts.pop();
|
|
const file_id = parts.pop();
|
|
return { file_id, filename: name, filepath: path };
|
|
}
|
|
return { file_id: '', filename: '', filepath: '' };
|
|
}, [user?.id, href]);
|
|
|
|
const { refetch: downloadFile } = useFileDownload(user?.id ?? '', file_id);
|
|
const props: { target?: string; onClick?: React.MouseEventHandler } = { target: '_blank' };
|
|
|
|
if (!file_id || !filename) {
|
|
return (
|
|
<a href={href} {...props}>
|
|
{children}
|
|
</a>
|
|
);
|
|
}
|
|
|
|
const handleDownload = async (event: React.MouseEvent<HTMLAnchorElement>) => {
|
|
event.preventDefault();
|
|
try {
|
|
const stream = await downloadFile();
|
|
if (stream.data == null || stream.data === '') {
|
|
console.error('Error downloading file: No data found');
|
|
showToast({
|
|
status: 'error',
|
|
message: localize('com_ui_download_error'),
|
|
});
|
|
return;
|
|
}
|
|
const link = document.createElement('a');
|
|
link.href = stream.data;
|
|
link.setAttribute('download', filename);
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
document.body.removeChild(link);
|
|
window.URL.revokeObjectURL(stream.data);
|
|
} catch (error) {
|
|
console.error('Error downloading file:', error);
|
|
}
|
|
};
|
|
|
|
props.onClick = handleDownload;
|
|
props.target = '_blank';
|
|
|
|
const domainServerBaseUrl = `${apiBaseUrl()}/api`;
|
|
|
|
return (
|
|
<a
|
|
href={
|
|
filepath?.startsWith('files/')
|
|
? `${domainServerBaseUrl}/${filepath}`
|
|
: `${domainServerBaseUrl}/files/${filepath}`
|
|
}
|
|
{...props}
|
|
>
|
|
{children}
|
|
</a>
|
|
);
|
|
});
|
|
a.displayName = 'MarkdownAnchor';
|
|
|
|
type TParagraphProps = {
|
|
children: React.ReactNode;
|
|
};
|
|
|
|
export const p: React.ElementType = memo(function MarkdownParagraph({ children }: TParagraphProps) {
|
|
return <p className="mb-2 whitespace-pre-wrap">{children}</p>;
|
|
});
|
|
p.displayName = 'MarkdownParagraph';
|
|
|
|
type TImageProps = {
|
|
src?: string;
|
|
alt?: string;
|
|
title?: string;
|
|
className?: string;
|
|
style?: React.CSSProperties;
|
|
};
|
|
|
|
export const img: React.ElementType = memo(function MarkdownImage({
|
|
src,
|
|
alt,
|
|
title,
|
|
className,
|
|
style,
|
|
}: TImageProps) {
|
|
// Get the base URL from the API endpoints
|
|
const baseURL = apiBaseUrl();
|
|
|
|
// If src starts with /images/, prepend the base URL
|
|
const fixedSrc = useMemo(() => {
|
|
if (!src) return src;
|
|
|
|
// If it's already an absolute URL or doesn't start with /images/, return as is
|
|
if (src.startsWith('http') || src.startsWith('data:') || !src.startsWith('/images/')) {
|
|
return src;
|
|
}
|
|
|
|
// Prepend base URL to the image path
|
|
return `${baseURL}${src}`;
|
|
}, [src, baseURL]);
|
|
|
|
return <img src={fixedSrc} alt={alt} title={title} className={className} style={style} />;
|
|
});
|
|
img.displayName = 'MarkdownImage';
|