123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- import useSWR, { useSWRConfig } from "swr";
- import { useSetRecoilState } from "recoil";
- import { useTranslation } from "react-i18next";
- import {
- TextField,
- Switch,
- Select,
- MenuItem,
- Typography,
- IconButton,
- } from "@mui/material";
- import { atomClashPort } from "@/services/states";
- import { ArrowForward } from "@mui/icons-material";
- import { patchClashConfig } from "@/services/cmds";
- import { SettingList, SettingItem } from "./setting";
- import { getClashConfig, getVersion, updateConfigs } from "@/services/api";
- import useModalHandler from "@/hooks/use-modal-handler";
- import Notice from "../base/base-notice";
- import GuardState from "./mods/guard-state";
- import CoreSwitch from "./mods/core-switch";
- import WebUIViewer from "./mods/web-ui-viewer";
- interface Props {
- onError: (err: Error) => void;
- }
- const SettingClash = ({ onError }: Props) => {
- const { t } = useTranslation();
- const { mutate } = useSWRConfig();
- const { data: clashConfig } = useSWR("getClashConfig", getClashConfig);
- const { data: versionData } = useSWR("getVersion", getVersion);
- const {
- ipv6,
- "allow-lan": allowLan,
- "log-level": logLevel,
- "mixed-port": mixedPort,
- } = clashConfig ?? {};
- const setGlobalClashPort = useSetRecoilState(atomClashPort);
- const webUIHandler = useModalHandler();
- const onSwitchFormat = (_e: any, value: boolean) => value;
- const onChangeData = (patch: Partial<ApiType.ConfigData>) => {
- mutate("getClashConfig", { ...clashConfig, ...patch }, false);
- };
- const onUpdateData = async (patch: Partial<ApiType.ConfigData>) => {
- await updateConfigs(patch);
- await patchClashConfig(patch);
- };
- const onUpdatePort = async (port: number) => {
- if (port < 1000) {
- throw new Error("The port should not < 1000");
- }
- if (port > 65536) {
- throw new Error("The port should not > 65536");
- }
- await patchClashConfig({ "mixed-port": port });
- setGlobalClashPort(port);
- Notice.success("Change Clash port successfully!", 1000);
- // update the config
- mutate("getClashConfig");
- };
- // get clash core version
- const clashVer = versionData?.premium
- ? `${versionData.version} Premium`
- : versionData?.version || "-";
- return (
- <SettingList title={t("Clash Setting")}>
- <WebUIViewer handler={webUIHandler} onError={onError} />
- <SettingItem label={t("Allow Lan")}>
- <GuardState
- value={allowLan ?? false}
- valueProps="checked"
- onCatch={onError}
- onFormat={onSwitchFormat}
- onChange={(e) => onChangeData({ "allow-lan": e })}
- onGuard={(e) => onUpdateData({ "allow-lan": e })}
- >
- <Switch edge="end" />
- </GuardState>
- </SettingItem>
- <SettingItem label={t("IPv6")}>
- <GuardState
- value={ipv6 ?? false}
- valueProps="checked"
- onCatch={onError}
- onFormat={onSwitchFormat}
- onChange={(e) => onChangeData({ ipv6: e })}
- onGuard={(e) => onUpdateData({ ipv6: e })}
- >
- <Switch edge="end" />
- </GuardState>
- </SettingItem>
- <SettingItem label={t("Web UI")}>
- <IconButton
- color="inherit"
- size="small"
- sx={{ my: "2px" }}
- onClick={() => webUIHandler.current.open()}
- >
- <ArrowForward />
- </IconButton>
- </SettingItem>
- <SettingItem label={t("Log Level")}>
- <GuardState
- value={logLevel ?? "info"}
- onCatch={onError}
- onFormat={(e: any) => e.target.value}
- onChange={(e) => onChangeData({ "log-level": e })}
- onGuard={(e) => onUpdateData({ "log-level": e })}
- >
- <Select size="small" sx={{ width: 120, "> div": { py: "7.5px" } }}>
- <MenuItem value="debug">Debug</MenuItem>
- <MenuItem value="info">Info</MenuItem>
- <MenuItem value="warning">Warning</MenuItem>
- <MenuItem value="error">Error</MenuItem>
- <MenuItem value="silent">Silent</MenuItem>
- </Select>
- </GuardState>
- </SettingItem>
- <SettingItem label={t("Mixed Port")}>
- <GuardState
- value={mixedPort ?? 0}
- onCatch={onError}
- onFormat={(e: any) => +e.target.value?.replace(/\D+/, "")}
- onChange={(e) => onChangeData({ "mixed-port": e })}
- onGuard={onUpdatePort}
- waitTime={1000}
- >
- <TextField
- autoComplete="off"
- size="small"
- sx={{ width: 120, input: { py: "7.5px" } }}
- />
- </GuardState>
- </SettingItem>
- <SettingItem label={t("Clash Core")} extra={<CoreSwitch />}>
- <Typography sx={{ py: "7px" }}>{clashVer}</Typography>
- </SettingItem>
- </SettingList>
- );
- };
- export default SettingClash;
|