Merge branch 'dev' of ssh://git.commumedia.org:2222/alex/headquarter into dev
This commit is contained in:
@@ -246,8 +246,6 @@ 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) return;
|
if (!fitAddonRef.current || !termRef.current) return;
|
||||||
// Ensure terminal is opened and has valid dimensions
|
|
||||||
if (termRef.current.cols === 0 || termRef.current.rows === 0) return;
|
|
||||||
const oldCols = termRef.current.cols;
|
const oldCols = termRef.current.cols;
|
||||||
const oldRows = termRef.current.rows;
|
const oldRows = termRef.current.rows;
|
||||||
try {
|
try {
|
||||||
@@ -257,8 +255,9 @@ export const TerminalComponent: React.FC<TerminalProps> = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { cols, rows } = termRef.current;
|
const { cols, rows } = termRef.current;
|
||||||
// Force refresh if dimensions changed and are valid
|
console.log(`[Terminal] fit() result: ${cols}x${rows} (was ${oldCols}x${oldRows})`);
|
||||||
if ((cols !== oldCols || rows !== oldRows) && cols > 0 && rows > 0) {
|
// Force refresh if dimensions are valid
|
||||||
|
if (cols > 0 && rows > 0) {
|
||||||
try {
|
try {
|
||||||
termRef.current.refresh(0, rows - 1);
|
termRef.current.refresh(0, rows - 1);
|
||||||
} catch {
|
} catch {
|
||||||
@@ -266,7 +265,7 @@ export const TerminalComponent: React.FC<TerminalProps> = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const currentWs = wsRef.current;
|
const currentWs = wsRef.current;
|
||||||
if (currentWs?.readyState === WebSocket.OPEN) {
|
if (currentWs?.readyState === WebSocket.OPEN && cols > 0 && rows > 0) {
|
||||||
currentWs.send(JSON.stringify({ type: "resize", cols, rows }));
|
currentWs.send(JSON.stringify({ type: "resize", cols, rows }));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -276,14 +275,20 @@ export const TerminalComponent: React.FC<TerminalProps> = ({
|
|||||||
ws = connectWebSocket();
|
ws = connectWebSocket();
|
||||||
|
|
||||||
// Initial fit after layout settles (terminal must be opened first)
|
// Initial fit after layout settles (terminal must be opened first)
|
||||||
|
let fitAttempts = 0;
|
||||||
const doInitialFit = () => {
|
const doInitialFit = () => {
|
||||||
if (!container.isConnected) return;
|
if (!container.isConnected) return;
|
||||||
|
fitAttempts++;
|
||||||
// Ensure container has dimensions before fitting
|
// Ensure container has dimensions before fitting
|
||||||
if (container.clientWidth > 0 && container.clientHeight > 0) {
|
if (container.clientWidth > 0 && container.clientHeight > 0) {
|
||||||
|
console.log(`[Terminal] Container ready: ${container.clientWidth}x${container.clientHeight} (attempt ${fitAttempts})`);
|
||||||
fitTerminal();
|
fitTerminal();
|
||||||
} else {
|
} else if (fitAttempts < 50) {
|
||||||
// Container not ready yet, try again
|
// Container not ready yet, try again (max 50 attempts ~ 1s)
|
||||||
|
console.log(`[Terminal] Container not ready: ${container.clientWidth}x${container.clientHeight} (attempt ${fitAttempts})`);
|
||||||
requestAnimationFrame(doInitialFit);
|
requestAnimationFrame(doInitialFit);
|
||||||
|
} else {
|
||||||
|
console.warn(`[Terminal] Container never got dimensions after ${fitAttempts} attempts`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
requestAnimationFrame(doInitialFit);
|
requestAnimationFrame(doInitialFit);
|
||||||
|
|||||||
+21
-13
@@ -3122,8 +3122,8 @@ a.nav-item,
|
|||||||
}
|
}
|
||||||
|
|
||||||
.mobile-terminal-wrapper {
|
.mobile-terminal-wrapper {
|
||||||
display: grid;
|
display: flex;
|
||||||
grid-template-rows: auto 1fr auto;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
background: #1e1e1e;
|
background: #1e1e1e;
|
||||||
@@ -3239,26 +3239,26 @@ a.nav-item,
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
background: #1e1e1e;
|
background: #1e1e1e;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Terminal wrapper - fills content area */
|
/* Terminal wrapper - fills content area */
|
||||||
.terminal-wrapper.mobile {
|
.terminal-wrapper.mobile {
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
position: absolute;
|
flex: 1;
|
||||||
top: 0;
|
min-height: 0;
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.terminal-wrapper.mobile .terminal-container {
|
.terminal-wrapper.mobile .terminal-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
flex: 1;
|
||||||
max-height: 100%;
|
min-height: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -3270,6 +3270,13 @@ a.nav-item,
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Enable scrolling in mobile terminal */
|
||||||
|
.terminal-wrapper.mobile .terminal-container .xterm-viewport {
|
||||||
|
overflow-y: auto !important;
|
||||||
|
-webkit-overflow-scrolling: touch !important;
|
||||||
|
height: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Special Keys Strip */
|
/* Special Keys Strip */
|
||||||
.special-keys-strip {
|
.special-keys-strip {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
@@ -3499,16 +3506,17 @@ a.nav-item,
|
|||||||
/* Disable zoom on mobile terminal */
|
/* Disable zoom on mobile terminal */
|
||||||
@media (max-width: 767px) {
|
@media (max-width: 767px) {
|
||||||
.mobile-terminal-wrapper {
|
.mobile-terminal-wrapper {
|
||||||
touch-action: none;
|
touch-action: pan-y;
|
||||||
-webkit-text-size-adjust: none;
|
-webkit-text-size-adjust: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-terminal-wrapper * {
|
.mobile-terminal-wrapper button,
|
||||||
|
.mobile-terminal-wrapper .special-key-button {
|
||||||
touch-action: manipulation;
|
touch-action: manipulation;
|
||||||
}
|
}
|
||||||
|
|
||||||
.terminal-container {
|
.terminal-container {
|
||||||
touch-action: none;
|
touch-action: pan-y;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user