From 2d6d3f6bbe18df261969a9d110f7bb22b90330f8 Mon Sep 17 00:00:00 2001 From: AmintaCCCP Date: Mon, 1 Jun 2026 21:51:03 +0800 Subject: [PATCH 1/2] fix: proxy toggle state not persisted when switching pages The proxy enable/disable toggle only updated local React state (setForm) without persisting to the Zustand store. Users expected the toggle to take effect immediately (standard UX for switches), but the change was lost when navigating away from the Network panel. Now the toggle immediately syncs the enabled state to: - Local form state (instant visual feedback) - Zustand store (survives page navigation) - Backend via PUT /api/settings/proxy (keeps server config in sync) - Electron main process via electronProxy.setProxy Fixes #183 Co-Authored-By: Claude Opus 4.8 --- src/components/settings/NetworkPanel.tsx | 26 +++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/components/settings/NetworkPanel.tsx b/src/components/settings/NetworkPanel.tsx index 5fe2b41d..b47ad403 100644 --- a/src/components/settings/NetworkPanel.tsx +++ b/src/components/settings/NetworkPanel.tsx @@ -119,7 +119,31 @@ export const NetworkPanel: React.FC = ({ t }) => { role="switch" aria-checked={form.enabled} aria-label={t('启用网络代理', 'Enable network proxy')} - onClick={() => setForm({ ...form, enabled: !form.enabled })} + onClick={async () => { + const newEnabled = !form.enabled; + const newForm = { ...form, enabled: newEnabled }; + setForm(newForm); + // 立即持久化 enabled 状态,无需用户手动点击保存 + setProxyConfig({ enabled: newEnabled }); + // 同步到后端 + if (backend.isAvailable) { + try { + const authHeaders: Record = { 'Content-Type': 'application/json' }; + if (backendApiSecret) { + authHeaders['Authorization'] = `Bearer ${backendApiSecret}`; + } + await fetch('/api/settings/proxy', { + method: 'PUT', + headers: authHeaders, + body: JSON.stringify({ ...proxyConfig, enabled: newEnabled }), + }); + } catch { /* best effort */ } + } + // 同步到 Electron + if (isElectron()) { + try { await electronProxy.setProxy(newForm); } catch { /* best effort */ } + } + }} className={`relative inline-flex h-5 w-9 items-center rounded-full transition-colors ${form.enabled ? 'bg-brand-indigo' : 'bg-gray-300 dark:bg-gray-600'}`} > Date: Mon, 1 Jun 2026 21:56:39 +0800 Subject: [PATCH 2/2] fix: use consistent payload (newForm) for store, backend and Electron sync Address CodeRabbit review: send identical newForm to all three targets instead of mixing { enabled }, { ...proxyConfig, enabled }, and newForm. Co-Authored-By: Claude Opus 4.8 --- src/components/settings/NetworkPanel.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/components/settings/NetworkPanel.tsx b/src/components/settings/NetworkPanel.tsx index b47ad403..773e83e7 100644 --- a/src/components/settings/NetworkPanel.tsx +++ b/src/components/settings/NetworkPanel.tsx @@ -120,11 +120,10 @@ export const NetworkPanel: React.FC = ({ t }) => { aria-checked={form.enabled} aria-label={t('启用网络代理', 'Enable network proxy')} onClick={async () => { - const newEnabled = !form.enabled; - const newForm = { ...form, enabled: newEnabled }; + const newForm = { ...form, enabled: !form.enabled }; setForm(newForm); - // 立即持久化 enabled 状态,无需用户手动点击保存 - setProxyConfig({ enabled: newEnabled }); + // 立即持久化,无需用户手动点击保存 + setProxyConfig(newForm); // 同步到后端 if (backend.isAvailable) { try { @@ -135,7 +134,7 @@ export const NetworkPanel: React.FC = ({ t }) => { await fetch('/api/settings/proxy', { method: 'PUT', headers: authHeaders, - body: JSON.stringify({ ...proxyConfig, enabled: newEnabled }), + body: JSON.stringify(newForm), }); } catch { /* best effort */ } }