From ad35ed96c863db74213db80adf67280f46af6dc5 Mon Sep 17 00:00:00 2001 From: Eric Huang Date: Sun, 9 Jun 2024 06:26:07 +0800 Subject: [PATCH] feat(settings page): add loading state (#1157) * feat(settings page): add loading state * fix: type --- src/components/setting/mods/setting-comp.tsx | 26 +++++++++++++++++--- src/components/setting/setting-clash.tsx | 4 +-- src/components/setting/setting-verge.tsx | 4 +-- src/utils/is-async-function.ts | 3 +++ 4 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 src/utils/is-async-function.ts diff --git a/src/components/setting/mods/setting-comp.tsx b/src/components/setting/mods/setting-comp.tsx index a2dbdf6..87cf3f3 100644 --- a/src/components/setting/mods/setting-comp.tsx +++ b/src/components/setting/mods/setting-comp.tsx @@ -1,4 +1,4 @@ -import React, { ReactNode } from "react"; +import React, { ReactNode, useState } from "react"; import { Box, List, @@ -8,13 +8,15 @@ import { ListSubheader, } from "@mui/material"; import { ChevronRightRounded } from "@mui/icons-material"; +import CircularProgress from "@mui/material/CircularProgress"; +import isAsyncFunction from "@/utils/is-async-function"; interface ItemProps { label: ReactNode; extra?: ReactNode; children?: ReactNode; secondary?: ReactNode; - onClick?: () => void; + onClick?: () => void | Promise; } export const SettingItem: React.FC = (props) => { @@ -28,11 +30,27 @@ export const SettingItem: React.FC = (props) => { ); + const [isLoading, setIsLoading] = useState(false); + const handleClick = () => { + if (onClick) { + if (isAsyncFunction(onClick)) { + setIsLoading(true); + onClick()!.finally(() => setIsLoading(false)); + } else { + onClick(); + } + } + }; + return clickable ? ( - + - + {isLoading ? ( + + ) : ( + + )} ) : ( diff --git a/src/components/setting/setting-clash.tsx b/src/components/setting/setting-clash.tsx index 651982d..41657cc 100644 --- a/src/components/setting/setting-clash.tsx +++ b/src/components/setting/setting-clash.tsx @@ -51,14 +51,14 @@ const SettingClash = ({ onError }: Props) => { const onChangeVerge = (patch: Partial) => { mutateVerge({ ...verge, ...patch }, false); }; - const onUpdateGeo = useLockFn(async () => { + const onUpdateGeo = async () => { try { await updateGeoData(); Notice.success(t("GeoData Updated")); } catch (err: any) { Notice.error(err?.response.data.message || err.toString()); } - }); + }; return ( diff --git a/src/components/setting/setting-verge.tsx b/src/components/setting/setting-verge.tsx index 2b2bc9f..e5d82fb 100644 --- a/src/components/setting/setting-verge.tsx +++ b/src/components/setting/setting-verge.tsx @@ -55,7 +55,7 @@ const SettingVerge = ({ onError }: Props) => { mutateVerge({ ...verge, ...patch }, false); }; - const onCheckUpdate = useLockFn(async () => { + const onCheckUpdate = async () => { try { const info = await checkUpdate(); if (!info?.shouldUpdate) { @@ -66,7 +66,7 @@ const SettingVerge = ({ onError }: Props) => { } catch (err: any) { Notice.error(err.message || err.toString()); } - }); + }; return ( diff --git a/src/utils/is-async-function.ts b/src/utils/is-async-function.ts new file mode 100644 index 0000000..e865115 --- /dev/null +++ b/src/utils/is-async-function.ts @@ -0,0 +1,3 @@ +export default function isAsyncFunction(fn: Function): boolean { + return fn.constructor.name === "AsyncFunction"; +}