proxy-global.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import useSWR, { useSWRConfig } from "swr";
  2. import { useEffect, useRef, useState } from "react";
  3. import { useLockFn } from "ahooks";
  4. import { Virtuoso } from "react-virtuoso";
  5. import { ApiType } from "../../services/types";
  6. import { updateProxy } from "../../services/api";
  7. import { getProfiles, patchProfile } from "../../services/cmds";
  8. import useSortProxy, { ProxySortType } from "./use-sort-proxy";
  9. import useFilterProxy from "./use-filter-proxy";
  10. import delayManager from "../../services/delay";
  11. import ProxyHead from "./proxy-head";
  12. import ProxyItem from "./proxy-item";
  13. interface Props {
  14. groupName: string;
  15. curProxy?: string;
  16. proxies: ApiType.ProxyItem[];
  17. }
  18. // this component will be used for DIRECT/GLOBAL
  19. const ProxyGlobal = (props: Props) => {
  20. const { groupName, curProxy, proxies } = props;
  21. const { mutate } = useSWRConfig();
  22. const [now, setNow] = useState(curProxy || "DIRECT");
  23. const [showType, setShowType] = useState(true);
  24. const [sortType, setSortType] = useState<ProxySortType>(0);
  25. const [filterText, setFilterText] = useState("");
  26. const virtuosoRef = useRef<any>();
  27. const filterProxies = useFilterProxy(proxies, groupName, filterText);
  28. const sortedProxies = useSortProxy(filterProxies, groupName, sortType);
  29. const { data: profiles } = useSWR("getProfiles", getProfiles);
  30. const onChangeProxy = useLockFn(async (name: string) => {
  31. await updateProxy(groupName, name);
  32. setNow(name);
  33. if (groupName === "DIRECT") return;
  34. // update global selected
  35. const profile = profiles?.items?.find((p) => p.uid === profiles.current);
  36. if (!profile) return;
  37. if (!profile.selected) profile.selected = [];
  38. const index = profile.selected.findIndex((item) => item.name === groupName);
  39. if (index < 0) {
  40. profile.selected.unshift({ name: groupName, now: name });
  41. } else {
  42. profile.selected[index] = { name: groupName, now: name };
  43. }
  44. await patchProfile(profiles!.current!, { selected: profile.selected });
  45. });
  46. const onLocation = (smooth = true) => {
  47. const index = sortedProxies.findIndex((p) => p.name === now);
  48. if (index >= 0) {
  49. virtuosoRef.current?.scrollToIndex?.({
  50. index,
  51. align: "center",
  52. behavior: smooth ? "smooth" : "auto",
  53. });
  54. }
  55. };
  56. const onCheckAll = useLockFn(async () => {
  57. const names = sortedProxies.map((p) => p.name);
  58. await delayManager.checkListDelay(
  59. { names, groupName, skipNum: 8, maxTimeout: 600 },
  60. () => mutate("getProxies")
  61. );
  62. mutate("getProxies");
  63. });
  64. useEffect(() => onLocation(false), [groupName]);
  65. useEffect(() => {
  66. if (groupName === "DIRECT") setNow("DIRECT");
  67. else if (groupName === "GLOBAL") {
  68. if (profiles) {
  69. const current = profiles.current;
  70. const profile = profiles.items?.find((p) => p.uid === current);
  71. profile?.selected?.forEach((item) => {
  72. if (item.name === "GLOBAL") {
  73. if (item.now && item.now !== curProxy) {
  74. updateProxy("GLOBAL", item.now).then(() => setNow(item!.now!));
  75. mutate("getProxies");
  76. }
  77. }
  78. });
  79. }
  80. setNow(curProxy || "DIRECT");
  81. }
  82. }, [groupName, curProxy, profiles]);
  83. return (
  84. <>
  85. <ProxyHead
  86. sx={{ px: 3, my: 0.5, button: { mr: 0.5 } }}
  87. showType={showType}
  88. sortType={sortType}
  89. groupName={groupName}
  90. filterText={filterText}
  91. onLocation={onLocation}
  92. onCheckDelay={onCheckAll}
  93. onShowType={setShowType}
  94. onSortType={setSortType}
  95. onFilterText={setFilterText}
  96. />
  97. <Virtuoso
  98. ref={virtuosoRef}
  99. style={{ height: "calc(100% - 40px)" }}
  100. totalCount={sortedProxies.length}
  101. itemContent={(index) => (
  102. <ProxyItem
  103. groupName={groupName}
  104. proxy={sortedProxies[index]}
  105. selected={sortedProxies[index].name === now}
  106. showType={showType}
  107. onClick={onChangeProxy}
  108. sx={{ py: 0, px: 2 }}
  109. />
  110. )}
  111. />
  112. </>
  113. );
  114. };
  115. export default ProxyGlobal;