Stabilize initial terminal sizing
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "textual-webterm"
|
||||
version = "0.3.21"
|
||||
version = "0.3.22"
|
||||
description = "Serve terminal sessions over the web"
|
||||
authors = ["Will McGugan <will@textualize.io>"]
|
||||
license = "MIT"
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -59,6 +59,7 @@ class WebTerminal {
|
||||
private reconnectAttempts = 0;
|
||||
private maxReconnectAttempts = 5;
|
||||
private reconnectDelay = 1000;
|
||||
private resizeEventsEnabled = false;
|
||||
|
||||
constructor(container: HTMLElement, wsUrl: string, config: TerminalConfig = {}) {
|
||||
this.element = container;
|
||||
@@ -114,6 +115,9 @@ class WebTerminal {
|
||||
|
||||
// Handle resize
|
||||
this.terminal.onResize(({ cols, rows }) => {
|
||||
if (!this.resizeEventsEnabled) {
|
||||
return;
|
||||
}
|
||||
this.send(["resize", { width: cols, height: rows }]);
|
||||
});
|
||||
|
||||
@@ -135,11 +139,7 @@ class WebTerminal {
|
||||
if (!("fonts" in document)) {
|
||||
return;
|
||||
}
|
||||
const fontSet = document.fonts;
|
||||
if (fontSet.status === "loaded") {
|
||||
return;
|
||||
}
|
||||
fontSet.ready
|
||||
document.fonts.ready
|
||||
.then(() => this.scheduleFit())
|
||||
.catch(() => {
|
||||
// Ignore font readiness errors; resize observer will handle future resizes.
|
||||
@@ -180,25 +180,40 @@ class WebTerminal {
|
||||
this.element.classList.remove("-disconnected");
|
||||
|
||||
// Send initial size.
|
||||
// Important: avoid sending a bogus early resize before fonts/layout settle,
|
||||
// otherwise the PTY will hard-wrap output at the wrong column count.
|
||||
this.fit();
|
||||
const sendResize = () => {
|
||||
const dims = this.fitAddon.proposeDimensions();
|
||||
if (dims) {
|
||||
// Important: the PTY hard-wraps output based on its initial cols/rows.
|
||||
// If we send a resize before fonts/layout settle, the initial cols can be
|
||||
// too small and the shell will wrap permanently.
|
||||
this.resizeEventsEnabled = false;
|
||||
|
||||
const init = () => {
|
||||
const fallback = { cols: 132, rows: 45 };
|
||||
const maxAttempts = 120;
|
||||
|
||||
const attemptFitAndResize = (attempt: number) => {
|
||||
const dims = this.fitAddon.proposeDimensions();
|
||||
if (!dims) {
|
||||
if (attempt < maxAttempts) {
|
||||
window.requestAnimationFrame(() => attemptFitAndResize(attempt + 1));
|
||||
return;
|
||||
}
|
||||
this.terminal.resize(fallback.cols, fallback.rows);
|
||||
this.resizeEventsEnabled = true;
|
||||
this.send(["resize", { width: fallback.cols, height: fallback.rows }]);
|
||||
return;
|
||||
}
|
||||
|
||||
this.terminal.resize(dims.cols, dims.rows);
|
||||
this.resizeEventsEnabled = true;
|
||||
this.send(["resize", { width: dims.cols, height: dims.rows }]);
|
||||
}
|
||||
};
|
||||
|
||||
window.requestAnimationFrame(() => attemptFitAndResize(0));
|
||||
};
|
||||
|
||||
if ("fonts" in document) {
|
||||
document.fonts.ready
|
||||
.then(() => {
|
||||
this.scheduleFit();
|
||||
sendResize();
|
||||
})
|
||||
.catch(() => sendResize());
|
||||
document.fonts.ready.then(init).catch(init);
|
||||
} else {
|
||||
sendResize();
|
||||
init();
|
||||
}
|
||||
|
||||
// Focus terminal
|
||||
|
||||
Reference in New Issue
Block a user