diff --git a/src/components/proxy-group.tsx b/src/components/proxy-group.tsx index 090539a00932fca7df04ed3e44cb0b0b0caaf0a2..e901c7706f8ef1d3a39d564369541529a6bb88fe 100644 --- a/src/components/proxy-group.tsx +++ b/src/components/proxy-group.tsx @@ -1,15 +1,12 @@ import { useState } from "react"; import { Virtuoso } from "react-virtuoso"; import { - alpha, Box, Collapse, Divider, IconButton, List, ListItem, - ListItemButton, - ListItemIcon, ListItemText, } from "@mui/material"; import { @@ -18,53 +15,11 @@ import { ExpandMoreRounded, MyLocationRounded, NetworkCheckRounded, - CheckCircleOutlineRounded, } from "@mui/icons-material"; import { updateProxy } from "../services/api"; import { ApiType } from "../services/types"; import { getProfiles, patchProfile } from "../services/cmds"; - -interface ItemProps { - proxy: ApiType.ProxyItem; - selected: boolean; - onClick?: (name: string) => void; -} - -const Item = ({ proxy, selected, onClick }: ItemProps) => { - return ( - <ListItem sx={{ py: 0, pl: 4 }}> - <ListItemButton - dense - selected={selected} - onClick={() => onClick?.(proxy.name)} - sx={[ - { - borderRadius: 1, - }, - ({ palette: { mode, primary } }) => { - const bgcolor = - mode === "light" - ? alpha(primary.main, 0.15) - : alpha(primary.main, 0.35); - const color = mode === "light" ? primary.main : primary.light; - - return { - "&.Mui-selected": { bgcolor }, - "&.Mui-selected .MuiListItemText-secondary": { color }, - }; - }, - ]} - > - <ListItemText title={proxy.name} secondary={proxy.name} /> - <ListItemIcon - sx={{ justifyContent: "flex-end", color: "primary.main" }} - > - {selected && <CheckCircleOutlineRounded sx={{ fontSize: 16 }} />} - </ListItemIcon> - </ListItemButton> - </ListItem> - ); -}; +import ProxyItem from "./proxy-item"; interface Props { group: ApiType.ProxyGroupItem; @@ -146,9 +101,10 @@ const ProxyGroup = ({ group }: Props) => { style={{ height: "400px", marginBottom: "4px" }} totalCount={proxies.length} itemContent={(index) => ( - <Item + <ProxyItem proxy={proxies[index]} selected={proxies[index].name === now} + sx={{ py: 0, pl: 4 }} onClick={onUpdate} /> )} @@ -160,10 +116,11 @@ const ProxyGroup = ({ group }: Props) => { sx={{ maxHeight: "400px", overflow: "auto", mb: "4px" }} > {proxies.map((proxy) => ( - <Item + <ProxyItem key={proxy.name} proxy={proxy} selected={proxy.name === now} + sx={{ py: 0, pl: 4 }} onClick={onUpdate} /> ))} diff --git a/src/components/proxy-item.tsx b/src/components/proxy-item.tsx new file mode 100644 index 0000000000000000000000000000000000000000..6e90a2cce0b2d6461f6484710badc1fcdf270dc3 --- /dev/null +++ b/src/components/proxy-item.tsx @@ -0,0 +1,58 @@ +import { CheckCircleOutlineRounded } from "@mui/icons-material"; +import { + alpha, + ListItem, + ListItemButton, + ListItemIcon, + ListItemText, + SxProps, + Theme, +} from "@mui/material"; +import { ApiType } from "../services/types"; + +interface Props { + proxy: ApiType.ProxyItem; + selected: boolean; + sx?: SxProps<Theme>; + onClick?: (name: string) => void; +} + +const ProxyItem = (props: Props) => { + const { proxy, selected, sx, onClick } = props; + + return ( + <ListItem sx={sx}> + <ListItemButton + dense + selected={selected} + onClick={() => onClick?.(proxy.name)} + sx={[ + { + borderRadius: 1, + }, + ({ palette: { mode, primary } }) => { + const bgcolor = + mode === "light" + ? alpha(primary.main, 0.15) + : alpha(primary.main, 0.35); + const color = mode === "light" ? primary.main : primary.light; + + return { + "&.Mui-selected": { bgcolor }, + "&.Mui-selected .MuiListItemText-secondary": { color }, + }; + }, + ]} + > + <ListItemText title={proxy.name} secondary={proxy.name} /> + <ListItemIcon + sx={{ justifyContent: "flex-end", color: "primary.main" }} + > + {selected && <CheckCircleOutlineRounded sx={{ fontSize: 16 }} />} + </ListItemIcon> + </ListItemButton> + </ListItem> + ); +}; + +export default ProxyItem; diff --git a/src/pages/proxy.tsx b/src/pages/proxy.tsx index 6e2fc86ff6b4e5b4e826efda7ae97419dfb881fc..02e5b0f0d0f4ca0d393e574870c6c0b7670b9055 100644 --- a/src/pages/proxy.tsx +++ b/src/pages/proxy.tsx @@ -3,11 +3,12 @@ import { useEffect } from "react"; import { Box, List, Paper, Typography } from "@mui/material"; import { getProxies } from "../services/api"; import ProxyGroup from "../components/proxy-group"; +import ProxyItem from "../components/proxy-item"; const ProxyPage = () => { const { mutate } = useSWRConfig(); const { data: proxiesData } = useSWR("getProxies", getProxies); - const { groups = [] } = proxiesData ?? {}; + const { groups = [], proxies = [] } = proxiesData ?? {}; useEffect(() => { // fix the empty proxies on the first sight @@ -20,18 +21,31 @@ const ProxyPage = () => { return ( <Box sx={{ width: 0.9, maxWidth: "850px", mx: "auto", mb: 2 }}> <Typography variant="h4" component="h1" sx={{ py: 2 }}> - Proxy Groups + {groups.length ? "Proxy Groups" : "Proxies"} </Typography> - {groups.length > 0 && ( - <Paper sx={{ borderRadius: 1, boxShadow: 2 }}> + <Paper sx={{ borderRadius: 1, boxShadow: 2 }}> + {groups.length > 0 && ( <List> {groups.map((group) => ( <ProxyGroup key={group.name} group={group} /> ))} </List> - </Paper> - )} + )} + + {!groups.length && ( + <List> + {Object.values(proxies).map((proxy) => ( + <ProxyItem + key={proxy.name} + proxy={proxy} + selected={false} + sx={{ py: 0, px: 2 }} + /> + ))} + </List> + )} + </Paper> </Box> ); };