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/
bin/
dist/
!web/dist/
web/dist/*
!web/dist/.gitkeep
release/
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 { Button, Divider, Modal, Space, Tabs, Tag, Tooltip } from 'antd';
import { getMessage } from '@/utils/messageBus';
@ -802,59 +802,86 @@ export default function InboundInfoModal({
)}
{dbInbound.isWireguard && inbound.settings && (
<table className="info-table protocol-table wg-table">
<tbody>
<tr><td>Secret key</td><td>{inbound.settings.secretKey as string}</td></tr>
<tr><td>Public key</td><td>{inbound.settings.pubKey as string}</td></tr>
<tr><td>MTU</td><td>{inbound.settings.mtu as number}</td></tr>
<tr><td>No-kernel TUN</td><td>{String(inbound.settings.noKernelTun)}</td></tr>
{Array.isArray(inbound.settings.peers) && (inbound.settings.peers as { privateKey: string; publicKey: string; psk: string; allowedIPs?: string[]; keepAlive?: number }[]).map((peer, idx) => (
<>
<tr key={`p-h-${idx}`}>
<td colSpan={2}><Divider>Peer {idx + 1}</Divider></td>
</tr>
<tr key={`p-sk-${idx}`}><td>Secret key</td><td>{peer.privateKey}</td></tr>
<tr key={`p-pk-${idx}`}><td>Public key</td><td>{peer.publicKey}</td></tr>
<tr key={`p-psk-${idx}`}><td>PSK</td><td>{peer.psk}</td></tr>
<tr key={`p-ai-${idx}`}><td>Allowed IPs</td><td>{(peer.allowedIPs || []).join(',')}</td></tr>
<tr key={`p-ka-${idx}`}><td>Keep alive</td><td>{peer.keepAlive}</td></tr>
{wireguardConfigs[idx] && (
<tr key={`p-conf-${idx}`}>
<td colSpan={2}>
<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>
</td>
</tr>
)}
{wireguardLinks[idx] && (
<tr key={`p-link-${idx}`}>
<td colSpan={2}>
<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>
</td>
</tr>
)}
</>
))}
</tbody>
</table>
<>
<dl className="info-list info-list-block">
<div className="info-row">
<dt>Secret key</dt>
<dd><Tag className="value-tag">{inbound.settings.secretKey as string}</Tag></dd>
</div>
<div className="info-row">
<dt>Public key</dt>
<dd><Tag className="value-tag">{inbound.settings.pubKey as string}</Tag></dd>
</div>
<div className="info-row">
<dt>MTU</dt>
<dd><Tag>{inbound.settings.mtu as number}</Tag></dd>
</div>
<div className="info-row">
<dt>No-kernel TUN</dt>
<dd>
<Tag color={inbound.settings.noKernelTun ? 'green' : 'default'}>
{String(inbound.settings.noKernelTun)}
</Tag>
</dd>
</div>
</dl>
{Array.isArray(inbound.settings.peers) && (inbound.settings.peers as { privateKey: string; publicKey: string; psk: string; allowedIPs?: string[]; keepAlive?: number }[]).map((peer, idx) => (
<Fragment key={idx}>
<Divider>Peer {idx + 1}</Divider>
<dl className="info-list info-list-block">
<div className="info-row">
<dt>Secret key</dt>
<dd><Tag className="value-tag">{peer.privateKey}</Tag></dd>
</div>
<div className="info-row">
<dt>Public key</dt>
<dd><Tag className="value-tag">{peer.publicKey}</Tag></dd>
</div>
<div className="info-row">
<dt>PSK</dt>
<dd><Tag className="value-tag">{peer.psk}</Tag></dd>
</div>
<div className="info-row">
<dt>Allowed IPs</dt>
<dd>
{(peer.allowedIPs || []).map((ip, j) => (
<Tag key={`wg-ip-${idx}-${j}`} className="value-tag">{ip}</Tag>
))}
</dd>
</div>
<div className="info-row">
<dt>Keep alive</dt>
<dd><Tag>{peer.keepAlive}</Tag></dd>
</div>
</dl>
{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 && (

View file

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