diff --git a/frontend/src/components/AppSidebar.tsx b/frontend/src/components/AppSidebar.tsx index 35983ee7..f763216e 100644 --- a/frontend/src/components/AppSidebar.tsx +++ b/frontend/src/components/AppSidebar.tsx @@ -199,7 +199,7 @@ export default function AppSidebar({ basePath = '', requestUri = '' }: AppSideba closable={false} open={drawerOpen} rootClassName={currentTheme} - width="min(82vw, 320px)" + size="min(82vw, 320px)" styles={{ wrapper: { padding: 0 }, body: { padding: 0, display: 'flex', flexDirection: 'column', height: '100%' }, diff --git a/frontend/src/components/CustomStatistic.css b/frontend/src/components/CustomStatistic.css index c3203bc2..33ab619a 100644 --- a/frontend/src/components/CustomStatistic.css +++ b/frontend/src/components/CustomStatistic.css @@ -1,5 +1,25 @@ .ant-statistic-content { - font-size: 16px; + font-size: 15px !important; + line-height: 1.4 !important; +} + +.ant-statistic-content-value, +.ant-statistic-content-prefix, +.ant-statistic-content-suffix { + font-size: 15px !important; +} + +.ant-statistic-content-prefix { + margin-inline-end: 6px !important; +} + +.ant-statistic-content-prefix .anticon { + font-size: 16px !important; +} + +.ant-statistic-title { + font-size: 12px !important; + margin-bottom: 4px !important; } body.dark .ant-statistic-content { diff --git a/frontend/src/components/PromptModal.tsx b/frontend/src/components/PromptModal.tsx index 36d488ad..59121425 100644 --- a/frontend/src/components/PromptModal.tsx +++ b/frontend/src/components/PromptModal.tsx @@ -55,11 +55,11 @@ export default function PromptModal({ title={title} okText={okText} cancelText="Cancel" - maskClosable={false} + mask={{ closable: false }} confirmLoading={loading} onOk={() => onConfirm(value)} onCancel={onClose} - destroyOnClose + destroyOnHidden > {type === 'textarea' ? ( {fileName && ( diff --git a/frontend/src/hooks/useTheme.tsx b/frontend/src/hooks/useTheme.tsx index b05d5c19..8a7d6bc1 100644 --- a/frontend/src/hooks/useTheme.tsx +++ b/frontend/src/hooks/useTheme.tsx @@ -42,24 +42,32 @@ const ULTRA_DARK_TOKENS = { colorBgElevated: '#141414', }; const DARK_LAYOUT_TOKENS = { - colorBgHeader: '#252526', - colorBgTrigger: '#333333', - colorBgBody: '#1e1e1e', + bodyBg: '#1e1e1e', + headerBg: '#252526', + headerColor: '#ffffff', + footerBg: '#1e1e1e', + siderBg: '#252526', + triggerBg: '#333333', + triggerColor: '#ffffff', }; const ULTRA_DARK_LAYOUT_TOKENS = { - colorBgHeader: '#0a0a0a', - colorBgTrigger: '#141414', - colorBgBody: '#000', + bodyBg: '#000', + headerBg: '#0a0a0a', + headerColor: '#ffffff', + footerBg: '#000', + siderBg: '#0a0a0a', + triggerBg: '#141414', + triggerColor: '#ffffff', }; const DARK_MENU_TOKENS = { - colorItemBg: '#252526', - colorSubItemBg: '#1e1e1e', - menuSubMenuBg: '#252526', + darkItemBg: '#252526', + darkSubMenuItemBg: '#1e1e1e', + darkPopupBg: '#252526', }; const ULTRA_DARK_MENU_TOKENS = { - colorItemBg: '#0a0a0a', - colorSubItemBg: '#000', - menuSubMenuBg: '#0a0a0a', + darkItemBg: '#0a0a0a', + darkSubMenuItemBg: '#000', + darkPopupBg: '#0a0a0a', }; export function buildAntdThemeConfig(isDark: boolean, isUltra: boolean): ThemeConfig { diff --git a/frontend/src/pages/clients/ClientBulkAddModal.tsx b/frontend/src/pages/clients/ClientBulkAddModal.tsx index 11cdc420..2d09c552 100644 --- a/frontend/src/pages/clients/ClientBulkAddModal.tsx +++ b/frontend/src/pages/clients/ClientBulkAddModal.tsx @@ -210,7 +210,7 @@ export default function ClientBulkAddModal({ okText={t('create')} cancelText={t('close')} confirmLoading={saving} - maskClosable={false} + mask={{ closable: false }} width={640} onOk={submit} onCancel={() => onOpenChange(false)} diff --git a/frontend/src/pages/clients/ClientFormModal.tsx b/frontend/src/pages/clients/ClientFormModal.tsx index 918cf480..df050f84 100644 --- a/frontend/src/pages/clients/ClientFormModal.tsx +++ b/frontend/src/pages/clients/ClientFormModal.tsx @@ -327,7 +327,7 @@ export default function ClientFormModal({ - + {!fetched ? (
) : ( diff --git a/frontend/src/pages/inbounds/InboundFormModal.tsx b/frontend/src/pages/inbounds/InboundFormModal.tsx index 14bb7c3b..1ba7a268 100644 --- a/frontend/src/pages/inbounds/InboundFormModal.tsx +++ b/frontend/src/pages/inbounds/InboundFormModal.tsx @@ -648,14 +648,14 @@ export default function InboundFormModal({ const sniffingFallback = () => inboundRef.current?.sniffing?.toJson?.() || {}; const streamFallback = () => inboundRef.current?.stream?.toJson?.() || {}; - const parseAdvancedSliceWithLabel = (rawText: string, fallback: unknown, label: string) => { + const parseAdvancedSliceWithLabel = useCallback((rawText: string, fallback: unknown, label: string) => { try { return parseAdvancedSliceOrFallback(rawText, fallback); } catch (e) { message.error(`${label} JSON invalid: ${(e as Error).message}`); throw e; } - }; + }, []); const compactAdvancedJson = (raw: string, fallback: string, label: string) => { try { @@ -696,7 +696,7 @@ export default function InboundFormModal({ return false; } return true; - }, [t, refresh]); + }, [t, refresh, parseAdvancedSliceWithLabel]); const handleTabChange = (next: string) => { if (activeTabKey === 'advanced' && next !== 'advanced') { @@ -886,16 +886,15 @@ export default function InboundFormModal({ } }, [canEnableStream, t, mode, dbInbound, isFallbackHost, saveFallbacks, onSaved, onClose]); + const protocolSnapshot = inboundRef.current?.protocol; + const streamSnapshot = JSON.stringify(inboundRef.current?.stream?.toJson?.() || {}); + const sniffingSnapshot = JSON.stringify(inboundRef.current?.sniffing?.toJson?.() || {}); + const settingsSnapshot = JSON.stringify(inboundRef.current?.settings?.toJson?.() || {}); + useEffect(() => { if (!inboundRef.current) return; (['stream', 'sniffing', 'settings'] as const).forEach(stampAdvancedTextFor); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [ - inboundRef.current?.protocol, - JSON.stringify(inboundRef.current?.stream?.toJson?.() || {}), - JSON.stringify(inboundRef.current?.sniffing?.toJson?.() || {}), - JSON.stringify(inboundRef.current?.settings?.toJson?.() || {}), - ]); + }, [protocolSnapshot, streamSnapshot, sniffingSnapshot, settingsSnapshot, stampAdvancedTextFor]); const title = mode === 'edit' ? t('pages.inbounds.modifyInbound') : t('pages.inbounds.addInbound'); const okText = mode === 'edit' ? t('pages.clients.submitEdit') : t('create'); @@ -998,7 +997,7 @@ export default function InboundFormModal({
- + @@ -1146,7 +1145,7 @@ export default function InboundFormModal({ {(ib.settings.accounts || []).map((account: any, idx: number) => ( - + { account.user = e.target.value; refresh(); }} /> @@ -1155,7 +1154,7 @@ export default function InboundFormModal({ - + ))} {ib.protocol === Protocols.HTTP && ( @@ -1208,7 +1207,7 @@ export default function InboundFormModal({ {(ib.settings.portMap || []).length > 0 && ( {(ib.settings.portMap as { name: string; value: string }[]).map((pm, idx) => ( - + { pm.name = e.target.value; refresh(); }} /> { ib.settings.removePortMap(idx); refresh(); }}> - + ))} )} @@ -1405,7 +1404,7 @@ export default function InboundFormModal({ {(ib.stream.tcp.request.headers || []).length > 0 && ( {(ib.stream.tcp.request.headers as { name: string; value: string }[]).map((h, idx) => ( - + { h.name = e.target.value; refresh(); }} /> @@ -1415,7 +1414,7 @@ export default function InboundFormModal({ - + ))} )} @@ -1440,7 +1439,7 @@ export default function InboundFormModal({ {(ib.stream.tcp.response.headers || []).length > 0 && ( {(ib.stream.tcp.response.headers as { name: string; value: string }[]).map((h, idx) => ( - + { h.name = e.target.value; refresh(); }} /> @@ -1450,7 +1449,7 @@ export default function InboundFormModal({ - + ))} )} @@ -1482,7 +1481,7 @@ export default function InboundFormModal({ {(ib.stream.ws.headers || []).length > 0 && ( {(ib.stream.ws.headers as { name: string; value: string }[]).map((h, idx) => ( - + { h.name = e.target.value; refresh(); }} /> @@ -1492,7 +1491,7 @@ export default function InboundFormModal({ - + ))} )} @@ -1518,7 +1517,7 @@ export default function InboundFormModal({ {(ib.stream.httpupgrade.headers || []).length > 0 && ( {(ib.stream.httpupgrade.headers as { name: string; value: string }[]).map((h, idx) => ( - + { h.name = e.target.value; refresh(); }} /> @@ -1528,7 +1527,7 @@ export default function InboundFormModal({ - + ))} )} @@ -1545,7 +1544,7 @@ export default function InboundFormModal({ {(ib.stream.xhttp.headers || []).length > 0 && ( {(ib.stream.xhttp.headers as { name: string; value: string }[]).map((h, idx) => ( - + { h.name = e.target.value; refresh(); }} /> @@ -1555,7 +1554,7 @@ export default function InboundFormModal({ - + ))} )} @@ -1652,7 +1651,7 @@ export default function InboundFormModal({ {externalProxyOn && ( {(ib.stream.externalProxy as { forceTls: string; dest: string; port: number; remark: string }[]).map((row, idx) => ( - + { row.remark = e.target.value; refresh(); }} addonAfter={ { ib.stream.externalProxy.splice(idx, 1); refresh(); }} />} /> - + ))} )} @@ -1762,7 +1761,7 @@ export default function InboundFormModal({ {(ib.stream.hysteria.masquerade.headers || []).length > 0 && ( {(ib.stream.hysteria.masquerade.headers as { name: string; value: string }[]).map((h, idx) => ( - + { h.name = e.target.value; refresh(); }} /> { ib.stream.hysteria.masquerade.removeHeader(idx); refresh(); }}> - + ))} )} @@ -1808,14 +1807,14 @@ export default function InboundFormModal({ - + - + 10 20 @@ -131,7 +130,7 @@ export default function LogModal({ open, onClose }: LogModalProps) { Warning Error - + setSyslog(e.target.checked)}> diff --git a/frontend/src/pages/index/PanelUpdateModal.tsx b/frontend/src/pages/index/PanelUpdateModal.tsx index dea21e30..47d81d1e 100644 --- a/frontend/src/pages/index/PanelUpdateModal.tsx +++ b/frontend/src/pages/index/PanelUpdateModal.tsx @@ -72,7 +72,6 @@ export default function PanelUpdateModal({ open, info, onClose, onBusy }: PanelU @@ -80,7 +79,7 @@ export default function PanelUpdateModal({ open, info, onClose, onBusy }: PanelU )} diff --git a/frontend/src/pages/index/StatusCard.css b/frontend/src/pages/index/StatusCard.css index 1c08427f..6a20a444 100644 --- a/frontend/src/pages/index/StatusCard.css +++ b/frontend/src/pages/index/StatusCard.css @@ -2,7 +2,8 @@ text-align: center; } -.status-card .ant-progress-text { - font-size: 14px !important; +.status-card .ant-progress-text, +.status-card .ant-progress-indicator { + font-size: 12px !important; font-weight: 500; } diff --git a/frontend/src/pages/index/StatusCard.tsx b/frontend/src/pages/index/StatusCard.tsx index 15d5ce63..e1ef94bf 100644 --- a/frontend/src/pages/index/StatusCard.tsx +++ b/frontend/src/pages/index/StatusCard.tsx @@ -3,6 +3,7 @@ import { Card, Col, Progress, Row, Tooltip } from 'antd'; import { AreaChartOutlined } from '@ant-design/icons'; import { CPUFormatter, SizeFormatter } from '@/utils'; +import { useTheme } from '@/hooks/useTheme'; import type { Status } from '@/models/status'; import './StatusCard.css'; @@ -11,11 +12,14 @@ interface StatusCardProps { isMobile: boolean; } -const TRAIL_COLOR = 'rgba(128, 128, 128, 0.25)'; - export default function StatusCard({ status, isMobile }: StatusCardProps) { const { t } = useTranslation(); - const gaugeSize = isMobile ? 60 : 70; + const { isDark, isUltra } = useTheme(); + const gaugeSize = isMobile ? 60 : 90; + const strokeWidth = isMobile ? 7 : 5; + const railColor = isDark + ? isUltra ? 'rgba(255, 255, 255, 0.1)' : 'rgba(255, 255, 255, 0.16)' + : 'rgba(0, 0, 0, 0.08)'; return ( @@ -27,7 +31,8 @@ export default function StatusCard({ status, isMobile }: StatusCardProps) { type="dashboard" status="normal" strokeColor={status.cpu.color} - trailColor={TRAIL_COLOR} + railColor={railColor} + strokeWidth={strokeWidth} percent={status.cpu.percent} size={gaugeSize} /> @@ -56,7 +61,8 @@ export default function StatusCard({ status, isMobile }: StatusCardProps) { type="dashboard" status="normal" strokeColor={status.mem.color} - trailColor={TRAIL_COLOR} + railColor={railColor} + strokeWidth={strokeWidth} percent={status.mem.percent} size={gaugeSize} /> @@ -75,7 +81,8 @@ export default function StatusCard({ status, isMobile }: StatusCardProps) { type="dashboard" status="normal" strokeColor={status.swap.color} - trailColor={TRAIL_COLOR} + railColor={railColor} + strokeWidth={strokeWidth} percent={status.swap.percent} size={gaugeSize} /> @@ -90,7 +97,8 @@ export default function StatusCard({ status, isMobile }: StatusCardProps) { type="dashboard" status="normal" strokeColor={status.disk.color} - trailColor={TRAIL_COLOR} + railColor={railColor} + strokeWidth={strokeWidth} percent={status.disk.percent} size={gaugeSize} /> diff --git a/frontend/src/pages/index/SystemHistoryModal.tsx b/frontend/src/pages/index/SystemHistoryModal.tsx index 186866d0..82502e1d 100644 --- a/frontend/src/pages/index/SystemHistoryModal.tsx +++ b/frontend/src/pages/index/SystemHistoryModal.tsx @@ -106,7 +106,6 @@ export default function SystemHistoryModal({ open, status, onClose }: SystemHist return ( @@ -117,7 +116,7 @@ export default function VersionModal({ open, status, onClose, onBusy }: VersionM diff --git a/frontend/src/pages/index/XrayLogModal.tsx b/frontend/src/pages/index/XrayLogModal.tsx index c0771a0d..5e5aa5e7 100644 --- a/frontend/src/pages/index/XrayLogModal.tsx +++ b/frontend/src/pages/index/XrayLogModal.tsx @@ -110,7 +110,6 @@ export default function XrayLogModal({ open, onClose }: XrayLogModalProps) { return ( )} @@ -269,7 +268,7 @@ export default function XrayMetricsModal({ open, onClose }: XrayMetricsModalProp type="info" showIcon className="metrics-alert" - message={t('pages.index.xrayObservatoryEmpty')} + title={t('pages.index.xrayObservatoryEmpty')} description={t('pages.index.xrayObservatoryHint')} /> ) : ( diff --git a/frontend/src/pages/index/XrayStatusCard.tsx b/frontend/src/pages/index/XrayStatusCard.tsx index e5a6a227..acdac689 100644 --- a/frontend/src/pages/index/XrayStatusCard.tsx +++ b/frontend/src/pages/index/XrayStatusCard.tsx @@ -50,7 +50,7 @@ export default function XrayStatusCard({ 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} @@ -105,21 +105,21 @@ export default function XrayStatusCard({ const actions = [ ...(ipLimitEnable ? [ - + {!isMobile && {t('pages.index.logs')}} , ] : []), - + {!isMobile && {t('pages.index.stopXray')}} , - + {!isMobile && {t('pages.index.restartXray')}} , - + {!isMobile && ( diff --git a/frontend/src/pages/login/LoginPage.tsx b/frontend/src/pages/login/LoginPage.tsx index 0ac07e10..127b6d23 100644 --- a/frontend/src/pages/login/LoginPage.tsx +++ b/frontend/src/pages/login/LoginPage.tsx @@ -145,12 +145,12 @@ export default function LoginPage() { {themeIcon} + diff --git a/frontend/src/pages/xray/BalancersTab.tsx b/frontend/src/pages/xray/BalancersTab.tsx index 435b7a6d..9a7e39eb 100644 --- a/frontend/src/pages/xray/BalancersTab.tsx +++ b/frontend/src/pages/xray/BalancersTab.tsx @@ -306,7 +306,7 @@ export default function BalancersTab({ return ( <> {modalContextHolder} - + {rows.length === 0 ? ( diff --git a/frontend/src/pages/xray/DnsPresetsModal.tsx b/frontend/src/pages/xray/DnsPresetsModal.tsx index f3f7fa41..cd049fde 100644 --- a/frontend/src/pages/xray/DnsPresetsModal.tsx +++ b/frontend/src/pages/xray/DnsPresetsModal.tsx @@ -44,7 +44,7 @@ export default function DnsPresetsModal({ open, onClose, onInstall }: DnsPresets open={open} title={t('pages.xray.dns.dnsPresetTitle')} footer={null} - maskClosable={false} + mask={{ closable: false }} onCancel={onClose} > diff --git a/frontend/src/pages/xray/DnsServerModal.tsx b/frontend/src/pages/xray/DnsServerModal.tsx index 5006617a..1652fecb 100644 --- a/frontend/src/pages/xray/DnsServerModal.tsx +++ b/frontend/src/pages/xray/DnsServerModal.tsx @@ -156,7 +156,7 @@ export default function DnsServerModal({ title={title} okText={t('confirm')} cancelText={t('close')} - maskClosable={false} + mask={{ closable: false }} onOk={submit} onCancel={onClose} > diff --git a/frontend/src/pages/xray/DnsTab.tsx b/frontend/src/pages/xray/DnsTab.tsx index 19050fee..3caa219d 100644 --- a/frontend/src/pages/xray/DnsTab.tsx +++ b/frontend/src/pages/xray/DnsTab.tsx @@ -427,7 +427,7 @@ export default function DnsTab({ templateSettings, setTemplateSettings }: DnsTab ) : ( - + @@ -475,7 +475,7 @@ export default function DnsTab({ templateSettings, setTemplateSettings }: DnsTab ) : ( - + ) : ( - + diff --git a/frontend/src/pages/xray/NordModal.tsx b/frontend/src/pages/xray/NordModal.tsx index 6dc71e3f..a9897c39 100644 --- a/frontend/src/pages/xray/NordModal.tsx +++ b/frontend/src/pages/xray/NordModal.tsx @@ -235,7 +235,7 @@ export default function NordModal({ } return ( - + {nordData == null ? ( +
@@ -386,7 +386,7 @@ export default function OutboundsTab({ return ( <> {modalContextHolder} - + diff --git a/frontend/src/pages/xray/RoutingTab.tsx b/frontend/src/pages/xray/RoutingTab.tsx index bd8552c4..57882c5a 100644 --- a/frontend/src/pages/xray/RoutingTab.tsx +++ b/frontend/src/pages/xray/RoutingTab.tsx @@ -402,7 +402,7 @@ export default function RoutingTab({ return ( <> {modalContextHolder} - + diff --git a/frontend/src/pages/xray/RuleFormModal.tsx b/frontend/src/pages/xray/RuleFormModal.tsx index ea54214a..81d752bf 100644 --- a/frontend/src/pages/xray/RuleFormModal.tsx +++ b/frontend/src/pages/xray/RuleFormModal.tsx @@ -149,7 +149,7 @@ export default function RuleFormModal({ title={title} okText={okText} cancelText={t('close')} - maskClosable={false} + mask={{ closable: false }} width={640} onOk={submit} onCancel={onClose} diff --git a/frontend/src/pages/xray/WarpModal.tsx b/frontend/src/pages/xray/WarpModal.tsx index c50ab0e6..92bbdfdc 100644 --- a/frontend/src/pages/xray/WarpModal.tsx +++ b/frontend/src/pages/xray/WarpModal.tsx @@ -207,7 +207,7 @@ export default function WarpModal({ const hasConfig = !ObjectUtil.isEmpty(warpConfig); return ( - + {!hasWarp ? ( {licenseError && ( - + )}
diff --git a/frontend/src/pages/xray/XrayPage.tsx b/frontend/src/pages/xray/XrayPage.tsx index ce95f391..ce074ea4 100644 --- a/frontend/src/pages/xray/XrayPage.tsx +++ b/frontend/src/pages/xray/XrayPage.tsx @@ -1,12 +1,12 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { - BackTop, Alert, Button, Card, Col, ConfigProvider, + FloatButton, Layout, message, Modal, @@ -258,7 +258,7 @@ export default function XrayPage() { - + {!fetched ? (
) : fetchError ? ( @@ -274,7 +274,7 @@ export default function XrayPage() { - + @@ -293,8 +293,8 @@ export default function XrayPage() { - - + +