import { forwardRef, useImperativeHandle, useState } from "react"; import { useLockFn } from "ahooks"; import { useTranslation } from "react-i18next"; import { Box, IconButton, Tooltip } from "@mui/material"; import { InfoRounded } from "@mui/icons-material"; import { InputAdornment, List, ListItem, ListItemText, styled, TextField, Typography, Button, } from "@mui/material"; import { useVerge } from "@/hooks/use-verge"; import { getSystemProxy, getAutotemProxy } from "@/services/cmds"; import { BaseDialog, DialogRef, Notice, Switch } from "@/components/base"; import { Edit } from "@mui/icons-material"; import { EditorViewer } from "@/components/profile/editor-viewer"; import { BaseFieldset } from "@/components/base/base-fieldset"; import getSystem from "@/utils/get-system"; import { TooltipIcon } from "@/components/base/base-tooltip-icon"; const DEFAULT_PAC = `function FindProxyForURL(url, host) { return "PROXY 127.0.0.1:%mixed-port%; SOCKS5 127.0.0.1:%mixed-port%; DIRECT;"; }`; export const SysproxyViewer = forwardRef((props, ref) => { const { t } = useTranslation(); let validReg; if (getSystem() === "windows") { validReg = /^((\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}|(\d{1,3}\.){1,3}\d{1,3}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\*|\d{1,3}\.\d{1,3}\.\*|\d{1,3}\.\*|([a-fA-F0-9:]+:+)+[a-fA-F0-9]+|localhost|)(;((\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}|(\d{1,3}\.){1,3}\d{1,3}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\*|\d{1,3}\.\d{1,3}\.\*|\d{1,3}\.\*|([a-fA-F0-9:]+:+)+[a-fA-F0-9]+|localhost|))*;?$/; } else { validReg = /^((\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}|(\d{1,3}\.){1,3}\d{1,3}(\/\d{1,2}|\/3[0-2])?|\d{1,3}\.\d{1,3}\.\d{1,3}\.\*(\/\d{1,2}|\/3[0-2])?|\d{1,3}\.\d{1,3}\.\*(\/\d{1,2}|\/3[0-2])?|\d{1,3}\.\*(\/\d{1,2}|\/3[0-2])?|([a-fA-F0-9:]+:+)+[a-fA-F0-9]+(\/\d{1,3})?|localhost|)(,((\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}|(\d{1,3}\.){1,3}\d{1,3}(\/\d{1,2}|\/3[0-2])?|\d{1,3}\.\d{1,3}\.\d{1,3}\.\*(\/\d{1,2}|\/3[0-2])?|\d{1,3}\.\d{1,3}\.\*(\/\d{1,2}|\/3[0-2])?|\d{1,3}\.\*(\/\d{1,2}|\/3[0-2])?|([a-fA-F0-9:]+:+)+[a-fA-F0-9]+(\/\d{1,3})?|localhost|))*,?$/; } const [open, setOpen] = useState(false); const [editorOpen, setEditorOpen] = useState(false); const { verge, patchVerge } = useVerge(); type SysProxy = Awaited>; const [sysproxy, setSysproxy] = useState(); type AutoProxy = Awaited>; const [autoproxy, setAutoproxy] = useState(); const { enable_system_proxy: enabled, proxy_auto_config, pac_file_content, enable_proxy_guard, system_proxy_bypass, proxy_guard_duration, } = verge ?? {}; const [value, setValue] = useState({ guard: enable_proxy_guard, bypass: system_proxy_bypass, duration: proxy_guard_duration ?? 10, pac: proxy_auto_config, pac_content: pac_file_content ?? DEFAULT_PAC, }); useImperativeHandle(ref, () => ({ open: () => { setOpen(true); setValue({ guard: enable_proxy_guard, bypass: system_proxy_bypass, duration: proxy_guard_duration ?? 10, pac: proxy_auto_config, pac_content: pac_file_content ?? DEFAULT_PAC, }); getSystemProxy().then((p) => setSysproxy(p)); getAutotemProxy().then((p) => setAutoproxy(p)); }, close: () => setOpen(false), })); const onSave = useLockFn(async () => { if (value.duration < 1) { Notice.error(t("Proxy Daemon Duration Cannot be Less than 1 Second")); return; } const patch: Partial = {}; if (value.guard !== enable_proxy_guard) { patch.enable_proxy_guard = value.guard; } if (value.duration !== proxy_guard_duration) { patch.proxy_guard_duration = value.duration; } if (value.bypass !== system_proxy_bypass) { patch.system_proxy_bypass = value.bypass; } if (value.pac !== proxy_auto_config) { patch.proxy_auto_config = value.pac; } if (value.pac_content !== pac_file_content) { patch.pac_file_content = value.pac_content; } if (value.bypass && !validReg.test(value.bypass)) { Notice.error(t("Invalid Bypass Format")); return; } try { await patchVerge(patch); setOpen(false); } catch (err: any) { Notice.error(err.message || err.toString()); } }); return ( setOpen(false)} onCancel={() => setOpen(false)} onOk={onSave} > {t("Enable status")} {value.pac ? autoproxy?.enable ? t("Enabled") : t("Disabled") : sysproxy?.enable ? t("Enabled") : t("Disabled")} {!value.pac && ( <> {t("Server Addr")} {sysproxy?.server ? sysproxy.server : t("Not available")} )} {value.pac && ( {t("PAC URL")} {autoproxy?.url || "-"} )} setValue((v) => ({ ...v, pac: e }))} /> setValue((v) => ({ ...v, guard: e }))} sx={{ marginLeft: "auto" }} /> s, }} onChange={(e) => { setValue((v) => ({ ...v, duration: +e.target.value.replace(/\D/, ""), })); }} /> {!value.pac && ( <> { setValue((v) => ({ ...v, bypass: e.target.value })); }} /> )} {value.pac && ( <> { let pac = DEFAULT_PAC; if (content && content.trim().length > 0) { pac = content; } setValue((v) => ({ ...v, pac_content: pac })); }} onClose={() => { setEditorOpen(false); }} /> )} ); }); const FlexBox = styled("div")` display: flex; margin-top: 4px; .label { flex: none; //width: 85px; } `;