Parcourir la source

refactor: Use Tauri WebSocket

MystiPanda il y a 1 an
Parent
commit
ba7242a815

+ 2 - 1
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",

+ 22 - 0
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

+ 78 - 15
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,9 +5277,29 @@ dependencies = [
  "byteorder",
  "bytes",
  "data-encoding",
- "http",
+ "http 0.2.11",
+ "httparse",
+ "log 0.4.20",
+ "rand 0.8.5",
+ "sha1",
+ "thiserror",
+ "url",
+ "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",
@@ -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",

+ 1 - 0
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

+ 1 - 0
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);

+ 5 - 3
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);

+ 1 - 1
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();

+ 31 - 26
src/hooks/use-websocket.ts

@@ -1,20 +1,19 @@
 import { useRef } from "react";
-
-export type WsMsgFn = (event: MessageEvent<any>) => 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<WebSocket | null>(null);
   const timerRef = useRef<any>(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 = () => {
-      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?.();
+    const connectHelper = async () => {
+      await disconnect();
+      const ws = await WebSocket.connect(url);
+
+      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 };

+ 2 - 2
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(() => {