feat: display delay check result timely

This commit is contained in:
GyDi
2022-10-26 01:11:02 +08:00
parent 947c38c124
commit 14f627d0d3
9 changed files with 179 additions and 138 deletions

View File

@@ -5,9 +5,8 @@ import { Virtuoso } from "react-virtuoso";
import { providerHealthCheck, updateProxy } from "@/services/api";
import { getProfiles, patchProfile } from "@/services/cmds";
import delayManager from "@/services/delay";
import useSortProxy from "./use-sort-proxy";
import useHeadState from "./use-head-state";
import useFilterProxy from "./use-filter-proxy";
import useFilterSort from "./use-filter-sort";
import ProxyHead from "./proxy-head";
import ProxyItem from "./proxy-item";
@@ -27,14 +26,10 @@ const ProxyGlobal = (props: Props) => {
const [headState, setHeadState] = useHeadState(groupName);
const virtuosoRef = useRef<any>();
const filterProxies = useFilterProxy(
const sortedProxies = useFilterSort(
proxies,
groupName,
headState.filterText
);
const sortedProxies = useSortProxy(
filterProxies,
groupName,
headState.filterText,
headState.sortType
);
@@ -85,13 +80,12 @@ const ProxyGlobal = (props: Props) => {
}
await delayManager.checkListDelay(
{
names: sortedProxies.filter((p) => !p.provider).map((p) => p.name),
groupName,
skipNum: 16,
},
() => mutate("getProxies")
sortedProxies.filter((p) => !p.provider).map((p) => p.name),
groupName,
16
);
mutate("getProxies");
});
useEffect(() => onLocation(false), [groupName]);

View File

@@ -18,9 +18,8 @@ import {
import { providerHealthCheck, updateProxy } from "@/services/api";
import { getProfiles, patchProfile } from "@/services/cmds";
import delayManager from "@/services/delay";
import useSortProxy from "./use-sort-proxy";
import useHeadState from "./use-head-state";
import useFilterProxy from "./use-filter-proxy";
import useFilterSort from "./use-filter-sort";
import ProxyHead from "./proxy-head";
import ProxyItem from "./proxy-item";
@@ -35,14 +34,10 @@ const ProxyGroup = ({ group }: Props) => {
const [headState, setHeadState] = useHeadState(group.name);
const virtuosoRef = useRef<any>();
const filterProxies = useFilterProxy(
const sortedProxies = useFilterSort(
group.all,
group.name,
headState.filterText
);
const sortedProxies = useSortProxy(
filterProxies,
group.name,
headState.filterText,
headState.sortType
);
@@ -105,13 +100,12 @@ const ProxyGroup = ({ group }: Props) => {
}
await delayManager.checkListDelay(
{
names: sortedProxies.filter((p) => !p.provider).map((p) => p.name),
groupName: group.name,
skipNum: 16,
},
() => mutate("getProxies")
sortedProxies.filter((p) => !p.provider).map((p) => p.name),
group.name,
16
);
mutate("getProxies");
});
// auto scroll to current index

View File

@@ -16,7 +16,7 @@ import {
} from "@mui/icons-material";
import delayManager from "@/services/delay";
import type { HeadState } from "./use-head-state";
import type { ProxySortType } from "./use-sort-proxy";
import type { ProxySortType } from "./use-filter-sort";
interface Props {
sx?: SxProps;

View File

@@ -49,6 +49,14 @@ const ProxyItem = (props: Props) => {
// -2 为 loading
const [delay, setDelay] = useState(-1);
useEffect(() => {
delayManager.setListener(proxy.name, groupName, setDelay);
return () => {
delayManager.removeListener(proxy.name, groupName);
};
}, [proxy.name, groupName]);
useEffect(() => {
if (!proxy) return;
@@ -66,10 +74,7 @@ const ProxyItem = (props: Props) => {
const onDelay = useLockFn(async () => {
setDelay(-2);
return delayManager
.checkDelay(proxy.name, groupName)
.then((result) => setDelay(result))
.catch(() => setDelay(1e6));
setDelay(await delayManager.checkDelay(proxy.name, groupName));
});
return (

View File

@@ -1,49 +0,0 @@
import { useMemo } from "react";
import delayManager from "@/services/delay";
const regex1 = /delay([=<>])(\d+|timeout|error)/i;
const regex2 = /type=(.*)/i;
/**
* filter the proxy
* according to the regular conditions
*/
export default function useFilterProxy(
proxies: ApiType.ProxyItem[],
groupName: string,
filterText: string
) {
return useMemo(() => {
if (!proxies) return [];
if (!filterText) return proxies;
const res1 = regex1.exec(filterText);
if (res1) {
const symbol = res1[1];
const symbol2 = res1[2].toLowerCase();
const value =
symbol2 === "error" ? 1e5 : symbol2 === "timeout" ? 3000 : +symbol2;
return proxies.filter((p) => {
const delay = delayManager.getDelay(p.name, groupName);
if (delay < 0) return false;
if (symbol === "=" && symbol2 === "error") return delay >= 1e5;
if (symbol === "=" && symbol2 === "timeout")
return delay < 1e5 && delay >= 3000;
if (symbol === "=") return delay == value;
if (symbol === "<") return delay <= value;
if (symbol === ">") return delay >= value;
return false;
});
}
const res2 = regex2.exec(filterText);
if (res2) {
const type = res2[1].toLowerCase();
return proxies.filter((p) => p.type.toLowerCase().includes(type));
}
return proxies.filter((p) => p.name.includes(filterText.trim()));
}, [proxies, groupName, filterText]);
}

View File

@@ -0,0 +1,114 @@
import { useEffect, useMemo, useState } from "react";
import delayManager from "@/services/delay";
// default | delay | alphabet
export type ProxySortType = 0 | 1 | 2;
export default function useFilterSort(
proxies: ApiType.ProxyItem[],
groupName: string,
filterText: string,
sortType: ProxySortType
) {
const [refresh, setRefresh] = useState({});
useEffect(() => {
let last = 0;
delayManager.setGroupListener(groupName, () => {
// 简单节流
const now = Date.now();
if (now - last > 666) {
last = now;
setRefresh({});
}
});
return () => {
delayManager.removeGroupListener(groupName);
};
}, [groupName]);
return useMemo(() => {
const fp = filterProxies(proxies, groupName, filterText);
const sp = sortProxies(fp, groupName, sortType);
return sp;
}, [proxies, groupName, filterText, sortType, refresh]);
}
/**
* 可以通过延迟数/节点类型 过滤
*/
const regex1 = /delay([=<>])(\d+|timeout|error)/i;
const regex2 = /type=(.*)/i;
/**
* filter the proxy
* according to the regular conditions
*/
function filterProxies(
proxies: ApiType.ProxyItem[],
groupName: string,
filterText: string
) {
if (!filterText) return proxies;
const res1 = regex1.exec(filterText);
if (res1) {
const symbol = res1[1];
const symbol2 = res1[2].toLowerCase();
const value =
symbol2 === "error" ? 1e5 : symbol2 === "timeout" ? 3000 : +symbol2;
return proxies.filter((p) => {
const delay = delayManager.getDelay(p.name, groupName);
if (delay < 0) return false;
if (symbol === "=" && symbol2 === "error") return delay >= 1e5;
if (symbol === "=" && symbol2 === "timeout")
return delay < 1e5 && delay >= 3000;
if (symbol === "=") return delay == value;
if (symbol === "<") return delay <= value;
if (symbol === ">") return delay >= value;
return false;
});
}
const res2 = regex2.exec(filterText);
if (res2) {
const type = res2[1].toLowerCase();
return proxies.filter((p) => p.type.toLowerCase().includes(type));
}
return proxies.filter((p) => p.name.includes(filterText.trim()));
}
/**
* sort the proxy
*/
function sortProxies(
proxies: ApiType.ProxyItem[],
groupName: string,
sortType: ProxySortType
) {
if (!proxies) return [];
if (sortType === 0) return proxies;
const list = proxies.slice();
if (sortType === 1) {
list.sort((a, b) => {
const ad = delayManager.getDelay(a.name, groupName);
const bd = delayManager.getDelay(b.name, groupName);
if (ad === -1 || ad === -2) return 1;
if (bd === -1 || bd === -2) return -1;
return ad - bd;
});
} else {
list.sort((a, b) => a.name.localeCompare(b.name));
}
return list;
}

View File

@@ -1,7 +1,7 @@
import { useCallback, useEffect, useState } from "react";
import { useRecoilValue } from "recoil";
import { atomCurrentProfile } from "@/services/states";
import { ProxySortType } from "./use-sort-proxy";
import { ProxySortType } from "./use-filter-sort";
export interface HeadState {
open?: boolean;

View File

@@ -1,37 +0,0 @@
import { useMemo } from "react";
import delayManager from "@/services/delay";
// default | delay | alpha
export type ProxySortType = 0 | 1 | 2;
/**
* sort the proxy
*/
export default function useSortProxy(
proxies: ApiType.ProxyItem[],
groupName: string,
sortType: ProxySortType
) {
return useMemo(() => {
if (!proxies) return [];
if (sortType === 0) return proxies;
const list = proxies.slice();
if (sortType === 1) {
list.sort((a, b) => {
const ad = delayManager.getDelay(a.name, groupName);
const bd = delayManager.getDelay(b.name, groupName);
if (ad === -1 || ad === -2) return 1;
if (bd === -1 || bd === -2) return -1;
return ad - bd;
});
} else {
list.sort((a, b) => a.name.localeCompare(b.name));
}
return list;
}, [proxies, groupName, sortType]);
}