|
@@ -1,90 +1,51 @@
|
|
import useSWR, { useSWRConfig } from "swr";
|
|
import useSWR, { useSWRConfig } from "swr";
|
|
-import { useEffect, useMemo, useRef, useState } from "react";
|
|
|
|
-import { Virtuoso } from "react-virtuoso";
|
|
|
|
|
|
+import { useEffect } from "react";
|
|
|
|
+import { useLockFn } from "ahooks";
|
|
import { Button, ButtonGroup, List, Paper } from "@mui/material";
|
|
import { Button, ButtonGroup, List, Paper } from "@mui/material";
|
|
-import { getClashConfig, updateConfigs, updateProxy } from "../services/api";
|
|
|
|
|
|
+import { getClashConfig, updateConfigs } from "../services/api";
|
|
import { patchClashConfig } from "../services/cmds";
|
|
import { patchClashConfig } from "../services/cmds";
|
|
import { getProxies } from "../services/api";
|
|
import { getProxies } from "../services/api";
|
|
import BasePage from "../components/base/base-page";
|
|
import BasePage from "../components/base/base-page";
|
|
-import ProxyItem from "../components/proxy/proxy-item";
|
|
|
|
import ProxyGroup from "../components/proxy/proxy-group";
|
|
import ProxyGroup from "../components/proxy/proxy-group";
|
|
|
|
+import ProxyGlobal from "../components/proxy/proxy-global";
|
|
|
|
|
|
const ProxyPage = () => {
|
|
const ProxyPage = () => {
|
|
const { mutate } = useSWRConfig();
|
|
const { mutate } = useSWRConfig();
|
|
const { data: proxiesData } = useSWR("getProxies", getProxies);
|
|
const { data: proxiesData } = useSWR("getProxies", getProxies);
|
|
const { data: clashConfig } = useSWR("getClashConfig", getClashConfig);
|
|
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 modeList = ["rule", "global", "direct"];
|
|
- const asGroup = curMode === "rule" && groups.length;
|
|
|
|
|
|
+ const curMode = clashConfig?.mode.toLowerCase() ?? "direct";
|
|
|
|
+ const { groups = [], proxies = [] } = proxiesData ?? {};
|
|
|
|
|
|
// make sure that fetch the proxies successfully
|
|
// make sure that fetch the proxies successfully
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
if (
|
|
if (
|
|
(curMode === "rule" && !groups.length) ||
|
|
(curMode === "rule" && !groups.length) ||
|
|
- (curMode === "global" && filterProxies.length < 4)
|
|
|
|
|
|
+ (curMode === "global" && proxies.length < 2)
|
|
) {
|
|
) {
|
|
setTimeout(() => mutate("getProxies"), 500);
|
|
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]);
|
|
|
|
|
|
+ }, [groups, proxies, curMode]);
|
|
|
|
|
|
- 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);
|
|
|
|
- };
|
|
|
|
|
|
+ const onChangeMode = useLockFn(async (mode: string) => {
|
|
|
|
+ // switch rapidly
|
|
|
|
+ await updateConfigs({ mode });
|
|
|
|
+ await patchClashConfig({ mode });
|
|
|
|
+ mutate("getClashConfig");
|
|
|
|
+ });
|
|
|
|
|
|
// difference style
|
|
// difference style
|
|
- const pageStyle = asGroup ? {} : { height: "100%" };
|
|
|
|
- const paperStyle: any = asGroup
|
|
|
|
|
|
+ const showGroup = curMode === "rule" && !!groups.length;
|
|
|
|
+ const pageStyle = showGroup ? {} : { height: "100%" };
|
|
|
|
+ const paperStyle: any = showGroup
|
|
? { mb: 0.5 }
|
|
? { mb: 0.5 }
|
|
: { py: 1, height: "100%", boxSizing: "border-box" };
|
|
: { py: 1, height: "100%", boxSizing: "border-box" };
|
|
|
|
|
|
return (
|
|
return (
|
|
<BasePage
|
|
<BasePage
|
|
contentStyle={pageStyle}
|
|
contentStyle={pageStyle}
|
|
- title={asGroup ? "Proxy Groups" : "Proxies"}
|
|
|
|
|
|
+ title={showGroup ? "Proxy Groups" : "Proxies"}
|
|
header={
|
|
header={
|
|
<ButtonGroup size="small">
|
|
<ButtonGroup size="small">
|
|
{modeList.map((mode) => (
|
|
{modeList.map((mode) => (
|
|
@@ -101,26 +62,25 @@ const ProxyPage = () => {
|
|
}
|
|
}
|
|
>
|
|
>
|
|
<Paper sx={{ borderRadius: 1, boxShadow: 2, ...paperStyle }}>
|
|
<Paper sx={{ borderRadius: 1, boxShadow: 2, ...paperStyle }}>
|
|
- {asGroup ? (
|
|
|
|
|
|
+ {curMode === "rule" && !!groups.length && (
|
|
<List>
|
|
<List>
|
|
{groups.map((group) => (
|
|
{groups.map((group) => (
|
|
<ProxyGroup key={group.name} group={group} />
|
|
<ProxyGroup key={group.name} group={group} />
|
|
))}
|
|
))}
|
|
</List>
|
|
</List>
|
|
- ) : (
|
|
|
|
- // virtual list
|
|
|
|
- <Virtuoso
|
|
|
|
- style={{ height: "100%" }}
|
|
|
|
- totalCount={filterProxies.length}
|
|
|
|
- itemContent={(index) => (
|
|
|
|
- <ProxyItem
|
|
|
|
- groupName="GLOBAL"
|
|
|
|
- proxy={filterProxies[index]}
|
|
|
|
- selected={filterProxies[index].name === curProxy}
|
|
|
|
- onClick={onChangeProxy}
|
|
|
|
- sx={{ py: 0, px: 2 }}
|
|
|
|
- />
|
|
|
|
- )}
|
|
|
|
|
|
+ )}
|
|
|
|
+ {((curMode === "rule" && !groups.length) || curMode === "global") && (
|
|
|
|
+ <ProxyGlobal
|
|
|
|
+ groupName="GLOBAL"
|
|
|
|
+ curProxy={proxiesData?.global?.now}
|
|
|
|
+ proxies={proxies}
|
|
|
|
+ />
|
|
|
|
+ )}
|
|
|
|
+ {curMode === "direct" && (
|
|
|
|
+ <ProxyGlobal
|
|
|
|
+ groupName="DIRECT"
|
|
|
|
+ curProxy="DIRECT"
|
|
|
|
+ proxies={[proxiesData?.direct!].filter(Boolean)}
|
|
/>
|
|
/>
|
|
)}
|
|
)}
|
|
</Paper>
|
|
</Paper>
|