import { CheckCircleOutlineRounded } from '@mui/icons-material' import { alpha, Box, ListItem, ListItemButton, ListItemIcon, ListItemText, styled, type SxProps, type Theme, } from '@mui/material' import { BaseLoading } from '@/components/base' import { useProxyDelayState } from '@/hooks/use-proxy-delay-state' import delayManager from '@/services/delay' import { memberDetails, providerNameOf, type ProxyGroupView, type ResolvedProxyMember, } from '@/types/proxy-view' interface Props { group: ProxyGroupView member: ResolvedProxyMember selected: boolean showType?: boolean sx?: SxProps onClick?: (member: ResolvedProxyMember) => void } const Widget = styled(Box)(() => ({ padding: '3px 6px', fontSize: 14, borderRadius: '4px', })) const TypeBox = styled('span')(({ theme }) => ({ display: 'inline-block', border: '1px solid #ccc', borderColor: alpha(theme.palette.text.secondary, 0.36), color: alpha(theme.palette.text.secondary, 0.42), borderRadius: 4, fontSize: 10, marginRight: '4px', padding: '0 2px', lineHeight: 1.25, })) export const ProxyItem = (props: Props) => { const { group, member, selected, showType = true, sx, onClick } = props const details = memberDetails(member) const unresolved = member.kind === 'unresolved' const name = member.ref.name const type = unresolved ? member.ref.reason : (details?.type ?? '') const provider = member.kind === 'node' ? providerNameOf(member.node) : undefined const now = member.kind === 'group' ? member.group.now : undefined // -1/<=0 为不显示,-2 为 loading const { delayValue, isPreset, timeout, onDelay } = useProxyDelayState( member, group.name, ) return ( onClick?.(member)} sx={[ { borderRadius: 1 }, ({ palette: { mode, primary } }) => { const bgcolor = mode === 'light' ? '#ffffff' : '#24252f' const selectColor = mode === 'light' ? primary.main : primary.light const showDelay = delayValue > 0 return { '&:hover .the-check': { display: !showDelay ? 'block' : 'none' }, '&:hover .the-delay': { display: showDelay ? 'block' : 'none' }, '&:hover .the-icon': { display: 'none' }, '&.Mui-selected': { width: `calc(100% + 3px)`, marginLeft: `-3px`, borderLeft: `3px solid ${selectColor}`, bgcolor: mode === 'light' ? alpha(primary.main, 0.15) : alpha(primary.main, 0.35), }, backgroundColor: bgcolor, marginBottom: '8px', height: '40px', } }, ]} > {name} {showType && now && ` - ${now}`} {showType && !!provider && {provider}} {showType && {type}} {!unresolved && showType && details?.udp && ( UDP )} {!unresolved && showType && details?.xudp && ( XUDP )} {!unresolved && showType && details?.tfo && ( TFO )} {!unresolved && showType && details?.mptcp && ( MPTCP )} {!unresolved && showType && details?.smux && ( SMUX )} } /> {!unresolved && delayValue === -2 && ( )} {!unresolved && delayValue !== -2 && ( { e.preventDefault() e.stopPropagation() void onDelay() }} sx={({ palette }) => ({ display: 'none', // hover 时显示 ':hover': { bgcolor: alpha(palette.primary.main, 0.15) }, })} > Check )} {!unresolved && delayValue > 0 && ( // 显示延迟 { e.preventDefault() e.stopPropagation() void onDelay() }} sx={({ palette }) => ({ color: delayManager.formatDelayColor(delayValue, timeout), ':hover': { bgcolor: alpha(palette.primary.main, 0.15) }, })} > {delayManager.formatDelay(delayValue, timeout)} )} {!unresolved && delayValue !== -2 && delayValue <= 0 && selected && ( // 展示已选择的 icon )} ) }