From d6f3549a53c12b63b7e219b3826f213c20b88cd2 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Sat, 21 Mar 2026 22:49:14 +0800 Subject: [PATCH] feat: add status bar with connection indicator and cd path detection --- src/frontend/index.html | 33 ++++++++++++++++------- src/frontend/styles.css | 58 +++++++++++++++++++++++++++++------------ 2 files changed, 66 insertions(+), 25 deletions(-) diff --git a/src/frontend/index.html b/src/frontend/index.html index 745eb6e..b9d0df7 100644 --- a/src/frontend/index.html +++ b/src/frontend/index.html @@ -411,26 +411,32 @@ for (let i = 0; i < totalTerminals; i++) { const pane = document.createElement('div'); pane.className = 'terminal-pane'; - pane.style.overflow = 'hidden'; - pane.style.margin = '0'; - pane.style.padding = '0'; - pane.style.position = 'relative'; const statusDiv = document.createElement('div'); statusDiv.className = 'pane-status'; + + const addressText = document.createElement('span'); + addressText.className = 'pane-address'; + addressText.textContent = shell; + statusDiv.appendChild(addressText); + const statusIndicator = document.createElement('span'); statusIndicator.className = 'status-indicator connecting'; statusIndicator.title = 'Connecting...'; statusDiv.appendChild(statusIndicator); pane.appendChild(statusDiv); + const contentDiv = document.createElement('div'); + contentDiv.className = 'terminal-content'; + pane.appendChild(contentDiv); + terminalsContainer.appendChild(pane); try { const ws = new WebSocket(wsUrl); websockets.push(ws); statusIndicators.push(statusIndicator); - const { term, fitAddon } = createTerminal(pane, ws, statusIndicator); + const { term, fitAddon } = createTerminal(contentDiv, ws, statusIndicator, addressText); terminals.push(term); fitAddons.push(fitAddon); } catch (err) { @@ -462,7 +468,7 @@ }); } - function createTerminal(container, ws, statusIndicator) { + function createTerminal(container, ws, statusIndicator, addressText) { const isDark = currentBrightness < 50; const bgValue = Math.round((currentBrightness / 100) * 255); const bgColor = `rgb(${bgValue}, ${bgValue}, ${bgValue})`; @@ -530,12 +536,14 @@ }; ws.onmessage = (event) => { + let text; if (event.data instanceof ArrayBuffer) { - const text = new TextDecoder().decode(event.data); - term.write(text); + text = new TextDecoder().decode(event.data); } else { - term.write(event.data); + text = event.data; } + + term.write(text); }; ws.onclose = () => { @@ -554,6 +562,13 @@ }; term.onData((data) => { + if (addressText) { + const trimmed = data.trim(); + const cdMatch = trimmed.match(/^cd\s+(.+)/i); + if (cdMatch && cdMatch[1]) { + addressText.textContent = cdMatch[1].trim(); + } + } if (ws && ws.readyState === WebSocket.OPEN) { ws.send(data); } diff --git a/src/frontend/styles.css b/src/frontend/styles.css index 4cbca48..9ecbb0c 100644 --- a/src/frontend/styles.css +++ b/src/frontend/styles.css @@ -89,29 +89,20 @@ html, body { .terminal-pane { flex: 1; + display: flex; + flex-direction: column; background: var(--bg-primary); overflow: hidden; margin: 0; padding: 0; } -.terminal-pane .xterm { - height: 100%; - margin: 0 !important; - padding: 0 !important; -} - -.terminal-pane .xterm-viewport { - margin: 0 !important; - padding: 0 !important; -} - .pane-status { - position: absolute; - top: 6px; - right: 6px; - z-index: 10; - pointer-events: none; + height: 20px; + display: flex; + align-items: center; + padding-right: 12px; + flex-shrink: 0; } .status-indicator { @@ -120,6 +111,41 @@ html, body { border-radius: 50%; display: block; transition: background 0.3s, box-shadow 0.3s; + margin-left: 8px; + flex-shrink: 0; +} + +.pane-address { + font-size: 11px; + color: var(--text-secondary); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + flex: 1; +} + +.terminal-content { + flex: 1; + overflow: hidden; +} + +.terminal-content .xterm { + height: 100%; + margin: 0 !important; + padding: 0 !important; +} + +.terminal-content .xterm-viewport { + margin: 0 !important; + padding: 0 !important; +} + +.status-indicator { + width: 6px; + height: 6px; + border-radius: 50%; + display: block; + transition: background 0.3s, box-shadow 0.3s; } .status-indicator.connected {