diff --git a/src/components/profile-item.tsx b/src/components/profile-item.tsx index fb6f021..6f1f70f 100644 --- a/src/components/profile-item.tsx +++ b/src/components/profile-item.tsx @@ -8,13 +8,15 @@ import { LinearProgress, IconButton, keyframes, + MenuItem, + Menu, } from "@mui/material"; import { useSWRConfig } from "swr"; import { RefreshRounded } from "@mui/icons-material"; import { CmdType } from "../services/types"; +import { updateProfile, deleteProfile } from "../services/cmds"; import parseTraffic from "../utils/parse-traffic"; import relativeTime from "dayjs/plugin/relativeTime"; -import { updateProfile } from "../services/cmds"; dayjs.extend(relativeTime); @@ -46,6 +48,8 @@ const ProfileItemComp: React.FC = (props) => { const { mutate } = useSWRConfig(); const [loading, setLoading] = useState(false); + const [anchorEl, setAnchorEl] = useState(null); + const [position, setPosition] = useState({ left: 0, top: 0 }); const { name = "Profile", extra, updated = 0 } = itemData; const { upload = 0, download = 0, total = 0 } = extra ?? {}; @@ -55,6 +59,7 @@ const ProfileItemComp: React.FC = (props) => { const fromnow = updated > 0 ? dayjs(updated * 1000).fromNow() : ""; const onUpdate = async () => { + setAnchorEl(null); if (loading) return; setLoading(true); try { @@ -67,98 +72,135 @@ const ProfileItemComp: React.FC = (props) => { } }; + const onDelete = async () => { + setAnchorEl(null); + try { + await deleteProfile(index); + mutate("getProfiles"); + } catch (err) { + console.error(err); + } + }; + + const handleContextMenu = ( + event: React.MouseEvent + ) => { + const { clientX, clientY } = event; + setPosition({ top: clientY, left: clientX }); + setAnchorEl(event.currentTarget); + event.preventDefault(); + }; + return ( - { - const { mode, primary, text, grey } = palette; - const isDark = mode === "dark"; + <> + { + const { mode, primary, text, grey } = palette; + const key = `${mode}-${selected}`; - if (selected) { - const bgcolor = isDark - ? alpha(primary.main, 0.35) - : alpha(primary.main, 0.15); + const bgcolor = { + "light-true": alpha(primary.main, 0.15), + "light-false": palette.background.paper, + "dark-true": alpha(primary.main, 0.35), + "dark-false": alpha(grey[700], 0.35), + }[key]!; - return { - bgcolor, - color: isDark ? alpha(text.secondary, 0.6) : text.secondary, - "& h2": { - color: isDark ? primary.light : primary.main, - }, - }; - } - const bgcolor = isDark - ? alpha(grey[700], 0.35) - : palette.background.paper; - return { - bgcolor, - color: isDark ? alpha(text.secondary, 0.6) : text.secondary, - "& h2": { - color: isDark ? text.primary : text.primary, - }, - }; - }} - onClick={onClick} - > - - - {name} - + const color = { + "light-true": text.secondary, + "light-false": text.secondary, + "dark-true": alpha(text.secondary, 0.6), + "dark-false": alpha(text.secondary, 0.6), + }[key]!; - { - e.stopPropagation(); - onUpdate(); - }} - > - - - + const h2color = { + "light-true": primary.main, + "light-false": text.primary, + "dark-true": primary.light, + "dark-false": text.primary, + }[key]!; - - - {from} - - - - {fromnow} - - - - - - {parseTraffic(upload + download)} / {parseTraffic(total)} - - {expire} - + + + {name} + - - + { + e.stopPropagation(); + onUpdate(); + }} + > + + + + + + + {from} + + + + {fromnow} + + + + + + {parseTraffic(upload + download)} / {parseTraffic(total)} + + {expire} + + + + + + setAnchorEl(null)} + anchorPosition={position} + anchorReference="anchorPosition" + > + Update + Delete + {/* Update(proxy) */} + + ); }; diff --git a/src/pages/profile.tsx b/src/pages/profile.tsx index e374509..adeef37 100644 --- a/src/pages/profile.tsx +++ b/src/pages/profile.tsx @@ -24,16 +24,20 @@ const ProfilePage = () => { if (profiles.current == null) return; if (!profiles.items) profiles.items = []; - const profile = profiles.items![profiles.current]; + const current = profiles.current; + const profile = profiles.items![current]; if (!profile) return; - getProxies().then((proxiesData) => { + setTimeout(async () => { + const proxiesData = await getProxies(); mutate("getProxies", proxiesData); + // init selected array const { selected = [] } = profile; const selectedMap = Object.fromEntries( selected.map((each) => [each.name!, each.now!]) ); + // todo: enhance error handle let hasChange = false; proxiesData.groups.forEach((group) => { @@ -52,10 +56,10 @@ const ProfilePage = () => { name, now, })); - patchProfile(profiles.current!, profile).catch(console.error); + patchProfile(current!, profile).catch(console.error); // update proxies cache if (hasChange) mutate("getProxies", getProxies()); - }); + }, 100); }, [profiles]); const onImport = async () => {