From 71103bb7b9ce089c3772ebe2dea376f87bf30573 Mon Sep 17 00:00:00 2001 From: MystiPanda Date: Sun, 14 Jan 2024 17:30:18 +0800 Subject: [PATCH] refactor: Use Tauri WebSocket --- package.json | 3 +- pnpm-lock.yaml | 22 ++++++ src-tauri/Cargo.lock | 93 ++++++++++++++++++++---- src-tauri/Cargo.toml | 1 + src-tauri/src/main.rs | 1 + src/components/layout/layout-traffic.tsx | 8 +- src/components/layout/use-log-setup.ts | 2 +- src/hooks/use-websocket.ts | 55 +++++++------- src/pages/connections.tsx | 4 +- 9 files changed, 142 insertions(+), 47 deletions(-) diff --git a/package.json b/package.json index c66b9199..222ca129 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,8 @@ "recoil": "^0.7.7", "snarkdown": "^2.0.0", "swr": "^1.3.0", - "tar": "^6.2.0" + "tar": "^6.2.0", + "tauri-plugin-websocket-api": "github:tauri-apps/tauri-plugin-websocket#v1" }, "devDependencies": { "@actions/github": "^5.1.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d607e3b8..9f07e9c4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -92,6 +92,9 @@ dependencies: tar: specifier: ^6.2.0 version: 6.2.0 + tauri-plugin-websocket-api: + specifier: github:tauri-apps/tauri-plugin-websocket#v1 + version: github.com/tauri-apps/tauri-plugin-websocket/ef0af116e47eea18af92b27629f00db996fd2e15 devDependencies: "@actions/github": @@ -1711,6 +1714,14 @@ packages: engines: { node: ">= 14.6.0", npm: ">= 6.6.0", yarn: ">= 1.19.1" } dev: false + /@tauri-apps/api@1.5.3: + resolution: + { + integrity: sha512-zxnDjHHKjOsrIzZm6nO5Xapb/BxqUq1tc7cGkFXsFkGTsSWgCPH1D8mm0XS9weJY2OaR73I3k3S+b7eSzJDfqA==, + } + engines: { node: ">= 14.6.0", npm: ">= 6.6.0", yarn: ">= 1.19.1" } + dev: false + /@tauri-apps/cli-darwin-arm64@1.5.6: resolution: { @@ -4090,3 +4101,14 @@ packages: } engines: { node: ">= 6" } dev: false + + github.com/tauri-apps/tauri-plugin-websocket/ef0af116e47eea18af92b27629f00db996fd2e15: + resolution: + { + tarball: https://codeload.github.com/tauri-apps/tauri-plugin-websocket/tar.gz/ef0af116e47eea18af92b27629f00db996fd2e15, + } + name: tauri-plugin-websocket-api + version: 0.0.0 + dependencies: + "@tauri-apps/api": 1.5.3 + dev: false diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 60f81186..caf9a771 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -595,6 +595,7 @@ dependencies = [ "sysproxy", "tauri", "tauri-build", + "tauri-plugin-websocket", "tokio", "warp", "which 5.0.0", @@ -1786,7 +1787,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.11", "indexmap 2.1.0", "slab", "tokio", @@ -1833,7 +1834,7 @@ dependencies = [ "base64 0.21.5", "bytes", "headers-core", - "http", + "http 0.2.11", "httpdate", "mime", "sha1", @@ -1845,7 +1846,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" dependencies = [ - "http", + "http 0.2.11", ] [[package]] @@ -1923,6 +1924,17 @@ dependencies = [ "itoa 1.0.9", ] +[[package]] +name = "http" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" +dependencies = [ + "bytes", + "fnv", + "itoa 1.0.9", +] + [[package]] name = "http-body" version = "0.4.5" @@ -1930,7 +1942,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes", - "http", + "http 0.2.11", "pin-project-lite", ] @@ -1969,7 +1981,7 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http", + "http 0.2.11", "http-body", "httparse", "httpdate", @@ -1989,7 +2001,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", - "http", + "http 0.2.11", "hyper", "rustls", "tokio", @@ -2631,7 +2643,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http", + "http 0.2.11", "httparse", "log 0.4.20", "memchr", @@ -3696,7 +3708,7 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http", + "http 0.2.11", "http-body", "hyper", "hyper-rustls", @@ -4620,7 +4632,7 @@ dependencies = [ "glob", "gtk", "heck 0.4.1", - "http", + "http 0.2.11", "ignore", "infer 0.9.0", "minisign-verify", @@ -4719,6 +4731,23 @@ dependencies = [ "tauri-utils", ] +[[package]] +name = "tauri-plugin-websocket" +version = "0.0.0" +source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#0cdbde386fd7225810a5a57b039d551d08995b29" +dependencies = [ + "futures-util", + "http 1.0.0", + "log 0.4.20", + "rand 0.8.5", + "serde", + "serde_json", + "tauri", + "thiserror", + "tokio", + "tokio-tungstenite 0.21.0", +] + [[package]] name = "tauri-runtime" version = "0.14.1" @@ -4726,7 +4755,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07f8e9e53e00e9f41212c115749e87d5cd2a9eebccafca77a19722eeecd56d43" dependencies = [ "gtk", - "http", + "http 0.2.11", "http-range", "rand 0.8.5", "raw-window-handle", @@ -5057,7 +5086,21 @@ dependencies = [ "futures-util", "log 0.4.20", "tokio", - "tungstenite", + "tungstenite 0.20.1", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" +dependencies = [ + "futures-util", + "log 0.4.20", + "native-tls", + "tokio", + "tokio-native-tls", + "tungstenite 0.21.0", ] [[package]] @@ -5234,7 +5277,7 @@ dependencies = [ "byteorder", "bytes", "data-encoding", - "http", + "http 0.2.11", "httparse", "log 0.4.20", "rand 0.8.5", @@ -5244,6 +5287,26 @@ dependencies = [ "utf-8", ] +[[package]] +name = "tungstenite" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http 1.0.0", + "httparse", + "log 0.4.20", + "native-tls", + "rand 0.8.5", + "sha1", + "thiserror", + "url", + "utf-8", +] + [[package]] name = "typemap-ors" version = "1.0.0" @@ -5472,7 +5535,7 @@ dependencies = [ "futures-channel", "futures-util", "headers", - "http", + "http 0.2.11", "hyper", "log 0.4.20", "mime", @@ -5487,7 +5550,7 @@ dependencies = [ "serde_urlencoded", "tokio", "tokio-stream", - "tokio-tungstenite", + "tokio-tungstenite 0.20.1", "tokio-util", "tower-service", "tracing", @@ -6182,7 +6245,7 @@ dependencies = [ "glib", "gtk", "html5ever 0.25.2", - "http", + "http 0.2.11", "kuchiki", "libc", "log 0.4.20", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 36076ee9..178bc75c 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -40,6 +40,7 @@ tokio = { version = "1", features = ["full"] } serde = { version = "1.0", features = ["derive"] } reqwest = { version = "0.11", features = ["json", "rustls-tls"] } tauri = { version = "1.5", features = [ "notification-all", "icon-png", "clipboard-all", "global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all"] } +tauri-plugin-websocket = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } [target.'cfg(windows)'.dependencies] runas = "=1.0.0" # 高版本会返回错误 Status diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index be57c645..1ca82490 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -24,6 +24,7 @@ fn main() -> std::io::Result<()> { #[allow(unused_mut)] let mut builder = tauri::Builder::default() + .plugin(tauri_plugin_websocket::init()) .system_tray(SystemTray::new()) .setup(|app| { resolve::resolve_setup(app); diff --git a/src/components/layout/layout-traffic.tsx b/src/components/layout/layout-traffic.tsx index 1aa3d5e3..8444a3b3 100644 --- a/src/components/layout/layout-traffic.tsx +++ b/src/components/layout/layout-traffic.tsx @@ -30,7 +30,7 @@ export const LayoutTraffic = () => { useLogSetup(); const { connect, disconnect } = useWebsocket((event) => { - const data = JSON.parse(event.data) as ITrafficItem; + const data = JSON.parse(event) as ITrafficItem; trafficRef.current?.appendData(data); setTraffic(data); }); @@ -52,7 +52,7 @@ export const LayoutTraffic = () => { const memoryWs = useWebsocket( (event) => { - setMemory(JSON.parse(event.data)); + setMemory(JSON.parse(event)); }, { onError: () => setMemory({ inuse: 0 }) } ); @@ -63,7 +63,9 @@ export const LayoutTraffic = () => { memoryWs.connect( `ws://${server}/memory?token=${encodeURIComponent(secret)}` ); - return () => memoryWs.disconnect(); + return () => { + memoryWs.disconnect(); + }; }, [clashInfo, pageVisible, displayMemory]); const [up, upUnit] = parseTraffic(traffic.up); diff --git a/src/components/layout/use-log-setup.ts b/src/components/layout/use-log-setup.ts index 0c130ac9..7ec1357d 100644 --- a/src/components/layout/use-log-setup.ts +++ b/src/components/layout/use-log-setup.ts @@ -16,7 +16,7 @@ export const useLogSetup = () => { const setLogData = useSetRecoilState(atomLogData); const { connect, disconnect } = useWebsocket((event) => { - const data = JSON.parse(event.data) as ILogItem; + const data = JSON.parse(event) as ILogItem; const time = dayjs().format("MM-DD HH:mm:ss"); setLogData((l) => { if (l.length >= MAX_LOG_NUM) l.shift(); diff --git a/src/hooks/use-websocket.ts b/src/hooks/use-websocket.ts index 810c7b13..4a49178b 100644 --- a/src/hooks/use-websocket.ts +++ b/src/hooks/use-websocket.ts @@ -1,20 +1,19 @@ import { useRef } from "react"; - -export type WsMsgFn = (event: MessageEvent) => void; +import WebSocket from "tauri-plugin-websocket-api"; +export type WsMsgFn = (event: string) => void; export interface WsOptions { errorCount?: number; // default is 5 - retryInterval?: number; // default is 2500 - onError?: () => void; + onError?: (e: any) => void; } export const useWebsocket = (onMessage: WsMsgFn, options?: WsOptions) => { const wsRef = useRef(null); const timerRef = useRef(null); - const disconnect = () => { + const disconnect = async () => { if (wsRef.current) { - wsRef.current.close(); + await wsRef.current.disconnect(); wsRef.current = null; } if (timerRef.current) { @@ -22,31 +21,37 @@ export const useWebsocket = (onMessage: WsMsgFn, options?: WsOptions) => { } }; - const connect = (url: string) => { + const connect = async (url: string) => { let errorCount = options?.errorCount ?? 5; - if (!url) return; + const connectHelper = async () => { + await disconnect(); + const ws = await WebSocket.connect(url); - const connectHelper = () => { - disconnect(); - - const ws = new WebSocket(url); - wsRef.current = ws; - - ws.addEventListener("message", onMessage); - ws.addEventListener("error", () => { - errorCount -= 1; - - if (errorCount >= 0) { - timerRef.current = setTimeout(connectHelper, 2500); - } else { - disconnect(); - options?.onError?.(); + ws.addListener((event) => { + switch (event.type) { + case "Text": { + onMessage(event.data); + break; + } + default: { + break; + } } }); + wsRef.current = ws; }; - - connectHelper(); + try { + await connectHelper(); + } catch (e) { + errorCount -= 1; + if (errorCount >= 0) { + timerRef.current = setTimeout(connectHelper, 2500); + } else { + await disconnect(); + options?.onError?.(e); + } + } }; return { connect, disconnect }; diff --git a/src/pages/connections.tsx b/src/pages/connections.tsx index 988fba1c..39510a78 100644 --- a/src/pages/connections.tsx +++ b/src/pages/connections.tsx @@ -61,7 +61,7 @@ const ConnectionsPage = () => { const { connect, disconnect } = useWebsocket( (event) => { // meta v1.15.0 出现data.connections为null的情况 - const data = JSON.parse(event.data) as IConnections; + const data = JSON.parse(event) as IConnections; // 尽量与前一次connections的展示顺序保持一致 setConnData((old) => { const oldConn = old.connections; @@ -94,7 +94,7 @@ const ConnectionsPage = () => { return { ...data, connections }; }); }, - { errorCount: 3, retryInterval: 1000 } + { errorCount: 3 } ); useEffect(() => {