import { useTranslation } from 'react-i18next'; import { Modal, Tag } from 'antd'; import { SizeFormatter, IntlUtil, ColorUtils } from '@/utils'; import { InfinityIcon } from '@/components/ui'; import type { NodeRecord } from '@/api/queries/useNodesQuery'; import { readStreamHints, networkLabel, networkL4, shadowsocksNetworkLabel, tunnelNetworkLabel, mixedNetworkLabel, } from './helpers'; import { InboundSpeedTag, isActiveSpeed } from './InboundSpeedTag'; import type { ClientCountEntry, DBInboundRecord, InboundSpeedEntry } from './types'; interface InboundStatsModalProps { open: boolean; record: DBInboundRecord | null; hasActiveNode: boolean; nodesById: Map; clientCount: Record; inboundSpeed: Record; trafficDiff: number; expireDiff: number; onClose: () => void; } export default function InboundStatsModal({ open, record, hasActiveNode, nodesById, clientCount, inboundSpeed, trafficDiff, expireDiff, onClose, }: InboundStatsModalProps) { const { t } = useTranslation(); return ( {record && (
{t('pages.inbounds.protocol')} {record.protocol} {(record.isWireguard || record.isHysteria) && UDP} {record.isSS && (() => { const stream = readStreamHints(record.streamSettings); return ( <> {shadowsocksNetworkLabel(record.settings)} {stream.isTls && TLS} ); })()} {record.isTunnel && {tunnelNetworkLabel(record.settings)}} {record.isMixed && {mixedNetworkLabel(record.settings)}} {(record.isVMess || record.isVLess || record.isTrojan) && (() => { const stream = readStreamHints(record.streamSettings); const l4 = networkL4(stream.network); return ( <> {networkLabel(stream.network)} {l4 && {l4}} {stream.isTls && TLS} {stream.isReality && Reality} ); })()}
{t('pages.inbounds.port')} {record.port}
{hasActiveNode && (
{t('pages.inbounds.node')} {record.nodeId == null ? ( {t('pages.inbounds.localPanel')} ) : nodesById.get(record.nodeId) ? ( {nodesById.get(record.nodeId)!.name} ) : ( #{record.nodeId} )}
)}
{t('pages.inbounds.traffic')} {SizeFormatter.sizeFormat(record.up + record.down)} /{' '} {record.total > 0 ? SizeFormatter.sizeFormat(record.total) : }
{(() => { const speed = inboundSpeed[record.id]; if (!isActiveSpeed(speed)) return null; return (
{t('pages.inbounds.speed')}
); })()} {clientCount[record.id] && (
{t('clients')} {clientCount[record.id].clients} {clientCount[record.id].online.length > 0 && ( {clientCount[record.id].online.length} {t('online')} )} {clientCount[record.id].depleted.length > 0 && ( {clientCount[record.id].depleted.length} {t('depleted')} )} {clientCount[record.id].expiring.length > 0 && ( {clientCount[record.id].expiring.length} {t('depletingSoon')} )}
)}
{t('pages.inbounds.expireDate')} {record.expiryTime > 0 ? ( {IntlUtil.formatRelativeTime(record.expiryTime)} ) : ( )}
)}
); }