import { RestartAltRounded, SwitchAccessShortcutRounded, } from "@mui/icons-material"; import { LoadingButton } from "@mui/lab"; import { Box, Chip, CircularProgress, List, ListItemButton, ListItemText, } from "@mui/material"; import { useLockFn } from "ahooks"; import type { Ref } from "react"; import { useImperativeHandle, useState } from "react"; import { useTranslation } from "react-i18next"; import { mutate } from "swr"; import { closeAllConnections, upgradeCore } from "tauri-plugin-mihomo-api"; import { BaseDialog, DialogRef } from "@/components/base"; import { useVerge } from "@/hooks/use-verge"; import { changeClashCore, restartCore } from "@/services/cmds"; import { showNotice } from "@/services/noticeService"; const VALID_CORE = [ { name: "Mihomo", core: "verge-mihomo", chipKey: "settings.modals.clashCore.variants.release", }, { name: "Mihomo Alpha", core: "verge-mihomo-alpha", chipKey: "settings.modals.clashCore.variants.alpha", }, ]; export function ClashCoreViewer({ ref }: { ref?: Ref }) { const { t } = useTranslation(); const { verge, mutateVerge } = useVerge(); const [open, setOpen] = useState(false); const [upgrading, setUpgrading] = useState(false); const [restarting, setRestarting] = useState(false); const [changingCore, setChangingCore] = useState(null); useImperativeHandle(ref, () => ({ open: () => setOpen(true), close: () => setOpen(false), })); const { clash_core = "verge-mihomo" } = verge ?? {}; const onCoreChange = useLockFn(async (core: string) => { if (core === clash_core) return; try { setChangingCore(core); closeAllConnections(); const errorMsg = await changeClashCore(core); if (errorMsg) { showNotice.error(errorMsg); setChangingCore(null); return; } mutateVerge(); setTimeout(async () => { mutate("getClashConfig"); mutate("getVersion"); setChangingCore(null); }, 500); } catch (err) { setChangingCore(null); showNotice.error(err); } }); const onRestart = useLockFn(async () => { try { setRestarting(true); await restartCore(); showNotice.success( t("settings.feedback.notifications.clash.restartSuccess"), ); setRestarting(false); } catch (err) { setRestarting(false); showNotice.error(err); } }); const onUpgrade = useLockFn(async () => { try { setUpgrading(true); await upgradeCore(); setUpgrading(false); showNotice.success( t("settings.feedback.notifications.clash.versionUpdated"), ); } catch (err: any) { setUpgrading(false); const errMsg = err?.response?.data?.message ?? String(err); const showMsg = errMsg.includes("already using latest version") ? t("settings.feedback.notifications.clash.alreadyLatestVersion") : errMsg; showNotice.info(showMsg); } }); return ( {t("settings.sections.clash.form.fields.clashCore")} } loadingPosition="start" loading={upgrading} disabled={restarting || changingCore !== null} sx={{ marginRight: "8px" }} onClick={onUpgrade} > {t("shared.actions.upgrade")} } loadingPosition="start" loading={restarting} disabled={upgrading} onClick={onRestart} > {t("shared.actions.restart")} } contentSx={{ pb: 0, width: 400, height: 180, overflowY: "auto", userSelect: "text", marginTop: "-8px", }} disableOk cancelBtn={t("shared.actions.close")} onClose={() => setOpen(false)} onCancel={() => setOpen(false)} > {VALID_CORE.map((each) => ( onCoreChange(each.core)} disabled={changingCore !== null || restarting || upgrading} > {changingCore === each.core ? ( ) : ( )} ))} ); }