World map imported from the local game files (public DES key + gzip, read-only), 485 zones / 723 portal connections, BFS router with safe-only vs all-zones modes and danger counts, haul advisor ranking items by trip profit per carry weight, Travel page + game-path setting. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
83 lines
2.9 KiB
TypeScript
83 lines
2.9 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
|
|
interface Settings {
|
|
albionServer: string;
|
|
availableServers: string[];
|
|
proxyUrl: string;
|
|
gamePath: string;
|
|
}
|
|
|
|
export default function SettingsPage() {
|
|
const [settings, setSettings] = useState<Settings | null>(null);
|
|
const [proxyUrl, setProxyUrl] = useState('');
|
|
const [gamePath, setGamePath] = useState('');
|
|
const [saved, setSaved] = useState(false);
|
|
|
|
useEffect(() => {
|
|
fetch('/api/settings')
|
|
.then((r) => r.json())
|
|
.then((s: Settings) => {
|
|
setSettings(s);
|
|
setProxyUrl(s.proxyUrl);
|
|
setGamePath(s.gamePath);
|
|
});
|
|
}, []);
|
|
|
|
const save = async (patch: Partial<{ albionServer: string; proxyUrl: string; gamePath: string }>) => {
|
|
await fetch('/api/settings', {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(patch),
|
|
});
|
|
const s = await fetch('/api/settings').then((r) => r.json());
|
|
setSettings(s);
|
|
setSaved(true);
|
|
setTimeout(() => setSaved(false), 2000);
|
|
};
|
|
|
|
if (!settings) return <p className="muted">Loading…</p>;
|
|
|
|
return (
|
|
<div>
|
|
<h2>Settings</h2>
|
|
<div className="card">
|
|
<h3>Albion server</h3>
|
|
<p className="muted">Which game server's market prices to download.</p>
|
|
<select value={settings.albionServer} onChange={(e) => save({ albionServer: e.target.value })}>
|
|
{settings.availableServers.map((s) => (
|
|
<option key={s} value={s}>{s}</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
<div className="card">
|
|
<h3>Proxy for market data (optional)</h3>
|
|
<p className="muted">
|
|
The market data API (albion-online-data.com) is blocked in some countries. If your VPN covers the whole
|
|
system, leave this empty. If it is browser-only, enter an HTTP proxy URL here (e.g.
|
|
http://127.0.0.1:8080) and market downloads will go through it.
|
|
</p>
|
|
<div style={{ display: 'flex', gap: 8 }}>
|
|
<input
|
|
type="text"
|
|
placeholder="http://host:port (empty = direct connection)"
|
|
value={proxyUrl}
|
|
onChange={(e) => setProxyUrl(e.target.value)}
|
|
/>
|
|
<button className="primary" onClick={() => save({ proxyUrl })}>Save</button>
|
|
</div>
|
|
{saved && <p style={{ color: '#7fd18a' }}>Saved.</p>}
|
|
</div>
|
|
<div className="card">
|
|
<h3>Albion game folder</h3>
|
|
<p className="muted">
|
|
Used to read the world map (travel planner) from the game's files — read-only. The folder that contains the
|
|
"game" directory, e.g. E:\albion.
|
|
</p>
|
|
<div style={{ display: 'flex', gap: 8 }}>
|
|
<input type="text" placeholder="E:\albion" value={gamePath} onChange={(e) => setGamePath(e.target.value)} />
|
|
<button className="primary" onClick={() => save({ gamePath })}>Save</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|