core-switch.tsx 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import useSWR, { useSWRConfig } from "swr";
  2. import { useState } from "react";
  3. import { useLockFn } from "ahooks";
  4. import { Menu, MenuItem } from "@mui/material";
  5. import { Settings } from "@mui/icons-material";
  6. import { changeClashCore, getVergeConfig } from "../../services/cmds";
  7. import { getVersion } from "../../services/api";
  8. import Notice from "../base/base-notice";
  9. const VALID_CORE = [
  10. { name: "Clash", core: "clash" },
  11. { name: "Clash Meta", core: "clash-meta" },
  12. ];
  13. const CoreSwitch = () => {
  14. const { mutate } = useSWRConfig();
  15. const { data: vergeConfig } = useSWR("getVergeConfig", getVergeConfig);
  16. const [anchorEl, setAnchorEl] = useState<any>(null);
  17. const [position, setPosition] = useState({ left: 0, top: 0 });
  18. const { clash_core = "clash" } = vergeConfig ?? {};
  19. const onCoreChange = useLockFn(async (core: string) => {
  20. if (core === clash_core) return;
  21. try {
  22. await changeClashCore(core);
  23. mutate("getVergeConfig");
  24. mutate("getClashConfig");
  25. mutate("getVersion", getVersion());
  26. setAnchorEl(null);
  27. Notice.success(`Successfully switch to ${core}`, 1000);
  28. } catch (err: any) {
  29. Notice.error(err?.message || err.toString());
  30. }
  31. });
  32. return (
  33. <>
  34. <Settings
  35. fontSize="small"
  36. style={{ cursor: "pointer", opacity: 0.75 }}
  37. onClick={(event) => {
  38. const { clientX, clientY } = event;
  39. setPosition({ top: clientY, left: clientX });
  40. setAnchorEl(event.currentTarget);
  41. }}
  42. />
  43. <Menu
  44. open={!!anchorEl}
  45. anchorEl={anchorEl}
  46. onClose={() => setAnchorEl(null)}
  47. anchorPosition={position}
  48. anchorReference="anchorPosition"
  49. transitionDuration={225}
  50. onContextMenu={(e) => {
  51. setAnchorEl(null);
  52. e.preventDefault();
  53. }}
  54. >
  55. {VALID_CORE.map((each) => (
  56. <MenuItem
  57. key={each.core}
  58. sx={{ minWidth: 125 }}
  59. selected={each.core === clash_core}
  60. onClick={() => onCoreChange(each.core)}
  61. >
  62. {each.name}
  63. </MenuItem>
  64. ))}
  65. </Menu>
  66. </>
  67. );
  68. };
  69. export default CoreSwitch;