From 21ef9a4567ec4f61a4d0db26f0e23815bb0f7924 Mon Sep 17 00:00:00 2001 From: Dogtiti <499960698@qq.com> Date: Thu, 25 Jul 2024 17:37:21 +0800 Subject: [PATCH 1/2] feat: artifacts style --- .gitignore | 2 ++ app/components/artifact.module.scss | 12 +++++++++ app/components/artifact.tsx | 25 +++++++++--------- app/components/markdown.tsx | 4 +-- app/components/ui-lib.module.scss | 1 + app/components/ui-lib.tsx | 39 +++++++++++++++++++++-------- 6 files changed, 58 insertions(+), 25 deletions(-) create mode 100644 app/components/artifact.module.scss diff --git a/.gitignore b/.gitignore index a24c6e047..2ff556f64 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,5 @@ dev *.key *.key.pub + +masks.json diff --git a/app/components/artifact.module.scss b/app/components/artifact.module.scss new file mode 100644 index 000000000..1e166f418 --- /dev/null +++ b/app/components/artifact.module.scss @@ -0,0 +1,12 @@ +.artifact { + display: block; + width: 100%; + height: 100%; + position: relative; +} + +.artifact-iframe { + width: 100%; + border: var(--border-in-light); + border-radius: 6px; +} diff --git a/app/components/artifact.tsx b/app/components/artifact.tsx index c06573b09..64a6ad652 100644 --- a/app/components/artifact.tsx +++ b/app/components/artifact.tsx @@ -13,6 +13,7 @@ import { Modal, showToast } from "./ui-lib"; import { copyToClipboard, downloadAs } from "../utils"; import { Path, ApiPath, REPO_URL } from "@/app/constant"; import { Loading } from "./home"; +import styles from "./artifact.module.scss"; export function HTMLPreview(props: { code: string; @@ -61,17 +62,22 @@ export function HTMLPreview(props: { return props.code + script; }, [props.code]); + const handleOnLoad = () => { + if (props?.onLoad) { + props.onLoad(title); + } + }; + return ( + onLoad={handleOnLoad} + /> ); } @@ -186,14 +192,7 @@ export function Artifact() { }, [id]); return ( -
+
)} {htmlCode.length > 0 && ( - + htmlCode} /> void; + onClick?: (e: React.MouseEvent) => void; }) { return (
(props: { onClose?: () => void; multiple?: boolean; }) { + const [selectedValues, setSelectedValues] = useState( + Array.isArray(props.defaultSelectedValue) + ? props.defaultSelectedValue + : props.defaultSelectedValue !== undefined + ? [props.defaultSelectedValue] + : [], + ); + + const handleSelection = ( + e: React.MouseEvent, + value: T, + ) => { + if (props.multiple) { + e.stopPropagation(); + const newSelectedValues = selectedValues.includes(value) + ? selectedValues.filter((v) => v !== value) + : [...selectedValues, value]; + setSelectedValues(newSelectedValues); + props.onSelection?.(newSelectedValues); + } else { + setSelectedValues([value]); + props.onSelection?.([value]); + props.onClose?.(); + } + }; + return (
props.onClose?.()}>
{props.items.map((item, i) => { - const selected = props.multiple - ? // @ts-ignore - props.defaultSelectedValue?.includes(item.value) - : props.defaultSelectedValue === item.value; + const selected = selectedValues.includes(item.value); return ( { - props.onSelection?.([item.value]); - props.onClose?.(); - }} + onClick={(e) => handleSelection(e, item.value)} > {selected ? (
(props: {
); } - export function FullScreen(props: any) { const { children, right = 10, top = 10, ...rest } = props; const ref = useRef(); From c27ef6ffbf94be6bab2f6ba7cc9237b1125627a2 Mon Sep 17 00:00:00 2001 From: Dogtiti <499960698@qq.com> Date: Thu, 25 Jul 2024 23:29:29 +0800 Subject: [PATCH 2/2] feat: artifacts style --- app/components/artifact.module.scss | 22 +++++++++++++-- app/components/artifact.tsx | 42 +++++++++++++---------------- app/components/chat.tsx | 5 ++-- app/components/markdown.tsx | 13 +++++++-- 4 files changed, 52 insertions(+), 30 deletions(-) diff --git a/app/components/artifact.module.scss b/app/components/artifact.module.scss index 1e166f418..2909008b0 100644 --- a/app/components/artifact.module.scss +++ b/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 { diff --git a/app/components/artifact.tsx b/app/components/artifact.tsx index b378cba37..3006fe012 100644 --- a/app/components/artifact.tsx +++ b/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(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 ( -
-
+
+
} shadow /> -
NextChat Artifact
+
NextChat Artifact
code} fileName={fileName} />
- {loading && } - {code && ( - { - setFileName(title as string); - setLoading(false); - }} - /> - )} +
+ {loading && } + {code && ( + { + setFileName(title as string); + setLoading(false); + }} + /> + )} +
); } diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 6bfd99b53..33956e6bc 100644 --- a/app/components/chat.tsx +++ b/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); + } }} /> )} diff --git a/app/components/markdown.tsx b/app/components/markdown.tsx index 219c4c868..36c742902 100644 --- a/app/components/markdown.tsx +++ b/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(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 ( <>
@@ -104,7 +113,7 @@ export function PreCode(props: { children: any }) {
       {mermaidCode.length > 0 && (
         
       )}
-      {htmlCode.length > 0 && (
+      {htmlCode.length > 0 && enableArtifacts && (