setting-theme.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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. Button,
  7. Dialog,
  8. DialogActions,
  9. DialogContent,
  10. DialogTitle,
  11. List,
  12. ListItem,
  13. ListItemText,
  14. styled,
  15. TextField,
  16. } from "@mui/material";
  17. import { getVergeConfig, patchVergeConfig } from "../../services/cmds";
  18. import { defaultTheme } from "../../pages/_theme";
  19. interface Props {
  20. open: boolean;
  21. onClose: () => void;
  22. onError?: (err: Error) => void;
  23. }
  24. const Item = styled(ListItem)(() => ({
  25. padding: "5px 2px",
  26. }));
  27. const Round = styled("div")(() => ({
  28. width: "24px",
  29. height: "24px",
  30. borderRadius: "18px",
  31. display: "inline-block",
  32. marginRight: "8px",
  33. }));
  34. const SettingTheme = (props: Props) => {
  35. const { open, onClose, onError } = props;
  36. const { t } = useTranslation();
  37. const { data: vergeConfig, mutate } = useSWR(
  38. "getVergeConfig",
  39. getVergeConfig
  40. );
  41. const { theme_setting } = vergeConfig ?? {};
  42. const [theme, setTheme] = useState(theme_setting || {});
  43. useEffect(() => {
  44. setTheme({ ...theme_setting } || {});
  45. }, [theme_setting]);
  46. const textProps = {
  47. size: "small",
  48. autoComplete: "off",
  49. sx: { width: 135 },
  50. } as const;
  51. const handleChange = (field: keyof typeof theme) => (e: any) => {
  52. setTheme((t) => ({ ...t, [field]: e.target.value }));
  53. };
  54. const onSave = useLockFn(async () => {
  55. try {
  56. await patchVergeConfig({ theme_setting: theme });
  57. mutate();
  58. onClose();
  59. } catch (err: any) {
  60. onError?.(err);
  61. }
  62. });
  63. const renderItem = (label: string, key: keyof typeof defaultTheme) => {
  64. return (
  65. <Item>
  66. <ListItemText primary={label} />
  67. <Round sx={{ background: theme[key] || defaultTheme[key] }} />
  68. <TextField
  69. {...textProps}
  70. value={theme[key] ?? ""}
  71. placeholder={defaultTheme[key]}
  72. onChange={handleChange(key)}
  73. onKeyDown={(e) => e.key === "Enter" && onSave()}
  74. />
  75. </Item>
  76. );
  77. };
  78. return (
  79. <Dialog open={open} onClose={onClose}>
  80. <DialogTitle>{t("Theme Setting")}</DialogTitle>
  81. <DialogContent
  82. sx={{ width: 400, maxHeight: 300, overflow: "auto", pb: 0 }}
  83. >
  84. <List sx={{ pt: 0 }}>
  85. {renderItem("Primary Color", "primary_color")}
  86. {renderItem("Secondary Color", "secondary_color")}
  87. {renderItem("Primary Text", "primary_text")}
  88. {renderItem("Secondary Text", "secondary_text")}
  89. {renderItem("Info Color", "info_color")}
  90. {renderItem("Error Color", "error_color")}
  91. {renderItem("Warning Color", "warning_color")}
  92. {renderItem("Success Color", "success_color")}
  93. <Item>
  94. <ListItemText primary="Font Family" />
  95. <TextField
  96. {...textProps}
  97. value={theme.font_family ?? ""}
  98. onChange={handleChange("font_family")}
  99. onKeyDown={(e) => e.key === "Enter" && onSave()}
  100. />
  101. </Item>
  102. <Item>
  103. <ListItemText primary="CSS Injection" />
  104. <TextField
  105. {...textProps}
  106. value={theme.css_injection ?? ""}
  107. onChange={handleChange("css_injection")}
  108. onKeyDown={(e) => e.key === "Enter" && onSave()}
  109. />
  110. </Item>
  111. </List>
  112. </DialogContent>
  113. <DialogActions>
  114. <Button onClick={onClose}>{t("Cancel")}</Button>
  115. <Button onClick={onSave} variant="contained">
  116. {t("Save")}
  117. </Button>
  118. </DialogActions>
  119. </Dialog>
  120. );
  121. };
  122. export default SettingTheme;