Render latency change immediately
This commit is contained in:
parent
e0bc53d5e0
commit
759d742b8b
5 changed files with 84 additions and 47 deletions
|
@ -2,7 +2,7 @@ import { TooltipPopup, useTooltip } from '@reach/tooltip';
|
|||
import cx from 'clsx';
|
||||
import * as React from 'react';
|
||||
|
||||
import { State } from '$src/store/types';
|
||||
import { ProxyDelayItem, State } from '$src/store/types';
|
||||
|
||||
import { getDelay, getProxies, NonProxyTypes } from '../../store/proxies';
|
||||
import { connect } from '../StateProvider';
|
||||
|
@ -22,7 +22,9 @@ const colorMap = {
|
|||
na: '#909399',
|
||||
};
|
||||
|
||||
function getLabelColor({ number }: { number?: number } = {}) {
|
||||
function getLabelColor(latency: ProxyDelayItem) {
|
||||
if (!latency || latency.kind !== 'Result') return colorMap.na;
|
||||
const number = latency.number;
|
||||
if (number === 0) {
|
||||
return colorMap.na;
|
||||
} else if (number < 200) {
|
||||
|
@ -35,7 +37,7 @@ function getLabelColor({ number }: { number?: number } = {}) {
|
|||
return colorMap.na;
|
||||
}
|
||||
|
||||
function getProxyDotStyle(latency: { number?: number }, proxyType: string) {
|
||||
function getProxyDotStyle(latency: ProxyDelayItem, proxyType: string) {
|
||||
if (NonProxyTypes.indexOf(proxyType) > -1) {
|
||||
return { border: '1px dotted #777' };
|
||||
}
|
||||
|
@ -47,7 +49,7 @@ type ProxyProps = {
|
|||
name: string;
|
||||
now?: boolean;
|
||||
proxy: any;
|
||||
latency?: { number?: number };
|
||||
latency?: ProxyDelayItem;
|
||||
isSelectable?: boolean;
|
||||
onClick?: (proxyName: string) => unknown;
|
||||
};
|
||||
|
@ -56,7 +58,7 @@ function ProxySmallImpl({ now, name, proxy, latency, isSelectable, onClick }: Pr
|
|||
const style = useMemo(() => getProxyDotStyle(latency, proxy.type), [latency, proxy]);
|
||||
const title = useMemo(() => {
|
||||
let ret = name;
|
||||
if (latency && typeof latency.number === 'number') {
|
||||
if (latency && latency.kind === 'Result' && typeof latency.number === 'number') {
|
||||
ret += ' ' + latency.number + ' ms';
|
||||
}
|
||||
return ret;
|
||||
|
@ -152,7 +154,7 @@ function ProxyImpl({ now, name, proxy, latency, isSelectable, onClick }: ProxyPr
|
|||
<span className={s0.proxyType} style={{ opacity: now ? 0.6 : 0.2 }}>
|
||||
{formatProxyType(proxy.type)}
|
||||
</span>
|
||||
<ProxyLatency number={latency?.number} color={color} />
|
||||
<ProxyLatency latency={latency} color={color} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,16 +1,32 @@
|
|||
import * as React from 'react';
|
||||
|
||||
import { ProxyDelayItem } from '$src/store/types';
|
||||
|
||||
import s0 from './ProxyLatency.module.scss';
|
||||
|
||||
type ProxyLatencyProps = {
|
||||
number?: number;
|
||||
latency: ProxyDelayItem | undefined;
|
||||
color: string;
|
||||
};
|
||||
|
||||
export function ProxyLatency({ number, color }: ProxyLatencyProps) {
|
||||
export function ProxyLatency({ latency, color }: ProxyLatencyProps) {
|
||||
let text = ' ';
|
||||
if (latency) {
|
||||
switch (latency.kind) {
|
||||
case 'Error':
|
||||
case 'Testing':
|
||||
text = '- ms';
|
||||
break;
|
||||
case 'Result':
|
||||
text = (latency.number !== 0 ? latency.number : '-') + ' ms';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (
|
||||
<span className={s0.proxyLatency} style={{ color }}>
|
||||
{typeof number === 'number' && number !== 0 ? number + ' ms' : ' '}
|
||||
{text}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,11 +5,7 @@ import { initReactI18next } from 'react-i18next';
|
|||
|
||||
const LngBackend = {
|
||||
type: 'backend' as const,
|
||||
read: (
|
||||
lng: string,
|
||||
_namespace: string,
|
||||
callback: ReadCallback,
|
||||
) => {
|
||||
read: (lng: string, _namespace: string, callback: ReadCallback) => {
|
||||
let p: PromiseLike<{ data: any }>;
|
||||
switch (lng) {
|
||||
case 'zh':
|
||||
|
@ -22,12 +18,15 @@ const LngBackend = {
|
|||
break;
|
||||
}
|
||||
if (p) {
|
||||
p.then(d => callback(null, d.data), err => callback(err, null));
|
||||
p.then(
|
||||
(d) => callback(null, d.data),
|
||||
(err) => callback(err, null)
|
||||
);
|
||||
} else {
|
||||
callback(new Error(`unable to load translation file for language ${lng}`), null)
|
||||
callback(new Error(`unable to load translation file for language ${lng}`), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
i18next
|
||||
.use(initReactI18next)
|
||||
|
|
|
@ -59,7 +59,7 @@ function mapLatency(names: string[], getProxy: (name: string) => { history: Late
|
|||
const history = p.history;
|
||||
const h = history[history.length - 1];
|
||||
if (h && typeof h.delay === 'number') {
|
||||
result[name] = { number: h.delay };
|
||||
result[name] = { kind: 'Result', number: h.delay };
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -268,18 +268,35 @@ export function switchProxy(apiConfig: ClashAPIConfig, groupName: string, itemNa
|
|||
|
||||
function requestDelayForProxyOnce(apiConfig: ClashAPIConfig, name: string) {
|
||||
return async (dispatch: DispatchFn, getState: GetStateFn) => {
|
||||
const latencyTestUrl = getLatencyTestUrl(getState());
|
||||
const res = await proxiesAPI.requestDelayForProxy(apiConfig, name, latencyTestUrl);
|
||||
let error = '';
|
||||
if (res.ok === false) {
|
||||
error = res.statusText;
|
||||
}
|
||||
const { delay } = await res.json();
|
||||
const delayNext = { ...getDelay(getState()), [name]: { error, number: delay } };
|
||||
|
||||
dispatch('requestDelayForProxyOnce', (s) => {
|
||||
s.proxies.delay = delayNext;
|
||||
dispatch('set latency state to testing in progress', (s) => {
|
||||
s.proxies.delay = { ...getDelay(getState()), [name]: { kind: 'Testing' } };
|
||||
});
|
||||
|
||||
const latencyTestUrl = getLatencyTestUrl(getState());
|
||||
|
||||
try {
|
||||
const res = await proxiesAPI.requestDelayForProxy(apiConfig, name, latencyTestUrl);
|
||||
if (res.ok) {
|
||||
const { delay } = await res.json();
|
||||
dispatch('set latency result', (s) => {
|
||||
s.proxies.delay = { ...getDelay(getState()), [name]: { kind: 'Result', number: delay } };
|
||||
});
|
||||
} else {
|
||||
dispatch('set latency testing error', (s) => {
|
||||
s.proxies.delay = {
|
||||
...getDelay(getState()),
|
||||
[name]: { kind: 'Error', message: res.statusText },
|
||||
};
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
dispatch('set latency testing networkish error', (s) => {
|
||||
s.proxies.delay = {
|
||||
...getDelay(getState()),
|
||||
[name]: { kind: 'Error', message: err.message || err.type },
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -292,30 +309,31 @@ export function requestDelayForProxy(apiConfig: ClashAPIConfig, name: string) {
|
|||
export function requestDelayForProxies(apiConfig: ClashAPIConfig, names: string[]) {
|
||||
return async (dispatch: DispatchFn, getState: GetStateFn) => {
|
||||
const proxies = getProxies(getState());
|
||||
const latencyTestUrl = getLatencyTestUrl(getState());
|
||||
|
||||
const proxyDedupMap = new Map<string, boolean>();
|
||||
const providerDedupMap = new Map<string, boolean>();
|
||||
|
||||
const works = names.map((name) => {
|
||||
const works: Array<Promise<void>> = [];
|
||||
|
||||
names.forEach((name) => {
|
||||
const p = proxies[name];
|
||||
if (!p.__provider) {
|
||||
if (proxyDedupMap.get(name)) {
|
||||
return undefined;
|
||||
} else {
|
||||
if (!proxyDedupMap.get(name)) {
|
||||
proxyDedupMap.set(name, true);
|
||||
return proxiesAPI.requestDelayForProxy(apiConfig, name, latencyTestUrl);
|
||||
dispatch(requestDelayForProxyOnce(apiConfig, name));
|
||||
}
|
||||
} else if (p.__provider) {
|
||||
// this one is from a proxy provider
|
||||
if (providerDedupMap.get(p.__provider)) {
|
||||
return undefined;
|
||||
} else {
|
||||
providerDedupMap.set(p.__provider, true);
|
||||
return healthcheckProviderByNameInternal(apiConfig, p.__provider);
|
||||
if (!proxyDedupMap.get(name)) {
|
||||
proxyDedupMap.set(name, true);
|
||||
dispatch('set latency state to testing in progress', (s) => {
|
||||
s.proxies.delay = { ...getDelay(getState()), [name]: { kind: 'Testing' } };
|
||||
});
|
||||
}
|
||||
// this one is from a proxy provider
|
||||
if (!providerDedupMap.get(p.__provider)) {
|
||||
providerDedupMap.set(p.__provider, true);
|
||||
works.push(healthcheckProviderByNameInternal(apiConfig, p.__provider));
|
||||
}
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
await Promise.all(works);
|
||||
|
|
|
@ -40,9 +40,11 @@ export type ProxyItem = {
|
|||
__provider?: string;
|
||||
};
|
||||
|
||||
export type ProxyDelayItem = {
|
||||
number?: number;
|
||||
};
|
||||
export type ProxyDelayItem =
|
||||
| { kind: 'Result'; number: number }
|
||||
| { kind: 'Testing' }
|
||||
| { kind: 'Error'; message: string }
|
||||
| { kind: 'None' };
|
||||
|
||||
export type ProxiesMapping = Record<string, ProxyItem>;
|
||||
export type DelayMapping = Record<string, ProxyDelayItem>;
|
||||
|
|
Loading…
Reference in a new issue