feat: Confirm before deletion

#703
This commit is contained in:
MystiPanda 2024-03-21 11:39:01 +08:00
parent ae46332e42
commit f435762b88
4 changed files with 121 additions and 7 deletions

View File

@ -0,0 +1,46 @@
import { useEffect, useRef } from "react";
import { useTranslation } from "react-i18next";
import {
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
} from "@mui/material";
interface Props {
open: boolean;
title: string;
message: string;
onClose: () => void;
onConfirm: () => void;
}
export const ConfirmViewer = (props: Props) => {
const { open, title, message, onClose, onConfirm } = props;
const { t } = useTranslation();
useEffect(() => {
if (!open) return;
}, [open]);
return (
<Dialog open={open} onClose={onClose} maxWidth="xs" fullWidth>
<DialogTitle>{t(title)}</DialogTitle>
<DialogContent sx={{ width: "95%", pb: 1, userSelect: "text" }}>
{t(message)}
</DialogContent>
<DialogActions>
<Button onClick={onClose} variant="outlined">
{t("Cancel")}
</Button>
<Button onClick={onConfirm} variant="contained">
{t("Confirm")}
</Button>
</DialogActions>
</Dialog>
);
};

View File

@ -23,6 +23,7 @@ import { Notice } from "@/components/base";
import { EditorViewer } from "./editor-viewer"; import { EditorViewer } from "./editor-viewer";
import { ProfileBox } from "./profile-box"; import { ProfileBox } from "./profile-box";
import parseTraffic from "@/utils/parse-traffic"; import parseTraffic from "@/utils/parse-traffic";
import { ConfirmViewer } from "./confirm-viewer";
const round = keyframes` const round = keyframes`
from { transform: rotate(0deg); } from { transform: rotate(0deg); }
@ -92,6 +93,7 @@ export const ProfileItem = (props: Props) => {
}, [hasUrl, updated]); }, [hasUrl, updated]);
const [fileOpen, setFileOpen] = useState(false); const [fileOpen, setFileOpen] = useState(false);
const [confirmOpen, setConfirmOpen] = useState(false);
const onEditInfo = () => { const onEditInfo = () => {
setAnchorEl(null); setAnchorEl(null);
@ -171,14 +173,24 @@ export const ProfileItem = (props: Props) => {
{ label: "Open File", handler: onOpenFile }, { label: "Open File", handler: onOpenFile },
{ label: "Update", handler: () => onUpdate(0) }, { label: "Update", handler: () => onUpdate(0) },
{ label: "Update(Proxy)", handler: () => onUpdate(2) }, { label: "Update(Proxy)", handler: () => onUpdate(2) },
{ label: "Delete", handler: onDelete }, {
label: "Delete",
handler: () => {
setConfirmOpen(true);
},
},
]; ];
const fileModeMenu = [ const fileModeMenu = [
{ label: "Select", handler: onForceSelect }, { label: "Select", handler: onForceSelect },
{ label: "Edit Info", handler: onEditInfo }, { label: "Edit Info", handler: onEditInfo },
{ label: "Edit File", handler: onEditFile }, { label: "Edit File", handler: onEditFile },
{ label: "Open File", handler: onOpenFile }, { label: "Open File", handler: onOpenFile },
{ label: "Delete", handler: onDelete }, {
label: "Delete",
handler: () => {
setConfirmOpen(true);
},
},
]; ];
const boxStyle = { const boxStyle = {
@ -341,7 +353,19 @@ export const ProfileItem = (props: Props) => {
<MenuItem <MenuItem
key={item.label} key={item.label}
onClick={item.handler} onClick={item.handler}
sx={{ minWidth: 120 }} sx={[
{
minWidth: 120,
},
(theme) => {
return {
color:
item.label === "Delete"
? theme.palette.error.main
: undefined,
};
},
]}
dense dense
> >
{t(item.label)} {t(item.label)}
@ -355,6 +379,16 @@ export const ProfileItem = (props: Props) => {
mode="yaml" mode="yaml"
onClose={() => setFileOpen(false)} onClose={() => setFileOpen(false)}
/> />
<ConfirmViewer
title="Confirm deletion"
message="This operation is not reversible"
open={confirmOpen}
onClose={() => setConfirmOpen(false)}
onConfirm={() => {
onDelete();
setConfirmOpen(false);
}}
/>
</Box> </Box>
); );
}; };

View File

@ -17,6 +17,7 @@ import { Notice } from "@/components/base";
import { EditorViewer } from "./editor-viewer"; import { EditorViewer } from "./editor-viewer";
import { ProfileBox } from "./profile-box"; import { ProfileBox } from "./profile-box";
import { LogViewer } from "./log-viewer"; import { LogViewer } from "./log-viewer";
import { ConfirmViewer } from "./confirm-viewer";
interface Props { interface Props {
selected: boolean; selected: boolean;
@ -51,6 +52,7 @@ export const ProfileMore = (props: Props) => {
const [anchorEl, setAnchorEl] = useState<any>(null); const [anchorEl, setAnchorEl] = useState<any>(null);
const [position, setPosition] = useState({ left: 0, top: 0 }); const [position, setPosition] = useState({ left: 0, top: 0 });
const [fileOpen, setFileOpen] = useState(false); const [fileOpen, setFileOpen] = useState(false);
const [confirmOpen, setConfirmOpen] = useState(false);
const [logOpen, setLogOpen] = useState(false); const [logOpen, setLogOpen] = useState(false);
const onEditInfo = () => { const onEditInfo = () => {
@ -87,7 +89,12 @@ export const ProfileMore = (props: Props) => {
{ label: "Open File", handler: onOpenFile }, { label: "Open File", handler: onOpenFile },
{ label: "To Top", show: showMove, handler: fnWrapper(onMoveTop) }, { label: "To Top", show: showMove, handler: fnWrapper(onMoveTop) },
{ label: "To End", show: showMove, handler: fnWrapper(onMoveEnd) }, { label: "To End", show: showMove, handler: fnWrapper(onMoveEnd) },
{ label: "Delete", handler: fnWrapper(onDelete) }, {
label: "Delete",
handler: () => {
setConfirmOpen(true);
},
},
]; ];
const disableMenu = [ const disableMenu = [
@ -95,7 +102,12 @@ export const ProfileMore = (props: Props) => {
{ label: "Edit Info", handler: onEditInfo }, { label: "Edit Info", handler: onEditInfo },
{ label: "Edit File", handler: onEditFile }, { label: "Edit File", handler: onEditFile },
{ label: "Open File", handler: onOpenFile }, { label: "Open File", handler: onOpenFile },
{ label: "Delete", handler: fnWrapper(onDelete) }, {
label: "Delete",
handler: () => {
setConfirmOpen(true);
},
},
]; ];
const boxStyle = { const boxStyle = {
@ -200,7 +212,17 @@ export const ProfileMore = (props: Props) => {
<MenuItem <MenuItem
key={item.label} key={item.label}
onClick={item.handler} onClick={item.handler}
sx={{ minWidth: 120 }} sx={[
{ minWidth: 120 },
(theme) => {
return {
color:
item.label === "Delete"
? theme.palette.error.main
: undefined,
};
},
]}
dense dense
> >
{t(item.label)} {t(item.label)}
@ -214,7 +236,16 @@ export const ProfileMore = (props: Props) => {
mode={type === "merge" ? "yaml" : "javascript"} mode={type === "merge" ? "yaml" : "javascript"}
onClose={() => setFileOpen(false)} onClose={() => setFileOpen(false)}
/> />
<ConfirmViewer
title="Confirm deletion"
message="This operation is not reversible"
open={confirmOpen}
onClose={() => setConfirmOpen(false)}
onConfirm={() => {
onDelete();
setConfirmOpen(false);
}}
/>
{selected && ( {selected && (
<LogViewer <LogViewer
open={logOpen} open={logOpen}

View File

@ -45,6 +45,8 @@
"Update All Profiles": "更新所有订阅", "Update All Profiles": "更新所有订阅",
"View Runtime Config": "查看运行时订阅", "View Runtime Config": "查看运行时订阅",
"Reactivate Profiles": "重新激活订阅", "Reactivate Profiles": "重新激活订阅",
"Confirm deletion": "确认删除",
"This operation is not reversible": "此操作不可逆",
"Location": "当前节点", "Location": "当前节点",
"Delay check": "延迟测试", "Delay check": "延迟测试",
@ -138,6 +140,7 @@
"Save": "保存", "Save": "保存",
"Cancel": "取消", "Cancel": "取消",
"Exit": "退出", "Exit": "退出",
"Confirm": "确认",
"Default": "默认", "Default": "默认",
"Download Speed": "下载速度", "Download Speed": "下载速度",