Simplify proxy routing and configuration
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user