SystemStrip.tsx 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import { useTranslation } from 'react-i18next';
  2. import { Card, Tooltip } from 'antd';
  3. import {
  4. ClockCircleOutlined,
  5. DatabaseOutlined,
  6. EyeInvisibleOutlined,
  7. EyeOutlined,
  8. GlobalOutlined,
  9. } from '@ant-design/icons';
  10. import { SizeFormatter, TimeFormatter } from '@/utils';
  11. import { activateOnKey } from '@/utils/a11y';
  12. import type { Status } from '@/models/status';
  13. interface SystemStripProps {
  14. status: Status;
  15. showIp: boolean;
  16. onToggleIp: () => void;
  17. }
  18. export default function SystemStrip({ status, showIp, onToggleIp }: SystemStripProps) {
  19. const { t } = useTranslation();
  20. return (
  21. <Card hoverable styles={{ body: { padding: 0 } }}>
  22. <div className="ov-strip-grid">
  23. <div className="ov-strip-cell">
  24. <div className="ov-kicker ov-kicker-icon">
  25. <ClockCircleOutlined />
  26. {t('pages.index.uptime')}
  27. </div>
  28. <div className="ov-strip-split">
  29. <div>
  30. <div className="ov-strip-sub">Xray</div>
  31. <div className="ov-strip-value">{TimeFormatter.formatSecond(status.appStats.uptime)}</div>
  32. </div>
  33. <span className="ov-strip-split-sep" />
  34. <div>
  35. <div className="ov-strip-sub">OS</div>
  36. <div className="ov-strip-value">{TimeFormatter.formatSecond(status.uptime)}</div>
  37. </div>
  38. </div>
  39. </div>
  40. <div className="ov-strip-cell">
  41. <div className="ov-kicker ov-kicker-icon">
  42. <DatabaseOutlined />
  43. {t('pages.index.panel')}
  44. </div>
  45. <div className="ov-strip-split">
  46. <div>
  47. <div className="ov-strip-sub">{t('pages.index.memory')}</div>
  48. <div className="ov-strip-value">{SizeFormatter.sizeFormat(status.appStats.mem)}</div>
  49. </div>
  50. <span className="ov-strip-split-sep" />
  51. <div>
  52. <div className="ov-strip-sub">{t('pages.index.threads')}</div>
  53. <div className="ov-strip-value">{status.appStats.threads}</div>
  54. </div>
  55. </div>
  56. </div>
  57. <div className="ov-strip-cell">
  58. <div className="ov-kicker ov-kicker-icon">
  59. <GlobalOutlined />
  60. {t('pages.index.ipAddresses')}
  61. <Tooltip title={t('pages.index.toggleIpVisibility')}>
  62. {showIp ? (
  63. <EyeOutlined
  64. className="ip-toggle-icon"
  65. role="button"
  66. tabIndex={0}
  67. aria-label={t('pages.index.toggleIpVisibility')}
  68. onClick={onToggleIp}
  69. onKeyDown={activateOnKey(onToggleIp)}
  70. />
  71. ) : (
  72. <EyeInvisibleOutlined
  73. className="ip-toggle-icon"
  74. role="button"
  75. tabIndex={0}
  76. aria-label={t('pages.index.toggleIpVisibility')}
  77. onClick={onToggleIp}
  78. onKeyDown={activateOnKey(onToggleIp)}
  79. />
  80. )}
  81. </Tooltip>
  82. </div>
  83. <div className={`ov-ip${showIp ? '' : ' ip-hidden'}`}>
  84. <div className="ov-mono">{status.publicIP.ipv4}</div>
  85. <div className="ov-mono ov-ip-v6">{status.publicIP.ipv6}</div>
  86. </div>
  87. </div>
  88. </div>
  89. </Card>
  90. );
  91. }