Stop shell terminal width growth
This commit is contained in:
@@ -16,6 +16,7 @@ export function ShellTerminal({ csrfToken }: { csrfToken: string }) {
|
||||
|
||||
useEffect(() => {
|
||||
if (!host.current) return;
|
||||
const hostElement = host.current;
|
||||
const terminal = new Terminal({
|
||||
cursorBlink: true,
|
||||
cursorStyle: "bar",
|
||||
@@ -36,8 +37,7 @@ export function ShellTerminal({ csrfToken }: { csrfToken: string }) {
|
||||
});
|
||||
const fit = new FitAddon();
|
||||
terminal.loadAddon(fit);
|
||||
terminal.open(host.current);
|
||||
fit.fit();
|
||||
terminal.open(hostElement);
|
||||
terminal.writeln("\x1b[38;2;185;231;105mPi Car Companion shell\x1b[0m");
|
||||
terminal.writeln("Restricted local session running as pi-companion.\r\n");
|
||||
|
||||
@@ -48,6 +48,24 @@ export function ShellTerminal({ csrfToken }: { csrfToken: string }) {
|
||||
socket.send(JSON.stringify({ type: "resize", cols: terminal.cols, rows: terminal.rows }));
|
||||
}
|
||||
};
|
||||
let resizeFrame: number | null = null;
|
||||
let fittedWidth = -1;
|
||||
let fittedHeight = -1;
|
||||
const fitToHost = () => {
|
||||
resizeFrame = null;
|
||||
const width = hostElement.clientWidth;
|
||||
const height = hostElement.clientHeight;
|
||||
if (width <= 0 || height <= 0 || (width === fittedWidth && height === fittedHeight)) return;
|
||||
fittedWidth = width;
|
||||
fittedHeight = height;
|
||||
fit.fit();
|
||||
sendSize();
|
||||
};
|
||||
const scheduleFit = () => {
|
||||
if (resizeFrame !== null) window.cancelAnimationFrame(resizeFrame);
|
||||
resizeFrame = window.requestAnimationFrame(fitToHost);
|
||||
};
|
||||
fitToHost();
|
||||
socket.addEventListener("open", () => {
|
||||
socket.send(JSON.stringify({ type: "authenticate", csrfToken }));
|
||||
});
|
||||
@@ -56,6 +74,7 @@ export function ShellTerminal({ csrfToken }: { csrfToken: string }) {
|
||||
const message = JSON.parse(String(event.data)) as ServerMessage;
|
||||
if (message.type === "ready") {
|
||||
setState("ready");
|
||||
fitToHost();
|
||||
sendSize();
|
||||
terminal.focus();
|
||||
} else if (message.type === "output") terminal.write(message.data);
|
||||
@@ -80,14 +99,12 @@ export function ShellTerminal({ csrfToken }: { csrfToken: string }) {
|
||||
const input = terminal.onData((data) => {
|
||||
if (socket.readyState === WebSocket.OPEN) socket.send(JSON.stringify({ type: "input", data }));
|
||||
});
|
||||
const resize = new ResizeObserver(() => {
|
||||
fit.fit();
|
||||
sendSize();
|
||||
});
|
||||
resize.observe(host.current);
|
||||
const resize = new ResizeObserver(scheduleFit);
|
||||
resize.observe(hostElement);
|
||||
|
||||
return () => {
|
||||
resize.disconnect();
|
||||
if (resizeFrame !== null) window.cancelAnimationFrame(resizeFrame);
|
||||
input.dispose();
|
||||
socket.close(1000, "Terminal tab closed");
|
||||
terminal.dispose();
|
||||
|
||||
+6
-5
@@ -137,7 +137,8 @@ button:disabled { opacity: 0.55; cursor: not-allowed; }
|
||||
.activity-empty { min-height: 74px; display: grid; place-items: center; padding: 18px; color: var(--muted); font-size: 0.8rem; text-align: center; }
|
||||
.activity-privacy { margin: 0; color: var(--muted); font-size: 0.72rem; text-align: right; }
|
||||
|
||||
.settings-page { display: grid; gap: 18px; }
|
||||
.settings-page { min-width: 0; width: 100%; display: grid; gap: 18px; }
|
||||
.settings-page > [role="tabpanel"] { min-width: 0; width: 100%; max-width: 100%; }
|
||||
.settings-tabs { width: fit-content; display: flex; gap: 5px; padding: 5px; background: #121610; border: 1px solid var(--line); border-radius: 12px; }
|
||||
.settings-tabs button { min-height: 48px; display: inline-flex; align-items: center; gap: 9px; padding: 0 19px; color: var(--muted); background: transparent; border: 0; border-radius: 8px; font-weight: 700; cursor: pointer; transition: color 160ms ease, background 160ms ease, transform 120ms ease; }
|
||||
.settings-tabs button:hover { color: var(--text); background: var(--surface-raised); }
|
||||
@@ -189,8 +190,8 @@ button:disabled { opacity: 0.55; cursor: not-allowed; }
|
||||
.behavior-list { display: grid; gap: 24px; margin: 26px 0 0; }
|
||||
.behavior-list div { display: grid; gap: 7px; }
|
||||
.behavior-list dd { color: #dce4d6; }
|
||||
.shell-panel { overflow: hidden; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); }
|
||||
.shell-loading { min-height: 420px; display: grid; place-items: center; color: var(--muted); background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); }
|
||||
.shell-panel { min-width: 0; width: 100%; max-width: 100%; overflow: hidden; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); }
|
||||
.shell-loading { min-width: 0; width: 100%; max-width: 100%; min-height: 420px; display: grid; place-items: center; color: var(--muted); background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); }
|
||||
.shell-toolbar { min-height: 68px; display: flex; align-items: center; justify-content: space-between; gap: 18px; padding: 10px 14px 10px 20px; border-bottom: 1px solid var(--line); }
|
||||
.shell-toolbar > div { display: grid; grid-template-columns: auto auto; align-items: center; gap: 3px 9px; }
|
||||
.shell-toolbar strong { font-size: 0.87rem; }
|
||||
@@ -198,8 +199,8 @@ button:disabled { opacity: 0.55; cursor: not-allowed; }
|
||||
.shell-state { grid-row: 1 / 3; width: 9px; height: 9px; border-radius: 50%; background: #7c8477; }
|
||||
.shell-state.ready { background: var(--accent); box-shadow: 0 0 0 5px rgba(185, 231, 105, 0.08); }
|
||||
.shell-state.error { background: var(--danger); }
|
||||
.terminal-host { height: min(590px, calc(100dvh - 290px)); min-height: 360px; padding: 16px 12px; background: #0b0e0a; }
|
||||
.terminal-host .xterm { height: 100%; }
|
||||
.terminal-host { contain: inline-size; min-width: 0; width: 100%; max-width: 100%; height: min(590px, calc(100dvh - 290px)); min-height: 360px; overflow: hidden; padding: 16px 12px; background: #0b0e0a; }
|
||||
.terminal-host .xterm { width: 100%; max-width: 100%; height: 100%; }
|
||||
.shell-panel > .settings-note { margin: 0; padding: 14px 20px 16px; border-top: 1px solid var(--line); }
|
||||
.shell-panel code { color: #dce4d6; }
|
||||
.modal-backdrop { position: fixed; inset: 0; z-index: 20; display: grid; place-items: center; padding: 24px; background: rgba(8, 10, 8, 0.78); }
|
||||
|
||||
Reference in New Issue
Block a user