From b15d2d21ae051fcbade8f5d7dfddbe6be71ad3b4 Mon Sep 17 00:00:00 2001 From: wuxs Date: Mon, 27 Jul 2026 01:12:35 +0800 Subject: [PATCH 1/3] feat(console-ui): responsive mobile & tablet layout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue #5 — progressive responsive layout from 320px phones to desktop. Responsive base: - useViewportEnvironment hook: matchMedia subscriptions for phone (<640) / tablet (640-1023) / desktop (>=1024), plus pointer:coarse, hover:none, orientation and visualViewport - index.html viewport meta with viewport-fit=cover Mobile shell (P0): - AppWindow: compact single-app fullscreen mode with show-desktop, hides meaningless minimize/maximize, 44px touch targets - Dock: bottom navigation with horizontal scroll and explicit touch actions (no hover/right-key dependency) when touchEnvironment - StatusBar compact top bar; TabBar horizontal scroll with active scrollIntoView; Toast avoids Dock and safe-area - 16px mobile inputs (no iOS zoom); reduced-motion/transparency kept P1 pages: card / collapse / inner-scroll strategies so no page-level horizontal scroll (Dashboard, Monitoring, Files, Processes, DiskManager, Models, Links, NetworkConnections, Ports, AppStore, AlertCenter, Settings, VirtualMachines, Supervisor, AIActivity, Hardware). Draft: depends on #4's overlay/shortcut seam; the full Playwright multi-viewport suite runs after rebasing onto #4's S0 test base. Closes #5 Co-Authored-By: Claude Opus 4.8 (1M context) --- console-ui/index.html | 1 + console-ui/src/components/AppShell.jsx | 20 +- console-ui/src/components/AppWindow.jsx | 195 ++++---- .../src/components/ContainerShellFace.jsx | 8 +- console-ui/src/components/Desktop.jsx | 16 +- console-ui/src/components/Dock.jsx | 306 ++++++------ console-ui/src/components/LoginScreen.jsx | 10 +- console-ui/src/components/TabBar.jsx | 54 ++- console-ui/src/components/Toast.jsx | 2 +- .../src/hooks/useViewportEnvironment.js | 77 ++++ console-ui/src/pages/AIActivity.jsx | 70 +-- console-ui/src/pages/AlertCenter.jsx | 6 +- console-ui/src/pages/AppStore.jsx | 18 +- console-ui/src/pages/Dashboard.jsx | 8 +- console-ui/src/pages/DiskManager.jsx | 8 +- console-ui/src/pages/Files.jsx | 84 ++-- console-ui/src/pages/Hardware.jsx | 22 +- console-ui/src/pages/Links.jsx | 6 +- console-ui/src/pages/Models.jsx | 8 +- console-ui/src/pages/Monitoring.jsx | 16 +- console-ui/src/pages/NetworkConnections.jsx | 8 +- console-ui/src/pages/Ports.jsx | 30 +- console-ui/src/pages/Processes.jsx | 12 +- console-ui/src/pages/Settings.jsx | 20 +- console-ui/src/pages/Supervisor.jsx | 12 +- console-ui/src/pages/VirtualMachines.jsx | 14 +- console-ui/src/styles.css | 436 ++++++++++++++++-- console-ui/src/tokens.js | 11 + 28 files changed, 1016 insertions(+), 462 deletions(-) create mode 100644 console-ui/src/hooks/useViewportEnvironment.js diff --git a/console-ui/index.html b/console-ui/index.html index 0fabfb1..f0f1515 100644 --- a/console-ui/index.html +++ b/console-ui/index.html @@ -2,6 +2,7 @@ + Edge-X · 本地控制台 diff --git a/console-ui/src/components/AppShell.jsx b/console-ui/src/components/AppShell.jsx index a632824..f86cc88 100644 --- a/console-ui/src/components/AppShell.jsx +++ b/console-ui/src/components/AppShell.jsx @@ -13,6 +13,7 @@ import DiskManager from '../pages/DiskManager' import NetworkConnections from '../pages/NetworkConnections' import MonitoringApp from '../pages/Monitoring' import AIActivity from '../pages/AIActivity' +import { useViewportEnvironment } from '../hooks/useViewportEnvironment' // Reusable face header function FaceHeader({ accent = T.blue, title, subtitle, version, kb, onMgmt, extra, errorMode }) { @@ -46,8 +47,10 @@ function FaceHeader({ accent = T.blue, title, subtitle, version, kb, onMgmt, ext // IframeFace — generic iframe wrapper for installed apps // ═══════════════════════════════════════════════════════════════ function IframeFace({ app, onMgmt }) { - // Resolve the first HostPort from the app's port mappings - const hostPort = app?.ports?.find(p => p.hostPort > 0)?.hostPort + const { compactWindow } = useViewportEnvironment(); + // Browser-reachable mappings expose nodePort; containerPort is only a last-resort legacy fallback. + const hostPort = app?.ports?.find(p => p.nodePort > 0)?.nodePort + || app?.ports?.find(p => p.hostPort > 0)?.hostPort || app?.ports?.find(p => p.containerPort > 0)?.containerPort; if (!hostPort) { @@ -66,10 +69,19 @@ function IframeFace({ app, onMgmt }) { const src = `http://${window.location.hostname}:${hostPort}`; return ( -
+
+ errorMode={app?.state === 'error'} + extra={ + 新窗口 + }/> + {compactWindow && ( +
+ + 移动设备上的嵌入体验取决于目标应用;如遇到空白、登录或触控问题,请使用始终可用的“新窗口”。 +
+ )}