import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { Badge, Card, Col, Popover, Row, Space, Tag } from 'antd'; import { BarsOutlined, PoweroffOutlined, ReloadOutlined, ToolOutlined, } from '@ant-design/icons'; import type { Status } from '@/models/status'; import { activateOnKey } from '@/utils/a11y'; import './XrayStatusCard.css'; interface XrayStatusCardProps { status: Status; isMobile: boolean; accessLogEnable: boolean; onStopXray: () => void; onRestartXray: () => void; onOpenLogs: () => void; onOpenXrayLogs: () => void; onOpenVersionSwitch: () => void; } const XRAY_STATE_KEYS: Record = { running: 'pages.index.xrayStatusRunning', stop: 'pages.index.xrayStatusStop', error: 'pages.index.xrayStatusError', }; export default function XrayStatusCard({ status, isMobile, accessLogEnable, onStopXray, onRestartXray, onOpenLogs, onOpenXrayLogs, onOpenVersionSwitch, }: XrayStatusCardProps) { const { t } = useTranslation(); const stateText = t(XRAY_STATE_KEYS[status.xray.state] ?? 'pages.index.xrayStatusUnknown'); const title = ( {t('pages.index.xrayStatus')} {isMobile && status.xray.version && status.xray.version !== 'Unknown' && ( v{status.xray.version} )} ); const errorLines = useMemo( () => (status.xray.errorMsg || '').split('\n'), [status.xray.errorMsg], ); const extra = status.xray.state !== 'error' ? ( ) : ( {t('pages.index.xrayStatusError')} } content={ <> {errorLines.map((line, i) => ( {line} ))} } > ); const actions = [ // the xray log viewer reads the access log file, so the button only makes // sense when one is configured (unlike IP limit, which no longer needs it) ...(accessLogEnable ? [ {!isMobile && {t('pages.index.accessLogs')}} , ] : []), {!isMobile && {t('pages.index.stopXray')}} , {!isMobile && {t('pages.index.restartXray')}} , {!isMobile && ( {status.xray.version && status.xray.version !== 'Unknown' ? `v${status.xray.version}` : t('pages.index.xraySwitch')} )} , ]; return ( ); }