save artifact content to cloudflare workers kv
This commit is contained in:
parent
421bf33c0e
commit
e31bec3aff
|
@ -17,10 +17,12 @@ export function HTMLPreview(props: {
|
||||||
code: string;
|
code: string;
|
||||||
autoHeight?: boolean;
|
autoHeight?: boolean;
|
||||||
height?: number;
|
height?: number;
|
||||||
|
onLoad?: (title?: string) => void;
|
||||||
}) {
|
}) {
|
||||||
const ref = useRef<HTMLIFrameElement>(null);
|
const ref = useRef<HTMLIFrameElement>(null);
|
||||||
const frameId = useRef<string>(nanoid());
|
const frameId = useRef<string>(nanoid());
|
||||||
const [iframeHeight, setIframeHeight] = useState(600);
|
const [iframeHeight, setIframeHeight] = useState(600);
|
||||||
|
const [title, setTitle] = useState("");
|
||||||
/*
|
/*
|
||||||
* https://stackoverflow.com/questions/19739001/what-is-the-difference-between-srcdoc-and-src-datatext-html-in-an
|
* https://stackoverflow.com/questions/19739001/what-is-the-difference-between-srcdoc-and-src-datatext-html-in-an
|
||||||
* 1. using srcdoc
|
* 1. using srcdoc
|
||||||
|
@ -31,9 +33,9 @@ export function HTMLPreview(props: {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.addEventListener("message", (e) => {
|
window.addEventListener("message", (e) => {
|
||||||
const { id, height } = e.data;
|
const { id, height, title } = e.data;
|
||||||
|
setTitle(title);
|
||||||
if (id == frameId.current) {
|
if (id == frameId.current) {
|
||||||
console.log("setHeight", height);
|
|
||||||
setIframeHeight(height);
|
setIframeHeight(height);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -65,32 +67,34 @@ export function HTMLPreview(props: {
|
||||||
style={{ width: "100%", height }}
|
style={{ width: "100%", height }}
|
||||||
// src={`data:text/html,${encodeURIComponent(srcDoc)}`}
|
// src={`data:text/html,${encodeURIComponent(srcDoc)}`}
|
||||||
srcDoc={srcDoc}
|
srcDoc={srcDoc}
|
||||||
|
onLoad={(e) => props?.onLoad(title)}
|
||||||
></iframe>
|
></iframe>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ArtifactShareButton({ getCode, id, style }) {
|
export function ArtifactShareButton({ getCode, id, style, fileName }) {
|
||||||
const [name, setName] = useState(id);
|
const [name, setName] = useState(id);
|
||||||
const [show, setShow] = useState(false);
|
const [show, setShow] = useState(false);
|
||||||
const shareUrl = useMemo(() =>
|
const shareUrl = useMemo(() =>
|
||||||
[location.origin, "#", Path.Artifact, "/", name].join(""),
|
[location.origin, "#", Path.Artifact, "/", name].join(""),
|
||||||
);
|
);
|
||||||
const upload = (code) =>
|
const upload = (code) =>
|
||||||
fetch(ApiPath.Artifact, {
|
id
|
||||||
method: "POST",
|
? Promise.resolve({ id })
|
||||||
body: getCode(),
|
: fetch(ApiPath.Artifact, {
|
||||||
})
|
method: "POST",
|
||||||
.then((res) => res.json())
|
body: getCode(),
|
||||||
.then(({ id }) => {
|
})
|
||||||
if (id) {
|
.then((res) => res.json())
|
||||||
setShow(true);
|
.then(({ id }) => {
|
||||||
return setName(id);
|
if (id) {
|
||||||
}
|
return { id };
|
||||||
throw Error();
|
}
|
||||||
})
|
throw Error();
|
||||||
.catch((e) => {
|
})
|
||||||
showToast(Locale.Export.Artifact.Error);
|
.catch((e) => {
|
||||||
});
|
showToast(Locale.Export.Artifact.Error);
|
||||||
|
});
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="window-action-button" style={style}>
|
<div className="window-action-button" style={style}>
|
||||||
|
@ -99,7 +103,10 @@ export function ArtifactShareButton({ getCode, id, style }) {
|
||||||
bordered
|
bordered
|
||||||
title={Locale.Export.Artifact.Title}
|
title={Locale.Export.Artifact.Title}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
upload(getCode());
|
upload(getCode()).then(({ id }) => {
|
||||||
|
setShow(true);
|
||||||
|
setName(id);
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -115,7 +122,7 @@ export function ArtifactShareButton({ getCode, id, style }) {
|
||||||
bordered
|
bordered
|
||||||
text={Locale.Export.Download}
|
text={Locale.Export.Download}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
downloadAs(getCode(), `${id}.html`).then(() =>
|
downloadAs(getCode(), `${fileName || name}.html`).then(() =>
|
||||||
setShow(false),
|
setShow(false),
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
@ -146,6 +153,8 @@ export function ArtifactShareButton({ getCode, id, style }) {
|
||||||
export function Artifact() {
|
export function Artifact() {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const [code, setCode] = useState("");
|
const [code, setCode] = useState("");
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [fileName, setFileName] = useState("");
|
||||||
const { height } = useWindowSize();
|
const { height } = useWindowSize();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -167,23 +176,29 @@ export function Artifact() {
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
height: 40,
|
height: 36,
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
padding: 12,
|
padding: 12,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ flex: 1 }}>
|
<a href={REPO_URL} target="_blank" rel="noopener noreferrer">
|
||||||
<a href={REPO_URL} target="_blank" rel="noopener noreferrer">
|
<IconButton bordered icon={<GithubIcon />} shadow />
|
||||||
<IconButton bordered icon={<GithubIcon />} shadow />
|
</a>
|
||||||
</a>
|
<div style={{ flex: 1, textAlign: "center" }}>NextChat Artifact</div>
|
||||||
</div>
|
<ArtifactShareButton id={id} getCode={() => code} fileName={fileName} />
|
||||||
<ArtifactShareButton id={id} getCode={() => code} />
|
|
||||||
</div>
|
</div>
|
||||||
{code ? (
|
{loading && <Loading />}
|
||||||
<HTMLPreview code={code} autoHeight={false} height={height - 40} />
|
{code && (
|
||||||
) : (
|
<HTMLPreview
|
||||||
<Loading />
|
code={code}
|
||||||
|
autoHeight={false}
|
||||||
|
height={height - 36}
|
||||||
|
onLoad={(title) => {
|
||||||
|
setFileName(title);
|
||||||
|
setLoading(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue