From a0f80aa62dc4ed90fed288019fc00ec26b952316 Mon Sep 17 00:00:00 2001 From: wzdnzd Date: Fri, 1 Dec 2023 19:16:42 +0800 Subject: [PATCH] feat: proxy group is always placed at the forefront when sorting proxies (#458) --- src/helpers/proxies.ts | 12 ++++++++++-- src/pages/Proxies.tsx | 4 ++++ src/signals/proxies.ts | 40 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/helpers/proxies.ts b/src/helpers/proxies.ts index bed292b..4077367 100644 --- a/src/helpers/proxies.ts +++ b/src/helpers/proxies.ts @@ -38,12 +38,17 @@ export const sortProxiesByOrderingType = ( proxyNames: string[], proxyLatencyMap: Record, orderingType: PROXIES_ORDERING_TYPE, + proxyGroupNames: Set | undefined, ) => { if (orderingType === PROXIES_ORDERING_TYPE.NATURAL) { return proxyNames } return proxyNames.sort((a, b) => { + if (proxyGroupNames?.has(a) && !proxyGroupNames?.has(b)) return -1 + + if (proxyGroupNames?.has(b) && !proxyGroupNames?.has(a)) return 1 + const prevLatency = proxyLatencyMap[a] const nextLatency = proxyLatencyMap[b] @@ -77,10 +82,13 @@ export const sortProxiesByOrderingType = ( export const filterProxiesByAvailability = ( proxyNames: string[], proxyLatencyMap: Record, + excludes: Set, enabled?: boolean, ) => enabled - ? proxyNames.filter( - (name) => proxyLatencyMap[name] !== latencyQualityMap().NOT_CONNECTED, + ? proxyNames.filter((name) => + excludes?.has(name) + ? true + : proxyLatencyMap[name] !== latencyQualityMap().NOT_CONNECTED, ) : proxyNames diff --git a/src/pages/Proxies.tsx b/src/pages/Proxies.tsx index a246106..fe55d77 100644 --- a/src/pages/Proxies.tsx +++ b/src/pages/Proxies.tsx @@ -41,6 +41,7 @@ export default () => { proxies, selectProxyInGroup, latencyMap, + proxyGroupNames, proxyProviders, updateProviderByProviderName, updateAllProvider, @@ -157,8 +158,10 @@ export default () => { proxyGroup.all ?? [], latencyMap(), proxiesOrderingType(), + proxyGroupNames(), ), latencyMap(), + proxyGroupNames(), hideUnAvailableProxies(), ), ) @@ -244,6 +247,7 @@ export default () => { proxyProvider.proxies.map((i) => i.name) ?? [], latencyMap(), proxiesOrderingType(), + undefined, ), ) diff --git a/src/signals/proxies.ts b/src/signals/proxies.ts index c0c4270..8b7041c 100644 --- a/src/signals/proxies.ts +++ b/src/signals/proxies.ts @@ -52,6 +52,9 @@ const [isAllProviderUpdating, setIsAllProviderUpdating] = createSignal(false) // these signals should be global state const [proxies, setProxies] = createSignal([]) +const [proxyGroupNames, setProxyGroupNames] = createSignal>( + new Set(), +) const [proxyProviders, setProxyProviders] = createSignal< (ProxyProvider & { proxies: ProxyNodeWithProvider[] })[] >([]) @@ -89,19 +92,46 @@ const setProxiesInfo = ( return proxy.history?.at(-1)?.delay } + const dependedLatencyProxies = {} as Record> + proxies.forEach((proxy) => { const { udp, xudp, type, now, name, provider = '' } = proxy newProxyNodeMap[proxy.name] = { udp, xudp, type, now, name, provider } - const latency = - lastDelay(proxy, urlForLatencyTest()) || latencyQualityMap().NOT_CONNECTED - newLatencyMap[proxy.name] = latency + // to solve the problem of the ProxyGroup cannot obtain the latency of the currently used proxy node + // it seems that only clash.core and clash.preminu have issues + if (!now) { + newLatencyMap[proxy.name] = + lastDelay(proxy, urlForLatencyTest()) || + latencyQualityMap().NOT_CONNECTED + } else if (newLatencyMap[now] !== undefined) { + newLatencyMap[proxy.name] = newLatencyMap[now] + } else { + const dependencies = dependedLatencyProxies[now] ?? new Set() + dependencies.add(proxy.name) + dependedLatencyProxies[now] = dependencies + } const proxyIPv6Support = (lastDelay(proxy, urlForIPv6SupportTest(), false) ?? 0) > 0 newProxyIPv6SupportMap[proxy.name] = proxyIPv6Support }) + const independencies = Object.keys(dependedLatencyProxies).filter( + (now) => newLatencyMap[now] !== undefined, + ) + + // maybe we should use Union-Find to implement this + while (independencies.length > 0) { + const now = independencies.shift()! + const delay = newLatencyMap[now]! + + for (const name of dependedLatencyProxies[now]?.values() ?? []) { + newLatencyMap[name] = delay + independencies.push(name) + } + } + batch(() => { setProxyNodeMap(newProxyNodeMap) setLatencyMap(newLatencyMap) @@ -142,6 +172,9 @@ export const useProxies = () => { batch(() => { setProxies(sortedProxies) + setProxyGroupNames( + new Set(['DIRECT', 'REJECT', ...sortedProxies.map((p) => p.name)]), + ) setProxyProviders(sortedProviders) setProxiesInfo(allProxies) }) @@ -293,6 +326,7 @@ export const useProxies = () => { updatingMap, isAllProviderUpdating, proxies, + proxyGroupNames, proxyProviders, proxyLatencyTest, proxyGroupLatencyTest,