|
1 | | -import { FormControlLabel, Radio, RadioGroup, Switch } from "@mui/material"; |
| 1 | +import { |
| 2 | + FormControlLabel, |
| 3 | + Radio, |
| 4 | + RadioGroup, |
| 5 | + Switch, |
| 6 | + Tooltip, |
| 7 | +} from "@mui/material"; |
2 | 8 | import Box from "@mui/material/Box"; |
3 | 9 | import InputLabel from "@mui/material/InputLabel"; |
4 | 10 | import MenuItem from "@mui/material/MenuItem"; |
| 11 | +import CheckIcon from "@mui/icons-material/Check"; |
5 | 12 | import Select, { type SelectChangeEvent } from "@mui/material/Select"; |
| 13 | +import { useEffect, useState } from "react"; |
6 | 14 | import { useTranslation } from "react-i18next"; |
7 | 15 | import { useShallow } from "zustand/react/shallow"; |
8 | 16 | import { useStore } from "@/store/appStore"; |
@@ -141,3 +149,116 @@ export const CardClickModeSettings = () => { |
141 | 149 | </Box> |
142 | 150 | ); |
143 | 151 | }; |
| 152 | + |
| 153 | +const PRESET_COLORS = [ |
| 154 | + { label: "MUI Blue", value: "#1976d2" }, |
| 155 | + { label: "Purple", value: "#9c27b0" }, |
| 156 | + { label: "Green", value: "#5cd08c" }, |
| 157 | + { label: "Red", value: "#d32f2f" }, |
| 158 | + { label: "Orange", value: "#ed6c02" }, |
| 159 | + { label: "Teal", value: "#009688" }, |
| 160 | +]; |
| 161 | + |
| 162 | +export const ThemeColorSettings = () => { |
| 163 | + const { t } = useTranslation(); |
| 164 | + const themeColor = useStore((state) => state.themeColor); |
| 165 | + const setThemeColor = useStore((state) => state.setThemeColor); |
| 166 | + const [localColor, setLocalColor] = useState(themeColor); |
| 167 | + |
| 168 | + useEffect(() => { |
| 169 | + setLocalColor(themeColor); |
| 170 | + }, [themeColor]); |
| 171 | + |
| 172 | + useEffect(() => { |
| 173 | + const timer = setTimeout(() => { |
| 174 | + if (localColor !== themeColor) { |
| 175 | + setThemeColor(localColor); |
| 176 | + } |
| 177 | + }, 300); |
| 178 | + return () => clearTimeout(timer); |
| 179 | + }, [localColor, themeColor, setThemeColor]); |
| 180 | + |
| 181 | + const handleColorClick = (color: string) => { |
| 182 | + setLocalColor(color); |
| 183 | + setThemeColor(color); |
| 184 | + }; |
| 185 | + |
| 186 | + return ( |
| 187 | + <Box className="mb-6"> |
| 188 | + <InputLabel className="font-semibold mb-4"> |
| 189 | + {t("pages.Settings.themeColor.title", "主题颜色")} |
| 190 | + </InputLabel> |
| 191 | + <Box className="pl-2 flex flex-wrap gap-4 items-center"> |
| 192 | + {PRESET_COLORS.map((color) => { |
| 193 | + const isSelected = |
| 194 | + localColor.toLowerCase() === color.value.toLowerCase(); |
| 195 | + return ( |
| 196 | + <Tooltip |
| 197 | + key={color.value} |
| 198 | + title={t( |
| 199 | + `pages.Settings.themeColor.${color.label.toLowerCase().replace(" ", "")}`, |
| 200 | + color.label, |
| 201 | + )} |
| 202 | + > |
| 203 | + <Box |
| 204 | + onClick={() => handleColorClick(color.value)} |
| 205 | + sx={{ |
| 206 | + width: 36, |
| 207 | + height: 36, |
| 208 | + borderRadius: "50%", |
| 209 | + backgroundColor: color.value, |
| 210 | + cursor: "pointer", |
| 211 | + display: "flex", |
| 212 | + alignItems: "center", |
| 213 | + justifyContent: "center", |
| 214 | + boxShadow: isSelected ? 3 : 1, |
| 215 | + transition: "all 0.2s ease-in-out", |
| 216 | + "&:hover": { transform: "scale(1.1)", boxShadow: 4 }, |
| 217 | + }} |
| 218 | + > |
| 219 | + {isSelected && ( |
| 220 | + <CheckIcon sx={{ color: "#fff", fontSize: 20 }} /> |
| 221 | + )} |
| 222 | + </Box> |
| 223 | + </Tooltip> |
| 224 | + ); |
| 225 | + })} |
| 226 | + |
| 227 | + <Box className="ml-2 flex items-center gap-3"> |
| 228 | + <InputLabel className="text-sm m-0"> |
| 229 | + {t("pages.Settings.themeColor.custom", "自定义:")} |
| 230 | + </InputLabel> |
| 231 | + <Box |
| 232 | + sx={{ |
| 233 | + width: 36, |
| 234 | + height: 36, |
| 235 | + borderRadius: "50%", |
| 236 | + overflow: "hidden", |
| 237 | + cursor: "pointer", |
| 238 | + boxShadow: 1, |
| 239 | + transition: "all 0.2s ease-in-out", |
| 240 | + "&:hover": { transform: "scale(1.1)", boxShadow: 4 }, |
| 241 | + position: "relative", |
| 242 | + }} |
| 243 | + > |
| 244 | + <input |
| 245 | + type="color" |
| 246 | + value={localColor} |
| 247 | + onChange={(e) => setLocalColor(e.target.value)} |
| 248 | + style={{ |
| 249 | + width: "150%", |
| 250 | + height: "150%", |
| 251 | + position: "absolute", |
| 252 | + top: "-25%", |
| 253 | + left: "-25%", |
| 254 | + cursor: "pointer", |
| 255 | + border: "none", |
| 256 | + padding: 0, |
| 257 | + }} |
| 258 | + /> |
| 259 | + </Box> |
| 260 | + </Box> |
| 261 | + </Box> |
| 262 | + </Box> |
| 263 | + ); |
| 264 | +}; |
0 commit comments