import useSWR from "swr"; import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { Button, Checkbox, Dialog, DialogActions, DialogContent, DialogTitle, Divider, Stack, Tooltip, Typography, } from "@mui/material"; import { InfoRounded } from "@mui/icons-material"; import { changeProfileValid, getProfiles, getRuntimeExists, } from "@/services/cmds"; import { ModalHandler } from "@/hooks/use-modal-handler"; import { HANDLE_FIELDS, DEFAULT_FIELDS, OTHERS_FIELDS, } from "@/utils/clash-fields"; import Notice from "@/components/base/base-notice"; interface Props { handler: ModalHandler; } 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); 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([]); if (handler) { handler.current = { open: () => setOpen(true), close: () => setOpen(false), }; } useEffect(() => { if (open) mutate(); }, [open]); useEffect(() => { setSelected(data?.valid || []); }, [data?.valid]); 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(data?.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 changeProfileValid([...curSet]); mutate(); Notice.success("Refresh clash config", 1000); } catch (err: any) { Notice.error(err?.message || err.toString()); } }; return ( setOpen(false)}> {t("Clash Field")} {otherFields.map((item) => { const inSelect = selected.includes(item); const inConfig = existsKeys.includes(item); const inValid = data?.valid?.includes(item); return ( handleChange(item)} /> {item} {!inSelect && inConfig && !inValid && } ); })} Clash Verge Control Fields {handleFields.map((item) => ( {item} ))} ); }; function WarnIcon() { return ( ); } export default ClashFieldViewer;