From 383be3a5338284f54abc55a5a525e0a264440ced Mon Sep 17 00:00:00 2001 From: Mist Date: Wed, 21 Feb 2024 18:33:44 +0800 Subject: [PATCH] [Feat] finished codesnap client --- lua/codesnap/client.lua | 8 +- lua/codesnap/init.lua | 17 +- lua/codesnap/static.lua | 5 +- plugin/build.lua | 20 + plugin/codesnap.lua | 18 +- snap-client/src/app.tsx | 48 +- .../control-bar/connection-status.tsx | 53 + .../components/control-bar/control-bar.tsx | 13 +- snap-client/src/hooks/use-config.ts | 2 - snap-client/src/hooks/use-event.ts | 2 + snap-server/Cargo.lock | 1519 ++++++++++++++++- snap-server/Cargo.toml | 8 +- snap-server/src/clipboard.rs | 21 + snap-server/src/event_handler.rs | 43 +- snap-server/src/event_handler/config.rs | 2 - snap-server/src/event_handler/messages.rs | 4 + snap-server/src/main.rs | 58 +- snap-server/src/port.rs | 12 + snap-server/src/session.rs | 17 +- 19 files changed, 1756 insertions(+), 114 deletions(-) create mode 100644 plugin/build.lua create mode 100644 snap-client/src/components/control-bar/connection-status.tsx create mode 100644 snap-server/src/clipboard.rs create mode 100644 snap-server/src/port.rs diff --git a/lua/codesnap/client.lua b/lua/codesnap/client.lua index 22b126c..c0ec413 100644 --- a/lua/codesnap/client.lua +++ b/lua/codesnap/client.lua @@ -1,15 +1,17 @@ local logger = require("codesnap.utils.logger") -local path_utils = require("codesnap.utils.path") +local static = require("codesnap.static") local client = { job_id = 0, } +local cwd = static.cwd .. "/snap-server" + function client:connect() return vim.fn.jobstart({ - path_utils.back(path_utils.back(debug.getinfo(1, "S").source:sub(2):match("(.*[/\\])"))) - .. "/snap-server/target/debug/snap-server", + cwd .. "/target/release/snap-server", }, { + cwd = cwd, stderr_buffered = true, rpc = true, on_stderr = function(_, err) diff --git a/lua/codesnap/init.lua b/lua/codesnap/init.lua index a703bb5..5d2944f 100644 --- a/lua/codesnap/init.lua +++ b/lua/codesnap/init.lua @@ -3,15 +3,14 @@ local static = require("codesnap.static") local client = require("codesnap.client") local visual_utils = require("codesnap.utils.visual") -local main = {} +local main = { + cwd = static.cwd, + preview_switch = static.preview_switch, +} function main.setup(config) static.config = table_utils.merge(static.config, config == nil and {} or config) - print(vim.inspect(static.config)) - print(table_utils.serialize_json(static.config)) - print() - if static.config.auto_load then client:start() end @@ -23,4 +22,12 @@ function main.preview_code() client:send("preview_code", { content = visual_utils.get_selected_text(), language = vim.bo.filetype }) end +function main.open_preview() + client:send("open_preview") +end + +function main.stop_client() + client:stop() +end + return main diff --git a/lua/codesnap/static.lua b/lua/codesnap/static.lua index ec8bba9..9655a14 100644 --- a/lua/codesnap/static.lua +++ b/lua/codesnap/static.lua @@ -1,11 +1,12 @@ +local path_utils = require("codesnap.utils.path") + return { config = { - breadcrumbs = true, - column_number = true, mac_window_bar = true, opacity = true, watermark = "CodeSnap.nvim", auto_load = true, }, + cwd = path_utils.back(path_utils.back(debug.getinfo(1, "S").source:sub(2):match("(.*[/\\])"))), preview_switch = true, } diff --git a/plugin/build.lua b/plugin/build.lua new file mode 100644 index 0000000..abec243 --- /dev/null +++ b/plugin/build.lua @@ -0,0 +1,20 @@ +local codesnap = require("codesnap") +local snap_client_cwd = codesnap.cwd .. "/snap-client" +local snap_server_cwd = codesnap.cwd .. "/snap-server" + +-- Build preview client +os.execute( + "cd " + .. snap_client_cwd + .. " && " + .. "npm i " + .. " && " + .. "npm run build" + .. " && " + .. "mv ./build " + .. snap_server_cwd + .. "/public" +) + +-- Build server +os.execute("cd " .. snap_server_cwd .. " && " .. "cargo build --release") diff --git a/plugin/codesnap.lua b/plugin/codesnap.lua index 99602a7..c0f5c4a 100644 --- a/plugin/codesnap.lua +++ b/plugin/codesnap.lua @@ -1,19 +1,19 @@ local codesnap = require("codesnap") -local static = require("codesnap.static") -local client = require("codesnap.client") +-- local client = require("codesnap.client") --- snap code -vim.api.nvim_create_user_command("CodeSnap", function() end, {}) +-- vim.api.nvim_create_user_command("CodeSnap", function() +-- client:send("copy") +-- end, {}) -vim.api.nvim_create_user_command("CodeSnapPreviewOn", function() end, {}) - -vim.api.nvim_create_user_command("CodeSnapPreviewOff", function() end, {}) +vim.api.nvim_create_user_command("CodeSnapPreviewOn", function() + codesnap.open_preview() +end, {}) vim.api.nvim_create_autocmd({ "CursorMoved" }, { callback = function() local mode = vim.api.nvim_get_mode().mode - if mode ~= "v" or not static.preview_switch then + if mode ~= "v" or not codesnap.preview_switch then return end @@ -24,6 +24,6 @@ vim.api.nvim_create_autocmd({ "CursorMoved" }, { vim.api.nvim_create_autocmd({ "VimLeavePre" }, { pattern = "*", callback = function() - client:stop() + codesnap.stop_client() end, }) diff --git a/snap-client/src/app.tsx b/snap-client/src/app.tsx index 38220dd..650c619 100644 --- a/snap-client/src/app.tsx +++ b/snap-client/src/app.tsx @@ -1,34 +1,37 @@ -import React, { - useCallback, - useEffect, - useMemo, - useRef, - useState, -} from "react"; +import { useCallback, useEffect, useRef, useState } from "react"; 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 { toPng, toBlob } 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 [socketUrl] = useState(`ws://${window.location.host}/ws`); const { sendMessage, lastMessage, readyState } = useWebSocket(socketUrl); const event = useEvent(lastMessage); const config = useConfig(event?.config_setup); const frameRef = useRef(null); + const [isCopyButtonDisabled, setIsCopyButtonDisabled] = useState(false); const handleCopyButtonClick = useCallback(async () => { if (!frameRef.current) { return; } - const blob = await toBlob(frameRef.current); - const clipboardItem = new ClipboardItem({ "image/png": blob! }); + setIsCopyButtonDisabled(true); - navigator.clipboard.write([clipboardItem]); + try { + const blob = await toBlob(frameRef.current); + const clipboardItem = new ClipboardItem({ "image/png": blob! }); + + navigator.clipboard.write([clipboardItem]); + } catch (e) { + console.error(e); + } finally { + setIsCopyButtonDisabled(false); + } }, []); const handleExportClick = useCallback(async () => { @@ -41,6 +44,24 @@ function App() { download(dataURL, "codesnap.png"); }, []); + const notifyCopyCommand = useCallback(async () => { + if (!frameRef.current) { + return; + } + + const dataURL = await toPng(frameRef.current); + + sendMessage(dataURL); + }, [sendMessage]); + + useEffect(() => { + if (readyState !== ReadyState.OPEN || !event?.copy) { + return; + } + + notifyCopyCommand(); + }, [event, readyState, notifyCopyCommand]); + return (

@@ -48,11 +69,12 @@ function App() {

-
+
{ + const parsedState = useMemo( + () => CONNECTION_STATUS_MAP[readyState] ?? UNKNOWN_STATE, + [readyState], + ); + + return ( +
+
+
+
+ {parsedState.text} +
+ ); +}; diff --git a/snap-client/src/components/control-bar/control-bar.tsx b/snap-client/src/components/control-bar/control-bar.tsx index 89d0aa8..46719d8 100644 --- a/snap-client/src/components/control-bar/control-bar.tsx +++ b/snap-client/src/components/control-bar/control-bar.tsx @@ -2,6 +2,7 @@ import { ConnectionStatus } from "./connection-status"; import { ReadyState } from "react-use-websocket"; interface ControlBarProps { + isCopyButtonDisabled: boolean; onCopyClick(): void; onExportClick(): void; readyState: ReadyState; @@ -10,13 +11,11 @@ interface ControlBarProps { export const ControlBar = ({ onCopyClick, onExportClick, + isCopyButtonDisabled, readyState, }: ControlBarProps) => { return ( -
+
{/* @@ -44,7 +43,11 @@ export const ControlBar = ({ -