diff options
| author | Larvan2 <[email protected]> | 2026-06-04 21:14:57 +0800 |
|---|---|---|
| committer | Larvan2 <[email protected]> | 2026-06-04 21:14:57 +0800 |
| commit | cc6efa25afc9853771565a5f68d1cc24b3a945b2 (patch) | |
| tree | b428b0aec1f183d2c2bddbba45f081bede7f1da5 /src/components | |
| parent | 64e7ca292446242c4769b8e54bd4db048eb46170 (diff) | |
feat(proxies): add latency test URL and timeout configuration
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/Config.tsx | 12 | ||||
| -rw-r--r-- | src/components/proxies/Proxies.tsx | 6 | ||||
| -rw-r--r-- | src/components/proxies/ProxyGroup.tsx | 6 | ||||
| -rw-r--r-- | src/components/proxies/Settings.module.scss | 67 | ||||
| -rw-r--r-- | src/components/proxies/Settings.tsx | 55 |
5 files changed, 130 insertions, 16 deletions
diff --git a/src/components/Config.tsx b/src/components/Config.tsx index 2d3f08b..553faad 100644 --- a/src/components/Config.tsx +++ b/src/components/Config.tsx @@ -38,7 +38,6 @@ type Props = { dispatch: DispatchFn; configs: ClashGeneralConfig; selectedChartStyleIndex: number; - latencyTestUrl: string; apiConfig: ClashAPIConfig; }; @@ -46,7 +45,6 @@ export default function Config({ dispatch, configs, selectedChartStyleIndex, - latencyTestUrl, apiConfig, }: Props) { const { t, i18n } = useTranslation(); @@ -277,16 +275,6 @@ export default function Config({ </div> <div className={s0.section}> <div> - <div className={s0.label}>{t('latency_test_url')}</div> - <SelfControlledInput - name="latencyTestUrl" - type="text" - value={latencyTestUrl} - onBlur={handleInputOnBlur} - className="" - /> - </div> - <div> <div className={s0.label}>{t('lang')}</div> <div> <Select diff --git a/src/components/proxies/Proxies.tsx b/src/components/proxies/Proxies.tsx index e8e3d4b..667c990 100644 --- a/src/components/proxies/Proxies.tsx +++ b/src/components/proxies/Proxies.tsx @@ -28,6 +28,8 @@ type AppConfig = { autoCloseOldConns: boolean; proxiesLayout: string; proxyGroupByProvider: boolean; + latencyTestUrl: string; + latencyTestTimeout: number; }; type Props = { @@ -35,7 +37,6 @@ type Props = { groupNames: string[]; proxies: ProxiesMapping; delay: DelayMapping; - latencyTestUrl: string; collapsibleIsOpen: Record<string, boolean>; proxyProviders: FormattedProxyProvider[]; apiConfig: ClashAPIConfig; @@ -48,13 +49,13 @@ export default function Proxies({ groupNames, proxies, delay, - latencyTestUrl, collapsibleIsOpen, proxyProviders, apiConfig, showModalClosePrevConns, appConfig, }: Props) { + const { latencyTestUrl, latencyTestTimeout } = appConfig; const { isSettingsModalOpen, openSettingsModal, @@ -99,6 +100,7 @@ export default function Proxies({ proxySortBy={appConfig.proxySortBy} isOpen={Boolean(collapsibleIsOpen[`proxyGroup:${name}`])} latencyTestUrl={latencyTestUrl} + latencyTestTimeout={latencyTestTimeout} proxyGroupByProvider={appConfig.proxyGroupByProvider} /> </div> diff --git a/src/components/proxies/ProxyGroup.tsx b/src/components/proxies/ProxyGroup.tsx index b493ff1..6991da6 100644 --- a/src/components/proxies/ProxyGroup.tsx +++ b/src/components/proxies/ProxyGroup.tsx @@ -92,6 +92,7 @@ type Props = { proxies: ProxiesMapping; isOpen: boolean; latencyTestUrl: string; + latencyTestTimeout?: number; apiConfig: ClashAPIConfig; dispatch: DispatchFn; proxyGroupByProvider?: boolean; @@ -105,6 +106,7 @@ export const ProxyGroup = memo(function ProxyGroup({ proxies, isOpen, latencyTestUrl, + latencyTestTimeout = 5000, apiConfig, dispatch, proxyGroupByProvider = false, @@ -172,7 +174,7 @@ export const ProxyGroup = memo(function ProxyGroup({ setIsTestingLatency(true); try { if (version.meta === true) { - await proxiesAPI.requestDelayForProxyGroup(apiConfig, name, latencyTestUrl); + await proxiesAPI.requestDelayForProxyGroup(apiConfig, name, latencyTestUrl, latencyTestTimeout); await dispatch(fetchProxies(apiConfig)); } else { await requestDelayForProxies(apiConfig, all); @@ -180,7 +182,7 @@ export const ProxyGroup = memo(function ProxyGroup({ } } catch (err) {} setIsTestingLatency(false); - }, [all, apiConfig, dispatch, name, version.meta, latencyTestUrl, requestDelayForProxies]); + }, [all, apiConfig, dispatch, name, version.meta, latencyTestUrl, latencyTestTimeout, requestDelayForProxies]); return ( <div className={s0.group}> diff --git a/src/components/proxies/Settings.module.scss b/src/components/proxies/Settings.module.scss index 364d07d..d3eb540 100644 --- a/src/components/proxies/Settings.module.scss +++ b/src/components/proxies/Settings.module.scss @@ -8,6 +8,73 @@ padding: 13px 0; } +.urlInputWrapper { + position: relative; + display: flex; + align-items: center; + width: 240px; +} + +.urlInput { + width: 100%; + padding: 4px 24px 4px 8px; + border: 1px solid var(--color-separator); + border-radius: 4px; + background: var(--color-bg-1, transparent); + color: inherit; + font-size: 12px; + outline: none; + + &:focus { + border-color: var(--color-focus-blue, #409eff); + } +} + +.urlClearBtn { + position: absolute; + right: 6px; + background: none; + border: none; + cursor: pointer; + color: var(--color-text-secondary, #909399); + padding: 0; + line-height: 1; + font-size: 14px; + display: flex; + align-items: center; + + &:hover { + color: var(--color-text, inherit); + } +} + +.timeoutInputWrapper { + display: flex; + align-items: center; + gap: 4px; +} + +.timeoutInput { + width: 70px; + padding: 4px 8px; + border: 1px solid var(--color-separator); + border-radius: 4px; + background: var(--color-bg-1, transparent); + color: inherit; + font-size: 12px; + text-align: right; + outline: none; + + &:focus { + border-color: var(--color-focus-blue, #409eff); + } +} + +.timeoutUnit { + font-size: 12px; + color: var(--color-text-secondary, #909399); +} + hr { height: 1px; background-color: var(--color-separator); diff --git a/src/components/proxies/Settings.tsx b/src/components/proxies/Settings.tsx index d61925a..649d9b9 100644 --- a/src/components/proxies/Settings.tsx +++ b/src/components/proxies/Settings.tsx @@ -17,6 +17,8 @@ type AppConfig = { autoCloseOldConns: boolean; proxiesLayout: string; proxyGroupByProvider: boolean; + latencyTestUrl: string; + latencyTestTimeout: number; }; type Props = { @@ -41,10 +43,63 @@ export default function Settings({ appConfig }: Props) { }, [updateAppConfig], ); + + const handleLatencyUrlChange = useCallback( + (e: React.ChangeEvent<HTMLInputElement>) => { + updateAppConfig('latencyTestUrl', e.target.value); + }, + [updateAppConfig], + ); + + const handleLatencyUrlClear = useCallback(() => { + updateAppConfig('latencyTestUrl', ''); + }, [updateAppConfig]); + + const handleLatencyTimeoutChange = useCallback( + (e: React.ChangeEvent<HTMLInputElement>) => { + const v = parseInt(e.target.value, 10); + if (!isNaN(v) && v > 0) updateAppConfig('latencyTestTimeout', v); + }, + [updateAppConfig], + ); + const { t } = useTranslation(); return ( <> <div className={s.labeledInput}> + <span>{t('latency_test_url')}</span> + <div className={s.urlInputWrapper}> + <input + className={s.urlInput} + type="text" + value={appConfig.latencyTestUrl} + onChange={handleLatencyUrlChange} + spellCheck={false} + /> + {appConfig.latencyTestUrl && ( + <button className={s.urlClearBtn} onClick={handleLatencyUrlClear} tabIndex={-1}> + × + </button> + )} + </div> + </div> + <div className={s.labeledInput}> + <span>{t('latency_test_timeout')}</span> + <div className={s.timeoutInputWrapper}> + <input + className={s.timeoutInput} + type="number" + min={100} + max={30000} + step={100} + value={appConfig.latencyTestTimeout} + onChange={handleLatencyTimeoutChange} + /> + <span className={s.timeoutUnit}>ms</span> + </div> + </div> + <hr /> + <div className={s.labeledInput}> <span>{t('sort_in_grp')}</span> <div> <Select |
