feat: refactor

This commit is contained in:
GyDi
2022-08-12 03:20:55 +08:00
parent ff6abf08b7
commit 142a62e371
22 changed files with 320 additions and 778 deletions

View File

@@ -1,29 +1,13 @@
import useSWR from "swr";
import { useState } from "react";
import { useLockFn } from "ahooks";
import {
Box,
Divider,
Grid,
IconButton,
ListItemIcon,
ListItemText,
Menu,
MenuItem,
Stack,
} from "@mui/material";
import {
AddchartRounded,
CheckRounded,
MenuRounded,
RestartAltRounded,
} from "@mui/icons-material";
import { Box, Grid, IconButton, Stack } from "@mui/material";
import { RestartAltRounded } from "@mui/icons-material";
import {
getProfiles,
deleteProfile,
enhanceProfiles,
changeProfileChain,
changeProfileValid,
getRuntimeLogs,
} from "@/services/cmds";
import ProfileMore from "./profile-more";
import Notice from "../base/base-notice";
@@ -36,10 +20,8 @@ interface Props {
const EnhancedMode = (props: Props) => {
const { items, chain } = props;
const { data, mutate } = useSWR("getProfiles", getProfiles);
const valid = data?.valid || [];
const [anchorEl, setAnchorEl] = useState<any>(null);
const { mutate: mutateProfiles } = useSWR("getProfiles", getProfiles);
const { data: chainLogs = {} } = useSWR("getRuntimeLogs", getRuntimeLogs);
// handler
const onEnhance = useLockFn(async () => {
@@ -56,7 +38,7 @@ const EnhancedMode = (props: Props) => {
const newChain = [...chain, uid];
await changeProfileChain(newChain);
mutate((conf = {}) => ({ ...conf, chain: newChain }), true);
mutateProfiles((conf = {}) => ({ ...conf, chain: newChain }), true);
});
const onEnhanceDisable = useLockFn(async (uid: string) => {
@@ -64,14 +46,14 @@ const EnhancedMode = (props: Props) => {
const newChain = chain.filter((i) => i !== uid);
await changeProfileChain(newChain);
mutate((conf = {}) => ({ ...conf, chain: newChain }), true);
mutateProfiles((conf = {}) => ({ ...conf, chain: newChain }), true);
});
const onEnhanceDelete = useLockFn(async (uid: string) => {
try {
await onEnhanceDisable(uid);
await deleteProfile(uid);
mutate();
mutateProfiles();
} catch (err: any) {
Notice.error(err?.message || err.toString());
}
@@ -82,7 +64,7 @@ const EnhancedMode = (props: Props) => {
const newChain = [uid].concat(chain.filter((i) => i !== uid));
await changeProfileChain(newChain);
mutate((conf = {}) => ({ ...conf, chain: newChain }), true);
mutateProfiles((conf = {}) => ({ ...conf, chain: newChain }), true);
});
const onMoveEnd = useLockFn(async (uid: string) => {
@@ -90,20 +72,7 @@ const EnhancedMode = (props: Props) => {
const newChain = chain.filter((i) => i !== uid).concat([uid]);
await changeProfileChain(newChain);
mutate((conf = {}) => ({ ...conf, chain: newChain }), true);
});
// update valid list
const onToggleValid = useLockFn(async (key: string) => {
try {
const newValid = valid.includes(key)
? valid.filter((i) => i !== key)
: valid.concat(key);
await changeProfileValid(newValid);
mutate();
} catch (err: any) {
Notice.error(err.message || err.toString());
}
mutateProfiles((conf = {}) => ({ ...conf, chain: newChain }), true);
});
return (
@@ -123,72 +92,6 @@ const EnhancedMode = (props: Props) => {
>
<RestartAltRounded />
</IconButton>
<IconButton
size="small"
color="inherit"
id="profile-use-button"
title="enable clash fields"
aria-controls={!!anchorEl ? "profile-use-menu" : undefined}
aria-haspopup="true"
aria-expanded={!!anchorEl ? "true" : undefined}
onClick={(e) => setAnchorEl(e.currentTarget)}
>
<MenuRounded />
</IconButton>
<Menu
id="profile-use-menu"
open={!!anchorEl}
anchorEl={anchorEl}
onClose={() => setAnchorEl(null)}
transitionDuration={225}
MenuListProps={{
dense: true,
"aria-labelledby": "profile-use-button",
}}
onContextMenu={(e) => {
setAnchorEl(null);
e.preventDefault();
}}
>
<MenuItem>
<ListItemIcon color="inherit">
<AddchartRounded />
</ListItemIcon>
Use Clash Fields
</MenuItem>
<Divider />
{[
"tun",
"dns",
"hosts",
"script",
"profile",
"payload",
"interface-name",
"routing-mark",
].map((key) => {
const has = valid.includes(key);
return (
<MenuItem
key={key}
sx={{ width: 180 }}
onClick={() => onToggleValid(key)}
>
{has && (
<ListItemIcon color="inherit">
<CheckRounded />
</ListItemIcon>
)}
<ListItemText inset={!has}>{key}</ListItemText>
</MenuItem>
);
})}
</Menu>
</Stack>
<Grid container spacing={2}>
@@ -198,6 +101,7 @@ const EnhancedMode = (props: Props) => {
selected={!!chain.includes(item.uid)}
itemData={item}
enableNum={chain.length}
logInfo={chainLogs[item.uid]}
onEnable={() => onEnhanceEnable(item.uid)}
onDisable={() => onEnhanceDisable(item.uid)}
onDelete={() => onEnhanceDelete(item.uid)}

View File

@@ -12,7 +12,6 @@ import {
Menu,
} from "@mui/material";
import { viewProfile } from "@/services/cmds";
import enhance from "@/services/enhance";
import ProfileEdit from "./profile-edit";
import FileEditor from "./file-editor";
import Notice from "../base/base-notice";
@@ -32,6 +31,7 @@ interface Props {
selected: boolean;
itemData: CmdType.ProfileItem;
enableNum: number;
logInfo?: [string, string][];
onEnable: () => void;
onDisable: () => void;
onMoveTop: () => void;
@@ -45,6 +45,7 @@ const ProfileMore = (props: Props) => {
selected,
itemData,
enableNum,
logInfo = [],
onEnable,
onDisable,
onMoveTop,
@@ -59,13 +60,13 @@ const ProfileMore = (props: Props) => {
const [position, setPosition] = useState({ left: 0, top: 0 });
const [editOpen, setEditOpen] = useState(false);
const [fileOpen, setFileOpen] = useState(false);
const [status, setStatus] = useState(enhance.status(uid));
// const [status, setStatus] = useState(enhance.status(uid));
// unlisten when unmount
useEffect(() => enhance.listen(uid, setStatus), [uid]);
// useEffect(() => enhance.listen(uid, setStatus), [uid]);
// error during enhanced mode
const hasError = selected && status?.status === "error";
const hasError = !!logInfo.find((e) => e[0] === "exception"); // selected && status?.status === "error";
const onEditInfo = () => {
setAnchorEl(null);
@@ -188,9 +189,11 @@ const ProfileMore = (props: Props) => {
noWrap
color="error"
sx={{ width: "calc(100% - 75px)" }}
title={status.message}
// title={status.message}
title="error"
>
{status.message}
{/* {status.message} */}
error
</Typography>
) : (
<Typography

View File

@@ -13,14 +13,18 @@ import {
Tooltip,
Typography,
} from "@mui/material";
import { BuildCircleRounded, InfoRounded } from "@mui/icons-material";
import { changeProfileValid, getProfiles } from "@/services/cmds";
import { InfoRounded } from "@mui/icons-material";
import {
changeProfileValid,
getProfiles,
getRuntimeExists,
} from "@/services/cmds";
import { ModalHandler } from "@/hooks/use-modal-handler";
import enhance, {
DEFAULT_FIELDS,
import {
HANDLE_FIELDS,
USE_FLAG_FIELDS,
} from "@/services/enhance";
DEFAULT_FIELDS,
OTHERS_FIELDS,
} from "@/utils/clash-fields";
import Notice from "@/components/base/base-notice";
interface Props {
@@ -36,19 +40,21 @@ const fieldSorter = (a: string, b: string) => {
return 0;
};
const useFields = [...USE_FLAG_FIELDS].sort(fieldSorter);
const otherFields = [...OTHERS_FIELDS].sort(fieldSorter);
const handleFields = [...HANDLE_FIELDS, ...DEFAULT_FIELDS].sort(fieldSorter);
const ClashFieldViewer = ({ handler }: Props) => {
const { t } = useTranslation();
const { data, mutate } = useSWR("getProfiles", getProfiles);
const { data: existsKeys = [] } = useSWR(
"getRuntimeExists",
getRuntimeExists
);
const [open, setOpen] = useState(false);
const [selected, setSelected] = useState<string[]>([]);
const { config: enhanceConfig, use: enhanceUse } = enhance.getFieldsState();
if (handler) {
handler.current = {
open: () => setOpen(true),
@@ -61,8 +67,8 @@ const ClashFieldViewer = ({ handler }: Props) => {
}, [open]);
useEffect(() => {
setSelected([...(data?.valid || []), ...enhanceUse]);
}, [data?.valid, enhanceUse]);
setSelected(data?.valid || []);
}, [data?.valid]);
const handleChange = (item: string) => {
if (!item) return;
@@ -75,7 +81,7 @@ const ClashFieldViewer = ({ handler }: Props) => {
const handleSave = async () => {
setOpen(false);
const oldSet = new Set([...(data?.valid || []), ...enhanceUse]);
const oldSet = new Set(data?.valid || []);
const curSet = new Set(selected);
const joinSet = new Set(selected.concat([...oldSet]));
@@ -103,10 +109,9 @@ const ClashFieldViewer = ({ handler }: Props) => {
userSelect: "text",
}}
>
{useFields.map((item) => {
{otherFields.map((item) => {
const inSelect = selected.includes(item);
const inConfig = enhanceConfig.includes(item);
const inConfigUse = enhanceUse.includes(item);
const inConfig = existsKeys.includes(item);
const inValid = data?.valid?.includes(item);
return (
@@ -119,8 +124,7 @@ const ClashFieldViewer = ({ handler }: Props) => {
/>
<Typography width="100%">{item}</Typography>
{inConfigUse && !inValid && <InfoIcon />}
{!inSelect && inConfig && <WarnIcon />}
{!inSelect && inConfig && !inValid && <WarnIcon />}
</Stack>
);
})}
@@ -159,15 +163,4 @@ function WarnIcon() {
);
}
function InfoIcon() {
return (
<Tooltip title="This field is provided by Merge Profile.">
<BuildCircleRounded
color="info"
sx={{ cursor: "pointer", opacity: 0.5 }}
/>
</Tooltip>
);
}
export default ClashFieldViewer;

View File

@@ -10,8 +10,8 @@ import {
DialogTitle,
} from "@mui/material";
import { InfoRounded } from "@mui/icons-material";
import { atomThemeMode } from "../../../services/states";
import { getRunningConfig } from "../../../services/cmds";
import { atomThemeMode } from "@/services/states";
import { getRuntimeYaml } from "@/services/cmds";
import "monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution.js";
import "monaco-editor/esm/vs/basic-languages/yaml/yaml.contribution.js";
@@ -29,7 +29,7 @@ const ConfigViewer = () => {
useEffect(() => {
if (!open) return;
getRunningConfig().then((data) => {
getRuntimeYaml().then((data) => {
const dom = editorRef.current;
if (!dom) return;
@@ -56,7 +56,7 @@ const ConfigViewer = () => {
<>
<Dialog open={open} onClose={() => setOpen(false)}>
<DialogTitle>
{t("Running Config")} <Chip label="ReadOnly" size="small" />
{t("Runtime Config")} <Chip label="ReadOnly" size="small" />
</DialogTitle>
<DialogContent sx={{ width: 520, pb: 1 }}>