fix(frontend): wireguard info alignment, blue login dark, embed gitkeep

- align WireGuard info-modal fields with Protocol/Address/Port by wrapping
  values in Tag (matches the rest of the dl.info-list rows)
- swap login dark palette from purple to pure blue blobs/accent/brand
- pin web/dist/.gitkeep through gitignore so //go:embed all:dist never
  fails on a fresh clone with an empty dist directory
This commit is contained in:
MHSanaei 2026-05-22 13:13:56 +02:00
parent 3939356b70
commit af6d801474
No known key found for this signature in database
GPG key ID: 7E4060F2FBE5AB7A
3 changed files with 107 additions and 66 deletions

3
.gitignore vendored
View file

@ -16,6 +16,9 @@ tmp/
backup/ backup/
bin/ bin/
dist/ dist/
!web/dist/
web/dist/*
!web/dist/.gitkeep
release/ release/
node_modules/ node_modules/

View file

@ -1,4 +1,4 @@
import { useCallback, useEffect, useMemo, useState } from 'react'; import { Fragment, useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Button, Divider, Modal, Space, Tabs, Tag, Tooltip } from 'antd'; import { Button, Divider, Modal, Space, Tabs, Tag, Tooltip } from 'antd';
import { getMessage } from '@/utils/messageBus'; import { getMessage } from '@/utils/messageBus';
@ -802,59 +802,86 @@ export default function InboundInfoModal({
)} )}
{dbInbound.isWireguard && inbound.settings && ( {dbInbound.isWireguard && inbound.settings && (
<table className="info-table protocol-table wg-table"> <>
<tbody> <dl className="info-list info-list-block">
<tr><td>Secret key</td><td>{inbound.settings.secretKey as string}</td></tr> <div className="info-row">
<tr><td>Public key</td><td>{inbound.settings.pubKey as string}</td></tr> <dt>Secret key</dt>
<tr><td>MTU</td><td>{inbound.settings.mtu as number}</td></tr> <dd><Tag className="value-tag">{inbound.settings.secretKey as string}</Tag></dd>
<tr><td>No-kernel TUN</td><td>{String(inbound.settings.noKernelTun)}</td></tr> </div>
{Array.isArray(inbound.settings.peers) && (inbound.settings.peers as { privateKey: string; publicKey: string; psk: string; allowedIPs?: string[]; keepAlive?: number }[]).map((peer, idx) => ( <div className="info-row">
<> <dt>Public key</dt>
<tr key={`p-h-${idx}`}> <dd><Tag className="value-tag">{inbound.settings.pubKey as string}</Tag></dd>
<td colSpan={2}><Divider>Peer {idx + 1}</Divider></td> </div>
</tr> <div className="info-row">
<tr key={`p-sk-${idx}`}><td>Secret key</td><td>{peer.privateKey}</td></tr> <dt>MTU</dt>
<tr key={`p-pk-${idx}`}><td>Public key</td><td>{peer.publicKey}</td></tr> <dd><Tag>{inbound.settings.mtu as number}</Tag></dd>
<tr key={`p-psk-${idx}`}><td>PSK</td><td>{peer.psk}</td></tr> </div>
<tr key={`p-ai-${idx}`}><td>Allowed IPs</td><td>{(peer.allowedIPs || []).join(',')}</td></tr> <div className="info-row">
<tr key={`p-ka-${idx}`}><td>Keep alive</td><td>{peer.keepAlive}</td></tr> <dt>No-kernel TUN</dt>
{wireguardConfigs[idx] && ( <dd>
<tr key={`p-conf-${idx}`}> <Tag color={inbound.settings.noKernelTun ? 'green' : 'default'}>
<td colSpan={2}> {String(inbound.settings.noKernelTun)}
<div className="link-panel"> </Tag>
<div className="link-panel-header"> </dd>
<Tag color="green">Peer {idx + 1} config</Tag> </div>
<Tooltip title={t('copy')}> </dl>
<Button size="small" icon={<CopyOutlined />} onClick={() => copyText(wireguardConfigs[idx], t)} /> {Array.isArray(inbound.settings.peers) && (inbound.settings.peers as { privateKey: string; publicKey: string; psk: string; allowedIPs?: string[]; keepAlive?: number }[]).map((peer, idx) => (
</Tooltip> <Fragment key={idx}>
<Tooltip title={t('download')}> <Divider>Peer {idx + 1}</Divider>
<Button size="small" icon={<DownloadOutlined />} onClick={() => downloadText(wireguardConfigs[idx], `peer-${idx + 1}.conf`)} /> <dl className="info-list info-list-block">
</Tooltip> <div className="info-row">
</div> <dt>Secret key</dt>
<code className="link-panel-text">{wireguardConfigs[idx]}</code> <dd><Tag className="value-tag">{peer.privateKey}</Tag></dd>
</div> </div>
</td> <div className="info-row">
</tr> <dt>Public key</dt>
)} <dd><Tag className="value-tag">{peer.publicKey}</Tag></dd>
{wireguardLinks[idx] && ( </div>
<tr key={`p-link-${idx}`}> <div className="info-row">
<td colSpan={2}> <dt>PSK</dt>
<div className="link-panel"> <dd><Tag className="value-tag">{peer.psk}</Tag></dd>
<div className="link-panel-header"> </div>
<Tag color="green">Peer {idx + 1} link</Tag> <div className="info-row">
<Tooltip title={t('copy')}> <dt>Allowed IPs</dt>
<Button size="small" icon={<CopyOutlined />} onClick={() => copyText(wireguardLinks[idx], t)} /> <dd>
</Tooltip> {(peer.allowedIPs || []).map((ip, j) => (
</div> <Tag key={`wg-ip-${idx}-${j}`} className="value-tag">{ip}</Tag>
<code className="link-panel-text">{wireguardLinks[idx]}</code> ))}
</div> </dd>
</td> </div>
</tr> <div className="info-row">
)} <dt>Keep alive</dt>
</> <dd><Tag>{peer.keepAlive}</Tag></dd>
))} </div>
</tbody> </dl>
</table> {wireguardConfigs[idx] && (
<div className="link-panel">
<div className="link-panel-header">
<Tag color="green">Peer {idx + 1} config</Tag>
<Tooltip title={t('copy')}>
<Button size="small" icon={<CopyOutlined />} onClick={() => copyText(wireguardConfigs[idx], t)} />
</Tooltip>
<Tooltip title={t('download')}>
<Button size="small" icon={<DownloadOutlined />} onClick={() => downloadText(wireguardConfigs[idx], `peer-${idx + 1}.conf`)} />
</Tooltip>
</div>
<code className="link-panel-text">{wireguardConfigs[idx]}</code>
</div>
)}
{wireguardLinks[idx] && (
<div className="link-panel">
<div className="link-panel-header">
<Tag color="green">Peer {idx + 1} link</Tag>
<Tooltip title={t('copy')}>
<Button size="small" icon={<CopyOutlined />} onClick={() => copyText(wireguardLinks[idx], t)} />
</Tooltip>
</div>
<code className="link-panel-text">{wireguardLinks[idx]}</code>
</div>
)}
</Fragment>
))}
</>
)} )}
{dbInbound.isSS && !inbound.isSSMultiUser && links.length > 0 && ( {dbInbound.isSS && !inbound.isSSMultiUser && links.length > 0 && (

View file

@ -22,22 +22,22 @@
} }
.login-app.is-dark { .login-app.is-dark {
--bg-page: #0b0d17; --bg-page: #0d1117;
--bg-card: rgba(30, 32, 50, 0.55); --bg-card: rgba(28, 30, 36, 0.55);
--bg-card-solid: #1a1c2e; --bg-card-solid: #1c1e22;
--color-text: rgba(255, 255, 255, 0.92); --color-text: rgba(255, 255, 255, 0.92);
--color-text-subtle: rgba(255, 255, 255, 0.55); --color-text-subtle: rgba(255, 255, 255, 0.55);
--color-accent: #818cf8; --color-accent: #3b82f6;
--color-border: rgba(255, 255, 255, 0.10); --color-border: rgba(255, 255, 255, 0.10);
--shadow-card: 0 1px 3px rgba(0, 0, 0, 0.4), 0 20px 60px rgba(99, 102, 241, 0.25); --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.4), 0 20px 60px rgba(59, 130, 246, 0.22);
--blob-1: rgba(99, 102, 241, 0.55); --blob-1: rgba(96, 165, 250, 0.42);
--blob-2: rgba(236, 72, 153, 0.45); --blob-2: rgba(59, 130, 246, 0.42);
--blob-3: rgba(34, 211, 238, 0.40); --blob-3: rgba(37, 99, 235, 0.35);
--blob-4: rgba(251, 146, 60, 0.30); --blob-4: rgba(251, 146, 60, 0.18);
--blob-5: rgba(168, 85, 247, 0.45); --blob-5: rgba(129, 140, 248, 0.30);
--grid-color: rgba(255, 255, 255, 0.04); --grid-color: rgba(255, 255, 255, 0.04);
--vignette: radial-gradient(ellipse at center, transparent 25%, rgba(0, 0, 0, 0.5) 100%); --vignette: radial-gradient(ellipse at center, transparent 25%, rgba(0, 0, 0, 0.5) 100%);
background: radial-gradient(ellipse at 25% 20%, #1e1b4b 0%, #0b0d17 60%); background: radial-gradient(ellipse at 25% 20%, #152038 0%, #0d1117 60%);
} }
.login-app.is-dark.is-ultra { .login-app.is-dark.is-ultra {
@ -301,7 +301,7 @@
135deg, 135deg,
rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0.15),
rgba(255, 255, 255, 0) 40%, rgba(255, 255, 255, 0) 40%,
rgba(129, 140, 248, 0.35) 80% rgba(59, 130, 246, 0.40) 80%
); );
} }
@ -330,6 +330,13 @@
-webkit-text-fill-color: transparent; -webkit-text-fill-color: transparent;
} }
.login-app.is-dark .brand-name {
background: linear-gradient(135deg, #60a5fa, #1d4ed8);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
.brand-accent { .brand-accent {
display: block; display: block;
width: 40px; width: 40px;
@ -338,6 +345,10 @@
background: linear-gradient(90deg, var(--color-accent), #ec4899); background: linear-gradient(90deg, var(--color-accent), #ec4899);
} }
.login-app.is-dark .brand-accent {
background: linear-gradient(90deg, #60a5fa, #1d4ed8);
}
.welcome { .welcome {
text-align: center; text-align: center;
color: var(--color-text); color: var(--color-text);