diff --git a/src/components/IPv6Support.tsx b/src/components/IPv6Support.tsx
index 20c6216..932cf6a 100644
--- a/src/components/IPv6Support.tsx
+++ b/src/components/IPv6Support.tsx
@@ -1,14 +1,16 @@
import { useProxies } from '~/signals'
+import { proxyIPv6SupportMap } from '~/signals/ipv6'
-export const IPv6Support = (props: { name?: string }) => {
- const { proxyIPv6SupportMap } = useProxies()
- const support = createMemo(() => proxyIPv6SupportMap()[props.name!] === true)
+export const IPv6Support = (props: { name?: string; class?: string }) => {
+ const { getNowProxyNodeName } = useProxies()
+
+ const support = createMemo(() => {
+ return proxyIPv6SupportMap()[getNowProxyNodeName(props.name || '')]
+ })
return (
-
- IPv6
-
+ IPv6
)
}
diff --git a/src/components/Latency.tsx b/src/components/Latency.tsx
index 55bffab..dd042d9 100644
--- a/src/components/Latency.tsx
+++ b/src/components/Latency.tsx
@@ -4,9 +4,11 @@ import { latencyQualityMap, useProxies } from '~/signals'
export const Latency = (props: { name?: string; class?: string }) => {
const [t] = useI18n()
- const { latencyMap } = useProxies()
+ const { getNowProxyNodeName, latencyMap } = useProxies()
const [textClassName, setTextClassName] = createSignal('')
- const latency = createMemo(() => latencyMap()[props.name!])
+ const latency = createMemo(() => {
+ return latencyMap()[getNowProxyNodeName(props.name || '')]
+ })
createEffect(() => {
setTextClassName('text-success')
diff --git a/src/signals/connections.ts b/src/signals/connections.ts
index a569a3c..cdc7baf 100644
--- a/src/signals/connections.ts
+++ b/src/signals/connections.ts
@@ -9,8 +9,10 @@ export type WsMsg = {
downloadTotal: number
} | null
+// DIRECT is from clash
+// direct and dns-out is from the example of sing-box official site
export const [quickFilterRegex, setQuickFilterRegex] = makePersisted(
- createSignal('Direct|direct|dns-out'),
+ createSignal('DIRECT|direct|dns-out'),
{
name: 'quickFilterRegex',
storage: localStorage,
diff --git a/src/signals/ipv6.ts b/src/signals/ipv6.ts
new file mode 100644
index 0000000..009b77e
--- /dev/null
+++ b/src/signals/ipv6.ts
@@ -0,0 +1,66 @@
+import { proxyGroupLatencyTestAPI, proxyLatencyTestAPI } from '~/apis'
+import {
+ latencyQualityMap,
+ latencyTestTimeoutDuration,
+ urlForIPv6SupportTest,
+} from './config'
+
+export const [proxyIPv6SupportMap, setProxyIPv6SupportMap] = createSignal<
+ Record
+>({})
+
+export const proxyIPv6SupportTest = async (
+ proxyName: string,
+ provider: string,
+) => {
+ const urlForTest = urlForIPv6SupportTest()
+
+ if (!urlForTest || urlForTest.length === 0) {
+ setProxyIPv6SupportMap({})
+
+ return
+ }
+
+ let support = false
+ try {
+ const { delay } = await proxyLatencyTestAPI(
+ proxyName,
+ provider,
+ urlForTest,
+ latencyTestTimeoutDuration(),
+ )
+ support = delay > latencyQualityMap().NOT_CONNECTED
+ } catch {
+ support = false
+ }
+ setProxyIPv6SupportMap((supportMap) => ({
+ ...supportMap,
+ [proxyName]: support,
+ }))
+}
+
+export const proxyGroupIPv6SupportTest = async (proxyGroupName: string) => {
+ const urlForTest = urlForIPv6SupportTest()
+
+ if (!urlForTest || urlForTest.length === 0) {
+ setProxyIPv6SupportMap({})
+
+ return
+ }
+
+ const newLatencyMap = await proxyGroupLatencyTestAPI(
+ proxyGroupName,
+ urlForTest,
+ latencyTestTimeoutDuration(),
+ )
+ const newSupportMap = Object.fromEntries(
+ Object.entries(newLatencyMap).map(([k, v]) => [
+ k,
+ v > latencyQualityMap().NOT_CONNECTED,
+ ]),
+ )
+ setProxyIPv6SupportMap((supportMap) => ({
+ ...supportMap,
+ ...newSupportMap,
+ }))
+}
diff --git a/src/signals/proxies.ts b/src/signals/proxies.ts
index dac9930..5eac5ab 100644
--- a/src/signals/proxies.ts
+++ b/src/signals/proxies.ts
@@ -19,6 +19,12 @@ import {
urlForLatencyTest,
} from '~/signals'
import type { Proxy, ProxyNode, ProxyProvider } from '~/types'
+import {
+ proxyGroupIPv6SupportTest,
+ proxyIPv6SupportMap,
+ proxyIPv6SupportTest,
+ setProxyIPv6SupportMap,
+} from './ipv6'
type ProxyInfo = {
name: string
@@ -58,13 +64,32 @@ const [proxyProviders, setProxyProviders] = createSignal<
>([])
const [latencyMap, setLatencyMap] = createSignal>({})
-const [proxyIPv6SupportMap, setProxyIPv6SupportMap] = createSignal<
- Record
->({})
const [proxyNodeMap, setProxyNodeMap] = createSignal>(
{},
)
+const getLatencyFromProxy = (
+ proxy: Pick,
+ url: string,
+ fallbackDefault = true,
+) => {
+ const extra = proxy.extra?.[url] as Proxy['history'] | undefined
+
+ if (Array.isArray(extra)) {
+ const delay = extra.at(-1)?.delay
+
+ if (delay) {
+ return delay
+ }
+ }
+
+ if (!fallbackDefault) {
+ return latencyQualityMap().NOT_CONNECTED
+ }
+
+ return proxy.history?.at(-1)?.delay ?? latencyQualityMap().NOT_CONNECTED
+}
+
const setProxiesInfo = (
proxies: (ProxyWithProvider | ProxyNodeWithProvider)[],
) => {
@@ -72,68 +97,21 @@ const setProxiesInfo = (
const newLatencyMap = { ...latencyMap() }
const newProxyIPv6SupportMap = { ...proxyIPv6SupportMap() }
- const lastDelay = (
- proxy: Pick,
- url: string,
- fallbackDefault = true,
- ) => {
- const extra = proxy.extra?.[url] as Proxy['history'] | undefined
-
- if (Array.isArray(extra)) {
- const delay = extra.at(-1)?.delay
-
- if (delay) {
- return delay
- }
- }
-
- if (!fallbackDefault) {
- return undefined
- }
-
- 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 }
+ newLatencyMap[proxy.name] = getLatencyFromProxy(proxy, urlForLatencyTest())
- // 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.premium 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
+ // we don't set it when false because sing-box didn't have "extra" so it will always be false
+ if (
+ getLatencyFromProxy(proxy, urlForIPv6SupportTest(), false) >
+ latencyQualityMap().NOT_CONNECTED
+ ) {
+ newProxyIPv6SupportMap[proxy.name] = true
}
-
- 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)
@@ -206,58 +184,9 @@ export const useProxies = () => {
}
}
- const proxyIPv6SupportTest = async (proxyName: string, provider: string) => {
- const urlForTest = urlForIPv6SupportTest()
-
- if (!urlForTest || urlForTest.length === 0) {
- setProxyIPv6SupportMap({})
-
- return
- }
-
- let support = false
- try {
- const { delay } = await proxyLatencyTestAPI(
- proxyName,
- provider,
- urlForTest,
- latencyTestTimeoutDuration(),
- )
- support = delay > 0
- } catch {
- support = false
- }
- setProxyIPv6SupportMap((supportMap) => ({
- ...supportMap,
- [proxyName]: support,
- }))
- }
- const proxyGroupIPv6SupportTest = async (proxyGroupName: string) => {
- const urlForTest = urlForIPv6SupportTest()
-
- if (!urlForTest || urlForTest.length === 0) {
- setProxyIPv6SupportMap({})
-
- return
- }
-
- const newLatencyMap = await proxyGroupLatencyTestAPI(
- proxyGroupName,
- urlForTest,
- latencyTestTimeoutDuration(),
- )
- const newSupportMap = Object.fromEntries(
- Object.entries(newLatencyMap).map(([k, v]) => [k, v > 0]),
- )
- setProxyIPv6SupportMap((supportMap) => ({
- ...supportMap,
- ...newSupportMap,
- }))
- }
-
const proxyLatencyTest = async (proxyName: string, provider: string) => {
- await proxyIPv6SupportTest(proxyName, provider)
setProxyLatencyTestingMap(proxyName, async () => {
+ await proxyIPv6SupportTest(proxyName, provider)
const { delay } = await proxyLatencyTestAPI(
proxyName,
provider,
@@ -273,19 +202,13 @@ export const useProxies = () => {
}
const proxyGroupLatencyTest = async (proxyGroupName: string) => {
- await proxyGroupIPv6SupportTest(proxyGroupName)
setProxyGroupLatencyTestingMap(proxyGroupName, async () => {
- const newLatencyMap = await proxyGroupLatencyTestAPI(
+ await proxyGroupIPv6SupportTest(proxyGroupName)
+ await proxyGroupLatencyTestAPI(
proxyGroupName,
urlForLatencyTest(),
latencyTestTimeoutDuration(),
)
-
- setLatencyMap((latencyMap) => ({
- ...latencyMap,
- ...newLatencyMap,
- }))
-
await fetchProxies()
})
}
@@ -320,8 +243,21 @@ export const useProxies = () => {
await fetchProxies()
})
+ const getNowProxyNodeName = (name: string) => {
+ let node = proxyNodeMap()[name]
+
+ if (!name || !node) {
+ return name
+ }
+
+ while (node.now && node.now !== node.name) {
+ node = proxyNodeMap()[node.now]
+ }
+
+ return node.name
+ }
+
return {
- proxyIPv6SupportMap,
proxyLatencyTestingMap,
proxyGroupLatencyTestingMap,
proxyProviderLatencyTestingMap,
@@ -339,5 +275,6 @@ export const useProxies = () => {
updateProviderByProviderName,
updateAllProvider,
proxyProviderLatencyTest,
+ getNowProxyNodeName,
}
}