123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- import { forwardRef, useImperativeHandle, useState } from "react";
- import { useLockFn } from "ahooks";
- import { useTranslation } from "react-i18next";
- import {
- List,
- ListItem,
- ListItemText,
- MenuItem,
- Select,
- Switch,
- TextField,
- } from "@mui/material";
- import { useClash } from "@/hooks/use-clash";
- import { BaseDialog, DialogRef, Notice } from "@/components/base";
- export const TunViewer = forwardRef<DialogRef>((props, ref) => {
- const { t } = useTranslation();
- const { clash, mutateClash, patchClash } = useClash();
- const [open, setOpen] = useState(false);
- const [values, setValues] = useState({
- stack: "gVisor",
- device: "Mihomo",
- autoRoute: true,
- autoDetectInterface: true,
- dnsHijack: ["any:53", "tcp://any:53"],
- strictRoute: true,
- mtu: 9000,
- });
- useImperativeHandle(ref, () => ({
- open: () => {
- setOpen(true);
- setValues({
- stack: clash?.tun.stack ?? "gVisor",
- device: clash?.tun.device ?? "Mihomo",
- autoRoute: clash?.tun["auto-route"] ?? true,
- autoDetectInterface: clash?.tun["auto-detect-interface"] ?? true,
- dnsHijack: clash?.tun["dns-hijack"] ?? ["any:53", "tcp://any:53"],
- strictRoute: clash?.tun["strict-route"] ?? true,
- mtu: clash?.tun.mtu ?? 9000,
- });
- },
- close: () => setOpen(false),
- }));
- const onSave = useLockFn(async () => {
- try {
- let tun = {
- stack: values.stack,
- device: values.device,
- "auto-route": values.autoRoute,
- "auto-detect-interface": values.autoDetectInterface,
- "dns-hijack": values.dnsHijack,
- "strict-route": values.strictRoute,
- mtu: values.mtu,
- };
- await patchClash({ tun });
- await mutateClash(
- (old) => ({
- ...(old! || {}),
- tun,
- }),
- false
- );
- setOpen(false);
- } catch (err: any) {
- Notice.error(err.message || err.toString());
- }
- });
- return (
- <BaseDialog
- open={open}
- title={t("Tun Mode")}
- contentSx={{ width: 450 }}
- okBtn={t("Save")}
- cancelBtn={t("Cancel")}
- onClose={() => setOpen(false)}
- onCancel={() => setOpen(false)}
- onOk={onSave}
- >
- <List>
- <ListItem sx={{ padding: "5px 2px" }}>
- <ListItemText primary={t("Stack")} />
- <Select
- size="small"
- sx={{ width: 100, "> div": { py: "7.5px" } }}
- value={values.stack}
- onChange={(e) => {
- setValues((v) => ({
- ...v,
- stack: e.target.value as string,
- }));
- }}
- >
- {["System", "gVisor", "Mixed"].map((i) => (
- <MenuItem value={i} key={i}>
- {i}
- </MenuItem>
- ))}
- </Select>
- </ListItem>
- <ListItem sx={{ padding: "5px 2px" }}>
- <ListItemText primary={t("Device")} />
- <TextField
- size="small"
- autoComplete="off"
- autoCorrect="off"
- autoCapitalize="off"
- spellCheck="false"
- sx={{ width: 250 }}
- value={values.device}
- placeholder="Mihomo"
- onChange={(e) =>
- setValues((v) => ({ ...v, device: e.target.value }))
- }
- />
- </ListItem>
- <ListItem sx={{ padding: "5px 2px" }}>
- <ListItemText primary={t("Auto Route")} />
- <Switch
- edge="end"
- checked={values.autoRoute}
- onChange={(_, c) => setValues((v) => ({ ...v, autoRoute: c }))}
- />
- </ListItem>
- <ListItem sx={{ padding: "5px 2px" }}>
- <ListItemText primary={t("Strict Route")} />
- <Switch
- edge="end"
- checked={values.strictRoute}
- onChange={(_, c) => setValues((v) => ({ ...v, strictRoute: c }))}
- />
- </ListItem>
- <ListItem sx={{ padding: "5px 2px" }}>
- <ListItemText primary={t("Auto Detect Interface")} />
- <Switch
- edge="end"
- checked={values.autoDetectInterface}
- onChange={(_, c) =>
- setValues((v) => ({ ...v, autoDetectInterface: c }))
- }
- />
- </ListItem>
- <ListItem sx={{ padding: "5px 2px" }}>
- <ListItemText primary={t("DNS Hijack")} />
- <TextField
- size="small"
- autoComplete="off"
- autoCorrect="off"
- autoCapitalize="off"
- spellCheck="false"
- sx={{ width: 250 }}
- value={values.dnsHijack.join(",")}
- placeholder="Please use , to separate multiple DNS servers"
- onChange={(e) =>
- setValues((v) => ({ ...v, dnsHijack: e.target.value.split(",") }))
- }
- />
- </ListItem>
- <ListItem sx={{ padding: "5px 2px" }}>
- <ListItemText primary={t("MTU")} />
- <TextField
- size="small"
- type="number"
- autoComplete="off"
- autoCorrect="off"
- autoCapitalize="off"
- spellCheck="false"
- sx={{ width: 250 }}
- value={values.mtu}
- placeholder="9000"
- onChange={(e) =>
- setValues((v) => ({
- ...v,
- mtu: parseInt(e.target.value),
- }))
- }
- />
- </ListItem>
- </List>
- </BaseDialog>
- );
- });
|