diff --git a/client/src/components/Artifacts/Artifacts.tsx b/client/src/components/Artifacts/Artifacts.tsx index 64022da672..1f4253be82 100644 --- a/client/src/components/Artifacts/Artifacts.tsx +++ b/client/src/components/Artifacts/Artifacts.tsx @@ -1,7 +1,7 @@ import React, { useMemo, useState, useEffect, useRef } from 'react'; -import { useRecoilValue } from 'recoil'; import * as Tabs from '@radix-ui/react-tabs'; import { Sandpack } from '@codesandbox/sandpack-react'; +import { useRecoilValue, useRecoilState } from 'recoil'; import { removeNullishValues } from 'librechat-data-provider'; import { SandpackPreview, SandpackProvider } from '@codesandbox/sandpack-react/unstyled'; import type { Artifact } from '~/common'; @@ -64,10 +64,10 @@ export default function Artifacts() { const { isSubmitting, latestMessage } = useChatContext(); const [isVisible, setIsVisible] = useState(false); - const [activeTab, setActiveTab] = useState('code'); + const [activeTab, setActiveTab] = useState('preview'); const artifacts = useRecoilValue(store.artifactsState); + const [currentArtifactId, setCurrentArtifactId] = useRecoilState(store.currentArtifactId); - const [currentArtifactId, setCurrentArtifactId] = useState(null); const orderedArtifactIds = useMemo(() => { return Object.keys(artifacts).sort( (a, b) => artifacts[a].lastUpdateTime - artifacts[b].lastUpdateTime, @@ -86,7 +86,7 @@ export default function Artifacts() { const latestArtifactId = orderedArtifactIds[orderedArtifactIds.length - 1]; setCurrentArtifactId(latestArtifactId); } - }, [orderedArtifactIds]); + }, [setCurrentArtifactId, orderedArtifactIds]); useEffect(() => { if (isSubmitting && orderedArtifactIds.length > 0) { @@ -99,7 +99,7 @@ export default function Artifacts() { lastContentRef.current = latestArtifact.content ?? null; } } - }, [isSubmitting, orderedArtifactIds, artifacts]); + }, [setCurrentArtifactId, isSubmitting, orderedArtifactIds, artifacts]); useEffect(() => { if (latestMessage?.messageId !== lastRunMessageIdRef.current) { diff --git a/client/src/components/Artifacts/CodePreview.tsx b/client/src/components/Artifacts/CodePreview.tsx index 40cb2d258a..5e0c0489c0 100644 --- a/client/src/components/Artifacts/CodePreview.tsx +++ b/client/src/components/Artifacts/CodePreview.tsx @@ -1,27 +1,38 @@ +import { useSetRecoilState } from 'recoil'; import type { Artifact } from '~/common'; import FilePreview from '~/components/Chat/Input/Files/FilePreview'; +import { useLocalize } from '~/hooks'; import { getFileType } from '~/utils'; +import store from '~/store'; const CodePreview = ({ artifact }: { artifact: Artifact | null }) => { - if (!artifact) { + const localize = useLocalize(); + const setArtifactId = useSetRecoilState(store.currentArtifactId); + if (artifact === null || artifact === undefined) { return null; } - const fileType = getFileType('text/x-'); + const fileType = getFileType('artifact'); return ( -
-
-
+ ); }; diff --git a/client/src/localization/languages/Eng.ts b/client/src/localization/languages/Eng.ts index d998e51446..52b039d141 100644 --- a/client/src/localization/languages/Eng.ts +++ b/client/src/localization/languages/Eng.ts @@ -3,6 +3,7 @@ // file deepcode ignore HardcodedNonCryptoSecret: No hardcoded secrets present in this file export default { + com_ui_artifact_click: 'Click to open', com_a11y_start: 'The AI is replying.', com_a11y_end: 'The AI has finished their reply.', com_error_moderation: diff --git a/client/src/store/artifacts.ts b/client/src/store/artifacts.ts index 35bc897535..f891545277 100644 --- a/client/src/store/artifacts.ts +++ b/client/src/store/artifacts.ts @@ -31,3 +31,18 @@ export const artifactIdsState = atom({ }, ] as const, }); + +export const currentArtifactId = atom({ + key: 'currentArtifactId', + default: null, + effects: [ + ({ onSet, node }) => { + onSet(async (newValue) => { + logger.log('artifacts', 'Recoil Effect: Setting currentArtifactId', { + key: node.key, + newValue, + }); + }); + }, + ] as const, +}); diff --git a/client/src/utils/files.ts b/client/src/utils/files.ts index 315d173114..f95f8cfd18 100644 --- a/client/src/utils/files.ts +++ b/client/src/utils/files.ts @@ -27,6 +27,12 @@ const codeFile = { title: 'Code', }; +const artifact = { + paths: CodePaths, + fill: '#2D305C', + title: 'Code', +}; + export const fileTypes = { /* Category matches */ file: { @@ -41,6 +47,7 @@ export const fileTypes = { csv: spreadsheet, pdf: textDocument, 'text/x-': codeFile, + artifact: artifact, /* Exact matches */ // 'application/json':,