mirror of
https://github.com/MetaCubeX/metacubexd.git
synced 2024-11-14 18:35:34 +08:00
feat(proxies): add proxy latency test history timeline
This commit is contained in:
parent
8252d04985
commit
1e7dcb13bc
@ -15,6 +15,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@commitlint/config-conventional": "^19.5.0",
|
"@commitlint/config-conventional": "^19.5.0",
|
||||||
|
"@corvu/tooltip": "^0.2.1",
|
||||||
"@eslint/js": "^9.12.0",
|
"@eslint/js": "^9.12.0",
|
||||||
"@felte/solid": "^1.2.13",
|
"@felte/solid": "^1.2.13",
|
||||||
"@felte/validator-zod": "^1.0.17",
|
"@felte/validator-zod": "^1.0.17",
|
||||||
|
@ -10,6 +10,9 @@ importers:
|
|||||||
'@commitlint/config-conventional':
|
'@commitlint/config-conventional':
|
||||||
specifier: ^19.5.0
|
specifier: ^19.5.0
|
||||||
version: 19.5.0
|
version: 19.5.0
|
||||||
|
'@corvu/tooltip':
|
||||||
|
specifier: ^0.2.1
|
||||||
|
version: 0.2.1(solid-js@1.9.2)
|
||||||
'@eslint/js':
|
'@eslint/js':
|
||||||
specifier: ^9.12.0
|
specifier: ^9.12.0
|
||||||
version: 9.12.0
|
version: 9.12.0
|
||||||
@ -1257,6 +1260,22 @@ packages:
|
|||||||
}
|
}
|
||||||
engines: { node: '>=v18' }
|
engines: { node: '>=v18' }
|
||||||
|
|
||||||
|
'@corvu/tooltip@0.2.1':
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-y2CQ2/6DH/gJJZPo1fV3O7l4Jfgu5ZW58bpqPmKS+l8Pa6gIKV6zkrMoyBg8Hsn6z9RmdZFqkGFs/9C5fvwKpg==,
|
||||||
|
}
|
||||||
|
peerDependencies:
|
||||||
|
solid-js: ^1.8
|
||||||
|
|
||||||
|
'@corvu/utils@0.4.2':
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-Ox2kYyxy7NoXdKWdHeDEjZxClwzO4SKM8plAaVwmAJPxHMqA0rLOoAsa+hBDwRLpctf+ZRnAd/ykguuJidnaTA==,
|
||||||
|
}
|
||||||
|
peerDependencies:
|
||||||
|
solid-js: ^1.8
|
||||||
|
|
||||||
'@esbuild/aix-ppc64@0.21.5':
|
'@esbuild/aix-ppc64@0.21.5':
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@ -1554,6 +1573,24 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
zod: ^3.2.0
|
zod: ^3.2.0
|
||||||
|
|
||||||
|
'@floating-ui/core@1.6.8':
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==,
|
||||||
|
}
|
||||||
|
|
||||||
|
'@floating-ui/dom@1.6.11':
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==,
|
||||||
|
}
|
||||||
|
|
||||||
|
'@floating-ui/utils@0.2.8':
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==,
|
||||||
|
}
|
||||||
|
|
||||||
'@fontsource/fira-sans@5.1.0':
|
'@fontsource/fira-sans@5.1.0':
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@ -5331,12 +5368,28 @@ packages:
|
|||||||
apexcharts: ^3.40.0
|
apexcharts: ^3.40.0
|
||||||
solid-js: ^1.6.0
|
solid-js: ^1.6.0
|
||||||
|
|
||||||
|
solid-dismissible@0.1.1:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-9kcKBJIMdS+586cA1g63HYWxKh3h89leeNHbPZ1csYjuni+NvPBtNr11l0iEX2AKKEt6FHk6qNhc/gjoYAW1pA==,
|
||||||
|
}
|
||||||
|
peerDependencies:
|
||||||
|
solid-js: ^1.8
|
||||||
|
|
||||||
solid-js@1.9.2:
|
solid-js@1.9.2:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
integrity: sha512-fe/K03nV+kMFJYhAOE8AIQHcGxB4rMIEoEyrulbtmf217NffbbwBqJnJI4ovt16e+kaIt0czE2WA7mP/pYN9yg==,
|
integrity: sha512-fe/K03nV+kMFJYhAOE8AIQHcGxB4rMIEoEyrulbtmf217NffbbwBqJnJI4ovt16e+kaIt0czE2WA7mP/pYN9yg==,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
solid-presence@0.1.8:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-pWGtXUFWYYUZNbg5YpG5vkQJyOtzn2KXhxYaMx/4I+lylTLYkITOLevaCwMRN+liCVk0pqB6EayLWojNqBFECA==,
|
||||||
|
}
|
||||||
|
peerDependencies:
|
||||||
|
solid-js: ^1.8
|
||||||
|
|
||||||
solid-refresh@0.6.3:
|
solid-refresh@0.6.3:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@ -7228,6 +7281,19 @@ snapshots:
|
|||||||
'@types/conventional-commits-parser': 5.0.0
|
'@types/conventional-commits-parser': 5.0.0
|
||||||
chalk: 5.3.0
|
chalk: 5.3.0
|
||||||
|
|
||||||
|
'@corvu/tooltip@0.2.1(solid-js@1.9.2)':
|
||||||
|
dependencies:
|
||||||
|
'@corvu/utils': 0.4.2(solid-js@1.9.2)
|
||||||
|
'@floating-ui/dom': 1.6.11
|
||||||
|
solid-dismissible: 0.1.1(solid-js@1.9.2)
|
||||||
|
solid-js: 1.9.2
|
||||||
|
solid-presence: 0.1.8(solid-js@1.9.2)
|
||||||
|
|
||||||
|
'@corvu/utils@0.4.2(solid-js@1.9.2)':
|
||||||
|
dependencies:
|
||||||
|
'@floating-ui/dom': 1.6.11
|
||||||
|
solid-js: 1.9.2
|
||||||
|
|
||||||
'@esbuild/aix-ppc64@0.21.5':
|
'@esbuild/aix-ppc64@0.21.5':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@ -7352,6 +7418,17 @@ snapshots:
|
|||||||
'@felte/common': 1.1.8
|
'@felte/common': 1.1.8
|
||||||
zod: 3.23.8
|
zod: 3.23.8
|
||||||
|
|
||||||
|
'@floating-ui/core@1.6.8':
|
||||||
|
dependencies:
|
||||||
|
'@floating-ui/utils': 0.2.8
|
||||||
|
|
||||||
|
'@floating-ui/dom@1.6.11':
|
||||||
|
dependencies:
|
||||||
|
'@floating-ui/core': 1.6.8
|
||||||
|
'@floating-ui/utils': 0.2.8
|
||||||
|
|
||||||
|
'@floating-ui/utils@0.2.8': {}
|
||||||
|
|
||||||
'@fontsource/fira-sans@5.1.0': {}
|
'@fontsource/fira-sans@5.1.0': {}
|
||||||
|
|
||||||
'@humanfs/core@0.19.0': {}
|
'@humanfs/core@0.19.0': {}
|
||||||
@ -9495,12 +9572,22 @@ snapshots:
|
|||||||
defu: 6.1.4
|
defu: 6.1.4
|
||||||
solid-js: 1.9.2
|
solid-js: 1.9.2
|
||||||
|
|
||||||
|
solid-dismissible@0.1.1(solid-js@1.9.2):
|
||||||
|
dependencies:
|
||||||
|
'@corvu/utils': 0.4.2(solid-js@1.9.2)
|
||||||
|
solid-js: 1.9.2
|
||||||
|
|
||||||
solid-js@1.9.2:
|
solid-js@1.9.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
csstype: 3.1.3
|
csstype: 3.1.3
|
||||||
seroval: 1.1.0
|
seroval: 1.1.0
|
||||||
seroval-plugins: 1.1.0(seroval@1.1.0)
|
seroval-plugins: 1.1.0(seroval@1.1.0)
|
||||||
|
|
||||||
|
solid-presence@0.1.8(solid-js@1.9.2):
|
||||||
|
dependencies:
|
||||||
|
'@corvu/utils': 0.4.2(solid-js@1.9.2)
|
||||||
|
solid-js: 1.9.2
|
||||||
|
|
||||||
solid-refresh@0.6.3(solid-js@1.9.2):
|
solid-refresh@0.6.3(solid-js@1.9.2):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/generator': 7.24.7
|
'@babel/generator': 7.24.7
|
||||||
|
@ -1,36 +1,28 @@
|
|||||||
import { LATENCY_QUALITY_MAP_HTTP } from '~/constants'
|
import { JSX, ParentComponent } from 'solid-js'
|
||||||
import { useI18n } from '~/i18n'
|
import { twMerge } from 'tailwind-merge'
|
||||||
import { latencyQualityMap, useProxies } from '~/signals'
|
import { getLatencyClassName } from '~/helpers'
|
||||||
|
import { useProxies } from '~/signals'
|
||||||
|
|
||||||
export const Latency = (props: { name?: string; class?: string }) => {
|
interface Props extends JSX.HTMLAttributes<HTMLSpanElement> {
|
||||||
const [t] = useI18n()
|
proxyName: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Latency: ParentComponent<Props> = (props) => {
|
||||||
|
const [local, others] = splitProps(props, ['class'])
|
||||||
const { getLatencyByName } = useProxies()
|
const { getLatencyByName } = useProxies()
|
||||||
const [textClassName, setTextClassName] = createSignal('')
|
const [textClassName, setTextClassName] = createSignal('')
|
||||||
const latency = createMemo(() => getLatencyByName(props.name || ''))
|
const latency = createMemo(() => getLatencyByName(others.proxyName || ''))
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
if (latency() > latencyQualityMap().HIGH) {
|
setTextClassName(getLatencyClassName(latency()))
|
||||||
setTextClassName('text-error')
|
|
||||||
} else if (latency() > latencyQualityMap().MEDIUM) {
|
|
||||||
setTextClassName('text-warning')
|
|
||||||
} else {
|
|
||||||
setTextClassName('text-success')
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Show
|
|
||||||
when={
|
|
||||||
typeof latency() === 'number' &&
|
|
||||||
latency() !== LATENCY_QUALITY_MAP_HTTP.NOT_CONNECTED
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<span
|
<span
|
||||||
class={`whitespace-nowrap text-xs ${textClassName()} ${props.class}`}
|
class={twMerge('badge whitespace-nowrap', textClassName(), local.class)}
|
||||||
|
{...others}
|
||||||
>
|
>
|
||||||
{latency()}
|
{latency() || '-'}
|
||||||
{t('ms')}
|
|
||||||
</span>
|
</span>
|
||||||
</Show>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
import { IconBrandSpeedtest } from '@tabler/icons-solidjs'
|
import Tooltip from '@corvu/tooltip'
|
||||||
|
import { IconCircleCheckFilled } from '@tabler/icons-solidjs'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
import { twMerge } from 'tailwind-merge'
|
import { twMerge } from 'tailwind-merge'
|
||||||
import { Button, Latency } from '~/components'
|
import { Latency } from '~/components'
|
||||||
import { filterSpecialProxyType, formatProxyType } from '~/helpers'
|
import {
|
||||||
import { useProxies } from '~/signals'
|
filterSpecialProxyType,
|
||||||
|
formatProxyType,
|
||||||
|
getLatencyClassName,
|
||||||
|
} from '~/helpers'
|
||||||
|
import { curTheme, useProxies } from '~/signals'
|
||||||
|
|
||||||
export const ProxyNodeCard = (props: {
|
export const ProxyNodeCard = (props: {
|
||||||
proxyName: string
|
proxyName: string
|
||||||
@ -32,21 +38,27 @@ export const ProxyNodeCard = (props: {
|
|||||||
: null
|
: null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip
|
||||||
|
placement="top"
|
||||||
|
floatingOptions={{
|
||||||
|
autoPlacement: true,
|
||||||
|
shift: true,
|
||||||
|
offset: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Tooltip.Anchor
|
||||||
class={twMerge(
|
class={twMerge(
|
||||||
'card tooltip card-compact tooltip-accent relative bg-neutral text-neutral-content',
|
'card bg-neutral text-neutral-content',
|
||||||
isSelected && 'bg-primary text-primary-content',
|
isSelected && 'bg-primary text-primary-content',
|
||||||
onClick && 'cursor-pointer',
|
onClick && 'cursor-pointer',
|
||||||
)}
|
)}
|
||||||
data-tip={proxyName}
|
title={proxyName}
|
||||||
onClick={onClick}
|
|
||||||
>
|
>
|
||||||
<div class="badge badge-secondary badge-sm absolute bottom-0 left-1/2 -translate-x-1/2 font-bold uppercase">
|
<Tooltip.Trigger>
|
||||||
{formatProxyType(proxyNode()?.type)}
|
<div class="card-body p-2.5" onClick={onClick}>
|
||||||
</div>
|
<h2 class="card-title line-clamp-1 text-start text-sm">
|
||||||
|
{proxyName}
|
||||||
<div class="card-body">
|
</h2>
|
||||||
<h2 class="card-title line-clamp-1 text-start text-sm">{proxyName}</h2>
|
|
||||||
|
|
||||||
<span
|
<span
|
||||||
class={twMerge(
|
class={twMerge(
|
||||||
@ -54,26 +66,25 @@ export const ProxyNodeCard = (props: {
|
|||||||
isSelected ? 'text-info-content' : 'text-neutral-content',
|
isSelected ? 'text-info-content' : 'text-neutral-content',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{[specialType(), supportIPv6() && 'IPv6'].filter(Boolean).join(' / ')}
|
{[
|
||||||
|
specialType(),
|
||||||
|
supportIPv6() && 'IPv6',
|
||||||
|
proxyNode().tfo && 'TFO',
|
||||||
|
]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(' / ')}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div class="card-actions items-center justify-end">
|
<div class="card-actions items-center justify-between">
|
||||||
<Latency
|
<div class="badge badge-secondary badge-sm font-bold uppercase">
|
||||||
name={props.proxyName}
|
{formatProxyType(proxyNode()?.type)}
|
||||||
class={twMerge(isSelected && 'badge')}
|
</div>
|
||||||
/>
|
|
||||||
|
|
||||||
<Button
|
<Latency
|
||||||
class="btn-square btn-sm"
|
proxyName={props.proxyName}
|
||||||
icon={
|
|
||||||
<IconBrandSpeedtest
|
|
||||||
class={twMerge(
|
class={twMerge(
|
||||||
'size-6',
|
proxyLatencyTestingMap()[proxyName] && 'animate-pulse',
|
||||||
proxyLatencyTestingMap()[proxyName] &&
|
|
||||||
'animate-pulse text-success',
|
|
||||||
)}
|
)}
|
||||||
/>
|
|
||||||
}
|
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
|
|
||||||
@ -82,6 +93,59 @@ export const ProxyNodeCard = (props: {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</Tooltip.Trigger>
|
||||||
|
|
||||||
|
<Tooltip.Portal>
|
||||||
|
<Tooltip.Content data-theme={curTheme()} class="z-50 bg-transparent">
|
||||||
|
<Tooltip.Arrow class="text-neutral" />
|
||||||
|
|
||||||
|
<div class="flex flex-col items-center gap-2 rounded-box bg-neutral p-2.5 text-neutral-content">
|
||||||
|
<h2 class="text-lg font-bold">{proxyName}</h2>
|
||||||
|
|
||||||
|
<ul class="timeline timeline-vertical timeline-compact timeline-snap-icon">
|
||||||
|
<For each={proxyNode().latencyTestHistory}>
|
||||||
|
{(latencyTestResult, index) => (
|
||||||
|
<li>
|
||||||
|
<Show when={index() > 0}>
|
||||||
|
<hr />
|
||||||
|
</Show>
|
||||||
|
|
||||||
|
<div class="timeline-start space-y-2">
|
||||||
|
<time class="text-sm italic">
|
||||||
|
{dayjs(latencyTestResult.time).format(
|
||||||
|
'YYYY-MM-DD HH:mm:ss',
|
||||||
|
)}
|
||||||
|
</time>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class={twMerge(
|
||||||
|
'badge block',
|
||||||
|
getLatencyClassName(latencyTestResult.delay),
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{latencyTestResult.delay || '-'}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="timeline-middle">
|
||||||
|
<IconCircleCheckFilled class="size-4" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Show
|
||||||
|
when={
|
||||||
|
index() !== proxyNode().latencyTestHistory.length - 1
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<hr />
|
||||||
|
</Show>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</Tooltip.Content>
|
||||||
|
</Tooltip.Portal>
|
||||||
|
</Tooltip.Anchor>
|
||||||
|
</Tooltip>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ export const ProxyPreviewBar = (props: {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Latency name={props.now} />
|
<Latency proxyName={props.now} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ export const ProxyPreviewDots = (props: {
|
|||||||
</For>
|
</For>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Latency name={props.now} />
|
<Latency proxyName={props.now} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { PROXIES_ORDERING_TYPE } from '~/constants'
|
import { LATENCY_QUALITY_MAP_HTTP, PROXIES_ORDERING_TYPE } from '~/constants'
|
||||||
import { latencyQualityMap, useProxies } from '~/signals'
|
import { latencyQualityMap, useProxies } from '~/signals'
|
||||||
|
|
||||||
export const formatProxyType = (type = '') => {
|
export const formatProxyType = (type = '') => {
|
||||||
@ -19,6 +19,18 @@ export const formatProxyType = (type = '') => {
|
|||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getLatencyClassName = (latency: LATENCY_QUALITY_MAP_HTTP) => {
|
||||||
|
if (latency > latencyQualityMap().HIGH) {
|
||||||
|
return 'text-error'
|
||||||
|
} else if (latency > latencyQualityMap().MEDIUM) {
|
||||||
|
return 'text-warning'
|
||||||
|
} else if (latency === LATENCY_QUALITY_MAP_HTTP.NOT_CONNECTED) {
|
||||||
|
return 'text-neutral-content'
|
||||||
|
} else {
|
||||||
|
return 'text-success'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const filterSpecialProxyType = (type = '') => {
|
export const filterSpecialProxyType = (type = '') => {
|
||||||
const t = type.toLowerCase()
|
const t = type.toLowerCase()
|
||||||
const conditions = [
|
const conditions = [
|
||||||
|
@ -24,7 +24,12 @@ import type { Proxy, ProxyNode, ProxyProvider } from '~/types'
|
|||||||
type ProxyInfo = {
|
type ProxyInfo = {
|
||||||
name: string
|
name: string
|
||||||
udp: boolean
|
udp: boolean
|
||||||
now: string
|
tfo: boolean
|
||||||
|
latencyTestHistory: {
|
||||||
|
time: string
|
||||||
|
delay: number
|
||||||
|
}[]
|
||||||
|
latency: string
|
||||||
xudp: boolean
|
xudp: boolean
|
||||||
type: string
|
type: string
|
||||||
provider: string
|
provider: string
|
||||||
@ -99,9 +104,19 @@ const setProxiesInfo = (
|
|||||||
const newProxyIPv6SupportMap = { ...proxyIPv6SupportMap() }
|
const newProxyIPv6SupportMap = { ...proxyIPv6SupportMap() }
|
||||||
|
|
||||||
proxies.forEach((proxy) => {
|
proxies.forEach((proxy) => {
|
||||||
const { udp, xudp, type, now, name, provider = '' } = proxy
|
const { udp, xudp, type, now, history, name, tfo, provider = '' } = proxy
|
||||||
|
|
||||||
|
newProxyNodeMap[proxy.name] = {
|
||||||
|
udp,
|
||||||
|
xudp,
|
||||||
|
type,
|
||||||
|
latency: now,
|
||||||
|
latencyTestHistory: history,
|
||||||
|
name,
|
||||||
|
tfo,
|
||||||
|
provider,
|
||||||
|
}
|
||||||
|
|
||||||
newProxyNodeMap[proxy.name] = { udp, xudp, type, now, name, provider }
|
|
||||||
newLatencyMap[proxy.name] = getLatencyFromProxy(proxy, urlForLatencyTest())
|
newLatencyMap[proxy.name] = getLatencyFromProxy(proxy, urlForLatencyTest())
|
||||||
|
|
||||||
// we don't set it when false because sing-box didn't have "extra" so it will always be false
|
// we don't set it when false because sing-box didn't have "extra" so it will always be false
|
||||||
@ -326,8 +341,8 @@ export const useProxies = () => {
|
|||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
while (node.now && node.now !== node.name) {
|
while (node.latency && node.latency !== node.name) {
|
||||||
const nextNode = proxyNodeMap()[node.now]
|
const nextNode = proxyNodeMap()[node.latency]
|
||||||
|
|
||||||
if (!nextNode) {
|
if (!nextNode) {
|
||||||
return node.name
|
return node.name
|
||||||
@ -353,7 +368,7 @@ export const useProxies = () => {
|
|||||||
return (
|
return (
|
||||||
['direct', 'reject', 'loadbalance'].includes(
|
['direct', 'reject', 'loadbalance'].includes(
|
||||||
proxyNode.type.toLowerCase(),
|
proxyNode.type.toLowerCase(),
|
||||||
) || !!proxyNode.now
|
) || !!proxyNode.latency
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user