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 {