From d9ae0f3263dc70c266d44e01dcf85c47b0f44d09 Mon Sep 17 00:00:00 2001 From: DigHuang <114602213+DigHuang@users.noreply.github.com> Date: Tue, 10 Mar 2026 14:48:54 +0800 Subject: [PATCH] feat(ui): redesign settings page and update sidebar navigation (#383) --- pnpm-lock.yaml | 158 +++-- src/App.tsx | 2 - src/components/layout/Sidebar.tsx | 38 +- src/pages/Chat/ChatInput.tsx | 9 +- src/pages/Dashboard/index.tsx | 324 ---------- src/pages/Settings/index.tsx | 993 ++++++++++++++---------------- 6 files changed, 618 insertions(+), 906 deletions(-) delete mode 100644 src/pages/Dashboard/index.tsx diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3d16afe93..d6cbbb8cb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -65,7 +65,7 @@ importers: version: 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@sliverp/qqbot': specifier: ^1.5.4 - version: 1.5.4(clawdbot@2026.1.24-3(@discordjs/opus@0.10.0(encoding@0.1.13))(@types/express@5.0.6)(devtools-protocol@0.0.1595872)(encoding@0.1.13)(opusscript@0.1.1)(typescript@5.9.3))(moltbot@0.1.0)(openclaw@2026.3.1(@napi-rs/canvas@0.1.95)(@types/express@5.0.6)(encoding@0.1.13)(hono@4.11.8)(node-llama-cpp@3.16.2(typescript@5.9.3))) + version: 1.5.4(clawdbot@2026.1.24-3(@discordjs/opus@0.10.0(encoding@0.1.13))(@types/express@5.0.6)(devtools-protocol@0.0.1596832)(encoding@0.1.13)(opusscript@0.1.1)(typescript@5.9.3))(moltbot@0.1.0)(openclaw@2026.3.1(@napi-rs/canvas@0.1.95)(@types/express@5.0.6)(encoding@0.1.13)(hono@4.11.8)(node-llama-cpp@3.16.2(typescript@5.9.3))) '@soimy/dingtalk': specifier: ^3.1.4 version: 3.1.4(openclaw@2026.3.1(@napi-rs/canvas@0.1.95)(@types/express@5.0.6)(encoding@0.1.13)(hono@4.11.8)(node-llama-cpp@3.16.2(typescript@5.9.3))) @@ -1384,6 +1384,34 @@ packages: os: [linux] libc: [glibc] + '@node-llama-cpp/linux-x64-cuda-ext@3.15.0': + resolution: {integrity: sha512-wQwgSl7Qm8vH56oBt7IuWWDNNsDECkVMS000C92wl3PkbzjwZFiWzehwa+kF8Lr2BBMiCJNkI5nEabhYH3RN2Q==} + engines: {node: '>=20.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@node-llama-cpp/linux-x64-cuda-ext@3.16.2': + resolution: {integrity: sha512-47d9myCJauZyzAlN7IK1eIt/4CcBMslF+yHy4q+yJotD/RV/S6qRpK2kGn+ybtdVjkPGNCoPkHKcyla9iIVjbw==} + engines: {node: '>=20.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@node-llama-cpp/linux-x64-cuda@3.15.0': + resolution: {integrity: sha512-mDjyVulCTRYilm9Emm3lDMx7dbI1vzGqk28Pj28shartjERTUu8aUNDYOmVKNMLpUKS1akw7vy0lMF8t4qswxQ==} + engines: {node: '>=20.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@node-llama-cpp/linux-x64-cuda@3.16.2': + resolution: {integrity: sha512-LTBQFqjin7tyrLNJz0XWTB5QAHDsZV71/qiiRRjXdBKSZHVVaPLfdgxypGu7ggPeBNsv+MckRXdlH5C7yMtE4A==} + engines: {node: '>=20.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + '@node-llama-cpp/linux-x64-vulkan@3.15.0': resolution: {integrity: sha512-htVIthQKq/rr8v5e7NiVtcHsstqTBAAC50kUymmDMbrzAu6d/EHacCJpNbU57b1UUa1nKN5cBqr6Jr+QqEalMA==} engines: {node: '>=20.0.0'} @@ -1448,6 +1476,42 @@ packages: cpu: [arm64, x64] os: [win32] + '@node-llama-cpp/win-x64-cuda-ext@3.15.0': + resolution: {integrity: sha512-KQoNH9KsVtqGVXaRdPrnHPrg5w3KOM7CfynPmG1m16gmjmDSIspdPg/Dbg6DgHBfkdAzt+duRZEBk8Bg8KbDHw==} + engines: {node: '>=20.0.0'} + cpu: [x64] + os: [win32] + + '@node-llama-cpp/win-x64-cuda-ext@3.16.2': + resolution: {integrity: sha512-sdv4Kzn9bOQWNBRvw6B/zcn8dQRfZhjIHv5AfDBIOfRlSCgjebFpBeYUoU4wZPpjr3ISwcqO5MEWsw+AbUdV3Q==} + engines: {node: '>=20.0.0'} + cpu: [x64] + os: [win32] + + '@node-llama-cpp/win-x64-cuda@3.15.0': + resolution: {integrity: sha512-2Kyu1roDwXwFLaJgGZQISIXP9lCDZtJCx/DRcmrYRHcSUFCzo5ikOuAECyliSSQmRUAvvlRCuD+GrTcegbhojA==} + engines: {node: '>=20.0.0'} + cpu: [x64] + os: [win32] + + '@node-llama-cpp/win-x64-cuda@3.16.2': + resolution: {integrity: sha512-jStDELHrU3rKQMOk5Hs5bWEazyjE2hzHwpNf6SblOpaGkajM/HJtxEZoL0mLHJx5qeXs4oOVkr7AzuLy0WPpNA==} + engines: {node: '>=20.0.0'} + cpu: [x64] + os: [win32] + + '@node-llama-cpp/win-x64-vulkan@3.15.0': + resolution: {integrity: sha512-sH+K7lO49WrUvCCC3RPddCBrn2ZQwKCXKL90P/NZicMRgxTPFZEVSU2jXR/bu1K8B+4lNN+z5OEbjSYs7cKEcA==} + engines: {node: '>=20.0.0'} + cpu: [x64] + os: [win32] + + '@node-llama-cpp/win-x64-vulkan@3.16.2': + resolution: {integrity: sha512-9xuHFCOhCQjZgQSFrk79EuSKn9nGWt/SAq/3wujQSQLtgp8jGdtZgwcmuDUoemInf10en2dcOmEt7t8dQdC3XA==} + engines: {node: '>=20.0.0'} + cpu: [x64] + os: [win32] + '@node-llama-cpp/win-x64@3.15.0': resolution: {integrity: sha512-gWhtc8l3HOry5guO46YfFohLQnF0NfL4On0GAO8E27JiYYxHO9nHSCfFif4+U03+FfHquZXL0znJ1qPVOiwOPw==} engines: {node: '>=20.0.0'} @@ -3597,8 +3661,8 @@ packages: devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} - devtools-protocol@0.0.1595872: - resolution: {integrity: sha512-kRfgp8vWVjBu/fbYCiVFiOqsCk3CrMKEo3WbgGT2NXK2dG7vawWPBljixajVgGK9II8rDO9G0oD0zLt3I1daRg==} + devtools-protocol@0.0.1596832: + resolution: {integrity: sha512-IwRVIiCa4mpaKeLcZ2cmGpG0hP8ls3zj3zg87Z/JwULm2xYmhOcMrwdeHos6xaANQHGEXzSCzji+6kEuZu873A==} didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} @@ -4141,6 +4205,7 @@ packages: glob@11.1.0: resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==} engines: {node: 20 || >=22} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true glob@13.0.6: @@ -4353,11 +4418,6 @@ packages: resolution: {integrity: sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==} engines: {node: '>= 10'} - ipull@3.9.3: - resolution: {integrity: sha512-ZMkxaopfwKHwmEuGDYx7giNBdLxbHbRCWcQVA1D2eqE4crUguupfxej6s7UqbidYEwT69dkyumYkY8DPHIxF9g==} - engines: {node: '>=18.0.0'} - hasBin: true - ipull@3.9.5: resolution: {integrity: sha512-5w/yZB5lXmTfsvNawmvkCjYo4SJNuKQz/av8TC1UiOyfOHyaM+DReqbpU2XpWYfmY+NIUbRRH8PUAWsxaS+IfA==} engines: {node: '>=18.0.0'} @@ -6125,6 +6185,7 @@ packages: tar@7.5.4: resolution: {integrity: sha512-AN04xbWGrSTDmVwlI4/GTlIIwMFk/XEv7uL8aa57zuvRy6s4hdBed+lVq2fAZ89XDa7Us3ANXcE3Tvqvja1kTA==} engines: {node: '>=18'} + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me tar@7.5.9: resolution: {integrity: sha512-BTLcK0xsDh2+PUe9F6c2TlRp4zOOBMTkoQHQIWSIzI0R7KG46uEwq4OPk2W7bZcprBMsuaeFsqwYr7pjh6CuHg==} @@ -8273,6 +8334,18 @@ snapshots: '@node-llama-cpp/linux-armv7l@3.16.2': optional: true + '@node-llama-cpp/linux-x64-cuda-ext@3.15.0': + optional: true + + '@node-llama-cpp/linux-x64-cuda-ext@3.16.2': + optional: true + + '@node-llama-cpp/linux-x64-cuda@3.15.0': + optional: true + + '@node-llama-cpp/linux-x64-cuda@3.16.2': + optional: true + '@node-llama-cpp/linux-x64-vulkan@3.15.0': optional: true @@ -8303,6 +8376,24 @@ snapshots: '@node-llama-cpp/win-arm64@3.16.2': optional: true + '@node-llama-cpp/win-x64-cuda-ext@3.15.0': + optional: true + + '@node-llama-cpp/win-x64-cuda-ext@3.16.2': + optional: true + + '@node-llama-cpp/win-x64-cuda@3.15.0': + optional: true + + '@node-llama-cpp/win-x64-cuda@3.16.2': + optional: true + + '@node-llama-cpp/win-x64-vulkan@3.15.0': + optional: true + + '@node-llama-cpp/win-x64-vulkan@3.16.2': + optional: true + '@node-llama-cpp/win-x64@3.15.0': optional: true @@ -9145,9 +9236,9 @@ snapshots: transitivePeerDependencies: - debug - '@sliverp/qqbot@1.5.4(clawdbot@2026.1.24-3(@discordjs/opus@0.10.0(encoding@0.1.13))(@types/express@5.0.6)(devtools-protocol@0.0.1595872)(encoding@0.1.13)(opusscript@0.1.1)(typescript@5.9.3))(moltbot@0.1.0)(openclaw@2026.3.1(@napi-rs/canvas@0.1.95)(@types/express@5.0.6)(encoding@0.1.13)(hono@4.11.8)(node-llama-cpp@3.16.2(typescript@5.9.3)))': + '@sliverp/qqbot@1.5.4(clawdbot@2026.1.24-3(@discordjs/opus@0.10.0(encoding@0.1.13))(@types/express@5.0.6)(devtools-protocol@0.0.1596832)(encoding@0.1.13)(opusscript@0.1.1)(typescript@5.9.3))(moltbot@0.1.0)(openclaw@2026.3.1(@napi-rs/canvas@0.1.95)(@types/express@5.0.6)(encoding@0.1.13)(hono@4.11.8)(node-llama-cpp@3.16.2(typescript@5.9.3)))': dependencies: - clawdbot: 2026.1.24-3(@discordjs/opus@0.10.0(encoding@0.1.13))(@types/express@5.0.6)(devtools-protocol@0.0.1595872)(encoding@0.1.13)(opusscript@0.1.1)(typescript@5.9.3) + clawdbot: 2026.1.24-3(@discordjs/opus@0.10.0(encoding@0.1.13))(@types/express@5.0.6)(devtools-protocol@0.0.1596832)(encoding@0.1.13)(opusscript@0.1.1)(typescript@5.9.3) moltbot: 0.1.0 openclaw: 2026.3.1(@napi-rs/canvas@0.1.95)(@types/express@5.0.6)(encoding@0.1.13)(hono@4.11.8)(node-llama-cpp@3.16.2(typescript@5.9.3)) @@ -10373,9 +10464,9 @@ snapshots: chownr@3.0.0: {} - chromium-bidi@13.0.1(devtools-protocol@0.0.1595872): + chromium-bidi@13.0.1(devtools-protocol@0.0.1596832): dependencies: - devtools-protocol: 0.0.1595872 + devtools-protocol: 0.0.1596832 mitt: 3.0.1 zod: 3.25.76 @@ -10389,7 +10480,7 @@ snapshots: dependencies: clsx: 2.1.1 - clawdbot@2026.1.24-3(@discordjs/opus@0.10.0(encoding@0.1.13))(@types/express@5.0.6)(devtools-protocol@0.0.1595872)(encoding@0.1.13)(opusscript@0.1.1)(typescript@5.9.3): + clawdbot@2026.1.24-3(@discordjs/opus@0.10.0(encoding@0.1.13))(@types/express@5.0.6)(devtools-protocol@0.0.1596832)(encoding@0.1.13)(opusscript@0.1.1)(typescript@5.9.3): dependencies: '@agentclientprotocol/sdk': 0.13.1(zod@4.3.6) '@aws-sdk/client-bedrock': 3.1000.0 @@ -10413,7 +10504,7 @@ snapshots: body-parser: 2.2.2 chalk: 5.6.2 chokidar: 5.0.0 - chromium-bidi: 13.0.1(devtools-protocol@0.0.1595872) + chromium-bidi: 13.0.1(devtools-protocol@0.0.1596832) cli-highlight: 2.1.11 commander: 14.0.3 croner: 9.1.0 @@ -10751,7 +10842,7 @@ snapshots: dependencies: dequal: 2.0.3 - devtools-protocol@0.0.1595872: {} + devtools-protocol@0.0.1596832: {} didyoumean@1.2.2: {} @@ -11710,31 +11801,6 @@ snapshots: ipaddr.js@2.3.0: {} - ipull@3.9.3: - dependencies: - '@tinyhttp/content-disposition': 2.2.4 - async-retry: 1.3.3 - chalk: 5.6.2 - ci-info: 4.4.0 - cli-spinners: 2.9.2 - commander: 10.0.1 - eventemitter3: 5.0.4 - filenamify: 6.0.0 - fs-extra: 11.3.3 - is-unicode-supported: 2.1.0 - lifecycle-utils: 2.1.0 - lodash.debounce: 4.0.8 - lowdb: 7.0.1 - pretty-bytes: 6.1.1 - pretty-ms: 8.0.0 - sleep-promise: 9.1.0 - slice-ansi: 7.1.2 - stdout-update: 4.0.1 - strip-ansi: 7.1.2 - optionalDependencies: - '@reflink/reflink': 0.1.19 - optional: true - ipull@3.9.5: dependencies: '@tinyhttp/content-disposition': 2.2.4 @@ -12685,7 +12751,7 @@ snapshots: filenamify: 6.0.0 fs-extra: 11.3.3 ignore: 7.0.5 - ipull: 3.9.3 + ipull: 3.9.5 is-unicode-supported: 2.1.0 lifecycle-utils: 3.1.1 log-symbols: 7.0.1 @@ -12707,11 +12773,16 @@ snapshots: '@node-llama-cpp/linux-arm64': 3.15.0 '@node-llama-cpp/linux-armv7l': 3.15.0 '@node-llama-cpp/linux-x64': 3.15.0 + '@node-llama-cpp/linux-x64-cuda': 3.15.0 + '@node-llama-cpp/linux-x64-cuda-ext': 3.15.0 '@node-llama-cpp/linux-x64-vulkan': 3.15.0 '@node-llama-cpp/mac-arm64-metal': 3.15.0 '@node-llama-cpp/mac-x64': 3.15.0 '@node-llama-cpp/win-arm64': 3.15.0 '@node-llama-cpp/win-x64': 3.15.0 + '@node-llama-cpp/win-x64-cuda': 3.15.0 + '@node-llama-cpp/win-x64-cuda-ext': 3.15.0 + '@node-llama-cpp/win-x64-vulkan': 3.15.0 typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -12752,11 +12823,16 @@ snapshots: '@node-llama-cpp/linux-arm64': 3.16.2 '@node-llama-cpp/linux-armv7l': 3.16.2 '@node-llama-cpp/linux-x64': 3.16.2 + '@node-llama-cpp/linux-x64-cuda': 3.16.2 + '@node-llama-cpp/linux-x64-cuda-ext': 3.16.2 '@node-llama-cpp/linux-x64-vulkan': 3.16.2 '@node-llama-cpp/mac-arm64-metal': 3.16.2 '@node-llama-cpp/mac-x64': 3.16.2 '@node-llama-cpp/win-arm64': 3.16.2 '@node-llama-cpp/win-x64': 3.16.2 + '@node-llama-cpp/win-x64-cuda': 3.16.2 + '@node-llama-cpp/win-x64-cuda-ext': 3.16.2 + '@node-llama-cpp/win-x64-vulkan': 3.16.2 typescript: 5.9.3 transitivePeerDependencies: - supports-color diff --git a/src/App.tsx b/src/App.tsx index 39b37219a..a7b47ea19 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -9,7 +9,6 @@ import { Toaster } from 'sonner'; import i18n from './i18n'; import { MainLayout } from './components/layout/MainLayout'; import { TooltipProvider } from '@/components/ui/tooltip'; -import { Dashboard } from './pages/Dashboard'; import { Models } from './pages/Models'; import { Chat } from './pages/Chat'; import { Channels } from './pages/Channels'; @@ -166,7 +165,6 @@ function App() { }> } /> } /> - } /> } /> } /> } /> diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx index a8f29b2c0..e58a19d57 100644 --- a/src/components/layout/Sidebar.tsx +++ b/src/components/layout/Sidebar.tsx @@ -17,7 +17,6 @@ import { ExternalLink, Trash2, Cpu, - LayoutDashboard, } from 'lucide-react'; import { cn } from '@/lib/utils'; import { useSettingsStore } from '@/stores/settings'; @@ -105,7 +104,6 @@ const INITIAL_NOW_MS = Date.now(); export function Sidebar() { const sidebarCollapsed = useSettingsStore((state) => state.sidebarCollapsed); const setSidebarCollapsed = useSettingsStore((state) => state.setSidebarCollapsed); - const devModeUnlocked = useSettingsStore((state) => state.devModeUnlocked); const sessions = useChatStore((s) => s.sessions); const currentSessionKey = useChatStore((s) => s.currentSessionKey); @@ -173,7 +171,6 @@ export function Sidebar() { { to: '/channels', icon: , label: t('sidebar.channels') }, { to: '/skills', icon: , label: t('sidebar.skills') }, { to: '/cron', icon: , label: t('sidebar.cronTasks') }, - { to: '/dashboard', icon: , label: t('sidebar.dashboard') }, ]; return ( @@ -286,21 +283,6 @@ export function Sidebar() { {/* Footer */}
- {devModeUnlocked && !sidebarCollapsed && ( - - )} - @@ -321,6 +303,26 @@ export function Sidebar() { )} + +
([]); const textareaRef = useRef(null); const isComposingRef = useRef(false); + const gatewayStatus = useGatewayStore((s) => s.status); // Auto-resize textarea useEffect(() => { @@ -407,7 +409,12 @@ export function ChatInput({ onSend, onStop, disabled = false, sending = false, i
- Tip: switch sessions from the sidebar to keep context clean. +
+
+ + gateway {gatewayStatus.state === 'running' ? 'connected' : gatewayStatus.state} | port: {gatewayStatus.port} {gatewayStatus.pid ? `| pid: ${gatewayStatus.pid}` : ''} + +
{hasFailedAttachments && ( - - - - - - {devModeUnlocked && ( - - )} -
- - - - {/* Recent Activity */} -
- {/* Connected Channels */} - - - {t('connectedChannels')} - - - {(!Array.isArray(channels) || channels.length === 0) ? ( - - {t('addFirst')} - - )} - /> - ) : ( -
- {channels.slice(0, 5).map((channel) => ( -
-
- - {channel.type === 'whatsapp' && '📱'} - {channel.type === 'telegram' && '✈️'} - {channel.type === 'discord' && '🎮'} - -
-

{channel.name}

-

- {channel.type} -

-
-
- -
- ))} -
- )} -
-
- - {/* Enabled Skills */} - - - {t('activeSkills')} - - - {(!Array.isArray(skills) || skills.filter((s) => s.enabled).length === 0) ? ( - - {t('enableSome')} - - )} - /> - ) : ( -
- {skills - .filter((s) => s.enabled) - .slice(0, 12) - .map((skill) => ( - - {skill.icon && {skill.icon}} - {skill.name} - - ))} - {skills.filter((s) => s.enabled).length > 12 && ( - - {t('more', { count: skills.filter((s) => s.enabled).length - 12 })} - - )} -
- )} -
-
-
-
- ); -} - -/** - * Format uptime in human-readable format - */ -function formatUptime(seconds: number): string { - const days = Math.floor(seconds / 86400); - const hours = Math.floor((seconds % 86400) / 3600); - const minutes = Math.floor((seconds % 3600) / 60); - - if (days > 0) { - return `${days}d ${hours}h`; - } else if (hours > 0) { - return `${hours}h ${minutes}m`; - } else { - return `${minutes}m`; - } -} - -export default Dashboard; diff --git a/src/pages/Settings/index.tsx b/src/pages/Settings/index.tsx index 07e5ef60e..037b59d01 100644 --- a/src/pages/Settings/index.tsx +++ b/src/pages/Settings/index.tsx @@ -8,16 +8,11 @@ import { Moon, Monitor, RefreshCw, - Terminal, ExternalLink, - Download, Copy, - ChevronDown, - ChevronRight, FileText, } from 'lucide-react'; import { Button } from '@/components/ui/button'; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Label } from '@/components/ui/label'; import { Switch } from '@/components/ui/switch'; import { Separator } from '@/components/ui/separator'; @@ -44,6 +39,7 @@ import { import { useTranslation } from 'react-i18next'; import { SUPPORTED_LANGUAGES } from '@/i18n'; import { hostApiFetch } from '@/lib/host-api'; +import { cn } from '@/lib/utils'; type ControlUiInfo = { url: string; token: string; @@ -91,7 +87,6 @@ export function Settings() { const [proxyAllServerDraft, setProxyAllServerDraft] = useState(''); const [proxyBypassRulesDraft, setProxyBypassRulesDraft] = useState(''); const [proxyEnabledDraft, setProxyEnabledDraft] = useState(false); - const [showAdvancedProxy, setShowAdvancedProxy] = useState(false); const [savingProxy, setSavingProxy] = useState(false); const [wsDiagnosticEnabled, setWsDiagnosticEnabled] = useState(false); const [showTelemetryViewer, setShowTelemetryViewer] = useState(false); @@ -124,27 +119,7 @@ export function Settings() { } }; - // Open developer console - const openDevConsole = async () => { - try { - const result = await hostApiFetch<{ - success: boolean; - url?: string; - token?: string; - port?: number; - error?: string; - }>('/api/gateway/control-ui'); - if (result.success && result.url && result.token && typeof result.port === 'number') { - setControlUiInfo({ url: result.url, token: result.token, port: result.port }); - trackUiEvent('settings.open_dev_console'); - window.electron.openExternal(result.url); - } else { - console.error('Failed to get Dev Console URL:', result.error); - } - } catch (err) { - console.error('Error opening Dev Console:', err); - } - }; + const refreshControlUiInfo = async () => { try { @@ -390,164 +365,182 @@ export function Settings() { }; return ( -
-
-

{t('title')}

-

- {t('subtitle')} -

-
- - {/* Appearance */} - - - {t('appearance.title')} - {t('appearance.description')} - - -
- -
- - - -
+
+
+ + {/* Header */} +
+
+

+ {t('title')} +

+

+ {t('subtitle')} +

-
- -
- {SUPPORTED_LANGUAGES.map((lang) => ( - - ))} -
-
- - +
- {/* Gateway */} - - - {t('gateway.title')} - {t('gateway.description')} - - -
-
- -

- {t('gateway.port')}: {gatewayStatus.port} -

-
-
- - {gatewayStatus.state} - - - -
-
+ {/* Content Area */} +
- {showLogs && ( -
-
-

{t('gateway.appLogs')}

-
- - +
-
-                {logContent || t('chat:noLogs')}
-              
+
+ +
+ {SUPPORTED_LANGUAGES.map((lang) => ( + + ))} +
+
- )} - - - -
-
- -

- {t('gateway.autoStartDesc')} -

-
-
- + - {devModeUnlocked ? ( -
-
- - {showAdvancedProxy && ( -
+ {/* Gateway */} +
+

+ {t('gateway.title')} +

+
+
+
+ +

+ {t('gateway.port')}: {gatewayStatus.port} +

+
+
+
+
+ {gatewayStatus.state} +
+ + +
+
+ + {showLogs && ( +
+
+

{t('gateway.appLogs')}

+
+ + +
+
+
+                    {logContent || t('chat:noLogs')}
+                  
+
+ )} + +
+
+ +

+ {t('gateway.autoStartDesc')} +

+
+ +
+ + +
+
+ +

+ {t('advanced.devModeDesc')} +

+
+ +
+ +
+
+ + + {/* Developer */} + {devModeUnlocked && ( + <> + +
+

+ {t('developer.title')} +

+
+ {/* Gateway Proxy */} +
- -

+ +

{t('gateway.proxyDesc')}

@@ -557,387 +550,347 @@ export function Settings() { />
-
- - setProxyServerDraft(event.target.value)} - placeholder="http://127.0.0.1:7890" - /> -

- {t('gateway.proxyServerHelp')} -

-
+ {proxyEnabledDraft && ( +
+
+
+ + setProxyServerDraft(event.target.value)} + placeholder="http://127.0.0.1:7890" + className="h-10 rounded-xl bg-black/5 dark:bg-white/5 border-transparent font-mono text-[13px]" + /> +

+ {t('gateway.proxyServerHelp')} +

+
-
- - setProxyHttpServerDraft(event.target.value)} - placeholder={proxyServerDraft || 'http://127.0.0.1:7890'} - /> -

- {t('gateway.proxyHttpServerHelp')} -

-
+
+ + setProxyHttpServerDraft(event.target.value)} + placeholder={proxyServerDraft || 'http://127.0.0.1:7890'} + className="h-10 rounded-xl bg-black/5 dark:bg-white/5 border-transparent font-mono text-[13px]" + /> +

+ {t('gateway.proxyHttpServerHelp')} +

+
-
- - setProxyHttpsServerDraft(event.target.value)} - placeholder={proxyServerDraft || 'http://127.0.0.1:7890'} - /> -

- {t('gateway.proxyHttpsServerHelp')} -

-
+
+ + setProxyHttpsServerDraft(event.target.value)} + placeholder={proxyServerDraft || 'http://127.0.0.1:7890'} + className="h-10 rounded-xl bg-black/5 dark:bg-white/5 border-transparent font-mono text-[13px]" + /> +

+ {t('gateway.proxyHttpsServerHelp')} +

+
-
- - setProxyAllServerDraft(event.target.value)} - placeholder={proxyServerDraft || 'socks5://127.0.0.1:7891'} - /> -

- {t('gateway.proxyAllServerHelp')} -

-
+
+ + setProxyAllServerDraft(event.target.value)} + placeholder={proxyServerDraft || 'socks5://127.0.0.1:7891'} + className="h-10 rounded-xl bg-black/5 dark:bg-white/5 border-transparent font-mono text-[13px]" + /> +

+ {t('gateway.proxyAllServerHelp')} +

+
+
-
- - setProxyBypassRulesDraft(event.target.value)} - placeholder=";localhost;127.0.0.1;::1" - /> -

- {t('gateway.proxyBypassHelp')} -

-
+
+ + setProxyBypassRulesDraft(event.target.value)} + placeholder=";localhost;127.0.0.1;::1" + className="h-10 rounded-xl bg-black/5 dark:bg-white/5 border-transparent font-mono text-[13px]" + /> +

+ {t('gateway.proxyBypassHelp')} +

+
-
-

- {t('gateway.proxyRestartNote')} -

+
+ +

+ {t('gateway.proxyRestartNote')} +

+
+
+ )} +
+
+ +

+ {t('developer.gatewayTokenDesc')} +

+
+ +
- )} -
-
- ) : ( -
- {t('advanced.devModeDesc')} -
- )} - - - {/* Updates */} - - - - - {t('updates.title')} - - {t('updates.description')} - - - - - - -
-
- -

- {t('updates.autoCheckDesc')} -

-
- -
- -
-
- -

- {t('updates.autoDownloadDesc')} -

-
- { - setAutoDownloadUpdate(value); - updateSetAutoDownload(value); - }} - /> -
-
-
- - {/* Advanced */} - - - {t('advanced.title')} - {t('advanced.description')} - - -
-
- -

- {t('advanced.devModeDesc')} -

-
- -
-
-
- - {/* Developer */} - {devModeUnlocked && ( - - - {t('developer.title')} - {t('developer.description')} - - -
- -

- {t('developer.consoleDesc')} -

- -

- {t('developer.consoleNote')} -

-
- -

- {t('developer.gatewayTokenDesc')} -

-
- - - -
-
-
- {showCliTools && ( - <> - -
- -

- {t('developer.cliDesc')} -

- {isWindows && ( -

- {t('developer.cliPowershell')} -

+ {showCliTools && ( +
+ +

+ {t('developer.cliDesc')} +

+ {isWindows && ( +

+ {t('developer.cliPowershell')} +

+ )} +
+ + +
+
)} -
- - + +
+
+
+ +

+ {t('developer.wsDiagnosticDesc')} +

+
+ +
+ +
+
+ +

+ {t('developer.telemetryViewerDesc')} +

+
+ +
+ + {showTelemetryViewer && ( +
+
+ {t('developer.telemetryTotal')}: {telemetryStats.total} + 0 ? 'destructive' : 'secondary'} className={cn("rounded-full px-3 py-1", telemetryStats.errorCount === 0 && "bg-white dark:bg-[#1a1a19] border border-black/5 dark:border-white/5")}> + {t('developer.telemetryErrors')}: {telemetryStats.errorCount} + + 0 ? 'secondary' : 'outline'} className={cn("rounded-full px-3 py-1", telemetryStats.slowCount === 0 && "bg-white dark:bg-[#1a1a19] border border-black/5 dark:border-white/5")}> + {t('developer.telemetrySlow')}: {telemetryStats.slowCount} + +
+ + +
+
+ +
+ {telemetryByEvent.length > 0 && ( +
+

+ {t('developer.telemetryAggregated')} +

+
+ {telemetryByEvent.map((item) => ( +
+ {item.event} + n={item.count} + + avg={item.timedCount > 0 ? Math.round(item.totalDuration / item.timedCount) : 0}ms + + slow={item.slowCount} + err={item.errorCount} +
+ ))} +
+
+ )} +
+ {telemetryEntries.length === 0 ? ( +
{t('developer.telemetryEmpty')}
+ ) : ( + telemetryEntries + .slice() + .reverse() + .map((entry) => ( +
+
+ {entry.event} + {entry.ts} +
+
+                                      {JSON.stringify({ count: entry.count, ...entry.payload }, null, 2)}
+                                    
+
+ )) + )} +
+
+
+ )}
- - )} +
+ + )} - -
-
+ + + {/* Updates */} +
+

+ {t('updates.title')} +

+
+ + +
- -

- {t('developer.wsDiagnosticDesc')} + +

+ {t('updates.autoCheckDesc')}

- -

- {t('developer.telemetryViewerDesc')} + +

+ {t('updates.autoDownloadDesc')}

+ { + setAutoDownloadUpdate(value); + updateSetAutoDownload(value); + }} + /> +
+
+
+ + + + {/* About */} +
+

+ {t('about.title')} +

+
+

+ {t('about.appName')} - {t('about.tagline')} +

+

{t('about.basedOn')}

+

{t('about.version', { version: currentVersion })}

+
+
- - {showTelemetryViewer && ( -
-
- {t('developer.telemetryTotal')}: {telemetryStats.total} - 0 ? 'destructive' : 'secondary'}> - {t('developer.telemetryErrors')}: {telemetryStats.errorCount} - - 0 ? 'secondary' : 'outline'}> - {t('developer.telemetrySlow')}: {telemetryStats.slowCount} - -
- - -
-
- -
- {telemetryByEvent.length > 0 && ( -
-

- {t('developer.telemetryAggregated')} -

-
- {telemetryByEvent.map((item) => ( -
- {item.event} - n={item.count} - - avg={item.timedCount > 0 ? Math.round(item.totalDuration / item.timedCount) : 0}ms - - slow={item.slowCount} - err={item.errorCount} -
- ))} -
-
- )} -
- {telemetryEntries.length === 0 ? ( -
{t('developer.telemetryEmpty')}
- ) : ( - telemetryEntries - .slice() - .reverse() - .map((entry) => ( -
-
- {entry.event} - {entry.ts} -
-
-                                {JSON.stringify({ count: entry.count, ...entry.payload }, null, 2)}
-                              
-
- )) - )} -
-
-
- )}
- - - )} - - {/* About */} - - - {t('about.title')} - - -

- {t('about.appName')} - {t('about.tagline')} -

-

{t('about.basedOn')}

-

{t('about.version', { version: currentVersion })}

-
- -
-
-
+ +
+
); }