Simplify proxy routing and configuration

This commit is contained in:
2026-07-11 04:42:16 +03:00
parent efa46d1ee5
commit d3b7f0d613
22 changed files with 786 additions and 787 deletions

View File

@@ -33,10 +33,6 @@ function App() {
proxyDefaultMode: 'vpn',
devices: [],
});
const [clientSettings, setClientSettings] = useState({
homeBypassEnabled: false,
sharedProxyEnabled: false,
});
const [selectedTag, setSelectedTag] = useState('');
const [pendingTag, setPendingTag] = useState('');
const [busy, setBusy] = useState(false);
@@ -82,7 +78,6 @@ function App() {
proxyDefaultMode: 'vpn',
devices: data.devices || [],
});
setClientSettings(data.clientSettings || { homeBypassEnabled: false, sharedProxyEnabled: false });
setSelectedTag((prev) => prev || data.selectedTag || '');
setPendingTag((prev) => prev || data.selectedTag || '');
}
@@ -109,7 +104,9 @@ function App() {
setError('');
try {
const result = await fn();
if (!quiet && label) pushToast({ kind: 'success', title: label });
if (!quiet && label && state?.mode !== 'client') {
pushToast({ kind: 'success', title: label });
}
return result;
} catch (err) {
setError(err.message);
@@ -125,9 +122,12 @@ function App() {
return withBusy('Подписка обновлена', async () => {
const data = await api.subscription.fetch(subscriptionUrl || state?.subscriptionHost || '');
setServers(data.servers || []);
if (!selectedTag && data.servers?.length) {
setSelectedTag(data.servers[0].tag);
setPendingTag(data.servers[0].tag);
if (data.servers?.length) {
const nextTag = data.servers.some((server) => server.tag === selectedTag)
? selectedTag
: data.servers[0].tag;
setSelectedTag(nextTag);
setPendingTag(nextTag);
}
await loadState();
});
@@ -158,7 +158,7 @@ function App() {
});
setApplyStatus('idle');
if (previous && previous !== target) {
if (state?.mode !== 'client' && previous && previous !== target) {
setRollbackOffer({ from: target, to: previous, expiresAt: Date.now() + ROLLBACK_WINDOW_MS });
if (rollbackTimerRef.current) clearTimeout(rollbackTimerRef.current);
rollbackTimerRef.current = setTimeout(() => setRollbackOffer(null), ROLLBACK_WINDOW_MS);
@@ -180,8 +180,8 @@ function App() {
}
// === sing-box control ===
async function stopSingbox() {
if (!confirm('Остановить sing-box? Трафик через шлюз перестанет ходить.')) return;
async function stopSingbox(confirmFirst = true) {
if (confirmFirst && !confirm('Остановить sing-box? Трафик через шлюз перестанет ходить.')) return;
return withBusy('Остановлено', async () => { await api.singbox.stop(); await loadState(); });
}
async function restartSingbox() {
@@ -278,22 +278,6 @@ function App() {
saveDevicesConfig(nextConfig);
}
async function saveClientSettings(nextSettings) {
return withBusy(null, async () => {
const data = await api.clientSettings.save(nextSettings);
setClientSettings(data.clientSettings || { homeBypassEnabled: false, sharedProxyEnabled: false });
await loadState();
}, { quiet: true });
}
async function checkSharedProxy(url) {
return withBusy('Общий proxy подключён', async () => {
const data = await api.clientSettings.checkSharedProxy(url);
setClientSettings(data.clientSettings || { homeBypassEnabled: false, sharedProxyEnabled: false });
await loadState();
});
}
// === Rules CRUD ===
function emptyRule() {
return {
@@ -410,16 +394,20 @@ function App() {
};
// === Render ===
if (!state) return <div className="app-loading">VPN</div>;
return (
<div className="app">
<Topbar
state={state}
status={status}
activeServer={activeServer}
dirty={dirty}
onRestart={restartSingbox}
onTryApply={rollback}
/>
<div className={`app${isClientMode ? ' client-app' : ''}`}>
{!isClientMode && (
<Topbar
state={state}
status={status}
activeServer={activeServer}
dirty={dirty}
onRestart={restartSingbox}
onTryApply={rollback}
/>
)}
<div className={`app-body${isClientMode ? ' client-mode' : ''}`}>
{!isClientMode && <Sidebar active={page} onChange={navigate} badges={sidebarBadges} mode={state?.mode} />}
@@ -437,13 +425,10 @@ function App() {
servers={servers}
pendingTag={pendingTag}
setPendingTag={setPendingTag}
clientSettings={clientSettings}
onSaveClientSettings={saveClientSettings}
onCheckSharedProxy={checkSharedProxy}
onFetchSubscription={fetchSubscription}
onApply={applyServer}
onRestart={restartSingbox}
onStop={stopSingbox}
onStop={() => stopSingbox(false)}
/>
) : (
<OverviewPage