feat: support to grant permission to clash core

This commit is contained in:
GyDi
2023-03-16 11:16:54 +08:00
parent fdcbc3904a
commit 9e2812d55c
7 changed files with 177 additions and 3 deletions

View File

@@ -0,0 +1,106 @@
import { mutate } from "swr";
import { forwardRef, useImperativeHandle, useState } from "react";
import { BaseDialog, DialogRef, Notice } from "@/components/base";
import { useTranslation } from "react-i18next";
import { useVerge } from "@/hooks/use-verge";
import { useLockFn } from "ahooks";
import { Lock } from "@mui/icons-material";
import { IconButton, List, ListItemButton, ListItemText } from "@mui/material";
import { changeClashCore } from "@/services/cmds";
import { closeAllConnections } from "@/services/api";
import { grantPermission } from "@/services/cmds";
import getSystem from "@/utils/get-system";
const VALID_CORE = [
{ name: "Clash", core: "clash" },
{ name: "Clash Meta", core: "clash-meta" },
];
const OS = getSystem();
export const ClashCoreViewer = forwardRef<DialogRef>((props, ref) => {
const { t } = useTranslation();
const { verge, mutateVerge } = useVerge();
const [open, setOpen] = useState(false);
useImperativeHandle(ref, () => ({
open: () => setOpen(true),
close: () => setOpen(false),
}));
const { clash_core = "clash" } = verge ?? {};
const onCoreChange = useLockFn(async (core: string) => {
if (core === clash_core) return;
try {
closeAllConnections();
await changeClashCore(core);
mutateVerge();
setTimeout(() => {
mutate("getClashConfig");
mutate("getVersion");
}, 100);
Notice.success(`Successfully switch to ${core}`, 1000);
} catch (err: any) {
Notice.error(err?.message || err.toString());
}
});
const onGrant = useLockFn(async (core: string) => {
try {
await grantPermission(core);
Notice.success(`Successfully grant permission to ${core}`, 1000);
} catch (err: any) {
Notice.error(err?.message || err.toString());
}
});
return (
<BaseDialog
open={open}
title={t("Clash Core")}
contentSx={{
pb: 0,
width: 320,
height: 200,
overflowY: "auto",
userSelect: "text",
marginTop: "-8px",
}}
disableOk
cancelBtn={t("Back")}
onClose={() => setOpen(false)}
onCancel={() => setOpen(false)}
>
<List component="nav">
{VALID_CORE.map((each) => (
<ListItemButton
key={each.core}
selected={each.core === clash_core}
onClick={() => onCoreChange(each.core)}
>
<ListItemText primary={each.name} secondary={`/${each.core}`} />
{(OS === "macos" || OS === "linux") && (
<IconButton
color="inherit"
size="small"
edge="end"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
onGrant(each.core);
}}
>
<Lock fontSize="inherit" />
</IconButton>
)}
</ListItemButton>
))}
</List>
</BaseDialog>
);
});