sysproxy-viewer.tsx 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. import useSWR from "swr";
  2. import { useEffect, useState } from "react";
  3. import { useLockFn } from "ahooks";
  4. import { useTranslation } from "react-i18next";
  5. import {
  6. Box,
  7. Button,
  8. Dialog,
  9. DialogActions,
  10. DialogContent,
  11. DialogTitle,
  12. InputAdornment,
  13. List,
  14. ListItem,
  15. ListItemText,
  16. styled,
  17. Switch,
  18. TextField,
  19. Typography,
  20. } from "@mui/material";
  21. import {
  22. getSystemProxy,
  23. getVergeConfig,
  24. patchVergeConfig,
  25. } from "@/services/cmds";
  26. import { ModalHandler } from "@/hooks/use-modal-handler";
  27. import Notice from "@/components/base/base-notice";
  28. interface Props {
  29. handler: ModalHandler;
  30. }
  31. const FlexBox = styled("div")`
  32. display: flex;
  33. margin-top: 4px;
  34. .label {
  35. flex: none;
  36. width: 80px;
  37. }
  38. `;
  39. const SysproxyViewer = ({ handler }: Props) => {
  40. const { t } = useTranslation();
  41. const [open, setOpen] = useState(false);
  42. if (handler) {
  43. handler.current = {
  44. open: () => setOpen(true),
  45. close: () => setOpen(false),
  46. };
  47. }
  48. const { data: vergeConfig, mutate: mutateVerge } = useSWR(
  49. "getVergeConfig",
  50. getVergeConfig
  51. );
  52. const {
  53. enable_system_proxy: enabled,
  54. enable_proxy_guard,
  55. system_proxy_bypass,
  56. proxy_guard_duration,
  57. } = vergeConfig ?? {};
  58. const { data: sysproxy } = useSWR(
  59. open ? "getSystemProxy" : null,
  60. getSystemProxy
  61. );
  62. const [value, setValue] = useState({
  63. guard: enable_proxy_guard,
  64. bypass: system_proxy_bypass,
  65. duration: proxy_guard_duration ?? 10,
  66. });
  67. useEffect(() => {
  68. setValue({
  69. guard: enable_proxy_guard,
  70. bypass: system_proxy_bypass,
  71. duration: proxy_guard_duration ?? 10,
  72. });
  73. }, [vergeConfig]);
  74. const onSave = useLockFn(async () => {
  75. if (value.duration < 5) {
  76. Notice.error("Proxy guard duration at least 5 seconds");
  77. return;
  78. }
  79. const patch: Partial<CmdType.VergeConfig> = {};
  80. if (value.guard !== enable_proxy_guard) {
  81. patch.enable_proxy_guard = value.guard;
  82. }
  83. if (value.duration !== proxy_guard_duration) {
  84. patch.proxy_guard_duration = value.duration;
  85. }
  86. if (value.bypass !== system_proxy_bypass) {
  87. patch.system_proxy_bypass = value.bypass;
  88. }
  89. try {
  90. await patchVergeConfig(patch);
  91. mutateVerge();
  92. setOpen(false);
  93. } catch (err: any) {
  94. Notice.error(err.message || err.toString());
  95. }
  96. });
  97. return (
  98. <Dialog open={open} onClose={() => setOpen(false)}>
  99. <DialogTitle>{t("System Proxy Setting")}</DialogTitle>
  100. <DialogContent sx={{ width: 450, maxHeight: 300 }}>
  101. <List>
  102. <ListItem sx={{ padding: "5px 2px" }}>
  103. <ListItemText primary={t("Proxy Guard")} />
  104. <Switch
  105. edge="end"
  106. disabled={!enabled}
  107. checked={value.guard}
  108. onChange={(_, e) => setValue((v) => ({ ...v, guard: e }))}
  109. />
  110. </ListItem>
  111. <ListItem sx={{ padding: "5px 2px" }}>
  112. <ListItemText primary={t("Guard Duration")} />
  113. <TextField
  114. disabled={!enabled}
  115. size="small"
  116. value={value.duration}
  117. sx={{ width: 100 }}
  118. InputProps={{
  119. endAdornment: <InputAdornment position="end">s</InputAdornment>,
  120. }}
  121. onChange={(e) => {
  122. setValue((v) => ({
  123. ...v,
  124. duration: +e.target.value.replace(/\D/, ""),
  125. }));
  126. }}
  127. />
  128. </ListItem>
  129. <ListItem sx={{ padding: "5px 2px", alignItems: "start" }}>
  130. <ListItemText
  131. primary={t("Proxy Bypass")}
  132. sx={{ padding: "3px 0" }}
  133. />
  134. <TextField
  135. disabled={!enabled}
  136. size="small"
  137. autoComplete="off"
  138. multiline
  139. rows={3}
  140. sx={{ width: 280 }}
  141. value={value.bypass}
  142. onChange={(e) =>
  143. setValue((v) => ({ ...v, bypass: e.target.value }))
  144. }
  145. />
  146. </ListItem>
  147. </List>
  148. <Box sx={{ mt: 2.5 }}>
  149. <Typography variant="body1" sx={{ fontSize: "18px", mb: 1 }}>
  150. {t("Current System Proxy")}
  151. </Typography>
  152. <FlexBox>
  153. <Typography className="label">Enable:</Typography>
  154. <Typography className="value">
  155. {(!!sysproxy?.enable).toString()}
  156. </Typography>
  157. </FlexBox>
  158. <FlexBox>
  159. <Typography className="label">Server:</Typography>
  160. <Typography className="value">{sysproxy?.server || "-"}</Typography>
  161. </FlexBox>
  162. <FlexBox>
  163. <Typography className="label">Bypass:</Typography>
  164. <Typography className="value">{sysproxy?.bypass || "-"}</Typography>
  165. </FlexBox>
  166. </Box>
  167. </DialogContent>
  168. <DialogActions>
  169. <Button variant="outlined" onClick={() => setOpen(false)}>
  170. {t("Cancel")}
  171. </Button>
  172. <Button onClick={onSave} variant="contained">
  173. {t("Save")}
  174. </Button>
  175. </DialogActions>
  176. </Dialog>
  177. );
  178. };
  179. export default SysproxyViewer;