feat: profile loading animation

This commit is contained in:
GyDi 2021-12-26 14:08:25 +08:00
parent cc96b5ad04
commit 2fdcc9c584
2 changed files with 37 additions and 24 deletions

View File

@ -1,18 +1,20 @@
import React from "react";
import React, { useState } from "react";
import dayjs from "dayjs";
import {
alpha,
Box,
ButtonBase,
styled,
Typography,
LinearProgress,
IconButton,
keyframes,
} from "@mui/material";
import { MenuRounded } from "@mui/icons-material";
import { useSWRConfig } from "swr";
import { RefreshRounded } from "@mui/icons-material";
import { CmdType } from "../services/types";
import parseTraffic from "../utils/parse-traffic";
import relativeTime from "dayjs/plugin/relativeTime";
import { updateProfile } from "../services/cmds";
dayjs.extend(relativeTime);
@ -27,15 +29,23 @@ const Wrapper = styled(Box)(({ theme }) => ({
boxSizing: "border-box",
}));
const round = keyframes`
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
`;
interface Props {
index: number;
selected: boolean;
itemData: CmdType.ProfileItem;
onClick: () => void;
onUpdate: () => void;
}
const ProfileItemComp: React.FC<Props> = (props) => {
const { selected, itemData, onClick, onUpdate } = props;
const { index, selected, itemData, onClick } = props;
const { mutate } = useSWRConfig();
const [loading, setLoading] = useState(false);
const { name = "Profile", extra, updated = 0 } = itemData;
const { upload = 0, download = 0, total = 0 } = extra ?? {};
@ -44,6 +54,19 @@ const ProfileItemComp: React.FC<Props> = (props) => {
const progress = Math.round(((download + upload) * 100) / (total + 0.1));
const fromnow = updated > 0 ? dayjs(updated * 1000).fromNow() : "";
const onUpdate = async () => {
if (loading) return;
setLoading(true);
try {
await updateProfile(index);
mutate("getProfiles");
} catch (err) {
console.error(err);
} finally {
setLoading(false);
}
};
return (
<Wrapper
sx={({ palette }) => {
@ -88,14 +111,19 @@ const ProfileItemComp: React.FC<Props> = (props) => {
</Typography>
<IconButton
sx={{ width: 30, height: 30 }}
sx={{
width: 30,
height: 30,
animation: loading ? `1s linear infinite ${round}` : "none",
}}
color="inherit"
disabled={loading}
onClick={(e) => {
e.stopPropagation();
onUpdate();
}}
>
<MenuRounded />
<RefreshRounded />
</IconButton>
</Box>

View File

@ -1,12 +1,7 @@
import { useRef, useState } from "react";
import useSWR, { useSWRConfig } from "swr";
import { Box, Button, Grid, TextField, Typography } from "@mui/material";
import {
getProfiles,
importProfile,
putProfiles,
updateProfile,
} from "../services/cmds";
import { getProfiles, importProfile, putProfiles } from "../services/cmds";
import { getProxies } from "../services/api";
import ProfileItemComp from "../components/profile-item";
import useNotice from "../utils/use-notice";
@ -54,16 +49,6 @@ const ProfilePage = () => {
});
};
const onUpdateProfile = (index: number) => {
updateProfile(index)
.then(() => {
mutate("getProfiles");
})
.catch((err) => {
console.error(err);
});
};
return (
<Box sx={{ width: 0.9, maxWidth: "850px", mx: "auto", mb: 2 }}>
<Typography variant="h4" component="h1" sx={{ py: 2, mb: 1 }}>
@ -94,10 +79,10 @@ const ProfilePage = () => {
{profiles?.items?.map((item, idx) => (
<Grid item xs={12} sm={6} key={item.file}>
<ProfileItemComp
index={idx}
selected={profiles.current === idx}
itemData={item}
onClick={() => onProfileChange(idx)}
onUpdate={() => onUpdateProfile(idx)}
/>
</Grid>
))}