Skip to content
This repository has been archived by the owner on Nov 3, 2023. It is now read-only.

Commit

Permalink
feat: profile loading animation
Browse files Browse the repository at this point in the history
  • Loading branch information
zzzgydi committed Dec 26, 2021
1 parent cc96b5a commit 2fdcc9c
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 24 deletions.
42 changes: 35 additions & 7 deletions src/components/profile-item.tsx
Original file line number Diff line number Diff line change
@@ -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);

Expand All @@ -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 ?? {};
Expand All @@ -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 }) => {
Expand Down Expand Up @@ -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>

Expand Down
19 changes: 2 additions & 17 deletions src/pages/profile.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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 }}>
Expand Down Expand Up @@ -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>
))}
Expand Down

0 comments on commit 2fdcc9c

Please sign in to comment.