Files
clash-verge-rev/src/hooks/use-proxy-delay-state.ts
T
Tunglies b1eb011050 refactor(ui): extract useProxyDelayState hook and tighten types
- Extract shared delay state logic from ProxyItem and ProxyItemMini
  into `useProxyDelayState` hook (src/hooks/use-proxy-delay-state.ts);
  JSX display thresholds preserved per-component.
- Deduplicate rAF/setTimeout/Promise scheduling in DelayManager via
  a private `scheduleOnNextFrame` helper.
- Drop no-op `useMemo(() => MODES, [])` in proxies page.
- Replace `any` on `setClashLog` prev params and layout-traffic sx
  objects with proper types (`pre!`, `Pick<BoxProps|...>`).
2026-04-19 17:25:57 +08:00

88 lines
2.2 KiB
TypeScript

import { useLockFn } from 'ahooks'
import { useCallback, useEffect, useReducer } from 'react'
import { useVerge } from '@/hooks/use-verge'
import delayManager, { type DelayUpdate } from '@/services/delay'
const PRESET_PROXY_NAMES = [
'DIRECT',
'REJECT',
'REJECT-DROP',
'PASS',
'COMPATIBLE',
]
const identity = (_: DelayUpdate, next: DelayUpdate): DelayUpdate => next
const INITIAL_DELAY: DelayUpdate = { delay: -1, updatedAt: 0 }
export interface UseProxyDelayState {
delayState: DelayUpdate
delayValue: number
isPreset: boolean
timeout: number
onDelay: () => Promise<void>
}
export function useProxyDelayState(
proxy: IProxyItem,
groupName: string,
): UseProxyDelayState {
const isPreset = PRESET_PROXY_NAMES.includes(proxy.name)
const [delayState, setDelayState] = useReducer(identity, INITIAL_DELAY)
const { verge } = useVerge()
const timeout = verge?.default_latency_timeout || 10000
useEffect(() => {
if (isPreset) return
delayManager.setListener(proxy.name, groupName, setDelayState)
return () => {
delayManager.removeListener(proxy.name, groupName)
}
}, [proxy.name, groupName, isPreset])
const updateDelay = useCallback(() => {
if (!proxy) return
const cachedUpdate = delayManager.getDelayUpdate(proxy.name, groupName)
if (cachedUpdate) {
setDelayState({ ...cachedUpdate })
return
}
const fallbackDelay = delayManager.getDelayFix(proxy, groupName)
if (fallbackDelay === -1) {
setDelayState({ delay: -1, updatedAt: 0 })
return
}
let updatedAt = 0
const history = proxy.history
if (history && history.length > 0) {
const lastRecord = history[history.length - 1]
const parsed = Date.parse(lastRecord.time)
if (!Number.isNaN(parsed)) {
updatedAt = parsed
}
}
setDelayState({ delay: fallbackDelay, updatedAt })
}, [proxy, groupName])
useEffect(() => {
updateDelay()
}, [updateDelay])
const onDelay = useLockFn(async () => {
setDelayState({ delay: -2, updatedAt: Date.now() })
setDelayState(await delayManager.checkDelay(proxy.name, groupName, timeout))
})
return {
delayState,
delayValue: delayState.delay,
isPreset,
timeout,
onDelay,
}
}