mirror of
https://github.com/stefanpejcic/openpanel
synced 2025-06-26 18:28:26 +00:00
101 lines
2.5 KiB
TypeScript
101 lines
2.5 KiB
TypeScript
import React from "react";
|
|
import { useRouter } from "next/router";
|
|
import { decompressFromEncodedURIComponent } from "lz-string";
|
|
import base64url from "base64url";
|
|
|
|
type UseCodeReturn = {
|
|
code: string | null;
|
|
css: string | null;
|
|
isReady: boolean;
|
|
hasQuery: boolean;
|
|
disableScroll: boolean;
|
|
useTailwind: boolean;
|
|
isLoading: boolean;
|
|
};
|
|
|
|
export const useCode = (): UseCodeReturn => {
|
|
const { query, isReady } = useRouter();
|
|
const {
|
|
code: encoded,
|
|
hash,
|
|
disableScroll,
|
|
tailwind,
|
|
css: cssCompressed,
|
|
} = query ?? {};
|
|
|
|
const [isLoading, setIsLoading] = React.useState<boolean>(true);
|
|
const [compressed, setCompressed] = React.useState<string | undefined>();
|
|
|
|
React.useEffect(() => {
|
|
if (!isReady) return;
|
|
if (compressed) return;
|
|
|
|
if (encoded) {
|
|
setCompressed(encoded as string);
|
|
setIsLoading(false);
|
|
return;
|
|
}
|
|
|
|
if (hash) {
|
|
fetch(
|
|
`https://${process.env.NEXT_PUBLIC_PREVIEWS_BUCKET_NAME}.fra1.cdn.digitaloceanspaces.com/preview-strings/${hash}`,
|
|
)
|
|
.then((body) =>
|
|
body.text().then((data) => {
|
|
setCompressed(data);
|
|
setIsLoading(false);
|
|
}),
|
|
)
|
|
.catch((e) => {
|
|
setIsLoading(false);
|
|
});
|
|
}
|
|
}, [isReady, compressed, encoded, hash]);
|
|
|
|
const code = React.useMemo(() => {
|
|
if (!isReady) return "";
|
|
if (!compressed) return "";
|
|
const decompressed = decompressFromEncodedURIComponent(
|
|
compressed as string,
|
|
);
|
|
const fixed = decompressed?.replace(/React\$1/g, "React");
|
|
|
|
const shouldChangeEntrypoint =
|
|
fixed.match(/render\(<App \/>\);?/) &&
|
|
fixed.match(/createRoot\(container\);?/);
|
|
|
|
let content = fixed;
|
|
|
|
if (shouldChangeEntrypoint) {
|
|
content = fixed.replace(/render\(<App \/>\);?/, "");
|
|
content = content.replace(
|
|
/createRoot\(container\);?/,
|
|
"{ render: (children) => render(<RefineCore.ExternalNavigationProvider>{children}</RefineCore.ExternalNavigationProvider>) };",
|
|
);
|
|
}
|
|
|
|
return content;
|
|
}, [compressed, isReady]);
|
|
|
|
const css = React.useMemo(() => {
|
|
if (!isReady) return "";
|
|
if (!cssCompressed) return "";
|
|
try {
|
|
return base64url.decode(cssCompressed as string);
|
|
} catch (err) {
|
|
console.log("CSS Decode Error", { err });
|
|
return "";
|
|
}
|
|
}, [cssCompressed, isReady]);
|
|
|
|
return {
|
|
code,
|
|
css,
|
|
isReady,
|
|
hasQuery: !!encoded || !!hash,
|
|
disableScroll: !!disableScroll,
|
|
useTailwind: !!tailwind,
|
|
isLoading,
|
|
};
|
|
};
|