mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-29 08:45:41 +08:00
feat: support check delay
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useRef, useState } from "react";
|
||||
import { Virtuoso, VirtuosoHandle } from "react-virtuoso";
|
||||
import { useSWRConfig } from "swr";
|
||||
import { Virtuoso } from "react-virtuoso";
|
||||
import {
|
||||
Box,
|
||||
Collapse,
|
||||
@@ -19,6 +20,7 @@ import {
|
||||
import { ApiType } from "../../services/types";
|
||||
import { updateProxy } from "../../services/api";
|
||||
import { getProfiles, patchProfile } from "../../services/cmds";
|
||||
import delayManager from "../../services/delay";
|
||||
import ProxyItem from "./proxy-item";
|
||||
|
||||
interface Props {
|
||||
@@ -26,13 +28,15 @@ interface Props {
|
||||
}
|
||||
|
||||
const ProxyGroup = ({ group }: Props) => {
|
||||
const { mutate } = useSWRConfig();
|
||||
|
||||
const listRef = useRef<any>();
|
||||
const [open, setOpen] = useState(false);
|
||||
const [now, setNow] = useState(group.now);
|
||||
|
||||
const proxies = group.all ?? [];
|
||||
|
||||
const onUpdate = async (name: string) => {
|
||||
const onSelect = async (name: string) => {
|
||||
// can not call update
|
||||
if (group.type !== "Selector") {
|
||||
// Todo
|
||||
@@ -80,6 +84,21 @@ const ProxyGroup = ({ group }: Props) => {
|
||||
}
|
||||
};
|
||||
|
||||
const onCheckAll = async () => {
|
||||
let names = proxies.map((p) => p.name);
|
||||
|
||||
while (names.length) {
|
||||
const list = names.slice(0, 10);
|
||||
names = names.slice(10);
|
||||
|
||||
await Promise.all(
|
||||
list.map((n) => delayManager.checkDelay(n, group.name))
|
||||
);
|
||||
|
||||
mutate("getProxies");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<ListItem button onClick={() => setOpen(!open)} dense>
|
||||
@@ -104,7 +123,7 @@ const ProxyGroup = ({ group }: Props) => {
|
||||
<IconButton size="small" title="location" onClick={onLocation}>
|
||||
<MyLocationRounded />
|
||||
</IconButton>
|
||||
<IconButton size="small" title="check">
|
||||
<IconButton size="small" title="check" onClick={onCheckAll}>
|
||||
<NetworkCheckRounded />
|
||||
</IconButton>
|
||||
</Box>
|
||||
@@ -116,10 +135,11 @@ const ProxyGroup = ({ group }: Props) => {
|
||||
totalCount={proxies.length}
|
||||
itemContent={(index) => (
|
||||
<ProxyItem
|
||||
groupName={group.name}
|
||||
proxy={proxies[index]}
|
||||
selected={proxies[index].name === now}
|
||||
sx={{ py: 0, pl: 4 }}
|
||||
onClick={onUpdate}
|
||||
onClick={onSelect}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
@@ -132,10 +152,11 @@ const ProxyGroup = ({ group }: Props) => {
|
||||
{proxies.map((proxy) => (
|
||||
<ProxyItem
|
||||
key={proxy.name}
|
||||
groupName={group.name}
|
||||
proxy={proxy}
|
||||
selected={proxy.name === now}
|
||||
sx={{ py: 0, pl: 4 }}
|
||||
onClick={onUpdate}
|
||||
onClick={onSelect}
|
||||
/>
|
||||
))}
|
||||
</List>
|
||||
|
||||
@@ -1,24 +1,51 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { CheckCircleOutlineRounded } from "@mui/icons-material";
|
||||
import {
|
||||
alpha,
|
||||
Box,
|
||||
ListItem,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
styled,
|
||||
SxProps,
|
||||
Theme,
|
||||
} from "@mui/material";
|
||||
import { ApiType } from "../../services/types";
|
||||
import delayManager from "../../services/delay";
|
||||
|
||||
interface Props {
|
||||
groupName: string;
|
||||
proxy: ApiType.ProxyItem;
|
||||
selected: boolean;
|
||||
sx?: SxProps<Theme>;
|
||||
onClick?: (name: string) => void;
|
||||
}
|
||||
|
||||
const Widget = styled(Box)(() => ({
|
||||
padding: "4px 6px",
|
||||
fontSize: 14,
|
||||
}));
|
||||
|
||||
const ProxyItem = (props: Props) => {
|
||||
const { proxy, selected, sx, onClick } = props;
|
||||
const { groupName, proxy, selected, sx, onClick } = props;
|
||||
const [delay, setDelay] = useState(-1);
|
||||
|
||||
useEffect(() => {
|
||||
if (proxy) {
|
||||
setDelay(delayManager.getDelay(proxy.name, groupName));
|
||||
}
|
||||
}, [proxy]);
|
||||
|
||||
const onDelay = (e: any) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
delayManager
|
||||
.checkDelay(proxy.name, groupName)
|
||||
.then((result) => setDelay(result))
|
||||
.catch(() => setDelay(1e6));
|
||||
};
|
||||
|
||||
return (
|
||||
<ListItem sx={sx}>
|
||||
@@ -27,9 +54,7 @@ const ProxyItem = (props: Props) => {
|
||||
selected={selected}
|
||||
onClick={() => onClick?.(proxy.name)}
|
||||
sx={[
|
||||
{
|
||||
borderRadius: 1,
|
||||
},
|
||||
{ borderRadius: 1 },
|
||||
({ palette: { mode, primary } }) => {
|
||||
const bgcolor =
|
||||
mode === "light"
|
||||
@@ -37,7 +62,16 @@ const ProxyItem = (props: Props) => {
|
||||
: alpha(primary.main, 0.35);
|
||||
const color = mode === "light" ? primary.main : primary.light;
|
||||
|
||||
const showDelay = delay > 0;
|
||||
const showIcon = !showDelay && selected;
|
||||
|
||||
return {
|
||||
".the-check": { display: "none" },
|
||||
".the-delay": { display: showDelay ? "block" : "none" },
|
||||
".the-icon": { display: showIcon ? "block" : "none" },
|
||||
"&:hover .the-check": { display: !showDelay ? "block" : "none" },
|
||||
"&:hover .the-delay": { display: showDelay ? "block" : "none" },
|
||||
"&:hover .the-icon": { display: "none" },
|
||||
"&.Mui-selected": { bgcolor },
|
||||
"&.Mui-selected .MuiListItemText-secondary": { color },
|
||||
};
|
||||
@@ -45,10 +79,32 @@ const ProxyItem = (props: Props) => {
|
||||
]}
|
||||
>
|
||||
<ListItemText title={proxy.name} secondary={proxy.name} />
|
||||
|
||||
<ListItemIcon
|
||||
sx={{ justifyContent: "flex-end", color: "primary.main" }}
|
||||
>
|
||||
{selected && <CheckCircleOutlineRounded sx={{ fontSize: 16 }} />}
|
||||
<Widget className="the-check" onClick={onDelay}>
|
||||
Check
|
||||
</Widget>
|
||||
|
||||
<Widget
|
||||
className="the-delay"
|
||||
onClick={onDelay}
|
||||
color={
|
||||
delay > 500
|
||||
? "error.main"
|
||||
: delay < 100
|
||||
? "success.main"
|
||||
: "text.secondary"
|
||||
}
|
||||
>
|
||||
{delay > 1e5 ? "Error" : delay > 3000 ? "Timeout" : `${delay}ms`}
|
||||
</Widget>
|
||||
|
||||
<CheckCircleOutlineRounded
|
||||
className="the-icon"
|
||||
sx={{ fontSize: 16 }}
|
||||
/>
|
||||
</ListItemIcon>
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
|
||||
Reference in New Issue
Block a user