import { ExpandLessRounded, ExpandMoreRounded, InboxRounded, } from '@mui/icons-material' import { alpha, Box, ListItemText, ListItemButton, Typography, styled, Chip, Tooltip, } from '@mui/material' import { memo, useId, useMemo } from 'react' import { useTranslation } from 'react-i18next' import { useIconCache } from '@/hooks/use-icon-cache' import { useVerge } from '@/hooks/use-verge' import { useThemeMode } from '@/services/states' import type { ResolvedProxyMember } from '@/types/proxy-view' import { ProxyGroupHeaderBlock } from './proxy-group-header-block' import { ProxyGroupTools } from './proxy-group-tools' import { ProxyHead } from './proxy-head' import { ProxyItem } from './proxy-item' import { ProxyItemMini } from './proxy-item-mini' import type { HeadState } from './use-head-state' import type { IRenderItem } from './use-render-list' interface RenderProps { item: IRenderItem stickyed?: boolean isChainMode?: boolean onLocation: (group: IRenderItem['group']) => void onCheckAll: (groupName: string) => void onHeadState: (groupName: string, patch: Partial) => void onChangeProxy: ( group: IRenderItem['group'], member: ResolvedProxyMember, ) => void onGroupToggle?: (group: IRenderItem['group']) => void } export const ProxyRender = memo(function ProxyRender(props: RenderProps) { const { t } = useTranslation() const { item, stickyed = false, onLocation, onCheckAll, onHeadState, onChangeProxy, onGroupToggle, isChainMode: _ = false, } = props const { type, group, headState, member, memberCol } = item const { verge } = useVerge() const enable_group_icon = verge?.enable_group_icon ?? true const toolsOnLeft = verge?.proxy_group_tools_position === 'left' const headerId = useId() const mode = useThemeMode() const isDark = mode === 'dark' const itembackgroundcolor = isDark ? '#282A36' : '#ffffff' const iconCachePath = useIconCache({ icon: group.icon, cacheKey: group.name.replaceAll(' ', ''), enabled: enable_group_icon, }) const showType = headState?.showType const memberColItemsMemo = useMemo(() => { if (type !== 4 || !memberCol) { return null } return memberCol.map((occurrence) => ( onChangeProxy(group, nextMember)} /> )) }, [type, memberCol, item.key, group, showType, onChangeProxy]) if (type === 0) { const nameBlock = ( {enable_group_icon && group.icon?.trim().startsWith('http') && ( {group.name} )} {enable_group_icon && group.icon?.trim().startsWith('data') && ( {group.name} )} {enable_group_icon && group.icon?.trim().startsWith(' )} {group.name}} secondary={ {group.type} {group.now} } slotProps={{ secondary: { component: 'div', sx: { display: 'flex', alignItems: 'center', color: '#ccc', }, }, }} /> ) const proxyCount = (
alpha(theme.palette.primary.main, 0.1), color: (theme) => theme.palette.primary.main, }} />
) const toolsBlock = ( {toolsOnLeft && proxyCount} onLocation(group)} onCheckDelay={() => onCheckAll(group.name)} onHeadState={(p) => onHeadState(group.name, p)} /> {!toolsOnLeft && proxyCount} ) return (
{ if (headState?.open) { onGroupToggle?.(group) } onHeadState?.(group.name, { open: !headState?.open }) }} > {toolsOnLeft ? toolsBlock : nameBlock} {toolsOnLeft ? nameBlock : toolsBlock} {headState?.open ? : }
) } if (type === 1) { return ( onLocation(group)} onCheckDelay={() => onCheckAll(group.name)} onHeadState={(p) => onHeadState(group.name, p)} /> ) } if (type === 2) { return ( onChangeProxy(group, nextMember)} /> ) } if (type === 3) { return ( {t('proxies.page.empty.noProxies')} ) } if (type === 4) { return ( {memberColItemsMemo} ) } return null }) const StyledPrimary = styled('span')` font-size: 16px; font-weight: 700; line-height: 1.5; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; ` const StyledSubtitle = styled('span')` font-size: 13px; overflow: hidden; color: text.secondary; text-overflow: ellipsis; white-space: nowrap; ` const StyledTypeBox = styled(Box)(({ theme }) => ({ display: 'inline-block', border: '1px solid #ccc', borderColor: alpha(theme.palette.primary.main, 0.5), color: alpha(theme.palette.primary.main, 0.8), borderRadius: 4, fontSize: 10, padding: '0 4px', lineHeight: 1.5, marginRight: '8px', }))