fix: unify homepage node selection
This commit is contained in:
143
src/hooks/use-proxy-selection.ts
Normal file
143
src/hooks/use-proxy-selection.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
import { useCallback, useMemo } from "react";
|
||||
import { useLockFn } from "ahooks";
|
||||
import {
|
||||
updateProxy,
|
||||
updateProxyAndSync,
|
||||
forceRefreshProxies,
|
||||
syncTrayProxySelection,
|
||||
getConnections,
|
||||
deleteConnection,
|
||||
} from "@/services/cmds";
|
||||
import { useProfiles } from "@/hooks/use-profiles";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
|
||||
// 缓存连接清理
|
||||
const cleanupConnections = async (previousProxy: string) => {
|
||||
try {
|
||||
const { connections } = await getConnections();
|
||||
const cleanupPromises = connections
|
||||
.filter((conn) => conn.chains.includes(previousProxy))
|
||||
.map((conn) => deleteConnection(conn.id));
|
||||
|
||||
if (cleanupPromises.length > 0) {
|
||||
await Promise.allSettled(cleanupPromises);
|
||||
console.log(`[ProxySelection] 清理了 ${cleanupPromises.length} 个连接`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("[ProxySelection] 连接清理失败:", error);
|
||||
}
|
||||
};
|
||||
|
||||
export 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 updateProxyAndSync(groupName, proxyName);
|
||||
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 updateProxy(groupName, proxyName);
|
||||
await forceRefreshProxies();
|
||||
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,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user