proxy-group.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. import { useState } from "react";
  2. import { Virtuoso } from "react-virtuoso";
  3. import {
  4. Box,
  5. Collapse,
  6. Divider,
  7. IconButton,
  8. List,
  9. ListItem,
  10. ListItemText,
  11. } from "@mui/material";
  12. import {
  13. SendRounded,
  14. ExpandLessRounded,
  15. ExpandMoreRounded,
  16. MyLocationRounded,
  17. NetworkCheckRounded,
  18. } from "@mui/icons-material";
  19. import { updateProxy } from "../services/api";
  20. import { ApiType } from "../services/types";
  21. import { getProfiles, patchProfile } from "../services/cmds";
  22. import ProxyItem from "./proxy-item";
  23. interface Props {
  24. group: ApiType.ProxyGroupItem;
  25. }
  26. const ProxyGroup = ({ group }: Props) => {
  27. const [open, setOpen] = useState(false);
  28. const [now, setNow] = useState(group.now);
  29. const proxies = group.all ?? [];
  30. const onUpdate = async (name: string) => {
  31. // can not call update
  32. if (group.type !== "Selector") {
  33. // Todo
  34. // error Tips
  35. return;
  36. }
  37. const oldValue = now;
  38. try {
  39. setNow(name);
  40. await updateProxy(group.name, name);
  41. const profiles = await getProfiles().catch(console.error);
  42. if (!profiles) return;
  43. const profile = profiles.items![profiles.current!]!;
  44. if (!profile) return;
  45. if (!profile.selected) profile.selected = [];
  46. const index = profile.selected.findIndex(
  47. (item) => item.name === group.name
  48. );
  49. if (index < 0) {
  50. profile.selected.push({ name: group.name, now: name });
  51. } else {
  52. profile.selected[index] = { name: group.name, now: name };
  53. }
  54. patchProfile(profiles.current!, profile).catch(console.error);
  55. } catch {
  56. setNow(oldValue);
  57. // Todo
  58. // error tips
  59. }
  60. };
  61. return (
  62. <>
  63. <ListItem button onClick={() => setOpen(!open)} dense>
  64. <ListItemText
  65. primary={group.name}
  66. secondary={
  67. <>
  68. <SendRounded color="primary" sx={{ mr: 1, fontSize: 14 }} />
  69. <span>{now}</span>
  70. </>
  71. }
  72. secondaryTypographyProps={{
  73. sx: { display: "flex", alignItems: "center" },
  74. }}
  75. />
  76. {open ? <ExpandLessRounded /> : <ExpandMoreRounded />}
  77. </ListItem>
  78. <Collapse in={open} timeout="auto" unmountOnExit>
  79. <Box sx={{ pl: 4, pr: 3, my: 0.5 }}>
  80. <IconButton size="small" title="location">
  81. <MyLocationRounded />
  82. </IconButton>
  83. <IconButton size="small" title="check">
  84. <NetworkCheckRounded />
  85. </IconButton>
  86. </Box>
  87. {proxies.length >= 10 ? (
  88. <Virtuoso
  89. style={{ height: "400px", marginBottom: "4px" }}
  90. totalCount={proxies.length}
  91. itemContent={(index) => (
  92. <ProxyItem
  93. proxy={proxies[index]}
  94. selected={proxies[index].name === now}
  95. sx={{ py: 0, pl: 4 }}
  96. onClick={onUpdate}
  97. />
  98. )}
  99. />
  100. ) : (
  101. <List
  102. component="div"
  103. disablePadding
  104. sx={{ maxHeight: "400px", overflow: "auto", mb: "4px" }}
  105. >
  106. {proxies.map((proxy) => (
  107. <ProxyItem
  108. key={proxy.name}
  109. proxy={proxy}
  110. selected={proxy.name === now}
  111. sx={{ py: 0, pl: 4 }}
  112. onClick={onUpdate}
  113. />
  114. ))}
  115. </List>
  116. )}
  117. <Divider variant="middle" />
  118. </Collapse>
  119. </>
  120. );
  121. };
  122. export default ProxyGroup;