Files
clash-verge-rev-lite/src/hooks/use-connection-data.ts
oomeow 7fc238c27b refactor: invock mihomo api by use tauri-plugin-mihomo (#4926)
* feat: add tauri-plugin-mihomo

* refactor: invock mihomo api by use tauri-plugin-mihomo

* chore: todo

* chore: update

* chore: update

* chore: update

* chore: update

* fix: incorrect delay status and update pretty config

* chore: update

* chore: remove cache

* chore: update

* chore: update

* fix: app freezed when change group proxy

* chore: update

* chore: update

* chore: add rustfmt.toml to tauri-plugin-mihomo

* chore: happy clippy

* refactor: connect mihomo websocket

* chore: update

* chore: update

* fix: parse bigint to number

* chore: update

* Revert "fix: parse bigint to number"

This reverts commit 74c006522e23aa52cf8979a8fb47d2b1ae0bb043.

* chore: use number instead of bigint

* chore: cleanup

* fix: rule data not refresh when switch profile

* chore: update

* chore: cleanup

* chore: update

* fix: traffic graph data display

* feat: add ipc connection pool

* chore: update

* chore: clippy

* fix: incorrect delay status

* fix: typo

* fix: empty proxies tray menu

* chore: clippy

* chore: import tauri-plugin-mihomo by using git repo

* chore: cleanup

* fix: mihomo api

* fix: incorrect delay status

* chore: update tauri-plugin-mihomo dep

chore: update
2025-10-08 12:32:40 +08:00

109 lines
3.5 KiB
TypeScript

import { useLocalStorage } from "foxact/use-local-storage";
import { useEffect, useRef } from "react";
import { mutate } from "swr";
import useSWRSubscription from "swr/subscription";
import { MihomoWebSocket } from "tauri-plugin-mihomo-api";
export const initConnData: IConnections = {
uploadTotal: 0,
downloadTotal: 0,
connections: [],
};
export const useConnectionData = () => {
const [date, setDate] = useLocalStorage("mihomo_connection_date", Date.now());
const subscriptKey = `getClashConnection-${date}`;
const ws = useRef<MihomoWebSocket | null>(null);
const wsFirstConnection = useRef<boolean>(true);
const timeoutRef = useRef<ReturnType<typeof setTimeout>>(null);
const response = useSWRSubscription<IConnections, any, string | null>(
subscriptKey,
(_key, { next }) => {
const reconnect = async () => {
await ws.current?.close();
ws.current = null;
timeoutRef.current = setTimeout(async () => await connect(), 500);
};
const connect = () =>
MihomoWebSocket.connect_connections()
.then((ws_) => {
ws.current = ws_;
if (timeoutRef.current) clearTimeout(timeoutRef.current);
ws_.addListener(async (msg) => {
if (msg.type === "Text") {
if (msg.data.startsWith("Websocket error")) {
next(msg.data);
await reconnect();
} else {
const data = JSON.parse(msg.data) as IConnections;
next(null, (old = initConnData) => {
const oldConn = old.connections;
const maxLen = data.connections?.length;
const connections: IConnectionsItem[] = [];
const rest = (data.connections || []).filter((each) => {
const index = oldConn.findIndex((o) => o.id === each.id);
if (index >= 0 && index < maxLen) {
const old = oldConn[index];
each.curUpload = each.upload - old.upload;
each.curDownload = each.download - old.download;
connections[index] = each;
return false;
}
return true;
});
for (let i = 0; i < maxLen; ++i) {
if (!connections[i] && rest.length > 0) {
connections[i] = rest.shift()!;
connections[i].curUpload = 0;
connections[i].curDownload = 0;
}
}
return { ...data, connections };
});
}
}
});
})
.catch((_) => {
if (!ws.current) {
timeoutRef.current = setTimeout(async () => await connect(), 500);
}
});
if (
wsFirstConnection.current ||
(ws.current && !wsFirstConnection.current)
) {
wsFirstConnection.current = false;
if (ws.current) {
ws.current.close();
ws.current = null;
}
connect();
}
return () => {
ws.current?.close();
};
},
{
fallbackData: initConnData,
keepPreviousData: true,
},
);
useEffect(() => {
mutate(`$sub$${subscriptKey}`);
}, [date, subscriptKey]);
const refreshGetClashConnection = () => {
setDate(Date.now());
};
return { response, refreshGetClashConnection };
};