[Feat] finished preview page

pull/3/head
Mist 2024-02-20 16:13:45 +08:00
parent 8f535dc24e
commit f8773e538e
6 changed files with 69 additions and 11 deletions

View File

@ -16,6 +16,7 @@
"@types/node": "^16.18.81",
"@types/react": "^18.2.55",
"@types/react-dom": "^18.2.19",
"downloadjs": "^1.4.7",
"highlight.js": "^11.9.0",
"html-to-image": "^1.11.11",
"react": "^18.2.0",
@ -26,6 +27,7 @@
"web-vitals": "^2.1.4"
},
"devDependencies": {
"@types/downloadjs": "^1.4.6",
"daisyui": "^3.9.4",
"tailwindcss": "^3.4.1"
}
@ -4084,6 +4086,12 @@
"@types/node": "*"
}
},
"node_modules/@types/downloadjs": {
"version": "1.4.6",
"resolved": "https://registry.npmjs.org/@types/downloadjs/-/downloadjs-1.4.6.tgz",
"integrity": "sha512-mp3w70vsaiLRT9ix92fmI9Ob2yJAPZm6tShJtofo2uHbN11G2i6a0ApIEjBl/kv3e9V7Pv7jMjk1bUwYWvMHvA==",
"dev": true
},
"node_modules/@types/eslint": {
"version": "8.56.2",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.2.tgz",
@ -6990,6 +6998,11 @@
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
"integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA=="
},
"node_modules/downloadjs": {
"version": "1.4.7",
"resolved": "https://registry.npmjs.org/downloadjs/-/downloadjs-1.4.7.tgz",
"integrity": "sha512-LN1gO7+u9xjU5oEScGFKvXhYf7Y/empUIIEAGBs1LzUq/rg5duiDrkuH5A2lQGd5jfMOb9X9usDa2oVXwJ0U/Q=="
},
"node_modules/duplexer": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
@ -20848,6 +20861,12 @@
"@types/node": "*"
}
},
"@types/downloadjs": {
"version": "1.4.6",
"resolved": "https://registry.npmjs.org/@types/downloadjs/-/downloadjs-1.4.6.tgz",
"integrity": "sha512-mp3w70vsaiLRT9ix92fmI9Ob2yJAPZm6tShJtofo2uHbN11G2i6a0ApIEjBl/kv3e9V7Pv7jMjk1bUwYWvMHvA==",
"dev": true
},
"@types/eslint": {
"version": "8.56.2",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.2.tgz",
@ -23009,6 +23028,11 @@
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
"integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA=="
},
"downloadjs": {
"version": "1.4.7",
"resolved": "https://registry.npmjs.org/downloadjs/-/downloadjs-1.4.7.tgz",
"integrity": "sha512-LN1gO7+u9xjU5oEScGFKvXhYf7Y/empUIIEAGBs1LzUq/rg5duiDrkuH5A2lQGd5jfMOb9X9usDa2oVXwJ0U/Q=="
},
"duplexer": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",

View File

@ -11,6 +11,7 @@
"@types/node": "^16.18.81",
"@types/react": "^18.2.55",
"@types/react-dom": "^18.2.19",
"downloadjs": "^1.4.7",
"highlight.js": "^11.9.0",
"html-to-image": "^1.11.11",
"react": "^18.2.0",
@ -47,6 +48,7 @@
]
},
"devDependencies": {
"@types/downloadjs": "^1.4.6",
"daisyui": "^3.9.4",
"tailwindcss": "^3.4.1"
}

View File

@ -9,12 +9,13 @@ import useWebSocket, { ReadyState } from "react-use-websocket";
import { ControlBar, Editor, Frame, Panel } from "./components";
import { useConfig, useEvent } from "./hooks";
import { toPng, toJpeg, toBlob, toPixelData, toSvg } from "html-to-image";
import download from "downloadjs";
const CODE_EMPTY_PLACEHOLDER = `print "Hello, CodeSnap.nvim!"`;
function App() {
const [socketUrl] = useState("ws://127.0.0.1:8080/ws");
const { sendMessage, lastMessage } = useWebSocket(socketUrl);
const { sendMessage, lastMessage, readyState } = useWebSocket(socketUrl);
const event = useEvent(lastMessage);
const config = useConfig(event?.config_setup);
const frameRef = useRef<HTMLDivElement | null>(null);
@ -30,13 +31,27 @@ function App() {
navigator.clipboard.write([clipboardItem]);
}, []);
const handleExportClick = useCallback(async () => {
if (!frameRef.current) {
return;
}
const dataURL = await toPng(frameRef.current);
download(dataURL, "codesnap.png");
}, []);
return (
<div className="w-full h-full flex flex-col items-center bg-deep-gray">
<p className="rainbow-text text-4xl font-extrabold mt-20">
CodeSnap.nvim
</p>
<Panel>
<ControlBar onCopyClick={handleCopyButtonClick}></ControlBar>
<ControlBar
onExportClick={handleExportClick}
onCopyClick={handleCopyButtonClick}
readyState={readyState}
/>
<div className="rounded-xl overflow-hidden">
<Frame ref={frameRef} watermark={config?.watermark}>
<Editor
@ -48,6 +63,17 @@ function App() {
</Frame>
</div>
</Panel>
<a href="https://github.com/mistricky/codesnap.nvim">
<svg
role="img"
viewBox="0 0 24 24"
className="w-10 h-10 mt-10 fill-white opacity-50"
xmlns="http://www.w3.org/2000/svg"
>
<title>GitHub</title>
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
</svg>
</a>
</div>
);
}

View File

@ -1,3 +0,0 @@
export const ColorPicker = () => {
return <div className="btn flex-grow mr-1"></div>;
};

View File

@ -1,18 +1,26 @@
import { ColorPicker } from "./color-picker";
import { ConnectionStatus } from "./connection-status";
import { ReadyState } from "react-use-websocket";
interface ControlBarProps {
onCopyClick(): void;
onExportClick(): void;
readyState: ReadyState;
}
export const ControlBar = ({ onCopyClick }: ControlBarProps) => {
export const ControlBar = ({
onCopyClick,
onExportClick,
readyState,
}: ControlBarProps) => {
return (
<div
className="bg-neutral rounded-xl mb-2 p-1 flex flex-row items-center"
onClick={onCopyClick}
>
<ColorPicker></ColorPicker>
<ConnectionStatus readyState={readyState} />
<div className="flex flex-row items-center">
<button className="btn mr-1">
{/*
* <button className="btn mr-1">
<svg
role="img"
className="h-4 w-4 fill-neutral-500"
@ -23,7 +31,8 @@ export const ControlBar = ({ onCopyClick }: ControlBarProps) => {
<path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" />
</svg>
</button>
<button className="btn mr-1">
*/}
<button className="btn mr-1" onClick={onExportClick}>
Export
<svg
className="fill-neutral-content"

View File

@ -6,7 +6,7 @@ export interface FrameProps {
export const Frame = forwardRef<HTMLDivElement, PropsWithChildren<FrameProps>>(
({ children, watermark }, ref) => (
<div ref={ref} className="bg-stripe min-w-[800px] p-20">
<div ref={ref} className="bg-relay min-w-[800px] p-20">
{children}
{watermark && (
<p className="pacifico-regular text-xl opacity-50 font-bold text-white text-center w-full mt-14">