feat: enable change proxy mode

This commit is contained in:
GyDi 2022-01-25 01:51:44 +08:00
parent 3a73868c10
commit 6a8ffe1642
No known key found for this signature in database
GPG Key ID: 1C95E0D3467B3084

View File

@ -1,6 +1,8 @@
import useSWR, { useSWRConfig } from "swr"; import useSWR, { useSWRConfig } from "swr";
import { useEffect } from "react"; import { useEffect, useMemo, useRef, useState } from "react";
import { List, Paper } from "@mui/material"; import { Button, ButtonGroup, List, Paper } from "@mui/material";
import { getClashConfig, updateConfigs, updateProxy } from "../services/api";
import { patchClashConfig } from "../services/cmds";
import { getProxies } from "../services/api"; import { getProxies } from "../services/api";
import BasePage from "../components/base-page"; import BasePage from "../components/base-page";
import ProxyItem from "../components/proxy-item"; import ProxyItem from "../components/proxy-item";
@ -9,34 +11,103 @@ import ProxyGroup from "../components/proxy-group";
const ProxyPage = () => { const ProxyPage = () => {
const { mutate } = useSWRConfig(); const { mutate } = useSWRConfig();
const { data: proxiesData } = useSWR("getProxies", getProxies); const { data: proxiesData } = useSWR("getProxies", getProxies);
const { groups = [], proxies = [] } = proxiesData ?? {}; const { data: clashConfig } = useSWR("getClashConfig", getClashConfig);
const [curProxy, setCurProxy] = useState<string>("DIRECT");
const curMode = clashConfig?.mode.toLowerCase();
// 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
useEffect(() => { useEffect(() => {
// fix the empty proxies on the first sight if (
// this bud only show on the build version (curMode === "rule" && !groups.length) ||
// call twice to avoid something unknown or the delay of the clash startup (curMode === "global" && filterProxies.length < 4)
setTimeout(() => mutate("getProxies"), 250); ) {
setTimeout(() => mutate("getProxies"), 1000); 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);
};
return ( return (
<BasePage title={groups.length ? "Proxy Groups" : "Proxies"}> <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>
}
>
<Paper sx={{ borderRadius: 1, boxShadow: 2, mb: 1 }}> <Paper sx={{ borderRadius: 1, boxShadow: 2, mb: 1 }}>
{groups.length > 0 && ( {asGroup ? (
<List> <List>
{groups.map((group) => ( {groups.map((group) => (
<ProxyGroup key={group.name} group={group} /> <ProxyGroup key={group.name} group={group} />
))} ))}
</List> </List>
)} ) : (
// todo: virtual list
{!groups.length && (
<List> <List>
{Object.values(proxies).map((proxy) => ( {filterProxies.map((proxy) => (
<ProxyItem <ProxyItem
key={proxy.name} key={proxy.name}
proxy={proxy} proxy={proxy}
selected={false} selected={proxy.name === curProxy}
onClick={onChangeProxy}
sx={{ py: 0, px: 2 }} sx={{ py: 0, px: 2 }}
/> />
))} ))}