diff --git a/client/src/components/Artifacts/Artifacts.tsx b/client/src/components/Artifacts/Artifacts.tsx index 83ca2254dc..d0df4fda25 100644 --- a/client/src/components/Artifacts/Artifacts.tsx +++ b/client/src/components/Artifacts/Artifacts.tsx @@ -13,6 +13,8 @@ import { getArtifactFilename, } from '~/utils/artifacts'; import { CodeMarkdown, CopyCodeButton } from './Code'; +import { useChatContext } from '~/Providers'; +import { cn } from '~/utils'; import store from '~/store'; export function ArtifactPreview({ @@ -59,44 +61,52 @@ export function ArtifactPreview({ } export default function Artifacts() { + const { isSubmitting } = useChatContext(); + const [isVisible, setIsVisible] = useState(false); const [activeTab, setActiveTab] = useState('code'); const artifacts = useRecoilValue(store.artifactsState); - const artifactIds = useRecoilValue(store.artifactIdsState); - const prevArtifactIdsLengthRef = useRef(artifactIds.length); - const [currentArtifactIndex, setCurrentArtifactIndex] = useState(artifactIds.length - 1); + const [currentArtifactId, setCurrentArtifactId] = useState(null); + const prevArtifactsRef = useRef({}); useEffect(() => { setIsVisible(true); }, []); useEffect(() => { - if (artifactIds.length !== prevArtifactIdsLengthRef.current) { - setCurrentArtifactIndex(artifactIds.length - 1); - prevArtifactIdsLengthRef.current = artifactIds.length; - } - }, [artifactIds]); + const artifactIds = Object.keys(artifacts); + const hasNewArtifact = artifactIds.length > Object.keys(prevArtifactsRef.current).length; + const latestArtifactId = artifactIds[artifactIds.length - 1]; - const currentArtifact = useMemo(() => { - if (artifactIds.length === 0) { - return null; + if ( + hasNewArtifact || + (isSubmitting && artifacts[latestArtifactId] !== prevArtifactsRef.current[latestArtifactId]) + ) { + setCurrentArtifactId(latestArtifactId); } - const currentId = artifactIds[currentArtifactIndex]; - return artifacts[currentId]; - }, [artifacts, artifactIds, currentArtifactIndex]); + prevArtifactsRef.current = artifacts; + }, [artifacts, isSubmitting]); + + const artifactIds = Object.keys(artifacts); + const currentArtifact = currentArtifactId != null ? artifacts[currentArtifactId] : null; + + const currentIndex = useMemo( + () => artifactIds.indexOf(currentArtifactId ?? ''), + [artifactIds, currentArtifactId], + ); const cycleArtifact = (direction: 'next' | 'prev') => { - setCurrentArtifactIndex((prevIndex) => { - if (direction === 'next') { - return (prevIndex + 1) % artifactIds.length; - } else { - return (prevIndex - 1 + artifactIds.length) % artifactIds.length; - } - }); + let newIndex: number; + if (direction === 'next') { + newIndex = (currentIndex + 1) % artifactIds.length; + } else { + newIndex = (currentIndex - 1 + artifactIds.length) % artifactIds.length; + } + setCurrentArtifactId(artifactIds[newIndex]); }; - if (currentArtifact === null) { + if (!currentArtifact) { return
No artifacts available.
; } @@ -157,8 +167,16 @@ export default function Artifacts() { {/* Content */} - + 0 ? 'result-streaming' : '', + )} + > - {`${currentArtifactIndex + 1} / ${ - artifactIds.length - }`} + {`${currentIndex + 1} / ${artifactIds.length}`}