소스 검색

feat: artifacts style

Dogtiti 1 년 전
부모
커밋
c27ef6ffbf
4개의 변경된 파일52개의 추가작업 그리고 30개의 파일을 삭제
  1. 20 2
      app/components/artifact.module.scss
  2. 18 24
      app/components/artifact.tsx
  3. 3 2
      app/components/chat.tsx
  4. 11 2
      app/components/markdown.tsx

+ 20 - 2
app/components/artifact.module.scss

@@ -1,8 +1,26 @@
 .artifact {
-  display: block;
+  display: flex;
   width: 100%;
   height: 100%;
-  position: relative;
+  flex-direction: column;
+  &-header {
+    display: flex;
+    align-items: center;
+    height: 36px;
+    padding: 20px;
+    background: var(--second);
+  }
+  &-title {
+    flex: 1;
+    text-align: center;
+    font-weight: bold;
+    font-size: 24px;
+  }
+  &-content {
+    flex-grow: 1;
+    padding: 0 20px 20px 20px;
+    background-color: var(--second);
+  }
 }
 
 .artifact-iframe {

+ 18 - 24
app/components/artifact.tsx

@@ -18,7 +18,7 @@ import styles from "./artifact.module.scss";
 export function HTMLPreview(props: {
   code: string;
   autoHeight?: boolean;
-  height?: number;
+  height?: number | string;
   onLoad?: (title?: string) => void;
 }) {
   const ref = useRef<HTMLIFrameElement>(null);
@@ -185,7 +185,6 @@ export function Artifact() {
   const [code, setCode] = useState("");
   const [loading, setLoading] = useState(true);
   const [fileName, setFileName] = useState("");
-  const { height } = useWindowSize();
 
   useEffect(() => {
     if (id) {
@@ -205,33 +204,28 @@ export function Artifact() {
   }, [id]);
 
   return (
-    <div className={styles.artifact}>
-      <div
-        style={{
-          height: 36,
-          display: "flex",
-          alignItems: "center",
-          padding: 12,
-        }}
-      >
+    <div className={styles["artifact"]}>
+      <div className={styles["artifact-header"]}>
         <a href={REPO_URL} target="_blank" rel="noopener noreferrer">
           <IconButton bordered icon={<GithubIcon />} shadow />
         </a>
-        <div style={{ flex: 1, textAlign: "center" }}>NextChat Artifact</div>
+        <div className={styles["artifact-title"]}>NextChat Artifact</div>
         <ArtifactShareButton id={id} getCode={() => code} fileName={fileName} />
       </div>
-      {loading && <Loading />}
-      {code && (
-        <HTMLPreview
-          code={code}
-          autoHeight={false}
-          height={height - 36}
-          onLoad={(title) => {
-            setFileName(title as string);
-            setLoading(false);
-          }}
-        />
-      )}
+      <div className={styles["artifact-content"]}>
+        {loading && <Loading />}
+        {code && (
+          <HTMLPreview
+            code={code}
+            autoHeight={false}
+            height={"100%"}
+            onLoad={(title) => {
+              setFileName(title as string);
+              setLoading(false);
+            }}
+          />
+        )}
+      </div>
     </div>
   );
 }

+ 3 - 2
app/components/chat.tsx

@@ -641,12 +641,13 @@ export function ChatActions(props: {
           ]}
           onClose={() => setShowPluginSelector(false)}
           onSelection={(s) => {
-            if (s.length === 0) return;
             const plugin = s[0];
             chatStore.updateCurrentSession((session) => {
               session.mask.plugin = s;
             });
-            showToast(plugin);
+            if (plugin) {
+              showToast(plugin);
+            }
           }}
         />
       )}

+ 11 - 2
app/components/markdown.tsx

@@ -14,7 +14,8 @@ import React from "react";
 import { useDebouncedCallback } from "use-debounce";
 import { showImageModal, FullScreen } from "./ui-lib";
 import { ArtifactShareButton, HTMLPreview } from "./artifact";
-
+import { Plugin } from "../constant";
+import { useChatStore } from "../store";
 export function Mermaid(props: { code: string }) {
   const ref = useRef<HTMLDivElement>(null);
   const [hasError, setHasError] = useState(false);
@@ -67,6 +68,9 @@ export function PreCode(props: { children: any }) {
   const [mermaidCode, setMermaidCode] = useState("");
   const [htmlCode, setHtmlCode] = useState("");
   const { height } = useWindowSize();
+  const chatStore = useChatStore();
+  const session = chatStore.currentSession();
+  const plugins = session.mask?.plugin;
 
   const renderArtifacts = useDebouncedCallback(() => {
     if (!ref.current) return;
@@ -87,6 +91,11 @@ export function PreCode(props: { children: any }) {
     // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [refText]);
 
+  const enableArtifacts = useMemo(
+    () => plugins?.includes(Plugin.Artifact),
+    [plugins],
+  );
+
   return (
     <>
       <pre ref={ref}>
@@ -104,7 +113,7 @@ export function PreCode(props: { children: any }) {
       {mermaidCode.length > 0 && (
         <Mermaid code={mermaidCode} key={mermaidCode} />
       )}
-      {htmlCode.length > 0 && (
+      {htmlCode.length > 0 && enableArtifacts && (
         <FullScreen className="no-dark html" right={70}>
           <ArtifactShareButton
             style={{ position: "absolute", right: 20, top: 10 }}