* 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 74c006522e.
* 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
143 lines
4.0 KiB
TypeScript
143 lines
4.0 KiB
TypeScript
import { useLockFn } from "ahooks";
|
|
import { useCallback, useMemo } from "react";
|
|
import {
|
|
closeConnections,
|
|
getConnections,
|
|
selectNodeForGroup,
|
|
} from "tauri-plugin-mihomo-api";
|
|
|
|
import { useProfiles } from "@/hooks/use-profiles";
|
|
import { useVerge } from "@/hooks/use-verge";
|
|
import { syncTrayProxySelection } from "@/services/cmds";
|
|
|
|
// 缓存连接清理
|
|
const cleanupConnections = async (previousProxy: string) => {
|
|
try {
|
|
const { connections } = await getConnections();
|
|
const cleanupPromises = (connections ?? [])
|
|
.filter((conn) => conn.chains.includes(previousProxy))
|
|
.map((conn) => closeConnections(conn.id));
|
|
|
|
if (cleanupPromises.length > 0) {
|
|
await Promise.allSettled(cleanupPromises);
|
|
console.log(`[ProxySelection] 清理了 ${cleanupPromises.length} 个连接`);
|
|
}
|
|
} catch (error) {
|
|
console.warn("[ProxySelection] 连接清理失败:", error);
|
|
}
|
|
};
|
|
|
|
interface ProxySelectionOptions {
|
|
onSuccess?: () => void;
|
|
onError?: (error: any) => void;
|
|
enableConnectionCleanup?: boolean;
|
|
}
|
|
|
|
// 代理选择 Hook
|
|
export const useProxySelection = (options: ProxySelectionOptions = {}) => {
|
|
const { current, patchCurrent } = useProfiles();
|
|
const { verge } = useVerge();
|
|
|
|
const { onSuccess, onError, enableConnectionCleanup = true } = options;
|
|
|
|
// 缓存
|
|
const config = useMemo(
|
|
() => ({
|
|
autoCloseConnection: verge?.auto_close_connection ?? false,
|
|
enableConnectionCleanup,
|
|
}),
|
|
[verge?.auto_close_connection, enableConnectionCleanup],
|
|
);
|
|
|
|
// 切换节点
|
|
const changeProxy = useLockFn(
|
|
async (
|
|
groupName: string,
|
|
proxyName: string,
|
|
previousProxy?: string,
|
|
skipConfigSave: boolean = false,
|
|
) => {
|
|
console.log(`[ProxySelection] 代理切换: ${groupName} -> ${proxyName}`);
|
|
|
|
try {
|
|
if (current && !skipConfigSave) {
|
|
if (!current.selected) current.selected = [];
|
|
|
|
const index = current.selected.findIndex(
|
|
(item) => item.name === groupName,
|
|
);
|
|
|
|
if (index < 0) {
|
|
current.selected.push({ name: groupName, now: proxyName });
|
|
} else {
|
|
current.selected[index] = { name: groupName, now: proxyName };
|
|
}
|
|
await patchCurrent({ selected: current.selected });
|
|
}
|
|
|
|
await selectNodeForGroup(groupName, proxyName);
|
|
await syncTrayProxySelection();
|
|
console.log(
|
|
`[ProxySelection] 代理和状态同步完成: ${groupName} -> ${proxyName}`,
|
|
);
|
|
|
|
onSuccess?.();
|
|
|
|
if (
|
|
config.enableConnectionCleanup &&
|
|
config.autoCloseConnection &&
|
|
previousProxy
|
|
) {
|
|
setTimeout(() => cleanupConnections(previousProxy), 0);
|
|
}
|
|
} catch (error) {
|
|
console.error(
|
|
`[ProxySelection] 代理切换失败: ${groupName} -> ${proxyName}`,
|
|
error,
|
|
);
|
|
|
|
try {
|
|
await selectNodeForGroup(groupName, proxyName);
|
|
await syncTrayProxySelection();
|
|
onSuccess?.();
|
|
console.log(
|
|
`[ProxySelection] 代理切换回退成功: ${groupName} -> ${proxyName}`,
|
|
);
|
|
} catch (fallbackError) {
|
|
console.error(
|
|
`[ProxySelection] 代理切换回退也失败: ${groupName} -> ${proxyName}`,
|
|
fallbackError,
|
|
);
|
|
onError?.(fallbackError);
|
|
}
|
|
}
|
|
},
|
|
);
|
|
|
|
const handleSelectChange = useCallback(
|
|
(
|
|
groupName: string,
|
|
previousProxy?: string,
|
|
skipConfigSave: boolean = false,
|
|
) =>
|
|
(event: { target: { value: string } }) => {
|
|
const newProxy = event.target.value;
|
|
changeProxy(groupName, newProxy, previousProxy, skipConfigSave);
|
|
},
|
|
[changeProxy],
|
|
);
|
|
|
|
const handleProxyGroupChange = useCallback(
|
|
(group: { name: string; now?: string }, proxy: { name: string }) => {
|
|
changeProxy(group.name, proxy.name, group.now);
|
|
},
|
|
[changeProxy],
|
|
);
|
|
|
|
return {
|
|
changeProxy,
|
|
handleSelectChange,
|
|
handleProxyGroupChange,
|
|
};
|
|
};
|