|
@@ -13,14 +13,19 @@ import {
|
|
Typography,
|
|
Typography,
|
|
Divider,
|
|
Divider,
|
|
LinearProgress,
|
|
LinearProgress,
|
|
|
|
+ keyframes,
|
|
} from "@mui/material";
|
|
} from "@mui/material";
|
|
import { RefreshRounded } from "@mui/icons-material";
|
|
import { RefreshRounded } from "@mui/icons-material";
|
|
import { useTranslation } from "react-i18next";
|
|
import { useTranslation } from "react-i18next";
|
|
-import { useLockFn } from "ahooks";
|
|
|
|
import { getProxyProviders, proxyProviderUpdate } from "@/services/api";
|
|
import { getProxyProviders, proxyProviderUpdate } from "@/services/api";
|
|
import { BaseDialog } from "../base";
|
|
import { BaseDialog } from "../base";
|
|
import parseTraffic from "@/utils/parse-traffic";
|
|
import parseTraffic from "@/utils/parse-traffic";
|
|
|
|
|
|
|
|
+const round = keyframes`
|
|
|
|
+ from { transform: rotate(0deg); }
|
|
|
|
+ to { transform: rotate(360deg); }
|
|
|
|
+`;
|
|
|
|
+
|
|
export const ProviderButton = () => {
|
|
export const ProviderButton = () => {
|
|
const { t } = useTranslation();
|
|
const { t } = useTranslation();
|
|
const { data } = useSWR("getProxyProviders", getProxyProviders);
|
|
const { data } = useSWR("getProxyProviders", getProxyProviders);
|
|
@@ -28,12 +33,31 @@ export const ProviderButton = () => {
|
|
const [open, setOpen] = useState(false);
|
|
const [open, setOpen] = useState(false);
|
|
|
|
|
|
const hasProvider = Object.keys(data || {}).length > 0;
|
|
const hasProvider = Object.keys(data || {}).length > 0;
|
|
|
|
+ const [updating, setUpdating] = useState(
|
|
|
|
+ Object.keys(data || {}).map(() => false)
|
|
|
|
+ );
|
|
|
|
|
|
- const handleUpdate = useLockFn(async (key: string) => {
|
|
|
|
- await proxyProviderUpdate(key);
|
|
|
|
- await mutate("getProxies");
|
|
|
|
- await mutate("getProxyProviders");
|
|
|
|
- });
|
|
|
|
|
|
+ const setUpdatingAt = (status: boolean, index: number) => {
|
|
|
|
+ setUpdating((prev) => {
|
|
|
|
+ const next = [...prev];
|
|
|
|
+ next[index] = status;
|
|
|
|
+ return next;
|
|
|
|
+ });
|
|
|
|
+ };
|
|
|
|
+ const handleUpdate = async (key: string, index: number) => {
|
|
|
|
+ setUpdatingAt(true, index);
|
|
|
|
+ proxyProviderUpdate(key)
|
|
|
|
+ .then(async () => {
|
|
|
|
+ setUpdatingAt(false, index);
|
|
|
|
+ await mutate("getProxies");
|
|
|
|
+ await mutate("getProxyProviders");
|
|
|
|
+ })
|
|
|
|
+ .catch(async () => {
|
|
|
|
+ setUpdatingAt(false, index);
|
|
|
|
+ await mutate("getProxies");
|
|
|
|
+ await mutate("getProxyProviders");
|
|
|
|
+ });
|
|
|
|
+ };
|
|
|
|
|
|
if (!hasProvider) return null;
|
|
if (!hasProvider) return null;
|
|
|
|
|
|
@@ -57,11 +81,11 @@ export const ProviderButton = () => {
|
|
variant="contained"
|
|
variant="contained"
|
|
size="small"
|
|
size="small"
|
|
onClick={async () => {
|
|
onClick={async () => {
|
|
- Object.entries(data || {}).forEach(async ([key, item]) => {
|
|
|
|
- await proxyProviderUpdate(key);
|
|
|
|
- await mutate("getProxies");
|
|
|
|
- await mutate("getProxyProviders");
|
|
|
|
- });
|
|
|
|
|
|
+ Object.entries(data || {}).forEach(
|
|
|
|
+ async ([key, item], index) => {
|
|
|
|
+ await handleUpdate(key, index);
|
|
|
|
+ }
|
|
|
|
+ );
|
|
}}
|
|
}}
|
|
>
|
|
>
|
|
{t("Update All")}
|
|
{t("Update All")}
|
|
@@ -75,7 +99,7 @@ export const ProviderButton = () => {
|
|
onCancel={() => setOpen(false)}
|
|
onCancel={() => setOpen(false)}
|
|
>
|
|
>
|
|
<List sx={{ py: 0, minHeight: 250 }}>
|
|
<List sx={{ py: 0, minHeight: 250 }}>
|
|
- {Object.entries(data || {}).map(([key, item]) => {
|
|
|
|
|
|
+ {Object.entries(data || {}).map(([key, item], index) => {
|
|
const time = dayjs(item.updatedAt);
|
|
const time = dayjs(item.updatedAt);
|
|
const sub = item.subscriptionInfo;
|
|
const sub = item.subscriptionInfo;
|
|
const hasSubInfo = !!sub;
|
|
const hasSubInfo = !!sub;
|
|
@@ -149,7 +173,12 @@ export const ProviderButton = () => {
|
|
size="small"
|
|
size="small"
|
|
color="inherit"
|
|
color="inherit"
|
|
title="Update Provider"
|
|
title="Update Provider"
|
|
- onClick={() => handleUpdate(key)}
|
|
|
|
|
|
+ onClick={() => handleUpdate(key, index)}
|
|
|
|
+ sx={{
|
|
|
|
+ animation: updating[index]
|
|
|
|
+ ? `1s linear infinite ${round}`
|
|
|
|
+ : "none",
|
|
|
|
+ }}
|
|
>
|
|
>
|
|
<RefreshRounded />
|
|
<RefreshRounded />
|
|
</IconButton>
|
|
</IconButton>
|