Files
clash-verge-rev/src/pages/proxies.tsx
T

121 lines
3.6 KiB
TypeScript
Raw Normal View History

2022-01-10 21:25:41 +08:00
import useSWR, { useSWRConfig } from "swr";
2022-01-25 01:51:44 +08:00
import { useEffect, useMemo, useRef, useState } from "react";
import { Button, ButtonGroup, List, Paper } from "@mui/material";
import { getClashConfig, updateConfigs, updateProxy } from "../services/api";
import { patchClashConfig } from "../services/cmds";
2021-12-25 22:33:29 +08:00
import { getProxies } from "../services/api";
2022-01-16 03:11:07 +08:00
import BasePage from "../components/base-page";
2022-01-13 02:51:30 +08:00
import ProxyItem from "../components/proxy-item";
2022-01-16 03:11:07 +08:00
import ProxyGroup from "../components/proxy-group";
2021-12-08 23:36:34 +08:00
const ProxyPage = () => {
2022-01-10 21:25:41 +08:00
const { mutate } = useSWRConfig();
2021-12-28 01:47:43 +08:00
const { data: proxiesData } = useSWR("getProxies", getProxies);
2022-01-25 01:51:44 +08:00
const { data: clashConfig } = useSWR("getClashConfig", getClashConfig);
const [curProxy, setCurProxy] = useState<string>("DIRECT");
const curMode = clashConfig?.mode.toLowerCase();
2022-01-25 01:51:44 +08:00
// proxy groups
const { groups = [] } = proxiesData ?? {};
// proxies and sorted
const filterProxies = useMemo(() => {
if (!proxiesData?.proxies) return [];
const list = Object.values(proxiesData.proxies);
const retList = list.filter(
(p) => !p.all?.length && p.name !== "DIRECT" && p.name !== "REJECT"
);
const direct = list.filter((p) => p.name === "DIRECT");
const reject = list.filter((p) => p.name === "REJECT");
return direct.concat(retList).concat(reject);
}, [proxiesData]);
const modeList = ["rule", "global", "direct"];
const asGroup = curMode === "rule" || !groups.length;
// make sure that fetch the proxies successfully
2022-01-10 21:25:41 +08:00
useEffect(() => {
2022-01-25 01:51:44 +08:00
if (
(curMode === "rule" && !groups.length) ||
(curMode === "global" && filterProxies.length < 4)
) {
setTimeout(() => mutate("getProxies"), 500);
}
}, [groups, filterProxies, curMode]);
// update the current proxy
useEffect(() => {
if (curMode === "direct") setCurProxy("DIRECT");
if (curMode === "global") {
const globalNow = proxiesData?.proxies?.GLOBAL?.now;
setCurProxy(globalNow || "DIRECT");
}
}, [curMode, proxiesData]);
const changeLockRef = useRef(false);
const onChangeMode = async (mode: string) => {
if (changeLockRef.current) return;
changeLockRef.current = true;
try {
// switch rapidly
await updateConfigs({ mode });
await patchClashConfig({ mode });
mutate("getClashConfig");
} finally {
changeLockRef.current = false;
}
};
const onChangeProxy = async (name: string) => {
if (curMode !== "global") return;
await updateProxy("GLOBAL", name);
setCurProxy(name);
};
2022-01-10 21:25:41 +08:00
return (
2022-01-25 01:51:44 +08:00
<BasePage
title={asGroup ? "Proxy Groups" : "Proxies"}
header={
<ButtonGroup size="small">
{modeList.map((mode) => (
<Button
key={mode}
variant={mode === curMode ? "contained" : "outlined"}
onClick={() => onChangeMode(mode)}
sx={{ textTransform: "capitalize" }}
>
{mode}
</Button>
))}
</ButtonGroup>
}
>
2022-01-16 03:11:07 +08:00
<Paper sx={{ borderRadius: 1, boxShadow: 2, mb: 1 }}>
2022-01-25 01:51:44 +08:00
{asGroup ? (
2021-12-22 02:11:31 +08:00
<List>
{groups.map((group) => (
<ProxyGroup key={group.name} group={group} />
))}
</List>
2022-01-25 01:51:44 +08:00
) : (
// todo: virtual list
2022-01-13 02:51:30 +08:00
<List>
2022-01-25 01:51:44 +08:00
{filterProxies.map((proxy) => (
2022-01-13 02:51:30 +08:00
<ProxyItem
key={proxy.name}
proxy={proxy}
2022-01-25 01:51:44 +08:00
selected={proxy.name === curProxy}
onClick={onChangeProxy}
2022-01-13 02:51:30 +08:00
sx={{ py: 0, px: 2 }}
/>
))}
</List>
)}
</Paper>
2022-01-16 03:11:07 +08:00
</BasePage>
);
2021-12-08 23:36:34 +08:00
};
export default ProxyPage;