proxy-head.tsx 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import { useEffect, useState } from "react";
  2. import { useTranslation } from "react-i18next";
  3. import { Box, IconButton, TextField, SxProps } from "@mui/material";
  4. import {
  5. AccessTimeRounded,
  6. MyLocationRounded,
  7. NetworkCheckRounded,
  8. FilterAltRounded,
  9. FilterAltOffRounded,
  10. VisibilityRounded,
  11. VisibilityOffRounded,
  12. WifiTetheringRounded,
  13. WifiTetheringOffRounded,
  14. SortByAlphaRounded,
  15. SortRounded,
  16. } from "@mui/icons-material";
  17. import { useVergeConfig } from "@/hooks/use-verge-config";
  18. import delayManager from "@/services/delay";
  19. import type { HeadState } from "./use-head-state";
  20. import type { ProxySortType } from "./use-filter-sort";
  21. interface Props {
  22. sx?: SxProps;
  23. groupName: string;
  24. headState: HeadState;
  25. onLocation: () => void;
  26. onCheckDelay: () => void;
  27. onHeadState: (val: Partial<HeadState>) => void;
  28. }
  29. export const ProxyHead = (props: Props) => {
  30. const { sx = {}, groupName, headState, onHeadState } = props;
  31. const { showType, sortType, filterText, textState, testUrl } = headState;
  32. const { t } = useTranslation();
  33. const [autoFocus, setAutoFocus] = useState(false);
  34. useEffect(() => {
  35. // fix the focus conflict
  36. const timer = setTimeout(() => setAutoFocus(true), 100);
  37. return () => clearTimeout(timer);
  38. }, []);
  39. const { data: vergeConfig } = useVergeConfig();
  40. useEffect(() => {
  41. delayManager.setUrl(
  42. groupName,
  43. testUrl || vergeConfig?.default_latency_test!
  44. );
  45. }, [groupName, testUrl, vergeConfig?.default_latency_test]);
  46. return (
  47. <Box sx={{ display: "flex", alignItems: "center", ...sx }}>
  48. <IconButton
  49. size="small"
  50. color="inherit"
  51. title={t("Location")}
  52. onClick={props.onLocation}
  53. >
  54. <MyLocationRounded />
  55. </IconButton>
  56. <IconButton
  57. size="small"
  58. color="inherit"
  59. title={t("Delay check")}
  60. onClick={() => {
  61. // Remind the user that it is custom test url
  62. if (testUrl?.trim() && textState !== "filter") {
  63. onHeadState({ textState: "url" });
  64. }
  65. props.onCheckDelay();
  66. }}
  67. >
  68. <NetworkCheckRounded />
  69. </IconButton>
  70. <IconButton
  71. size="small"
  72. color="inherit"
  73. title={
  74. [t("Sort by default"), t("Sort by delay"), t("Sort by name")][
  75. sortType
  76. ]
  77. }
  78. onClick={() =>
  79. onHeadState({ sortType: ((sortType + 1) % 3) as ProxySortType })
  80. }
  81. >
  82. {sortType === 0 && <SortRounded />}
  83. {sortType === 1 && <AccessTimeRounded />}
  84. {sortType === 2 && <SortByAlphaRounded />}
  85. </IconButton>
  86. <IconButton
  87. size="small"
  88. color="inherit"
  89. title={t("Delay check URL")}
  90. onClick={() =>
  91. onHeadState({ textState: textState === "url" ? null : "url" })
  92. }
  93. >
  94. {textState === "url" ? (
  95. <WifiTetheringRounded />
  96. ) : (
  97. <WifiTetheringOffRounded />
  98. )}
  99. </IconButton>
  100. <IconButton
  101. size="small"
  102. color="inherit"
  103. title={t("Proxy detail")}
  104. onClick={() => onHeadState({ showType: !showType })}
  105. >
  106. {showType ? <VisibilityRounded /> : <VisibilityOffRounded />}
  107. </IconButton>
  108. <IconButton
  109. size="small"
  110. color="inherit"
  111. title={t("Filter")}
  112. onClick={() =>
  113. onHeadState({ textState: textState === "filter" ? null : "filter" })
  114. }
  115. >
  116. {textState === "filter" ? (
  117. <FilterAltRounded />
  118. ) : (
  119. <FilterAltOffRounded />
  120. )}
  121. </IconButton>
  122. {textState === "filter" && (
  123. <TextField
  124. autoFocus={autoFocus}
  125. hiddenLabel
  126. value={filterText}
  127. size="small"
  128. variant="outlined"
  129. placeholder={t("Filter conditions")}
  130. onChange={(e) => onHeadState({ filterText: e.target.value })}
  131. sx={{ ml: 0.5, flex: "1 1 auto", input: { py: 0.65, px: 1 } }}
  132. />
  133. )}
  134. {textState === "url" && (
  135. <TextField
  136. autoFocus={autoFocus}
  137. hiddenLabel
  138. autoSave="off"
  139. autoComplete="off"
  140. value={testUrl}
  141. size="small"
  142. variant="outlined"
  143. placeholder={t("Delay check URL")}
  144. onChange={(e) => onHeadState({ testUrl: e.target.value })}
  145. sx={{ ml: 0.5, flex: "1 1 auto", input: { py: 0.65, px: 1 } }}
  146. />
  147. )}
  148. </Box>
  149. );
  150. };