LibreChat/client/src/components/Chat/Presentation.tsx
Danny Avila 9a7f763714
🔄 refactor: Artifact Visibility Management (#7181)
* fix: Reset artifacts on unmount and remove useIdChangeEffect hook

* feat: Replace SVG icons with Lucide icons for improved consistency

* fix: Refactor artifact reset logic on unmount and conversation change

* refactor: Rename artifactsVisible to artifactsVisibility for consistency

* feat: Replace custom SVG icons with Lucide icons for improved consistency

* feat: Add visibleArtifacts atom for managing visibility state

* feat: Implement debounced visibility state management for artifacts

* refactor: Add useIdChangeEffect hook to reset visible artifacts on conversation ID change

* refactor: Remove unnecessary dependency from useMemo in TextPart component

* refactor: Enhance artifact visibility management by incorporating location checks for search path

* refactor: Improve transition effects for artifact visibility in Artifacts component

* chore: Remove preprocessCodeArtifacts function and related tests

* fix: Update regex for detecting enclosed artifacts in latest message

* refactor: Update artifact visibility checks to be more generic (not just search)

* chore: Enhance artifact visibility logging

* refactor: Extract closeArtifacts function to improve button click handling

* refactor: remove nested logic from use artifacts effect

* refactor: Update regex for detecting enclosed artifacts to handle new line variations
2025-05-01 14:40:39 -04:00

80 lines
2.9 KiB
TypeScript

import { useRecoilValue } from 'recoil';
import { useEffect, useMemo } from 'react';
import { FileSources, LocalStorageKeys } from 'librechat-data-provider';
import type { ExtendedFile } from '~/common';
import { useDeleteFilesMutation } from '~/data-provider';
import DragDropWrapper from '~/components/Chat/Input/Files/DragDropWrapper';
import Artifacts from '~/components/Artifacts/Artifacts';
import { SidePanelGroup } from '~/components/SidePanel';
import { useSetFilesToDelete } from '~/hooks';
import { EditorProvider } from '~/Providers';
import store from '~/store';
export default function Presentation({ children }: { children: React.ReactNode }) {
const artifacts = useRecoilValue(store.artifactsState);
const artifactsVisibility = useRecoilValue(store.artifactsVisibility);
const setFilesToDelete = useSetFilesToDelete();
const { mutateAsync } = useDeleteFilesMutation({
onSuccess: () => {
console.log('Temporary Files deleted');
setFilesToDelete({});
},
onError: (error) => {
console.log('Error deleting temporary files:', error);
},
});
useEffect(() => {
const filesToDelete = localStorage.getItem(LocalStorageKeys.FILES_TO_DELETE);
const map = JSON.parse(filesToDelete ?? '{}') as Record<string, ExtendedFile>;
const files = Object.values(map)
.filter(
(file) =>
file.filepath != null && file.source && !(file.embedded ?? false) && file.temp_file_id,
)
.map((file) => ({
file_id: file.file_id,
filepath: file.filepath as string,
source: file.source as FileSources,
embedded: !!(file.embedded ?? false),
}));
if (files.length === 0) {
return;
}
mutateAsync({ files });
}, [mutateAsync]);
const defaultLayout = useMemo(() => {
const resizableLayout = localStorage.getItem('react-resizable-panels:layout');
return typeof resizableLayout === 'string' ? JSON.parse(resizableLayout) : undefined;
}, []);
const defaultCollapsed = useMemo(() => {
const collapsedPanels = localStorage.getItem('react-resizable-panels:collapsed');
return typeof collapsedPanels === 'string' ? JSON.parse(collapsedPanels) : true;
}, []);
const fullCollapse = useMemo(() => localStorage.getItem('fullPanelCollapse') === 'true', []);
return (
<DragDropWrapper className="relative flex w-full grow overflow-hidden bg-presentation">
<SidePanelGroup
defaultLayout={defaultLayout}
fullPanelCollapse={fullCollapse}
defaultCollapsed={defaultCollapsed}
artifacts={
artifactsVisibility === true && Object.keys(artifacts ?? {}).length > 0 ? (
<EditorProvider>
<Artifacts />
</EditorProvider>
) : null
}
>
<main className="flex h-full flex-col overflow-y-auto" role="main">
{children}
</main>
</SidePanelGroup>
</DragDropWrapper>
);
}