fix: mobile terminal black screen - replace grid with flexbox layout

- Root cause: CSS Grid 1fr row got 0 height inside flex parent
- Fix: Replace grid layout with flexbox column for mobile terminal wrapper
- Header and keys strip use flex-shrink: 0
- Content area uses flex: 1 to fill remaining space
- Remove debug logging
This commit is contained in:
Fusion
2026-05-24 23:00:32 +02:00
parent 9751b65dce
commit 21285498ae
2 changed files with 10 additions and 28 deletions
+4 -17
View File
@@ -74,7 +74,6 @@ export const TerminalComponent: React.FC<TerminalProps> = ({
wsRef.current = ws; wsRef.current = ws;
ws.onopen = () => { ws.onopen = () => {
console.log("[Terminal] WebSocket connected");
setStatus("connected"); setStatus("connected");
setError(null); setError(null);
reconnectAttemptsRef.current = 0; reconnectAttemptsRef.current = 0;
@@ -107,10 +106,8 @@ export const TerminalComponent: React.FC<TerminalProps> = ({
if (!termRef.current) return; if (!termRef.current) return;
if (event.data instanceof Blob) { if (event.data instanceof Blob) {
console.log("[Terminal] Received blob:", event.data.size, "bytes");
event.data.arrayBuffer().then((buffer) => { event.data.arrayBuffer().then((buffer) => {
const data = new Uint8Array(buffer); const data = new Uint8Array(buffer);
console.log("[Terminal] Writing data to terminal");
termRef.current?.write(data); termRef.current?.write(data);
}); });
} else if (typeof event.data === "string") { } else if (typeof event.data === "string") {
@@ -231,25 +228,18 @@ export const TerminalComponent: React.FC<TerminalProps> = ({
// Define fitTerminal before connectWebSocket so it's available in onmessage // Define fitTerminal before connectWebSocket so it's available in onmessage
const fitTerminal = () => { const fitTerminal = () => {
if (!fitAddonRef.current || !termRef.current) { if (!fitAddonRef.current || !termRef.current) return;
console.log("[Terminal] fitTerminal: missing refs");
return;
}
// Ensure terminal is opened and has valid dimensions // Ensure terminal is opened and has valid dimensions
if (termRef.current.cols === 0 || termRef.current.rows === 0) { if (termRef.current.cols === 0 || termRef.current.rows === 0) return;
console.log("[Terminal] fitTerminal: zero dimensions", termRef.current.cols, termRef.current.rows);
return;
}
const oldCols = termRef.current.cols; const oldCols = termRef.current.cols;
const oldRows = termRef.current.rows; const oldRows = termRef.current.rows;
try { try {
fitAddonRef.current.fit(); fitAddonRef.current.fit();
} catch (err) { } catch {
console.error("[Terminal] fit error:", err); // Ignore fit errors during initialization
return; return;
} }
const { cols, rows } = termRef.current; const { cols, rows } = termRef.current;
console.log("[Terminal] fitTerminal:", oldCols, "x", oldRows, "->", cols, "x", rows);
// Force refresh if dimensions changed and are valid // Force refresh if dimensions changed and are valid
if ((cols !== oldCols || rows !== oldRows) && cols > 0 && rows > 0) { if ((cols !== oldCols || rows !== oldRows) && cols > 0 && rows > 0) {
try { try {
@@ -265,10 +255,7 @@ export const TerminalComponent: React.FC<TerminalProps> = ({
}; };
// Open xterm first (must happen before fit) // Open xterm first (must happen before fit)
console.log("[Terminal] Before open - container:", container.clientWidth, "x", container.clientHeight);
term.open(container); term.open(container);
console.log("[Terminal] After open - container:", container.clientWidth, "x", container.clientHeight);
console.log("[Terminal] Term dimensions after open:", term.cols, "x", term.rows);
ws = connectWebSocket(); ws = connectWebSocket();
// Initial fit after layout settles (terminal must be opened first) // Initial fit after layout settles (terminal must be opened first)
+6 -11
View File
@@ -3125,12 +3125,8 @@ a.nav-item,
} }
.mobile-terminal-wrapper { .mobile-terminal-wrapper {
display: grid; display: flex;
grid-template-rows: auto 1fr auto; flex-direction: column;
grid-template-areas:
"header"
"content"
"keys";
flex: 1; flex: 1;
min-height: 0; min-height: 0;
background: #1e1e1e; background: #1e1e1e;
@@ -3140,7 +3136,7 @@ a.nav-item,
/* Mobile Terminal Header */ /* Mobile Terminal Header */
.mobile-terminal-header { .mobile-terminal-header {
grid-area: header; flex-shrink: 0;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
@@ -3241,12 +3237,11 @@ a.nav-item,
/* Mobile Terminal Content */ /* Mobile Terminal Content */
.mobile-terminal-content { .mobile-terminal-content {
grid-area: content; flex: 1;
min-height: 0;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
background: #1e1e1e; background: #1e1e1e;
min-height: 0;
max-height: 100%;
} }
/* Terminal wrapper - fills content area */ /* Terminal wrapper - fills content area */
@@ -3280,7 +3275,7 @@ a.nav-item,
/* Special Keys Strip */ /* Special Keys Strip */
.special-keys-strip { .special-keys-strip {
grid-area: keys; flex-shrink: 0;
display: flex; display: flex;
align-items: center; align-items: center;
gap: 2px; gap: 2px;