import useSWR from "swr"; import { forwardRef, useImperativeHandle, useState } from "react"; import { useTranslation } from "react-i18next"; import { Checkbox, Divider, Stack, Tooltip, Typography } from "@mui/material"; import { InfoRounded } from "@mui/icons-material"; import { getRuntimeExists } from "@/services/cmds"; import { HANDLE_FIELDS, DEFAULT_FIELDS, OTHERS_FIELDS, } from "@/utils/clash-fields"; import { BaseDialog, DialogRef } from "@/components/base"; import { useProfiles } from "@/hooks/use-profiles"; import { Notice } from "@/components/base"; const fieldSorter = (a: string, b: string) => { if (a.includes("-") === a.includes("-")) { if (a.length === b.length) return a.localeCompare(b); return a.length - b.length; } else if (a.includes("-")) return 1; else if (b.includes("-")) return -1; return 0; }; const otherFields = [...OTHERS_FIELDS].sort(fieldSorter); const handleFields = [...HANDLE_FIELDS, ...DEFAULT_FIELDS].sort(fieldSorter); export const ClashFieldViewer = forwardRef((props, ref) => { const { t } = useTranslation(); const { profiles = {}, patchProfiles } = useProfiles(); const { data: existsKeys = [], mutate: mutateExists } = useSWR( "getRuntimeExists", getRuntimeExists ); const [open, setOpen] = useState(false); const [selected, setSelected] = useState([]); useImperativeHandle(ref, () => ({ open: () => { mutateExists(); setSelected(profiles.valid || []); setOpen(true); }, close: () => setOpen(false), })); const handleChange = (item: string) => { if (!item) return; setSelected((old) => old.includes(item) ? old.filter((e) => e !== item) : [...old, item] ); }; const handleSave = async () => { setOpen(false); const oldSet = new Set(profiles.valid || []); const curSet = new Set(selected); const joinSet = new Set(selected.concat([...oldSet])); if (curSet.size === oldSet.size && curSet.size === joinSet.size) return; try { await patchProfiles({ valid: [...curSet] }); // Notice.success("Refresh clash config", 1000); } catch (err: any) { Notice.error(err?.message || err.toString()); } }; return ( setOpen(false)} onCancel={() => setOpen(false)} onOk={handleSave} > {otherFields.map((item) => { const inSelect = selected.includes(item); const inConfig = existsKeys.includes(item); return ( handleChange(item)} /> {item} {!inSelect && inConfig && } ); })} Clash Verge Control Fields {handleFields.map((item) => ( {item} ))} ); }); function WarnIcon() { return ( ); }