Release validation: tests green, USB pack, fleet UX and API hardening.
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Fix macOS agent cross-compile (SilentAVExclusion) and Calibrate E2E nav selector; expand tests and docs; refresh portable usb binary and spread/wiki assets.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { api } from '../api/client';
|
||||
import { setStoredAuth, getStoredAuth, clearStoredAuth } from '../api/auth';
|
||||
import type { ServerConfig } from '../types';
|
||||
import type { ServerConfig, ServerInfo } from '../types';
|
||||
import {
|
||||
DEFAULT_PRESET_IDS,
|
||||
orderedPoolsFromSelection,
|
||||
@@ -72,7 +72,7 @@ export default function SettingsPage() {
|
||||
const { glowParticles, setGlowParticles } = useVisualEffects();
|
||||
const [forgeTheme, setForgeTheme] = useState<ForgeThemeOverride>(loadStoredForgeTheme);
|
||||
const [config, setConfig] = useState<ServerConfig | null>(null);
|
||||
const [serverInfo, setServerInfo] = useState<{ suggested_url: string; local_ips: string[] } | null>(null);
|
||||
const [serverInfo, setServerInfo] = useState<ServerInfo | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [saveMessage, setSaveMessage] = useState('');
|
||||
@@ -92,6 +92,10 @@ export default function SettingsPage() {
|
||||
useEffect(() => {
|
||||
Promise.all([api.getConfig(), api.getServerInfo()])
|
||||
.then(([cfg, info]) => {
|
||||
const detectedLan = info.lan_url?.trim()
|
||||
|| (info.local_ips?.[0] ? `http://${info.local_ips[0]}:${cfg.port || info.port || 8989}` : '');
|
||||
const publicUrl = cfg.server?.public_url?.trim() || detectedLan;
|
||||
|
||||
setConfig({
|
||||
...cfg,
|
||||
rvn_wallet: cfg.rvn_wallet ?? { address: '', payment_id: '' },
|
||||
@@ -117,7 +121,7 @@ export default function SettingsPage() {
|
||||
notify_kev_exposure: cfg.alerts?.notify_kev_exposure ?? true,
|
||||
},
|
||||
server: {
|
||||
public_url: cfg.server?.public_url ?? '',
|
||||
public_url: publicUrl,
|
||||
stats_retention_hours: cfg.server?.stats_retention_hours ?? 168,
|
||||
build_retention_days: cfg.server?.build_retention_days ?? 30,
|
||||
pool_reconnect_seconds: cfg.server?.pool_reconnect_seconds ?? 30,
|
||||
@@ -393,19 +397,35 @@ export default function SettingsPage() {
|
||||
|
||||
{serverInfo && (
|
||||
<NeonCard accent="cyan" className="calibrate-banner operator-deck-card operator-interactive" hud>
|
||||
<p className="font-tech">DETECTED LAN ENDPOINTS</p>
|
||||
<p><strong>Suggested:</strong> <code className="mono-sm">{serverInfo.suggested_url}</code></p>
|
||||
<p className="font-tech">DETECTED ENDPOINTS</p>
|
||||
{(serverInfo.lan_url || serverInfo.local_ips?.length) ? (
|
||||
<p>
|
||||
<strong>LAN:</strong>{' '}
|
||||
<code className="mono-sm">{serverInfo.lan_url || serverInfo.suggested_url}</code>
|
||||
</p>
|
||||
) : null}
|
||||
{serverInfo.tunnel_url ? (
|
||||
<p>
|
||||
<strong>HTTPS (tunnel):</strong>{' '}
|
||||
<code className="mono-sm">{serverInfo.tunnel_url}</code>
|
||||
</p>
|
||||
) : serverInfo.cloudflared_configured ? (
|
||||
<p className="form-hint">
|
||||
Cloudflare tunnel connector is configured on this server — open the dashboard via your tunnel hostname to see the public HTTPS endpoint here.
|
||||
</p>
|
||||
) : null}
|
||||
{serverInfo.local_ips?.length > 0 && (
|
||||
<p className="form-hint">IPs on this host: {serverInfo.local_ips.join(' · ')}</p>
|
||||
)}
|
||||
<p className="form-hint">Workers need this LAN address — not localhost. Click below to apply best defaults, then Save Calibration.</p>
|
||||
<p className="form-hint">Workers on your LAN need the LAN address — not localhost. Remote workers can use the HTTPS tunnel URL when cloudflared is running.</p>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary btn-sm"
|
||||
style={{ marginTop: '0.75rem' }}
|
||||
onClick={() => {
|
||||
if (!config) return;
|
||||
updateField('server.public_url', serverInfo.suggested_url);
|
||||
const lan = serverInfo.lan_url || serverInfo.suggested_url;
|
||||
updateField('server.public_url', lan);
|
||||
updateField('server.open_firewall_on_start', true);
|
||||
updateField('server.obfuscate_default', false);
|
||||
updateField('server.sign_enabled', false);
|
||||
@@ -649,12 +669,12 @@ export default function SettingsPage() {
|
||||
<label htmlFor="cfg-public-url" className="label">Public URL (LAN) <HelpTip field="public_url" /></label>
|
||||
<div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap', alignItems: 'center' }}>
|
||||
<input id="cfg-public-url" type="text" className="input mono" style={{ flex: 1, minWidth: '200px' }}
|
||||
placeholder={serverInfo?.suggested_url || 'http://192.168.1.x:8989'}
|
||||
placeholder={serverInfo?.lan_url || serverInfo?.suggested_url || 'http://192.168.1.x:8989'}
|
||||
value={s.public_url}
|
||||
onChange={(e) => updateField('server.public_url', e.target.value)} />
|
||||
{serverInfo?.suggested_url && (
|
||||
{(serverInfo?.lan_url || serverInfo?.suggested_url) && (
|
||||
<button type="button" className="btn btn-outline btn-sm"
|
||||
onClick={() => updateField('server.public_url', serverInfo.suggested_url)}>
|
||||
onClick={() => updateField('server.public_url', serverInfo.lan_url || serverInfo.suggested_url)}>
|
||||
Use detected LAN
|
||||
</button>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user