From fc6eb9f77f48945ab87ccef2156279456ddfbbda Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Thu, 22 Aug 2024 18:51:57 -0400 Subject: [PATCH] refactor: first pass rewrite --- client/src/components/Artifacts/Artifact.tsx | 86 +++++++++++++------ client/src/components/Artifacts/Artifacts.tsx | 38 ++++---- .../Chat/Messages/Content/Markdown.tsx | 6 +- client/src/components/Chat/Presentation.tsx | 2 +- client/src/store/artifacts.ts | 29 +++++-- 5 files changed, 106 insertions(+), 55 deletions(-) diff --git a/client/src/components/Artifacts/Artifact.tsx b/client/src/components/Artifacts/Artifact.tsx index 73faee54ca..8dad0116f0 100644 --- a/client/src/components/Artifacts/Artifact.tsx +++ b/client/src/components/Artifacts/Artifact.tsx @@ -1,34 +1,72 @@ +import { useEffect, useCallback } from 'react'; import { visit } from 'unist-util-visit'; -import type { Plugin } from 'unified'; -import type { Root } from 'mdast'; +import { useSetRecoilState } from 'recoil'; +import { artifactsState, artifactIdsState } from '~/store/artifacts'; +import type { Pluggable } from 'unified'; -export function artifactPlugin() { +export const artifactPlugin: Pluggable = () => { return (tree) => { - visit( - tree, - ['textDirective', 'leafDirective', 'containerDirective'], - (node) => { - node.data = { - hName: node.name, - hProperties: node.attributes, - ...node.data, - }; - return node; - }, - ); + visit(tree, ['textDirective', 'leafDirective', 'containerDirective'], (node) => { + node.data = { + hName: node.name, + hProperties: node.attributes, + ...node.data, + }; + return node; + }); }; -} +}; + +export function Artifact({ node, ...props }) { + const setArtifacts = useSetRecoilState(artifactsState); + const setArtifactIds = useSetRecoilState(artifactIdsState); + + const updateArtifact = useCallback(() => { + const content = + props.children && typeof props.children === 'string' + ? props.children + : props.children?.props?.children || ''; + + const title = props.title || 'Untitled Artifact'; + const type = props.type || 'unknown'; + const identifier = props.identifier || 'no-identifier'; + const artifactKey = `${identifier}_${type}_${title}`.replace(/\s+/g, '_').toLowerCase(); + + setArtifacts((prevArtifacts) => { + if (prevArtifacts[artifactKey] && prevArtifacts[artifactKey].content === content) { + return prevArtifacts; + } + + return { + ...prevArtifacts, + [artifactKey]: { + id: artifactKey, + identifier, + title, + type, + content, + }, + }; + }); + + setArtifactIds((prevIds) => { + if (!prevIds.includes(artifactKey)) { + return [...prevIds, artifactKey]; + } + return prevIds; + }); + }, [props, setArtifacts, setArtifactIds]); + + useEffect(() => { + updateArtifact(); + }, [updateArtifact]); -export function artifact({ node, ...props }) { - // if (props.className === 'artifact') { - console.dir(props, { depth: null }); return (
-

{props.dataIdentifier}

-

Type: {props.dataType}

+ {props.title || 'Untitled Artifact'} +

Type: {props.type || 'unknown'}

+

Identifier: {props.identifier || 'No identifier'}

{props.children}
); - // } - // return
; -} \ No newline at end of file +} diff --git a/client/src/components/Artifacts/Artifacts.tsx b/client/src/components/Artifacts/Artifacts.tsx index b5d7713add..ef5633965d 100644 --- a/client/src/components/Artifacts/Artifacts.tsx +++ b/client/src/components/Artifacts/Artifacts.tsx @@ -2,21 +2,19 @@ import React, { useMemo, useState } from 'react'; import { useRecoilValue } from 'recoil'; import * as Tabs from '@radix-ui/react-tabs'; import { Sandpack } from '@codesandbox/sandpack-react'; -import { - SandpackPreview, - SandpackProvider, -} from '@codesandbox/sandpack-react/unstyled'; +import { SandpackPreview, SandpackProvider } from '@codesandbox/sandpack-react/unstyled'; import { mapCodeFiles, sharedOptions, sharedFiles, sharedProps } from '~/utils/artifacts'; import store from '~/store'; export function CodeViewer({ showEditor = false }: { showEditor?: boolean }) { - const codeBlockIds = useRecoilValue(store.codeBlockIdsState); - const codeBlocks = useRecoilValue(store.codeBlocksState); + const artifactIds = useRecoilValue(store.artifactIdsState); + const artifacts = useRecoilValue(store.artifactsState); - const files = useMemo(() => mapCodeFiles(codeBlockIds, codeBlocks), [codeBlockIds, codeBlocks]); + // const files = useMemo(() => mapCodeFiles(artifactIds, artifacts), [artifactIds, artifacts]); - console.log('CODE FILES & blocks', files, codeBlocks); - if ((Object.keys(files)).length === 0) { + // console.log('CODE FILES & blocks', files, artifacts); + const files = {}; + if (Object.keys(files).length === 0) { return null; } @@ -55,32 +53,34 @@ export function CodeViewer({ showEditor = false }: { showEditor?: boolean }) { export default function Artifacts() { const [activeTab, setActiveTab] = useState('code'); - const codeBlockIds = useRecoilValue(store.codeBlockIdsState); - const codeBlocks = useRecoilValue(store.codeBlocksState); + const artifactIds = useRecoilValue(store.artifactIdsState); + const artifacts = useRecoilValue(store.artifactsState); - const files = useMemo(() => mapCodeFiles(codeBlockIds, codeBlocks), [codeBlockIds, codeBlocks]); - const firstFileContent = Object.values(files)[0] || ''; + // const files = useMemo(() => mapCodeFiles(artifactIds, artifacts), [artifactIds, artifacts]); + // const firstFileContent = Object.values(files)[0] || ''; + + const firstFileContent = ''; return ( -
-
- +
+
+ Code Preview -
+            
               {firstFileContent}
             
diff --git a/client/src/components/Chat/Messages/Content/Markdown.tsx b/client/src/components/Chat/Messages/Content/Markdown.tsx index a669ccd66e..db0083ef08 100644 --- a/client/src/components/Chat/Messages/Content/Markdown.tsx +++ b/client/src/components/Chat/Messages/Content/Markdown.tsx @@ -10,7 +10,7 @@ import remarkDirective from 'remark-directive'; import type { PluggableList, Pluggable } from 'unified'; import { langSubset, preprocessLaTeX, handleDoubleClick } from '~/utils'; import { CodeBlockArtifact, CodeMarkdown } from '~/components/Artifacts/Code'; -import { artifact, artifactPlugin } from '~/components/Artifacts/Artifact'; +import { Artifact as artifact, artifactPlugin } from '~/components/Artifacts/Artifact'; import CodeBlock from '~/components/Messages/Content/CodeBlock'; import { useFileDownload } from '~/data-provider'; import useLocalize from '~/hooks/useLocalize'; @@ -156,11 +156,13 @@ const Markdown = memo(({ content = '', showCursor, isLatestMessage }: TContentPr return ( startupConfig?.interface ?? defaultInterface, [startupConfig], diff --git a/client/src/store/artifacts.ts b/client/src/store/artifacts.ts index 34fa78de64..008bb208b6 100644 --- a/client/src/store/artifacts.ts +++ b/client/src/store/artifacts.ts @@ -1,27 +1,38 @@ -// client/src/store/artifacts.ts import { atom } from 'recoil'; -import type { CodeBlock } from '~/common'; +import { logger } from '~/utils'; +export interface Artifact { + identifier?: string; + title: string; + type: string; + content: string; +} -export const codeBlocksState = atom>({ - key: 'codeBlocksState', +export const artifactsState = atom>({ + key: 'artifactsState', default: {}, effects: [ ({ onSet, node }) => { onSet(async (newValue) => { - console.log('Recoil Effect: Setting codeBlocksState', { key: node.key, newValue }); + logger.log('artifacts', 'Recoil Effect: Setting artifactsState', { + key: node.key, + newValue, + }); }); }, ] as const, }); -export const codeBlockIdsState = atom({ - key: 'codeBlockIdsState', +export const artifactIdsState = atom({ + key: 'artifactIdsState', default: [], effects: [ ({ onSet, node }) => { onSet(async (newValue) => { - console.log('Recoil Effect: Setting codeBlockIdsState', { key: node.key, newValue }); + logger.log('artifacts', 'Recoil Effect: Setting artifactIdsState', { + key: node.key, + newValue, + }); }); }, ] as const, -}); \ No newline at end of file +});