misc-viewer.tsx 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. import { forwardRef, useImperativeHandle, useState } from "react";
  2. import { useLockFn } from "ahooks";
  3. import { useTranslation } from "react-i18next";
  4. import {
  5. List,
  6. ListItem,
  7. ListItemText,
  8. MenuItem,
  9. Select,
  10. TextField,
  11. InputAdornment,
  12. } from "@mui/material";
  13. import { useVerge } from "@/hooks/use-verge";
  14. import { BaseDialog, DialogRef, Notice, Switch } from "@/components/base";
  15. import { TooltipIcon } from "@/components/base/base-tooltip-icon";
  16. export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
  17. const { t } = useTranslation();
  18. const { verge, patchVerge } = useVerge();
  19. const [open, setOpen] = useState(false);
  20. const [values, setValues] = useState({
  21. appLogLevel: "info",
  22. autoCloseConnection: true,
  23. autoCheckUpdate: true,
  24. enableBuiltinEnhanced: true,
  25. proxyLayoutColumn: 6,
  26. defaultLatencyTest: "",
  27. autoLogClean: 0,
  28. defaultLatencyTimeout: 10000,
  29. });
  30. useImperativeHandle(ref, () => ({
  31. open: () => {
  32. setOpen(true);
  33. setValues({
  34. appLogLevel: verge?.app_log_level ?? "info",
  35. autoCloseConnection: verge?.auto_close_connection ?? true,
  36. autoCheckUpdate: verge?.auto_check_update ?? true,
  37. enableBuiltinEnhanced: verge?.enable_builtin_enhanced ?? true,
  38. proxyLayoutColumn: verge?.proxy_layout_column || 6,
  39. defaultLatencyTest: verge?.default_latency_test || "",
  40. autoLogClean: verge?.auto_log_clean || 0,
  41. defaultLatencyTimeout: verge?.default_latency_timeout || 10000,
  42. });
  43. },
  44. close: () => setOpen(false),
  45. }));
  46. const onSave = useLockFn(async () => {
  47. try {
  48. await patchVerge({
  49. app_log_level: values.appLogLevel,
  50. auto_close_connection: values.autoCloseConnection,
  51. auto_check_update: values.autoCheckUpdate,
  52. enable_builtin_enhanced: values.enableBuiltinEnhanced,
  53. proxy_layout_column: values.proxyLayoutColumn,
  54. default_latency_test: values.defaultLatencyTest,
  55. default_latency_timeout: values.defaultLatencyTimeout,
  56. auto_log_clean: values.autoLogClean as any,
  57. });
  58. setOpen(false);
  59. } catch (err: any) {
  60. Notice.error(err.message || err.toString());
  61. }
  62. });
  63. return (
  64. <BaseDialog
  65. open={open}
  66. title={t("Miscellaneous")}
  67. contentSx={{ width: 450 }}
  68. okBtn={t("Save")}
  69. cancelBtn={t("Cancel")}
  70. onClose={() => setOpen(false)}
  71. onCancel={() => setOpen(false)}
  72. onOk={onSave}
  73. >
  74. <List>
  75. <ListItem sx={{ padding: "5px 2px" }}>
  76. <ListItemText primary={t("App Log Level")} />
  77. <Select
  78. size="small"
  79. sx={{ width: 100, "> div": { py: "7.5px" } }}
  80. value={values.appLogLevel}
  81. onChange={(e) =>
  82. setValues((v) => ({
  83. ...v,
  84. appLogLevel: e.target.value as string,
  85. }))
  86. }
  87. >
  88. {["trace", "debug", "info", "warn", "error", "silent"].map((i) => (
  89. <MenuItem value={i} key={i}>
  90. {i[0].toUpperCase() + i.slice(1).toLowerCase()}
  91. </MenuItem>
  92. ))}
  93. </Select>
  94. </ListItem>
  95. <ListItem sx={{ padding: "5px 2px" }}>
  96. <ListItemText
  97. primary={t("Auto Close Connections")}
  98. sx={{ maxWidth: "fit-content" }}
  99. />
  100. <TooltipIcon title={t("Auto Close Connections Info")} />
  101. <Switch
  102. edge="end"
  103. checked={values.autoCloseConnection}
  104. onChange={(_, c) =>
  105. setValues((v) => ({ ...v, autoCloseConnection: c }))
  106. }
  107. sx={{ marginLeft: "auto" }}
  108. />
  109. </ListItem>
  110. <ListItem sx={{ padding: "5px 2px" }}>
  111. <ListItemText primary={t("Auto Check Update")} />
  112. <Switch
  113. edge="end"
  114. checked={values.autoCheckUpdate}
  115. onChange={(_, c) =>
  116. setValues((v) => ({ ...v, autoCheckUpdate: c }))
  117. }
  118. />
  119. </ListItem>
  120. <ListItem sx={{ padding: "5px 2px" }}>
  121. <ListItemText
  122. primary={t("Enable Builtin Enhanced")}
  123. sx={{ maxWidth: "fit-content" }}
  124. />
  125. <TooltipIcon title={t("Enable Builtin Enhanced Info")} />
  126. <Switch
  127. edge="end"
  128. checked={values.enableBuiltinEnhanced}
  129. onChange={(_, c) =>
  130. setValues((v) => ({ ...v, enableBuiltinEnhanced: c }))
  131. }
  132. sx={{ marginLeft: "auto" }}
  133. />
  134. </ListItem>
  135. <ListItem sx={{ padding: "5px 2px" }}>
  136. <ListItemText primary={t("Proxy Layout Columns")} />
  137. <Select
  138. size="small"
  139. sx={{ width: 135, "> div": { py: "7.5px" } }}
  140. value={values.proxyLayoutColumn}
  141. onChange={(e) =>
  142. setValues((v) => ({
  143. ...v,
  144. proxyLayoutColumn: e.target.value as number,
  145. }))
  146. }
  147. >
  148. <MenuItem value={6} key={6}>
  149. {t("Auto Columns")}
  150. </MenuItem>
  151. {[1, 2, 3, 4, 5].map((i) => (
  152. <MenuItem value={i} key={i}>
  153. {i}
  154. </MenuItem>
  155. ))}
  156. </Select>
  157. </ListItem>
  158. <ListItem sx={{ padding: "5px 2px" }}>
  159. <ListItemText primary={t("Auto Log Clean")} />
  160. <Select
  161. size="small"
  162. sx={{ width: 135, "> div": { py: "7.5px" } }}
  163. value={values.autoLogClean}
  164. onChange={(e) =>
  165. setValues((v) => ({
  166. ...v,
  167. autoLogClean: e.target.value as number,
  168. }))
  169. }
  170. >
  171. {[
  172. { key: t("Never Clean"), value: 0 },
  173. { key: t("Retain _n Days", { n: 7 }), value: 1 },
  174. { key: t("Retain _n Days", { n: 30 }), value: 2 },
  175. { key: t("Retain _n Days", { n: 90 }), value: 3 },
  176. ].map((i) => (
  177. <MenuItem key={i.value} value={i.value}>
  178. {i.key}
  179. </MenuItem>
  180. ))}
  181. </Select>
  182. </ListItem>
  183. <ListItem sx={{ padding: "5px 2px" }}>
  184. <ListItemText
  185. primary={t("Default Latency Test")}
  186. sx={{ maxWidth: "fit-content" }}
  187. />
  188. <TooltipIcon title={t("Default Latency Test Info")} />
  189. <TextField
  190. size="small"
  191. autoComplete="off"
  192. autoCorrect="off"
  193. autoCapitalize="off"
  194. spellCheck="false"
  195. sx={{ width: 250, marginLeft: "auto" }}
  196. value={values.defaultLatencyTest}
  197. placeholder="http://1.1.1.1"
  198. onChange={(e) =>
  199. setValues((v) => ({ ...v, defaultLatencyTest: e.target.value }))
  200. }
  201. />
  202. </ListItem>
  203. <ListItem sx={{ padding: "5px 2px" }}>
  204. <ListItemText primary={t("Default Latency Timeout")} />
  205. <TextField
  206. size="small"
  207. type="number"
  208. autoComplete="off"
  209. autoCorrect="off"
  210. autoCapitalize="off"
  211. spellCheck="false"
  212. sx={{ width: 250 }}
  213. value={values.defaultLatencyTimeout}
  214. placeholder="10000"
  215. onChange={(e) =>
  216. setValues((v) => ({
  217. ...v,
  218. defaultLatencyTimeout: parseInt(e.target.value),
  219. }))
  220. }
  221. InputProps={{
  222. endAdornment: (
  223. <InputAdornment position="end">{t("millis")}</InputAdornment>
  224. ),
  225. }}
  226. />
  227. </ListItem>
  228. </List>
  229. </BaseDialog>
  230. );
  231. });