From 4bec1a059805ffbc11c0c14fad04d2c0073452c3 Mon Sep 17 00:00:00 2001 From: lerte smith Date: Fri, 12 Apr 2024 00:45:33 +0800 Subject: [PATCH] update --- app.go | 83 +- apps/frontend/hooks/useAutoDark.tsx | 23 + apps/frontend/package.json | 7 +- apps/frontend/src/App.tsx | 24 + apps/frontend/src/Home.tsx | 122 +- apps/frontend/src/main.tsx | 9 +- apps/frontend/types/zrok.d.ts | 20 + apps/frontend/wailsjs/go/main/App.d.ts | 14 +- apps/frontend/wailsjs/go/main/App.js | 16 +- frontend/wailsjs/go/main/App.d.ts | 4 + frontend/wailsjs/go/main/App.js | 8 + go.mod | 5 +- go.sum | 2 + pnpm-lock.yaml | 1496 ++++++++++++++++++++++-- 14 files changed, 1628 insertions(+), 205 deletions(-) create mode 100644 apps/frontend/hooks/useAutoDark.tsx create mode 100644 apps/frontend/src/App.tsx create mode 100644 apps/frontend/types/zrok.d.ts diff --git a/app.go b/app.go index 12df1c4..c6e34f2 100644 --- a/app.go +++ b/app.go @@ -12,6 +12,7 @@ import ( "github.com/gofiber/fiber/v2/log" "github.com/wailsapp/wails/v2/pkg/runtime" + "mvdan.cc/xurls/v2" ) // App struct @@ -19,6 +20,8 @@ type App struct { ctx context.Context } +var zrokCommand = "./resources/zrok.exe" + // NewApp creates a new App application struct func NewApp() *App { @@ -54,16 +57,6 @@ func (a *App) ChooseFolder() (string, error) { return folder,nil } -func (a *App) Invite(email string) string { - requestBody := []byte(fmt.Sprintf(`{"email": "%s"}`, email)) - resp, err := http.Post("https://api.zrok.io/api/v1/invite", "application/zrok.v1+json", bytes.NewBuffer(requestBody)) - if err != nil { - log.Error("发送请求时出错:", err) - } - defer resp.Body.Close() - return resp.Status -} - func writeToFile(name string, data string) error { f, err := os.OpenFile(name, os.O_CREATE | os.O_APPEND | os.O_WRONLY, 0644) if err != nil { @@ -77,34 +70,60 @@ func writeToFile(name string, data string) error { return nil } +func (a *App) Invite(email string) string { + cmd := exec.Command(zrokCommand, "status") + cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} + output, _ := cmd.Output() + xurlsStrict := xurls.Strict() + find := xurlsStrict.FindAllString(string(output), -1) + apiEndpoint := find[0] + + requestBody := []byte(fmt.Sprintf(`{"email": "%s"}`, email)) + resp, err := http.Post(apiEndpoint+"/api/v1/invite", "application/zrok.v1+json", bytes.NewBuffer(requestBody)) + if err != nil { + log.Error("发送请求时出错:", err) + } + defer resp.Body.Close() + return resp.Status +} + +func (a *App) Version() string { + cmd := exec.Command(zrokCommand, "version") + cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} + output, _ := cmd.Output() + return string(output) +} + +func (a *App) Overview() string { + cmd := exec.Command(zrokCommand, "overview") + cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} + output, _ := cmd.Output() + return string(output) +} // Zrok func (a *App) Zrok(args []string) string { log.Info("Zrok", args) writeToFile("./resources/logs.txt", strings.Join(args, " ")) - zrokCommand := "./resources/zrok.exe" - command := args[0] - if command == "enable" { - cmd := exec.Command(zrokCommand, args...) - cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - // 创建一个缓冲区来保存标准错误输出 - var stderr bytes.Buffer - cmd.Stderr = &stderr - // 执行命令 - err := cmd.Run() - if err != nil { - // 如果命令执行出错,则打印标准错误输出 - fmt.Println("执行命令时出错:", err) - fmt.Println("标准错误输出:", stderr.String()) - return stderr.String() - } - - // 如果命令执行成功,则打印标准错误输出 - fmt.Println("标准错误输出:", stderr.String()) - } + cmd := exec.Command(zrokCommand, args...) cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - output, _ := cmd.Output() - return string(output) + // 创建一个缓冲区来保存标准错误输出 + var stdout bytes.Buffer + var stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr + // 执行命令 + err := cmd.Run() + if err != nil { + // 如果命令执行出错,则打印标准错误输出 + log.Error("执行命令时出错:", err) + log.Error("标准错误输出:", stderr.String()) + return stderr.String() + } + // 如果命令执行成功,则打印标准输出 + + log.Info("标准输出:", stdout.String()) + return stdout.String() } diff --git a/apps/frontend/hooks/useAutoDark.tsx b/apps/frontend/hooks/useAutoDark.tsx new file mode 100644 index 0000000..1bb9d0a --- /dev/null +++ b/apps/frontend/hooks/useAutoDark.tsx @@ -0,0 +1,23 @@ +import { useState, useEffect } from "react"; + +type Theme = "inherit" | "light" | "dark"; + +export const useAutoDark = () => { + const [theme, setTheme] = useState("dark"); + const handleThemeChange = (system: MediaQueryList) => { + if (system.matches) { + setTheme("dark"); + } else { + setTheme("light"); + } + }; + const system = window.matchMedia("(prefers-color-scheme: dark)"); + useEffect(() => { + handleThemeChange(system); + system.addEventListener("change", () => handleThemeChange(system)); + return () => { + system.removeEventListener("change", () => handleThemeChange(system)); + }; + }, []); + return [theme, setTheme] as const; +}; diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 8c55ba9..a17bc7f 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -9,12 +9,11 @@ "preview": "vite preview" }, "dependencies": { - "@chakra-ui/react": "^2.8.2", - "@emotion/react": "^11.11.4", - "@emotion/styled": "^11.11.5", - "framer-motion": "^11.0.25", + "@radix-ui/themes": "^3.0.2", + "lucide-react": "^0.367.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-hot-toast": "^2.4.1", "react-router-dom": "^6.22.3" }, "devDependencies": { diff --git a/apps/frontend/src/App.tsx b/apps/frontend/src/App.tsx new file mode 100644 index 0000000..8ae7323 --- /dev/null +++ b/apps/frontend/src/App.tsx @@ -0,0 +1,24 @@ +import router from "./router"; +import { Toaster } from "react-hot-toast"; +import { RouterProvider } from "react-router-dom"; +import { Theme, ThemePanel } from "@radix-ui/themes"; +import { useAutoDark } from "./../hooks/useAutoDark"; + +const App = () => { + const [theme] = useAutoDark(); + return ( + + + + + + ); +}; + +export default App; diff --git a/apps/frontend/src/Home.tsx b/apps/frontend/src/Home.tsx index 94cd009..8a0111d 100644 --- a/apps/frontend/src/Home.tsx +++ b/apps/frontend/src/Home.tsx @@ -1,70 +1,89 @@ import { useState } from "react"; -import { Invite, Zrok } from "./../wailsjs/go/main/App"; -import { Input, Button, useToast } from "@chakra-ui/react"; +import { Share, Environment } from "./../types/zrok"; +import toast from "react-hot-toast"; +import { Button, TextField } from "@radix-ui/themes"; +import { + Zrok, + Invite, + Version, + Overview, +} from "../../../frontend/wailsjs/go/main/App"; function Home() { - const toast = useToast(); const [email, setEmail] = useState(""); const [command, setCommand] = useState(""); + const [loading, setLoading] = useState(false); const handleInvite = async () => { const result = await Invite(email); const [statusCode, ...statusText] = result.split(" "); if (statusCode == "201") { - toast({ - title: "Invited", - description: "Invite sent to " + email, - status: "success", - duration: 3000, - isClosable: true, - }); + toast.success("Invite sent to " + email); } else { - toast({ - title: "Result", - description: statusText.join(" "), - status: "error", - duration: 3000, - isClosable: true, - }); + toast.error(statusText.join(" ")); } }; const handleEnable = async () => { + setLoading(true); const commands = command.split(" ").filter((item) => item != ""); commands.shift(); const result = await Zrok(commands); if (/^\[ERROR\]/.test(result)) { - toast({ - title: "Error", - description: result, - status: "error", - duration: 3000, - isClosable: true, - }); + toast.error(result); } + if (/successfully/.test(result)) { + toast.success("the zrok environment was successfully enabled..."); + } + setLoading(false); + }; + + const handleSharing = async () => { + setLoading(true); + const commands = command.split(" ").filter((item) => item != ""); + commands.shift(); + Zrok(commands); + setInterval(() => { + getOverview(); + }, 2000); }; const getVersion = async () => { - const version = await Zrok(["version"]); - toast({ - title: "Version", - description: version.slice(-20), - status: "success", - duration: 3000, - isClosable: true, - }); + const version = await Version(); + toast.success("Version: " + version.slice(-20)); + }; + + type Environments = { + environment: Environment[]; + shares?: Share[]; + }; + const getOverview = async () => { + const overview = await Overview(); + const { environments }: { environments: Environments[] } = + JSON.parse(overview); + + console.info(environments); + const index = environments.findIndex((environment) => + environment.shares?.filter( + (share) => share.backendProxyEndpoint == "http://localhost:300" + ) + ); + if (index > -1) { + setLoading(false); + } }; return (
- setEmail(e.target.value)} - /> + >
+

Sharing

+
+ setCommand(e.target.value)} + > + +
+ + +