diff --git a/snap-client/package-lock.json b/snap-client/package-lock.json index 1187181..be3c405 100644 --- a/snap-client/package-lock.json +++ b/snap-client/package-lock.json @@ -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", diff --git a/snap-client/package.json b/snap-client/package.json index dccc594..092333e 100644 --- a/snap-client/package.json +++ b/snap-client/package.json @@ -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" } diff --git a/snap-client/src/app.tsx b/snap-client/src/app.tsx index bf141fa..38220dd 100644 --- a/snap-client/src/app.tsx +++ b/snap-client/src/app.tsx @@ -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(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 (

CodeSnap.nvim

- +
+ + + GitHub + + +
); } diff --git a/snap-client/src/components/control-bar/color-picker.tsx b/snap-client/src/components/control-bar/color-picker.tsx deleted file mode 100644 index 88509ae..0000000 --- a/snap-client/src/components/control-bar/color-picker.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export const ColorPicker = () => { - return
; -}; diff --git a/snap-client/src/components/control-bar/control-bar.tsx b/snap-client/src/components/control-bar/control-bar.tsx index 9e56463..89d0aa8 100644 --- a/snap-client/src/components/control-bar/control-bar.tsx +++ b/snap-client/src/components/control-bar/control-bar.tsx @@ -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 (
- +
- -