feat: adjust proxy page

This commit is contained in:
GyDi 2022-01-13 02:51:30 +08:00
parent 4979a472de
commit 5fcd25506e
3 changed files with 83 additions and 54 deletions

View File

@ -1,15 +1,12 @@
import { useState } from "react"; import { useState } from "react";
import { Virtuoso } from "react-virtuoso"; import { Virtuoso } from "react-virtuoso";
import { import {
alpha,
Box, Box,
Collapse, Collapse,
Divider, Divider,
IconButton, IconButton,
List, List,
ListItem, ListItem,
ListItemButton,
ListItemIcon,
ListItemText, ListItemText,
} from "@mui/material"; } from "@mui/material";
import { import {
@ -18,53 +15,11 @@ import {
ExpandMoreRounded, ExpandMoreRounded,
MyLocationRounded, MyLocationRounded,
NetworkCheckRounded, NetworkCheckRounded,
CheckCircleOutlineRounded,
} from "@mui/icons-material"; } from "@mui/icons-material";
import { updateProxy } from "../services/api"; import { updateProxy } from "../services/api";
import { ApiType } from "../services/types"; import { ApiType } from "../services/types";
import { getProfiles, patchProfile } from "../services/cmds"; import { getProfiles, patchProfile } from "../services/cmds";
import ProxyItem from "./proxy-item";
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>
);
};
interface Props { interface Props {
group: ApiType.ProxyGroupItem; group: ApiType.ProxyGroupItem;
@ -146,9 +101,10 @@ const ProxyGroup = ({ group }: Props) => {
style={{ height: "400px", marginBottom: "4px" }} style={{ height: "400px", marginBottom: "4px" }}
totalCount={proxies.length} totalCount={proxies.length}
itemContent={(index) => ( itemContent={(index) => (
<Item <ProxyItem
proxy={proxies[index]} proxy={proxies[index]}
selected={proxies[index].name === now} selected={proxies[index].name === now}
sx={{ py: 0, pl: 4 }}
onClick={onUpdate} onClick={onUpdate}
/> />
)} )}
@ -160,10 +116,11 @@ const ProxyGroup = ({ group }: Props) => {
sx={{ maxHeight: "400px", overflow: "auto", mb: "4px" }} sx={{ maxHeight: "400px", overflow: "auto", mb: "4px" }}
> >
{proxies.map((proxy) => ( {proxies.map((proxy) => (
<Item <ProxyItem
key={proxy.name} key={proxy.name}
proxy={proxy} proxy={proxy}
selected={proxy.name === now} selected={proxy.name === now}
sx={{ py: 0, pl: 4 }}
onClick={onUpdate} onClick={onUpdate}
/> />
))} ))}

View File

@ -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;

View File

@ -3,11 +3,12 @@ import { useEffect } from "react";
import { Box, List, Paper, Typography } from "@mui/material"; import { Box, List, Paper, Typography } from "@mui/material";
import { getProxies } from "../services/api"; import { getProxies } from "../services/api";
import ProxyGroup from "../components/proxy-group"; import ProxyGroup from "../components/proxy-group";
import ProxyItem from "../components/proxy-item";
const ProxyPage = () => { const ProxyPage = () => {
const { mutate } = useSWRConfig(); const { mutate } = useSWRConfig();
const { data: proxiesData } = useSWR("getProxies", getProxies); const { data: proxiesData } = useSWR("getProxies", getProxies);
const { groups = [] } = proxiesData ?? {}; const { groups = [], proxies = [] } = proxiesData ?? {};
useEffect(() => { useEffect(() => {
// fix the empty proxies on the first sight // fix the empty proxies on the first sight
@ -20,18 +21,31 @@ const ProxyPage = () => {
return ( return (
<Box sx={{ width: 0.9, maxWidth: "850px", mx: "auto", mb: 2 }}> <Box sx={{ width: 0.9, maxWidth: "850px", mx: "auto", mb: 2 }}>
<Typography variant="h4" component="h1" sx={{ py: 2 }}> <Typography variant="h4" component="h1" sx={{ py: 2 }}>
Proxy Groups {groups.length ? "Proxy Groups" : "Proxies"}
</Typography> </Typography>
{groups.length > 0 && ( <Paper sx={{ borderRadius: 1, boxShadow: 2 }}>
<Paper sx={{ borderRadius: 1, boxShadow: 2 }}> {groups.length > 0 && (
<List> <List>
{groups.map((group) => ( {groups.map((group) => (
<ProxyGroup key={group.name} group={group} /> <ProxyGroup key={group.name} group={group} />
))} ))}
</List> </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> </Box>
); );
}; };